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.20 2009/11/19 21:56:00 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; 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=%u, 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("%u\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 /* return the hexdump as a string */ 400 static char * 401 strhexdump(char *dest, const unsigned char *src, size_t length, const char *sep) 402 { 403 unsigned i; 404 int n; 405 406 for (n = 0, i = 0 ; i < length ; i += 2) { 407 n += snprintf(&dest[n], 3, "%02x", *src++); 408 n += snprintf(&dest[n], 10, "%02x%s", *src++, sep); 409 } 410 return dest; 411 } 412 413 /* return the time as a string */ 414 static char * 415 ptimestr(char *dest, size_t size, time_t t) 416 { 417 struct tm *tm; 418 419 tm = gmtime(&t); 420 (void) snprintf(dest, size, "%04d-%02d-%02d", 421 tm->tm_year + 1900, 422 tm->tm_mon + 1, 423 tm->tm_mday); 424 return dest; 425 } 426 427 #ifndef KB 428 #define KB(x) ((x) * 1024) 429 #endif 430 431 /* print into a string (malloc'ed) the pubkeydata */ 432 int 433 __ops_sprint_pubkeydata(const __ops_key_t *key, char **buf) 434 { 435 unsigned i; 436 char uidbuf[KB(128)]; 437 char keyid[OPS_KEY_ID_SIZE * 3]; 438 char fp[(OPS_FINGERPRINT_SIZE * 3) + 1]; 439 char t[32]; 440 int n; 441 442 for (i = 0, n = 0; i < key->uidc; i++) { 443 n += snprintf(&uidbuf[n], sizeof(uidbuf) - n, 444 "uid %s\n", key->uids[i].userid); 445 } 446 return asprintf(buf, "pub %d/%s %s %s\nKey fingerprint: %s\n%s", 447 numkeybits(&key->key.pubkey), 448 __ops_show_pka(key->key.pubkey.alg), 449 strhexdump(keyid, key->key_id, OPS_KEY_ID_SIZE, ""), 450 ptimestr(t, sizeof(t), key->key.pubkey.birthtime), 451 strhexdump(fp, key->fingerprint.fingerprint, OPS_FINGERPRINT_SIZE, " "), 452 uidbuf); 453 } 454 455 /** 456 \ingroup Core_Print 457 \param pubkey 458 */ 459 void 460 __ops_print_pubkey(const __ops_pubkey_t *pubkey) 461 { 462 printf("------- PUBLIC KEY ------\n"); 463 print_uint("Version", (unsigned)pubkey->version); 464 print_time("Creation Time", pubkey->birthtime); 465 if (pubkey->version == OPS_V3) { 466 print_uint("Days Valid", pubkey->days_valid); 467 } 468 print_string_and_value("Algorithm", __ops_show_pka(pubkey->alg), 469 pubkey->alg); 470 switch (pubkey->alg) { 471 case OPS_PKA_DSA: 472 print_bn("p", pubkey->key.dsa.p); 473 print_bn("q", pubkey->key.dsa.q); 474 print_bn("g", pubkey->key.dsa.g); 475 print_bn("y", pubkey->key.dsa.y); 476 break; 477 478 case OPS_PKA_RSA: 479 case OPS_PKA_RSA_ENCRYPT_ONLY: 480 case OPS_PKA_RSA_SIGN_ONLY: 481 print_bn("n", pubkey->key.rsa.n); 482 print_bn("e", pubkey->key.rsa.e); 483 break; 484 485 case OPS_PKA_ELGAMAL: 486 case OPS_PKA_ELGAMAL_ENCRYPT_OR_SIGN: 487 print_bn("p", pubkey->key.elgamal.p); 488 print_bn("g", pubkey->key.elgamal.g); 489 print_bn("y", pubkey->key.elgamal.y); 490 break; 491 492 default: 493 (void) fprintf(stderr, 494 "__ops_print_pubkey: Unusual algorithm\n"); 495 } 496 497 printf("------- end of PUBLIC KEY ------\n"); 498 } 499 500 /** 501 \ingroup Core_Print 502 503 Prints a secret key 504 505 \param key Ptr to public key 506 */ 507 508 void 509 __ops_print_seckeydata(__ops_io_t *io, const __ops_key_t *key) 510 { 511 (void) fprintf(io->res, "sec "); 512 __ops_show_pka(key->key.pubkey.alg); /* XXX - redirect to io */ 513 (void) fprintf(io->res, " "); 514 hexdump(io->res, key->key_id, OPS_KEY_ID_SIZE, ""); 515 (void) fprintf(io->res, " "); 516 ptime(io->res, key->key.pubkey.birthtime); 517 (void) fprintf(io->res, " "); 518 if (key->uidc == 1) { 519 /* print on same line as other info */ 520 (void) fprintf(io->res, "%s\n", key->uids[0].userid); 521 } else { 522 /* print all uids on separate line */ 523 unsigned int i; 524 525 (void) fprintf(io->res, "\n"); 526 for (i = 0; i < key->uidc; i++) { 527 (void) fprintf(io->res, "uid %s\n", 528 key->uids[i].userid); 529 } 530 } 531 } 532 533 /** 534 \ingroup Core_Print 535 \param type 536 \param seckey 537 */ 538 static void 539 __ops_print_seckey_verbose(const __ops_content_tag_t type, 540 const __ops_seckey_t *seckey) 541 { 542 printf("------- SECRET KEY or ENCRYPTED SECRET KEY ------\n"); 543 print_tagname((type == OPS_PTAG_CT_SECRET_KEY) ? 544 "SECRET_KEY" : 545 "ENCRYPTED_SECRET_KEY"); 546 /* __ops_print_pubkey(key); */ 547 printf("S2K Usage: %d\n", seckey->s2k_usage); 548 if (seckey->s2k_usage != OPS_S2KU_NONE) { 549 printf("S2K Specifier: %d\n", seckey->s2k_specifier); 550 printf("Symmetric algorithm: %d (%s)\n", seckey->alg, 551 __ops_show_symm_alg(seckey->alg)); 552 printf("Hash algorithm: %d (%s)\n", seckey->hash_alg, 553 __ops_show_hash_alg((unsigned char)seckey->hash_alg)); 554 if (seckey->s2k_specifier != OPS_S2KS_SIMPLE) { 555 print_hexdump("Salt", seckey->salt, 556 sizeof(seckey->salt)); 557 } 558 if (seckey->s2k_specifier == OPS_S2KS_ITERATED_AND_SALTED) { 559 printf("Octet count: %u\n", seckey->octetc); 560 } 561 print_hexdump("IV", seckey->iv, __ops_block_size(seckey->alg)); 562 } 563 /* no more set if encrypted */ 564 if (type == OPS_PTAG_CT_ENCRYPTED_SECRET_KEY) { 565 return; 566 } 567 switch (seckey->pubkey.alg) { 568 case OPS_PKA_RSA: 569 print_bn("d", seckey->key.rsa.d); 570 print_bn("p", seckey->key.rsa.p); 571 print_bn("q", seckey->key.rsa.q); 572 print_bn("u", seckey->key.rsa.u); 573 break; 574 575 case OPS_PKA_DSA: 576 print_bn("x", seckey->key.dsa.x); 577 break; 578 579 default: 580 (void) fprintf(stderr, 581 "__ops_print_seckey_verbose: unusual algorithm\n"); 582 } 583 if (seckey->s2k_usage == OPS_S2KU_ENCRYPTED_AND_HASHED) { 584 print_hexdump("Checkhash", seckey->checkhash, 585 OPS_CHECKHASH_SIZE); 586 } else { 587 printf("Checksum: %04x\n", seckey->checksum); 588 } 589 printf("------- end of SECRET KEY or ENCRYPTED SECRET KEY ------\n"); 590 } 591 592 593 /** 594 \ingroup Core_Print 595 \param tag 596 \param key 597 */ 598 static void 599 __ops_print_pk_sesskey(__ops_content_tag_t tag, 600 const __ops_pk_sesskey_t * key) 601 { 602 print_tagname((tag == OPS_PTAG_CT_PK_SESSION_KEY) ? 603 "PUBLIC KEY SESSION KEY" : 604 "ENCRYPTED PUBLIC KEY SESSION KEY"); 605 printf("Version: %d\n", key->version); 606 print_hexdump("Key ID", key->key_id, sizeof(key->key_id)); 607 printf("Algorithm: %d (%s)\n", key->alg, 608 __ops_show_pka(key->alg)); 609 switch (key->alg) { 610 case OPS_PKA_RSA: 611 print_bn("encrypted_m", key->params.rsa.encrypted_m); 612 break; 613 614 case OPS_PKA_ELGAMAL: 615 print_bn("g_to_k", key->params.elgamal.g_to_k); 616 print_bn("encrypted_m", key->params.elgamal.encrypted_m); 617 break; 618 619 default: 620 (void) fprintf(stderr, 621 "__ops_print_pk_sesskey: unusual algorithm\n"); 622 } 623 if (tag == OPS_PTAG_CT_PK_SESSION_KEY) { 624 printf("Symmetric algorithm: %d (%s)\n", key->symm_alg, 625 __ops_show_symm_alg(key->symm_alg)); 626 print_hexdump("Key", key->key, __ops_key_size(key->symm_alg)); 627 printf("Checksum: %04x\n", key->checksum); 628 } 629 } 630 631 static void 632 start_subpacket(int type) 633 { 634 indent++; 635 print_indent(); 636 printf("-- %s (type 0x%02x)\n", 637 __ops_show_ss_type((__ops_ss_type_t)type), 638 type - OPS_PTAG_SIG_SUBPKT_BASE); 639 } 640 641 static void 642 end_subpacket(void) 643 { 644 indent--; 645 } 646 647 /** 648 \ingroup Core_Print 649 \param contents 650 */ 651 int 652 __ops_print_packet(const __ops_packet_t *pkt) 653 { 654 const __ops_contents_t *content = &pkt->u; 655 static unsigned unarmoured; 656 __ops_text_t *text; 657 const char *str; 658 659 if (unarmoured && pkt->tag != OPS_PTAG_CT_UNARMOURED_TEXT) { 660 unarmoured = 0; 661 puts("UNARMOURED TEXT ends"); 662 } 663 if (pkt->tag == OPS_PARSER_PTAG) { 664 printf("=> OPS_PARSER_PTAG: %s\n", 665 __ops_show_packet_tag((__ops_packet_tag_t)content->ptag.type)); 666 } else { 667 printf("=> %s\n", __ops_show_packet_tag(pkt->tag)); 668 } 669 670 switch (pkt->tag) { 671 case OPS_PARSER_ERROR: 672 printf("parse error: %s\n", content->error.error); 673 break; 674 675 case OPS_PARSER_ERRCODE: 676 printf("parse error: %s\n", 677 __ops_errcode(content->errcode.errcode)); 678 break; 679 680 case OPS_PARSER_PACKET_END: 681 print_packet_hex(&content->packet); 682 break; 683 684 case OPS_PARSER_PTAG: 685 if (content->ptag.type == OPS_PTAG_CT_PUBLIC_KEY) { 686 indent = 0; 687 printf("\n*** NEXT KEY ***\n"); 688 } 689 printf("\n"); 690 print_indent(); 691 printf("==== ptag new_format=%u type=%u length_type=%d" 692 " length=0x%x (%u) position=0x%x (%u)\n", 693 content->ptag.new_format, 694 content->ptag.type, content->ptag.length_type, 695 content->ptag.length, content->ptag.length, 696 content->ptag.position, content->ptag.position); 697 print_tagname(__ops_show_packet_tag((__ops_packet_tag_t)content->ptag.type)); 698 break; 699 700 case OPS_PTAG_CT_SE_DATA_HEADER: 701 print_tagname("SYMMETRIC ENCRYPTED DATA"); 702 break; 703 704 case OPS_PTAG_CT_SE_IP_DATA_HEADER: 705 print_tagname( 706 "SYMMETRIC ENCRYPTED INTEGRITY PROTECTED DATA HEADER"); 707 printf("Version: %d\n", content->se_ip_data_header.version); 708 break; 709 710 case OPS_PTAG_CT_SE_IP_DATA_BODY: 711 print_tagname( 712 "SYMMETRIC ENCRYPTED INTEGRITY PROTECTED DATA BODY"); 713 printf(" data body length=%u\n", 714 content->se_data_body.length); 715 printf(" data="); 716 hexdump(stdout, content->se_data_body.data, 717 content->se_data_body.length, ""); 718 printf("\n"); 719 break; 720 721 case OPS_PTAG_CT_PUBLIC_KEY: 722 case OPS_PTAG_CT_PUBLIC_SUBKEY: 723 print_tagname((pkt->tag == OPS_PTAG_CT_PUBLIC_KEY) ? 724 "PUBLIC KEY" : 725 "PUBLIC SUBKEY"); 726 __ops_print_pubkey(&content->pubkey); 727 break; 728 729 case OPS_PTAG_CT_TRUST: 730 print_tagname("TRUST"); 731 print_data("Trust", &content->trust.data); 732 break; 733 734 case OPS_PTAG_CT_USER_ID: 735 print_tagname("USER ID"); 736 print_utf8_string("userid", content->userid.userid); 737 break; 738 739 case OPS_PTAG_CT_SIGNATURE: 740 print_tagname("SIGNATURE"); 741 print_indent(); 742 print_uint("Signature Version", 743 (unsigned)content->sig.info.version); 744 if (content->sig.info.birthtime_set) { 745 print_time("Signature Creation Time", 746 content->sig.info.birthtime); 747 } 748 749 print_string_and_value("Signature Type", 750 __ops_show_sig_type(content->sig.info.type), 751 content->sig.info.type); 752 753 if (content->sig.info.signer_id_set) { 754 hexdump_data("Signer ID", 755 content->sig.info.signer_id, 756 sizeof(content->sig.info.signer_id)); 757 } 758 759 print_string_and_value("Public Key Algorithm", 760 __ops_show_pka(content->sig.info.key_alg), 761 content->sig.info.key_alg); 762 print_string_and_value("Hash Algorithm", 763 __ops_show_hash_alg((unsigned char) 764 content->sig.info.hash_alg), 765 (unsigned char)content->sig.info.hash_alg); 766 print_uint("Hashed data len", 767 content->sig.info.v4_hashlen); 768 print_indent(); 769 hexdump_data("hash2", &content->sig.hash2[0], 2); 770 switch (content->sig.info.key_alg) { 771 case OPS_PKA_RSA: 772 case OPS_PKA_RSA_SIGN_ONLY: 773 print_bn("sig", content->sig.info.sig.rsa.sig); 774 break; 775 776 case OPS_PKA_DSA: 777 print_bn("r", content->sig.info.sig.dsa.r); 778 print_bn("s", content->sig.info.sig.dsa.s); 779 break; 780 781 case OPS_PKA_ELGAMAL_ENCRYPT_OR_SIGN: 782 print_bn("r", content->sig.info.sig.elgamal.r); 783 print_bn("s", content->sig.info.sig.elgamal.s); 784 break; 785 786 default: 787 (void) fprintf(stderr, 788 "__ops_print_packet: Unusual algorithm\n"); 789 return 0; 790 } 791 792 if (content->sig.hash) 793 printf("data hash is set\n"); 794 795 break; 796 797 case OPS_PTAG_CT_COMPRESSED: 798 print_tagname("COMPRESSED"); 799 print_uint("Compressed Data Type", 800 (unsigned)content->compressed.type); 801 break; 802 803 case OPS_PTAG_CT_1_PASS_SIG: 804 print_tagname("ONE PASS SIGNATURE"); 805 806 print_uint("Version", (unsigned)content->one_pass_sig.version); 807 print_string_and_value("Signature Type", 808 __ops_show_sig_type(content->one_pass_sig.sig_type), 809 content->one_pass_sig.sig_type); 810 print_string_and_value("Hash Algorithm", 811 __ops_show_hash_alg((unsigned char)content->one_pass_sig.hash_alg), 812 (unsigned char)content->one_pass_sig.hash_alg); 813 print_string_and_value("Public Key Algorithm", 814 __ops_show_pka(content->one_pass_sig.key_alg), 815 content->one_pass_sig.key_alg); 816 hexdump_data("Signer ID", 817 content->one_pass_sig.keyid, 818 sizeof(content->one_pass_sig.keyid)); 819 print_uint("Nested", content->one_pass_sig.nested); 820 break; 821 822 case OPS_PTAG_CT_USER_ATTR: 823 print_tagname("USER ATTRIBUTE"); 824 print_hexdump("User Attribute", 825 content->userattr.data.contents, 826 content->userattr.data.len); 827 break; 828 829 case OPS_PTAG_RAW_SS: 830 if (pkt->critical) { 831 (void) fprintf(stderr, "contents are critical\n"); 832 return 0; 833 } 834 start_subpacket(pkt->tag); 835 print_uint("Raw Signature Subpacket: tag", 836 (unsigned)(content->ss_raw.tag - 837 (unsigned)OPS_PTAG_SIG_SUBPKT_BASE)); 838 print_hexdump("Raw Data", 839 content->ss_raw.raw, 840 content->ss_raw.length); 841 break; 842 843 case OPS_PTAG_SS_CREATION_TIME: 844 start_subpacket(pkt->tag); 845 print_time("Signature Creation Time", content->ss_time.time); 846 end_subpacket(); 847 break; 848 849 case OPS_PTAG_SS_EXPIRATION_TIME: 850 start_subpacket(pkt->tag); 851 print_duration("Signature Expiration Time", 852 content->ss_time.time); 853 end_subpacket(); 854 break; 855 856 case OPS_PTAG_SS_KEY_EXPIRY: 857 start_subpacket(pkt->tag); 858 print_duration("Key Expiration Time", content->ss_time.time); 859 end_subpacket(); 860 break; 861 862 case OPS_PTAG_SS_TRUST: 863 start_subpacket(pkt->tag); 864 print_string("Trust Signature", ""); 865 print_uint("Level", (unsigned)content->ss_trust.level); 866 print_uint("Amount", (unsigned)content->ss_trust.amount); 867 end_subpacket(); 868 break; 869 870 case OPS_PTAG_SS_REVOCABLE: 871 start_subpacket(pkt->tag); 872 print_boolean("Revocable", content->ss_revocable.revocable); 873 end_subpacket(); 874 break; 875 876 case OPS_PTAG_SS_REVOCATION_KEY: 877 start_subpacket(pkt->tag); 878 /* not yet tested */ 879 printf(" revocation key: class=0x%x", 880 content->ss_revocation_key.class); 881 if (content->ss_revocation_key.class & 0x40) { 882 printf(" (sensitive)"); 883 } 884 printf(", algid=0x%x", content->ss_revocation_key.algid); 885 printf(", fingerprint="); 886 hexdump(stdout, content->ss_revocation_key.fingerprint, 887 OPS_FINGERPRINT_SIZE, ""); 888 printf("\n"); 889 end_subpacket(); 890 break; 891 892 case OPS_PTAG_SS_ISSUER_KEY_ID: 893 start_subpacket(pkt->tag); 894 print_hexdump("Issuer Key Id", 895 &content->ss_issuer.key_id[0], 896 sizeof(content->ss_issuer.key_id)); 897 end_subpacket(); 898 break; 899 900 case OPS_PTAG_SS_PREFERRED_SKA: 901 start_subpacket(pkt->tag); 902 print_data("Preferred Symmetric Algorithms", 903 &content->ss_skapref.data); 904 905 text = __ops_showall_ss_skapref(content->ss_skapref); 906 print_text_breakdown(text); 907 __ops_text_free(text); 908 909 end_subpacket(); 910 break; 911 912 case OPS_PTAG_SS_PRIMARY_USER_ID: 913 start_subpacket(pkt->tag); 914 print_boolean("Primary User ID", 915 content->ss_primary_userid.primary_userid); 916 end_subpacket(); 917 break; 918 919 case OPS_PTAG_SS_PREFERRED_HASH: 920 start_subpacket(pkt->tag); 921 print_data("Preferred Hash Algorithms", 922 &content->ss_hashpref.data); 923 924 text = __ops_showall_ss_hashpref(content->ss_hashpref); 925 print_text_breakdown(text); 926 __ops_text_free(text); 927 end_subpacket(); 928 break; 929 930 case OPS_PTAG_SS_PREF_COMPRESS: 931 start_subpacket(pkt->tag); 932 print_data("Preferred Compression Algorithms", 933 &content->ss_zpref.data); 934 935 text = __ops_showall_ss_zpref(content->ss_zpref); 936 print_text_breakdown(text); 937 __ops_text_free(text); 938 end_subpacket(); 939 break; 940 941 case OPS_PTAG_SS_KEY_FLAGS: 942 start_subpacket(pkt->tag); 943 print_data("Key Flags", &content->ss_key_flags.data); 944 945 text = __ops_showall_ss_key_flags(content->ss_key_flags); 946 print_text_breakdown(text); 947 __ops_text_free(text); 948 949 end_subpacket(); 950 break; 951 952 case OPS_PTAG_SS_KEYSERV_PREFS: 953 start_subpacket(pkt->tag); 954 print_data("Key Server Preferences", 955 &content->ss_key_server_prefs.data); 956 957 text = __ops_show_keyserv_prefs(content->ss_key_server_prefs); 958 print_text_breakdown(text); 959 __ops_text_free(text); 960 961 end_subpacket(); 962 break; 963 964 case OPS_PTAG_SS_FEATURES: 965 start_subpacket(pkt->tag); 966 print_data("Features", 967 &content->ss_features.data); 968 969 text = __ops_showall_ss_features(content->ss_features); 970 print_text_breakdown(text); 971 __ops_text_free(text); 972 973 end_subpacket(); 974 break; 975 976 case OPS_PTAG_SS_NOTATION_DATA: 977 start_subpacket(pkt->tag); 978 print_indent(); 979 printf("Notation Data:\n"); 980 981 indent++; 982 print_data("Flags", &content->ss_notation.flags); 983 text = __ops_showall_notation(content->ss_notation); 984 print_text_breakdown(text); 985 __ops_text_free(text); 986 987 print_data("Name", &content->ss_notation.name); 988 989 print_data("Value", &content->ss_notation.value); 990 991 indent--; 992 end_subpacket(); 993 break; 994 995 case OPS_PTAG_SS_REGEXP: 996 start_subpacket(pkt->tag); 997 print_hexdump("Regular Expression", 998 (unsigned char *) content->ss_regexp.regexp, 999 strlen(content->ss_regexp.regexp)); 1000 print_string(NULL, content->ss_regexp.regexp); 1001 end_subpacket(); 1002 break; 1003 1004 case OPS_PTAG_SS_POLICY_URI: 1005 start_subpacket(pkt->tag); 1006 print_string("Policy URL", content->ss_policy.url); 1007 end_subpacket(); 1008 break; 1009 1010 case OPS_PTAG_SS_SIGNERS_USER_ID: 1011 start_subpacket(pkt->tag); 1012 print_utf8_string("Signer's User ID", 1013 content->ss_signer.userid); 1014 end_subpacket(); 1015 break; 1016 1017 case OPS_PTAG_SS_PREF_KEYSERV: 1018 start_subpacket(pkt->tag); 1019 print_string("Preferred Key Server", content->ss_keyserv.name); 1020 end_subpacket(); 1021 break; 1022 1023 case OPS_PTAG_SS_EMBEDDED_SIGNATURE: 1024 start_subpacket(pkt->tag); 1025 end_subpacket();/* \todo print out contents? */ 1026 break; 1027 1028 case OPS_PTAG_SS_USERDEFINED00: 1029 case OPS_PTAG_SS_USERDEFINED01: 1030 case OPS_PTAG_SS_USERDEFINED02: 1031 case OPS_PTAG_SS_USERDEFINED03: 1032 case OPS_PTAG_SS_USERDEFINED04: 1033 case OPS_PTAG_SS_USERDEFINED05: 1034 case OPS_PTAG_SS_USERDEFINED06: 1035 case OPS_PTAG_SS_USERDEFINED07: 1036 case OPS_PTAG_SS_USERDEFINED08: 1037 case OPS_PTAG_SS_USERDEFINED09: 1038 case OPS_PTAG_SS_USERDEFINED10: 1039 start_subpacket(pkt->tag); 1040 print_hexdump("Internal or user-defined", 1041 content->ss_userdef.data.contents, 1042 content->ss_userdef.data.len); 1043 end_subpacket(); 1044 break; 1045 1046 case OPS_PTAG_SS_RESERVED: 1047 start_subpacket(pkt->tag); 1048 print_hexdump("Reserved", 1049 content->ss_userdef.data.contents, 1050 content->ss_userdef.data.len); 1051 end_subpacket(); 1052 break; 1053 1054 case OPS_PTAG_SS_REVOCATION_REASON: 1055 start_subpacket(pkt->tag); 1056 print_hexdump("Revocation Reason", 1057 &content->ss_revocation.code, 1058 1); 1059 str = __ops_show_ss_rr_code(content->ss_revocation.code); 1060 print_string(NULL, str); 1061 end_subpacket(); 1062 break; 1063 1064 case OPS_PTAG_CT_LITDATA_HEADER: 1065 print_tagname("LITERAL DATA HEADER"); 1066 printf(" literal data header format=%c filename='%s'\n", 1067 content->litdata_header.format, 1068 content->litdata_header.filename); 1069 showtime(" modification time", 1070 content->litdata_header.mtime); 1071 printf("\n"); 1072 break; 1073 1074 case OPS_PTAG_CT_LITDATA_BODY: 1075 print_tagname("LITERAL DATA BODY"); 1076 printf(" literal data body length=%u\n", 1077 content->litdata_body.length); 1078 printf(" data="); 1079 print_escaped(content->litdata_body.data, 1080 content->litdata_body.length); 1081 printf("\n"); 1082 break; 1083 1084 case OPS_PTAG_CT_SIGNATURE_HEADER: 1085 print_tagname("SIGNATURE"); 1086 print_indent(); 1087 print_uint("Signature Version", 1088 (unsigned)content->sig.info.version); 1089 if (content->sig.info.birthtime_set) { 1090 print_time("Signature Creation Time", 1091 content->sig.info.birthtime); 1092 } 1093 print_string_and_value("Signature Type", 1094 __ops_show_sig_type(content->sig.info.type), 1095 content->sig.info.type); 1096 if (content->sig.info.signer_id_set) { 1097 hexdump_data("Signer ID", 1098 content->sig.info.signer_id, 1099 sizeof(content->sig.info.signer_id)); 1100 } 1101 print_string_and_value("Public Key Algorithm", 1102 __ops_show_pka(content->sig.info.key_alg), 1103 content->sig.info.key_alg); 1104 print_string_and_value("Hash Algorithm", 1105 __ops_show_hash_alg((unsigned char)content->sig.info.hash_alg), 1106 (unsigned char)content->sig.info.hash_alg); 1107 1108 break; 1109 1110 case OPS_PTAG_CT_SIGNATURE_FOOTER: 1111 print_indent(); 1112 hexdump_data("hash2", &content->sig.hash2[0], 2); 1113 1114 switch (content->sig.info.key_alg) { 1115 case OPS_PKA_RSA: 1116 print_bn("sig", content->sig.info.sig.rsa.sig); 1117 break; 1118 1119 case OPS_PKA_DSA: 1120 print_bn("r", content->sig.info.sig.dsa.r); 1121 print_bn("s", content->sig.info.sig.dsa.s); 1122 break; 1123 1124 case OPS_PKA_ELGAMAL_ENCRYPT_OR_SIGN: 1125 print_bn("r", content->sig.info.sig.elgamal.r); 1126 print_bn("s", content->sig.info.sig.elgamal.s); 1127 break; 1128 1129 case OPS_PKA_PRIVATE00: 1130 case OPS_PKA_PRIVATE01: 1131 case OPS_PKA_PRIVATE02: 1132 case OPS_PKA_PRIVATE03: 1133 case OPS_PKA_PRIVATE04: 1134 case OPS_PKA_PRIVATE05: 1135 case OPS_PKA_PRIVATE06: 1136 case OPS_PKA_PRIVATE07: 1137 case OPS_PKA_PRIVATE08: 1138 case OPS_PKA_PRIVATE09: 1139 case OPS_PKA_PRIVATE10: 1140 print_data("Private/Experimental", 1141 &content->sig.info.sig.unknown.data); 1142 break; 1143 1144 default: 1145 (void) fprintf(stderr, 1146 "__ops_print_packet: Unusual key algorithm\n"); 1147 return 0; 1148 } 1149 break; 1150 1151 case OPS_GET_PASSPHRASE: 1152 print_tagname("OPS_GET_PASSPHRASE"); 1153 break; 1154 1155 case OPS_PTAG_CT_SECRET_KEY: 1156 print_tagname("OPS_PTAG_CT_SECRET_KEY"); 1157 __ops_print_seckey_verbose(pkt->tag, &content->seckey); 1158 break; 1159 1160 case OPS_PTAG_CT_ENCRYPTED_SECRET_KEY: 1161 print_tagname("OPS_PTAG_CT_ENCRYPTED_SECRET_KEY"); 1162 __ops_print_seckey_verbose(pkt->tag, &content->seckey); 1163 break; 1164 1165 case OPS_PTAG_CT_ARMOUR_HEADER: 1166 print_tagname("ARMOUR HEADER"); 1167 print_string("type", content->armour_header.type); 1168 break; 1169 1170 case OPS_PTAG_CT_SIGNED_CLEARTEXT_HEADER: 1171 print_tagname("SIGNED CLEARTEXT HEADER"); 1172 print_headers(&content->cleartext_head.headers); 1173 break; 1174 1175 case OPS_PTAG_CT_SIGNED_CLEARTEXT_BODY: 1176 print_tagname("SIGNED CLEARTEXT BODY"); 1177 print_block("signed cleartext", content->cleartext_body.data, 1178 content->cleartext_body.length); 1179 break; 1180 1181 case OPS_PTAG_CT_SIGNED_CLEARTEXT_TRAILER: 1182 print_tagname("SIGNED CLEARTEXT TRAILER"); 1183 printf("hash algorithm: %d\n", 1184 content->cleartext_trailer.hash->alg); 1185 printf("\n"); 1186 break; 1187 1188 case OPS_PTAG_CT_UNARMOURED_TEXT: 1189 if (!unarmoured) { 1190 print_tagname("UNARMOURED TEXT"); 1191 unarmoured = 1; 1192 } 1193 putchar('['); 1194 print_escaped(content->unarmoured_text.data, 1195 content->unarmoured_text.length); 1196 putchar(']'); 1197 break; 1198 1199 case OPS_PTAG_CT_ARMOUR_TRAILER: 1200 print_tagname("ARMOUR TRAILER"); 1201 print_string("type", content->armour_header.type); 1202 break; 1203 1204 case OPS_PTAG_CT_PK_SESSION_KEY: 1205 case OPS_PTAG_CT_ENCRYPTED_PK_SESSION_KEY: 1206 __ops_print_pk_sesskey(pkt->tag, &content->pk_sesskey); 1207 break; 1208 1209 case OPS_GET_SECKEY: 1210 __ops_print_pk_sesskey(OPS_PTAG_CT_ENCRYPTED_PK_SESSION_KEY, 1211 content->get_seckey.pk_sesskey); 1212 break; 1213 1214 default: 1215 print_tagname("UNKNOWN PACKET TYPE"); 1216 fprintf(stderr, "__ops_print_packet: unknown tag=%d (0x%x)\n", 1217 pkt->tag, pkt->tag); 1218 exit(EXIT_FAILURE); 1219 } 1220 return 1; 1221 } 1222 1223 static __ops_cb_ret_t 1224 cb_list_packets(const __ops_packet_t *pkt, __ops_cbdata_t *cbinfo) 1225 { 1226 __OPS_USED(cbinfo); 1227 1228 __ops_print_packet(pkt); 1229 return OPS_RELEASE_MEMORY; 1230 } 1231 1232 /** 1233 \ingroup Core_Print 1234 \param filename 1235 \param armour 1236 \param keyring 1237 \param cb_get_passphrase 1238 */ 1239 int 1240 __ops_list_packets(__ops_io_t *io, 1241 char *filename, 1242 unsigned armour, 1243 __ops_keyring_t *keyring, 1244 void *passfp, 1245 __ops_cbfunc_t *cb_get_passphrase) 1246 { 1247 __ops_stream_t *stream = NULL; 1248 const unsigned accumulate = 1; 1249 const int printerrors = 1; 1250 int fd; 1251 1252 fd = __ops_setup_file_read(io, &stream, filename, NULL, cb_list_packets, 1253 accumulate); 1254 __ops_parse_options(stream, OPS_PTAG_SS_ALL, OPS_PARSE_PARSED); 1255 stream->cryptinfo.keyring = keyring; 1256 stream->cbinfo.passfp = passfp; 1257 stream->cryptinfo.getpassphrase = cb_get_passphrase; 1258 if (armour) { 1259 __ops_reader_push_dearmour(stream); 1260 } 1261 __ops_parse(stream, printerrors); 1262 __ops_teardown_file_read(stream, fd); 1263 return 1; 1264 } 1265