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 50 /* 51 * ! \file \brief Standard API print functions 52 */ 53 #include "config.h" 54 55 #include <string.h> 56 #include <stdio.h> 57 58 #ifdef HAVE_UNISTD_H 59 #include <unistd.h> 60 #endif 61 62 #include "crypto.h" 63 #include "keyring.h" 64 #include "packet-show.h" 65 #include "signature.h" 66 #include "readerwriter.h" 67 #include "netpgpdefs.h" 68 #include "keyring_local.h" 69 #include "parse_local.h" 70 71 static int indent = 0; 72 73 /* static functions */ 74 75 /* printhex is now print_hex for consistency */ 76 static void 77 print_hex(const unsigned char *src, size_t length) 78 { 79 while (length-- > 0) { 80 printf("%02X", *src++); 81 } 82 } 83 84 static void 85 print_indent(void) 86 { 87 int i = 0; 88 89 for (i = 0; i < indent; i++) { 90 printf(" "); 91 } 92 } 93 94 static void 95 print_name(const char *name) 96 { 97 print_indent(); 98 if (name) { 99 printf("%s: ", name); 100 } 101 } 102 103 static void 104 print_hexdump(const char *name, const unsigned char *data, unsigned int len) 105 { 106 print_name(name); 107 108 printf("len=%d, data=0x", len); 109 print_hex(data, len); 110 printf("\n"); 111 } 112 113 static void 114 print_hexdump_data(const char *name, const unsigned char *data, unsigned len) 115 { 116 print_name(name); 117 118 printf("0x"); 119 print_hex(data, len); 120 printf("\n"); 121 } 122 123 static void 124 print_unsigned_int(const char *name, unsigned int val) 125 { 126 print_name(name); 127 printf("%d\n", val); 128 } 129 130 static void 131 showtime(const char *name, time_t t) 132 { 133 printf("%s=%" PRItime "d (%.24s)", name, (long long) t, ctime(&t)); 134 } 135 136 static void 137 print_time(const char *name, time_t t) 138 { 139 print_indent(); 140 printf("%s: ", name); 141 showtime("time", t); 142 printf("\n"); 143 } 144 145 static void 146 showtime_short(time_t t) 147 { 148 struct tm *tm; 149 150 tm = gmtime(&t); 151 printf("%04d-%02d-%02d", 152 tm->tm_year + 1900, 153 tm->tm_mon + 1, 154 tm->tm_mday); 155 } 156 157 static void 158 print_time_short(time_t t) 159 { 160 showtime_short(t); 161 } 162 163 static void 164 print_string_and_value(const char *name, const char *str, 165 unsigned char value) 166 { 167 print_name(name); 168 169 printf("%s", str); 170 printf(" (0x%x)", value); 171 printf("\n"); 172 } 173 174 static void 175 print_tagname(const char *str) 176 { 177 print_indent(); 178 printf("%s packet\n", str); 179 } 180 181 static void 182 print_data(const char *name, const __ops_data_t * data) 183 { 184 print_hexdump(name, data->contents, data->len); 185 } 186 187 static void 188 print_bn(const char *name, const BIGNUM * bn) 189 { 190 print_indent(); 191 printf("%s=", name); 192 if (bn) { 193 BN_print_fp(stdout, bn); 194 putchar('\n'); 195 } else { 196 puts("(unset)"); 197 } 198 } 199 200 201 static void 202 print_packet_hex(const __ops_subpacket_t *pkt) 203 { 204 unsigned char *cur; 205 unsigned rem; 206 unsigned blksz = 4; 207 int i; 208 209 printf("\nhexdump of packet contents follows:\n"); 210 for (i = 1, cur = pkt->raw; 211 cur < (pkt->raw + pkt->length); 212 cur += blksz, i++) { 213 rem = pkt->raw + pkt->length - cur; 214 hexdump(cur, (rem <= blksz) ? rem : blksz, ""); 215 printf(" "); 216 if (i % 8 == 0) { 217 printf("\n"); 218 } 219 220 } 221 printf("\n"); 222 } 223 224 static void 225 print_escaped(const unsigned char *data, size_t length) 226 { 227 while (length-- > 0) { 228 if ((*data >= 0x20 && *data < 0x7f && *data != '%') || 229 *data == '\n') { 230 putchar(*data); 231 } else { 232 printf("%%%02x", *data); 233 } 234 ++data; 235 } 236 } 237 238 static void 239 print_string(const char *name, const char *str) 240 { 241 print_name(name); 242 print_escaped((const unsigned char *) str, strlen(str)); 243 putchar('\n'); 244 } 245 246 static void 247 print_utf8_string(const char *name, const unsigned char *str) 248 { 249 /* \todo Do this better for non-English character sets */ 250 print_string(name, (const char *) str); 251 } 252 253 static void 254 print_duration(const char *name, time_t t) 255 { 256 int mins, hours, days, years; 257 258 print_indent(); 259 printf("%s: ", name); 260 printf("duration %" PRItime "d seconds", (long long) t); 261 262 mins = (int)(t / 60); 263 hours = mins / 60; 264 days = hours / 24; 265 years = days / 365; 266 267 printf(" (approx. "); 268 if (years) { 269 printf("%d %s", years, years == 1 ? "year" : "years"); 270 } else if (days) { 271 printf("%d %s", days, days == 1 ? "day" : "days"); 272 } else if (hours) { 273 printf("%d %s", hours, hours == 1 ? "hour" : "hours"); 274 } 275 printf(")\n"); 276 } 277 278 static void 279 print_boolean(const char *name, unsigned char boolval) 280 { 281 print_name(name); 282 printf("%s\n", (boolval) ? "Yes" : "No"); 283 } 284 285 static void 286 print_text_breakdown(__ops_text_t * text) 287 { 288 const char *prefix = ".. "; 289 unsigned i; 290 291 /* these were recognised */ 292 for (i = 0; i < text->known.used; i++) { 293 print_indent(); 294 printf("%s", prefix); 295 printf("%s\n", text->known.strings[i]); 296 } 297 /* 298 * these were not recognised. the strings will contain the hex value 299 * of the unrecognised value in string format - see 300 * process_octet_str() 301 */ 302 if (text->unknown.used) { 303 printf("\n"); 304 print_indent(); 305 printf("Not Recognised: "); 306 } 307 for (i = 0; i < text->unknown.used; i++) { 308 print_indent(); 309 printf("%s", prefix); 310 printf("%s\n", text->unknown.strings[i]); 311 } 312 } 313 314 static void 315 print_headers(const __ops_headers_t *h) 316 { 317 unsigned i; 318 319 for (i = 0; i < h->headerc; ++i) { 320 printf("%s=%s\n", h->headers[i].key, h->headers[i].value); 321 } 322 } 323 324 static void 325 print_block(const char *name, const unsigned char *str, size_t length) 326 { 327 int o = length; 328 329 print_indent(); 330 printf(">>>>> %s >>>>>\n", name); 331 332 print_indent(); 333 for (; length > 0; --length) { 334 if (*str >= 0x20 && *str < 0x7f && *str != '%') { 335 putchar(*str); 336 } else if (*str == '\n') { 337 putchar(*str); 338 print_indent(); 339 } else { 340 printf("%%%02x", *str); 341 } 342 ++str; 343 } 344 if (o && str[-1] != '\n') { 345 putchar('\n'); 346 print_indent(); 347 fputs("[no newline]", stdout); 348 } else { 349 print_indent(); 350 } 351 printf("<<<<< %s <<<<<\n", name); 352 } 353 354 /* return the number of bits in the public key */ 355 static int 356 numkeybits(const __ops_pubkey_t *pubkey) 357 { 358 switch(pubkey->alg) { 359 case OPS_PKA_RSA: 360 case OPS_PKA_RSA_ENCRYPT_ONLY: 361 case OPS_PKA_RSA_SIGN_ONLY: 362 return BN_num_bytes(pubkey->key.rsa.n) * 8; 363 case OPS_PKA_DSA: 364 switch(BN_num_bytes(pubkey->key.dsa.q)) { 365 case 20: 366 return 1024; 367 case 28: 368 return 2048; 369 case 32: 370 return 3072; 371 default: 372 return 0; 373 } 374 case OPS_PKA_ELGAMAL: 375 return BN_num_bytes(pubkey->key.elgamal.y) * 8; 376 default: 377 return -1; 378 } 379 } 380 381 /** 382 \ingroup Core_Print 383 384 Prints a public key in succinct detail 385 386 \param key Ptr to public key 387 */ 388 void 389 __ops_print_pubkeydata(const __ops_keydata_t * key) 390 { 391 unsigned int i; 392 393 printf("pub %d/%s ", 394 numkeybits(&key->key.pubkey), 395 __ops_show_pka(key->key.pubkey.alg)); 396 hexdump(key->key_id, OPS_KEY_ID_SIZE, ""); 397 printf(" "); 398 print_time_short(key->key.pubkey.birthtime); 399 printf("\nKey fingerprint: "); 400 hexdump(key->fingerprint.fingerprint, 20, " "); 401 printf("\n"); 402 403 for (i = 0; i < key->nuids; i++) { 404 printf("uid %s\n", key->uids[i].user_id); 405 } 406 } 407 408 /** 409 \ingroup Core_Print 410 \param pubkey 411 */ 412 void 413 __ops_print_pubkey(const __ops_pubkey_t * pubkey) 414 { 415 printf("------- PUBLIC KEY ------\n"); 416 print_unsigned_int("Version", (unsigned)pubkey->version); 417 print_time("Creation Time", pubkey->birthtime); 418 if (pubkey->version == OPS_V3) 419 print_unsigned_int("Days Valid", pubkey->days_valid); 420 421 print_string_and_value("Algorithm", __ops_show_pka(pubkey->alg), 422 pubkey->alg); 423 424 switch (pubkey->alg) { 425 case OPS_PKA_DSA: 426 print_bn("p", pubkey->key.dsa.p); 427 print_bn("q", pubkey->key.dsa.q); 428 print_bn("g", pubkey->key.dsa.g); 429 print_bn("y", pubkey->key.dsa.y); 430 break; 431 432 case OPS_PKA_RSA: 433 case OPS_PKA_RSA_ENCRYPT_ONLY: 434 case OPS_PKA_RSA_SIGN_ONLY: 435 print_bn("n", pubkey->key.rsa.n); 436 print_bn("e", pubkey->key.rsa.e); 437 break; 438 439 case OPS_PKA_ELGAMAL: 440 case OPS_PKA_ELGAMAL_ENCRYPT_OR_SIGN: 441 print_bn("p", pubkey->key.elgamal.p); 442 print_bn("g", pubkey->key.elgamal.g); 443 print_bn("y", pubkey->key.elgamal.y); 444 break; 445 446 default: 447 (void) fprintf(stderr, 448 "__ops_print_pubkey: Unusual algorithm\n"); 449 } 450 451 printf("------- end of PUBLIC KEY ------\n"); 452 } 453 454 /** 455 \ingroup Core_Print 456 457 Prints a secret key 458 459 \param key Ptr to public key 460 */ 461 462 void 463 __ops_print_seckeydata(const __ops_keydata_t * key) 464 { 465 printf("sec "); 466 __ops_show_pka(key->key.pubkey.alg); 467 printf(" "); 468 469 hexdump(key->key_id, OPS_KEY_ID_SIZE, ""); 470 printf(" "); 471 472 print_time_short(key->key.pubkey.birthtime); 473 printf(" "); 474 475 if (key->nuids == 1) { 476 /* print on same line as other info */ 477 printf("%s\n", key->uids[0].user_id); 478 } else { 479 /* print all uids on separate line */ 480 unsigned int i; 481 printf("\n"); 482 for (i = 0; i < key->nuids; i++) { 483 printf("uid %s\n", key->uids[i].user_id); 484 } 485 } 486 } 487 488 /** 489 \ingroup Core_Print 490 \param type 491 \param seckey 492 */ 493 static void 494 __ops_print_seckey_verbose(const __ops_content_tag_t type, 495 const __ops_seckey_t *seckey) 496 { 497 printf("------- SECRET KEY or ENCRYPTED SECRET KEY ------\n"); 498 print_tagname((type == OPS_PTAG_CT_SECRET_KEY) ? 499 "SECRET_KEY" : 500 "ENCRYPTED_SECRET_KEY"); 501 /* __ops_print_pubkey(key); */ 502 printf("S2K Usage: %d\n", seckey->s2k_usage); 503 if (seckey->s2k_usage != OPS_S2KU_NONE) { 504 printf("S2K Specifier: %d\n", seckey->s2k_specifier); 505 printf("Symmetric algorithm: %d (%s)\n", seckey->alg, 506 __ops_show_symm_alg(seckey->alg)); 507 printf("Hash algorithm: %d (%s)\n", seckey->hash_alg, 508 __ops_show_hash_alg(seckey->hash_alg)); 509 if (seckey->s2k_specifier != OPS_S2KS_SIMPLE) { 510 print_hexdump("Salt", seckey->salt, 511 sizeof(seckey->salt)); 512 } 513 if (seckey->s2k_specifier == OPS_S2KS_ITERATED_AND_SALTED) { 514 printf("Octet count: %d\n", seckey->octetc); 515 } 516 print_hexdump("IV", seckey->iv, __ops_block_size(seckey->alg)); 517 } 518 /* no more set if encrypted */ 519 if (type == OPS_PTAG_CT_ENCRYPTED_SECRET_KEY) { 520 return; 521 } 522 switch (seckey->pubkey.alg) { 523 case OPS_PKA_RSA: 524 print_bn("d", seckey->key.rsa.d); 525 print_bn("p", seckey->key.rsa.p); 526 print_bn("q", seckey->key.rsa.q); 527 print_bn("u", seckey->key.rsa.u); 528 break; 529 530 case OPS_PKA_DSA: 531 print_bn("x", seckey->key.dsa.x); 532 break; 533 534 default: 535 (void) fprintf(stderr, 536 "__ops_print_seckey_verbose: unusual algorithm\n"); 537 } 538 if (seckey->s2k_usage == OPS_S2KU_ENCRYPTED_AND_HASHED) { 539 print_hexdump("Checkhash", seckey->checkhash, 540 OPS_CHECKHASH_SIZE); 541 } else { 542 printf("Checksum: %04x\n", seckey->checksum); 543 } 544 printf("------- end of SECRET KEY or ENCRYPTED SECRET KEY ------\n"); 545 } 546 547 548 /** 549 \ingroup Core_Print 550 \param tag 551 \param key 552 */ 553 static void 554 __ops_print_pk_sesskey(__ops_content_tag_t tag, 555 const __ops_pk_sesskey_t * key) 556 { 557 print_tagname((tag == OPS_PTAG_CT_PK_SESSION_KEY) ? 558 "PUBLIC KEY SESSION KEY" : 559 "ENCRYPTED PUBLIC KEY SESSION KEY"); 560 printf("Version: %d\n", key->version); 561 print_hexdump("Key ID", key->key_id, sizeof(key->key_id)); 562 printf("Algorithm: %d (%s)\n", key->alg, 563 __ops_show_pka(key->alg)); 564 switch (key->alg) { 565 case OPS_PKA_RSA: 566 print_bn("encrypted_m", key->parameters.rsa.encrypted_m); 567 break; 568 569 case OPS_PKA_ELGAMAL: 570 print_bn("g_to_k", key->parameters.elgamal.g_to_k); 571 print_bn("encrypted_m", key->parameters.elgamal.encrypted_m); 572 break; 573 574 default: 575 (void) fprintf(stderr, 576 "__ops_print_pk_sesskey: unusual algorithm\n"); 577 } 578 if (tag == OPS_PTAG_CT_PK_SESSION_KEY) { 579 printf("Symmetric algorithm: %d (%s)\n", key->symm_alg, 580 __ops_show_symm_alg(key->symm_alg)); 581 print_hexdump("Key", key->key, __ops_key_size(key->symm_alg)); 582 printf("Checksum: %04x\n", key->checksum); 583 } 584 } 585 586 static void 587 start_subpacket(int type) 588 { 589 indent++; 590 print_indent(); 591 printf("-- %s (type 0x%02x)\n", 592 __ops_show_ss_type(type), 593 type - OPS_PTAG_SIGNATURE_SUBPACKET_BASE); 594 } 595 596 static void 597 end_subpacket(void) 598 { 599 indent--; 600 } 601 602 /** 603 \ingroup Core_Print 604 \param contents 605 */ 606 int 607 __ops_print_packet(const __ops_packet_t * pkt) 608 { 609 const __ops_parser_content_union_t *content = &pkt->u; 610 __ops_text_t *text; 611 static bool unarmoured; 612 const char *str; 613 614 if (unarmoured && pkt->tag != OPS_PTAG_CT_UNARMOURED_TEXT) { 615 unarmoured = false; 616 puts("UNARMOURED TEXT ends"); 617 } 618 if (pkt->tag == OPS_PARSER_PTAG) { 619 printf("=> OPS_PARSER_PTAG: %s\n", 620 __ops_show_packet_tag(content->ptag.type)); 621 } else { 622 printf("=> %s\n", __ops_show_packet_tag(pkt->tag)); 623 } 624 625 switch (pkt->tag) { 626 case OPS_PARSER_ERROR: 627 printf("parse error: %s\n", content->error.error); 628 break; 629 630 case OPS_PARSER_ERRCODE: 631 printf("parse error: %s\n", 632 __ops_errcode(content->errcode.errcode)); 633 break; 634 635 case OPS_PARSER_PACKET_END: 636 print_packet_hex(&content->packet); 637 break; 638 639 case OPS_PARSER_PTAG: 640 if (content->ptag.type == OPS_PTAG_CT_PUBLIC_KEY) { 641 indent = 0; 642 printf("\n*** NEXT KEY ***\n"); 643 } 644 printf("\n"); 645 print_indent(); 646 printf("==== ptag new_format=%d type=%d length_type=%d" 647 " length=0x%x (%d) position=0x%x (%d)\n", 648 content->ptag.new_format, 649 content->ptag.type, content->ptag.length_type, 650 content->ptag.length, content->ptag.length, 651 content->ptag.position, content->ptag.position); 652 print_tagname(__ops_show_packet_tag(content->ptag.type)); 653 break; 654 655 case OPS_PTAG_CT_SE_DATA_HEADER: 656 print_tagname("SYMMETRIC ENCRYPTED DATA"); 657 break; 658 659 case OPS_PTAG_CT_SE_IP_DATA_HEADER: 660 print_tagname( 661 "SYMMETRIC ENCRYPTED INTEGRITY PROTECTED DATA HEADER"); 662 printf("Version: %d\n", content->se_ip_data_header.version); 663 break; 664 665 case OPS_PTAG_CT_SE_IP_DATA_BODY: 666 print_tagname( 667 "SYMMETRIC ENCRYPTED INTEGRITY PROTECTED DATA BODY"); 668 printf(" data body length=%d\n", 669 content->se_data_body.length); 670 printf(" data="); 671 hexdump(content->se_data_body.data, 672 content->se_data_body.length, ""); 673 printf("\n"); 674 break; 675 676 case OPS_PTAG_CT_PUBLIC_KEY: 677 case OPS_PTAG_CT_PUBLIC_SUBKEY: 678 print_tagname((pkt->tag == OPS_PTAG_CT_PUBLIC_KEY) ? 679 "PUBLIC KEY" : 680 "PUBLIC SUBKEY"); 681 __ops_print_pubkey(&content->pubkey); 682 break; 683 684 case OPS_PTAG_CT_TRUST: 685 print_tagname("TRUST"); 686 print_data("Trust", &content->trust.data); 687 break; 688 689 case OPS_PTAG_CT_USER_ID: 690 /* XXX: how do we print UTF-8? */ 691 print_tagname("USER ID"); 692 print_utf8_string("user_id", content->user_id.user_id); 693 break; 694 695 case OPS_PTAG_CT_SIGNATURE: 696 print_tagname("SIGNATURE"); 697 print_indent(); 698 print_unsigned_int("Signature Version", 699 (unsigned)content->sig.info.version); 700 if (content->sig.info.birthtime_set) { 701 print_time("Signature Creation Time", 702 content->sig.info.birthtime); 703 } 704 705 print_string_and_value("Signature Type", 706 __ops_show_sig_type(content->sig.info.type), 707 content->sig.info.type); 708 709 if (content->sig.info.signer_id_set) { 710 print_hexdump_data("Signer ID", 711 content->sig.info.signer_id, 712 sizeof(content->sig.info.signer_id)); 713 } 714 715 print_string_and_value("Public Key Algorithm", 716 __ops_show_pka(content->sig.info.key_alg), 717 content->sig.info.key_alg); 718 print_string_and_value("Hash Algorithm", 719 __ops_show_hash_alg(content->sig.info.hash_alg), 720 content->sig.info.hash_alg); 721 722 print_unsigned_int("Hashed data len", 723 content->sig.info.v4_hashed_data_length); 724 725 print_indent(); 726 print_hexdump_data("hash2", &content->sig.hash2[0], 2); 727 728 switch (content->sig.info.key_alg) { 729 case OPS_PKA_RSA: 730 case OPS_PKA_RSA_SIGN_ONLY: 731 print_bn("sig", content->sig.info.sig.rsa.sig); 732 break; 733 734 case OPS_PKA_DSA: 735 print_bn("r", content->sig.info.sig.dsa.r); 736 print_bn("s", content->sig.info.sig.dsa.s); 737 break; 738 739 case OPS_PKA_ELGAMAL_ENCRYPT_OR_SIGN: 740 print_bn("r", content->sig.info.sig.elgamal.r); 741 print_bn("s", content->sig.info.sig.elgamal.s); 742 break; 743 744 default: 745 (void) fprintf(stderr, 746 "__ops_print_packet: Unusual algorithm\n"); 747 return 0; 748 } 749 750 if (content->sig.hash) 751 printf("data hash is set\n"); 752 753 break; 754 755 case OPS_PTAG_CT_COMPRESSED: 756 print_tagname("COMPRESSED"); 757 print_unsigned_int("Compressed Data Type", 758 (unsigned)content->compressed.type); 759 break; 760 761 case OPS_PTAG_CT_ONE_PASS_SIGNATURE: 762 print_tagname("ONE PASS SIGNATURE"); 763 764 print_unsigned_int("Version", 765 (unsigned)content->one_pass_sig.version); 766 print_string_and_value("Signature Type", 767 __ops_show_sig_type(content->one_pass_sig.sig_type), 768 content->one_pass_sig.sig_type); 769 print_string_and_value("Hash Algorithm", 770 __ops_show_hash_alg(content->one_pass_sig.hash_alg), 771 content->one_pass_sig.hash_alg); 772 print_string_and_value("Public Key Algorithm", 773 __ops_show_pka(content->one_pass_sig.key_alg), 774 content->one_pass_sig.key_alg); 775 print_hexdump_data("Signer ID", 776 content->one_pass_sig.keyid, 777 sizeof(content->one_pass_sig.keyid)); 778 779 print_unsigned_int("Nested", 780 content->one_pass_sig.nested); 781 break; 782 783 case OPS_PTAG_CT_USER_ATTRIBUTE: 784 print_tagname("USER ATTRIBUTE"); 785 print_hexdump("User Attribute", 786 content->user_attribute.data.contents, 787 content->user_attribute.data.len); 788 break; 789 790 case OPS_PTAG_RAW_SS: 791 if (pkt->critical) { 792 (void) fprintf(stderr, "contents are critical\n"); 793 return 0; 794 } 795 start_subpacket(pkt->tag); 796 print_unsigned_int("Raw Signature Subpacket: tag", 797 (unsigned)(content->ss_raw.tag - 798 OPS_PTAG_SIGNATURE_SUBPACKET_BASE)); 799 print_hexdump("Raw Data", 800 content->ss_raw.raw, 801 content->ss_raw.length); 802 break; 803 804 case OPS_PTAG_SS_CREATION_TIME: 805 start_subpacket(pkt->tag); 806 print_time("Signature Creation Time", content->ss_time.time); 807 end_subpacket(); 808 break; 809 810 case OPS_PTAG_SS_EXPIRATION_TIME: 811 start_subpacket(pkt->tag); 812 print_duration("Signature Expiration Time", 813 content->ss_time.time); 814 end_subpacket(); 815 break; 816 817 case OPS_PTAG_SS_KEY_EXPIRATION_TIME: 818 start_subpacket(pkt->tag); 819 print_duration("Key Expiration Time", content->ss_time.time); 820 end_subpacket(); 821 break; 822 823 case OPS_PTAG_SS_TRUST: 824 start_subpacket(pkt->tag); 825 print_string("Trust Signature", ""); 826 print_unsigned_int("Level", 827 (unsigned)content->ss_trust.level); 828 print_unsigned_int("Amount", 829 (unsigned)content->ss_trust.amount); 830 end_subpacket(); 831 break; 832 833 case OPS_PTAG_SS_REVOCABLE: 834 start_subpacket(pkt->tag); 835 print_boolean("Revocable", content->ss_revocable.revocable); 836 end_subpacket(); 837 break; 838 839 case OPS_PTAG_SS_REVOCATION_KEY: 840 start_subpacket(pkt->tag); 841 /* not yet tested */ 842 printf(" revocation key: class=0x%x", 843 content->ss_revocation_key.class); 844 if (content->ss_revocation_key.class & 0x40) 845 printf(" (sensitive)"); 846 printf(", algid=0x%x", 847 content->ss_revocation_key.algid); 848 printf(", fingerprint="); 849 hexdump(content->ss_revocation_key.fingerprint, 20, ""); 850 printf("\n"); 851 end_subpacket(); 852 break; 853 854 case OPS_PTAG_SS_ISSUER_KEY_ID: 855 start_subpacket(pkt->tag); 856 print_hexdump("Issuer Key Id", 857 &content->ss_issuer_key_id.key_id[0], 858 sizeof(content->ss_issuer_key_id.key_id)); 859 end_subpacket(); 860 break; 861 862 case OPS_PTAG_SS_PREFERRED_SKA: 863 start_subpacket(pkt->tag); 864 print_data("Preferred Symmetric Algorithms", 865 &content->ss_skapref.data); 866 867 text = __ops_showall_ss_skapref(content->ss_skapref); 868 print_text_breakdown(text); 869 __ops_text_free(text); 870 871 end_subpacket(); 872 break; 873 874 case OPS_PTAG_SS_PRIMARY_USER_ID: 875 start_subpacket(pkt->tag); 876 print_boolean("Primary User ID", 877 content->ss_primary_user_id.primary_user_id); 878 end_subpacket(); 879 break; 880 881 case OPS_PTAG_SS_PREFERRED_HASH: 882 start_subpacket(pkt->tag); 883 print_data("Preferred Hash Algorithms", 884 &content->ss_hashpref.data); 885 886 text = __ops_showall_ss_hashpref(content->ss_hashpref); 887 print_text_breakdown(text); 888 __ops_text_free(text); 889 end_subpacket(); 890 break; 891 892 case OPS_PTAG_SS_PREFERRED_COMPRESSION: 893 start_subpacket(pkt->tag); 894 print_data("Preferred Compression Algorithms", 895 &content->ss_zpref.data); 896 897 text = __ops_showall_ss_zpref(content->ss_zpref); 898 print_text_breakdown(text); 899 __ops_text_free(text); 900 end_subpacket(); 901 break; 902 903 case OPS_PTAG_SS_KEY_FLAGS: 904 start_subpacket(pkt->tag); 905 print_data("Key Flags", &content->ss_key_flags.data); 906 907 text = __ops_showall_ss_key_flags(content->ss_key_flags); 908 print_text_breakdown(text); 909 __ops_text_free(text); 910 911 end_subpacket(); 912 break; 913 914 case OPS_PTAG_SS_KEY_SERVER_PREFS: 915 start_subpacket(pkt->tag); 916 print_data("Key Server Preferences", 917 &content->ss_key_server_prefs.data); 918 919 text = __ops_showall_ss_key_server_prefs( 920 content->ss_key_server_prefs); 921 print_text_breakdown(text); 922 __ops_text_free(text); 923 924 end_subpacket(); 925 break; 926 927 case OPS_PTAG_SS_FEATURES: 928 start_subpacket(pkt->tag); 929 print_data("Features", 930 &content->ss_features.data); 931 932 text = __ops_showall_ss_features(content->ss_features); 933 print_text_breakdown(text); 934 __ops_text_free(text); 935 936 end_subpacket(); 937 break; 938 939 case OPS_PTAG_SS_NOTATION_DATA: 940 start_subpacket(pkt->tag); 941 print_indent(); 942 printf("Notation Data:\n"); 943 944 indent++; 945 print_data("Flags", &content->ss_notation_data.flags); 946 text = __ops_showall_ss_notation_data_flags( 947 content->ss_notation_data); 948 print_text_breakdown(text); 949 __ops_text_free(text); 950 951 /* xxx - TODO: print out UTF - rachel */ 952 953 print_data("Name", &content->ss_notation_data.name); 954 955 print_data("Value", &content->ss_notation_data.value); 956 957 indent--; 958 end_subpacket(); 959 break; 960 961 case OPS_PTAG_SS_REGEXP: 962 start_subpacket(pkt->tag); 963 print_hexdump("Regular Expression", 964 (unsigned char *) content->ss_regexp.regexp, 965 strlen(content->ss_regexp.regexp)); 966 print_string(NULL, content->ss_regexp.regexp); 967 end_subpacket(); 968 break; 969 970 case OPS_PTAG_SS_POLICY_URI: 971 start_subpacket(pkt->tag); 972 print_string("Policy URL", content->ss_policy.url); 973 end_subpacket(); 974 break; 975 976 case OPS_PTAG_SS_SIGNERS_USER_ID: 977 start_subpacket(pkt->tag); 978 print_utf8_string("Signer's User ID", 979 content->ss_signer.user_id); 980 end_subpacket(); 981 break; 982 983 case OPS_PTAG_SS_PREFERRED_KEY_SERVER: 984 start_subpacket(pkt->tag); 985 print_string("Preferred Key Server", 986 content->ss_pref_keyserv.name); 987 end_subpacket(); 988 break; 989 990 case OPS_PTAG_SS_EMBEDDED_SIGNATURE: 991 start_subpacket(pkt->tag); 992 end_subpacket();/* \todo print out contents? */ 993 break; 994 995 case OPS_PTAG_SS_USERDEFINED00: 996 case OPS_PTAG_SS_USERDEFINED01: 997 case OPS_PTAG_SS_USERDEFINED02: 998 case OPS_PTAG_SS_USERDEFINED03: 999 case OPS_PTAG_SS_USERDEFINED04: 1000 case OPS_PTAG_SS_USERDEFINED05: 1001 case OPS_PTAG_SS_USERDEFINED06: 1002 case OPS_PTAG_SS_USERDEFINED07: 1003 case OPS_PTAG_SS_USERDEFINED08: 1004 case OPS_PTAG_SS_USERDEFINED09: 1005 case OPS_PTAG_SS_USERDEFINED10: 1006 start_subpacket(pkt->tag); 1007 print_hexdump("Internal or user-defined", 1008 content->ss_userdefined.data.contents, 1009 content->ss_userdefined.data.len); 1010 end_subpacket(); 1011 break; 1012 1013 case OPS_PTAG_SS_RESERVED: 1014 start_subpacket(pkt->tag); 1015 print_hexdump("Reserved", 1016 content->ss_userdefined.data.contents, 1017 content->ss_userdefined.data.len); 1018 end_subpacket(); 1019 break; 1020 1021 case OPS_PTAG_SS_REVOCATION_REASON: 1022 start_subpacket(pkt->tag); 1023 print_hexdump("Revocation Reason", 1024 &content->ss_revocation.code, 1025 1); 1026 str = __ops_show_ss_rr_code(content->ss_revocation.code); 1027 print_string(NULL, str); 1028 /* xxx - todo : output text as UTF-8 string */ 1029 end_subpacket(); 1030 break; 1031 1032 case OPS_PTAG_CT_LITERAL_DATA_HEADER: 1033 print_tagname("LITERAL DATA HEADER"); 1034 printf(" literal data header format=%c filename='%s'\n", 1035 content->litdata_header.format, 1036 content->litdata_header.filename); 1037 showtime(" modification time", 1038 content->litdata_header.mtime); 1039 printf("\n"); 1040 break; 1041 1042 case OPS_PTAG_CT_LITERAL_DATA_BODY: 1043 print_tagname("LITERAL DATA BODY"); 1044 printf(" literal data body length=%d\n", 1045 content->litdata_body.length); 1046 printf(" data="); 1047 print_escaped(content->litdata_body.data, 1048 content->litdata_body.length); 1049 printf("\n"); 1050 break; 1051 1052 case OPS_PTAG_CT_SIGNATURE_HEADER: 1053 print_tagname("SIGNATURE"); 1054 print_indent(); 1055 print_unsigned_int("Signature Version", 1056 (unsigned)content->sig.info.version); 1057 if (content->sig.info.birthtime_set) 1058 print_time("Signature Creation Time", 1059 content->sig.info.birthtime); 1060 1061 print_string_and_value("Signature Type", 1062 __ops_show_sig_type(content->sig.info.type), 1063 content->sig.info.type); 1064 1065 if (content->sig.info.signer_id_set) 1066 print_hexdump_data("Signer ID", 1067 content->sig.info.signer_id, 1068 sizeof(content->sig.info.signer_id)); 1069 1070 print_string_and_value("Public Key Algorithm", 1071 __ops_show_pka(content->sig.info.key_alg), 1072 content->sig.info.key_alg); 1073 print_string_and_value("Hash Algorithm", 1074 __ops_show_hash_alg(content->sig.info.hash_alg), 1075 content->sig.info.hash_alg); 1076 1077 break; 1078 1079 case OPS_PTAG_CT_SIGNATURE_FOOTER: 1080 print_indent(); 1081 print_hexdump_data("hash2", &content->sig.hash2[0], 2); 1082 1083 switch (content->sig.info.key_alg) { 1084 case OPS_PKA_RSA: 1085 print_bn("sig", content->sig.info.sig.rsa.sig); 1086 break; 1087 1088 case OPS_PKA_DSA: 1089 print_bn("r", content->sig.info.sig.dsa.r); 1090 print_bn("s", content->sig.info.sig.dsa.s); 1091 break; 1092 1093 case OPS_PKA_ELGAMAL_ENCRYPT_OR_SIGN: 1094 print_bn("r", content->sig.info.sig.elgamal.r); 1095 print_bn("s", content->sig.info.sig.elgamal.s); 1096 break; 1097 1098 case OPS_PKA_PRIVATE00: 1099 case OPS_PKA_PRIVATE01: 1100 case OPS_PKA_PRIVATE02: 1101 case OPS_PKA_PRIVATE03: 1102 case OPS_PKA_PRIVATE04: 1103 case OPS_PKA_PRIVATE05: 1104 case OPS_PKA_PRIVATE06: 1105 case OPS_PKA_PRIVATE07: 1106 case OPS_PKA_PRIVATE08: 1107 case OPS_PKA_PRIVATE09: 1108 case OPS_PKA_PRIVATE10: 1109 print_data("Private/Experimental", 1110 &content->sig.info.sig.unknown.data); 1111 break; 1112 1113 default: 1114 (void) fprintf(stderr, 1115 "__ops_print_packet: Unusual key algorithm\n"); 1116 return 0; 1117 } 1118 break; 1119 1120 case OPS_PARSER_CMD_GET_SK_PASSPHRASE: 1121 print_tagname("OPS_PARSER_CMD_GET_SK_PASSPHRASE"); 1122 break; 1123 1124 case OPS_PTAG_CT_SECRET_KEY: 1125 print_tagname("OPS_PTAG_CT_SECRET_KEY"); 1126 __ops_print_seckey_verbose(pkt->tag, &content->seckey); 1127 break; 1128 1129 case OPS_PTAG_CT_ENCRYPTED_SECRET_KEY: 1130 print_tagname("OPS_PTAG_CT_ENCRYPTED_SECRET_KEY"); 1131 __ops_print_seckey_verbose(pkt->tag, &content->seckey); 1132 break; 1133 1134 case OPS_PTAG_CT_ARMOUR_HEADER: 1135 print_tagname("ARMOUR HEADER"); 1136 print_string("type", content->armour_header.type); 1137 break; 1138 1139 case OPS_PTAG_CT_SIGNED_CLEARTEXT_HEADER: 1140 print_tagname("SIGNED CLEARTEXT HEADER"); 1141 print_headers(&content->cleartext_head.headers); 1142 break; 1143 1144 case OPS_PTAG_CT_SIGNED_CLEARTEXT_BODY: 1145 print_tagname("SIGNED CLEARTEXT BODY"); 1146 print_block("signed cleartext", content->cleartext_body.data, 1147 content->cleartext_body.length); 1148 break; 1149 1150 case OPS_PTAG_CT_SIGNED_CLEARTEXT_TRAILER: 1151 print_tagname("SIGNED CLEARTEXT TRAILER"); 1152 printf("hash algorithm: %d\n", 1153 content->cleartext_trailer.hash->alg); 1154 printf("\n"); 1155 break; 1156 1157 case OPS_PTAG_CT_UNARMOURED_TEXT: 1158 if (!unarmoured) { 1159 print_tagname("UNARMOURED TEXT"); 1160 unarmoured = true; 1161 } 1162 putchar('['); 1163 print_escaped(content->unarmoured_text.data, 1164 content->unarmoured_text.length); 1165 putchar(']'); 1166 break; 1167 1168 case OPS_PTAG_CT_ARMOUR_TRAILER: 1169 print_tagname("ARMOUR TRAILER"); 1170 print_string("type", content->armour_header.type); 1171 break; 1172 1173 case OPS_PTAG_CT_PK_SESSION_KEY: 1174 case OPS_PTAG_CT_ENCRYPTED_PK_SESSION_KEY: 1175 __ops_print_pk_sesskey(pkt->tag, &content->pk_sesskey); 1176 break; 1177 1178 case OPS_PARSER_CMD_GET_SECRET_KEY: 1179 __ops_print_pk_sesskey(OPS_PTAG_CT_ENCRYPTED_PK_SESSION_KEY, 1180 content->get_seckey.pk_sesskey); 1181 break; 1182 1183 default: 1184 print_tagname("UNKNOWN PACKET TYPE"); 1185 fprintf(stderr, "__ops_print_packet: unknown tag=%d (0x%x)\n", 1186 pkt->tag, pkt->tag); 1187 exit(EXIT_FAILURE); 1188 } 1189 return 1; 1190 } 1191 1192 static __ops_parse_cb_return_t 1193 cb_list_packets(const __ops_packet_t * pkt, __ops_callback_data_t * cbinfo) 1194 { 1195 __OPS_USED(cbinfo); 1196 1197 __ops_print_packet(pkt); 1198 return OPS_RELEASE_MEMORY; 1199 } 1200 1201 /** 1202 \ingroup Core_Print 1203 \param filename 1204 \param armour 1205 \param keyring 1206 \param cb_get_passphrase 1207 */ 1208 void 1209 __ops_list_packets(char *filename, 1210 bool armour, 1211 __ops_keyring_t *keyring, 1212 __ops_parse_cb_t *cb_get_passphrase) 1213 { 1214 __ops_parseinfo_t *pinfo = NULL; 1215 const bool accumulate = true; 1216 int fd = 0; 1217 1218 fd = __ops_setup_file_read(&pinfo, filename, NULL, cb_list_packets, 1219 accumulate); 1220 __ops_parse_options(pinfo, OPS_PTAG_SS_ALL, OPS_PARSE_PARSED); 1221 pinfo->cryptinfo.keyring = keyring; 1222 pinfo->cryptinfo.cb_get_passphrase = cb_get_passphrase; 1223 if (armour) { 1224 __ops_reader_push_dearmour(pinfo); 1225 } 1226 __ops_parse(pinfo, 1); 1227 __ops_teardown_file_read(pinfo, fd); 1228 } 1229