2016年1月14日 星期四

Check the signature of kernel module (old format before 3f1e1bea3 commit in v4.3-rc1)

There have a situation that I need to check the signature blob that attached in the end of .ko file, it's should signed by appropriate key. Here is a procedure to manually checking signature by public key.

Success Case

acer-wmi.ko (from kernel-default-3.12.28-4.6.x86_64.rpm):

STEP 1. Find out the "Subject Key Identifier"

linux-aiip:/lib/modules/3.12.28-4-default # modinfo acer-wmi
filename:       /lib/modules/3.12.28-4-default/kernel/drivers/platform/x86/acer-wmi.ko
[...snip]
signer:         SUSE Linux Enterprise Secure Boot Signkey
sig_key:        3F:B0:77:B6:CE:BC:6F:F2:52:2E:1C:14:8C:57:C7:77:C7:88:E3:E7
sig_hashalgo:   sha256

The sig_key match with "Subject Key Identifier" in SUSE Linux Enterprise Secure Boot
Signkey, so the public key can decrypt the signature that it is attached on acer-wmi.ko.


STEP 2. Extract the signature from acer-wmi.ko

Signature is attached behind the key name and Subject Key Identifier number.
It's a 256 bytes block because hashed by SHA256. In this case, the Subject Key
Identifier is 3F B0 77 B6...E3 E7, finding out the position from acer-wmi.ko:

0000eb10  00 00 00 00 00 00 00 00  53 55 53 45 20 4c 69 6e  |........SUSE Lin|
0000eb20  75 78 20 45 6e 74 65 72  70 72 69 73 65 20 53 65  |ux Enterprise Se|
0000eb30  63 75 72 65 20 42 6f 6f  74 20 53 69 67 6e 6b 65  |cure Boot Signke|
0000eb40  79 3f b0 77 b6 ce bc 6f  f2 52 2e 1c 14 8c 57 c7  |y?.w...o.R....W.|  <=== 3F B0 77 B6...
0000eb50  77 c7 88 e3 e7 01 00 9b  eb 31 d2 cd f7 3a 65 92  |w........1...:e.|  <=== ...E3 E7 01 00 signature /* 60240 *//* 60240 + 7 = 60247 */
0000eb60  30 ee 2e d4 97 d2 7b 15  a0 e0 08 1f db 2d a7 9e  |0.....{......-..|
0000eb70  7f 0a 5f 25 ed 04 6e 95  2d 98 85 cc 98 5a 4f 08  |.._%..n.-....ZO.|

The signature is always leading by "01 00" head, we don't need the head, so
the start of signature is 60240 + 7 = 60247. Use dd to extract signature to
another file:

dd skip=60247 count=256 bs=1 if=./acer-wmi.ko of=./acer-wmi.ko.sig

> hexdump -C acer-wmi.ko.sig
00000000  9b eb 31 d2 cd f7 3a 65  92 30 ee 2e d4 97 d2 7b  |..1...:e.0.....{|
00000010  15 a0 e0 08 1f db 2d a7  9e 7f 0a 5f 25 ed 04 6e  |......-...._%..n|
00000020  95 2d 98 85 cc 98 5a 4f  08 b5 c6 b5 1b 2f 87 52  |.-....ZO...../.R|
00000030  00 28 bb f0 6b bd f1 60  8e 58 be 18 0e 30 e7 dd  |.(..k..`.X...0..|
00000040  87 91 ce 1f 84 71 f8 83  f3 ba f7 07 68 c4 35 6d  |.....q......h.5m|
00000050  c4 3d 87 e7 ff 4c b2 20  ae b9 65 52 0f 56 38 38  |.=...L. ..eR.V88|

STEP 3. Verify signature by the public key in SLES certificate

First, extract public key from certificate file:
openssl x509 -in SLES-UEFI-SIGN-Certificate.der -inform DER -pubkey -noout > SLES-UEFI-SIGN-Certificate.pub

Then, decrypting signature by public key. If the signature didn't encrypt by right
key, then this step will be fail:

openssl rsautl -verify -inkey SLES-UEFI-SIGN-Certificate.pub -pubin -in acer-wmi.ko.sig > acer-wmi.ko.sha

The acer-wmi.ko.sha file is the decrypted signature. It's leaded by ASN.1 format
and a SHA256 hash result:

> hexdump -C acer-wmi.ko.sha
00000000  30 31 30 0d 06 09 60 86  48 01 65 03 04 02 01 05  |010...`.H.e.....| <== ASN1. format head
00000010  00 04 20 ae 4a 31 b2 46  2b 1d e6 01 26 aa 38 2e  |.. .J1.F+...&.8.| <=== should match with the result of modhash
00000020  9d 3d ab 08 78 1a c2 85  b3 2f 87 96 3e 7f 15 7a  |.=..x..../..>..z|
00000030  31 b7 8c                                          |1..|
00000033

The attached perl script, modhash, is developed by Gary Lin for calculating
signature from a signed ko file. Comparing the result from modhash and the above decrypted
hash value to confirm the hash value matched:
> perl modhash -v acer-wmi.ko
Hash algorithm: sha256
acer-wmi.ko: ae4a31b2462b1de60126aa382e9d3dab08781ac285b32f87963e7f157a31b78c

The same procedure, following is a failed case.

Failed Case

sample.ko:

It's also claimed signed by SUSE Linux Enterprise Secure Boot Signkey:
linux-aiip:~ # modinfo sample
filename:       /lib/modules/3.12.28-4-default/updates/sample.ko
description:    xxxxxxxxxxxxxx
[...snip]
signer:         SUSE Linux Enterprise Secure Boot Signkey
sig_key:        3F:B0:77:B6:CE:BC:6F:F2:52:2E:1C:14:8C:57:C7:77:C7:88:E3:E7
sig_hashalgo:   sha256

Found the Subject Key Identifier in .ko file, looks OK:
00061790  70 61 67 65 73 5f 63 75  72 72 65 6e 74 00 53 55  |pages_current.SU|
000617a0  53 45 20 4c 69 6e 75 78  20 45 6e 74 65 72 70 72  |SE Linux Enterpr|
000617b0  69 73 65 20 53 65 63 75  72 65 20 42 6f 6f 74 20  |ise Secure Boot |
000617c0  53 69 67 6e 6b 65 79 3f  b0 77 b6 ce bc 6f f2 52  |Signkey?.w...o.R|  <=== 3F B0 77...
000617d0  2e 1c 14 8c 57 c7 77 c7  88 e3 e7 01 00 c6 12 1d  |....W.w.........|  <=== ...88 E3 E7 01 00 signature /* 399312 */ /* 399325 */
000617e0  ba 45 3a b3 b1 99 fb 55  1b fc d3 90 6a ea 92 64  |.E:....U....j..d|

Then extract signature:
dd skip=399325 count=256 bs=1 if=./sample.ko of=./sample.ko.sig
> hexdump -C sample.ko.sig
00000000  c6 12 1d ba 45 3a b3 b1  99 fb 55 1b fc d3 90 6a  |....E:....U....j|
00000010  ea 92 64 8a 04 04 f9 22  a7 74 35 98 05 d7 e6 85  |..d....".t5.....|
00000020  8c 5f 32 e6 6c 71 f7 ba  1c 0a 0f 8a 95 f3 ec c7  |._2.lq..........|
00000030  88 b2 11 71 27 28 ca b8  b8 55 ae df 56 38 c6 b4  |...q'(...U..V8..|

Unfortunately the signature can not be decrypted by public key success:
openssl rsautl -verify -inkey SLES-UEFI-SIGN-Certificate.pub -pubin -in sample.ko.sig > sample.ko.sha
RSA operation error
139755852273296:error:0407006A:rsa routines:RSA_padding_check_PKCS1_type_1:block type is not 01:rsa_pk1.c:100:
139755852273296:error:04067072:rsa routines:RSA_EAY_PUBLIC_DECRYPT:padding check failed:rsa_eay.c:721:

Got problem when decrypting the blob by public key. So, looks signature didn't encrypted by appropriate key.

沒有留言:

張貼留言