1 /*- 2 * Copyright (c) 2009 The NetBSD Foundation, Inc. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to The NetBSD Foundation 6 * by Alistair Crooks (agc@NetBSD.org) 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 * POSSIBILITY OF SUCH DAMAGE. 28 */ 29 /* 30 * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) 31 * All rights reserved. 32 * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted 33 * their moral rights under the UK Copyright Design and Patents Act 1988 to 34 * be recorded as the authors of this copyright work. 35 * 36 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 37 * use this file except in compliance with the License. 38 * 39 * You may obtain a copy of the License at 40 * http://www.apache.org/licenses/LICENSE-2.0 41 * 42 * Unless required by applicable law or agreed to in writing, software 43 * distributed under the License is distributed on an "AS IS" BASIS, 44 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 45 * 46 * See the License for the specific language governing permissions and 47 * limitations under the License. 48 */ 49 #include "config.h" 50 51 #include <sys/types.h> 52 #include <sys/param.h> 53 #include <sys/stat.h> 54 55 #include <string.h> 56 #include <stdio.h> 57 58 #include "packet-parse.h" 59 #include "packet-show.h" 60 #include "keyring.h" 61 #include "signature.h" 62 #include "netpgpsdk.h" 63 #include "readerwriter.h" 64 #include "netpgpdefs.h" 65 #include "memory.h" 66 #include "keyring_local.h" 67 #include "parse_local.h" 68 #include "validate.h" 69 70 71 /* Does the signed hash match the given hash? */ 72 static bool 73 check_binary_sig(const unsigned len, 74 const unsigned char *data, 75 const __ops_sig_t *sig, 76 const __ops_pubkey_t *signer) 77 { 78 unsigned char hashout[OPS_MAX_HASH_SIZE]; 79 unsigned char trailer[6]; 80 unsigned int hashedlen; 81 __ops_hash_t hash; 82 unsigned n = 0; 83 84 __OPS_USED(signer); 85 __ops_hash_any(&hash, sig->info.hash_alg); 86 hash.init(&hash); 87 hash.add(&hash, data, len); 88 switch (sig->info.version) { 89 case OPS_V3: 90 trailer[0] = sig->info.type; 91 trailer[1] = (unsigned)(sig->info.birthtime) >> 24; 92 trailer[2] = (unsigned)(sig->info.birthtime) >> 16; 93 trailer[3] = (unsigned)(sig->info.birthtime) >> 8; 94 trailer[4] = (unsigned char)(sig->info.birthtime); 95 hash.add(&hash, &trailer[0], 5); 96 break; 97 98 case OPS_V4: 99 hash.add(&hash, sig->info.v4_hashed_data, 100 sig->info.v4_hashed_data_length); 101 trailer[0] = 0x04; /* version */ 102 trailer[1] = 0xFF; 103 hashedlen = sig->info.v4_hashed_data_length; 104 trailer[2] = hashedlen >> 24; 105 trailer[3] = hashedlen >> 16; 106 trailer[4] = hashedlen >> 8; 107 trailer[5] = hashedlen; 108 hash.add(&hash, &trailer[0], 6); 109 break; 110 111 default: 112 fprintf(stderr, "Invalid signature version %d\n", 113 sig->info.version); 114 return false; 115 } 116 117 n = hash.finish(&hash, hashout); 118 if (__ops_get_debug_level(__FILE__)) { 119 printf("check_binary_sig: hash length %" PRIsize "u\n", 120 hash.size); 121 } 122 return __ops_check_sig(hashout, n, sig, signer); 123 } 124 125 static int 126 keydata_reader(void *dest, size_t length, __ops_error_t ** errors, 127 __ops_reader_t * readinfo, 128 __ops_callback_data_t * cbinfo) 129 { 130 validate_reader_t *reader = __ops_reader_get_arg(readinfo); 131 132 __OPS_USED(errors); 133 __OPS_USED(cbinfo); 134 if (reader->offset == reader->key->packets[reader->packet].length) { 135 reader->packet += 1; 136 reader->offset = 0; 137 } 138 if (reader->packet == reader->key->npackets) { 139 return 0; 140 } 141 142 /* 143 * we should never be asked to cross a packet boundary in a single 144 * read 145 */ 146 if (reader->key->packets[reader->packet].length < 147 reader->offset + length) { 148 (void) fprintf(stderr, "keydata_reader: weird length\n"); 149 return 0; 150 } 151 152 (void) memcpy(dest, 153 &reader->key->packets[reader->packet].raw[reader->offset], 154 length); 155 reader->offset += length; 156 157 return length; 158 } 159 160 static void 161 free_sig_info(__ops_sig_info_t * sig) 162 { 163 (void) free(sig->v4_hashed_data); 164 (void) free(sig); 165 } 166 167 static void 168 copy_sig_info(__ops_sig_info_t * dst, const __ops_sig_info_t * src) 169 { 170 (void) memcpy(dst, src, sizeof(*src)); 171 dst->v4_hashed_data = calloc(1, src->v4_hashed_data_length); 172 (void) memcpy(dst->v4_hashed_data, src->v4_hashed_data, 173 src->v4_hashed_data_length); 174 } 175 176 static void 177 add_sig_to_list(const __ops_sig_info_t *sig, __ops_sig_info_t **sigs, 178 unsigned *count) 179 { 180 if (*count == 0) { 181 *sigs = calloc(*count + 1, sizeof(__ops_sig_info_t)); 182 } else { 183 *sigs = realloc(*sigs, 184 (*count + 1) * sizeof(__ops_sig_info_t)); 185 } 186 copy_sig_info(&(*sigs)[*count], sig); 187 *count += 1; 188 } 189 190 191 __ops_parse_cb_return_t 192 __ops_validate_key_cb(const __ops_packet_t *pkt, __ops_callback_data_t *cbinfo) 193 { 194 const __ops_parser_content_union_t *content = &pkt->u; 195 const __ops_keydata_t *signer; 196 validate_key_cb_t *key = __ops_parse_cb_get_arg(cbinfo); 197 __ops_error_t **errors = __ops_parse_cb_get_errors(cbinfo); 198 bool valid = false; 199 200 if (__ops_get_debug_level(__FILE__)) { 201 printf("%s\n", __ops_show_packet_tag(pkt->tag)); 202 } 203 204 switch (pkt->tag) { 205 case OPS_PTAG_CT_PUBLIC_KEY: 206 if (key->pubkey.version != 0) { 207 (void) fprintf(stderr, 208 "__ops_validate_key_cb: version bad\n"); 209 return OPS_FINISHED; 210 } 211 key->pubkey = content->pubkey; 212 return OPS_KEEP_MEMORY; 213 214 case OPS_PTAG_CT_PUBLIC_SUBKEY: 215 if (key->subkey.version) 216 __ops_pubkey_free(&key->subkey); 217 key->subkey = content->pubkey; 218 return OPS_KEEP_MEMORY; 219 220 case OPS_PTAG_CT_SECRET_KEY: 221 key->seckey = content->seckey; 222 key->pubkey = key->seckey.pubkey; 223 return OPS_KEEP_MEMORY; 224 225 case OPS_PTAG_CT_USER_ID: 226 if (key->user_id.user_id) 227 __ops_user_id_free(&key->user_id); 228 key->user_id = content->user_id; 229 key->last_seen = ID; 230 return OPS_KEEP_MEMORY; 231 232 case OPS_PTAG_CT_USER_ATTRIBUTE: 233 if (content->user_attribute.data.len == 0) { 234 (void) fprintf(stderr, 235 "__ops_validate_key_cb: user attribute length 0"); 236 return OPS_FINISHED; 237 } 238 printf("user attribute, length=%d\n", 239 (int) content->user_attribute.data.len); 240 if (key->user_attribute.data.len) 241 __ops_user_attribute_free(&key->user_attribute); 242 key->user_attribute = content->user_attribute; 243 key->last_seen = ATTRIBUTE; 244 return OPS_KEEP_MEMORY; 245 246 case OPS_PTAG_CT_SIGNATURE: /* V3 sigs */ 247 case OPS_PTAG_CT_SIGNATURE_FOOTER: /* V4 sigs */ 248 249 signer = __ops_keyring_find_key_by_id(key->keyring, 250 content->sig.info.signer_id); 251 if (!signer) { 252 add_sig_to_list(&content->sig.info, 253 &key->result->unknown_sigs, 254 &key->result->unknownc); 255 break; 256 } 257 switch (content->sig.info.type) { 258 case OPS_CERT_GENERIC: 259 case OPS_CERT_PERSONA: 260 case OPS_CERT_CASUAL: 261 case OPS_CERT_POSITIVE: 262 case OPS_SIG_REV_CERT: 263 valid = (key->last_seen == ID) ? 264 __ops_check_useridcert_sig(&key->pubkey, 265 &key->user_id, 266 &content->sig, 267 __ops_get_pubkey(signer), 268 key->rarg->key->packets[key->rarg->packet].raw): 269 __ops_check_userattrcert_sig(&key->pubkey, 270 &key->user_attribute, 271 &content->sig, 272 __ops_get_pubkey(signer), 273 key->rarg->key->packets[key->rarg->packet].raw); 274 break; 275 276 case OPS_SIG_SUBKEY: 277 /* 278 * XXX: we should also check that the signer is the 279 * key we are validating, I think. 280 */ 281 valid = __ops_check_subkey_sig(&key->pubkey, &key->subkey, 282 &content->sig, 283 __ops_get_pubkey(signer), 284 key->rarg->key->packets[key->rarg->packet].raw); 285 break; 286 287 case OPS_SIG_DIRECT: 288 valid = __ops_check_direct_sig(&key->pubkey, 289 &content->sig, 290 __ops_get_pubkey(signer), 291 key->rarg->key->packets[key->rarg->packet].raw); 292 break; 293 294 case OPS_SIG_STANDALONE: 295 case OPS_SIG_PRIMARY: 296 case OPS_SIG_REV_KEY: 297 case OPS_SIG_REV_SUBKEY: 298 case OPS_SIG_TIMESTAMP: 299 case OPS_SIG_3RD_PARTY: 300 OPS_ERROR_1(errors, OPS_E_UNIMPLEMENTED, 301 "Sig Verification type 0x%02x not done yet\n", 302 content->sig.info.type); 303 break; 304 305 default: 306 OPS_ERROR_1(errors, OPS_E_UNIMPLEMENTED, 307 "Unexpected signature type 0x%02x\n", 308 content->sig.info.type); 309 } 310 311 if (valid) { 312 add_sig_to_list(&content->sig.info, 313 &key->result->valid_sigs, 314 &key->result->validc); 315 } else { 316 OPS_ERROR(errors, OPS_E_V_BAD_SIGNATURE, "Bad Sig"); 317 add_sig_to_list(&content->sig.info, 318 &key->result->invalid_sigs, 319 &key->result->invalidc); 320 } 321 break; 322 323 /* ignore these */ 324 case OPS_PARSER_PTAG: 325 case OPS_PTAG_CT_SIGNATURE_HEADER: 326 case OPS_PARSER_PACKET_END: 327 break; 328 329 case OPS_PARSER_CMD_GET_SK_PASSPHRASE: 330 if (key->cb_get_passphrase) { 331 return key->cb_get_passphrase(pkt, cbinfo); 332 } 333 break; 334 335 default: 336 (void) fprintf(stderr, "unexpected tag=0x%x\n", pkt->tag); 337 return OPS_FINISHED; 338 } 339 return OPS_RELEASE_MEMORY; 340 } 341 342 __ops_parse_cb_return_t 343 validate_data_cb(const __ops_packet_t * pkt, 344 __ops_callback_data_t * cbinfo) 345 { 346 const __ops_parser_content_union_t *content = &pkt->u; 347 const __ops_keydata_t *signer; 348 validate_data_cb_t *data = __ops_parse_cb_get_arg(cbinfo); 349 __ops_error_t **errors = __ops_parse_cb_get_errors(cbinfo); 350 bool valid = false; 351 352 if (__ops_get_debug_level(__FILE__)) { 353 printf("validate_data_cb: %s\n", 354 __ops_show_packet_tag(pkt->tag)); 355 } 356 switch (pkt->tag) { 357 case OPS_PTAG_CT_SIGNED_CLEARTEXT_HEADER: 358 /* 359 * ignore - this gives us the "Armor Header" line "Hash: 360 * SHA1" or similar 361 */ 362 break; 363 364 case OPS_PTAG_CT_LITERAL_DATA_HEADER: 365 /* ignore */ 366 break; 367 368 case OPS_PTAG_CT_LITERAL_DATA_BODY: 369 data->data.litdata_body = content->litdata_body; 370 data->use = LITERAL_DATA; 371 __ops_memory_add(data->mem, data->data.litdata_body.data, 372 data->data.litdata_body.length); 373 return OPS_KEEP_MEMORY; 374 375 case OPS_PTAG_CT_SIGNED_CLEARTEXT_BODY: 376 data->data.cleartext_body = 377 content->cleartext_body; 378 data->use = SIGNED_CLEARTEXT; 379 __ops_memory_add(data->mem, data->data.litdata_body.data, 380 data->data.litdata_body.length); 381 return OPS_KEEP_MEMORY; 382 383 case OPS_PTAG_CT_SIGNED_CLEARTEXT_TRAILER: 384 /* this gives us an __ops_hash_t struct */ 385 break; 386 387 case OPS_PTAG_CT_SIGNATURE: /* V3 sigs */ 388 case OPS_PTAG_CT_SIGNATURE_FOOTER: /* V4 sigs */ 389 if (__ops_get_debug_level(__FILE__)) { 390 unsigned i = 0; 391 392 printf("\n*** hashed data:\n"); 393 for (i = 0; 394 i < content->sig.info.v4_hashed_data_length; 395 i++) { 396 printf("0x%02x ", 397 content->sig.info.v4_hashed_data[i]); 398 } 399 printf("\n"); 400 printf(" type=%02x signer_id=", 401 content->sig.info.type); 402 hexdump(content->sig.info.signer_id, 403 sizeof(content->sig.info.signer_id), ""); 404 printf("\n"); 405 } 406 signer = __ops_keyring_find_key_by_id(data->keyring, 407 content->sig.info.signer_id); 408 if (!signer) { 409 OPS_ERROR(errors, OPS_E_V_UNKNOWN_SIGNER, 410 "Unknown Signer"); 411 add_sig_to_list(&content->sig.info, 412 &data->result->unknown_sigs, 413 &data->result->unknownc); 414 break; 415 } 416 switch (content->sig.info.type) { 417 case OPS_SIG_BINARY: 418 case OPS_SIG_TEXT: 419 valid = check_binary_sig( 420 __ops_memory_get_length(data->mem), 421 __ops_memory_get_data(data->mem), 422 &content->sig, 423 __ops_get_pubkey(signer)); 424 break; 425 426 default: 427 OPS_ERROR_1(errors, OPS_E_UNIMPLEMENTED, 428 "No Sig Verification type 0x%02x yet\n", 429 content->sig.info.type); 430 break; 431 432 } 433 434 __ops_memory_free(data->mem); 435 436 if (valid) { 437 add_sig_to_list(&content->sig.info, 438 &data->result->valid_sigs, 439 &data->result->validc); 440 } else { 441 OPS_ERROR(errors, OPS_E_V_BAD_SIGNATURE, 442 "Bad Signature"); 443 add_sig_to_list(&content->sig.info, 444 &data->result->invalid_sigs, 445 &data->result->invalidc); 446 } 447 break; 448 449 /* ignore these */ 450 case OPS_PARSER_PTAG: 451 case OPS_PTAG_CT_SIGNATURE_HEADER: 452 case OPS_PTAG_CT_ARMOUR_HEADER: 453 case OPS_PTAG_CT_ARMOUR_TRAILER: 454 case OPS_PTAG_CT_ONE_PASS_SIGNATURE: 455 case OPS_PARSER_PACKET_END: 456 break; 457 458 default: 459 OPS_ERROR(errors, OPS_E_V_NO_SIGNATURE, "No signature"); 460 break; 461 } 462 return OPS_RELEASE_MEMORY; 463 } 464 465 static void 466 keydata_destroyer(__ops_reader_t * readinfo) 467 { 468 free(__ops_reader_get_arg(readinfo)); 469 } 470 471 void 472 __ops_keydata_reader_set(__ops_parseinfo_t *pinfo, 473 const __ops_keydata_t *key) 474 { 475 validate_reader_t *data = calloc(1, sizeof(*data)); 476 477 data->key = key; 478 data->packet = 0; 479 data->offset = 0; 480 481 __ops_reader_set(pinfo, keydata_reader, keydata_destroyer, data); 482 } 483 484 /** 485 * \ingroup HighLevel_Verify 486 * \brief Indicicates whether any errors were found 487 * \param result Validation result to check 488 * \return false if any invalid signatures or unknown signers 489 or no valid signatures; else true 490 */ 491 static bool 492 validate_result_status(__ops_validation_t *val) 493 { 494 return val->validc && !val->invalidc && !val->unknownc; 495 } 496 497 /** 498 * \ingroup HighLevel_Verify 499 * \brief Validate all signatures on a single key against the given keyring 500 * \param result Where to put the result 501 * \param key Key to validate 502 * \param keyring Keyring to use for validation 503 * \param cb_get_passphrase Callback to use to get passphrase 504 * \return true if all signatures OK; else false 505 * \note It is the caller's responsiblity to free result after use. 506 * \sa __ops_validate_result_free() 507 */ 508 bool 509 __ops_validate_key_sigs(__ops_validation_t * result, 510 const __ops_keydata_t * key, 511 const __ops_keyring_t * keyring, 512 __ops_parse_cb_return_t cb_get_passphrase(const __ops_packet_t *, 513 __ops_callback_data_t *)) 514 { 515 __ops_parseinfo_t *pinfo; 516 validate_key_cb_t carg; 517 518 (void) memset(&carg, 0x0, sizeof(carg)); 519 carg.result = result; 520 carg.cb_get_passphrase = cb_get_passphrase; 521 522 pinfo = __ops_parseinfo_new(); 523 /* __ops_parse_options(&opt,OPS_PTAG_CT_SIGNATURE,OPS_PARSE_PARSED); */ 524 525 carg.keyring = keyring; 526 527 __ops_parse_cb_set(pinfo, __ops_validate_key_cb, &carg); 528 pinfo->readinfo.accumulate = true; 529 __ops_keydata_reader_set(pinfo, key); 530 531 /* Note: Coverity incorrectly reports an error that carg.rarg */ 532 /* is never used. */ 533 carg.rarg = pinfo->readinfo.arg; 534 535 __ops_parse(pinfo, 0); 536 537 __ops_pubkey_free(&carg.pubkey); 538 if (carg.subkey.version) { 539 __ops_pubkey_free(&carg.subkey); 540 } 541 __ops_user_id_free(&carg.user_id); 542 __ops_user_attribute_free(&carg.user_attribute); 543 544 __ops_parseinfo_delete(pinfo); 545 546 return (!result->invalidc && !result->unknownc && result->validc); 547 } 548 549 /** 550 \ingroup HighLevel_Verify 551 \param result Where to put the result 552 \param ring Keyring to use 553 \param cb_get_passphrase Callback to use to get passphrase 554 \note It is the caller's responsibility to free result after use. 555 \sa __ops_validate_result_free() 556 */ 557 bool 558 __ops_validate_all_sigs(__ops_validation_t *result, 559 const __ops_keyring_t *ring, 560 __ops_parse_cb_return_t cb_get_passphrase(const __ops_packet_t *, 561 __ops_callback_data_t *)) 562 { 563 int n; 564 565 (void) memset(result, 0x0, sizeof(*result)); 566 for (n = 0; n < ring->nkeys; ++n) { 567 __ops_validate_key_sigs(result, &ring->keys[n], ring, 568 cb_get_passphrase); 569 } 570 return validate_result_status(result); 571 } 572 573 /** 574 \ingroup HighLevel_Verify 575 \brief Frees validation result and associated memory 576 \param result Struct to be freed 577 \note Must be called after validation functions 578 */ 579 void 580 __ops_validate_result_free(__ops_validation_t *result) 581 { 582 if (result != NULL) { 583 if (result->valid_sigs) { 584 free_sig_info(result->valid_sigs); 585 } 586 if (result->invalid_sigs) { 587 free_sig_info(result->invalid_sigs); 588 } 589 if (result->unknown_sigs) { 590 free_sig_info(result->unknown_sigs); 591 } 592 (void) free(result); 593 result = NULL; 594 } 595 } 596 597 /** 598 \ingroup HighLevel_Verify 599 \brief Verifies the signatures in a signed file 600 \param result Where to put the result 601 \param filename Name of file to be validated 602 \param armoured Treat file as armoured, if set 603 \param keyring Keyring to use 604 \return true if signatures validate successfully; 605 false if signatures fail or there are no signatures 606 \note After verification, result holds the details of all keys which 607 have passed, failed and not been recognised. 608 \note It is the caller's responsiblity to call 609 __ops_validate_result_free(result) after use. 610 */ 611 bool 612 __ops_validate_file(__ops_validation_t *result, 613 const char *infile, 614 const char *outfile, 615 const int armoured, 616 const __ops_keyring_t *keyring) 617 { 618 __ops_parseinfo_t *parse = NULL; 619 validate_data_cb_t validation; 620 struct stat st; 621 int64_t origsize; 622 char *filename; 623 char origfile[MAXPATHLEN]; 624 int fd_out = 0; 625 int fd_in; 626 int cc; 627 628 #define SIG_OVERHEAD 284 /* XXX - depends on sig size? */ 629 630 if (stat(infile, &st) < 0) { 631 (void) fprintf(stderr, "can't validate \"%s\"\n", infile); 632 return false; 633 } 634 origsize = st.st_size; 635 cc = snprintf(origfile, sizeof(origfile), "%s", infile); 636 if (strcmp(&origfile[cc - 4], ".sig") == 0) { 637 origfile[cc - 4] = 0x0; 638 if (stat(origfile, &st) == 0 && 639 st.st_size - SIG_OVERHEAD < origsize) { 640 parse->synthlit = strdup(origfile); 641 } 642 } 643 644 fd_in = __ops_setup_file_read(&parse, infile, &validation, 645 validate_data_cb, true); 646 if (fd_in < 0) { 647 return false; 648 } 649 650 /* setup output filename */ 651 filename = NULL; 652 if (outfile) { 653 if (strcmp(outfile, "-") == 0) { 654 outfile = NULL; 655 } 656 fd_out = __ops_setup_file_write(&parse->cbinfo.cinfo, 657 NULL, false); 658 if (fd_out < 0) { 659 __ops_teardown_file_read(parse, fd_in); 660 return false; 661 } 662 } 663 664 /* Set verification reader and handling options */ 665 (void) memset(&validation, 0x0, sizeof(validation)); 666 validation.result = result; 667 validation.keyring = keyring; 668 validation.mem = __ops_memory_new(); 669 __ops_memory_init(validation.mem, 128); 670 /* Note: Coverity incorrectly reports an error that carg.rarg */ 671 /* is never used. */ 672 validation.rarg = parse->readinfo.arg; 673 674 if (armoured) { 675 __ops_reader_push_dearmour(parse); 676 } 677 678 /* Do the verification */ 679 __ops_parse(parse, 0); 680 681 if (__ops_get_debug_level(__FILE__)) { 682 printf("valid=%d, invalid=%d, unknown=%d\n", 683 result->validc, 684 result->invalidc, 685 result->unknownc); 686 } 687 688 /* Tidy up */ 689 if (armoured) { 690 __ops_reader_pop_dearmour(parse); 691 } 692 __ops_teardown_file_read(parse, fd_in); 693 694 return validate_result_status(result); 695 } 696 697 /** 698 \ingroup HighLevel_Verify 699 \brief Verifies the signatures in a __ops_memory_t struct 700 \param result Where to put the result 701 \param mem Memory to be validated 702 \param armoured Treat data as armoured, if set 703 \param keyring Keyring to use 704 \return true if signature validates successfully; false if not 705 \note After verification, result holds the details of all keys which 706 have passed, failed and not been recognised. 707 \note It is the caller's responsiblity to call 708 __ops_validate_result_free(result) after use. 709 */ 710 711 bool 712 __ops_validate_mem(__ops_validation_t *result, __ops_memory_t *mem, 713 const int armoured, const __ops_keyring_t *keyring) 714 { 715 __ops_parseinfo_t *pinfo = NULL; 716 validate_data_cb_t validation; 717 718 __ops_setup_memory_read(&pinfo, mem, &validation, validate_data_cb, 719 true); 720 721 /* Set verification reader and handling options */ 722 (void) memset(&validation, 0x0, sizeof(validation)); 723 validation.result = result; 724 validation.keyring = keyring; 725 validation.mem = __ops_memory_new(); 726 __ops_memory_init(validation.mem, 128); 727 /* Note: Coverity incorrectly reports an error that carg.rarg */ 728 /* is never used. */ 729 validation.rarg = pinfo->readinfo.arg; 730 731 if (armoured) { 732 __ops_reader_push_dearmour(pinfo); 733 } 734 735 /* Do the verification */ 736 __ops_parse(pinfo, 0); 737 if (__ops_get_debug_level(__FILE__)) { 738 printf("valid=%d, invalid=%d, unknown=%d\n", 739 result->validc, 740 result->invalidc, 741 result->unknownc); 742 } 743 744 /* Tidy up */ 745 if (armoured) { 746 __ops_reader_pop_dearmour(pinfo); 747 } 748 __ops_teardown_memory_read(pinfo, mem); 749 750 return validate_result_status(result); 751 } 752