1 /* 2 * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) 3 * All rights reserved. 4 * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted 5 * their moral rights under the UK Copyright Design and Patents Act 1988 to 6 * be recorded as the authors of this copyright work. 7 * 8 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 9 * use this file except in compliance with the License. 10 * 11 * You may obtain a copy of the License at 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * 18 * See the License for the specific language governing permissions and 19 * limitations under the License. 20 */ 21 #include "config.h" 22 23 #include "packet-parse.h" 24 #include "packet-show.h" 25 #include "keyring.h" 26 #include "signature.h" 27 #include "netpgpsdk.h" 28 29 #include "readerwriter.h" 30 #include "netpgpdefs.h" 31 #include "memory.h" 32 #include "keyring_local.h" 33 #include "parse_local.h" 34 #include "validate.h" 35 36 #ifdef HAVE_ASSERT_H 37 #include <assert.h> 38 #endif 39 40 #include <string.h> 41 42 43 /* Does the signed hash match the given hash? */ 44 static bool 45 check_binary_signature(const unsigned len, 46 const unsigned char *data, 47 const __ops_signature_t * sig, 48 const __ops_public_key_t * signer __attribute__((unused))) 49 { 50 unsigned char hashout[OPS_MAX_HASH_SIZE]; 51 unsigned char trailer[6]; 52 unsigned int hashedlen; 53 __ops_hash_t hash; 54 unsigned n = 0; 55 56 __ops_hash_any(&hash, sig->info.hash_algorithm); 57 hash.init(&hash); 58 hash.add(&hash, data, len); 59 switch (sig->info.version) { 60 case OPS_V3: 61 trailer[0] = sig->info.type; 62 trailer[1] = (unsigned)(sig->info.creation_time) >> 24; 63 trailer[2] = (unsigned)(sig->info.creation_time) >> 16; 64 trailer[3] = (unsigned)(sig->info.creation_time) >> 8; 65 trailer[4] = (unsigned char)(sig->info.creation_time); 66 hash.add(&hash, &trailer[0], 5); 67 break; 68 69 case OPS_V4: 70 hash.add(&hash, sig->info.v4_hashed_data, 71 sig->info.v4_hashed_data_length); 72 trailer[0] = 0x04; /* version */ 73 trailer[1] = 0xFF; 74 hashedlen = sig->info.v4_hashed_data_length; 75 trailer[2] = hashedlen >> 24; 76 trailer[3] = hashedlen >> 16; 77 trailer[4] = hashedlen >> 8; 78 trailer[5] = hashedlen; 79 hash.add(&hash, &trailer[0], 6); 80 break; 81 82 default: 83 fprintf(stderr, "Invalid signature version %d\n", 84 sig->info.version); 85 return false; 86 } 87 88 n = hash.finish(&hash, hashout); 89 if (__ops_get_debug_level(__FILE__)) { 90 printf("check_binary_signature: hash length %" PRIsize "u\n", 91 hash.size); 92 } 93 return __ops_check_signature(hashout, n, sig, signer); 94 } 95 96 static int 97 keydata_reader(void *dest, size_t length, __ops_error_t ** errors, 98 __ops_reader_info_t * rinfo, 99 __ops_parse_cb_info_t * cbinfo) 100 { 101 validate_reader_t *reader = __ops_reader_get_arg(rinfo); 102 103 OPS_USED(errors); 104 OPS_USED(cbinfo); 105 if (reader->offset == reader->key->packets[reader->packet].length) { 106 ++reader->packet; 107 reader->offset = 0; 108 } 109 if (reader->packet == reader->key->npackets) 110 return 0; 111 112 /* 113 * we should never be asked to cross a packet boundary in a single 114 * read 115 */ 116 assert(reader->key->packets[reader->packet].length >= 117 reader->offset + length); 118 119 (void) memcpy(dest, 120 &reader->key->packets[reader->packet].raw[reader->offset], 121 length); 122 reader->offset += length; 123 124 return length; 125 } 126 127 static void 128 free_signature_info(__ops_signature_info_t * sig) 129 { 130 free(sig->v4_hashed_data); 131 free(sig); 132 } 133 134 static void 135 copy_signature_info(__ops_signature_info_t * dst, 136 const __ops_signature_info_t * src) 137 { 138 (void) memcpy(dst, src, sizeof(*src)); 139 dst->v4_hashed_data = calloc(1, src->v4_hashed_data_length); 140 (void) memcpy(dst->v4_hashed_data, src->v4_hashed_data, 141 src->v4_hashed_data_length); 142 } 143 144 static void 145 add_sig_to_list(const __ops_signature_info_t *sig, 146 __ops_signature_info_t **sigs, 147 unsigned *count) 148 { 149 if (*count == 0) { 150 *sigs = calloc(*count + 1, sizeof(__ops_signature_info_t)); 151 } else { 152 *sigs = realloc(*sigs, 153 (*count + 1) * sizeof(__ops_signature_info_t)); 154 } 155 copy_signature_info(&(*sigs)[*count], sig); 156 *count += 1; 157 } 158 159 160 __ops_parse_cb_return_t 161 __ops_validate_key_cb(const __ops_parser_content_t * contents, 162 __ops_parse_cb_info_t * cbinfo) 163 { 164 const __ops_parser_content_union_t *content = &contents->u; 165 const __ops_keydata_t *signer; 166 validate_key_cb_t *key = __ops_parse_cb_get_arg(cbinfo); 167 __ops_error_t **errors = __ops_parse_cb_get_errors(cbinfo); 168 bool valid = false; 169 170 if (__ops_get_debug_level(__FILE__)) { 171 printf("%s\n", __ops_show_packet_tag(contents->tag)); 172 } 173 174 switch (contents->tag) { 175 case OPS_PTAG_CT_PUBLIC_KEY: 176 assert(key->pkey.version == 0); 177 key->pkey = content->public_key; 178 return OPS_KEEP_MEMORY; 179 180 case OPS_PTAG_CT_PUBLIC_SUBKEY: 181 if (key->subkey.version) 182 __ops_public_key_free(&key->subkey); 183 key->subkey = content->public_key; 184 return OPS_KEEP_MEMORY; 185 186 case OPS_PTAG_CT_SECRET_KEY: 187 key->skey = content->secret_key; 188 key->pkey = key->skey.public_key; 189 return OPS_KEEP_MEMORY; 190 191 case OPS_PTAG_CT_USER_ID: 192 if (key->user_id.user_id) 193 __ops_user_id_free(&key->user_id); 194 key->user_id = content->user_id; 195 key->last_seen = ID; 196 return OPS_KEEP_MEMORY; 197 198 case OPS_PTAG_CT_USER_ATTRIBUTE: 199 assert(content->user_attribute.data.len); 200 printf("user attribute, length=%d\n", 201 (int) content->user_attribute.data.len); 202 if (key->user_attribute.data.len) 203 __ops_user_attribute_free(&key->user_attribute); 204 key->user_attribute = content->user_attribute; 205 key->last_seen = ATTRIBUTE; 206 return OPS_KEEP_MEMORY; 207 208 case OPS_PTAG_CT_SIGNATURE: /* V3 sigs */ 209 case OPS_PTAG_CT_SIGNATURE_FOOTER: /* V4 sigs */ 210 211 signer = __ops_keyring_find_key_by_id(key->keyring, 212 content->signature.info.signer_id); 213 if (!signer) { 214 add_sig_to_list(&content->signature.info, 215 &key->result->unknown_sigs, 216 &key->result->unknownc); 217 break; 218 } 219 switch (content->signature.info.type) { 220 case OPS_CERT_GENERIC: 221 case OPS_CERT_PERSONA: 222 case OPS_CERT_CASUAL: 223 case OPS_CERT_POSITIVE: 224 case OPS_SIG_REV_CERT: 225 if (key->last_seen == ID) 226 valid = __ops_check_user_id_certification_signature(&key->pkey, 227 &key->user_id, 228 &content->signature, 229 __ops_get_public_key_from_data(signer), 230 key->rarg->key->packets[key->rarg->packet].raw); 231 else 232 valid = __ops_check_user_attribute_certification_signature(&key->pkey, 233 &key->user_attribute, 234 &content->signature, 235 __ops_get_public_key_from_data(signer), 236 key->rarg->key->packets[key->rarg->packet].raw); 237 238 break; 239 240 case OPS_SIG_SUBKEY: 241 /* 242 * XXX: we should also check that the signer is the 243 * key we are validating, I think. 244 */ 245 valid = __ops_check_subkey_signature(&key->pkey, &key->subkey, 246 &content->signature, 247 __ops_get_public_key_from_data(signer), 248 key->rarg->key->packets[key->rarg->packet].raw); 249 break; 250 251 case OPS_SIG_DIRECT: 252 valid = __ops_check_direct_signature(&key->pkey, &content->signature, 253 __ops_get_public_key_from_data(signer), 254 key->rarg->key->packets[key->rarg->packet].raw); 255 break; 256 257 case OPS_SIG_STANDALONE: 258 case OPS_SIG_PRIMARY: 259 case OPS_SIG_REV_KEY: 260 case OPS_SIG_REV_SUBKEY: 261 case OPS_SIG_TIMESTAMP: 262 case OPS_SIG_3RD_PARTY: 263 OPS_ERROR_1(errors, OPS_E_UNIMPLEMENTED, 264 "Verification of signature type 0x%02x not yet implemented\n", content->signature.info.type); 265 break; 266 267 default: 268 OPS_ERROR_1(errors, OPS_E_UNIMPLEMENTED, 269 "Unexpected signature type 0x%02x\n", 270 content->signature.info.type); 271 } 272 273 if (valid) { 274 add_sig_to_list(&content->signature.info, 275 &key->result->valid_sigs, 276 &key->result->validc); 277 } else { 278 OPS_ERROR(errors, OPS_E_V_BAD_SIGNATURE, "Bad Sig"); 279 add_sig_to_list(&content->signature.info, 280 &key->result->invalid_sigs, 281 &key->result->invalidc); 282 } 283 break; 284 285 /* ignore these */ 286 case OPS_PARSER_PTAG: 287 case OPS_PTAG_CT_SIGNATURE_HEADER: 288 case OPS_PARSER_PACKET_END: 289 break; 290 291 case OPS_PARSER_CMD_GET_SK_PASSPHRASE: 292 if (key->cb_get_passphrase) { 293 return key->cb_get_passphrase(contents, cbinfo); 294 } 295 break; 296 297 default: 298 fprintf(stderr, "unexpected tag=0x%x\n", contents->tag); 299 assert(/* CONSTCOND */0); 300 break; 301 } 302 return OPS_RELEASE_MEMORY; 303 } 304 305 __ops_parse_cb_return_t 306 validate_data_cb(const __ops_parser_content_t * contents, 307 __ops_parse_cb_info_t * cbinfo) 308 { 309 const __ops_parser_content_union_t *content = &contents->u; 310 const __ops_keydata_t *signer; 311 validate_data_cb_t *data = __ops_parse_cb_get_arg(cbinfo); 312 __ops_error_t **errors = __ops_parse_cb_get_errors(cbinfo); 313 bool valid = false; 314 315 if (__ops_get_debug_level(__FILE__)) { 316 printf("validate_data_cb: %s\n", 317 __ops_show_packet_tag(contents->tag)); 318 } 319 switch (contents->tag) { 320 case OPS_PTAG_CT_SIGNED_CLEARTEXT_HEADER: 321 /* 322 * ignore - this gives us the "Armor Header" line "Hash: 323 * SHA1" or similar 324 */ 325 break; 326 327 case OPS_PTAG_CT_LITERAL_DATA_HEADER: 328 /* ignore */ 329 break; 330 331 case OPS_PTAG_CT_LITERAL_DATA_BODY: 332 data->data.literal_data_body = content->literal_data_body; 333 data->use = LITERAL_DATA; 334 __ops_memory_add(data->mem, data->data.literal_data_body.data, 335 data->data.literal_data_body.length); 336 return OPS_KEEP_MEMORY; 337 338 case OPS_PTAG_CT_SIGNED_CLEARTEXT_BODY: 339 data->data.signed_cleartext_body = content->signed_cleartext_body; 340 data->use = SIGNED_CLEARTEXT; 341 __ops_memory_add(data->mem, data->data.literal_data_body.data, 342 data->data.literal_data_body.length); 343 return OPS_KEEP_MEMORY; 344 345 case OPS_PTAG_CT_SIGNED_CLEARTEXT_TRAILER: 346 /* this gives us an __ops_hash_t struct */ 347 break; 348 349 case OPS_PTAG_CT_SIGNATURE: /* V3 sigs */ 350 case OPS_PTAG_CT_SIGNATURE_FOOTER: /* V4 sigs */ 351 if (__ops_get_debug_level(__FILE__)) { 352 unsigned i = 0; 353 354 printf("\n*** hashed data:\n"); 355 for (i = 0; 356 i < content->signature.info.v4_hashed_data_length; 357 i++) { 358 printf("0x%02x ", 359 content->signature.info.v4_hashed_data[i]); 360 } 361 printf("\n"); 362 printf(" type=%02x signer_id=", 363 content->signature.info.type); 364 hexdump(content->signature.info.signer_id, 365 sizeof(content->signature.info.signer_id), ""); 366 printf("\n"); 367 } 368 signer = __ops_keyring_find_key_by_id(data->keyring, 369 content->signature.info.signer_id); 370 if (!signer) { 371 OPS_ERROR(errors, OPS_E_V_UNKNOWN_SIGNER, 372 "Unknown Signer"); 373 add_sig_to_list(&content->signature.info, 374 &data->result->unknown_sigs, 375 &data->result->unknownc); 376 break; 377 } 378 switch (content->signature.info.type) { 379 case OPS_SIG_BINARY: 380 case OPS_SIG_TEXT: 381 valid = check_binary_signature( 382 __ops_memory_get_length(data->mem), 383 __ops_memory_get_data(data->mem), 384 &content->signature, 385 __ops_get_public_key_from_data(signer)); 386 break; 387 388 default: 389 OPS_ERROR_1(errors, OPS_E_UNIMPLEMENTED, 390 "No Sig Verification type 0x%02x yet\n", 391 content->signature.info.type); 392 break; 393 394 } 395 396 __ops_memory_free(data->mem); 397 398 if (valid) { 399 add_sig_to_list(&content->signature.info, 400 &data->result->valid_sigs, 401 &data->result->validc); 402 } else { 403 OPS_ERROR(errors, OPS_E_V_BAD_SIGNATURE, 404 "Bad Signature"); 405 add_sig_to_list(&content->signature.info, 406 &data->result->invalid_sigs, 407 &data->result->invalidc); 408 } 409 break; 410 411 /* ignore these */ 412 case OPS_PARSER_PTAG: 413 case OPS_PTAG_CT_SIGNATURE_HEADER: 414 case OPS_PTAG_CT_ARMOUR_HEADER: 415 case OPS_PTAG_CT_ARMOUR_TRAILER: 416 case OPS_PTAG_CT_ONE_PASS_SIGNATURE: 417 case OPS_PARSER_PACKET_END: 418 break; 419 420 default: 421 OPS_ERROR(errors, OPS_E_V_NO_SIGNATURE, "No signature"); 422 break; 423 } 424 return OPS_RELEASE_MEMORY; 425 } 426 427 static void 428 keydata_destroyer(__ops_reader_info_t * rinfo) 429 { 430 free(__ops_reader_get_arg(rinfo)); 431 } 432 433 void 434 __ops_keydata_reader_set(__ops_parse_info_t *pinfo, 435 const __ops_keydata_t *key) 436 { 437 validate_reader_t *data = calloc(1, sizeof(*data)); 438 439 data->key = key; 440 data->packet = 0; 441 data->offset = 0; 442 443 __ops_reader_set(pinfo, keydata_reader, keydata_destroyer, data); 444 } 445 446 /** 447 * \ingroup HighLevel_Verify 448 * \brief Indicicates whether any errors were found 449 * \param result Validation result to check 450 * \return false if any invalid signatures or unknown signers 451 or no valid signatures; else true 452 */ 453 static bool 454 validate_result_status(__ops_validation_t *val) 455 { 456 return val->validc && !val->invalidc && !val->unknownc; 457 } 458 459 /** 460 * \ingroup HighLevel_Verify 461 * \brief Validate all signatures on a single key against the given keyring 462 * \param result Where to put the result 463 * \param key Key to validate 464 * \param keyring Keyring to use for validation 465 * \param cb_get_passphrase Callback to use to get passphrase 466 * \return true if all signatures OK; else false 467 * \note It is the caller's responsiblity to free result after use. 468 * \sa __ops_validate_result_free() 469 */ 470 bool 471 __ops_validate_key_signatures(__ops_validation_t * result, 472 const __ops_keydata_t * key, 473 const __ops_keyring_t * keyring, 474 __ops_parse_cb_return_t cb_get_passphrase(const __ops_parser_content_t *, __ops_parse_cb_info_t *) 475 ) 476 { 477 __ops_parse_info_t *pinfo; 478 validate_key_cb_t carg; 479 480 (void) memset(&carg, 0x0, sizeof(carg)); 481 carg.result = result; 482 carg.cb_get_passphrase = cb_get_passphrase; 483 484 pinfo = __ops_parse_info_new(); 485 /* __ops_parse_options(&opt,OPS_PTAG_CT_SIGNATURE,OPS_PARSE_PARSED); */ 486 487 carg.keyring = keyring; 488 489 __ops_parse_cb_set(pinfo, __ops_validate_key_cb, &carg); 490 pinfo->rinfo.accumulate = true; 491 __ops_keydata_reader_set(pinfo, key); 492 493 /* Note: Coverity incorrectly reports an error that carg.rarg */ 494 /* is never used. */ 495 carg.rarg = pinfo->rinfo.arg; 496 497 __ops_parse(pinfo); 498 499 __ops_public_key_free(&carg.pkey); 500 if (carg.subkey.version) 501 __ops_public_key_free(&carg.subkey); 502 __ops_user_id_free(&carg.user_id); 503 __ops_user_attribute_free(&carg.user_attribute); 504 505 __ops_parse_info_delete(pinfo); 506 507 if (result->invalidc || result->unknownc || !result->validc) 508 return false; 509 else 510 return true; 511 } 512 513 /** 514 \ingroup HighLevel_Verify 515 \param result Where to put the result 516 \param ring Keyring to use 517 \param cb_get_passphrase Callback to use to get passphrase 518 \note It is the caller's responsibility to free result after use. 519 \sa __ops_validate_result_free() 520 */ 521 bool 522 __ops_validate_all_signatures(__ops_validation_t * result, 523 const __ops_keyring_t * ring, 524 __ops_parse_cb_return_t cb_get_passphrase(const __ops_parser_content_t *, __ops_parse_cb_info_t *) 525 ) 526 { 527 int n; 528 529 (void) memset(result, 0x0, sizeof(*result)); 530 for (n = 0; n < ring->nkeys; ++n) { 531 __ops_validate_key_signatures(result, &ring->keys[n], ring, 532 cb_get_passphrase); 533 } 534 return validate_result_status(result); 535 } 536 537 /** 538 \ingroup HighLevel_Verify 539 \brief Frees validation result and associated memory 540 \param result Struct to be freed 541 \note Must be called after validation functions 542 */ 543 void 544 __ops_validate_result_free(__ops_validation_t *result) 545 { 546 if (result != NULL) { 547 if (result->valid_sigs) { 548 free_signature_info(result->valid_sigs); 549 } 550 if (result->invalid_sigs) { 551 free_signature_info(result->invalid_sigs); 552 } 553 if (result->unknown_sigs) { 554 free_signature_info(result->unknown_sigs); 555 } 556 (void) free(result); 557 result = NULL; 558 } 559 } 560 561 /** 562 \ingroup HighLevel_Verify 563 \brief Verifies the signatures in a signed file 564 \param result Where to put the result 565 \param filename Name of file to be validated 566 \param armoured Treat file as armoured, if set 567 \param keyring Keyring to use 568 \return true if signatures validate successfully; 569 false if signatures fail or there are no signatures 570 \note After verification, result holds the details of all keys which 571 have passed, failed and not been recognised. 572 \note It is the caller's responsiblity to call 573 __ops_validate_result_free(result) after use. 574 */ 575 bool 576 __ops_validate_file(__ops_validation_t *result, 577 const char *filename, 578 const int armoured, 579 const __ops_keyring_t *keyring) 580 { 581 __ops_parse_info_t *pinfo = NULL; 582 validate_data_cb_t validation; 583 int fd = 0; 584 585 fd = __ops_setup_file_read(&pinfo, filename, &validation, 586 validate_data_cb, true); 587 if (fd < 0) { 588 return false; 589 } 590 591 /* Set verification reader and handling options */ 592 (void) memset(&validation, 0x0, sizeof(validation)); 593 validation.result = result; 594 validation.keyring = keyring; 595 validation.mem = __ops_memory_new(); 596 __ops_memory_init(validation.mem, 128); 597 /* Note: Coverity incorrectly reports an error that carg.rarg */ 598 /* is never used. */ 599 validation.rarg = pinfo->rinfo.arg; 600 601 if (armoured) { 602 __ops_reader_push_dearmour(pinfo); 603 } 604 605 /* Do the verification */ 606 __ops_parse(pinfo); 607 if (__ops_get_debug_level(__FILE__)) { 608 printf("valid=%d, invalid=%d, unknown=%d\n", 609 result->validc, 610 result->invalidc, 611 result->unknownc); 612 } 613 614 /* Tidy up */ 615 if (armoured) { 616 __ops_reader_pop_dearmour(pinfo); 617 } 618 __ops_teardown_file_read(pinfo, fd); 619 620 return validate_result_status(result); 621 } 622 623 /** 624 \ingroup HighLevel_Verify 625 \brief Verifies the signatures in a __ops_memory_t struct 626 \param result Where to put the result 627 \param mem Memory to be validated 628 \param armoured Treat data as armoured, if set 629 \param keyring Keyring to use 630 \return true if signature validates successfully; false if not 631 \note After verification, result holds the details of all keys which 632 have passed, failed and not been recognised. 633 \note It is the caller's responsiblity to call 634 __ops_validate_result_free(result) after use. 635 */ 636 637 bool 638 __ops_validate_mem(__ops_validation_t *result, __ops_memory_t *mem, 639 const int armoured, const __ops_keyring_t *keyring) 640 { 641 __ops_parse_info_t *pinfo = NULL; 642 validate_data_cb_t validation; 643 644 __ops_setup_memory_read(&pinfo, mem, &validation, validate_data_cb, 645 true); 646 647 /* Set verification reader and handling options */ 648 (void) memset(&validation, 0x0, sizeof(validation)); 649 validation.result = result; 650 validation.keyring = keyring; 651 validation.mem = __ops_memory_new(); 652 __ops_memory_init(validation.mem, 128); 653 /* Note: Coverity incorrectly reports an error that carg.rarg */ 654 /* is never used. */ 655 validation.rarg = pinfo->rinfo.arg; 656 657 if (armoured) { 658 __ops_reader_push_dearmour(pinfo); 659 } 660 661 /* Do the verification */ 662 __ops_parse(pinfo); 663 if (__ops_get_debug_level(__FILE__)) { 664 printf("valid=%d, invalid=%d, unknown=%d\n", 665 result->validc, 666 result->invalidc, 667 result->unknownc); 668 } 669 670 /* Tidy up */ 671 if (armoured) { 672 __ops_reader_pop_dearmour(pinfo); 673 } 674 __ops_teardown_memory_read(pinfo, mem); 675 676 return validate_result_status(result); 677 } 678