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