aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTao Bao2016-02-02 16:02:27 -0600
committerTao Bao2016-02-02 23:51:32 -0600
commit71e3e09ec2ac4f022e8f9213657746d8cad5dd97 (patch)
treed588a2f9f86e0eac79c9aeb2dcb1591353229272 /verifier.cpp
parent4c07a7ec0557130b95fc1f69da818e83b0887d20 (diff)
downloadplatform-bootable-recovery-71e3e09ec2ac4f022e8f9213657746d8cad5dd97.tar.gz
platform-bootable-recovery-71e3e09ec2ac4f022e8f9213657746d8cad5dd97.tar.xz
platform-bootable-recovery-71e3e09ec2ac4f022e8f9213657746d8cad5dd97.zip
recovery: Refactor verifier and verifier_test.
Move to using std::vector and std::unique_ptr to manage key certificates to stop memory leaks. Bug: 26908001 Change-Id: Ia5f799bc8dcc036a0ffae5eaa8d9f6e09abd031c
Diffstat (limited to 'verifier.cpp')
-rw-r--r--verifier.cpp265
1 files changed, 124 insertions, 141 deletions
diff --git a/verifier.cpp b/verifier.cpp
index 61e5adf0..9a2d60c6 100644
--- a/verifier.cpp
+++ b/verifier.cpp
@@ -113,7 +113,7 @@ static bool read_pkcs7(uint8_t* pkcs7_der, size_t pkcs7_der_len, uint8_t** sig_d
113// or no key matches the signature). 113// or no key matches the signature).
114 114
115int verify_file(unsigned char* addr, size_t length, 115int verify_file(unsigned char* addr, size_t length,
116 const Certificate* pKeys, unsigned int numKeys) { 116 const std::vector<Certificate>& keys) {
117 ui->SetProgress(0.0); 117 ui->SetProgress(0.0);
118 118
119 // An archive with a whole-file signature will end in six bytes: 119 // An archive with a whole-file signature will end in six bytes:
@@ -176,8 +176,7 @@ int verify_file(unsigned char* addr, size_t length,
176 return VERIFY_FAILURE; 176 return VERIFY_FAILURE;
177 } 177 }
178 178
179 size_t i; 179 for (size_t i = 4; i < eocd_size-3; ++i) {
180 for (i = 4; i < eocd_size-3; ++i) {
181 if (eocd[i ] == 0x50 && eocd[i+1] == 0x4b && 180 if (eocd[i ] == 0x50 && eocd[i+1] == 0x4b &&
182 eocd[i+2] == 0x05 && eocd[i+3] == 0x06) { 181 eocd[i+2] == 0x05 && eocd[i+3] == 0x06) {
183 // if the sequence $50 $4b $05 $06 appears anywhere after 182 // if the sequence $50 $4b $05 $06 appears anywhere after
@@ -193,8 +192,8 @@ int verify_file(unsigned char* addr, size_t length,
193 192
194 bool need_sha1 = false; 193 bool need_sha1 = false;
195 bool need_sha256 = false; 194 bool need_sha256 = false;
196 for (i = 0; i < numKeys; ++i) { 195 for (const auto& key : keys) {
197 switch (pKeys[i].hash_len) { 196 switch (key.hash_len) {
198 case SHA_DIGEST_SIZE: need_sha1 = true; break; 197 case SHA_DIGEST_SIZE: need_sha1 = true; break;
199 case SHA256_DIGEST_SIZE: need_sha256 = true; break; 198 case SHA256_DIGEST_SIZE: need_sha256 = true; break;
200 } 199 }
@@ -225,7 +224,7 @@ int verify_file(unsigned char* addr, size_t length,
225 const uint8_t* sha1 = SHA_final(&sha1_ctx); 224 const uint8_t* sha1 = SHA_final(&sha1_ctx);
226 const uint8_t* sha256 = SHA256_final(&sha256_ctx); 225 const uint8_t* sha256 = SHA256_final(&sha256_ctx);
227 226
228 uint8_t* sig_der = NULL; 227 uint8_t* sig_der = nullptr;
229 size_t sig_der_length = 0; 228 size_t sig_der_length = 0;
230 229
231 size_t signature_size = signature_start - FOOTER_SIZE; 230 size_t signature_size = signature_start - FOOTER_SIZE;
@@ -240,9 +239,10 @@ int verify_file(unsigned char* addr, size_t length,
240 * any key can match, we need to try each before determining a verification 239 * any key can match, we need to try each before determining a verification
241 * failure has happened. 240 * failure has happened.
242 */ 241 */
243 for (i = 0; i < numKeys; ++i) { 242 size_t i = 0;
243 for (const auto& key : keys) {
244 const uint8_t* hash; 244 const uint8_t* hash;
245 switch (pKeys[i].hash_len) { 245 switch (key.hash_len) {
246 case SHA_DIGEST_SIZE: hash = sha1; break; 246 case SHA_DIGEST_SIZE: hash = sha1; break;
247 case SHA256_DIGEST_SIZE: hash = sha256; break; 247 case SHA256_DIGEST_SIZE: hash = sha256; break;
248 default: continue; 248 default: continue;
@@ -250,15 +250,15 @@ int verify_file(unsigned char* addr, size_t length,
250 250
251 // The 6 bytes is the "(signature_start) $ff $ff (comment_size)" that 251 // The 6 bytes is the "(signature_start) $ff $ff (comment_size)" that
252 // the signing tool appends after the signature itself. 252 // the signing tool appends after the signature itself.
253 if (pKeys[i].key_type == Certificate::RSA) { 253 if (key.key_type == Certificate::RSA) {
254 if (sig_der_length < RSANUMBYTES) { 254 if (sig_der_length < RSANUMBYTES) {
255 // "signature" block isn't big enough to contain an RSA block. 255 // "signature" block isn't big enough to contain an RSA block.
256 LOGI("signature is too short for RSA key %zu\n", i); 256 LOGI("signature is too short for RSA key %zu\n", i);
257 continue; 257 continue;
258 } 258 }
259 259
260 if (!RSA_verify(pKeys[i].rsa, sig_der, RSANUMBYTES, 260 if (!RSA_verify(key.rsa.get(), sig_der, RSANUMBYTES,
261 hash, pKeys[i].hash_len)) { 261 hash, key.hash_len)) {
262 LOGI("failed to verify against RSA key %zu\n", i); 262 LOGI("failed to verify against RSA key %zu\n", i);
263 continue; 263 continue;
264 } 264 }
@@ -266,8 +266,8 @@ int verify_file(unsigned char* addr, size_t length,
266 LOGI("whole-file signature verified against RSA key %zu\n", i); 266 LOGI("whole-file signature verified against RSA key %zu\n", i);
267 free(sig_der); 267 free(sig_der);
268 return VERIFY_SUCCESS; 268 return VERIFY_SUCCESS;
269 } else if (pKeys[i].key_type == Certificate::EC 269 } else if (key.key_type == Certificate::EC
270 && pKeys[i].hash_len == SHA256_DIGEST_SIZE) { 270 && key.hash_len == SHA256_DIGEST_SIZE) {
271 p256_int r, s; 271 p256_int r, s;
272 if (!dsa_sig_unpack(sig_der, sig_der_length, &r, &s)) { 272 if (!dsa_sig_unpack(sig_der, sig_der_length, &r, &s)) {
273 LOGI("Not a DSA signature block for EC key %zu\n", i); 273 LOGI("Not a DSA signature block for EC key %zu\n", i);
@@ -276,7 +276,7 @@ int verify_file(unsigned char* addr, size_t length,
276 276
277 p256_int p256_hash; 277 p256_int p256_hash;
278 p256_from_bin(hash, &p256_hash); 278 p256_from_bin(hash, &p256_hash);
279 if (!p256_ecdsa_verify(&(pKeys[i].ec->x), &(pKeys[i].ec->y), 279 if (!p256_ecdsa_verify(&(key.ec->x), &(key.ec->y),
280 &p256_hash, &r, &s)) { 280 &p256_hash, &r, &s)) {
281 LOGI("failed to verify against EC key %zu\n", i); 281 LOGI("failed to verify against EC key %zu\n", i);
282 continue; 282 continue;
@@ -286,8 +286,9 @@ int verify_file(unsigned char* addr, size_t length,
286 free(sig_der); 286 free(sig_der);
287 return VERIFY_SUCCESS; 287 return VERIFY_SUCCESS;
288 } else { 288 } else {
289 LOGI("Unknown key type %d\n", pKeys[i].key_type); 289 LOGI("Unknown key type %d\n", key.key_type);
290 } 290 }
291 i++;
291 } 292 }
292 free(sig_der); 293 free(sig_der);
293 LOGE("failed to verify whole-file signature\n"); 294 LOGE("failed to verify whole-file signature\n");
@@ -323,140 +324,122 @@ int verify_file(unsigned char* addr, size_t length,
323// 4: 2048-bit RSA key with e=65537 and SHA-256 hash 324// 4: 2048-bit RSA key with e=65537 and SHA-256 hash
324// 5: 256-bit EC key using the NIST P-256 curve parameters and SHA-256 hash 325// 5: 256-bit EC key using the NIST P-256 curve parameters and SHA-256 hash
325// 326//
326// Returns NULL if the file failed to parse, or if it contain zero keys. 327// Returns true on success, and appends the found keys (at least one) to certs.
327Certificate* 328// Otherwise returns false if the file failed to parse, or if it contains zero
328load_keys(const char* filename, int* numKeys) { 329// keys. The contents in certs would be unspecified on failure.
329 Certificate* out = NULL; 330bool load_keys(const char* filename, std::vector<Certificate>& certs) {
330 *numKeys = 0; 331 std::unique_ptr<FILE, decltype(&fclose)> f(fopen(filename, "r"), fclose);
331 332 if (!f) {
332 FILE* f = fopen(filename, "r");
333 if (f == NULL) {
334 LOGE("opening %s: %s\n", filename, strerror(errno)); 333 LOGE("opening %s: %s\n", filename, strerror(errno));
335 goto exit; 334 return false;
336 } 335 }
337 336
338 { 337 while (true) {
339 int i; 338 certs.emplace_back(0, Certificate::RSA, nullptr, nullptr);
340 bool done = false; 339 Certificate& cert = certs.back();
341 while (!done) { 340
342 ++*numKeys; 341 char start_char;
343 out = (Certificate*)realloc(out, *numKeys * sizeof(Certificate)); 342 if (fscanf(f.get(), " %c", &start_char) != 1) return false;
344 Certificate* cert = out + (*numKeys - 1); 343 if (start_char == '{') {
345 memset(cert, '\0', sizeof(Certificate)); 344 // a version 1 key has no version specifier.
346 345 cert.key_type = Certificate::RSA;
347 char start_char; 346 cert.rsa = std::unique_ptr<RSAPublicKey>(new RSAPublicKey);
348 if (fscanf(f, " %c", &start_char) != 1) goto exit; 347 cert.rsa->exponent = 3;
349 if (start_char == '{') { 348 cert.hash_len = SHA_DIGEST_SIZE;
350 // a version 1 key has no version specifier. 349 } else if (start_char == 'v') {
351 cert->key_type = Certificate::RSA; 350 int version;
352 cert->rsa = (RSAPublicKey*)malloc(sizeof(RSAPublicKey)); 351 if (fscanf(f.get(), "%d {", &version) != 1) return false;
353 cert->rsa->exponent = 3; 352 switch (version) {
354 cert->hash_len = SHA_DIGEST_SIZE; 353 case 2:
355 } else if (start_char == 'v') { 354 cert.key_type = Certificate::RSA;
356 int version; 355 cert.rsa = std::unique_ptr<RSAPublicKey>(new RSAPublicKey);
357 if (fscanf(f, "%d {", &version) != 1) goto exit; 356 cert.rsa->exponent = 65537;
358 switch (version) { 357 cert.hash_len = SHA_DIGEST_SIZE;
359 case 2: 358 break;
360 cert->key_type = Certificate::RSA; 359 case 3:
361 cert->rsa = (RSAPublicKey*)malloc(sizeof(RSAPublicKey)); 360 cert.key_type = Certificate::RSA;
362 cert->rsa->exponent = 65537; 361 cert.rsa = std::unique_ptr<RSAPublicKey>(new RSAPublicKey);
363 cert->hash_len = SHA_DIGEST_SIZE; 362 cert.rsa->exponent = 3;
364 break; 363 cert.hash_len = SHA256_DIGEST_SIZE;
365 case 3: 364 break;
366 cert->key_type = Certificate::RSA; 365 case 4:
367 cert->rsa = (RSAPublicKey*)malloc(sizeof(RSAPublicKey)); 366 cert.key_type = Certificate::RSA;
368 cert->rsa->exponent = 3; 367 cert.rsa = std::unique_ptr<RSAPublicKey>(new RSAPublicKey);
369 cert->hash_len = SHA256_DIGEST_SIZE; 368 cert.rsa->exponent = 65537;
370 break; 369 cert.hash_len = SHA256_DIGEST_SIZE;
371 case 4: 370 break;
372 cert->key_type = Certificate::RSA; 371 case 5:
373 cert->rsa = (RSAPublicKey*)malloc(sizeof(RSAPublicKey)); 372 cert.key_type = Certificate::EC;
374 cert->rsa->exponent = 65537; 373 cert.ec = std::unique_ptr<ECPublicKey>(new ECPublicKey);
375 cert->hash_len = SHA256_DIGEST_SIZE; 374 cert.hash_len = SHA256_DIGEST_SIZE;
376 break; 375 break;
377 case 5: 376 default:
378 cert->key_type = Certificate::EC; 377 return false;
379 cert->ec = (ECPublicKey*)calloc(1, sizeof(ECPublicKey));
380 cert->hash_len = SHA256_DIGEST_SIZE;
381 break;
382 default:
383 goto exit;
384 }
385 } 378 }
379 }
386 380
387 if (cert->key_type == Certificate::RSA) { 381 if (cert.key_type == Certificate::RSA) {
388 RSAPublicKey* key = cert->rsa; 382 RSAPublicKey* key = cert.rsa.get();
389 if (fscanf(f, " %i , 0x%x , { %u", 383 if (fscanf(f.get(), " %i , 0x%x , { %u", &(key->len), &(key->n0inv),
390 &(key->len), &(key->n0inv), &(key->n[0])) != 3) { 384 &(key->n[0])) != 3) {
391 goto exit; 385 return false;
392 }
393 if (key->len != RSANUMWORDS) {
394 LOGE("key length (%d) does not match expected size\n", key->len);
395 goto exit;
396 }
397 for (i = 1; i < key->len; ++i) {
398 if (fscanf(f, " , %u", &(key->n[i])) != 1) goto exit;
399 }
400 if (fscanf(f, " } , { %u", &(key->rr[0])) != 1) goto exit;
401 for (i = 1; i < key->len; ++i) {
402 if (fscanf(f, " , %u", &(key->rr[i])) != 1) goto exit;
403 }
404 fscanf(f, " } } ");
405
406 LOGI("read key e=%d hash=%d\n", key->exponent, cert->hash_len);
407 } else if (cert->key_type == Certificate::EC) {
408 ECPublicKey* key = cert->ec;
409 int key_len;
410 unsigned int byte;
411 uint8_t x_bytes[P256_NBYTES];
412 uint8_t y_bytes[P256_NBYTES];
413 if (fscanf(f, " %i , { %u", &key_len, &byte) != 2) goto exit;
414 if (key_len != P256_NBYTES) {
415 LOGE("Key length (%d) does not match expected size %d\n", key_len, P256_NBYTES);
416 goto exit;
417 }
418 x_bytes[P256_NBYTES - 1] = byte;
419 for (i = P256_NBYTES - 2; i >= 0; --i) {
420 if (fscanf(f, " , %u", &byte) != 1) goto exit;
421 x_bytes[i] = byte;
422 }
423 if (fscanf(f, " } , { %u", &byte) != 1) goto exit;
424 y_bytes[P256_NBYTES - 1] = byte;
425 for (i = P256_NBYTES - 2; i >= 0; --i) {
426 if (fscanf(f, " , %u", &byte) != 1) goto exit;
427 y_bytes[i] = byte;
428 }
429 fscanf(f, " } } ");
430 p256_from_bin(x_bytes, &key->x);
431 p256_from_bin(y_bytes, &key->y);
432 } else {
433 LOGE("Unknown key type %d\n", cert->key_type);
434 goto exit;
435 } 386 }
436 387 if (key->len != RSANUMWORDS) {
437 // if the line ends in a comma, this file has more keys. 388 LOGE("key length (%d) does not match expected size\n", key->len);
438 switch (fgetc(f)) { 389 return false;
439 case ',': 390 }
440 // more keys to come. 391 for (int i = 1; i < key->len; ++i) {
441 break; 392 if (fscanf(f.get(), " , %u", &(key->n[i])) != 1) return false;
442 393 }
443 case EOF: 394 if (fscanf(f.get(), " } , { %u", &(key->rr[0])) != 1) return false;
444 done = true; 395 for (int i = 1; i < key->len; ++i) {
445 break; 396 if (fscanf(f.get(), " , %u", &(key->rr[i])) != 1) return false;
446 397 }
447 default: 398 fscanf(f.get(), " } } ");
448 LOGE("unexpected character between keys\n"); 399
449 goto exit; 400 LOGI("read key e=%d hash=%d\n", key->exponent, cert.hash_len);
401 } else if (cert.key_type == Certificate::EC) {
402 ECPublicKey* key = cert.ec.get();
403 int key_len;
404 unsigned int byte;
405 uint8_t x_bytes[P256_NBYTES];
406 uint8_t y_bytes[P256_NBYTES];
407 if (fscanf(f.get(), " %i , { %u", &key_len, &byte) != 2) return false;
408 if (key_len != P256_NBYTES) {
409 LOGE("Key length (%d) does not match expected size %d\n", key_len, P256_NBYTES);
410 return false;
411 }
412 x_bytes[P256_NBYTES - 1] = byte;
413 for (int i = P256_NBYTES - 2; i >= 0; --i) {
414 if (fscanf(f.get(), " , %u", &byte) != 1) return false;
415 x_bytes[i] = byte;
416 }
417 if (fscanf(f.get(), " } , { %u", &byte) != 1) return false;
418 y_bytes[P256_NBYTES - 1] = byte;
419 for (int i = P256_NBYTES - 2; i >= 0; --i) {
420 if (fscanf(f.get(), " , %u", &byte) != 1) return false;
421 y_bytes[i] = byte;
450 } 422 }
423 fscanf(f.get(), " } } ");
424 p256_from_bin(x_bytes, &key->x);
425 p256_from_bin(y_bytes, &key->y);
426 } else {
427 LOGE("Unknown key type %d\n", cert.key_type);
428 return false;
451 } 429 }
452 }
453 430
454 fclose(f); 431 // if the line ends in a comma, this file has more keys.
455 return out; 432 int ch = fgetc(f.get());
433 if (ch == ',') {
434 // more keys to come.
435 continue;
436 } else if (ch == EOF) {
437 break;
438 } else {
439 LOGE("unexpected character between keys\n");
440 return false;
441 }
442 }
456 443
457exit: 444 return true;
458 if (f) fclose(f);
459 free(out);
460 *numKeys = 0;
461 return NULL;
462} 445}