summaryrefslogtreecommitdiffstats
path: root/install.c
diff options
context:
space:
mode:
Diffstat (limited to 'install.c')
-rw-r--r--install.c96
1 files changed, 88 insertions, 8 deletions
diff --git a/install.c b/install.c
index 069112080..4dcfe7536 100644
--- a/install.c
+++ b/install.c
@@ -31,12 +31,8 @@
#include "roots.h"
#include "verifier.h"
-/* List of public keys */
-static const RSAPublicKey keys[] = {
-#include "keys.inc"
-};
-
#define ASSUMED_UPDATE_SCRIPT_NAME "META-INF/com/google/android/update-script"
+#define PUBLIC_KEYS_FILE "/res/keys"
static const ZipEntry *
find_update_script(ZipArchive *zip)
@@ -114,7 +110,8 @@ handle_update_script(ZipArchive *zip, const ZipEntry *update_script_entry)
}
static int
-handle_update_package(const char *path, ZipArchive *zip)
+handle_update_package(const char *path, ZipArchive *zip,
+ const RSAPublicKey *keys, int numKeys)
{
// Give verification half the progress bar...
ui_print("Verifying update package...\n");
@@ -122,7 +119,7 @@ handle_update_package(const char *path, ZipArchive *zip)
VERIFICATION_PROGRESS_FRACTION,
VERIFICATION_PROGRESS_TIME);
- if (!verify_jar_signature(zip, keys, sizeof(keys) / sizeof(keys[0]))) {
+ if (!verify_jar_signature(zip, keys, numKeys)) {
LOGE("Verification failed\n");
return INSTALL_CORRUPT;
}
@@ -147,6 +144,80 @@ handle_update_package(const char *path, ZipArchive *zip)
return ret;
}
+// 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}}"
+//
+// (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 = realloc(out, *numKeys * sizeof(RSAPublicKey));
+ RSAPublicKey* key = out + (*numKeys - 1);
+ if (fscanf(f, " { %i , %i , { %i",
+ &(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, " , %i", &(key->n[i])) != 1) goto exit;
+ }
+ if (fscanf(f, " } , { %i", &(key->rr[0])) != 1) goto exit;
+ for (i = 1; i < key->len; ++i) {
+ if (fscanf(f, " , %i", &(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;
+ }
+ }
+
+ fclose(f);
+ return out;
+
+exit:
+ if (f) fclose(f);
+ free(out);
+ *numKeys = 0;
+ return NULL;
+}
+
int
install_package(const char *root_path)
{
@@ -169,6 +240,14 @@ install_package(const char *root_path)
ui_print("Opening update package...\n");
LOGI("Update file path: %s\n", path);
+ int numKeys;
+ RSAPublicKey* loadedKeys = load_keys(PUBLIC_KEYS_FILE, &numKeys);
+ if (loadedKeys == NULL) {
+ LOGE("Failed to load keys\n");
+ return INSTALL_CORRUPT;
+ }
+ LOGI("%d key(s) loaded from %s\n", numKeys, PUBLIC_KEYS_FILE);
+
/* Try to open the package.
*/
ZipArchive zip;
@@ -180,7 +259,8 @@ install_package(const char *root_path)
/* Verify and install the contents of the package.
*/
- int status = handle_update_package(path, &zip);
+ int status = handle_update_package(path, &zip, loadedKeys, numKeys);
mzCloseZipArchive(&zip);
+ free(loadedKeys);
return status;
}