Android AVB 分析(八)VBMeta 数据解析和签名验证实战

文章目录

    • 1. 导读
    • 2. 解析 boot 分区 vbmeta
      • 2.1 查看 AVB Footer
      • 2.2 查看 VBMeta
    • 3. 手动验证 VBMeta 数据
      • 3.1 分割 VBMeta 数据
      • 3.2 计算哈希
      • 3.3 提取 VBMeta 的公钥
        • a. 从签名的秘钥中提取公钥
        • b. 从 Auxiliary Data 中提取 public key 公钥数据
      • 3.4 使用公钥验证签名
    • 4. 原始的 vbmeta 数据
    • 5. 总结
    • 6. 其它

1. 导读

在上一篇《AVB 的 VBMeta 数据是如何生成的?》中,我们分析了 VBMeta 数据时如何生成的,以及 VBMeta 的主要布局,但并没有进一步深入检查 VBMeta 的数据。

本篇我们继续深入 VBMeta 数据,实战手动验证签名,解析各种描述符。

2. 解析 boot 分区 vbmeta

先看下 avbtool 提取的信息:

$ avbtool info_image --imageboot.imgFooter version:           1.0Image size:               67108864bytesOriginal image size:      24981504bytesVBMeta offset:            24981504VBMeta size:              1664bytes--Minimum libavb version:   1.0Header Block:             256bytesAuthentication Block:     320bytesAuxiliary Block:          1088bytesPublic key (sha1):        cdbb77177f731920bbe0a0f94f84d9038ae0617dAlgorithm:                SHA256_RSA2048Rollback Index:           1680652800Flags:                    0Rollback Index Location:  0Release String:           'avbtool 1.2.0'Descriptors:    Hash descriptor:      Image Size:            24981504bytes      Hash Algorithm:        sha256      Partition Name:        boot      Salt:                  9f4a6530e6ce8d00b77548ed0ad00344cd7724f83ca0bf9a8f0ad9ea4c366b41      Digest:                e355127406fbce41f1cd044e6ab06aff4c24a36e9984bceb3cc59d3f14a66be1      Flags:                 0Prop: com.android.build.boot.os_version ->'13'Prop: com.android.build.boot.fingerprint ->'Android/aosp_panther/panther:13/TQ2A.230405.003.E1/rocky12021421:userdebug/test-keys'Prop: com.android.build.boot.security_patch ->'2023-04-05'

这里我们手动解析 boot.img

2.1 查看 AVB Footer

通过命令 ls -al boot.img | cut -d' ' -f5获取 boot.img 的大小,并查看文件的末尾 64 个字节,如下:

rocky@guyongqiangx:/public/rocky/android-13.0.0_r41$ ls-alboot.img |cut-d' '-f567108864rocky@guyongqiangx:/public/rocky/android-13.0.0_r41$ hexdump -Cv-s$((67108864-64))boot.img03ffffc0  4156426600 00 00 01  00 00 00 00 00 00 00 00  |AVBf............|03ffffd0  01 7d 3000 00 00 00 00  01 7d 3000 00 00 00 00  |.}0......}0.....|03ffffe0  00 00 06 8000 00 00 00  00 00 00 00 00 00 00 00  |................|03fffff0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|04000000

在这里插入图片描述

解析结果:

magic( 4): 41 56 42 66              -> magic: "AVBf"      version_major( 4): 00 00 00 01              -> major: 1      version_minor( 4): 00 00 00 00              -> minor: 0original_image_size( 8): 00 00 00 00  01 7d 30 00 -> 0x00000000 017d3000 = 24981504      vbmeta_offset( 8): 00 00 00 00  01 7d 30 00 -> 0x00000000 017d3000 = 24981504        vbmeta_size( 8): 00 00 00 00  00 00 06 80 -> 0x00000000 00000680 = 1664

所以,通过最后 64 字节的 AVB Footer 解析得到以下内容:

Footer version:           1.0Image size:               67108864 bytesOriginal image size:      24981504 bytesVBMeta offset:            24981504VBMeta size:              1664 bytes

2.2 查看 VBMeta

通过上一节的 AVB Footer 我们看到 vbmeta_offset = 0x017d3000, vbmeta_size = 0x0680 = 1664

所以镜像 0x017d3000 开始的 1664 字节内容就是 boot.img 的 VBMeta 数据了。

手动解析和标注 VBMeta 实在太花时间了,我这里就只解析 boot.img 的 VBMeta 数据。强哥我花了一整天,才将 boot.img 的 VBMeta 数据在输出的图上标注了出来。简直崩了个溃~

如果有兴趣,可以自行试着标注 system.img 或者 vbmeta.img 的 VBMeta 数据。

在上一篇中,我们介绍过 VBMeta 的布局,如下:

在这里插入图片描述

基于 boot.img 标注的 VBMeta 数据如下:

在这里插入图片描述

经过标注,对 VBMeta 数据的布局理解更加深刻。

VBMeta 总体分成 3 个部分:

  • AvbVBMetaImageHeader
  • Authentication Data Block
  • Auxiliary Data Block

在 Authentication Data Block 内包含了基于 AvbVBMetaImageHeader 和 Auxiliary Data Block 数据计算的哈希,以及签名;

在 Auxiliary Data Block 内包含了多个 Descriptor 描述符,以及用于验证签名的 public key 公钥;

3. 手动验证 VBMeta 数据

你以为通过手动标记出 VBMeta 就完了吗?

在手动标记过程中,已经解析了各种描述符等信息,接下来我会对 VBMeta 的哈希和签名等数据进行验证。

3.1 分割 VBMeta 数据

定位 VBMeta 数据以后,基于 AvbVBMetaImageHeader 中 authentication_data_block_sizeauxiliary_data_block_size提取各部分数据。

# 1. 提取整个 vbmeta 数据到 vbmeta.bin$ ddif=boot.img of=vbmeta.bin skip=24981504bs=1count=1664# 2. 从 vbmeta.bin 中分别提取 AvbVBMetaImageHeader, Authentication Data 和 Auxiliary Data# AvbVBMetaImageHeader 256 bytes# authentication_data_block_size = 0x0140 bytes# auxiliary_data_block_size = 0x0440 bytes$ ddif=vbmeta.bin of=vbmeta-header.bin bs=1count=256$ ddif=vbmeta.bin of=vbmeta-auth.bin skip=256bs=1count=$((0x0140))$ ddif=vbmeta.bin of=vbmeta-auxiliary.bin skip=$((256+$((0x0140))))bs=1count=$((0x0440))

3.2 计算哈希

计算 AvbVBMetaImageHeader 和 Auxiliary Data 的 sha256 哈希

$ catvbmeta-header.bin vbmeta-auxiliary.bin |sha256sum97e0ad7d58290d949e8c1904db9ff1508d4d2e03c223ffedf5717e39eea1c935  -

对比 Authentication Data 的前 32 字节内容:

$ hexdump -Cv-n32vbmeta-auth.bin 00000000  97e0 ad 7d 58290d 949e 8c 1904 db 9f f1 50|...}X).........P|00000010  8d 4d 2e 03 c2 23ff ed  f5 717e 39ee a1 c9 35|.M...#...q~9...5|00000020

验证了 Authentication Data 前面 32 字节就是 AvbVBMetaImageHeader 和 Auxiliary Data 的 sha256 哈希。

3.3 提取 VBMeta 的公钥

为了验证 VBMeta 的签名,需要获取验证使用的公钥。

这里的公钥有两种途径获得:

  1. 直接从avbtool 处理 boot.img 时签名的秘钥中提取公钥
  2. 从 Auxiliary Data 中提取 public key 公钥数据

这两种方式我们这里都分别进行操作。

a. 从签名的秘钥中提取公钥

在前面使用 avbtool 处理 boot.img 时,传入的秘钥为 external/avb/test/data/testkey_rsa2048.pem

我们这里使用 openssl 查看下这个秘钥的信息,并导出公钥

# 从签名的私钥 testkey_rsa2048.pem 中导出用于验证签名的公钥 testkey_rsa2048_pub.pem$ openssl rsa -inexternal/avb/test/data/testkey_rsa2048.pem -pubout-outtestkey_rsa2048_pub.pemwriting RSA key# 查看公钥的明文内容,或者也可以使用 `cat testkey_rsa2048_pub.pem` 查看,只是没有明文输出$ openssl rsa -informPEM -pubin-intestkey_rsa2048_pub.pem -textRSA Public-Key: (2048bit)Modulus:    00:c6:55:51:dd:32:24:a2:e0:0e:bc:7e:fd:bd:a2:    53:80:58:69:7e:f5:4a:40:87:95:90:54:59:3d:55:    ca:ff:36:34:1a:fa:e1:e0:90:2a:1a:32:68:5b:f3:    df:ad:0b:f9:b1:d0:f7:ea:ab:47:1f:76:be:1b:98:    4b:67:a3:62:fa:df:e6:b5:f8:ee:73:16:5f:b8:b1:    82:de:49:89:d5:3d:d7:a8:42:99:81:75:c8:d8:84:    7b:bd:54:a8:22:64:44:bc:34:06:10:3c:89:c2:d1:    f3:2c:03:65:91:b1:a0:d1:c8:21:56:15:99:48:20:    27:74:ef:01:7a:76:a5:0b:6b:fd:e3:fa:ed:0d:f9:    0f:7a:41:fa:76:05:37:49:fe:34:4f:4b:01:49:e4:    98:f7:89:8e:cd:36:aa:39:1d:a9:7d:5d:6b:5a:52:    d1:75:69:a8:df:7c:de:1c:1b:f9:d9:19:5b:b7:47:    4c:b9:70:2e:ad:e5:d6:88:7c:ed:92:6e:46:08:10:    b5:76:03:3e:09:ac:4d:b6:2c:cd:12:00:bd:d4:a7:    03:d3:1b:91:08:23:36:5b:11:fe:af:59:69:b3:3c:    88:24:37:2d:61:ba:c5:99:51:18:97:f9:23:42:96:    9f:87:2e:cd:b2:4d:5f:a9:24:f2:45:da:e2:65:26:    26:4dExponent: 65537(0x10001)writing RSA key-----BEGIN PUBLIC KEY-----MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxlVR3TIkouAOvH79vaJTgFhpfvVKQIeVkFRZPVXK/zY0Gvrh4JAqGjJoW/PfrQv5sdD36qtHH3a+G5hLZ6Ni+t/mtfjucxZfuLGC3kmJ1T3XqEKZgXXI2IR7vVSoImREvDQGEDyJwtHzLANlkbGg0cghVhWZSCAndO8BenalC2v94/rtDfkPekH6dgU3Sf40T0sBSeSY94mOzTaqOR2pfV1rWlLRdWmo33zeHBv52Rlbt0dMuXAureXWiHztkm5GCBC1dgM+CaxNtizNEgC91KcD0xuRCCM2WxH+r1lpszyIJDctYbrFmVEYl/kjQpafhy7Nsk1fqSTyRdriZSYmTQIDAQAB-----END PUBLIC KEY-----$ md5sum testkey_rsa2048_pub.pem cb07e4a86d943a8ad4390b58f54ecc63  testkey_rsa2048_pub.pem
b. 从 Auxiliary Data 中提取 public key 公钥数据

根据前面 VBMeta 手动标注的结果,公钥 public key 位于 Auxiliary Data 的 0x0200 偏移位置,大小为 0x0208。

因此,我们从 Auxiliary Data 中提取公钥:

# 1. 从 vbmeta-auxiliary.bin 中提取公钥数据# 由于 dd 的命令不直接支持十六进制,所以我这里使用 $((0x0200)) 这样的方式转换 $ ddif=vbmeta-auxiliary.bin of=pub_key.bin skip=$((0x0200))bs=1count=$((0x0208))520+0 records in520+0 records out520bytes copied, 0.0759345s, 6.8kB/s# 2. 查看 sha1 哈希值,和 `avbtool info_image` 中的输出一致# Public key (sha1):        cdbb77177f731920bbe0a0f94f84d9038ae0617d$ sha1sum pub_key.bin cdbb77177f731920bbe0a0f94f84d9038ae0617d  pub_key.bin# 3. 查看公钥数据# 公钥数据的头部是 8 字节的: AvbRSAPublicKeyHeader# 包括: key_num_bits(4 bytes), n0inv(4 bytes), 随后才是公钥的 modulus 数据$ hexdump -Cvpub_key.bin00000000  00 00 08 00 c9 d8 7d 7b  c6 5551dd3224a2 e0  |......}{ .UQ.2$..|00000010  0e bc7e fd bd a2 538058697e f5 4a 408795|..~...S.Xi~.J@..|00000020  9054593d 55ca ff 36341a fa e1 e0 902a 1a  |.TY=U..64.....*.|00000030  32685b f3 dfad 0b f9  b1 d0 f7 ea ab 471f 76|2h[..........G.v|00000040  be 1b 984b 67a3 62fa  dfe6 b5 f8 ee 73165f  |...Kg.b......s._|00000050  b8 b1 82de 4989d5 3d  d7 a8 42998175c8 d8  |....I..=..B..u..|00000060  847b bd 54a8 226444bc3406 103c 89c2 d1  |.{ .T."dD.4..<...|00000070  f3 2c 03 65 91 b1 a0 d1  c8 21 56 15 99 48 20 27  |.,.e.....!V..H '|00000080  74 ef 01 7a 76 a5 0b 6b  fd e3 fa ed 0d f9 0f 7a  |t..zv..k.......z|00000090  41 fa 76 05 37 49 fe 34  4f 4b 01 49 e4 98 f7 89  |A.v.7I.4OK.I....|000000a0  8e cd 36 aa 39 1d a9 7d  5d 6b 5a 52 d1 75 69 a8  |..6.9..}]kZR.ui.|000000b0  df 7c de 1c 1b f9 d9 19  5b b7 47 4c b9 70 2e ad  |.|......[.GL.p..|000000c0  e5 d6 88 7c ed 92 6e 46  08 10 b5 76 03 3e 09 ac  |...|..nF...v.>..|000000d0  4d b6 2c cd 12 00 bd d4  a7 03 d3 1b 91 08 23 36  |M.,...........#6|000000e0  5b 11 fe af 59 69 b3 3c  88 24 37 2d 61 ba c5 99  |[...Yi.<.$7-a...|000000f0  51 18 97 f9 23 42 96 9f  87 2e cd b2 4d 5f a9 24  |Q...#B......M_.$|00000100  f2 45 da e2 65 26 26 4d  1e fa 3b 53 ab c5 d3 79  |.E..e&&M..;S...y|00000110  53 2f 66 b8 21 94 66 9a  93 6f 35 26 43 8c 8f 96  |S/f.!.f..o5&C...|00000120  b9 ff ac cd f4 00 6e be  b6 73 54 84 50 85 46 53  |......n..sT.P.FS|00000130  d5 dd 43 fe b2 6a 78 40  79 56 9f 86 f3 d3 81 3b  |..C..jx@yV.....;|00000140  3d 40 90 35 32 9a 51 7f  f8 c3 4b c7 d6 a1 ca 30  |=@.52.Q...K....0|00000150  fb 1b fd 27 0a b8 64 41  34 c1 17 de a1 76 9a eb  |...'..dA4....v..|00000160  cf 0c 50 d9 13 f5 0d 0b  2c 99 24 cb b5 b4 f8 c6  |..P.....,.$.....|00000170  0a d0 26 b1 5b fd 4d 44  66 9d b0 76 aa 79 9d c0  |..&.[.MDf..v.y..|00000180  5c 3b 94 36 c1 8f fe c9  d2 5a 6a a0 46 e1 a2 8b  |\;.6.....Zj.F...|00000190  2f 51 61 51 a3 36 91 83  b4 fb cd a9 40 34 46 98  |/QaQ.6......@4F.|000001a0  8a 1a 91 df d9 2c 3a bf  57 3a 46 46 20 f2 f0 bc  |.....,:.W:FF ...|000001b0  31 5e 29 fe 58 90 32 5c  66 97 99 9a 8e 15 23 eb  |1^).X.2\f.....#.|000001c0  a9 47 d3 63 c6 18 bb 8e  d2 20 9f 78 af 71 b3 2e  |.G.c..... .x.q..|000001d0  08 89 a1 f1 7d b1 30 a0  e6 1b bd 6e c8 f6 33 e1  |....}.0....n..3.|000001e0  da b0 bd 16 41 fe 07 6f  6e 97 8b 6a 33 d2 d7 80  |....A..on..j3...|000001f0  03 6a 4d e7 05 82 28 1f  ef 6a a9 75 7e e1 4e e2  |.jM...(..j.u~.N.|00000200  95 5b 4f e6 dc 03 b9 81                           |.[O.....|00000208# 4. 将十六进制的 public key 数据转换成 modulus 字符串# 使用以下的 xxd 或 hexdump 命令均可获得 public key 的 modulus,从而通过 (mmodulus, e) 构建公钥# modulus=$(echo-n$(xxd -ps-s8-l256pub_key.bin)|tr-d' ')# modulus=$(hexdump -v-e'1/1 "%02x"'-s8-n256pub_key.bin)$ modulus=$(echo-n$(xxd -ps-s8-l256pub_key.bin)|tr-d' ')$ echo $modulusc65551dd3224a2e00ebc7efdbda2538058697ef54a4087959054593d55caff36341afae1e0902a1a32685bf3dfad0bf9b1d0f7eaab471f76be1b984b67a362fadfe6b5f8ee73165fb8b182de4989d53dd7a842998175c8d8847bbd54a8226444bc3406103c89c2d1f32c036591b1a0d1c82156159948202774ef017a76a50b6bfde3faed0df90f7a41fa76053749fe344f4b0149e498f7898ecd36aa391da97d5d6b5a52d17569a8df7cde1c1bf9d9195bb7474cb9702eade5d6887ced926e460810b576033e09ac4db62ccd1200bdd4a703d31b910823365b11feaf5969b33c8824372d61bac599511897f92342969f872ecdb24d5fa924f245dae26526264d# 5. 创建公钥描述结构 pubkey.asn1$ (  echo "asn1=SEQUENCE:pubkey"  echo "[pubkey]"  echo "algorithm=SEQUENCE:alg"  echo "pubkey=BITWRAP,SEQUENCE:rsa"  echo "[alg]"  echo "algorithm=OID:rsaEncryption"  echo "parameter=NULL"  echo "[rsa]"  echo "n=INTEGER:0x${ modulus}"  echo "e=INTEGER:65537")>pubkey.asn1# 6. 基于公钥描述结构 pubkey.asn1 文件创建 DER 格式公钥$ openssl asn1parse -genconfpubkey.asn1 -outpubkey.der -noout# 7. 将 DER 格式的公钥转换成 PEM 格式$ openssl rsa -inpubkey.der -informDER -pubin-outpubkey.pemwriting RSA key# 显示公钥内容$ $ openssl rsa -inpubkey.pem -pubin-textRSA Public-Key: (2048bit)Modulus:    00:c6:55:51:dd:32:24:a2:e0:0e:bc:7e:fd:bd:a2:    53:80:58:69:7e:f5:4a:40:87:95:90:54:59:3d:55:    ca:ff:36:34:1a:fa:e1:e0:90:2a:1a:32:68:5b:f3:    df:ad:0b:f9:b1:d0:f7:ea:ab:47:1f:76:be:1b:98:    4b:67:a3:62:fa:df:e6:b5:f8:ee:73:16:5f:b8:b1:    82:de:49:89:d5:3d:d7:a8:42:99:81:75:c8:d8:84:    7b:bd:54:a8:22:64:44:bc:34:06:10:3c:89:c2:d1:    f3:2c:03:65:91:b1:a0:d1:c8:21:56:15:99:48:20:    27:74:ef:01:7a:76:a5:0b:6b:fd:e3:fa:ed:0d:f9:    0f:7a:41:fa:76:05:37:49:fe:34:4f:4b:01:49:e4:    98:f7:89:8e:cd:36:aa:39:1d:a9:7d:5d:6b:5a:52:    d1:75:69:a8:df:7c:de:1c:1b:f9:d9:19:5b:b7:47:    4c:b9:70:2e:ad:e5:d6:88:7c:ed:92:6e:46:08:10:    b5:76:03:3e:09:ac:4d:b6:2c:cd:12:00:bd:d4:a7:    03:d3:1b:91:08:23:36:5b:11:fe:af:59:69:b3:3c:    88:24:37:2d:61:ba:c5:99:51:18:97:f9:23:42:96:    9f:87:2e:cd:b2:4d:5f:a9:24:f2:45:da:e2:65:26:    26:4dExponent: 65537(0x10001)writing RSA key-----BEGIN PUBLIC KEY-----MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxlVR3TIkouAOvH79vaJTgFhpfvVKQIeVkFRZPVXK/zY0Gvrh4JAqGjJoW/PfrQv5sdD36qtHH3a+G5hLZ6Ni+t/mtfjucxZfuLGC3kmJ1T3XqEKZgXXI2IR7vVSoImREvDQGEDyJwtHzLANlkbGg0cghVhWZSCAndO8BenalC2v94/rtDfkPekH6dgU3Sf40T0sBSeSY94mOzTaqOR2pfV1rWlLRdWmo33zeHBv52Rlbt0dMuXAureXWiHztkm5GCBC1dgM+CaxNtizNEgC91KcD0xuRCCM2WxH+r1lpszyIJDctYbrFmVEYl/kjQpafhy7Nsk1fqSTyRdriZSYmTQIDAQAB-----END PUBLIC KEY-----$ md5sum pubkey.pem cb07e4a86d943a8ad4390b58f54ecc63  pubkey.pem

从这里可以看到,我们最终通过两种方式都获取到了验证签名的公钥(两个公钥文件的 md5 值一样)。

  • 从签名使用的 testkey_rsa2048.pem 中提取公钥
  • 从 Auxiliary Data 中提取数据构建公钥

3.4 使用公钥验证签名

我们从上一步中拿到了公钥 testkey_rsa2048.pem 或 pubkey.pem,二者完全一样。

这里我们使用这个公钥验证 VBMeta 数据的签名。

从 Authentication Data 中提取签名数据到 signature.bin:

# 签名数据的偏移为: 256(vbmeta header) + 0x20(hash size)# 签名数据的大小为: 0x100(256) bytes$ ddif=vbmeta.bin of=signature.bin skip=$((256+0x20))bs=1count=$((0x100))

我们可以试着解密原始的签名数据:

$ openssl rsautl -insignature.bin -inkeypubkey.pem -pubin-verify-hexdump-raw0000 - 00 01 ff ff ff ff ff ff-ff ff ff ff ff ff ff ff   ................0010 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff   ................0020 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff   ................0030 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff   ................0040 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff   ................0050 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff   ................0060 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff   ................0070 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff   ................0080 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff   ................0090 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff   ................00a0 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff   ................00b0 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff   ................00c0 - ff ff ff ff ff ff ff ff-ff ff ff ff 00 303130.............01000d0 - 0d 06 09 60864801 65-03 04 02 01 05 00 04 20...`.H.e.......00e0 - 97e0 ad 7d 58290d 94-9e 8c 1904 db 9f f1 50...}X).........P00f0 - 8d 4d 2e 03 c2 23ff ed-f5 717e 39ee a1 c9 35.M...#...q~9...5

这里的最后两行就是和 3.2 一节算出来的一样的哈希值了。

或者我们也可以直接验证哈希值,但需要提前准备好签名数据。

将签名的 AvbVBMetaImageHeader 和 Auxiliary Data 数据合并成一个 data.bin 文件,因为签名时基于这两个部分的数据进行计算的:

$ catvbmeta-header.bin vbmeta-auxiliary.bin >data.bin

直接使用数据 data.bin 和 signature.bin 验证签名:

$ openssl dgst -sha256-verifypubkey.pem -signaturesignature.bin data.binVerified OK

显然,这里直接验证签名成功。

本篇实战内容涉及到一些关于 sha256 哈希,以及私钥签名,公钥验证等密码学知识,以及各种 openssl 命令。估计不少同学会不太清楚各种具体命令的意思,即使操作了也会有似懂非懂的感觉。

更多关于使用 openssl 命令利用非对称秘钥进行加密和解密,以及签名和验证,请参考以下文章:

《OpenSSL RSA Key的生成和转换》

  • https://blog.csdn.net/guyongqiangx/article/details/74331892

《OpenSSL和Python实现RSA Key公钥加密私钥解密》

  • https://blog.csdn.net/guyongqiangx/article/details/74732434

《OpenSSL和Python实现RSA Key数字签名和验证》

  • https://blog.csdn.net/guyongqiangx/article/details/74454969

4. 原始的 vbmeta 数据

我强烈建议你也试着手动解析 boot.img 的 VBMeta 数据实战下。

以下是我解析的原始数据,你可以对照我上面的标注图试着对这块 VBMeta 数据解析看看。

$ hexdump -Cv-s0x017d3000 -n1664boot.img017d3000  4156423000 00 00 01  00 00 00 00 00 00 00 00  |AVB0............|017d3010  00 00 01 4000 00 00 00  00 00 04 4000 00 00 01  |...@.......@....|017d3020  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 20|............... |017d3030  00 00 00 00 00 00 00 2000 00 00 00 00 00 01 00  |....... ........|017d3040  00 00 00 00 00 00 02 00  00 00 00 00 00 00 02 08  |................|017d3050  00 00 00 00 00 00 04 08  00 00 00 00 00 00 00 00  |................|017d3060  00 00 00 00 00 00 00 00  00 00 00 00 00 00 02 00  |................|017d3070  00 00 00 00 642c ba 00  00 00 00 00 00 00 00 00  |....d,..........|017d3080  617662746f 6f 6c 20312e 322e 3000 00 00  |avbtool 1.2.0...|017d3090  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|017d30a0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|017d30b0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|017d30c0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|017d30d0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|017d30e0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|017d30f0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|017d3100  97e0 ad 7d 58290d 949e 8c 1904 db 9f f1 50|...}X).........P|017d3110  8d 4d 2e 03 c2 23ff ed  f5 717e 39ee a1 c9 35|.M...#...q~9...5|017d3120  71b9 613a 06 3e ae 36e3 79191210c8 d9 cb  |q.a:.>.6.y......|017d3130  06 5806 4f c2 04 03 46f1 0b a8 8784e7 a4 84|.X.O...F........|017d3140  7a e3 3979e3 48d8 8368a1 fd bc33155e 76|z.9y.H..h...3.^v|017d3150  1396ef f1 964a de 936200 b9 00 391f 2a 01  |.....J..b...9.*.|017d3160  7e b1 da c1 7e 9b a4 8a  977a 1b d6 eb 8e f3 73|~...~....z.....s|017d3170  9e 3f 6136c3 741f 7483e9 7d e7 5d 8b 8531|.?a6.t.t..}.]..1|017d3180  57bf 55e6 8318f1 763f 93c6 dc68b2 c2 54|W.U....v?...h..T|017d3190  a3 56426f b0 da 9e 4155624d bf 3e 8d 24cb  |.VBo...AUbM.>.$.|017d31a0  d6 b0 9f 9b 08 58e6 75d8 0c fd 61f2 6e 2d 80|.....X.u...a.n-.|017d31b0  25e4 120d 09 640c 27447f 4e e9 10c4 9503  |%....d.'D.N.....|017d31c0  ea f4 89 26 c0 ae d4 c5  9b e5 74 44 af 9e d9 58  |...&......tD...X|017d31d0  77 85 73 51 ea ad f2 0b  76 f8 81 ff 26 d8 e5 8e  |w.sQ....v...&...|017d31e0  ab 0d 2b e7 e6 10 9e 44  86 28 16 10 d5 57 90 f0  |..+....D.(...W..|017d31f0  db 9a db f5 76 e0 1e c2  f6 88 e7 e1 a4 11 91 79  |....v..........y|017d3200  e2 eb 56 85 32 ba 0a bd  49 45 09 0d fc ce 9a 18  |..V.2...IE......|017d3210  85 80 ab 64 c9 db cc f2  8c 35 fd a2 55 2c 4e 9f  |...d.....5..U,N.|017d3220  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|017d3230  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|017d3240  00 00 00 00 00 00 00 02  00 00 00 00 00 00 00 b8  |................|017d3250  00 00 00 00 01 7d 30 00  73 68 61 32 35 36 00 00  |.....}0.sha256..|017d3260  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|017d3270  00 00 00 00 00 00 00 00  00 00 00 04 00 00 00 20  |............... |017d3280  00 00 00 20 00 00 00 00  00 00 00 00 00 00 00 00  |... ............|017d3290  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|017d32a0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|017d32b0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|017d32c0  00 00 00 00 62 6f 6f 74  9f 4a 65 30 e6 ce 8d 00  |....boot.Je0....|017d32d0  b7 75 48 ed 0a d0 03 44  cd 77 24 f8 3c a0 bf 9a  |.uH....D.w$.<...|017d32e0  8f 0a d9 ea 4c 36 6b 41  e3 55 12 74 06 fb ce 41  |....L6kA.U.t...A|017d32f0  f1 cd 04 4e 6a b0 6a ff  4c 24 a3 6e 99 84 bc eb  |...Nj.j.L$.n....|017d3300  3c c5 9d 3f 14 a6 6b e1  00 00 00 00 00 00 00 00  |<..?..k.........|017d3310  00 00 00 00 00 00 00 38  00 00 00 00 00 00 00 21  |.......8.......!|017d3320  00 00 00 00 00 00 00 02  63 6f 6d 2e 61 6e 64 72  |........com.andr|017d3330  6f 69 64 2e 62 75 69 6c  64 2e 62 6f 6f 74 2e 6f  |oid.build.boot.o|017d3340  73 5f 76 65 72 73 69 6f  6e 00 31 33 00 00 00 00  |s_version.13....|017d3350  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 88  |................|017d3360  00 00 00 00 00 00 00 22  00 00 00 00 00 00 00 54  |.......".......T|017d3370  63 6f 6d 2e 61 6e 64 72  6f 69 64 2e 62 75 69 6c  |com.android.buil|017d3380  64 2e 62 6f 6f 74 2e 66  69 6e 67 65 72 70 72 69  |d.boot.fingerpri|017d3390  6e 74 00 41 6e 64 72 6f  69 64 2f 61 6f 73 70 5f  |nt.Android/aosp_|017d33a0  70 61 6e 74 68 65 72 2f  70 61 6e 74 68 65 72 3a  |panther/panther:|017d33b0  31 33 2f 54 51 32 41 2e  32 33 30 34 30 35 2e 30  |13/TQ2A.230405.0|017d33c0  30 33 2e 45 31 2f 72 6f  63 6b 79 31 32 30 32 31  |03.E1/rocky12021|017d33d0  34 32 31 3a 75 73 65 72  64 65 62 75 67 2f 74 65  |421:userdebug/te|017d33e0  73 74 2d 6b 65 79 73 00  00 00 00 00 00 00 00 00  |st-keys.........|017d33f0  00 00 00 00 00 00 00 48  00 00 00 00 00 00 00 25  |.......H.......%|017d3400  00 00 00 00 00 00 00 0a  63 6f 6d 2e 61 6e 64 72  |........com.andr|017d3410  6f 69 64 2e 62 75 69 6c  64 2e 62 6f 6f 74 2e 73  |oid.build.boot.s|017d3420  65 63 75 72 69 74 79 5f  70 61 74 63 68 00 32 30  |ecurity_patch.20|017d3430  32 33 2d 30 34 2d 30 35  00 00 00 00 00 00 00 00  |23-04-05........|017d3440  00 00 08 00 c9 d8 7d 7b  c6 55 51 dd 32 24 a2 e0  |......}{ .UQ.2$..|017d3450  0e bc 7e fd bd a2 53 80  58 69 7e f5 4a 40 87 95  |..~...S.Xi~.J@..|017d3460  90 54 59 3d 55 ca ff 36  34 1a fa e1 e0 90 2a 1a  |.TY=U..64.....*.|017d3470  32 68 5b f3 df ad 0b f9  b1 d0 f7 ea ab 47 1f 76  |2h[..........G.v|017d3480  be 1b 98 4b 67 a3 62 fa  df e6 b5 f8 ee 73 16 5f  |...Kg.b......s._|017d3490  b8 b1 82 de 49 89 d5 3d  d7 a8 42 99 81 75 c8 d8  |....I..=..B..u..|017d34a0  84 7b bd 54 a8 22 64 44  bc 34 06 10 3c 89 c2 d1  |.{ .T."dD.4..<...|017d34b0  f3 2c 03 65 91 b1 a0 d1  c8 21 56 15 99 48 20 27  |.,.e.....!V..H '|017d34c0  74ef 01 7a 76a5 0b 6b  fd e3 fa ed 0d f9 0f 7a  |t..zv..k.......z|017d34d0  41fa 7605 3749fe 344f 4b 01 49e4 98f7 89|A.v.7I.4OK.I....|017d34e0  8e cd36aa 391d a9 7d  5d 6b 5a 52d1 7569a8  |..6.9..}]kZR.ui.|017d34f0  df7c de 1c 1b f9 d9 195b b7 474c b9 702e ad  |.|......[.GL.p..|017d3500  e5 d6 887c ed 926e 4608 10b5 7603 3e 09 ac  |...|..nF...v.>..|017d3510  4d b6 2c cd1200 bd d4  a7 03 d3 1b 9108 2336|M.,...........#6|017d3520  5b 11fe af 5969b3 3c  8824372d 61ba c5 99|[...Yi.<.$7-a...|017d3530  511897f9 2342969f  872e cdb2 4d 5f a9 24|Q...#B......M_.$|017d3540  f2 45da e2 6526264d  1e fa 3b 53ab c5 d3 79|.E..e&&M..;S...y|017d3550  532f 66b8 2194669a  936f 3526438c 8f 96|S/f.!.f..o5&C...|017d3560  b9 ff ac cdf4 00 6e be  b6 73548450854653|......n..sT.P.FS|017d3570  d5 dd43fe b2 6a 784079569f 86f3 d3 813b  |..C..jx@yV.....;|017d3580  3d 409035329a 517f  f8 c3 4b c7 d6 a1 ca 30|=@.52.Q...K....0|017d3590  fb 1b fd 270a b8 644134c1 17de a1 769a eb  |...'..dA4....v..|017d35a0  cf 0c 50d9 13f5 0d 0b  2c 9924cb b5 b4 f8 c6  |..P.....,.$.....|017d35b0  0a d0 26b1 5b fd 4d 44669d b0 76aa 799d c0  |..&.[.MDf..v.y..|017d35c0  5c 3b 9436c1 8f fe c9  d2 5a 6a a0 46e1 a2 8b  |\;.6.....Zj.F...|017d35d0  2f 516151a3 369183b4 fb cda9 40344698|/QaQ.6......@4F.|017d35e0  8a 1a 91dfd9 2c 3a bf  573a 464620f2 f0 bc|.....,:.W:FF ...|017d35f0  315e 29fe 5890325c  6697999a 8e 1523eb  |1^).X.2\f.....#.|017d3600  a9 47d3 63c6 18bb 8e  d2 209f 78af 71b3 2e  |.G.c..... .x.q..|017d3610  08 89a1 f1 7d b1 30a0  e6 1b bd 6e c8 f6 33e1  |....}.0....n..3.|017d3620  da b0 bd 1641fe 07 6f  6e 978b 6a 33d2 d7 80|....A..on..j3...|017d3630  03 6a 4d e7 05 82281f  ef 6a a9 757e e1 4e e2  |.jM...(..j.u~.N.|017d3640  955b 4f e6 dc03 b9 8100 00 00 00 00 00 00 00  |.[O.............|017d3650  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|017d3660  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|017d3670  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|017d3680

或者编译一个 Android 版本的代码,利用生成 boot.img,system.img 或 vbmeta.img 进行实战验证。

5. 总结

Android AVB 的核心数据时 VBMeta,主要包含以下 3 个部分:

  • AvbVBMetaImageHeader
  • Authentication Data Block
  • Auxiliary Data Block

本文主要从解析 boot 分区的 AVB Footer 数据开始,提取和验证 VBMeta 数据信息。

在提取到 VBMeta 后,根据 VBMeta 的布局信息图,对 VBMeta 的每一个字段都进行了手工标注。

说实话,这个标注没什么技术含量,但却真是太浪费时间了。好处就是可以大大加深你对 AVB 数据的理解。

随后,根据 VBMeta 的 AvbVBMetaImageHeader 信息,分别提取了 AvbVBMetaImageHeader, Authentication Data Block, Auxiliary Data Block 三个部分的内容到独立的文件中。

并进一步从 Authentication Data Block 中提取出 Hash 和 签名数据,并从 Auxiliary Data Block 中提取了 public key,还原得到 PEM 格式的公约文件,最终使用这个公钥文件验证了 VBMeta 数据的签名。

6. 其它

我创建了一个 Android AVB 讨论群,主要讨论 Android 设备的 AVB 验证问题。

我还几个 Android OTA 升级讨论群,主要讨论 Android 设备的 OTA 升级话题。

欢迎您加群和我们一起交流,请在加我微信时注明“Android AVB 交流”或“Android OTA 交流”。

仅限 Android 相关的开发者参与~

公众号“洛奇看世界”后台回复“wx”获取个人微信。