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