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