summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDoug Zongker <dougz@android.com>2010-09-12 14:23:27 -0700
committerAndroid Git Automerger <android-git-automerger@android.com>2010-09-12 14:23:27 -0700
commit21856f36acab77f986436ec26bca73edbf3ddfc7 (patch)
tree861ddfec5887458a1d2a48025a68687393e854fd
parentb6cc76159b4ec1fa7f0f96b4d4fb093b160d0147 (diff)
parent06083e44b28162761d718da52dc1662cb6e5ee35 (diff)
downloadcommon-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.py7
-rw-r--r--updater/firmware.c113
-rw-r--r--updater/firmware.h3
-rw-r--r--updater/recovery_updater.c33
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: