diff options
author | Doug Zongker <dougz@android.com> | 2010-09-12 14:23:27 -0700 |
---|---|---|
committer | Android Git Automerger <android-git-automerger@android.com> | 2010-09-12 14:23:27 -0700 |
commit | 21856f36acab77f986436ec26bca73edbf3ddfc7 (patch) | |
tree | 861ddfec5887458a1d2a48025a68687393e854fd | |
parent | b6cc76159b4ec1fa7f0f96b4d4fb093b160d0147 (diff) | |
parent | 06083e44b28162761d718da52dc1662cb6e5ee35 (diff) | |
download | common-21856f36acab77f986436ec26bca73edbf3ddfc7.tar.gz |
am 06083e44: read back and verify radio image from cache before installing
Merge commit '06083e44b28162761d718da52dc1662cb6e5ee35' into gingerbread-plus-aosp
* commit '06083e44b28162761d718da52dc1662cb6e5ee35':
read back and verify radio image from cache before installing
-rw-r--r-- | releasetools.py | 7 | ||||
-rw-r--r-- | updater/firmware.c | 113 | ||||
-rw-r--r-- | updater/firmware.h | 3 | ||||
-rw-r--r-- | updater/recovery_updater.c | 33 |
4 files changed, 135 insertions, 21 deletions
diff --git a/releasetools.py b/releasetools.py index d8c3361..01b39e6 100644 --- a/releasetools.py +++ b/releasetools.py @@ -17,7 +17,7 @@ import common import re - +import sha def FullOTA_Assertions(info): AddBootloaderAssertion(info, info.input_zip) @@ -46,12 +46,15 @@ def InstallRadio(radio_img, api_version, input_zip, info): error_img = input_zip.read("RADIO/firmware_error.565") width, height, bpp = bitmap_txt.split() + radio_sha = sha.sha(radio_img).hexdigest() + info.script.UnmountAll() info.script.AppendExtra((''' assert(htc.install_radio(package_extract_file("radio.img"), %(width)s, %(height)s, %(bpp)s, package_extract_file("install.565"), - package_extract_file("error.565"))); + package_extract_file("error.565"), + %(radio_sha)s)); ''' % locals()).lstrip()) common.ZipWriteStr(info.output_zip, "install.565", install_img) diff --git a/updater/firmware.c b/updater/firmware.c index 76b9344..4672e18 100644 --- a/updater/firmware.c +++ b/updater/firmware.c @@ -18,6 +18,7 @@ #include "common.h" #include "firmware.h" #include "mtdutils/mtdutils.h" +#include "mincrypt/sha.h" #include <errno.h> #include <string.h> @@ -58,13 +59,98 @@ #undef LOGE #define LOGE(...) fprintf(stderr, "E:" __VA_ARGS__) + +int verify_image(const uint8_t* expected_sha1) { + MtdPartition* part = mtd_find_partition_by_name(CACHE_NAME); + if (part == NULL) { + printf("verify image: failed to find cache partition\n"); + return -1; + } + + size_t block_size; + if (mtd_partition_info(part, NULL, &block_size, NULL) != 0) { + printf("verify image: failed to get cache partition block size\n"); + return -1; + } + printf("block size is 0x%x\n", block_size); + + char* buffer = malloc(block_size); + if (buffer == NULL) { + printf("verify image: failed to allocate memory\n"); + return -1; + } + + MtdReadContext* ctx = mtd_read_partition(part); + if (ctx == NULL) { + printf("verify image: failed to init read context\n"); + return -1; + } + + size_t pos = 0; + if (mtd_read_data(ctx, buffer, block_size) != block_size) { + printf("verify image: failed to read header\n"); + return -1; + } + pos += block_size; + + if (strncmp(buffer, "MSM-RADIO-UPDATE", 16) != 0) { + printf("verify image: header missing magic\n"); + return -1; + } + + unsigned image_offset = *(unsigned*)(buffer+24); + unsigned image_length = *(unsigned*)(buffer+28); + printf("image offset 0x%x length 0x%x\n", image_offset, image_length); + + while (pos < image_offset) { + size_t to_read = image_offset - pos; + if (to_read > block_size) to_read = block_size; + ssize_t read = mtd_read_data(ctx, buffer, to_read); + if (read < 0) { + printf("verify image: failed to skip to image start\n"); + return -1; + } + pos += read; + } + + SHA_CTX sha_ctx; + SHA_init(&sha_ctx); + + size_t total = 0; + while (total < image_length) { + size_t to_read = image_length - total; + if (to_read > block_size) to_read = block_size; + ssize_t read = mtd_read_data(ctx, buffer, to_read); + if (read < 0) { + printf("verify image: failed reading image (read 0x%x so far)\n", + total); + return -1; + } + SHA_update(&sha_ctx, buffer, read); + total += read; + } + + free(buffer); + + const uint8_t* sha1 = SHA_final(&sha_ctx); + if (memcmp(sha1, expected_sha1, SHA_DIGEST_SIZE) != 0) { + printf("verify image: sha1 doesn't match\n"); + return -1; + } + + printf("verify image: verification succeeded\n"); + + return 0; +} + int install_firmware_update(const char *update_type, const char *update_data, size_t update_length, int width, int height, int bpp, const char* busy_image, const char* fail_image, - const char *log_filename) { + const char *log_filename, + const uint8_t* expected_sha1) { if (update_data == NULL || update_length == 0) return 0; mtd_scan_partitions(); @@ -87,18 +173,21 @@ int install_firmware_update(const char *update_type, return -1; } - /* The update image is fully written, so now we can instruct the bootloader - * to install it. (After doing so, it will come back here, and we will - * wipe the cache and reboot into the system.) - */ - snprintf(boot.command, sizeof(boot.command), "update-%s", update_type); - if (set_bootloader_message(&boot)) { - return -1; - } + if (verify_image(expected_sha1) == 0) { + /* The update image is fully written, so now we can instruct + * the bootloader to install it. (After doing so, it will + * come back here, and we will wipe the cache and reboot into + * the system.) + */ + snprintf(boot.command, sizeof(boot.command), "update-%s", update_type); + if (set_bootloader_message(&boot)) { + return -1; + } - reboot(RB_AUTOBOOT); + reboot(RB_AUTOBOOT); - // Can't reboot? WTF? - LOGE("Can't reboot\n"); + // Can't reboot? WTF? + LOGE("Can't reboot\n"); + } return -1; } diff --git a/updater/firmware.h b/updater/firmware.h index 7297ecf..e463b6c 100644 --- a/updater/firmware.h +++ b/updater/firmware.h @@ -27,6 +27,7 @@ int install_firmware_update(const char *update_type, int width, int height, int bpp, const char* busy_image, const char* fail_image, - const char *log_filename); + const char *log_filename, + const uint8_t* expected_sha1); #endif diff --git a/updater/recovery_updater.c b/updater/recovery_updater.c index 64b35a5..d382f96 100644 --- a/updater/recovery_updater.c +++ b/updater/recovery_updater.c @@ -21,12 +21,13 @@ #include <string.h> #include <sys/stat.h> +#include "mincrypt/sha.h" #include "edify/expr.h" #include "firmware.h" Value* UpdateFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 6) { - return ErrorAbort(state, "%s() expects 6 args, got %d", name, argc); + if (argc != 7) { + return ErrorAbort(state, "%s() expects 7 args, got %d", name, argc); } char* type = strrchr(name, '_'); @@ -42,9 +43,10 @@ Value* UpdateFn(const char* name, State* state, int argc, Expr* argv[]) { Value* bpp_string; Value* busy; Value* fail; - if (ReadValueArgs(state, argv, 6, &image, - &width_string, &height_string, &bpp_string, - &busy, &fail) < 0) { + Value* expected_sha1_string; + if (ReadValueArgs(state, argv, 7, &image, + &width_string, &height_string, &bpp_string, + &busy, &fail, &expected_sha1_string) < 0) { return NULL; } @@ -68,6 +70,24 @@ Value* UpdateFn(const char* name, State* state, int argc, Expr* argv[]) { goto done; } + uint8_t expected_sha1[SHA_DIGEST_SIZE]; + char* data = expected_sha1_string->data; + if (expected_sha1_string->type != VAL_STRING || + strlen(data) != SHA_DIGEST_SIZE*2) { + printf("%s(): bad expected_sha1 argument", name); + goto done; + } + printf("expected sha1 is: "); + int i; + for (i = 0; i < SHA_DIGEST_SIZE; ++i) { + char temp = data[i*2+2]; + data[i*2+2] = '\0'; + expected_sha1[i] = strtol(data+i*2, NULL, 16); + data[i*2+2] = temp; + printf("%02x", expected_sha1[i]); + } + printf("\n"); + install_firmware_update( type, image->data, @@ -75,7 +95,8 @@ Value* UpdateFn(const char* name, State* state, int argc, Expr* argv[]) { width, height, bpp, busy->size > 0 ? busy->data : NULL, fail->size > 0 ? fail->data : NULL, - "/tmp/recovery.log"); + "/tmp/recovery.log", + expected_sha1); printf("%s: install_firmware_update returned!\n", name); done: |