Patrick Welche <prlw1@cam.ac.uk>
[netbsd-mini2440.git] / crypto / external / bsd / netpgp / dist / src / lib / packet-print.c
blob3c37ed6fb93b07b353d03a2f00e63bd4ebb61c6e
1 /*-
2 * Copyright (c) 2009 The NetBSD Foundation, Inc.
3 * All rights reserved.
5 * This code is derived from software contributed to The NetBSD Foundation
6 * by Alistair Crooks (agc@NetBSD.org)
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.
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.
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.
36 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
37 * use this file except in compliance with the License.
39 * You may obtain a copy of the License at
40 * http://www.apache.org/licenses/LICENSE-2.0
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.
46 * See the License for the specific language governing permissions and
47 * limitations under the License.
51 * ! \file \brief Standard API print functions
53 #include "config.h"
55 #ifdef HAVE_SYS_CDEFS_H
56 #include <sys/cdefs.h>
57 #endif
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
64 #include <string.h>
65 #include <stdio.h>
67 #ifdef HAVE_UNISTD_H
68 #include <unistd.h>
69 #endif
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"
81 static int indent = 0;
83 /* static functions */
85 static void
86 print_indent(void)
88 int i;
90 for (i = 0; i < indent; i++) {
91 printf(" ");
95 static void
96 print_name(const char *name)
98 print_indent();
99 if (name) {
100 printf("%s: ", name);
104 static void
105 print_hexdump(const char *name, const unsigned char *data, unsigned int len)
107 print_name(name);
109 printf("len=%u, data=0x", len);
110 hexdump(stdout, data, len, "");
111 printf("\n");
114 static void
115 hexdump_data(const char *name, const unsigned char *data, unsigned len)
117 print_name(name);
119 printf("0x");
120 hexdump(stdout, data, len, "");
121 printf("\n");
124 static void
125 print_uint(const char *name, unsigned int val)
127 print_name(name);
128 printf("%u\n", val);
131 static void
132 showtime(const char *name, time_t t)
134 printf("%s=%" PRItime "d (%.24s)", name, (long long) t, ctime(&t));
137 static void
138 print_time(const char *name, time_t t)
140 print_indent();
141 printf("%s: ", name);
142 showtime("time", t);
143 printf("\n");
146 static void
147 print_string_and_value(const char *name, const char *str, unsigned char value)
149 print_name(name);
150 printf("%s (0x%x)\n", str, value);
153 static void
154 print_tagname(const char *str)
156 print_indent();
157 printf("%s packet\n", str);
160 static void
161 print_data(const char *name, const __ops_data_t *data)
163 print_hexdump(name, data->contents, data->len);
166 static void
167 print_bn(const char *name, const BIGNUM *bn)
169 print_indent();
170 printf("%s=", name);
171 if (bn) {
172 BN_print_fp(stdout, bn);
173 putchar('\n');
174 } else {
175 puts("(unset)");
179 static void
180 print_packet_hex(const __ops_subpacket_t *pkt)
182 unsigned char *cur;
183 unsigned rem;
184 unsigned blksz = 4;
185 int i;
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");
199 printf("\n");
202 static void
203 print_escaped(const unsigned char *data, size_t length)
205 while (length-- > 0) {
206 if ((*data >= 0x20 && *data < 0x7f && *data != '%') ||
207 *data == '\n') {
208 putchar(*data);
209 } else {
210 printf("%%%02x", *data);
212 ++data;
216 static void
217 print_string(const char *name, const char *str)
219 print_name(name);
220 print_escaped((const unsigned char *) str, strlen(str));
221 putchar('\n');
224 static void
225 print_utf8_string(const char *name, const unsigned char *str)
227 /* \todo Do this better for non-English character sets */
228 print_string(name, (const char *) str);
231 static void
232 print_duration(const char *name, time_t t)
234 int mins, hours, days, years;
236 print_indent();
237 printf("%s: ", name);
238 printf("duration %" PRItime "d seconds", (long long) t);
240 mins = (int)(t / 60);
241 hours = mins / 60;
242 days = hours / 24;
243 years = days / 365;
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");
253 printf(")\n");
256 static void
257 print_boolean(const char *name, unsigned char boolval)
259 print_name(name);
260 printf("%s\n", (boolval) ? "Yes" : "No");
263 static void
264 print_text_breakdown(__ops_text_t *text)
266 const char *prefix = ".. ";
267 unsigned i;
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]);
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()
280 if (text->unknown.used) {
281 printf("\n");
282 print_indent();
283 printf("Not Recognised: ");
285 for (i = 0; i < text->unknown.used; i++) {
286 print_indent();
287 printf("%s", prefix);
288 printf("%s\n", text->unknown.strings[i]);
292 static void
293 print_headers(const __ops_headers_t *h)
295 unsigned i;
297 for (i = 0; i < h->headerc; ++i) {
298 printf("%s=%s\n", h->headers[i].key, h->headers[i].value);
302 static void
303 print_block(const char *name, const unsigned char *str, size_t length)
305 int o = length;
307 print_indent();
308 printf(">>>>> %s >>>>>\n", name);
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);
320 ++str;
322 if (o && str[-1] != '\n') {
323 putchar('\n');
324 print_indent();
325 fputs("[no newline]", stdout);
326 } else {
327 print_indent();
329 printf("<<<<< %s <<<<<\n", name);
332 /* return the number of bits in the public key */
333 static int
334 numkeybits(const __ops_pubkey_t *pubkey)
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;
352 case OPS_PKA_ELGAMAL:
353 return BN_num_bytes(pubkey->key.elgamal.y) * 8;
354 default:
355 return -1;
359 /* return the hexdump as a string */
360 static char *
361 strhexdump(char *dest, const unsigned char *src, size_t length, const char *sep)
363 unsigned i;
364 int n;
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);
370 return dest;
373 /* return the time as a string */
374 static char *
375 ptimestr(char *dest, size_t size, time_t t)
377 struct tm *tm;
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;
387 #ifndef KB
388 #define KB(x) ((x) * 1024)
389 #endif
391 /* print into a string (malloc'ed) the pubkeydata */
393 __ops_sprint_keydata(const __ops_key_t *key, char **buf, const char *header,
394 const __ops_pubkey_t *pubkey)
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;
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);
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);
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)
422 char *cp;
424 if (__ops_sprint_keydata(key, &cp, header, pubkey)) {
425 (void) fprintf(io->res, "%s", cp);
426 free(cp);
431 \ingroup Core_Print
432 \param pubkey
434 void
435 __ops_print_pubkey(const __ops_pubkey_t *pubkey)
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);
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;
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;
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;
467 default:
468 (void) fprintf(stderr,
469 "__ops_print_pubkey: Unusual algorithm\n");
472 printf("------- end of PUBLIC KEY ------\n");
476 \ingroup Core_Print
477 \param type
478 \param seckey
480 static void
481 __ops_print_seckey_verbose(const __ops_content_tag_t type,
482 const __ops_seckey_t *seckey)
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));
500 if (seckey->s2k_specifier == OPS_S2KS_ITERATED_AND_SALTED) {
501 printf("Octet count: %u\n", seckey->octetc);
503 print_hexdump("IV", seckey->iv, __ops_block_size(seckey->alg));
505 /* no more set if encrypted */
506 if (type == OPS_PTAG_CT_ENCRYPTED_SECRET_KEY) {
507 return;
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;
517 case OPS_PKA_DSA:
518 print_bn("x", seckey->key.dsa.x);
519 break;
521 default:
522 (void) fprintf(stderr,
523 "__ops_print_seckey_verbose: unusual algorithm\n");
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);
531 printf("------- end of SECRET KEY or ENCRYPTED SECRET KEY ------\n");
536 \ingroup Core_Print
537 \param tag
538 \param key
540 static void
541 __ops_print_pk_sesskey(__ops_content_tag_t tag,
542 const __ops_pk_sesskey_t * key)
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;
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;
561 default:
562 (void) fprintf(stderr,
563 "__ops_print_pk_sesskey: unusual algorithm\n");
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);
573 static void
574 start_subpacket(int type)
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);
583 static void
584 end_subpacket(void)
586 indent--;
590 \ingroup Core_Print
591 \param contents
593 int
594 __ops_print_packet(const __ops_packet_t *pkt)
596 const __ops_contents_t *content = &pkt->u;
597 static unsigned unarmoured;
598 __ops_text_t *text;
599 const char *str;
601 if (unarmoured && pkt->tag != OPS_PTAG_CT_UNARMOURED_TEXT) {
602 unarmoured = 0;
603 puts("UNARMOURED TEXT ends");
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));
612 switch (pkt->tag) {
613 case OPS_PARSER_ERROR:
614 printf("parse error: %s\n", content->error.error);
615 break;
617 case OPS_PARSER_ERRCODE:
618 printf("parse error: %s\n",
619 __ops_errcode(content->errcode.errcode));
620 break;
622 case OPS_PARSER_PACKET_END:
623 print_packet_hex(&content->packet);
624 break;
626 case OPS_PARSER_PTAG:
627 if (content->ptag.type == OPS_PTAG_CT_PUBLIC_KEY) {
628 indent = 0;
629 printf("\n*** NEXT KEY ***\n");
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;
642 case OPS_PTAG_CT_SE_DATA_HEADER:
643 print_tagname("SYMMETRIC ENCRYPTED DATA");
644 break;
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;
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;
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;
671 case OPS_PTAG_CT_TRUST:
672 print_tagname("TRUST");
673 print_data("Trust", &content->trust.data);
674 break;
676 case OPS_PTAG_CT_USER_ID:
677 print_tagname("USER ID");
678 print_utf8_string("userid", content->userid.userid);
679 break;
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);
691 print_string_and_value("Signature Type",
692 __ops_show_sig_type(content->sig.info.type),
693 content->sig.info.type);
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));
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;
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;
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;
728 default:
729 (void) fprintf(stderr,
730 "__ops_print_packet: Unusual algorithm\n");
731 return 0;
734 if (content->sig.hash)
735 printf("data hash is set\n");
737 break;
739 case OPS_PTAG_CT_COMPRESSED:
740 print_tagname("COMPRESSED");
741 print_uint("Compressed Data Type",
742 (unsigned)content->compressed.type);
743 break;
745 case OPS_PTAG_CT_1_PASS_SIG:
746 print_tagname("ONE PASS SIGNATURE");
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;
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;
771 case OPS_PTAG_RAW_SS:
772 if (pkt->critical) {
773 (void) fprintf(stderr, "contents are critical\n");
774 return 0;
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;
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;
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;
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;
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;
812 case OPS_PTAG_SS_REVOCABLE:
813 start_subpacket(pkt->tag);
814 print_boolean("Revocable", content->ss_revocable.revocable);
815 end_subpacket();
816 break;
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)");
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;
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;
842 case OPS_PTAG_SS_PREFERRED_SKA:
843 start_subpacket(pkt->tag);
844 print_data("Preferred Symmetric Algorithms",
845 &content->ss_skapref.data);
847 text = __ops_showall_ss_skapref(content->ss_skapref);
848 print_text_breakdown(text);
849 __ops_text_free(text);
851 end_subpacket();
852 break;
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;
861 case OPS_PTAG_SS_PREFERRED_HASH:
862 start_subpacket(pkt->tag);
863 print_data("Preferred Hash Algorithms",
864 &content->ss_hashpref.data);
866 text = __ops_showall_ss_hashpref(content->ss_hashpref);
867 print_text_breakdown(text);
868 __ops_text_free(text);
869 end_subpacket();
870 break;
872 case OPS_PTAG_SS_PREF_COMPRESS:
873 start_subpacket(pkt->tag);
874 print_data("Preferred Compression Algorithms",
875 &content->ss_zpref.data);
877 text = __ops_showall_ss_zpref(content->ss_zpref);
878 print_text_breakdown(text);
879 __ops_text_free(text);
880 end_subpacket();
881 break;
883 case OPS_PTAG_SS_KEY_FLAGS:
884 start_subpacket(pkt->tag);
885 print_data("Key Flags", &content->ss_key_flags.data);
887 text = __ops_showall_ss_key_flags(content->ss_key_flags);
888 print_text_breakdown(text);
889 __ops_text_free(text);
891 end_subpacket();
892 break;
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);
899 text = __ops_show_keyserv_prefs(content->ss_key_server_prefs);
900 print_text_breakdown(text);
901 __ops_text_free(text);
903 end_subpacket();
904 break;
906 case OPS_PTAG_SS_FEATURES:
907 start_subpacket(pkt->tag);
908 print_data("Features",
909 &content->ss_features.data);
911 text = __ops_showall_ss_features(content->ss_features);
912 print_text_breakdown(text);
913 __ops_text_free(text);
915 end_subpacket();
916 break;
918 case OPS_PTAG_SS_NOTATION_DATA:
919 start_subpacket(pkt->tag);
920 print_indent();
921 printf("Notation Data:\n");
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);
929 print_data("Name", &content->ss_notation.name);
931 print_data("Value", &content->ss_notation.value);
933 indent--;
934 end_subpacket();
935 break;
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;
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;
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;
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;
965 case OPS_PTAG_SS_EMBEDDED_SIGNATURE:
966 start_subpacket(pkt->tag);
967 end_subpacket();/* \todo print out contents? */
968 break;
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;
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;
996 case OPS_PTAG_SS_REVOCATION_REASON:
997 start_subpacket(pkt->tag);
998 print_hexdump("Revocation Reason",
999 &content->ss_revocation.code,
1001 str = __ops_show_ss_rr_code(content->ss_revocation.code);
1002 print_string(NULL, str);
1003 end_subpacket();
1004 break;
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;
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;
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);
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));
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);
1050 break;
1052 case OPS_PTAG_CT_SIGNATURE_FOOTER:
1053 print_indent();
1054 hexdump_data("hash2", &content->sig.hash2[0], 2);
1056 switch (content->sig.info.key_alg) {
1057 case OPS_PKA_RSA:
1058 print_bn("sig", content->sig.info.sig.rsa.sig);
1059 break;
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;
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;
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;
1086 default:
1087 (void) fprintf(stderr,
1088 "__ops_print_packet: Unusual key algorithm\n");
1089 return 0;
1091 break;
1093 case OPS_GET_PASSPHRASE:
1094 print_tagname("OPS_GET_PASSPHRASE");
1095 break;
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;
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;
1107 case OPS_PTAG_CT_ARMOUR_HEADER:
1108 print_tagname("ARMOUR HEADER");
1109 print_string("type", content->armour_header.type);
1110 break;
1112 case OPS_PTAG_CT_SIGNED_CLEARTEXT_HEADER:
1113 print_tagname("SIGNED CLEARTEXT HEADER");
1114 print_headers(&content->cleartext_head.headers);
1115 break;
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;
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;
1130 case OPS_PTAG_CT_UNARMOURED_TEXT:
1131 if (!unarmoured) {
1132 print_tagname("UNARMOURED TEXT");
1133 unarmoured = 1;
1135 putchar('[');
1136 print_escaped(content->unarmoured_text.data,
1137 content->unarmoured_text.length);
1138 putchar(']');
1139 break;
1141 case OPS_PTAG_CT_ARMOUR_TRAILER:
1142 print_tagname("ARMOUR TRAILER");
1143 print_string("type", content->armour_header.type);
1144 break;
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;
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;
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);
1162 return 1;
1165 static __ops_cb_ret_t
1166 cb_list_packets(const __ops_packet_t *pkt, __ops_cbdata_t *cbinfo)
1168 __OPS_USED(cbinfo);
1170 __ops_print_packet(pkt);
1171 return OPS_RELEASE_MEMORY;
1175 \ingroup Core_Print
1176 \param filename
1177 \param armour
1178 \param keyring
1179 \param cb_get_passphrase
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)
1189 __ops_stream_t *stream = NULL;
1190 const unsigned accumulate = 1;
1191 const int printerrors = 1;
1192 int fd;
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);
1203 __ops_parse(stream, printerrors);
1204 __ops_teardown_file_read(stream, fd);
1205 return 1;