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