xref: /netbsd-src/crypto/external/bsd/netpgp/dist/src/lib/packet-print.c (revision 9ee9e0d7de4c59c936a17df52be682915dc66f43)
1 /*
2  * Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
3  * All rights reserved.
4  * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
5  * their moral rights under the UK Copyright Design and Patents Act 1988 to
6  * be recorded as the authors of this copyright work.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
9  * use this file except in compliance with the License.
10  *
11  * You may obtain a copy of the License at
12  *     http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  *
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  */
21 
22 /*
23  * ! \file \brief Standard API print functions
24  */
25 #include "config.h"
26 
27 #ifdef HAVE_ASSERT_H
28 #include <assert.h>
29 #endif
30 
31 #include <string.h>
32 
33 #include "crypto.h"
34 #include "keyring.h"
35 #include "packet-show.h"
36 #include "signature.h"
37 
38 #include "readerwriter.h"
39 #include "netpgpdefs.h"
40 #include "keyring_local.h"
41 #include "parse_local.h"
42 
43 static int      indent = 0;
44 
45 static void print_bn(const char *, const BIGNUM *);
46 static void print_hex(const unsigned char *, size_t);
47 static void print_hexdump(const char *, const unsigned char *, unsigned int);
48 static void print_hexdump_data(const char *, const unsigned char *, unsigned int);
49 static void     print_indent(void);
50 static void     print_name(const char *);
51 static void print_string_and_value(const char *, const char *, unsigned char);
52 static void     print_tagname(const char *);
53 static void print_time(const char *, time_t);
54 static void     print_time_short(time_t);
55 static void print_unsigned_int(const char *, unsigned int);
56 static void     showtime(const char *, time_t);
57 static void     showtime_short(time_t);
58 
59 /**
60    \ingroup Core_Print
61 
62    Prints a public key in succinct detail
63 
64    \param key Ptr to public key
65 */
66 
67 void
68 __ops_print_public_keydata(const __ops_keydata_t * key)
69 {
70 	unsigned int    i;
71 
72 	printf("pub %s ", __ops_show_pka(key->key.pkey.algorithm));
73 	hexdump(key->key_id, OPS_KEY_ID_SIZE, "");
74 	printf(" ");
75 	print_time_short(key->key.pkey.creation_time);
76 	printf("\nKey fingerprint: ");
77 	hexdump(key->fingerprint.fingerprint, 20, " ");
78 	printf("\n");
79 
80 	for (i = 0; i < key->nuids; i++) {
81 		printf("uid                              %s\n",
82 			key->uids[i].user_id);
83 	}
84 }
85 
86 /**
87 \ingroup Core_Print
88 \param pkey
89 */
90 void
91 __ops_print_public_key(const __ops_public_key_t * pkey)
92 {
93 	printf("------- PUBLIC KEY ------\n");
94 	print_unsigned_int("Version", (unsigned)pkey->version);
95 	print_time("Creation Time", pkey->creation_time);
96 	if (pkey->version == OPS_V3)
97 		print_unsigned_int("Days Valid", pkey->days_valid);
98 
99 	print_string_and_value("Algorithm", __ops_show_pka(pkey->algorithm),
100 			       pkey->algorithm);
101 
102 	switch (pkey->algorithm) {
103 	case OPS_PKA_DSA:
104 		print_bn("p", pkey->key.dsa.p);
105 		print_bn("q", pkey->key.dsa.q);
106 		print_bn("g", pkey->key.dsa.g);
107 		print_bn("y", pkey->key.dsa.y);
108 		break;
109 
110 	case OPS_PKA_RSA:
111 	case OPS_PKA_RSA_ENCRYPT_ONLY:
112 	case OPS_PKA_RSA_SIGN_ONLY:
113 		print_bn("n", pkey->key.rsa.n);
114 		print_bn("e", pkey->key.rsa.e);
115 		break;
116 
117 	case OPS_PKA_ELGAMAL:
118 	case OPS_PKA_ELGAMAL_ENCRYPT_OR_SIGN:
119 		print_bn("p", pkey->key.elgamal.p);
120 		print_bn("g", pkey->key.elgamal.g);
121 		print_bn("y", pkey->key.elgamal.y);
122 		break;
123 
124 	default:
125 		assert( /* CONSTCOND */ 0);
126 	}
127 
128 	printf("------- end of PUBLIC KEY ------\n");
129 }
130 
131 /**
132    \ingroup Core_Print
133 
134    Prints a secret key
135 
136    \param key Ptr to public key
137 */
138 
139 void
140 __ops_print_secret_keydata(const __ops_keydata_t * key)
141 {
142 	printf("sec ");
143 	__ops_show_pka(key->key.pkey.algorithm);
144 	printf(" ");
145 
146 	hexdump(key->key_id, OPS_KEY_ID_SIZE, "");
147 	printf(" ");
148 
149 	print_time_short(key->key.pkey.creation_time);
150 	printf(" ");
151 
152 	if (key->nuids == 1) {
153 		/* print on same line as other info */
154 		printf("%s\n", key->uids[0].user_id);
155 	} else {
156 		/* print all uids on separate line  */
157 		unsigned int    i;
158 		printf("\n");
159 		for (i = 0; i < key->nuids; i++) {
160 			printf("uid                              %s\n", key->uids[i].user_id);
161 		}
162 	}
163 }
164 
165 /*
166 void
167 __ops_print_secret_key_verbose(const __ops_secret_key_t* skey)
168     {
169     if(key->type == OPS_PTAG_CT_SECRET_KEY)
170 	print_tagname("SECRET_KEY");
171     else
172 	print_tagname("ENCRYPTED_SECRET_KEY");
173     __ops_print_secret_key(key->type,skey);
174 	}
175 */
176 
177 /**
178 \ingroup Core_Print
179 \param type
180 \param skey
181 */
182 static void
183 __ops_print_secret_key_verbose(const __ops_content_tag_t type, const __ops_secret_key_t * skey)
184 {
185 	printf("------- SECRET KEY or ENCRYPTED SECRET KEY ------\n");
186 	if (type == OPS_PTAG_CT_SECRET_KEY)
187 		print_tagname("SECRET_KEY");
188 	else
189 		print_tagname("ENCRYPTED_SECRET_KEY");
190 	/* __ops_print_public_key(key); */
191 	printf("S2K Usage: %d\n", skey->s2k_usage);
192 	if (skey->s2k_usage != OPS_S2KU_NONE) {
193 		printf("S2K Specifier: %d\n", skey->s2k_specifier);
194 		printf("Symmetric algorithm: %d (%s)\n", skey->algorithm,
195 		       __ops_show_symmetric_algorithm(skey->algorithm));
196 		printf("Hash algorithm: %d (%s)\n", skey->hash_algorithm,
197 		       __ops_show_hash_algorithm(skey->hash_algorithm));
198 		if (skey->s2k_specifier != OPS_S2KS_SIMPLE)
199 			print_hexdump("Salt", skey->salt, sizeof(skey->salt));
200 		if (skey->s2k_specifier == OPS_S2KS_ITERATED_AND_SALTED)
201 			printf("Octet count: %d\n", skey->octet_count);
202 		print_hexdump("IV", skey->iv, __ops_block_size(skey->algorithm));
203 	}
204 	/* no more set if encrypted */
205 	if (type == OPS_PTAG_CT_ENCRYPTED_SECRET_KEY)
206 		return;
207 
208 	switch (skey->public_key.algorithm) {
209 	case OPS_PKA_RSA:
210 		print_bn("d", skey->key.rsa.d);
211 		print_bn("p", skey->key.rsa.p);
212 		print_bn("q", skey->key.rsa.q);
213 		print_bn("u", skey->key.rsa.u);
214 		break;
215 
216 	case OPS_PKA_DSA:
217 		print_bn("x", skey->key.dsa.x);
218 		break;
219 
220 	default:
221 		assert( /* CONSTCOND */ 0);
222 	}
223 
224 	if (skey->s2k_usage == OPS_S2KU_ENCRYPTED_AND_HASHED)
225 		print_hexdump("Checkhash", skey->checkhash, OPS_CHECKHASH_SIZE);
226 	else
227 		printf("Checksum: %04x\n", skey->checksum);
228 
229 	printf("------- end of SECRET KEY or ENCRYPTED SECRET KEY ------\n");
230 }
231 
232 
233 /* static functions */
234 
235 static void
236 print_unsigned_int(const char *name, unsigned int val)
237 {
238 	print_name(name);
239 	printf("%d\n", val);
240 }
241 
242 static void
243 print_time(const char *name, time_t t)
244 {
245 	print_indent();
246 	printf("%s: ", name);
247 	showtime("time", t);
248 	printf("\n");
249 }
250 
251 static void
252 print_time_short(time_t t)
253 {
254 	showtime_short(t);
255 }
256 
257 static void
258 print_string_and_value(const char *name, const char *str,
259 		       unsigned char value)
260 {
261 	print_name(name);
262 
263 	printf("%s", str);
264 	printf(" (0x%x)", value);
265 	printf("\n");
266 }
267 
268 void
269 print_bn(const char *name, const BIGNUM * bn)
270 {
271 	print_indent();
272 	printf("%s=", name);
273 	if (bn) {
274 		BN_print_fp(stdout, bn);
275 		putchar('\n');
276 	} else
277 		puts("(unset)");
278 }
279 
280 static void
281 print_tagname(const char *str)
282 {
283 	print_indent();
284 	printf("%s packet\n", str);
285 }
286 
287 static void
288 print_hexdump(const char *name,
289 	      const unsigned char *data,
290 	      unsigned int len)
291 {
292 	print_name(name);
293 
294 	printf("len=%d, data=0x", len);
295 	print_hex(data, len);
296 	printf("\n");
297 }
298 
299 static void
300 print_hexdump_data(const char *name,
301 		   const unsigned char *data,
302 		   unsigned int len)
303 {
304 	print_name(name);
305 
306 	printf("0x");
307 	print_hex(data, len);
308 	printf("\n");
309 }
310 
311 static void
312 print_data(const char *name, const __ops_data_t * data)
313 {
314 	print_hexdump(name, data->contents, data->len);
315 }
316 
317 
318 static void
319 print_name(const char *name)
320 {
321 	print_indent();
322 	if (name)
323 		printf("%s: ", name);
324 }
325 
326 static void
327 print_indent(void)
328 {
329 	int             i = 0;
330 
331 	for (i = 0; i < indent; i++)
332 		printf("  ");
333 }
334 
335 /* printhex is now print_hex for consistency */
336 static void
337 print_hex(const unsigned char *src, size_t length)
338 {
339 	while (length--)
340 		printf("%02X", *src++);
341 }
342 
343 static void
344 showtime(const char *name, time_t t)
345 {
346 	printf("%s=%" PRItime "d (%.24s)", name, (long long) t, ctime(&t));
347 }
348 static void
349 showtime_short(time_t t)
350 {
351 	struct tm      *tm;
352 	/*
353         const int maxbuf=512;
354         char buf[maxbuf+1];
355         buf[maxbuf]='\0';
356         // this needs to be tm struct
357         strftime(buf,maxbuf,"%F",&t);
358         printf(buf);
359         */
360 	tm = gmtime(&t);
361 	printf("%04d-%02d-%02d", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday);
362 }
363 
364 
365 static void
366 print_packet_hex(const __ops_packet_t * packet)
367 {
368 	unsigned char  *cur;
369 	unsigned	rem;
370 	unsigned	blksz = 4;
371 	int             i;
372 
373 	printf("\nhexdump of packet contents follows:\n");
374 	for (i = 1, cur = packet->raw; cur < (packet->raw + packet->length); cur += blksz, i++) {
375 		rem = packet->raw + packet->length - cur;
376 		hexdump(cur, (rem <= blksz) ? rem : blksz, "");
377 		printf(" ");
378 		if (i % 8 == 0) {
379 			printf("\n");
380 		}
381 
382 	}
383 	printf("\n");
384 }
385 
386 static void
387 print_escaped(const unsigned char *data, size_t length)
388 {
389 	while (length-- > 0) {
390 		if ((*data >= 0x20 && *data < 0x7f && *data != '%') || *data == '\n')
391 			putchar(*data);
392 		else
393 			printf("%%%02x", *data);
394 		++data;
395 	}
396 }
397 
398 static void
399 print_string(const char *name, const char *str)
400 {
401 	print_name(name);
402 	print_escaped((const unsigned char *) str, strlen(str));
403 	putchar('\n');
404 }
405 
406 static void
407 print_utf8_string(const char *name, const unsigned char *str)
408 {
409 	/* \todo Do this better for non-English character sets */
410 	print_string(name, (const char *) str);
411 }
412 
413 static void
414 print_duration(const char *name, time_t t)
415 {
416 	int             mins, hours, days, years;
417 
418 	print_indent();
419 	printf("%s: ", name);
420 	printf("duration %" PRItime "d seconds", (long long) t);
421 
422 	mins = (int)(t / 60);
423 	hours = mins / 60;
424 	days = hours / 24;
425 	years = days / 365;
426 
427 	printf(" (approx. ");
428 	if (years)
429 		printf("%d %s", years, years == 1 ? "year" : "years");
430 	else if (days)
431 		printf("%d %s", days, days == 1 ? "day" : "days");
432 	else if (hours)
433 		printf("%d %s", hours, hours == 1 ? "hour" : "hours");
434 
435 	printf(")");
436 	printf("\n");
437 }
438 
439 static void
440 print_boolean(const char *name, unsigned char boolval)
441 {
442 	print_name(name);
443 	printf("%s\n", (boolval) ? "Yes" : "No");
444 }
445 
446 static void
447 print_text_breakdown(__ops_text_t * text)
448 {
449 	unsigned        i;
450 	const char     *prefix = ".. ";
451 
452 	/* these were recognised */
453 
454 	for (i = 0; i < text->known.used; i++) {
455 		print_indent();
456 		printf(prefix);
457 		printf("%s\n", text->known.strings[i]);
458 	}
459 
460 	/*
461 	 * these were not recognised. the strings will contain the hex value
462 	 * of the unrecognised value in string format - see
463 	 * process_octet_str()
464 	 */
465 
466 	if (text->unknown.used) {
467 		printf("\n");
468 		print_indent();
469 		printf("Not Recognised: ");
470 	}
471 	for (i = 0; i < text->unknown.used; i++) {
472 		print_indent();
473 		printf(prefix);
474 		printf("%s\n", text->unknown.strings[i]);
475 	}
476 
477 }
478 
479 static void
480 print_headers(const __ops_headers_t * headers)
481 {
482 	unsigned        n;
483 
484 	for (n = 0; n < headers->nheaders; ++n)
485 		printf("%s=%s\n", headers->headers[n].key, headers->headers[n].value);
486 }
487 
488 static void
489 print_block(const char *name, const unsigned char *str,
490 	    size_t length)
491 {
492 	int             o = length;
493 
494 	print_indent();
495 	printf(">>>>> %s >>>>>\n", name);
496 
497 	print_indent();
498 	for (; length > 0; --length) {
499 		if (*str >= 0x20 && *str < 0x7f && *str != '%')
500 			putchar(*str);
501 		else if (*str == '\n') {
502 			putchar(*str);
503 			print_indent();
504 		} else
505 			printf("%%%02x", *str);
506 		++str;
507 	}
508 	if (o && str[-1] != '\n') {
509 		putchar('\n');
510 		print_indent();
511 		fputs("[no newline]", stdout);
512 	} else
513 		print_indent();
514 	printf("<<<<< %s <<<<<\n", name);
515 }
516 
517 /**
518 \ingroup Core_Print
519 \param tag
520 \param key
521 */
522 static void
523 __ops_print_pk_session_key(__ops_content_tag_t tag,
524 			 const __ops_pk_session_key_t * key)
525 {
526 	if (tag == OPS_PTAG_CT_PK_SESSION_KEY)
527 		print_tagname("PUBLIC KEY SESSION KEY");
528 	else
529 		print_tagname("ENCRYPTED PUBLIC KEY SESSION KEY");
530 
531 	printf("Version: %d\n", key->version);
532 	print_hexdump("Key ID", key->key_id, sizeof(key->key_id));
533 	printf("Algorithm: %d (%s)\n", key->algorithm,
534 	       __ops_show_pka(key->algorithm));
535 	switch (key->algorithm) {
536 	case OPS_PKA_RSA:
537 		print_bn("encrypted_m", key->parameters.rsa.encrypted_m);
538 		break;
539 
540 	case OPS_PKA_ELGAMAL:
541 		print_bn("g_to_k", key->parameters.elgamal.g_to_k);
542 		print_bn("encrypted_m", key->parameters.elgamal.encrypted_m);
543 		break;
544 
545 	default:
546 		assert( /* CONSTCOND */ 0);
547 	}
548 
549 	if (tag != OPS_PTAG_CT_PK_SESSION_KEY)
550 		return;
551 
552 	printf("Symmetric algorithm: %d (%s)\n", key->symmetric_algorithm,
553 	       __ops_show_symmetric_algorithm(key->symmetric_algorithm));
554 	print_hexdump("Key", key->key, __ops_key_size(key->symmetric_algorithm));
555 	printf("Checksum: %04x\n", key->checksum);
556 }
557 
558 static void
559 start_subpacket(int type)
560 {
561 	indent++;
562 	print_indent();
563 	printf("-- %s (type 0x%02x)\n",
564 	       __ops_show_ss_type(type),
565 	       type - OPS_PTAG_SIGNATURE_SUBPACKET_BASE);
566 }
567 
568 static void
569 end_subpacket(void)
570 {
571 	indent--;
572 }
573 
574 /**
575 \ingroup Core_Print
576 \param contents
577 */
578 int
579 __ops_print_packet(const __ops_parser_content_t * contents)
580 {
581 	const __ops_parser_content_union_t *content = &contents->u;
582 	__ops_text_t     *text;
583 	const char     *str;
584 	static bool unarmoured;
585 
586 	if (unarmoured && contents->tag != OPS_PTAG_CT_UNARMOURED_TEXT) {
587 		unarmoured = false;
588 		puts("UNARMOURED TEXT ends");
589 	}
590 	if (contents->tag == OPS_PARSER_PTAG) {
591 		printf("=> OPS_PARSER_PTAG: %s\n", __ops_show_packet_tag(content->ptag.content_tag));
592 	} else {
593 		printf("=> %s\n", __ops_show_packet_tag(contents->tag));
594 	}
595 
596 	switch (contents->tag) {
597 	case OPS_PARSER_ERROR:
598 		printf("parse error: %s\n", content->error.error);
599 		break;
600 
601 	case OPS_PARSER_ERRCODE:
602 		printf("parse error: %s\n",
603 		       __ops_errcode(content->errcode.errcode));
604 		break;
605 
606 	case OPS_PARSER_PACKET_END:
607 		print_packet_hex(&content->packet);
608 		break;
609 
610 	case OPS_PARSER_PTAG:
611 		if (content->ptag.content_tag == OPS_PTAG_CT_PUBLIC_KEY) {
612 			indent = 0;
613 			printf("\n*** NEXT KEY ***\n");
614 		}
615 		printf("\n");
616 		print_indent();
617 		printf("==== ptag new_format=%d content_tag=%d length_type=%d"
618 		       " length=0x%x (%d) position=0x%x (%d)\n", content->ptag.new_format,
619 		       content->ptag.content_tag, content->ptag.length_type,
620 		       content->ptag.length, content->ptag.length,
621 		       content->ptag.position, content->ptag.position);
622 		print_tagname(__ops_show_packet_tag(content->ptag.content_tag));
623 		break;
624 
625 	case OPS_PTAG_CT_SE_DATA_HEADER:
626 		print_tagname("SYMMETRIC ENCRYPTED DATA");
627 		break;
628 
629 	case OPS_PTAG_CT_SE_IP_DATA_HEADER:
630 		print_tagname("SYMMETRIC ENCRYPTED INTEGRITY PROTECTED DATA HEADER");
631 		printf("Version: %d\n", content->se_ip_data_header.version);
632 		break;
633 
634 	case OPS_PTAG_CT_SE_IP_DATA_BODY:
635 		print_tagname("SYMMETRIC ENCRYPTED INTEGRITY PROTECTED DATA BODY");
636 		printf("  data body length=%d\n",
637 		       content->se_data_body.length);
638 		printf("    data=");
639 		hexdump(content->se_data_body.data,
640 			content->se_data_body.length, "");
641 		printf("\n");
642 		break;
643 
644 	case OPS_PTAG_CT_PUBLIC_KEY:
645 	case OPS_PTAG_CT_PUBLIC_SUBKEY:
646 		if (contents->tag == OPS_PTAG_CT_PUBLIC_KEY)
647 			print_tagname("PUBLIC KEY");
648 		else
649 			print_tagname("PUBLIC SUBKEY");
650 		__ops_print_public_key(&content->public_key);
651 		break;
652 
653 	case OPS_PTAG_CT_TRUST:
654 		print_tagname("TRUST");
655 		print_data("Trust", &content->trust.data);
656 		break;
657 
658 	case OPS_PTAG_CT_USER_ID:
659 		/* XXX: how do we print UTF-8? */
660 		print_tagname("USER ID");
661 		print_utf8_string("user_id", content->user_id.user_id);
662 		break;
663 
664 	case OPS_PTAG_CT_SIGNATURE:
665 		print_tagname("SIGNATURE");
666 		print_indent();
667 		print_unsigned_int("Signature Version",
668 				   (unsigned)content->signature.info.version);
669 		if (content->signature.info.creation_time_set)
670 			print_time("Signature Creation Time",
671 				   content->signature.info.creation_time);
672 
673 		print_string_and_value("Signature Type",
674 			    __ops_show_sig_type(content->signature.info.type),
675 				       content->signature.info.type);
676 
677 		if (content->signature.info.signer_id_set)
678 			print_hexdump_data("Signer ID",
679 					   content->signature.info.signer_id,
680 				  sizeof(content->signature.info.signer_id));
681 
682 		print_string_and_value("Public Key Algorithm",
683 			__ops_show_pka(content->signature.info.key_algorithm),
684 				     content->signature.info.key_algorithm);
685 		print_string_and_value("Hash Algorithm",
686 				       __ops_show_hash_algorithm(content->signature.info.hash_algorithm),
687 				    content->signature.info.hash_algorithm);
688 
689 		print_unsigned_int("Hashed data len", content->signature.info.v4_hashed_data_length);
690 
691 		print_indent();
692 		print_hexdump_data("hash2", &content->signature.hash2[0], 2);
693 
694 		switch (content->signature.info.key_algorithm) {
695 		case OPS_PKA_RSA:
696 		case OPS_PKA_RSA_SIGN_ONLY:
697 			print_bn("sig", content->signature.info.signature.rsa.sig);
698 			break;
699 
700 		case OPS_PKA_DSA:
701 			print_bn("r", content->signature.info.signature.dsa.r);
702 			print_bn("s", content->signature.info.signature.dsa.s);
703 			break;
704 
705 		case OPS_PKA_ELGAMAL_ENCRYPT_OR_SIGN:
706 			print_bn("r", content->signature.info.signature.elgamal.r);
707 			print_bn("s", content->signature.info.signature.elgamal.s);
708 			break;
709 
710 		default:
711 			assert( /* CONSTCOND */ 0);
712 		}
713 
714 		if (content->signature.hash)
715 			printf("data hash is set\n");
716 
717 		break;
718 
719 	case OPS_PTAG_CT_COMPRESSED:
720 		print_tagname("COMPRESSED");
721 		print_unsigned_int("Compressed Data Type",
722 			(unsigned)content->compressed.type);
723 		break;
724 
725 	case OPS_PTAG_CT_ONE_PASS_SIGNATURE:
726 		print_tagname("ONE PASS SIGNATURE");
727 
728 		print_unsigned_int("Version",
729 			(unsigned)content->one_pass_signature.version);
730 		print_string_and_value("Signature Type",
731 		    __ops_show_sig_type(content->one_pass_signature.sig_type),
732 				       content->one_pass_signature.sig_type);
733 		print_string_and_value("Hash Algorithm",
734 				       __ops_show_hash_algorithm(content->one_pass_signature.hash_algorithm),
735 				content->one_pass_signature.hash_algorithm);
736 		print_string_and_value("Public Key Algorithm",
737 		    __ops_show_pka(content->one_pass_signature.key_algorithm),
738 				 content->one_pass_signature.key_algorithm);
739 		print_hexdump_data("Signer ID",
740 				   content->one_pass_signature.keyid,
741 				   sizeof(content->one_pass_signature.keyid));
742 
743 		print_unsigned_int("Nested",
744 				   content->one_pass_signature.nested);
745 		break;
746 
747 	case OPS_PTAG_CT_USER_ATTRIBUTE:
748 		print_tagname("USER ATTRIBUTE");
749 		print_hexdump("User Attribute",
750 			      content->user_attribute.data.contents,
751 			      content->user_attribute.data.len);
752 		break;
753 
754 	case OPS_PTAG_RAW_SS:
755 		assert(!contents->critical);
756 		start_subpacket(contents->tag);
757 		print_unsigned_int("Raw Signature Subpacket: tag",
758 			(unsigned)(content->ss_raw.tag -
759 		   	OPS_PTAG_SIGNATURE_SUBPACKET_BASE));
760 		print_hexdump("Raw Data",
761 			      content->ss_raw.raw,
762 			      content->ss_raw.length);
763 		break;
764 
765 	case OPS_PTAG_SS_CREATION_TIME:
766 		start_subpacket(contents->tag);
767 		print_time("Signature Creation Time", content->ss_time.time);
768 		end_subpacket();
769 		break;
770 
771 	case OPS_PTAG_SS_EXPIRATION_TIME:
772 		start_subpacket(contents->tag);
773 		print_duration("Signature Expiration Time", content->ss_time.time);
774 		end_subpacket();
775 		break;
776 
777 	case OPS_PTAG_SS_KEY_EXPIRATION_TIME:
778 		start_subpacket(contents->tag);
779 		print_duration("Key Expiration Time", content->ss_time.time);
780 		end_subpacket();
781 		break;
782 
783 	case OPS_PTAG_SS_TRUST:
784 		start_subpacket(contents->tag);
785 		print_string("Trust Signature", "");
786 		print_unsigned_int("Level",
787 				   (unsigned)content->ss_trust.level);
788 		print_unsigned_int("Amount",
789 				   (unsigned)content->ss_trust.amount);
790 		end_subpacket();
791 		break;
792 
793 	case OPS_PTAG_SS_REVOCABLE:
794 		start_subpacket(contents->tag);
795 		print_boolean("Revocable", content->ss_revocable.revocable);
796 		end_subpacket();
797 		break;
798 
799 	case OPS_PTAG_SS_REVOCATION_KEY:
800 		start_subpacket(contents->tag);
801 		/* not yet tested */
802 		printf("  revocation key: class=0x%x",
803 		       content->ss_revocation_key.class);
804 		if (content->ss_revocation_key.class & 0x40)
805 			printf(" (sensitive)");
806 		printf(", algid=0x%x",
807 		       content->ss_revocation_key.algid);
808 		printf(", fingerprint=");
809 		hexdump(content->ss_revocation_key.fingerprint, 20, "");
810 		printf("\n");
811 		end_subpacket();
812 		break;
813 
814 	case OPS_PTAG_SS_ISSUER_KEY_ID:
815 		start_subpacket(contents->tag);
816 		print_hexdump("Issuer Key Id",
817 			      &content->ss_issuer_key_id.key_id[0],
818 			      sizeof(content->ss_issuer_key_id.key_id));
819 		end_subpacket();
820 		break;
821 
822 	case OPS_PTAG_SS_PREFERRED_SKA:
823 		start_subpacket(contents->tag);
824 		print_data("Preferred Symmetric Algorithms",
825 			   &content->ss_preferred_ska.data);
826 
827 		text = __ops_showall_ss_preferred_ska(content->ss_preferred_ska);
828 		print_text_breakdown(text);
829 		__ops_text_free(text);
830 
831 		end_subpacket();
832 		break;
833 
834 	case OPS_PTAG_SS_PRIMARY_USER_ID:
835 		start_subpacket(contents->tag);
836 		print_boolean("Primary User ID",
837 			      content->ss_primary_user_id.primary_user_id);
838 		end_subpacket();
839 		break;
840 
841 	case OPS_PTAG_SS_PREFERRED_HASH:
842 		start_subpacket(contents->tag);
843 		print_data("Preferred Hash Algorithms",
844 			   &content->ss_preferred_hash.data);
845 
846 		text = __ops_showall_ss_preferred_hash(content->ss_preferred_hash);
847 		print_text_breakdown(text);
848 		__ops_text_free(text);
849 		end_subpacket();
850 		break;
851 
852 	case OPS_PTAG_SS_PREFERRED_COMPRESSION:
853 		start_subpacket(contents->tag);
854 		print_data("Preferred Compression Algorithms",
855 			   &content->ss_preferred_compression.data);
856 
857 		text = __ops_showall_ss_preferred_compression(content->ss_preferred_compression);
858 		print_text_breakdown(text);
859 		__ops_text_free(text);
860 		end_subpacket();
861 		break;
862 
863 	case OPS_PTAG_SS_KEY_FLAGS:
864 		start_subpacket(contents->tag);
865 		print_data("Key Flags", &content->ss_key_flags.data);
866 
867 		text = __ops_showall_ss_key_flags(content->ss_key_flags);
868 		print_text_breakdown(text);
869 		__ops_text_free(text);
870 
871 		end_subpacket();
872 		break;
873 
874 	case OPS_PTAG_SS_KEY_SERVER_PREFS:
875 		start_subpacket(contents->tag);
876 		print_data("Key Server Preferences",
877 			   &content->ss_key_server_prefs.data);
878 
879 		text = __ops_showall_ss_key_server_prefs(content->ss_key_server_prefs);
880 		print_text_breakdown(text);
881 		__ops_text_free(text);
882 
883 		end_subpacket();
884 		break;
885 
886 	case OPS_PTAG_SS_FEATURES:
887 		start_subpacket(contents->tag);
888 		print_data("Features",
889 			   &content->ss_features.data);
890 
891 		text = __ops_showall_ss_features(content->ss_features);
892 		print_text_breakdown(text);
893 		__ops_text_free(text);
894 
895 		end_subpacket();
896 		break;
897 
898 	case OPS_PTAG_SS_NOTATION_DATA:
899 		start_subpacket(contents->tag);
900 		print_indent();
901 		printf("Notation Data:\n");
902 
903 		indent++;
904 		print_data("Flags",
905 			   &content->ss_notation_data.flags);
906 		text = __ops_showall_ss_notation_data_flags(content->ss_notation_data);
907 		print_text_breakdown(text);
908 		__ops_text_free(text);
909 
910 		/* xxx - TODO: print out UTF - rachel */
911 
912 		print_data("Name",
913 			   &content->ss_notation_data.name);
914 
915 		print_data("Value",
916 			   &content->ss_notation_data.value);
917 
918 		indent--;
919 		end_subpacket();
920 		break;
921 
922 	case OPS_PTAG_SS_REGEXP:
923 		start_subpacket(contents->tag);
924 		print_hexdump("Regular Expression",
925 			      (unsigned char *) content->ss_regexp.text,
926 			      strlen(content->ss_regexp.text));
927 		print_string(NULL,
928 			     content->ss_regexp.text);
929 		end_subpacket();
930 		break;
931 
932 	case OPS_PTAG_SS_POLICY_URI:
933 		start_subpacket(contents->tag);
934 		print_string("Policy URL",
935 			     content->ss_policy_url.text);
936 		end_subpacket();
937 		break;
938 
939 	case OPS_PTAG_SS_SIGNERS_USER_ID:
940 		start_subpacket(contents->tag);
941 		print_utf8_string("Signer's User ID", content->ss_signers_user_id.user_id);
942 		end_subpacket();
943 		break;
944 
945 	case OPS_PTAG_SS_PREFERRED_KEY_SERVER:
946 		start_subpacket(contents->tag);
947 		print_string("Preferred Key Server",
948 			     content->ss_preferred_key_server.text);
949 		end_subpacket();
950 		break;
951 
952 	case OPS_PTAG_SS_EMBEDDED_SIGNATURE:
953 		start_subpacket(contents->tag);
954 		end_subpacket();/* \todo print out contents? */
955 		break;
956 
957 	case OPS_PTAG_SS_USERDEFINED00:
958 	case OPS_PTAG_SS_USERDEFINED01:
959 	case OPS_PTAG_SS_USERDEFINED02:
960 	case OPS_PTAG_SS_USERDEFINED03:
961 	case OPS_PTAG_SS_USERDEFINED04:
962 	case OPS_PTAG_SS_USERDEFINED05:
963 	case OPS_PTAG_SS_USERDEFINED06:
964 	case OPS_PTAG_SS_USERDEFINED07:
965 	case OPS_PTAG_SS_USERDEFINED08:
966 	case OPS_PTAG_SS_USERDEFINED09:
967 	case OPS_PTAG_SS_USERDEFINED10:
968 		start_subpacket(contents->tag);
969 		print_hexdump("Internal or user-defined",
970 			      content->ss_userdefined.data.contents,
971 			      content->ss_userdefined.data.len);
972 		end_subpacket();
973 		break;
974 
975 	case OPS_PTAG_SS_RESERVED:
976 		start_subpacket(contents->tag);
977 		print_hexdump("Reserved",
978 			      content->ss_userdefined.data.contents,
979 			      content->ss_userdefined.data.len);
980 		end_subpacket();
981 		break;
982 
983 	case OPS_PTAG_SS_REVOCATION_REASON:
984 		start_subpacket(contents->tag);
985 		print_hexdump("Revocation Reason",
986 			      &content->ss_revocation_reason.code,
987 			      1);
988 		str = __ops_show_ss_rr_code(content->ss_revocation_reason.code);
989 		print_string(NULL, str);
990 		/* xxx - todo : output text as UTF-8 string */
991 		end_subpacket();
992 		break;
993 
994 	case OPS_PTAG_CT_LITERAL_DATA_HEADER:
995 		print_tagname("LITERAL DATA HEADER");
996 		printf("  literal data header format=%c filename='%s'\n",
997 		       content->literal_data_header.format,
998 		       content->literal_data_header.filename);
999 		showtime("    modification time",
1000 			 content->literal_data_header.modification_time);
1001 		printf("\n");
1002 		break;
1003 
1004 	case OPS_PTAG_CT_LITERAL_DATA_BODY:
1005 		print_tagname("LITERAL DATA BODY");
1006 		printf("  literal data body length=%d\n",
1007 		       content->literal_data_body.length);
1008 		printf("    data=");
1009 		print_escaped(content->literal_data_body.data,
1010 			      content->literal_data_body.length);
1011 		printf("\n");
1012 		break;
1013 
1014 	case OPS_PTAG_CT_SIGNATURE_HEADER:
1015 		print_tagname("SIGNATURE");
1016 		print_indent();
1017 		print_unsigned_int("Signature Version",
1018 				   (unsigned)content->signature.info.version);
1019 		if (content->signature.info.creation_time_set)
1020 			print_time("Signature Creation Time",
1021 				content->signature.info.creation_time);
1022 
1023 		print_string_and_value("Signature Type",
1024 			    __ops_show_sig_type(content->signature.info.type),
1025 				       content->signature.info.type);
1026 
1027 		if (content->signature.info.signer_id_set)
1028 			print_hexdump_data("Signer ID",
1029 					   content->signature.info.signer_id,
1030 				  sizeof(content->signature.info.signer_id));
1031 
1032 		print_string_and_value("Public Key Algorithm",
1033 			__ops_show_pka(content->signature.info.key_algorithm),
1034 				     content->signature.info.key_algorithm);
1035 		print_string_and_value("Hash Algorithm",
1036 				       __ops_show_hash_algorithm(content->signature.info.hash_algorithm),
1037 				    content->signature.info.hash_algorithm);
1038 
1039 		break;
1040 
1041 	case OPS_PTAG_CT_SIGNATURE_FOOTER:
1042 		print_indent();
1043 		print_hexdump_data("hash2", &content->signature.hash2[0], 2);
1044 
1045 		switch (content->signature.info.key_algorithm) {
1046 		case OPS_PKA_RSA:
1047 			print_bn("sig", content->signature.info.signature.rsa.sig);
1048 			break;
1049 
1050 		case OPS_PKA_DSA:
1051 			print_bn("r", content->signature.info.signature.dsa.r);
1052 			print_bn("s", content->signature.info.signature.dsa.s);
1053 			break;
1054 
1055 		case OPS_PKA_ELGAMAL_ENCRYPT_OR_SIGN:
1056 			print_bn("r", content->signature.info.signature.elgamal.r);
1057 			print_bn("s", content->signature.info.signature.elgamal.s);
1058 			break;
1059 
1060 		case OPS_PKA_PRIVATE00:
1061 		case OPS_PKA_PRIVATE01:
1062 		case OPS_PKA_PRIVATE02:
1063 		case OPS_PKA_PRIVATE03:
1064 		case OPS_PKA_PRIVATE04:
1065 		case OPS_PKA_PRIVATE05:
1066 		case OPS_PKA_PRIVATE06:
1067 		case OPS_PKA_PRIVATE07:
1068 		case OPS_PKA_PRIVATE08:
1069 		case OPS_PKA_PRIVATE09:
1070 		case OPS_PKA_PRIVATE10:
1071 			print_data("Private/Experimental",
1072 			   &content->signature.info.signature.unknown.data);
1073 			break;
1074 
1075 		default:
1076 			assert( /* CONSTCOND */ 0);
1077 		}
1078 		break;
1079 
1080 	case OPS_PARSER_CMD_GET_SK_PASSPHRASE:
1081 		print_tagname("OPS_PARSER_CMD_GET_SK_PASSPHRASE");
1082 		break;
1083 
1084 	case OPS_PTAG_CT_SECRET_KEY:
1085 		print_tagname("OPS_PTAG_CT_SECRET_KEY");
1086 		__ops_print_secret_key_verbose(contents->tag, &content->secret_key);
1087 		break;
1088 
1089 	case OPS_PTAG_CT_ENCRYPTED_SECRET_KEY:
1090 		print_tagname("OPS_PTAG_CT_ENCRYPTED_SECRET_KEY");
1091 		__ops_print_secret_key_verbose(contents->tag, &content->secret_key);
1092 		break;
1093 
1094 	case OPS_PTAG_CT_ARMOUR_HEADER:
1095 		print_tagname("ARMOUR HEADER");
1096 		print_string("type", content->armour_header.type);
1097 		break;
1098 
1099 	case OPS_PTAG_CT_SIGNED_CLEARTEXT_HEADER:
1100 		print_tagname("SIGNED CLEARTEXT HEADER");
1101 		print_headers(&content->signed_cleartext_header.headers);
1102 		break;
1103 
1104 	case OPS_PTAG_CT_SIGNED_CLEARTEXT_BODY:
1105 		print_tagname("SIGNED CLEARTEXT BODY");
1106 		print_block("signed cleartext", content->signed_cleartext_body.data,
1107 			    content->signed_cleartext_body.length);
1108 		break;
1109 
1110 	case OPS_PTAG_CT_SIGNED_CLEARTEXT_TRAILER:
1111 		print_tagname("SIGNED CLEARTEXT TRAILER");
1112 		printf("hash algorithm: %d\n",
1113 		       content->signed_cleartext_trailer.hash->algorithm);
1114 		printf("\n");
1115 		break;
1116 
1117 	case OPS_PTAG_CT_UNARMOURED_TEXT:
1118 		if (!unarmoured) {
1119 			print_tagname("UNARMOURED TEXT");
1120 			unarmoured = true;
1121 		}
1122 		putchar('[');
1123 		print_escaped(content->unarmoured_text.data,
1124 			      content->unarmoured_text.length);
1125 		putchar(']');
1126 		break;
1127 
1128 	case OPS_PTAG_CT_ARMOUR_TRAILER:
1129 		print_tagname("ARMOUR TRAILER");
1130 		print_string("type", content->armour_header.type);
1131 		break;
1132 
1133 	case OPS_PTAG_CT_PK_SESSION_KEY:
1134 	case OPS_PTAG_CT_ENCRYPTED_PK_SESSION_KEY:
1135 		__ops_print_pk_session_key(contents->tag, &content->pk_session_key);
1136 		break;
1137 
1138 	case OPS_PARSER_CMD_GET_SECRET_KEY:
1139 		__ops_print_pk_session_key(OPS_PTAG_CT_ENCRYPTED_PK_SESSION_KEY,
1140 				    content->get_secret_key.pk_session_key);
1141 		break;
1142 
1143 	default:
1144 		print_tagname("UNKNOWN PACKET TYPE");
1145 		fprintf(stderr, "__ops_print_packet: unknown tag=%d (0x%x)\n", contents->tag,
1146 			contents->tag);
1147 		exit(1);
1148 	}
1149 	return 1;
1150 }
1151 
1152 static __ops_parse_cb_return_t
1153 cb_list_packets(const __ops_parser_content_t * contents, __ops_parse_cb_info_t * cbinfo)
1154 {
1155 	OPS_USED(cbinfo);
1156 
1157 	__ops_print_packet(contents);
1158 #ifdef XXX
1159 	if (unarmoured && contents->tag != OPS_PTAG_CT_UNARMOURED_TEXT) {
1160 		unarmoured = false;
1161 		puts("UNARMOURED TEXT ends");
1162 	}
1163 	switch (contents->tag) {
1164 	case OPS_PARSER_ERROR:
1165 		printf("parse error: %s\n", content->error.error);
1166 		break;
1167 
1168 	case OPS_PARSER_ERRCODE:
1169 		printf("parse error: %s\n",
1170 		       __ops_errcode(content->errcode.errcode));
1171 		break;
1172 
1173 	case OPS_PARSER_PACKET_END:
1174 		print_packet_hex(&content->packet);
1175 		break;
1176 
1177 	case OPS_PARSER_PTAG:
1178 		if (content->ptag.content_tag == OPS_PTAG_CT_PUBLIC_KEY) {
1179 			indent = 0;
1180 			printf("\n*** NEXT KEY ***\n");
1181 		}
1182 		printf("\n");
1183 		print_indent();
1184 		printf("==== ptag new_format=%d content_tag=%d length_type=%d"
1185 		       " length=0x%x (%d) position=0x%x (%d)\n", content->ptag.new_format,
1186 		       content->ptag.content_tag, content->ptag.length_type,
1187 		       content->ptag.length, content->ptag.length,
1188 		       content->ptag.position, content->ptag.position);
1189 		print_tagname(__ops_show_packet_tag(content->ptag.content_tag));
1190 		break;
1191 
1192 	case OPS_PTAG_CT_SE_DATA_HEADER:
1193 		print_tagname("SYMMETRIC ENCRYPTED DATA");
1194 		break;
1195 
1196 	case OPS_PTAG_CT_SE_IP_DATA_HEADER:
1197 		print_tagname("SYMMETRIC ENCRYPTED INTEGRITY PROTECTED DATA HEADER");
1198 		printf("Version: %d\n", content->se_ip_data_header.version);
1199 		break;
1200 
1201 	case OPS_PTAG_CT_SE_IP_DATA_BODY:
1202 		print_tagname("SYMMETRIC ENCRYPTED INTEGRITY PROTECTED DATA BODY");
1203 		printf("  data body length=%d\n",
1204 		       content->se_data_body.length);
1205 		printf("    data=");
1206 		hexdump(content->se_data_body.data,
1207 			content->se_data_body.length, "");
1208 		printf("\n");
1209 		break;
1210 
1211 	case OPS_PTAG_CT_PUBLIC_KEY:
1212 	case OPS_PTAG_CT_PUBLIC_SUBKEY:
1213 		if (contents->tag == OPS_PTAG_CT_PUBLIC_KEY)
1214 			print_tagname("PUBLIC KEY");
1215 		else
1216 			print_tagname("PUBLIC SUBKEY");
1217 
1218 		__ops_print_public_key(&content->public_key);
1219 		break;
1220 
1221 	case OPS_PTAG_CT_TRUST:
1222 		print_tagname("TRUST");
1223 		print_data("Trust", &content->trust.data);
1224 		break;
1225 
1226 	case OPS_PTAG_CT_USER_ID:
1227 		/* XXX: how do we print UTF-8? */
1228 		print_tagname("USER ID");
1229 		print_utf8_string("user_id", content->user_id.user_id);
1230 		break;
1231 
1232 	case OPS_PTAG_CT_SIGNATURE:
1233 		print_tagname("SIGNATURE");
1234 		print_indent();
1235 		print_unsigned_int("Signature Version",
1236 				   content->signature.info.version);
1237 		if (content->signature.info.creation_time_set)
1238 			print_time("Signature Creation Time",
1239 				   content->signature.info.creation_time);
1240 
1241 		print_string_and_value("Signature Type",
1242 			    __ops_show_sig_type(content->signature.info.type),
1243 				       content->signature.info.type);
1244 
1245 		if (content->signature.info.signer_id_set)
1246 			print_hexdump_data("Signer ID",
1247 					   content->signature.info.signer_id,
1248 				  sizeof(content->signature.info.signer_id));
1249 
1250 		print_string_and_value("Public Key Algorithm",
1251 			__ops_show_pka(content->signature.info.key_algorithm),
1252 				     content->signature.info.key_algorithm);
1253 		print_string_and_value("Hash Algorithm",
1254 				       __ops_show_hash_algorithm(content->signature.info.hash_algorithm),
1255 				    content->signature.info.hash_algorithm);
1256 		print_unsigned_int("Hashed data len", content->signature.info.v4_hashed_data_length);
1257 
1258 		print_indent();
1259 		print_hexdump_data("hash2", &content->signature.hash2[0], 2);
1260 
1261 		switch (content->signature.info.key_algorithm) {
1262 		case OPS_PKA_RSA:
1263 		case OPS_PKA_RSA_SIGN_ONLY:
1264 			print_bn("sig", content->signature.info.signature.rsa.sig);
1265 			break;
1266 
1267 		case OPS_PKA_DSA:
1268 			print_bn("r", content->signature.info.signature.dsa.r);
1269 			print_bn("s", content->signature.info.signature.dsa.s);
1270 			break;
1271 
1272 		case OPS_PKA_ELGAMAL_ENCRYPT_OR_SIGN:
1273 			print_bn("r", content->signature.info.signature.elgamal.r);
1274 			print_bn("s", content->signature.info.signature.elgamal.s);
1275 			break;
1276 
1277 		default:
1278 			assert(0);
1279 		}
1280 
1281 		if (content->signature.hash)
1282 			printf("data hash is set\n");
1283 
1284 		break;
1285 
1286 	case OPS_PTAG_CT_COMPRESSED:
1287 		print_tagname("COMPRESSED");
1288 		print_unsigned_int("Compressed Data Type", content->compressed.type);
1289 		break;
1290 
1291 	case OPS_PTAG_CT_ONE_PASS_SIGNATURE:
1292 		print_tagname("ONE PASS SIGNATURE");
1293 
1294 		print_unsigned_int("Version", content->one_pass_signature.version);
1295 		print_string_and_value("Signature Type",
1296 		    __ops_show_sig_type(content->one_pass_signature.sig_type),
1297 				       content->one_pass_signature.sig_type);
1298 		print_string_and_value("Hash Algorithm",
1299 				       __ops_show_hash_algorithm(content->one_pass_signature.hash_algorithm),
1300 				content->one_pass_signature.hash_algorithm);
1301 		print_string_and_value("Public Key Algorithm",
1302 		    __ops_show_pka(content->one_pass_signature.key_algorithm),
1303 				 content->one_pass_signature.key_algorithm);
1304 		print_hexdump_data("Signer ID",
1305 				   content->one_pass_signature.keyid,
1306 				   sizeof(content->one_pass_signature.keyid));
1307 
1308 		print_unsigned_int("Nested",
1309 				   content->one_pass_signature.nested);
1310 		break;
1311 
1312 	case OPS_PTAG_CT_USER_ATTRIBUTE:
1313 		print_tagname("USER ATTRIBUTE");
1314 		print_hexdump("User Attribute",
1315 			      content->user_attribute.data.contents,
1316 			      content->user_attribute.data.len);
1317 		break;
1318 
1319 	case OPS_PTAG_RAW_SS:
1320 		assert(!contents->critical);
1321 		start_subpacket(contents->tag);
1322 		print_unsigned_int("Raw Signature Subpacket: tag",
1323 		   content->ss_raw.tag - OPS_PTAG_SIGNATURE_SUBPACKET_BASE);
1324 		print_hexdump("Raw Data",
1325 			      content->ss_raw.raw,
1326 			      content->ss_raw.length);
1327 		break;
1328 
1329 	case OPS_PTAG_SS_CREATION_TIME:
1330 		start_subpacket(contents->tag);
1331 		print_time("Signature Creation Time", content->ss_time.time);
1332 		end_subpacket();
1333 		break;
1334 
1335 	case OPS_PTAG_SS_EXPIRATION_TIME:
1336 		start_subpacket(contents->tag);
1337 		print_duration("Signature Expiration Time", content->ss_time.time);
1338 		end_subpacket();
1339 		break;
1340 
1341 	case OPS_PTAG_SS_KEY_EXPIRATION_TIME:
1342 		start_subpacket(contents->tag);
1343 		print_duration("Key Expiration Time", content->ss_time.time);
1344 		end_subpacket();
1345 		break;
1346 
1347 	case OPS_PTAG_SS_TRUST:
1348 		start_subpacket(contents->tag);
1349 		print_string("Trust Signature", "");
1350 		print_unsigned_int("Level",
1351 				   content->ss_trust.level);
1352 		print_unsigned_int("Amount",
1353 				   content->ss_trust.amount);
1354 		end_subpacket();
1355 		break;
1356 
1357 	case OPS_PTAG_SS_REVOCABLE:
1358 		start_subpacket(contents->tag);
1359 		print_boolean("Revocable", content->ss_revocable.revocable);
1360 		end_subpacket();
1361 		break;
1362 
1363 	case OPS_PTAG_SS_REVOCATION_KEY:
1364 		start_subpacket(contents->tag);
1365 		/* not yet tested */
1366 		printf("  revocation key: class=0x%x",
1367 		       content->ss_revocation_key.class);
1368 		if (content->ss_revocation_key.class & 0x40)
1369 			printf(" (sensitive)");
1370 		printf(", algid=0x%x",
1371 		       content->ss_revocation_key.algid);
1372 		printf(", fingerprint=");
1373 		hexdump(content->ss_revocation_key.fingerprint, 20, "");
1374 		printf("\n");
1375 		end_subpacket();
1376 		break;
1377 
1378 	case OPS_PTAG_SS_ISSUER_KEY_ID:
1379 		start_subpacket(contents->tag);
1380 		print_hexdump("Issuer Key Id",
1381 			      &content->ss_issuer_key_id.key_id[0],
1382 			      sizeof(content->ss_issuer_key_id.key_id));
1383 		end_subpacket();
1384 		break;
1385 
1386 	case OPS_PTAG_SS_PREFERRED_SKA:
1387 		start_subpacket(contents->tag);
1388 		print_data("Preferred Symmetric Algorithms",
1389 			   &content->ss_preferred_ska.data);
1390 
1391 		text = __ops_showall_ss_preferred_ska(content->ss_preferred_ska);
1392 		print_text_breakdown(text);
1393 		__ops_text_free(text);
1394 
1395 		end_subpacket();
1396 		break;
1397 
1398 	case OPS_PTAG_SS_PRIMARY_USER_ID:
1399 		start_subpacket(contents->tag);
1400 		print_boolean("Primary User ID",
1401 			      content->ss_primary_user_id.primary_user_id);
1402 		end_subpacket();
1403 		break;
1404 
1405 	case OPS_PTAG_SS_PREFERRED_HASH:
1406 		start_subpacket(contents->tag);
1407 		print_data("Preferred Hash Algorithms",
1408 			   &content->ss_preferred_hash.data);
1409 
1410 		text = __ops_showall_ss_preferred_hash(content->ss_preferred_hash);
1411 		print_text_breakdown(text);
1412 		__ops_text_free(text);
1413 		end_subpacket();
1414 		break;
1415 
1416 	case OPS_PTAG_SS_PREFERRED_COMPRESSION:
1417 		start_subpacket(contents->tag);
1418 		print_data("Preferred Compression Algorithms",
1419 			   &content->ss_preferred_compression.data);
1420 
1421 		text = __ops_showall_ss_preferred_compression(content->ss_preferred_compression);
1422 		print_text_breakdown(text);
1423 		__ops_text_free(text);
1424 		end_subpacket();
1425 		break;
1426 
1427 	case OPS_PTAG_SS_KEY_FLAGS:
1428 		start_subpacket(contents->tag);
1429 		print_data("Key Flags", &content->ss_key_flags.data);
1430 
1431 		text = __ops_showall_ss_key_flags(content->ss_key_flags);
1432 		print_text_breakdown(text);
1433 		__ops_text_free(text);
1434 
1435 		end_subpacket();
1436 		break;
1437 
1438 	case OPS_PTAG_SS_KEY_SERVER_PREFS:
1439 		start_subpacket(contents->tag);
1440 		print_data("Key Server Preferences",
1441 			   &content->ss_key_server_prefs.data);
1442 
1443 		text = __ops_showall_ss_key_server_prefs(content->ss_key_server_prefs);
1444 		print_text_breakdown(text);
1445 		__ops_text_free(text);
1446 
1447 		end_subpacket();
1448 		break;
1449 
1450 	case OPS_PTAG_SS_FEATURES:
1451 		start_subpacket(contents->tag);
1452 		print_data("Features",
1453 			   &content->ss_features.data);
1454 
1455 		text = __ops_showall_ss_features(content->ss_features);
1456 		print_text_breakdown(text);
1457 		__ops_text_free(text);
1458 
1459 		end_subpacket();
1460 		break;
1461 
1462 	case OPS_PTAG_SS_NOTATION_DATA:
1463 		start_subpacket(contents->tag);
1464 		print_indent();
1465 		printf("Notation Data:\n");
1466 
1467 		indent++;
1468 		print_data("Flags",
1469 			   &content->ss_notation_data.flags);
1470 		text = __ops_showall_ss_notation_data_flags(content->ss_notation_data);
1471 		print_text_breakdown(text);
1472 		__ops_text_free(text);
1473 
1474 		/* xxx - TODO: print out UTF - rachel */
1475 
1476 		print_data("Name",
1477 			   &content->ss_notation_data.name);
1478 
1479 		print_data("Value",
1480 			   &content->ss_notation_data.value);
1481 
1482 		indent--;
1483 		end_subpacket();
1484 		break;
1485 
1486 	case OPS_PTAG_SS_REGEXP:
1487 		start_subpacket(contents->tag);
1488 		print_hexdump("Regular Expression",
1489 			      (unsigned char *) content->ss_regexp.text,
1490 			      strlen(content->ss_regexp.text));
1491 		print_string(NULL,
1492 			     content->ss_regexp.text);
1493 		end_subpacket();
1494 		break;
1495 
1496 	case OPS_PTAG_SS_POLICY_URL:
1497 		start_subpacket(contents->tag);
1498 		print_string("Policy URL",
1499 			     content->ss_policy_url.text);
1500 		end_subpacket();
1501 		break;
1502 
1503 	case OPS_PTAG_SS_SIGNERS_USER_ID:
1504 		start_subpacket(contents->tag);
1505 		print_utf8_string("Signer's User ID", content->ss_signers_user_id.user_id);
1506 		end_subpacket();
1507 		break;
1508 
1509 	case OPS_PTAG_SS_PREFERRED_KEY_SERVER:
1510 		start_subpacket(contents->tag);
1511 		print_string("Preferred Key Server",
1512 			     content->ss_preferred_key_server.text);
1513 		end_subpacket();
1514 		break;
1515 
1516 	case OPS_PTAG_SS_USERDEFINED00:
1517 	case OPS_PTAG_SS_USERDEFINED01:
1518 	case OPS_PTAG_SS_USERDEFINED02:
1519 	case OPS_PTAG_SS_USERDEFINED03:
1520 	case OPS_PTAG_SS_USERDEFINED04:
1521 	case OPS_PTAG_SS_USERDEFINED05:
1522 	case OPS_PTAG_SS_USERDEFINED06:
1523 	case OPS_PTAG_SS_USERDEFINED07:
1524 	case OPS_PTAG_SS_USERDEFINED08:
1525 	case OPS_PTAG_SS_USERDEFINED09:
1526 	case OPS_PTAG_SS_USERDEFINED10:
1527 		start_subpacket(contents->tag);
1528 		print_hexdump("Internal or user-defined",
1529 			      content->ss_userdefined.data.contents,
1530 			      content->ss_userdefined.data.len);
1531 		end_subpacket();
1532 		break;
1533 
1534 	case OPS_PTAG_SS_RESERVED:
1535 		start_subpacket(contents->tag);
1536 		print_hexdump("Reserved",
1537 			      content->ss_userdefined.data.contents,
1538 			      content->ss_userdefined.data.len);
1539 		end_subpacket();
1540 		break;
1541 
1542 	case OPS_PTAG_SS_REVOCATION_REASON:
1543 		start_subpacket(contents->tag);
1544 		print_hexdump("Revocation Reason",
1545 			      &content->ss_revocation_reason.code,
1546 			      1);
1547 		str = __ops_show_ss_rr_code(content->ss_revocation_reason.code);
1548 		print_string(NULL, str);
1549 		/* xxx - todo : output text as UTF-8 string */
1550 		end_subpacket();
1551 		break;
1552 
1553 	case OPS_PTAG_CT_LITERAL_DATA_HEADER:
1554 		print_tagname("LITERAL DATA HEADER");
1555 		printf("  literal data header format=%c filename='%s'\n",
1556 		       content->literal_data_header.format,
1557 		       content->literal_data_header.filename);
1558 		print_time("    modification time",
1559 			   content->literal_data_header.modification_time);
1560 		printf("\n");
1561 		break;
1562 
1563 	case OPS_PTAG_CT_LITERAL_DATA_BODY:
1564 		print_tagname("LITERAL DATA BODY");
1565 		printf("  literal data body length=%d\n",
1566 		       content->literal_data_body.length);
1567 		printf("    data=");
1568 		print_escaped(content->literal_data_body.data,
1569 			      content->literal_data_body.length);
1570 		printf("\n");
1571 		break;
1572 
1573 	case OPS_PTAG_CT_SIGNATURE_HEADER:
1574 		print_tagname("SIGNATURE");
1575 		print_indent();
1576 		print_unsigned_int("Signature Version",
1577 				   content->signature.info.version);
1578 		if (content->signature.info.creation_time_set)
1579 			print_time("Signature Creation Time", content->signature.info.creation_time);
1580 
1581 		print_string_and_value("Signature Type",
1582 			    __ops_show_sig_type(content->signature.info.type),
1583 				       content->signature.info.type);
1584 
1585 		if (content->signature.info.signer_id_set)
1586 			print_hexdump_data("Signer ID",
1587 					   content->signature.info.signer_id,
1588 				  sizeof(content->signature.info.signer_id));
1589 
1590 		print_string_and_value("Public Key Algorithm",
1591 			__ops_show_pka(content->signature.info.key_algorithm),
1592 				     content->signature.info.key_algorithm);
1593 		print_string_and_value("Hash Algorithm",
1594 				       __ops_show_hash_algorithm(content->signature.info.hash_algorithm),
1595 				    content->signature.info.hash_algorithm);
1596 
1597 		break;
1598 
1599 	case OPS_PTAG_CT_SIGNATURE_FOOTER:
1600 		print_indent();
1601 		print_hexdump_data("hash2", &content->signature.hash2[0], 2);
1602 
1603 		switch (content->signature.info.key_algorithm) {
1604 		case OPS_PKA_RSA:
1605 			print_bn("sig", content->signature.info.signature.rsa.sig);
1606 			break;
1607 
1608 		case OPS_PKA_DSA:
1609 			print_bn("r", content->signature.info.signature.dsa.r);
1610 			print_bn("s", content->signature.info.signature.dsa.s);
1611 			break;
1612 
1613 		case OPS_PKA_ELGAMAL_ENCRYPT_OR_SIGN:
1614 			print_bn("r", content->signature.info.signature.elgamal.r);
1615 			print_bn("s", content->signature.info.signature.elgamal.s);
1616 			break;
1617 
1618 		case OPS_PKA_PRIVATE00:
1619 		case OPS_PKA_PRIVATE01:
1620 		case OPS_PKA_PRIVATE02:
1621 		case OPS_PKA_PRIVATE03:
1622 		case OPS_PKA_PRIVATE04:
1623 		case OPS_PKA_PRIVATE05:
1624 		case OPS_PKA_PRIVATE06:
1625 		case OPS_PKA_PRIVATE07:
1626 		case OPS_PKA_PRIVATE08:
1627 		case OPS_PKA_PRIVATE09:
1628 		case OPS_PKA_PRIVATE10:
1629 			print_data("Private/Experimental",
1630 			   &content->signature.info.signature.unknown.data);
1631 			break;
1632 
1633 		default:
1634 			assert(0);
1635 		}
1636 		break;
1637 
1638 	case OPS_PARSER_CMD_GET_SK_PASSPHRASE:
1639 		if (cbinfo->cryptinfo.cb_get_passphrase) {
1640 			return cbinfo->cryptinfo.cb_get_passphrase(contents, cbinfo);
1641 		}
1642 		break;
1643 
1644 	case OPS_PTAG_CT_SECRET_KEY:
1645 	case OPS_PTAG_CT_ENCRYPTED_SECRET_KEY:
1646 		__ops_print_secret_key_verbose(contents->tag, &content->secret_key);
1647 		break;
1648 
1649 	case OPS_PTAG_CT_ARMOUR_HEADER:
1650 		print_tagname("ARMOUR HEADER");
1651 		print_string("type", content->armour_header.type);
1652 		break;
1653 
1654 	case OPS_PTAG_CT_SIGNED_CLEARTEXT_HEADER:
1655 		print_tagname("SIGNED CLEARTEXT HEADER");
1656 		print_headers(&content->signed_cleartext_header.headers);
1657 		break;
1658 
1659 	case OPS_PTAG_CT_SIGNED_CLEARTEXT_BODY:
1660 		print_tagname("SIGNED CLEARTEXT BODY");
1661 		print_block("signed cleartext", content->signed_cleartext_body.data,
1662 			    content->signed_cleartext_body.length);
1663 		break;
1664 
1665 	case OPS_PTAG_CT_SIGNED_CLEARTEXT_TRAILER:
1666 		print_tagname("SIGNED CLEARTEXT TRAILER");
1667 		printf("hash algorithm: %d\n",
1668 		       content->signed_cleartext_trailer.hash->algorithm);
1669 		printf("\n");
1670 		break;
1671 
1672 	case OPS_PTAG_CT_UNARMOURED_TEXT:
1673 		if (!unarmoured) {
1674 			print_tagname("UNARMOURED TEXT");
1675 			unarmoured = true;
1676 		}
1677 		putchar('[');
1678 		print_escaped(content->unarmoured_text.data,
1679 			      content->unarmoured_text.length);
1680 		putchar(']');
1681 		break;
1682 
1683 	case OPS_PTAG_CT_ARMOUR_TRAILER:
1684 		print_tagname("ARMOUR TRAILER");
1685 		print_string("type", content->armour_header.type);
1686 		break;
1687 
1688 	case OPS_PTAG_CT_PK_SESSION_KEY:
1689 	case OPS_PTAG_CT_ENCRYPTED_PK_SESSION_KEY:
1690 		__ops_print_pk_session_key(contents->tag, &content->pk_session_key);
1691 		break;
1692 
1693 	case OPS_PARSER_CMD_GET_SECRET_KEY:
1694 		__ops_print_pk_session_key(OPS_PTAG_CT_ENCRYPTED_PK_SESSION_KEY,
1695 				    content->get_secret_key.pk_session_key);
1696 		return get_secret_key_cb(contents, cbinfo);
1697 
1698 	default:
1699 		print_tagname("UNKNOWN PACKET TYPE");
1700 		fprintf(stderr, "packet-dump: unknown tag=%d (0x%x)\n", contents->tag,
1701 			contents->tag);
1702 		exit(1);
1703 	}
1704 #endif				/* XXX */
1705 	return OPS_RELEASE_MEMORY;
1706 }
1707 
1708 /**
1709 \ingroup Core_Print
1710 \param filename
1711 \param armour
1712 \param keyring
1713 \param cb_get_passphrase
1714 */
1715 void
1716 __ops_list_packets(char *filename, bool armour, __ops_keyring_t * keyring, __ops_parse_cb_t * cb_get_passphrase)
1717 {
1718 	int             fd = 0;
1719 	__ops_parse_info_t *pinfo = NULL;
1720 	const bool accumulate = true;
1721 
1722 	fd = __ops_setup_file_read(&pinfo, filename, NULL, cb_list_packets, accumulate);
1723 	__ops_parse_options(pinfo, OPS_PTAG_SS_ALL, OPS_PARSE_PARSED);
1724 	pinfo->cryptinfo.keyring = keyring;
1725 	pinfo->cryptinfo.cb_get_passphrase = cb_get_passphrase;
1726 
1727 	if (armour)
1728 		__ops_reader_push_dearmour(pinfo);
1729 
1730 	__ops_parse_and_print_errors(pinfo);
1731 
1732 	__ops_teardown_file_read(pinfo, fd);
1733 }
1734