diff options
-rw-r--r-- | applypatch/applypatch.c | 27 | ||||
-rw-r--r-- | install.cpp | 100 | ||||
-rw-r--r-- | minzip/Zip.c | 6 | ||||
-rw-r--r-- | verifier.cpp | 102 | ||||
-rw-r--r-- | verifier.h | 2 | ||||
-rw-r--r-- | verifier_test.cpp | 11 |
6 files changed, 138 insertions, 110 deletions
diff --git a/applypatch/applypatch.c b/applypatch/applypatch.c index 7b8a010e3..69f8633ab 100644 --- a/applypatch/applypatch.c +++ b/applypatch/applypatch.c @@ -585,6 +585,14 @@ int CacheSizeCheck(size_t bytes) { } } +static void print_short_sha1(const uint8_t sha1[SHA_DIGEST_SIZE]) { + int i; + const char* hex = "0123456789abcdef"; + for (i = 0; i < 4; ++i) { + putchar(hex[(sha1[i]>>4) & 0xf]); + putchar(hex[sha1[i] & 0xf]); + } +} // This function applies binary patches to files in a way that is safe // (the original file is not touched until we have the desired @@ -620,7 +628,7 @@ int applypatch(const char* source_filename, char** const patch_sha1_str, Value** patch_data, Value* bonus_data) { - printf("\napplying patch to %s\n", source_filename); + printf("patch %s: ", source_filename); if (target_filename[0] == '-' && target_filename[1] == '\0') { @@ -646,8 +654,9 @@ int applypatch(const char* source_filename, if (memcmp(source_file.sha1, target_sha1, SHA_DIGEST_SIZE) == 0) { // The early-exit case: the patch was already applied, this file // has the desired hash, nothing for us to do. - printf("\"%s\" is already target; no patch needed\n", - target_filename); + printf("already "); + print_short_sha1(target_sha1); + putchar('\n'); free(source_file.data); return 0; } @@ -769,8 +778,10 @@ static int GenerateTarget(FileContents* source_file, enough_space = (free_space > (256 << 10)) && // 256k (two-block) minimum (free_space > (target_size * 3 / 2)); // 50% margin of error - printf("target %ld bytes; free space %ld bytes; retry %d; enough %d\n", - (long)target_size, (long)free_space, retry, enough_space); + if (!enough_space) { + printf("target %ld bytes; free space %ld bytes; retry %d; enough %d\n", + (long)target_size, (long)free_space, retry, enough_space); + } } if (!enough_space) { @@ -805,7 +816,7 @@ static int GenerateTarget(FileContents* source_file, unlink(source_filename); size_t free_space = FreeSpaceForFile(target_fs); - printf("(now %ld bytes free for target)\n", (long)free_space); + printf("(now %ld bytes free for target) ", (long)free_space); } } @@ -901,6 +912,10 @@ static int GenerateTarget(FileContents* source_file, if (memcmp(current_target_sha1, target_sha1, SHA_DIGEST_SIZE) != 0) { printf("patch did not produce expected sha1\n"); return 1; + } else { + printf("now "); + print_short_sha1(target_sha1); + putchar('\n'); } if (output < 0) { diff --git a/install.cpp b/install.cpp index b8f478130..0f3298f1d 100644 --- a/install.cpp +++ b/install.cpp @@ -174,106 +174,6 @@ try_update_binary(const char *path, ZipArchive *zip, int* wipe_cache) { return INSTALL_SUCCESS; } -// Reads a file containing one or more public keys as produced by -// DumpPublicKey: this is an RSAPublicKey struct as it would appear -// as a C source literal, eg: -// -// "{64,0xc926ad21,{1795090719,...,-695002876},{-857949815,...,1175080310}}" -// -// For key versions newer than the original 2048-bit e=3 keys -// supported by Android, the string is preceded by a version -// identifier, eg: -// -// "v2 {64,0xc926ad21,{1795090719,...,-695002876},{-857949815,...,1175080310}}" -// -// (Note that the braces and commas in this example are actual -// characters the parser expects to find in the file; the ellipses -// indicate more numbers omitted from this example.) -// -// The file may contain multiple keys in this format, separated by -// commas. The last key must not be followed by a comma. -// -// Returns NULL if the file failed to parse, or if it contain zero keys. -static RSAPublicKey* -load_keys(const char* filename, int* numKeys) { - RSAPublicKey* out = NULL; - *numKeys = 0; - - FILE* f = fopen(filename, "r"); - if (f == NULL) { - LOGE("opening %s: %s\n", filename, strerror(errno)); - goto exit; - } - - { - int i; - bool done = false; - while (!done) { - ++*numKeys; - out = (RSAPublicKey*)realloc(out, *numKeys * sizeof(RSAPublicKey)); - RSAPublicKey* key = out + (*numKeys - 1); - - char start_char; - if (fscanf(f, " %c", &start_char) != 1) goto exit; - if (start_char == '{') { - // a version 1 key has no version specifier. - key->exponent = 3; - } else if (start_char == 'v') { - int version; - if (fscanf(f, "%d {", &version) != 1) goto exit; - if (version == 2) { - key->exponent = 65537; - } else { - goto exit; - } - } - - if (fscanf(f, " %i , 0x%x , { %u", - &(key->len), &(key->n0inv), &(key->n[0])) != 3) { - goto exit; - } - if (key->len != RSANUMWORDS) { - LOGE("key length (%d) does not match expected size\n", key->len); - goto exit; - } - for (i = 1; i < key->len; ++i) { - if (fscanf(f, " , %u", &(key->n[i])) != 1) goto exit; - } - if (fscanf(f, " } , { %u", &(key->rr[0])) != 1) goto exit; - for (i = 1; i < key->len; ++i) { - if (fscanf(f, " , %u", &(key->rr[i])) != 1) goto exit; - } - fscanf(f, " } } "); - - // if the line ends in a comma, this file has more keys. - switch (fgetc(f)) { - case ',': - // more keys to come. - break; - - case EOF: - done = true; - break; - - default: - LOGE("unexpected character between keys\n"); - goto exit; - } - - LOGI("read key e=%d\n", key->exponent); - } - } - - fclose(f); - return out; - -exit: - if (f) fclose(f); - free(out); - *numKeys = 0; - return NULL; -} - static int really_install_package(const char *path, int* wipe_cache) { diff --git a/minzip/Zip.c b/minzip/Zip.c index c87f038c5..439e5d9cd 100644 --- a/minzip/Zip.c +++ b/minzip/Zip.c @@ -985,6 +985,7 @@ bool mzExtractRecursive(const ZipArchive *pArchive, unsigned int i; bool seenMatch = false; int ok = true; + int extractCount = 0; for (i = 0; i < pArchive->numEntries; i++) { ZipEntry *pEntry = pArchive->pEntries + i; if (pEntry->fileNameLen < zipDirLen) { @@ -1150,13 +1151,16 @@ bool mzExtractRecursive(const ZipArchive *pArchive, break; } - LOGD("Extracted file \"%s\"\n", targetFile); + LOGV("Extracted file \"%s\"\n", targetFile); + ++extractCount; } } if (callback != NULL) callback(targetFile, cookie); } + LOGD("Extracted %d file(s)\n", extractCount); + free(helper.buf); free(zpath); diff --git a/verifier.cpp b/verifier.cpp index 1c5a41d1b..5f4c981e5 100644 --- a/verifier.cpp +++ b/verifier.cpp @@ -179,9 +179,111 @@ int verify_file(const char* path, const RSAPublicKey *pKeys, unsigned int numKey LOGI("whole-file signature verified against key %d\n", i); free(eocd); return VERIFY_SUCCESS; + } else { + LOGI("failed to verify against key %d\n", i); } } free(eocd); LOGE("failed to verify whole-file signature\n"); return VERIFY_FAILURE; } + +// Reads a file containing one or more public keys as produced by +// DumpPublicKey: this is an RSAPublicKey struct as it would appear +// as a C source literal, eg: +// +// "{64,0xc926ad21,{1795090719,...,-695002876},{-857949815,...,1175080310}}" +// +// For key versions newer than the original 2048-bit e=3 keys +// supported by Android, the string is preceded by a version +// identifier, eg: +// +// "v2 {64,0xc926ad21,{1795090719,...,-695002876},{-857949815,...,1175080310}}" +// +// (Note that the braces and commas in this example are actual +// characters the parser expects to find in the file; the ellipses +// indicate more numbers omitted from this example.) +// +// The file may contain multiple keys in this format, separated by +// commas. The last key must not be followed by a comma. +// +// Returns NULL if the file failed to parse, or if it contain zero keys. +RSAPublicKey* +load_keys(const char* filename, int* numKeys) { + RSAPublicKey* out = NULL; + *numKeys = 0; + + FILE* f = fopen(filename, "r"); + if (f == NULL) { + LOGE("opening %s: %s\n", filename, strerror(errno)); + goto exit; + } + + { + int i; + bool done = false; + while (!done) { + ++*numKeys; + out = (RSAPublicKey*)realloc(out, *numKeys * sizeof(RSAPublicKey)); + RSAPublicKey* key = out + (*numKeys - 1); + + char start_char; + if (fscanf(f, " %c", &start_char) != 1) goto exit; + if (start_char == '{') { + // a version 1 key has no version specifier. + key->exponent = 3; + } else if (start_char == 'v') { + int version; + if (fscanf(f, "%d {", &version) != 1) goto exit; + if (version == 2) { + key->exponent = 65537; + } else { + goto exit; + } + } + + if (fscanf(f, " %i , 0x%x , { %u", + &(key->len), &(key->n0inv), &(key->n[0])) != 3) { + goto exit; + } + if (key->len != RSANUMWORDS) { + LOGE("key length (%d) does not match expected size\n", key->len); + goto exit; + } + for (i = 1; i < key->len; ++i) { + if (fscanf(f, " , %u", &(key->n[i])) != 1) goto exit; + } + if (fscanf(f, " } , { %u", &(key->rr[0])) != 1) goto exit; + for (i = 1; i < key->len; ++i) { + if (fscanf(f, " , %u", &(key->rr[i])) != 1) goto exit; + } + fscanf(f, " } } "); + + // if the line ends in a comma, this file has more keys. + switch (fgetc(f)) { + case ',': + // more keys to come. + break; + + case EOF: + done = true; + break; + + default: + LOGE("unexpected character between keys\n"); + goto exit; + } + + LOGI("read key e=%d\n", key->exponent); + } + } + + fclose(f); + return out; + +exit: + if (f) fclose(f); + free(out); + *numKeys = 0; + return NULL; +} diff --git a/verifier.h b/verifier.h index 1bdfca6dd..e9ef3b722 100644 --- a/verifier.h +++ b/verifier.h @@ -24,6 +24,8 @@ */ int verify_file(const char* path, const RSAPublicKey *pKeys, unsigned int numKeys); +RSAPublicKey* load_keys(const char* filename, int* numKeys); + #define VERIFY_SUCCESS 0 #define VERIFY_FAILURE 1 diff --git a/verifier_test.cpp b/verifier_test.cpp index 01d092680..79c55783d 100644 --- a/verifier_test.cpp +++ b/verifier_test.cpp @@ -129,21 +129,26 @@ class FakeUI : public RecoveryUI { }; int main(int argc, char **argv) { - if (argc != 2 && argc != 3) { - fprintf(stderr, "Usage: %s [-f4] <package>\n", argv[0]); + if (argc < 2 || argc > 4) { + fprintf(stderr, "Usage: %s [-f4 | -file <keys>] <package>\n", argv[0]); return 2; } RSAPublicKey* key = &test_key; + int num_keys = 1; ++argv; if (strcmp(argv[0], "-f4") == 0) { ++argv; key = &test_f4_key; + } else if (strcmp(argv[0], "-file") == 0) { + ++argv; + key = load_keys(argv[0], &num_keys); + ++argv; } ui = new FakeUI(); - int result = verify_file(*argv, key, 1); + int result = verify_file(*argv, key, num_keys); if (result == VERIFY_SUCCESS) { printf("SUCCESS\n"); return 0; |