From 67667c803c0526bf7443bd28956e62e591c7132c Mon Sep 17 00:00:00 2001 From: cfig Date: Sun, 9 Feb 2020 13:42:04 +0800 Subject: [PATCH] refine avbVerifier; fix AuthBlob bug 1. AuthBlob bug: if change algorithm_type from 0 to non-zero values, auth_blob should not be empty 2. avbVerifier: move key file to config/pubkey add gradle task "v1/v2" to verify normal/recovery flow --- .gitignore | 1 + README.md | 2 +- avbImpl/build.gradle | 13 ++++ avbImpl/src/avbVerifier/cpp/main.cpp | 62 ++++++++++++++++--- avbImpl/src/avbx/cpp/CfigAvbOps.cpp | 4 +- bbootimg/src/main/kotlin/avb/Avb.kt | 7 +-- bbootimg/src/main/kotlin/avb/blob/AuthBlob.kt | 2 +- 7 files changed, 71 insertions(+), 20 deletions(-) diff --git a/.gitignore b/.gitignore index 23841a6..6eb8b6a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .idea .gradle +build/ diff --git a/README.md b/README.md index a84a8e5..ff36f9b 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ Supported images: (2) These utilities are known to work for Nexus/Pixel boot.img for the following Android releases: - AOSP master - - Lollipop (5.0) - Q preview + - Lollipop (5.0) - Android 10 ## 2. Usage Clone this repo with minimal depth: diff --git a/avbImpl/build.gradle b/avbImpl/build.gradle index 4307fec..84bdb2e 100644 --- a/avbImpl/build.gradle +++ b/avbImpl/build.gradle @@ -34,3 +34,16 @@ model { } } } + +task v1(type:Exec) { + workingDir "." + environment preloads: "vbmeta boot", requests: "boot dtbo", suffix: "" + commandLine "./build/exe/avbVerifier/avbVerifier" +} + +task v2(type:Exec) { + description "verify non-AB recovery mode" + workingDir "." + environment preloads: "", requests: "recovery", suffix: "" + commandLine "./build/exe/avbVerifier/avbVerifier" +} diff --git a/avbImpl/src/avbVerifier/cpp/main.cpp b/avbImpl/src/avbVerifier/cpp/main.cpp index 7e8abd3..aa54ee2 100644 --- a/avbImpl/src/avbVerifier/cpp/main.cpp +++ b/avbImpl/src/avbVerifier/cpp/main.cpp @@ -15,36 +15,75 @@ #include "helper.hpp" std::vector splitString(const std::string& subject) { + if (subject.size() == 0) { + return std::vector(); + } static const std::regex re{"\\s+"}; - std::vector container{ - std::sregex_token_iterator(subject.begin(), subject.end(), re, -1), + std::vector container { + std::sregex_token_iterator(subject.begin(), subject.end(), re, -1), std::sregex_token_iterator() }; return container; } int main(int, char**) { - auto cfigOps = CfigAvbOps(); - auto preloads = getenv("preload"); + int flags = AVB_SLOT_VERIFY_FLAGS_NONE; + //param 1: preload partitions + auto preloads = getenv("preloads"); if (preloads == NULL) { - } else { + preloads = (char*) ""; + } + std::cout << "[" << __FUNCTION__ << "]: partitions to preload: " << preloads << std::endl; + + //param 2: requested partitions + auto requests = getenv("requests"); + if (requests == NULL) { + requests = (char*) ""; + } + std::cout << "[" << __FUNCTION__ << "]: requested partitions: " << requests << std::endl; + auto requestVec = splitString(requests); + //example: const char* requestedPartitions[] = { (const char*) "boot", (const char*)NULL }; + const char* requestedPartitions[requestVec.size() + 1]; + for (int i = 0; i< requestVec.size(); i++) { + requestedPartitions[i] = requestVec[i].c_str(); + if (requestVec[i] == "recovery") { + flags |= AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION; + std::cout << "[" << __FUNCTION__ << "]: using NO-VBMETA mode for recovery" << std::endl; + } + } + requestedPartitions[requestVec.size()] = (const char*)NULL; + //param3: ab_suffix + auto abSuffix = getenv("suffix"); + if (abSuffix == NULL) { + abSuffix = (char*) ""; + } + std::cout << "[" << __FUNCTION__ << "]: ab_suffix: " << abSuffix << std::endl; + + //main + auto cfigOps = CfigAvbOps(); + + {//preload partitions auto preloadVec = splitString(preloads); for (auto item: preloadVec) { cfigOps.preload_partition(item); } } - cfigOps.preload_partition("vbmeta"); + bool isDeviceLocked = true; + cfigOps.avb_ops_.read_is_device_unlocked(NULL, &isDeviceLocked); + if (isDeviceLocked) { + flags |= AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR; + } + std::cout << "[" << __FUNCTION__ << "]: flags: " << flags << std::endl; + AvbSlotVerifyData *slotData = NULL; - const char* requestedPartitions[] = { (const char*) "boot", (const char*)NULL }; AvbSlotVerifyResult result = avb_slot_verify( &(cfigOps.avb_ops_), requestedPartitions, - "", - AVB_SLOT_VERIFY_FLAGS_NONE, + abSuffix, /* ab_suffix */ + static_cast(flags), /* AvbSlotVerifyFlags */ AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE, &slotData); - std::cout << "AvbSlotVerifyResult = " << toString(result) << std::endl; if (AVB_SLOT_VERIFY_RESULT_OK == result) { auto outFile = "verify_result.json"; std::cout << "Writing result to " << outFile << "... "; @@ -52,6 +91,9 @@ int main(int, char**) { outJson << toString(slotData); outJson.close(); std::cout << " done" << std::endl; + std::cout << "Run:\n python -m json.tool " << outFile << std::endl; } + if (slotData) { avb_slot_verify_data_free(slotData); } + std::cerr << "\n\tVerify Result: " << toString(result) << std::endl; return 0; } diff --git a/avbImpl/src/avbx/cpp/CfigAvbOps.cpp b/avbImpl/src/avbx/cpp/CfigAvbOps.cpp index e613cab..7390fc2 100644 --- a/avbImpl/src/avbx/cpp/CfigAvbOps.cpp +++ b/avbImpl/src/avbx/cpp/CfigAvbOps.cpp @@ -22,7 +22,7 @@ static std::string expected_public_key_; static std::string expected_public_key_metadata_; static auto lockStatusFile = "config/locked"; -static auto pubkeyFile = "config/rsa4096.pubkey"; +static auto pubkeyFile = "config/pubkey"; static std::string read_line(std::string file); @@ -347,7 +347,7 @@ bool CfigAvbOps::preload_partition(std::string partition) { preloaded_partitions_[partition] = buffer; - fprintf(stderr, + fprintf(stdout, "[%s()]: partition [%s] preloaded\n", __FUNCTION__, partition.c_str()); diff --git a/bbootimg/src/main/kotlin/avb/Avb.kt b/bbootimg/src/main/kotlin/avb/Avb.kt index bcfacd5..2b2895d 100644 --- a/bbootimg/src/main/kotlin/avb/Avb.kt +++ b/bbootimg/src/main/kotlin/avb/Avb.kt @@ -298,12 +298,7 @@ class Avb { }.encode() //2 - auth blob - var authBlob = byteArrayOf() - if (ai.authBlob != null) { - authBlob = AuthBlob.createBlob(headerBlob, auxBlob, alg.name) - } else { - log.info("No auth blob") - } + val authBlob = AuthBlob.createBlob(headerBlob, auxBlob, alg.name) return Helper.join(headerBlob, authBlob, auxBlob) } diff --git a/bbootimg/src/main/kotlin/avb/blob/AuthBlob.kt b/bbootimg/src/main/kotlin/avb/blob/AuthBlob.kt index 1113c7f..3ee3a65 100644 --- a/bbootimg/src/main/kotlin/avb/blob/AuthBlob.kt +++ b/bbootimg/src/main/kotlin/avb/blob/AuthBlob.kt @@ -19,7 +19,7 @@ data class AuthBlob( val alg = Algorithms.get(algorithm_name)!! val authBlockSize = Helper.round_to_multiple((alg.hash_num_bytes + alg.signature_num_bytes).toLong(), 64) if (0L == authBlockSize) { - log.info("No auth blob") + log.info("No auth blob for algorithm " + alg.name) return byteArrayOf() }