diff options
author | Doug Zongker | 2013-04-10 13:32:17 -0500 |
---|---|---|
committer | Kenny Root | 2013-09-25 12:11:46 -0500 |
commit | 30362a6ad132cbafde82cc57293e00679d4f86c2 (patch) | |
tree | 47f9585d4cd72de8a3fb935d8e8387763ce3a9b1 /verifier.cpp | |
parent | 5c4e1dac0bd8f31559bd50eec4343b7a17b7a976 (diff) | |
download | platform-bootable-recovery-30362a6ad132cbafde82cc57293e00679d4f86c2.tar.gz platform-bootable-recovery-30362a6ad132cbafde82cc57293e00679d4f86c2.tar.xz platform-bootable-recovery-30362a6ad132cbafde82cc57293e00679d4f86c2.zip |
verifier: update to support certificates using SHA-256
(cherry picked from commit bac7fba02763ae5e78e8e4ba0bea727330ad953e)
Change-Id: I01c38d7fea088622a8b0bbf2c833fa2d969417af
Diffstat (limited to 'verifier.cpp')
-rw-r--r-- | verifier.cpp | 80 |
1 files changed, 63 insertions, 17 deletions
diff --git a/verifier.cpp b/verifier.cpp index 5f4c981e..782a8386 100644 --- a/verifier.cpp +++ b/verifier.cpp | |||
@@ -20,6 +20,7 @@ | |||
20 | 20 | ||
21 | #include "mincrypt/rsa.h" | 21 | #include "mincrypt/rsa.h" |
22 | #include "mincrypt/sha.h" | 22 | #include "mincrypt/sha.h" |
23 | #include "mincrypt/sha256.h" | ||
23 | 24 | ||
24 | #include <string.h> | 25 | #include <string.h> |
25 | #include <stdio.h> | 26 | #include <stdio.h> |
@@ -34,7 +35,7 @@ extern RecoveryUI* ui; | |||
34 | // Return VERIFY_SUCCESS, VERIFY_FAILURE (if any error is encountered | 35 | // Return VERIFY_SUCCESS, VERIFY_FAILURE (if any error is encountered |
35 | // or no key matches the signature). | 36 | // or no key matches the signature). |
36 | 37 | ||
37 | int verify_file(const char* path, const RSAPublicKey *pKeys, unsigned int numKeys) { | 38 | int verify_file(const char* path, const Certificate* pKeys, unsigned int numKeys) { |
38 | ui->SetProgress(0.0); | 39 | ui->SetProgress(0.0); |
39 | 40 | ||
40 | FILE* f = fopen(path, "rb"); | 41 | FILE* f = fopen(path, "rb"); |
@@ -68,6 +69,7 @@ int verify_file(const char* path, const RSAPublicKey *pKeys, unsigned int numKey | |||
68 | } | 69 | } |
69 | 70 | ||
70 | if (footer[2] != 0xff || footer[3] != 0xff) { | 71 | if (footer[2] != 0xff || footer[3] != 0xff) { |
72 | LOGE("footer is wrong\n"); | ||
71 | fclose(f); | 73 | fclose(f); |
72 | return VERIFY_FAILURE; | 74 | return VERIFY_FAILURE; |
73 | } | 75 | } |
@@ -139,8 +141,19 @@ int verify_file(const char* path, const RSAPublicKey *pKeys, unsigned int numKey | |||
139 | 141 | ||
140 | #define BUFFER_SIZE 4096 | 142 | #define BUFFER_SIZE 4096 |
141 | 143 | ||
142 | SHA_CTX ctx; | 144 | bool need_sha1 = false; |
143 | SHA_init(&ctx); | 145 | bool need_sha256 = false; |
146 | for (i = 0; i < numKeys; ++i) { | ||
147 | switch (pKeys[i].hash_len) { | ||
148 | case SHA_DIGEST_SIZE: need_sha1 = true; break; | ||
149 | case SHA256_DIGEST_SIZE: need_sha256 = true; break; | ||
150 | } | ||
151 | } | ||
152 | |||
153 | SHA_CTX sha1_ctx; | ||
154 | SHA256_CTX sha256_ctx; | ||
155 | SHA_init(&sha1_ctx); | ||
156 | SHA256_init(&sha256_ctx); | ||
144 | unsigned char* buffer = (unsigned char*)malloc(BUFFER_SIZE); | 157 | unsigned char* buffer = (unsigned char*)malloc(BUFFER_SIZE); |
145 | if (buffer == NULL) { | 158 | if (buffer == NULL) { |
146 | LOGE("failed to alloc memory for sha1 buffer\n"); | 159 | LOGE("failed to alloc memory for sha1 buffer\n"); |
@@ -159,7 +172,8 @@ int verify_file(const char* path, const RSAPublicKey *pKeys, unsigned int numKey | |||
159 | fclose(f); | 172 | fclose(f); |
160 | return VERIFY_FAILURE; | 173 | return VERIFY_FAILURE; |
161 | } | 174 | } |
162 | SHA_update(&ctx, buffer, size); | 175 | if (need_sha1) SHA_update(&sha1_ctx, buffer, size); |
176 | if (need_sha256) SHA256_update(&sha256_ctx, buffer, size); | ||
163 | so_far += size; | 177 | so_far += size; |
164 | double f = so_far / (double)signed_len; | 178 | double f = so_far / (double)signed_len; |
165 | if (f > frac + 0.02 || size == so_far) { | 179 | if (f > frac + 0.02 || size == so_far) { |
@@ -170,12 +184,21 @@ int verify_file(const char* path, const RSAPublicKey *pKeys, unsigned int numKey | |||
170 | fclose(f); | 184 | fclose(f); |
171 | free(buffer); | 185 | free(buffer); |
172 | 186 | ||
173 | const uint8_t* sha1 = SHA_final(&ctx); | 187 | const uint8_t* sha1 = SHA_final(&sha1_ctx); |
188 | const uint8_t* sha256 = SHA256_final(&sha256_ctx); | ||
189 | |||
174 | for (i = 0; i < numKeys; ++i) { | 190 | for (i = 0; i < numKeys; ++i) { |
191 | const uint8_t* hash; | ||
192 | switch (pKeys[i].hash_len) { | ||
193 | case SHA_DIGEST_SIZE: hash = sha1; break; | ||
194 | case SHA256_DIGEST_SIZE: hash = sha256; break; | ||
195 | default: continue; | ||
196 | } | ||
197 | |||
175 | // The 6 bytes is the "(signature_start) $ff $ff (comment_size)" that | 198 | // The 6 bytes is the "(signature_start) $ff $ff (comment_size)" that |
176 | // the signing tool appends after the signature itself. | 199 | // the signing tool appends after the signature itself. |
177 | if (RSA_verify(pKeys+i, eocd + eocd_size - 6 - RSANUMBYTES, | 200 | if (RSA_verify(pKeys[i].public_key, eocd + eocd_size - 6 - RSANUMBYTES, |
178 | RSANUMBYTES, sha1)) { | 201 | RSANUMBYTES, hash, pKeys[i].hash_len)) { |
179 | LOGI("whole-file signature verified against key %d\n", i); | 202 | LOGI("whole-file signature verified against key %d\n", i); |
180 | free(eocd); | 203 | free(eocd); |
181 | return VERIFY_SUCCESS; | 204 | return VERIFY_SUCCESS; |
@@ -207,10 +230,19 @@ int verify_file(const char* path, const RSAPublicKey *pKeys, unsigned int numKey | |||
207 | // The file may contain multiple keys in this format, separated by | 230 | // The file may contain multiple keys in this format, separated by |
208 | // commas. The last key must not be followed by a comma. | 231 | // commas. The last key must not be followed by a comma. |
209 | // | 232 | // |
233 | // A Certificate is a pair of an RSAPublicKey and a particular hash | ||
234 | // (we support SHA-1 and SHA-256; we store the hash length to signify | ||
235 | // which is being used). The hash used is implied by the version number. | ||
236 | // | ||
237 | // 1: 2048-bit RSA key with e=3 and SHA-1 hash | ||
238 | // 2: 2048-bit RSA key with e=65537 and SHA-1 hash | ||
239 | // 3: 2048-bit RSA key with e=3 and SHA-256 hash | ||
240 | // 4: 2048-bit RSA key with e=65537 and SHA-256 hash | ||
241 | // | ||
210 | // Returns NULL if the file failed to parse, or if it contain zero keys. | 242 | // Returns NULL if the file failed to parse, or if it contain zero keys. |
211 | RSAPublicKey* | 243 | Certificate* |
212 | load_keys(const char* filename, int* numKeys) { | 244 | load_keys(const char* filename, int* numKeys) { |
213 | RSAPublicKey* out = NULL; | 245 | Certificate* out = NULL; |
214 | *numKeys = 0; | 246 | *numKeys = 0; |
215 | 247 | ||
216 | FILE* f = fopen(filename, "r"); | 248 | FILE* f = fopen(filename, "r"); |
@@ -224,24 +256,38 @@ load_keys(const char* filename, int* numKeys) { | |||
224 | bool done = false; | 256 | bool done = false; |
225 | while (!done) { | 257 | while (!done) { |
226 | ++*numKeys; | 258 | ++*numKeys; |
227 | out = (RSAPublicKey*)realloc(out, *numKeys * sizeof(RSAPublicKey)); | 259 | out = (Certificate*)realloc(out, *numKeys * sizeof(Certificate)); |
228 | RSAPublicKey* key = out + (*numKeys - 1); | 260 | Certificate* cert = out + (*numKeys - 1); |
261 | cert->public_key = (RSAPublicKey*)malloc(sizeof(RSAPublicKey)); | ||
229 | 262 | ||
230 | char start_char; | 263 | char start_char; |
231 | if (fscanf(f, " %c", &start_char) != 1) goto exit; | 264 | if (fscanf(f, " %c", &start_char) != 1) goto exit; |
232 | if (start_char == '{') { | 265 | if (start_char == '{') { |
233 | // a version 1 key has no version specifier. | 266 | // a version 1 key has no version specifier. |
234 | key->exponent = 3; | 267 | cert->public_key->exponent = 3; |
268 | cert->hash_len = SHA_DIGEST_SIZE; | ||
235 | } else if (start_char == 'v') { | 269 | } else if (start_char == 'v') { |
236 | int version; | 270 | int version; |
237 | if (fscanf(f, "%d {", &version) != 1) goto exit; | 271 | if (fscanf(f, "%d {", &version) != 1) goto exit; |
238 | if (version == 2) { | 272 | switch (version) { |
239 | key->exponent = 65537; | 273 | case 2: |
240 | } else { | 274 | cert->public_key->exponent = 65537; |
241 | goto exit; | 275 | cert->hash_len = SHA_DIGEST_SIZE; |
276 | break; | ||
277 | case 3: | ||
278 | cert->public_key->exponent = 3; | ||
279 | cert->hash_len = SHA256_DIGEST_SIZE; | ||
280 | break; | ||
281 | case 4: | ||
282 | cert->public_key->exponent = 65537; | ||
283 | cert->hash_len = SHA256_DIGEST_SIZE; | ||
284 | break; | ||
285 | default: | ||
286 | goto exit; | ||
242 | } | 287 | } |
243 | } | 288 | } |
244 | 289 | ||
290 | RSAPublicKey* key = cert->public_key; | ||
245 | if (fscanf(f, " %i , 0x%x , { %u", | 291 | if (fscanf(f, " %i , 0x%x , { %u", |
246 | &(key->len), &(key->n0inv), &(key->n[0])) != 3) { | 292 | &(key->len), &(key->n0inv), &(key->n[0])) != 3) { |
247 | goto exit; | 293 | goto exit; |
@@ -274,7 +320,7 @@ load_keys(const char* filename, int* numKeys) { | |||
274 | goto exit; | 320 | goto exit; |
275 | } | 321 | } |
276 | 322 | ||
277 | LOGI("read key e=%d\n", key->exponent); | 323 | LOGI("read key e=%d hash=%d\n", key->exponent, cert->hash_len); |
278 | } | 324 | } |
279 | } | 325 | } |
280 | 326 | ||