Support AVB1.0 signing and verification in magiskboot

This commit is contained in:
topjohnwu 2023-07-17 18:57:50 -07:00
parent 16d728f379
commit af65d07456
10 changed files with 865 additions and 31 deletions

504
native/src/Cargo.lock generated
View File

@ -74,6 +74,18 @@ dependencies = [
"thiserror", "thiserror",
] ]
[[package]]
name = "base16ct"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf"
[[package]]
name = "base64ct"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
[[package]] [[package]]
name = "bitflags" name = "bitflags"
version = "1.3.2" version = "1.3.2"
@ -133,14 +145,32 @@ dependencies = [
] ]
[[package]] [[package]]
name = "cpufeatures" name = "const-oid"
version = "0.2.8" version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03e69e28e9f7f77debdedbaafa2866e1de9ba56df55a8bd7cfc724c25a09987c" checksum = "795bc6e66a8e340f075fcf6227e417a2dc976b92b91f3cdc778bb858778b6747"
[[package]]
name = "cpufeatures"
version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1"
dependencies = [ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "crypto-bigint"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf4c2f4e1afd912bc40bfd6fed5d9dc1f288e0ba01bfcc835cc5bc3eb13efe15"
dependencies = [
"generic-array",
"rand_core",
"subtle",
"zeroize",
]
[[package]] [[package]]
name = "crypto-common" name = "crypto-common"
version = "0.1.6" version = "0.1.6"
@ -167,7 +197,7 @@ dependencies = [
"codespan-reporting", "codespan-reporting",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.18", "syn 2.0.26",
] ]
[[package]] [[package]]
@ -180,7 +210,32 @@ version = "1.0.94"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.18", "syn 2.0.26",
]
[[package]]
name = "der"
version = "0.7.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c7ed52955ce76b1554f509074bb357d3fb8ac9b51288a65a3fd480d1dfba946"
dependencies = [
"const-oid",
"der_derive",
"flagset",
"pem-rfc7468",
"zeroize",
]
[[package]]
name = "der_derive"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "114792ba6b7545d3f3dd693794aed3a312a67795cd577fcc725c148d84fabe32"
dependencies = [
"proc-macro-error",
"proc-macro2",
"quote",
"syn 2.0.26",
] ]
[[package]] [[package]]
@ -190,7 +245,44 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
dependencies = [ dependencies = [
"block-buffer", "block-buffer",
"const-oid",
"crypto-common", "crypto-common",
"subtle",
]
[[package]]
name = "ecdsa"
version = "0.16.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0997c976637b606099b9985693efa3581e84e41f5c11ba5255f88711058ad428"
dependencies = [
"der",
"digest",
"elliptic-curve",
"rfc6979",
"signature",
"spki",
]
[[package]]
name = "elliptic-curve"
version = "0.13.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "968405c8fdc9b3bf4df0a6638858cc0b52462836ab6b1c87377785dd09cf1c0b"
dependencies = [
"base16ct",
"crypto-bigint",
"digest",
"ff",
"generic-array",
"group",
"hkdf",
"pem-rfc7468",
"pkcs8",
"rand_core",
"sec1",
"subtle",
"zeroize",
] ]
[[package]] [[package]]
@ -206,6 +298,22 @@ dependencies = [
"termcolor", "termcolor",
] ]
[[package]]
name = "ff"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449"
dependencies = [
"rand_core",
"subtle",
]
[[package]]
name = "flagset"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cda653ca797810c02f7ca4b804b40b8b95ae046eb989d356bce17919a8c25499"
[[package]] [[package]]
name = "generic-array" name = "generic-array"
version = "0.14.7" version = "0.14.7"
@ -214,6 +322,29 @@ checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
dependencies = [ dependencies = [
"typenum", "typenum",
"version_check", "version_check",
"zeroize",
]
[[package]]
name = "getrandom"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427"
dependencies = [
"cfg-if",
"libc",
"wasi",
]
[[package]]
name = "group"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63"
dependencies = [
"ff",
"rand_core",
"subtle",
] ]
[[package]] [[package]]
@ -225,6 +356,24 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "hkdf"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437"
dependencies = [
"hmac",
]
[[package]]
name = "hmac"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
dependencies = [
"digest",
]
[[package]] [[package]]
name = "humantime" name = "humantime"
version = "1.3.0" version = "1.3.0"
@ -235,10 +384,25 @@ dependencies = [
] ]
[[package]] [[package]]
name = "libc" name = "lazy_static"
version = "0.2.146" version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
dependencies = [
"spin",
]
[[package]]
name = "libc"
version = "0.2.147"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
[[package]]
name = "libm"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4"
[[package]] [[package]]
name = "log" name = "log"
@ -266,12 +430,17 @@ dependencies = [
"byteorder", "byteorder",
"cxx", "cxx",
"cxx-gen", "cxx-gen",
"der",
"digest", "digest",
"p256",
"p384",
"pb-rs", "pb-rs",
"quick-protobuf", "quick-protobuf",
"rsa",
"sha1", "sha1",
"sha2", "sha2",
"size", "size",
"x509-cert",
] ]
[[package]] [[package]]
@ -315,6 +484,23 @@ dependencies = [
"minimal-lexical", "minimal-lexical",
] ]
[[package]]
name = "num-bigint-dig"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151"
dependencies = [
"byteorder",
"lazy_static",
"libm",
"num-integer",
"num-iter",
"num-traits",
"rand",
"smallvec",
"zeroize",
]
[[package]] [[package]]
name = "num-derive" name = "num-derive"
version = "0.3.3" version = "0.3.3"
@ -326,6 +512,27 @@ dependencies = [
"syn 1.0.109", "syn 1.0.109",
] ]
[[package]]
name = "num-integer"
version = "0.1.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
dependencies = [
"autocfg",
"num-traits",
]
[[package]]
name = "num-iter"
version = "0.1.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252"
dependencies = [
"autocfg",
"num-integer",
"num-traits",
]
[[package]] [[package]]
name = "num-traits" name = "num-traits"
version = "0.2.15" version = "0.2.15"
@ -333,6 +540,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
dependencies = [ dependencies = [
"autocfg", "autocfg",
"libm",
]
[[package]]
name = "p256"
version = "0.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b"
dependencies = [
"ecdsa",
"elliptic-curve",
"primeorder",
"sha2",
]
[[package]]
name = "p384"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70786f51bcc69f6a4c0360e063a4cac5419ef7c5cd5b3c99ad70f3be5ba79209"
dependencies = [
"ecdsa",
"elliptic-curve",
"primeorder",
"sha2",
] ]
[[package]] [[package]]
@ -347,10 +579,79 @@ dependencies = [
] ]
[[package]] [[package]]
name = "proc-macro2" name = "pem-rfc7468"
version = "1.0.60" version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dec2b086b7a862cf4de201096214fa870344cf922b2b30c167badb3af3195406" checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412"
dependencies = [
"base64ct",
]
[[package]]
name = "pkcs1"
version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f"
dependencies = [
"der",
"pkcs8",
"spki",
]
[[package]]
name = "pkcs8"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7"
dependencies = [
"der",
"spki",
]
[[package]]
name = "ppv-lite86"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
[[package]]
name = "primeorder"
version = "0.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c2fcef82c0ec6eefcc179b978446c399b3cdf73c392c35604e399eee6df1ee3"
dependencies = [
"elliptic-curve",
]
[[package]]
name = "proc-macro-error"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
dependencies = [
"proc-macro-error-attr",
"proc-macro2",
"quote",
"syn 1.0.109",
"version_check",
]
[[package]]
name = "proc-macro-error-attr"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
dependencies = [
"proc-macro2",
"quote",
"version_check",
]
[[package]]
name = "proc-macro2"
version = "1.0.66"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9"
dependencies = [ dependencies = [
"unicode-ident", "unicode-ident",
] ]
@ -371,18 +672,59 @@ dependencies = [
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.28" version = "1.0.31"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488" checksum = "5fe8a65d69dd0808184ebb5f836ab526bb259db23c657efa38711b1072ee47f0"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
] ]
[[package]] [[package]]
name = "regex" name = "rand"
version = "1.8.4" version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0ab3ca65655bb1e41f2a8c8cd662eb4fb035e67c3f78da1d61dffe89d07300f" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"rand_chacha",
"rand_core",
]
[[package]]
name = "rand_chacha"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
"rand_core",
]
[[package]]
name = "rand_core"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
"getrandom",
]
[[package]]
name = "regex"
version = "1.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575"
dependencies = [
"aho-corasick",
"memchr",
"regex-automata",
"regex-syntax",
]
[[package]]
name = "regex-automata"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39354c10dd07468c2e73926b23bb9c2caca74c5501e38a35da70406f1d923310"
dependencies = [ dependencies = [
"aho-corasick", "aho-corasick",
"memchr", "memchr",
@ -391,9 +733,56 @@ dependencies = [
[[package]] [[package]]
name = "regex-syntax" name = "regex-syntax"
version = "0.7.2" version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78" checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2"
[[package]]
name = "rfc6979"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2"
dependencies = [
"hmac",
"subtle",
]
[[package]]
name = "rsa"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ab43bb47d23c1a631b4b680199a45255dce26fa9ab2fa902581f624ff13e6a8"
dependencies = [
"byteorder",
"const-oid",
"digest",
"num-bigint-dig",
"num-integer",
"num-iter",
"num-traits",
"pkcs1",
"pkcs8",
"rand_core",
"sha2",
"signature",
"spki",
"subtle",
"zeroize",
]
[[package]]
name = "sec1"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc"
dependencies = [
"base16ct",
"der",
"generic-array",
"pkcs8",
"subtle",
"zeroize",
]
[[package]] [[package]]
name = "sha1" name = "sha1"
@ -417,18 +806,56 @@ dependencies = [
"digest", "digest",
] ]
[[package]]
name = "signature"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500"
dependencies = [
"digest",
"rand_core",
]
[[package]] [[package]]
name = "size" name = "size"
version = "0.4.1" version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9fed904c7fb2856d868b92464fc8fa597fce366edea1a9cbfaa8cb5fe080bd6d" checksum = "9fed904c7fb2856d868b92464fc8fa597fce366edea1a9cbfaa8cb5fe080bd6d"
[[package]]
name = "smallvec"
version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9"
[[package]]
name = "spin"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
[[package]]
name = "spki"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d1e996ef02c474957d681f1b05213dfb0abab947b446a62d37770b23500184a"
dependencies = [
"base64ct",
"der",
]
[[package]] [[package]]
name = "strsim" name = "strsim"
version = "0.8.0" version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
[[package]]
name = "subtle"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
[[package]] [[package]]
name = "syn" name = "syn"
version = "1.0.109" version = "1.0.109"
@ -442,9 +869,9 @@ dependencies = [
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.18" version = "2.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32d41677bcbe24c20c52e7c70b0d8db04134c5d1066bf98662e2871ad200ea3e" checksum = "45c3457aacde3c65315de5031ec191ce46604304d2446e803d71ade03308d970"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -471,22 +898,22 @@ dependencies = [
[[package]] [[package]]
name = "thiserror" name = "thiserror"
version = "1.0.40" version = "1.0.43"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" checksum = "a35fc5b8971143ca348fa6df4f024d4d55264f3468c71ad1c2f365b0a4d58c42"
dependencies = [ dependencies = [
"thiserror-impl", "thiserror-impl",
] ]
[[package]] [[package]]
name = "thiserror-impl" name = "thiserror-impl"
version = "1.0.40" version = "1.0.43"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" checksum = "463fe12d7993d3b327787537ce8dd4dfa058de32fc2b195ef3cde03dc4771e8f"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.18", "syn 2.0.26",
] ]
[[package]] [[package]]
@ -497,9 +924,9 @@ checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
[[package]] [[package]]
name = "unicode-ident" name = "unicode-ident"
version = "1.0.9" version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0" checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c"
[[package]] [[package]]
name = "unicode-width" name = "unicode-width"
@ -519,6 +946,12 @@ version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]] [[package]]
name = "winapi" name = "winapi"
version = "0.3.9" version = "0.3.9"
@ -549,3 +982,20 @@ name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0" version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "x509-cert"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "077a1672d8ecfa5c1fe69fa7c5d043962e4e32866d4375495536261c0b4781f5"
dependencies = [
"const-oid",
"der",
"spki",
]
[[package]]
name = "zeroize"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9"

View File

@ -16,6 +16,11 @@ size = "0.4"
sha1 = "0.10" sha1 = "0.10"
sha2 = "0.10" sha2 = "0.10"
digest = "0.10" digest = "0.10"
p256 = "0.13"
p384 = "0.13"
rsa = "0.9"
x509-cert = "0.2"
der = "0.7"
[workspace.dependencies.argh] [workspace.dependencies.argh]
git = "https://github.com/topjohnwu/argh.git" git = "https://github.com/topjohnwu/argh.git"

View File

@ -140,7 +140,7 @@ struct byte_view {
// Bridging to Rust slice // Bridging to Rust slice
byte_view(rust::Slice<const uint8_t> o) : byte_view(o.data(), o.size()) {} byte_view(rust::Slice<const uint8_t> o) : byte_view(o.data(), o.size()) {}
operator rust::Slice<const uint8_t>() { return rust::Slice<const uint8_t>(_buf, _sz); } operator rust::Slice<const uint8_t>() const { return rust::Slice<const uint8_t>(_buf, _sz); }
// String as bytes // String as bytes
byte_view(const char *s, bool with_nul = true) byte_view(const char *s, bool with_nul = true)

View File

@ -21,3 +21,8 @@ argh = { workspace = true }
sha1 = { workspace = true } sha1 = { workspace = true }
sha2 = { workspace = true } sha2 = { workspace = true }
digest = { workspace = true } digest = { workspace = true }
p256 = { workspace = true }
p384 = { workspace = true }
rsa = { workspace = true, features = ["sha2"] }
x509-cert = { workspace = true }
der = { workspace = true, features = ["derive"] }

View File

@ -451,6 +451,12 @@ bool boot_img::parse_image(const uint8_t *p, format_t type) {
flags[LG_BUMP_FLAG] = true; flags[LG_BUMP_FLAG] = true;
} }
// Check if the image is signed
if (verify()) {
fprintf(stderr, "AVB1_SIGNED\n");
flags[AVB1_SIGNED_FLAG] = true;
}
// Find AVB footer // Find AVB footer
const void *footer = tail.buf() + tail.sz() - sizeof(AvbFooter); const void *footer = tail.buf() + tail.sz() - sizeof(AvbFooter);
if (BUFFER_MATCH(footer, AVB_FOOTER_MAGIC)) { if (BUFFER_MATCH(footer, AVB_FOOTER_MAGIC)) {
@ -469,6 +475,10 @@ bool boot_img::parse_image(const uint8_t *p, format_t type) {
return true; return true;
} }
bool boot_img::verify(const char *cert) const {
return rust::verify_boot_image(*this, cert);
}
int split_image_dtb(const char *filename) { int split_image_dtb(const char *filename) {
mmap_data img(filename); mmap_data img(filename);
@ -740,8 +750,6 @@ void repack(const char *src_img, const char *out_img, bool skip_comp) {
} }
} }
close(fd);
/****************** /******************
* Patch the image * Patch the image
******************/ ******************/
@ -810,11 +818,11 @@ void repack(const char *src_img, const char *out_img, bool skip_comp) {
if (boot.flags[AVB_FLAG]) { if (boot.flags[AVB_FLAG]) {
// Copy and patch AVB structures // Copy and patch AVB structures
auto footer = reinterpret_cast<AvbFooter*>(out.buf() + out.sz() - sizeof(AvbFooter)); auto footer = reinterpret_cast<AvbFooter*>(out.buf() + out.sz() - sizeof(AvbFooter));
auto vbmeta = reinterpret_cast<AvbVBMetaImageHeader*>(out.buf() + off.vbmeta);
memcpy(footer, boot.avb_footer, sizeof(AvbFooter)); memcpy(footer, boot.avb_footer, sizeof(AvbFooter));
footer->original_image_size = __builtin_bswap64(off.total); footer->original_image_size = __builtin_bswap64(off.total);
footer->vbmeta_offset = __builtin_bswap64(off.vbmeta); footer->vbmeta_offset = __builtin_bswap64(off.vbmeta);
if (check_env("PATCHVBMETAFLAG")) { if (check_env("PATCHVBMETAFLAG")) {
auto vbmeta = reinterpret_cast<AvbVBMetaImageHeader*>(out.buf() + off.vbmeta);
vbmeta->flags = __builtin_bswap32(3); vbmeta->flags = __builtin_bswap32(3);
} }
} }
@ -831,4 +839,45 @@ void repack(const char *src_img, const char *out_img, bool skip_comp) {
auto b_hdr = reinterpret_cast<blob_hdr *>(out.buf()); auto b_hdr = reinterpret_cast<blob_hdr *>(out.buf());
b_hdr->size = off.total - sizeof(blob_hdr); b_hdr->size = off.total - sizeof(blob_hdr);
} }
// Sign the image after we finish patching the boot image
if (boot.flags[AVB1_SIGNED_FLAG]) {
byte_view payload(out.buf() + off.header, off.total - off.header);
auto sig = rust::sign_boot_image(payload, "/boot", nullptr, nullptr);
if (!sig.empty()) {
lseek(fd, off.total, SEEK_SET);
xwrite(fd, sig.data(), sig.size());
}
}
close(fd);
}
int verify(const char *image, const char *cert) {
const boot_img boot(image);
if (cert == nullptr) {
// Boot image parsing already checks if the image is signed
return boot.flags[AVB1_SIGNED_FLAG] ? 0 : 1;
} else {
// Provide a custom certificate and re-verify
return boot.verify(cert) ? 0 : 1;
}
}
int sign(const char *image, const char *name, const char *cert, const char *key) {
const boot_img boot(image);
auto sig = rust::sign_boot_image(boot.payload, name, cert, key);
if (sig.empty())
return 1;
auto eof = boot.tail.buf() - boot.map.buf();
int fd = xopen(image, O_WRONLY | O_CLOEXEC);
if (lseek(fd, eof, SEEK_SET) != eof || xwrite(fd, sig.data(), sig.size()) != sig.size()) {
close(fd);
return 1;
}
// Wipe out rest of tail
write_zero(fd, boot.map.sz() - lseek(fd, 0, SEEK_CUR));
close(fd);
return 0;
} }

View File

@ -3,6 +3,8 @@
#include <stdint.h> #include <stdint.h>
#include <utility> #include <utility>
#include <bitset> #include <bitset>
#include <cxx.h>
#include "format.hpp" #include "format.hpp"
/****************** /******************
@ -578,6 +580,7 @@ enum {
NOOKHD_FLAG, NOOKHD_FLAG,
ACCLAIM_FLAG, ACCLAIM_FLAG,
AMONET_FLAG, AMONET_FLAG,
AVB1_SIGNED_FLAG,
AVB_FLAG, AVB_FLAG,
ZIMAGE_KERNEL, ZIMAGE_KERNEL,
BOOT_FLAGS_MAX BOOT_FLAGS_MAX
@ -655,4 +658,9 @@ struct boot_img {
bool parse_image(const uint8_t *addr, format_t type); bool parse_image(const uint8_t *addr, format_t type);
const std::pair<const uint8_t *, dyn_img_hdr *> create_hdr(const uint8_t *addr, format_t type); const std::pair<const uint8_t *, dyn_img_hdr *> create_hdr(const uint8_t *addr, format_t type);
// Rust FFI
rust::Slice<const uint8_t> get_payload() const { return payload; }
rust::Slice<const uint8_t> get_tail() const { return tail; }
bool verify(const char *cert = nullptr) const;
}; };

View File

@ -1,11 +1,14 @@
#![feature(format_args_nl)] #![feature(format_args_nl)]
#![feature(btree_drain_filter)] #![feature(btree_drain_filter)]
extern crate alloc;
pub use base; pub use base;
use cpio::cpio_commands; use cpio::cpio_commands;
use patch::{hexpatch, patch_encryption, patch_verity}; use patch::{hexpatch, patch_encryption, patch_verity};
use payload::extract_boot_from_payload; use payload::extract_boot_from_payload;
use sha::{get_sha, sha1_hash, sha256_hash, SHA}; use sha::{get_sha, sha1_hash, sha256_hash, SHA};
use sign::{sign_boot_image, verify_boot_image};
mod cpio; mod cpio;
mod patch; mod patch;
@ -15,12 +18,21 @@ mod payload;
mod proto; mod proto;
mod ramdisk; mod ramdisk;
mod sha; mod sha;
mod sign;
#[cxx::bridge] #[cxx::bridge]
pub mod ffi { pub mod ffi {
unsafe extern "C++" { unsafe extern "C++" {
include!("compress.hpp"); include!("compress.hpp");
fn decompress(buf: &[u8], fd: i32) -> bool; fn decompress(buf: &[u8], fd: i32) -> bool;
include!("bootimg.hpp");
#[rust_name = "BootImage"]
type boot_img;
#[rust_name = "payload"]
fn get_payload(self: &BootImage) -> &[u8];
#[rust_name = "tail"]
fn get_tail(self: &BootImage) -> &[u8];
} }
extern "Rust" { extern "Rust" {
@ -46,5 +58,12 @@ pub mod ffi {
) -> bool; ) -> bool;
unsafe fn cpio_commands(argc: i32, argv: *const *const c_char) -> bool; unsafe fn cpio_commands(argc: i32, argv: *const *const c_char) -> bool;
unsafe fn verify_boot_image(img: &BootImage, cert: *const c_char) -> bool;
unsafe fn sign_boot_image(
payload: &[u8],
name: *const c_char,
cert: *const c_char,
key: *const c_char,
) -> Vec<u8>;
} }
} }

View File

@ -16,6 +16,8 @@
int unpack(const char *image, bool skip_decomp = false, bool hdr = false); int unpack(const char *image, bool skip_decomp = false, bool hdr = false);
void repack(const char *src_img, const char *out_img, bool skip_comp = false); void repack(const char *src_img, const char *out_img, bool skip_comp = false);
int verify(const char *image, const char *cert);
int sign(const char *image, const char *name, const char *cert, const char *key);
int split_image_dtb(const char *filename); int split_image_dtb(const char *filename);
int dtb_commands(int argc, char *argv[]); int dtb_commands(int argc, char *argv[]);

View File

@ -45,6 +45,20 @@ Supported actions:
If env variable PATCHVBMETAFLAG is set to true, all disable flags in If env variable PATCHVBMETAFLAG is set to true, all disable flags in
the boot image's vbmeta header will be set. the boot image's vbmeta header will be set.
verify <bootimg> [x509.pem]
Check whether the boot image is signed with AVB 1.0 signature.
Optionally provide a certificate to verify whether the image is
signed by the public key certificate.
Return value:
0:valid 1:error
sign <bootimg> [name] [x509.pem pk8]
Sign <bootimg> with AVB 1.0 signature.
Optionally provide the name of the image (default: '/boot').
Optionally provide the certificate/private key pair for signing.
If the certificate/private key pair is not provided, the AOSP
verity key bundled in the executable will be used.
extract <payload.bin> [partition] [outfile] extract <payload.bin> [partition] [outfile]
Extract [partition] from <payload.bin> to [outfile]. Extract [partition] from <payload.bin> to [outfile].
If [outfile] is not specified, then output to '[partition].img'. If [outfile] is not specified, then output to '[partition].img'.
@ -171,6 +185,15 @@ int main(int argc, char *argv[]) {
} else { } else {
repack(argv[2], argv[3] ? argv[3] : NEW_BOOT); repack(argv[2], argv[3] ? argv[3] : NEW_BOOT);
} }
} else if (argc > 2 && action == "verify") {
return verify(argv[2], argv[3]);
} else if (argc > 2 && action == "sign") {
if (argc == 5) usage(argv[0]);
return sign(
argv[2],
argc > 3 ? argv[3] : "/boot",
argc > 5 ? argv[4] : nullptr,
argc > 5 ? argv[5] : nullptr);
} else if (argc > 2 && action == "decompress") { } else if (argc > 2 && action == "decompress") {
decompress(argv[2], argv[3]); decompress(argv[2], argv[3]);
} else if (argc > 2 && str_starts(action, "compress")) { } else if (argc > 2 && str_starts(action, "compress")) {

273
native/src/boot/sign.rs Normal file
View File

@ -0,0 +1,273 @@
use der::referenced::OwnedToRef;
use der::{Decode, DecodePem, Encode, Sequence, SliceReader};
use digest::DynDigest;
use p256::ecdsa::{
Signature as P256Signature, SigningKey as P256SigningKey, VerifyingKey as P256VerifyingKey,
};
use p256::pkcs8::DecodePrivateKey;
use p384::ecdsa::{
Signature as P384Signature, SigningKey as P384SigningKey, VerifyingKey as P384VerifyingKey,
};
use rsa::pkcs1v15::{
Signature as RsaSignature, SigningKey as RsaSigningKey, VerifyingKey as RsaVerifyingKey,
};
use rsa::pkcs8::SubjectPublicKeyInfoRef;
use rsa::signature::hazmat::{PrehashSigner, PrehashVerifier};
use rsa::signature::SignatureEncoding;
use rsa::{RsaPrivateKey, RsaPublicKey};
use sha2::{Sha256, Sha384};
use x509_cert::der::asn1::{OctetString, PrintableString};
use x509_cert::der::Any;
use x509_cert::spki::AlgorithmIdentifier;
use x509_cert::Certificate;
use base::libc::c_char;
use base::{log_err, LoggedResult, MappedFile, ResultExt, StrErr, Utf8CStr};
use crate::ffi::BootImage;
#[allow(clippy::large_enum_variant)]
enum SigningKey {
SHA256withRSA(RsaSigningKey<Sha256>),
SHA256withECDSA(P256SigningKey),
SHA384withECDSA(P384SigningKey),
}
#[allow(clippy::large_enum_variant)]
enum VerifyingKey {
SHA256withRSA(RsaVerifyingKey<Sha256>),
SHA256withECDSA(P256VerifyingKey),
SHA384withECDSA(P384VerifyingKey),
}
struct Verifier {
digest: Box<dyn DynDigest>,
key: VerifyingKey,
}
impl Verifier {
fn from_public_key(key: SubjectPublicKeyInfoRef) -> LoggedResult<Verifier> {
let digest: Box<dyn DynDigest>;
let key = if let Ok(rsa) = RsaPublicKey::try_from(key.clone()) {
digest = Box::<Sha256>::default();
VerifyingKey::SHA256withRSA(RsaVerifyingKey::<Sha256>::new(rsa))
} else if let Ok(ec) = P256VerifyingKey::try_from(key.clone()) {
digest = Box::<Sha256>::default();
VerifyingKey::SHA256withECDSA(ec)
} else if let Ok(ec) = P384VerifyingKey::try_from(key.clone()) {
digest = Box::<Sha384>::default();
VerifyingKey::SHA384withECDSA(ec)
} else {
return Err(log_err!("Unsupported private key"));
};
Ok(Verifier { digest, key })
}
fn update(&mut self, data: &[u8]) {
self.digest.update(data)
}
fn verify(mut self, signature: &[u8]) -> LoggedResult<()> {
let hash = self.digest.finalize_reset();
return match &self.key {
VerifyingKey::SHA256withRSA(key) => {
let sig = RsaSignature::try_from(signature)?;
key.verify_prehash(hash.as_ref(), &sig).log()
}
VerifyingKey::SHA256withECDSA(key) => {
let sig = P256Signature::from_slice(signature)?;
key.verify_prehash(hash.as_ref(), &sig).log()
}
VerifyingKey::SHA384withECDSA(key) => {
let sig = P384Signature::from_slice(signature)?;
key.verify_prehash(hash.as_ref(), &sig).log()
}
};
}
}
struct Signer {
digest: Box<dyn DynDigest>,
key: SigningKey,
}
impl Signer {
fn from_private_key(key: &[u8]) -> LoggedResult<Signer> {
let digest: Box<dyn DynDigest>;
let key = if let Ok(rsa) = RsaPrivateKey::from_pkcs8_der(key) {
digest = Box::<Sha256>::default();
SigningKey::SHA256withRSA(RsaSigningKey::<Sha256>::new(rsa))
} else if let Ok(ec) = P256SigningKey::from_pkcs8_der(key) {
digest = Box::<Sha256>::default();
SigningKey::SHA256withECDSA(ec)
} else if let Ok(ec) = P384SigningKey::from_pkcs8_der(key) {
digest = Box::<Sha384>::default();
SigningKey::SHA384withECDSA(ec)
} else {
return Err(log_err!("Unsupported private key"));
};
Ok(Signer { digest, key })
}
fn update(&mut self, data: &[u8]) {
self.digest.update(data)
}
fn sign(mut self) -> LoggedResult<Vec<u8>> {
let hash = self.digest.finalize_reset();
let v = match &self.key {
SigningKey::SHA256withRSA(key) => {
let sig: RsaSignature = key.sign_prehash(hash.as_ref())?;
sig.to_vec()
}
SigningKey::SHA256withECDSA(key) => {
let sig: P256Signature = key.sign_prehash(hash.as_ref())?;
sig.to_vec()
}
SigningKey::SHA384withECDSA(key) => {
let sig: P384Signature = key.sign_prehash(hash.as_ref())?;
sig.to_vec()
}
};
Ok(v)
}
}
/*
* BootSignature ::= SEQUENCE {
* formatVersion ::= INTEGER,
* certificate ::= Certificate,
* algorithmIdentifier ::= SEQUENCE {
* algorithm OBJECT IDENTIFIER,
* parameters ANY DEFINED BY algorithm OPTIONAL
* },
* authenticatedAttributes ::= SEQUENCE {
* target CHARACTER STRING,
* length INTEGER
* },
* signature ::= OCTET STRING
* }
*/
#[derive(Sequence)]
struct AuthenticatedAttributes {
target: PrintableString,
length: u64,
}
#[derive(Sequence)]
struct BootSignature {
format_version: i32,
certificate: Certificate,
algorithm_identifier: AlgorithmIdentifier<Any>,
authenticated_attributes: AuthenticatedAttributes,
signature: OctetString,
}
impl BootSignature {
fn verify(self, payload: &[u8]) -> LoggedResult<()> {
if self.authenticated_attributes.length as usize != payload.len() {
return Err(log_err!("Invalid image size"));
}
let mut verifier = Verifier::from_public_key(
self.certificate
.tbs_certificate
.subject_public_key_info
.owned_to_ref(),
)?;
verifier.update(payload);
let attr = self.authenticated_attributes.to_der()?;
verifier.update(attr.as_slice());
verifier.verify(self.signature.as_bytes())?;
Ok(())
}
}
pub fn verify_boot_image(img: &BootImage, cert: *const c_char) -> bool {
fn inner(img: &BootImage, cert: *const c_char) -> LoggedResult<()> {
let tail = img.tail();
// Don't use BootSignature::from_der because tail might have trailing zeros
let mut reader = SliceReader::new(tail)?;
let mut sig = BootSignature::decode(&mut reader)?;
match unsafe { Utf8CStr::from_ptr(cert) } {
Ok(s) => {
let pem = MappedFile::open(s)?;
sig.certificate = Certificate::from_pem(pem)?;
}
Err(StrErr::NullPointerError) => {}
Err(e) => Err(e)?,
};
sig.verify(img.payload())?;
Ok(())
}
inner(img, cert).is_ok()
}
enum Bytes {
Mapped(MappedFile),
Slice(&'static [u8]),
}
impl AsRef<[u8]> for Bytes {
fn as_ref(&self) -> &[u8] {
match self {
Bytes::Mapped(m) => m.as_ref(),
Bytes::Slice(s) => s,
}
}
}
const VERITY_PEM: &[u8] = include_bytes!("../../../tools/keys/verity.x509.pem");
const VERITY_PK8: &[u8] = include_bytes!("../../../tools/keys/verity.pk8");
pub fn sign_boot_image(
payload: &[u8],
name: *const c_char,
cert: *const c_char,
key: *const c_char,
) -> Vec<u8> {
fn inner(
payload: &[u8],
name: *const c_char,
cert: *const c_char,
key: *const c_char,
) -> LoggedResult<Vec<u8>> {
// Process arguments
let name = unsafe { Utf8CStr::from_ptr(name) }?;
let cert = match unsafe { Utf8CStr::from_ptr(cert) } {
Ok(s) => Bytes::Mapped(MappedFile::open(s)?),
Err(StrErr::NullPointerError) => Bytes::Slice(VERITY_PEM),
Err(e) => Err(e)?,
};
let key = match unsafe { Utf8CStr::from_ptr(key) } {
Ok(s) => Bytes::Mapped(MappedFile::open(s)?),
Err(StrErr::NullPointerError) => Bytes::Slice(VERITY_PK8),
Err(e) => Err(e)?,
};
// Parse cert and private key
let cert = Certificate::from_pem(cert)?;
let mut signer = Signer::from_private_key(key.as_ref())?;
// Sign image
let attr = AuthenticatedAttributes {
target: PrintableString::new(name.as_bytes())?,
length: payload.len() as u64,
};
signer.update(payload);
signer.update(attr.to_der()?.as_slice());
let sig = signer.sign()?;
// Create BootSignature DER
let alg_id = cert.signature_algorithm.clone();
let sig = BootSignature {
format_version: 1,
certificate: cert,
algorithm_identifier: alg_id,
authenticated_attributes: attr,
signature: OctetString::new(sig)?,
};
sig.to_der().log()
}
inner(payload, name, cert, key).unwrap_or(Vec::new())
}