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