xref: /netbsd-src/crypto/external/bsd/netpgp/dist/src/lib/packet-print.c (revision 93bf6008f8b7982c1d1a9486e4a4a0e687fe36eb)
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", 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 	int             i;
370 	int             rem;
371 	int             blksz = 4;
372 
373 	printf("\nhexdump of packet contents follows:\n");
374 
375 
376 	for (i = 1, cur = packet->raw; cur < (packet->raw + packet->length); cur += blksz, i++) {
377 		rem = packet->raw + packet->length - cur;
378 		hexdump(cur, rem <= blksz ? rem : blksz, "");
379 		printf(" ");
380 		if (!(i % 8))
381 			printf("\n");
382 
383 	}
384 
385 	printf("\n");
386 }
387 
388 static void
389 print_escaped(const unsigned char *data, size_t length)
390 {
391 	while (length-- > 0) {
392 		if ((*data >= 0x20 && *data < 0x7f && *data != '%') || *data == '\n')
393 			putchar(*data);
394 		else
395 			printf("%%%02x", *data);
396 		++data;
397 	}
398 }
399 
400 static void
401 print_string(const char *name, const char *str)
402 {
403 	print_name(name);
404 	print_escaped((const unsigned char *) str, strlen(str));
405 	putchar('\n');
406 }
407 
408 static void
409 print_utf8_string(const char *name, const unsigned char *str)
410 {
411 	/* \todo Do this better for non-English character sets */
412 	print_string(name, (const char *) str);
413 }
414 
415 static void
416 print_duration(const char *name, time_t t)
417 {
418 	int             mins, hours, days, years;
419 
420 	print_indent();
421 	printf("%s: ", name);
422 	printf("duration %" PRItime "d seconds", (long long) t);
423 
424 	mins = t / 60;
425 	hours = mins / 60;
426 	days = hours / 24;
427 	years = days / 365;
428 
429 	printf(" (approx. ");
430 	if (years)
431 		printf("%d %s", years, years == 1 ? "year" : "years");
432 	else if (days)
433 		printf("%d %s", days, days == 1 ? "day" : "days");
434 	else if (hours)
435 		printf("%d %s", hours, hours == 1 ? "hour" : "hours");
436 
437 	printf(")");
438 	printf("\n");
439 }
440 
441 static void
442 print_boolean(const char *name, unsigned char boolval)
443 {
444 	print_name(name);
445 	printf("%s\n", (boolval) ? "Yes" : "No");
446 }
447 
448 static void
449 print_text_breakdown(__ops_text_t * text)
450 {
451 	unsigned        i;
452 	const char     *prefix = ".. ";
453 
454 	/* these were recognised */
455 
456 	for (i = 0; i < text->known.used; i++) {
457 		print_indent();
458 		printf(prefix);
459 		printf("%s\n", text->known.strings[i]);
460 	}
461 
462 	/*
463 	 * these were not recognised. the strings will contain the hex value
464 	 * of the unrecognised value in string format - see
465 	 * process_octet_str()
466 	 */
467 
468 	if (text->unknown.used) {
469 		printf("\n");
470 		print_indent();
471 		printf("Not Recognised: ");
472 	}
473 	for (i = 0; i < text->unknown.used; i++) {
474 		print_indent();
475 		printf(prefix);
476 		printf("%s\n", text->unknown.strings[i]);
477 	}
478 
479 }
480 
481 static void
482 print_headers(const __ops_headers_t * headers)
483 {
484 	unsigned        n;
485 
486 	for (n = 0; n < headers->nheaders; ++n)
487 		printf("%s=%s\n", headers->headers[n].key, headers->headers[n].value);
488 }
489 
490 static void
491 print_block(const char *name, const unsigned char *str,
492 	    size_t length)
493 {
494 	int             o = length;
495 
496 	print_indent();
497 	printf(">>>>> %s >>>>>\n", name);
498 
499 	print_indent();
500 	for (; length > 0; --length) {
501 		if (*str >= 0x20 && *str < 0x7f && *str != '%')
502 			putchar(*str);
503 		else if (*str == '\n') {
504 			putchar(*str);
505 			print_indent();
506 		} else
507 			printf("%%%02x", *str);
508 		++str;
509 	}
510 	if (o && str[-1] != '\n') {
511 		putchar('\n');
512 		print_indent();
513 		fputs("[no newline]", stdout);
514 	} else
515 		print_indent();
516 	printf("<<<<< %s <<<<<\n", name);
517 }
518 
519 /**
520 \ingroup Core_Print
521 \param tag
522 \param key
523 */
524 static void
525 __ops_print_pk_session_key(__ops_content_tag_t tag,
526 			 const __ops_pk_session_key_t * key)
527 {
528 	if (tag == OPS_PTAG_CT_PK_SESSION_KEY)
529 		print_tagname("PUBLIC KEY SESSION KEY");
530 	else
531 		print_tagname("ENCRYPTED PUBLIC KEY SESSION KEY");
532 
533 	printf("Version: %d\n", key->version);
534 	print_hexdump("Key ID", key->key_id, sizeof(key->key_id));
535 	printf("Algorithm: %d (%s)\n", key->algorithm,
536 	       __ops_show_pka(key->algorithm));
537 	switch (key->algorithm) {
538 	case OPS_PKA_RSA:
539 		print_bn("encrypted_m", key->parameters.rsa.encrypted_m);
540 		break;
541 
542 	case OPS_PKA_ELGAMAL:
543 		print_bn("g_to_k", key->parameters.elgamal.g_to_k);
544 		print_bn("encrypted_m", key->parameters.elgamal.encrypted_m);
545 		break;
546 
547 	default:
548 		assert( /* CONSTCOND */ 0);
549 	}
550 
551 	if (tag != OPS_PTAG_CT_PK_SESSION_KEY)
552 		return;
553 
554 	printf("Symmetric algorithm: %d (%s)\n", key->symmetric_algorithm,
555 	       __ops_show_symmetric_algorithm(key->symmetric_algorithm));
556 	print_hexdump("Key", key->key, __ops_key_size(key->symmetric_algorithm));
557 	printf("Checksum: %04x\n", key->checksum);
558 }
559 
560 static void
561 start_subpacket(unsigned type)
562 {
563 	indent++;
564 	print_indent();
565 	printf("-- %s (type 0x%02x)\n",
566 	       __ops_show_ss_type(type),
567 	       type - OPS_PTAG_SIGNATURE_SUBPACKET_BASE);
568 }
569 
570 static void
571 end_subpacket(void)
572 {
573 	indent--;
574 }
575 
576 /**
577 \ingroup Core_Print
578 \param contents
579 */
580 int
581 __ops_print_packet(const __ops_parser_content_t * contents)
582 {
583 	const __ops_parser_content_union_t *content = &contents->u;
584 	__ops_text_t     *text;
585 	const char     *str;
586 	static bool unarmoured;
587 
588 	if (unarmoured && contents->tag != OPS_PTAG_CT_UNARMOURED_TEXT) {
589 		unarmoured = false;
590 		puts("UNARMOURED TEXT ends");
591 	}
592 	if (contents->tag == OPS_PARSER_PTAG) {
593 		printf("=> OPS_PARSER_PTAG: %s\n", __ops_show_packet_tag(content->ptag.content_tag));
594 	} else {
595 		printf("=> %s\n", __ops_show_packet_tag(contents->tag));
596 	}
597 
598 	switch (contents->tag) {
599 	case OPS_PARSER_ERROR:
600 		printf("parse error: %s\n", content->error.error);
601 		break;
602 
603 	case OPS_PARSER_ERRCODE:
604 		printf("parse error: %s\n",
605 		       __ops_errcode(content->errcode.errcode));
606 		break;
607 
608 	case OPS_PARSER_PACKET_END:
609 		print_packet_hex(&content->packet);
610 		break;
611 
612 	case OPS_PARSER_PTAG:
613 		if (content->ptag.content_tag == OPS_PTAG_CT_PUBLIC_KEY) {
614 			indent = 0;
615 			printf("\n*** NEXT KEY ***\n");
616 		}
617 		printf("\n");
618 		print_indent();
619 		printf("==== ptag new_format=%d content_tag=%d length_type=%d"
620 		       " length=0x%x (%d) position=0x%x (%d)\n", content->ptag.new_format,
621 		       content->ptag.content_tag, content->ptag.length_type,
622 		       content->ptag.length, content->ptag.length,
623 		       content->ptag.position, content->ptag.position);
624 		print_tagname(__ops_show_packet_tag(content->ptag.content_tag));
625 		break;
626 
627 	case OPS_PTAG_CT_SE_DATA_HEADER:
628 		print_tagname("SYMMETRIC ENCRYPTED DATA");
629 		break;
630 
631 	case OPS_PTAG_CT_SE_IP_DATA_HEADER:
632 		print_tagname("SYMMETRIC ENCRYPTED INTEGRITY PROTECTED DATA HEADER");
633 		printf("Version: %d\n", content->se_ip_data_header.version);
634 		break;
635 
636 	case OPS_PTAG_CT_SE_IP_DATA_BODY:
637 		print_tagname("SYMMETRIC ENCRYPTED INTEGRITY PROTECTED DATA BODY");
638 		printf("  data body length=%d\n",
639 		       content->se_data_body.length);
640 		printf("    data=");
641 		hexdump(content->se_data_body.data,
642 			content->se_data_body.length, "");
643 		printf("\n");
644 		break;
645 
646 	case OPS_PTAG_CT_PUBLIC_KEY:
647 	case OPS_PTAG_CT_PUBLIC_SUBKEY:
648 		if (contents->tag == OPS_PTAG_CT_PUBLIC_KEY)
649 			print_tagname("PUBLIC KEY");
650 		else
651 			print_tagname("PUBLIC SUBKEY");
652 		__ops_print_public_key(&content->public_key);
653 		break;
654 
655 	case OPS_PTAG_CT_TRUST:
656 		print_tagname("TRUST");
657 		print_data("Trust", &content->trust.data);
658 		break;
659 
660 	case OPS_PTAG_CT_USER_ID:
661 		/* XXX: how do we print UTF-8? */
662 		print_tagname("USER ID");
663 		print_utf8_string("user_id", content->user_id.user_id);
664 		break;
665 
666 	case OPS_PTAG_CT_SIGNATURE:
667 		print_tagname("SIGNATURE");
668 		print_indent();
669 		print_unsigned_int("Signature Version",
670 				   content->signature.info.version);
671 		if (content->signature.info.creation_time_set)
672 			print_time("Signature Creation Time",
673 				   content->signature.info.creation_time);
674 
675 		print_string_and_value("Signature Type",
676 			    __ops_show_sig_type(content->signature.info.type),
677 				       content->signature.info.type);
678 
679 		if (content->signature.info.signer_id_set)
680 			print_hexdump_data("Signer ID",
681 					   content->signature.info.signer_id,
682 				  sizeof(content->signature.info.signer_id));
683 
684 		print_string_and_value("Public Key Algorithm",
685 			__ops_show_pka(content->signature.info.key_algorithm),
686 				     content->signature.info.key_algorithm);
687 		print_string_and_value("Hash Algorithm",
688 				       __ops_show_hash_algorithm(content->signature.info.hash_algorithm),
689 				    content->signature.info.hash_algorithm);
690 
691 		print_unsigned_int("Hashed data len", content->signature.info.v4_hashed_data_length);
692 
693 		print_indent();
694 		print_hexdump_data("hash2", &content->signature.hash2[0], 2);
695 
696 		switch (content->signature.info.key_algorithm) {
697 		case OPS_PKA_RSA:
698 		case OPS_PKA_RSA_SIGN_ONLY:
699 			print_bn("sig", content->signature.info.signature.rsa.sig);
700 			break;
701 
702 		case OPS_PKA_DSA:
703 			print_bn("r", content->signature.info.signature.dsa.r);
704 			print_bn("s", content->signature.info.signature.dsa.s);
705 			break;
706 
707 		case OPS_PKA_ELGAMAL_ENCRYPT_OR_SIGN:
708 			print_bn("r", content->signature.info.signature.elgamal.r);
709 			print_bn("s", content->signature.info.signature.elgamal.s);
710 			break;
711 
712 		default:
713 			assert( /* CONSTCOND */ 0);
714 		}
715 
716 		if (content->signature.hash)
717 			printf("data hash is set\n");
718 
719 		break;
720 
721 	case OPS_PTAG_CT_COMPRESSED:
722 		print_tagname("COMPRESSED");
723 		print_unsigned_int("Compressed Data Type", content->compressed.type);
724 		break;
725 
726 	case OPS_PTAG_CT_ONE_PASS_SIGNATURE:
727 		print_tagname("ONE PASS SIGNATURE");
728 
729 		print_unsigned_int("Version", 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 		   content->ss_raw.tag - OPS_PTAG_SIGNATURE_SUBPACKET_BASE);
759 		print_hexdump("Raw Data",
760 			      content->ss_raw.raw,
761 			      content->ss_raw.length);
762 		break;
763 
764 	case OPS_PTAG_SS_CREATION_TIME:
765 		start_subpacket(contents->tag);
766 		print_time("Signature Creation Time", content->ss_time.time);
767 		end_subpacket();
768 		break;
769 
770 	case OPS_PTAG_SS_EXPIRATION_TIME:
771 		start_subpacket(contents->tag);
772 		print_duration("Signature Expiration Time", content->ss_time.time);
773 		end_subpacket();
774 		break;
775 
776 	case OPS_PTAG_SS_KEY_EXPIRATION_TIME:
777 		start_subpacket(contents->tag);
778 		print_duration("Key Expiration Time", content->ss_time.time);
779 		end_subpacket();
780 		break;
781 
782 	case OPS_PTAG_SS_TRUST:
783 		start_subpacket(contents->tag);
784 		print_string("Trust Signature", "");
785 		print_unsigned_int("Level",
786 				   content->ss_trust.level);
787 		print_unsigned_int("Amount",
788 				   content->ss_trust.amount);
789 		end_subpacket();
790 		break;
791 
792 	case OPS_PTAG_SS_REVOCABLE:
793 		start_subpacket(contents->tag);
794 		print_boolean("Revocable", content->ss_revocable.revocable);
795 		end_subpacket();
796 		break;
797 
798 	case OPS_PTAG_SS_REVOCATION_KEY:
799 		start_subpacket(contents->tag);
800 		/* not yet tested */
801 		printf("  revocation key: class=0x%x",
802 		       content->ss_revocation_key.class);
803 		if (content->ss_revocation_key.class & 0x40)
804 			printf(" (sensitive)");
805 		printf(", algid=0x%x",
806 		       content->ss_revocation_key.algid);
807 		printf(", fingerprint=");
808 		hexdump(content->ss_revocation_key.fingerprint, 20, "");
809 		printf("\n");
810 		end_subpacket();
811 		break;
812 
813 	case OPS_PTAG_SS_ISSUER_KEY_ID:
814 		start_subpacket(contents->tag);
815 		print_hexdump("Issuer Key Id",
816 			      &content->ss_issuer_key_id.key_id[0],
817 			      sizeof(content->ss_issuer_key_id.key_id));
818 		end_subpacket();
819 		break;
820 
821 	case OPS_PTAG_SS_PREFERRED_SKA:
822 		start_subpacket(contents->tag);
823 		print_data("Preferred Symmetric Algorithms",
824 			   &content->ss_preferred_ska.data);
825 
826 		text = __ops_showall_ss_preferred_ska(content->ss_preferred_ska);
827 		print_text_breakdown(text);
828 		__ops_text_free(text);
829 
830 		end_subpacket();
831 		break;
832 
833 	case OPS_PTAG_SS_PRIMARY_USER_ID:
834 		start_subpacket(contents->tag);
835 		print_boolean("Primary User ID",
836 			      content->ss_primary_user_id.primary_user_id);
837 		end_subpacket();
838 		break;
839 
840 	case OPS_PTAG_SS_PREFERRED_HASH:
841 		start_subpacket(contents->tag);
842 		print_data("Preferred Hash Algorithms",
843 			   &content->ss_preferred_hash.data);
844 
845 		text = __ops_showall_ss_preferred_hash(content->ss_preferred_hash);
846 		print_text_breakdown(text);
847 		__ops_text_free(text);
848 		end_subpacket();
849 		break;
850 
851 	case OPS_PTAG_SS_PREFERRED_COMPRESSION:
852 		start_subpacket(contents->tag);
853 		print_data("Preferred Compression Algorithms",
854 			   &content->ss_preferred_compression.data);
855 
856 		text = __ops_showall_ss_preferred_compression(content->ss_preferred_compression);
857 		print_text_breakdown(text);
858 		__ops_text_free(text);
859 		end_subpacket();
860 		break;
861 
862 	case OPS_PTAG_SS_KEY_FLAGS:
863 		start_subpacket(contents->tag);
864 		print_data("Key Flags", &content->ss_key_flags.data);
865 
866 		text = __ops_showall_ss_key_flags(content->ss_key_flags);
867 		print_text_breakdown(text);
868 		__ops_text_free(text);
869 
870 		end_subpacket();
871 		break;
872 
873 	case OPS_PTAG_SS_KEY_SERVER_PREFS:
874 		start_subpacket(contents->tag);
875 		print_data("Key Server Preferences",
876 			   &content->ss_key_server_prefs.data);
877 
878 		text = __ops_showall_ss_key_server_prefs(content->ss_key_server_prefs);
879 		print_text_breakdown(text);
880 		__ops_text_free(text);
881 
882 		end_subpacket();
883 		break;
884 
885 	case OPS_PTAG_SS_FEATURES:
886 		start_subpacket(contents->tag);
887 		print_data("Features",
888 			   &content->ss_features.data);
889 
890 		text = __ops_showall_ss_features(content->ss_features);
891 		print_text_breakdown(text);
892 		__ops_text_free(text);
893 
894 		end_subpacket();
895 		break;
896 
897 	case OPS_PTAG_SS_NOTATION_DATA:
898 		start_subpacket(contents->tag);
899 		print_indent();
900 		printf("Notation Data:\n");
901 
902 		indent++;
903 		print_data("Flags",
904 			   &content->ss_notation_data.flags);
905 		text = __ops_showall_ss_notation_data_flags(content->ss_notation_data);
906 		print_text_breakdown(text);
907 		__ops_text_free(text);
908 
909 		/* xxx - TODO: print out UTF - rachel */
910 
911 		print_data("Name",
912 			   &content->ss_notation_data.name);
913 
914 		print_data("Value",
915 			   &content->ss_notation_data.value);
916 
917 		indent--;
918 		end_subpacket();
919 		break;
920 
921 	case OPS_PTAG_SS_REGEXP:
922 		start_subpacket(contents->tag);
923 		print_hexdump("Regular Expression",
924 			      (unsigned char *) content->ss_regexp.text,
925 			      strlen(content->ss_regexp.text));
926 		print_string(NULL,
927 			     content->ss_regexp.text);
928 		end_subpacket();
929 		break;
930 
931 	case OPS_PTAG_SS_POLICY_URI:
932 		start_subpacket(contents->tag);
933 		print_string("Policy URL",
934 			     content->ss_policy_url.text);
935 		end_subpacket();
936 		break;
937 
938 	case OPS_PTAG_SS_SIGNERS_USER_ID:
939 		start_subpacket(contents->tag);
940 		print_utf8_string("Signer's User ID", content->ss_signers_user_id.user_id);
941 		end_subpacket();
942 		break;
943 
944 	case OPS_PTAG_SS_PREFERRED_KEY_SERVER:
945 		start_subpacket(contents->tag);
946 		print_string("Preferred Key Server",
947 			     content->ss_preferred_key_server.text);
948 		end_subpacket();
949 		break;
950 
951 	case OPS_PTAG_SS_EMBEDDED_SIGNATURE:
952 		start_subpacket(contents->tag);
953 		end_subpacket();/* \todo print out contents? */
954 		break;
955 
956 	case OPS_PTAG_SS_USERDEFINED00:
957 	case OPS_PTAG_SS_USERDEFINED01:
958 	case OPS_PTAG_SS_USERDEFINED02:
959 	case OPS_PTAG_SS_USERDEFINED03:
960 	case OPS_PTAG_SS_USERDEFINED04:
961 	case OPS_PTAG_SS_USERDEFINED05:
962 	case OPS_PTAG_SS_USERDEFINED06:
963 	case OPS_PTAG_SS_USERDEFINED07:
964 	case OPS_PTAG_SS_USERDEFINED08:
965 	case OPS_PTAG_SS_USERDEFINED09:
966 	case OPS_PTAG_SS_USERDEFINED10:
967 		start_subpacket(contents->tag);
968 		print_hexdump("Internal or user-defined",
969 			      content->ss_userdefined.data.contents,
970 			      content->ss_userdefined.data.len);
971 		end_subpacket();
972 		break;
973 
974 	case OPS_PTAG_SS_RESERVED:
975 		start_subpacket(contents->tag);
976 		print_hexdump("Reserved",
977 			      content->ss_userdefined.data.contents,
978 			      content->ss_userdefined.data.len);
979 		end_subpacket();
980 		break;
981 
982 	case OPS_PTAG_SS_REVOCATION_REASON:
983 		start_subpacket(contents->tag);
984 		print_hexdump("Revocation Reason",
985 			      &content->ss_revocation_reason.code,
986 			      1);
987 		str = __ops_show_ss_rr_code(content->ss_revocation_reason.code);
988 		print_string(NULL, str);
989 		/* xxx - todo : output text as UTF-8 string */
990 		end_subpacket();
991 		break;
992 
993 	case OPS_PTAG_CT_LITERAL_DATA_HEADER:
994 		print_tagname("LITERAL DATA HEADER");
995 		printf("  literal data header format=%c filename='%s'\n",
996 		       content->literal_data_header.format,
997 		       content->literal_data_header.filename);
998 		showtime("    modification time",
999 			 content->literal_data_header.modification_time);
1000 		printf("\n");
1001 		break;
1002 
1003 	case OPS_PTAG_CT_LITERAL_DATA_BODY:
1004 		print_tagname("LITERAL DATA BODY");
1005 		printf("  literal data body length=%d\n",
1006 		       content->literal_data_body.length);
1007 		printf("    data=");
1008 		print_escaped(content->literal_data_body.data,
1009 			      content->literal_data_body.length);
1010 		printf("\n");
1011 		break;
1012 
1013 	case OPS_PTAG_CT_SIGNATURE_HEADER:
1014 		print_tagname("SIGNATURE");
1015 		print_indent();
1016 		print_unsigned_int("Signature Version",
1017 				   content->signature.info.version);
1018 		if (content->signature.info.creation_time_set)
1019 			print_time("Signature Creation Time", content->signature.info.creation_time);
1020 
1021 		print_string_and_value("Signature Type",
1022 			    __ops_show_sig_type(content->signature.info.type),
1023 				       content->signature.info.type);
1024 
1025 		if (content->signature.info.signer_id_set)
1026 			print_hexdump_data("Signer ID",
1027 					   content->signature.info.signer_id,
1028 				  sizeof(content->signature.info.signer_id));
1029 
1030 		print_string_and_value("Public Key Algorithm",
1031 			__ops_show_pka(content->signature.info.key_algorithm),
1032 				     content->signature.info.key_algorithm);
1033 		print_string_and_value("Hash Algorithm",
1034 				       __ops_show_hash_algorithm(content->signature.info.hash_algorithm),
1035 				    content->signature.info.hash_algorithm);
1036 
1037 		break;
1038 
1039 	case OPS_PTAG_CT_SIGNATURE_FOOTER:
1040 		print_indent();
1041 		print_hexdump_data("hash2", &content->signature.hash2[0], 2);
1042 
1043 		switch (content->signature.info.key_algorithm) {
1044 		case OPS_PKA_RSA:
1045 			print_bn("sig", content->signature.info.signature.rsa.sig);
1046 			break;
1047 
1048 		case OPS_PKA_DSA:
1049 			print_bn("r", content->signature.info.signature.dsa.r);
1050 			print_bn("s", content->signature.info.signature.dsa.s);
1051 			break;
1052 
1053 		case OPS_PKA_ELGAMAL_ENCRYPT_OR_SIGN:
1054 			print_bn("r", content->signature.info.signature.elgamal.r);
1055 			print_bn("s", content->signature.info.signature.elgamal.s);
1056 			break;
1057 
1058 		case OPS_PKA_PRIVATE00:
1059 		case OPS_PKA_PRIVATE01:
1060 		case OPS_PKA_PRIVATE02:
1061 		case OPS_PKA_PRIVATE03:
1062 		case OPS_PKA_PRIVATE04:
1063 		case OPS_PKA_PRIVATE05:
1064 		case OPS_PKA_PRIVATE06:
1065 		case OPS_PKA_PRIVATE07:
1066 		case OPS_PKA_PRIVATE08:
1067 		case OPS_PKA_PRIVATE09:
1068 		case OPS_PKA_PRIVATE10:
1069 			print_data("Private/Experimental",
1070 			   &content->signature.info.signature.unknown.data);
1071 			break;
1072 
1073 		default:
1074 			assert( /* CONSTCOND */ 0);
1075 		}
1076 		break;
1077 
1078 	case OPS_PARSER_CMD_GET_SK_PASSPHRASE:
1079 		print_tagname("OPS_PARSER_CMD_GET_SK_PASSPHRASE");
1080 		break;
1081 
1082 	case OPS_PTAG_CT_SECRET_KEY:
1083 		print_tagname("OPS_PTAG_CT_SECRET_KEY");
1084 		__ops_print_secret_key_verbose(contents->tag, &content->secret_key);
1085 		break;
1086 
1087 	case OPS_PTAG_CT_ENCRYPTED_SECRET_KEY:
1088 		print_tagname("OPS_PTAG_CT_ENCRYPTED_SECRET_KEY");
1089 		__ops_print_secret_key_verbose(contents->tag, &content->secret_key);
1090 		break;
1091 
1092 	case OPS_PTAG_CT_ARMOUR_HEADER:
1093 		print_tagname("ARMOUR HEADER");
1094 		print_string("type", content->armour_header.type);
1095 		break;
1096 
1097 	case OPS_PTAG_CT_SIGNED_CLEARTEXT_HEADER:
1098 		print_tagname("SIGNED CLEARTEXT HEADER");
1099 		print_headers(&content->signed_cleartext_header.headers);
1100 		break;
1101 
1102 	case OPS_PTAG_CT_SIGNED_CLEARTEXT_BODY:
1103 		print_tagname("SIGNED CLEARTEXT BODY");
1104 		print_block("signed cleartext", content->signed_cleartext_body.data,
1105 			    content->signed_cleartext_body.length);
1106 		break;
1107 
1108 	case OPS_PTAG_CT_SIGNED_CLEARTEXT_TRAILER:
1109 		print_tagname("SIGNED CLEARTEXT TRAILER");
1110 		printf("hash algorithm: %d\n",
1111 		       content->signed_cleartext_trailer.hash->algorithm);
1112 		printf("\n");
1113 		break;
1114 
1115 	case OPS_PTAG_CT_UNARMOURED_TEXT:
1116 		if (!unarmoured) {
1117 			print_tagname("UNARMOURED TEXT");
1118 			unarmoured = true;
1119 		}
1120 		putchar('[');
1121 		print_escaped(content->unarmoured_text.data,
1122 			      content->unarmoured_text.length);
1123 		putchar(']');
1124 		break;
1125 
1126 	case OPS_PTAG_CT_ARMOUR_TRAILER:
1127 		print_tagname("ARMOUR TRAILER");
1128 		print_string("type", content->armour_header.type);
1129 		break;
1130 
1131 	case OPS_PTAG_CT_PK_SESSION_KEY:
1132 	case OPS_PTAG_CT_ENCRYPTED_PK_SESSION_KEY:
1133 		__ops_print_pk_session_key(contents->tag, &content->pk_session_key);
1134 		break;
1135 
1136 	case OPS_PARSER_CMD_GET_SECRET_KEY:
1137 		__ops_print_pk_session_key(OPS_PTAG_CT_ENCRYPTED_PK_SESSION_KEY,
1138 				    content->get_secret_key.pk_session_key);
1139 		break;
1140 
1141 	default:
1142 		print_tagname("UNKNOWN PACKET TYPE");
1143 		fprintf(stderr, "__ops_print_packet: unknown tag=%d (0x%x)\n", contents->tag,
1144 			contents->tag);
1145 		exit(1);
1146 	}
1147 	return 1;
1148 }
1149 
1150 static __ops_parse_cb_return_t
1151 cb_list_packets(const __ops_parser_content_t * contents, __ops_parse_cb_info_t * cbinfo)
1152 {
1153 	OPS_USED(cbinfo);
1154 
1155 	__ops_print_packet(contents);
1156 #ifdef XXX
1157 	if (unarmoured && contents->tag != OPS_PTAG_CT_UNARMOURED_TEXT) {
1158 		unarmoured = false;
1159 		puts("UNARMOURED TEXT ends");
1160 	}
1161 	switch (contents->tag) {
1162 	case OPS_PARSER_ERROR:
1163 		printf("parse error: %s\n", content->error.error);
1164 		break;
1165 
1166 	case OPS_PARSER_ERRCODE:
1167 		printf("parse error: %s\n",
1168 		       __ops_errcode(content->errcode.errcode));
1169 		break;
1170 
1171 	case OPS_PARSER_PACKET_END:
1172 		print_packet_hex(&content->packet);
1173 		break;
1174 
1175 	case OPS_PARSER_PTAG:
1176 		if (content->ptag.content_tag == OPS_PTAG_CT_PUBLIC_KEY) {
1177 			indent = 0;
1178 			printf("\n*** NEXT KEY ***\n");
1179 		}
1180 		printf("\n");
1181 		print_indent();
1182 		printf("==== ptag new_format=%d content_tag=%d length_type=%d"
1183 		       " length=0x%x (%d) position=0x%x (%d)\n", content->ptag.new_format,
1184 		       content->ptag.content_tag, content->ptag.length_type,
1185 		       content->ptag.length, content->ptag.length,
1186 		       content->ptag.position, content->ptag.position);
1187 		print_tagname(__ops_show_packet_tag(content->ptag.content_tag));
1188 		break;
1189 
1190 	case OPS_PTAG_CT_SE_DATA_HEADER:
1191 		print_tagname("SYMMETRIC ENCRYPTED DATA");
1192 		break;
1193 
1194 	case OPS_PTAG_CT_SE_IP_DATA_HEADER:
1195 		print_tagname("SYMMETRIC ENCRYPTED INTEGRITY PROTECTED DATA HEADER");
1196 		printf("Version: %d\n", content->se_ip_data_header.version);
1197 		break;
1198 
1199 	case OPS_PTAG_CT_SE_IP_DATA_BODY:
1200 		print_tagname("SYMMETRIC ENCRYPTED INTEGRITY PROTECTED DATA BODY");
1201 		printf("  data body length=%d\n",
1202 		       content->se_data_body.length);
1203 		printf("    data=");
1204 		hexdump(content->se_data_body.data,
1205 			content->se_data_body.length, "");
1206 		printf("\n");
1207 		break;
1208 
1209 	case OPS_PTAG_CT_PUBLIC_KEY:
1210 	case OPS_PTAG_CT_PUBLIC_SUBKEY:
1211 		if (contents->tag == OPS_PTAG_CT_PUBLIC_KEY)
1212 			print_tagname("PUBLIC KEY");
1213 		else
1214 			print_tagname("PUBLIC SUBKEY");
1215 
1216 		__ops_print_public_key(&content->public_key);
1217 		break;
1218 
1219 	case OPS_PTAG_CT_TRUST:
1220 		print_tagname("TRUST");
1221 		print_data("Trust", &content->trust.data);
1222 		break;
1223 
1224 	case OPS_PTAG_CT_USER_ID:
1225 		/* XXX: how do we print UTF-8? */
1226 		print_tagname("USER ID");
1227 		print_utf8_string("user_id", content->user_id.user_id);
1228 		break;
1229 
1230 	case OPS_PTAG_CT_SIGNATURE:
1231 		print_tagname("SIGNATURE");
1232 		print_indent();
1233 		print_unsigned_int("Signature Version",
1234 				   content->signature.info.version);
1235 		if (content->signature.info.creation_time_set)
1236 			print_time("Signature Creation Time",
1237 				   content->signature.info.creation_time);
1238 
1239 		print_string_and_value("Signature Type",
1240 			    __ops_show_sig_type(content->signature.info.type),
1241 				       content->signature.info.type);
1242 
1243 		if (content->signature.info.signer_id_set)
1244 			print_hexdump_data("Signer ID",
1245 					   content->signature.info.signer_id,
1246 				  sizeof(content->signature.info.signer_id));
1247 
1248 		print_string_and_value("Public Key Algorithm",
1249 			__ops_show_pka(content->signature.info.key_algorithm),
1250 				     content->signature.info.key_algorithm);
1251 		print_string_and_value("Hash Algorithm",
1252 				       __ops_show_hash_algorithm(content->signature.info.hash_algorithm),
1253 				    content->signature.info.hash_algorithm);
1254 		print_unsigned_int("Hashed data len", content->signature.info.v4_hashed_data_length);
1255 
1256 		print_indent();
1257 		print_hexdump_data("hash2", &content->signature.hash2[0], 2);
1258 
1259 		switch (content->signature.info.key_algorithm) {
1260 		case OPS_PKA_RSA:
1261 		case OPS_PKA_RSA_SIGN_ONLY:
1262 			print_bn("sig", content->signature.info.signature.rsa.sig);
1263 			break;
1264 
1265 		case OPS_PKA_DSA:
1266 			print_bn("r", content->signature.info.signature.dsa.r);
1267 			print_bn("s", content->signature.info.signature.dsa.s);
1268 			break;
1269 
1270 		case OPS_PKA_ELGAMAL_ENCRYPT_OR_SIGN:
1271 			print_bn("r", content->signature.info.signature.elgamal.r);
1272 			print_bn("s", content->signature.info.signature.elgamal.s);
1273 			break;
1274 
1275 		default:
1276 			assert(0);
1277 		}
1278 
1279 		if (content->signature.hash)
1280 			printf("data hash is set\n");
1281 
1282 		break;
1283 
1284 	case OPS_PTAG_CT_COMPRESSED:
1285 		print_tagname("COMPRESSED");
1286 		print_unsigned_int("Compressed Data Type", content->compressed.type);
1287 		break;
1288 
1289 	case OPS_PTAG_CT_ONE_PASS_SIGNATURE:
1290 		print_tagname("ONE PASS SIGNATURE");
1291 
1292 		print_unsigned_int("Version", content->one_pass_signature.version);
1293 		print_string_and_value("Signature Type",
1294 		    __ops_show_sig_type(content->one_pass_signature.sig_type),
1295 				       content->one_pass_signature.sig_type);
1296 		print_string_and_value("Hash Algorithm",
1297 				       __ops_show_hash_algorithm(content->one_pass_signature.hash_algorithm),
1298 				content->one_pass_signature.hash_algorithm);
1299 		print_string_and_value("Public Key Algorithm",
1300 		    __ops_show_pka(content->one_pass_signature.key_algorithm),
1301 				 content->one_pass_signature.key_algorithm);
1302 		print_hexdump_data("Signer ID",
1303 				   content->one_pass_signature.keyid,
1304 				   sizeof(content->one_pass_signature.keyid));
1305 
1306 		print_unsigned_int("Nested",
1307 				   content->one_pass_signature.nested);
1308 		break;
1309 
1310 	case OPS_PTAG_CT_USER_ATTRIBUTE:
1311 		print_tagname("USER ATTRIBUTE");
1312 		print_hexdump("User Attribute",
1313 			      content->user_attribute.data.contents,
1314 			      content->user_attribute.data.len);
1315 		break;
1316 
1317 	case OPS_PTAG_RAW_SS:
1318 		assert(!contents->critical);
1319 		start_subpacket(contents->tag);
1320 		print_unsigned_int("Raw Signature Subpacket: tag",
1321 		   content->ss_raw.tag - OPS_PTAG_SIGNATURE_SUBPACKET_BASE);
1322 		print_hexdump("Raw Data",
1323 			      content->ss_raw.raw,
1324 			      content->ss_raw.length);
1325 		break;
1326 
1327 	case OPS_PTAG_SS_CREATION_TIME:
1328 		start_subpacket(contents->tag);
1329 		print_time("Signature Creation Time", content->ss_time.time);
1330 		end_subpacket();
1331 		break;
1332 
1333 	case OPS_PTAG_SS_EXPIRATION_TIME:
1334 		start_subpacket(contents->tag);
1335 		print_duration("Signature Expiration Time", content->ss_time.time);
1336 		end_subpacket();
1337 		break;
1338 
1339 	case OPS_PTAG_SS_KEY_EXPIRATION_TIME:
1340 		start_subpacket(contents->tag);
1341 		print_duration("Key Expiration Time", content->ss_time.time);
1342 		end_subpacket();
1343 		break;
1344 
1345 	case OPS_PTAG_SS_TRUST:
1346 		start_subpacket(contents->tag);
1347 		print_string("Trust Signature", "");
1348 		print_unsigned_int("Level",
1349 				   content->ss_trust.level);
1350 		print_unsigned_int("Amount",
1351 				   content->ss_trust.amount);
1352 		end_subpacket();
1353 		break;
1354 
1355 	case OPS_PTAG_SS_REVOCABLE:
1356 		start_subpacket(contents->tag);
1357 		print_boolean("Revocable", content->ss_revocable.revocable);
1358 		end_subpacket();
1359 		break;
1360 
1361 	case OPS_PTAG_SS_REVOCATION_KEY:
1362 		start_subpacket(contents->tag);
1363 		/* not yet tested */
1364 		printf("  revocation key: class=0x%x",
1365 		       content->ss_revocation_key.class);
1366 		if (content->ss_revocation_key.class & 0x40)
1367 			printf(" (sensitive)");
1368 		printf(", algid=0x%x",
1369 		       content->ss_revocation_key.algid);
1370 		printf(", fingerprint=");
1371 		hexdump(content->ss_revocation_key.fingerprint, 20, "");
1372 		printf("\n");
1373 		end_subpacket();
1374 		break;
1375 
1376 	case OPS_PTAG_SS_ISSUER_KEY_ID:
1377 		start_subpacket(contents->tag);
1378 		print_hexdump("Issuer Key Id",
1379 			      &content->ss_issuer_key_id.key_id[0],
1380 			      sizeof(content->ss_issuer_key_id.key_id));
1381 		end_subpacket();
1382 		break;
1383 
1384 	case OPS_PTAG_SS_PREFERRED_SKA:
1385 		start_subpacket(contents->tag);
1386 		print_data("Preferred Symmetric Algorithms",
1387 			   &content->ss_preferred_ska.data);
1388 
1389 		text = __ops_showall_ss_preferred_ska(content->ss_preferred_ska);
1390 		print_text_breakdown(text);
1391 		__ops_text_free(text);
1392 
1393 		end_subpacket();
1394 		break;
1395 
1396 	case OPS_PTAG_SS_PRIMARY_USER_ID:
1397 		start_subpacket(contents->tag);
1398 		print_boolean("Primary User ID",
1399 			      content->ss_primary_user_id.primary_user_id);
1400 		end_subpacket();
1401 		break;
1402 
1403 	case OPS_PTAG_SS_PREFERRED_HASH:
1404 		start_subpacket(contents->tag);
1405 		print_data("Preferred Hash Algorithms",
1406 			   &content->ss_preferred_hash.data);
1407 
1408 		text = __ops_showall_ss_preferred_hash(content->ss_preferred_hash);
1409 		print_text_breakdown(text);
1410 		__ops_text_free(text);
1411 		end_subpacket();
1412 		break;
1413 
1414 	case OPS_PTAG_SS_PREFERRED_COMPRESSION:
1415 		start_subpacket(contents->tag);
1416 		print_data("Preferred Compression Algorithms",
1417 			   &content->ss_preferred_compression.data);
1418 
1419 		text = __ops_showall_ss_preferred_compression(content->ss_preferred_compression);
1420 		print_text_breakdown(text);
1421 		__ops_text_free(text);
1422 		end_subpacket();
1423 		break;
1424 
1425 	case OPS_PTAG_SS_KEY_FLAGS:
1426 		start_subpacket(contents->tag);
1427 		print_data("Key Flags", &content->ss_key_flags.data);
1428 
1429 		text = __ops_showall_ss_key_flags(content->ss_key_flags);
1430 		print_text_breakdown(text);
1431 		__ops_text_free(text);
1432 
1433 		end_subpacket();
1434 		break;
1435 
1436 	case OPS_PTAG_SS_KEY_SERVER_PREFS:
1437 		start_subpacket(contents->tag);
1438 		print_data("Key Server Preferences",
1439 			   &content->ss_key_server_prefs.data);
1440 
1441 		text = __ops_showall_ss_key_server_prefs(content->ss_key_server_prefs);
1442 		print_text_breakdown(text);
1443 		__ops_text_free(text);
1444 
1445 		end_subpacket();
1446 		break;
1447 
1448 	case OPS_PTAG_SS_FEATURES:
1449 		start_subpacket(contents->tag);
1450 		print_data("Features",
1451 			   &content->ss_features.data);
1452 
1453 		text = __ops_showall_ss_features(content->ss_features);
1454 		print_text_breakdown(text);
1455 		__ops_text_free(text);
1456 
1457 		end_subpacket();
1458 		break;
1459 
1460 	case OPS_PTAG_SS_NOTATION_DATA:
1461 		start_subpacket(contents->tag);
1462 		print_indent();
1463 		printf("Notation Data:\n");
1464 
1465 		indent++;
1466 		print_data("Flags",
1467 			   &content->ss_notation_data.flags);
1468 		text = __ops_showall_ss_notation_data_flags(content->ss_notation_data);
1469 		print_text_breakdown(text);
1470 		__ops_text_free(text);
1471 
1472 		/* xxx - TODO: print out UTF - rachel */
1473 
1474 		print_data("Name",
1475 			   &content->ss_notation_data.name);
1476 
1477 		print_data("Value",
1478 			   &content->ss_notation_data.value);
1479 
1480 		indent--;
1481 		end_subpacket();
1482 		break;
1483 
1484 	case OPS_PTAG_SS_REGEXP:
1485 		start_subpacket(contents->tag);
1486 		print_hexdump("Regular Expression",
1487 			      (unsigned char *) content->ss_regexp.text,
1488 			      strlen(content->ss_regexp.text));
1489 		print_string(NULL,
1490 			     content->ss_regexp.text);
1491 		end_subpacket();
1492 		break;
1493 
1494 	case OPS_PTAG_SS_POLICY_URL:
1495 		start_subpacket(contents->tag);
1496 		print_string("Policy URL",
1497 			     content->ss_policy_url.text);
1498 		end_subpacket();
1499 		break;
1500 
1501 	case OPS_PTAG_SS_SIGNERS_USER_ID:
1502 		start_subpacket(contents->tag);
1503 		print_utf8_string("Signer's User ID", content->ss_signers_user_id.user_id);
1504 		end_subpacket();
1505 		break;
1506 
1507 	case OPS_PTAG_SS_PREFERRED_KEY_SERVER:
1508 		start_subpacket(contents->tag);
1509 		print_string("Preferred Key Server",
1510 			     content->ss_preferred_key_server.text);
1511 		end_subpacket();
1512 		break;
1513 
1514 	case OPS_PTAG_SS_USERDEFINED00:
1515 	case OPS_PTAG_SS_USERDEFINED01:
1516 	case OPS_PTAG_SS_USERDEFINED02:
1517 	case OPS_PTAG_SS_USERDEFINED03:
1518 	case OPS_PTAG_SS_USERDEFINED04:
1519 	case OPS_PTAG_SS_USERDEFINED05:
1520 	case OPS_PTAG_SS_USERDEFINED06:
1521 	case OPS_PTAG_SS_USERDEFINED07:
1522 	case OPS_PTAG_SS_USERDEFINED08:
1523 	case OPS_PTAG_SS_USERDEFINED09:
1524 	case OPS_PTAG_SS_USERDEFINED10:
1525 		start_subpacket(contents->tag);
1526 		print_hexdump("Internal or user-defined",
1527 			      content->ss_userdefined.data.contents,
1528 			      content->ss_userdefined.data.len);
1529 		end_subpacket();
1530 		break;
1531 
1532 	case OPS_PTAG_SS_RESERVED:
1533 		start_subpacket(contents->tag);
1534 		print_hexdump("Reserved",
1535 			      content->ss_userdefined.data.contents,
1536 			      content->ss_userdefined.data.len);
1537 		end_subpacket();
1538 		break;
1539 
1540 	case OPS_PTAG_SS_REVOCATION_REASON:
1541 		start_subpacket(contents->tag);
1542 		print_hexdump("Revocation Reason",
1543 			      &content->ss_revocation_reason.code,
1544 			      1);
1545 		str = __ops_show_ss_rr_code(content->ss_revocation_reason.code);
1546 		print_string(NULL, str);
1547 		/* xxx - todo : output text as UTF-8 string */
1548 		end_subpacket();
1549 		break;
1550 
1551 	case OPS_PTAG_CT_LITERAL_DATA_HEADER:
1552 		print_tagname("LITERAL DATA HEADER");
1553 		printf("  literal data header format=%c filename='%s'\n",
1554 		       content->literal_data_header.format,
1555 		       content->literal_data_header.filename);
1556 		print_time("    modification time",
1557 			   content->literal_data_header.modification_time);
1558 		printf("\n");
1559 		break;
1560 
1561 	case OPS_PTAG_CT_LITERAL_DATA_BODY:
1562 		print_tagname("LITERAL DATA BODY");
1563 		printf("  literal data body length=%d\n",
1564 		       content->literal_data_body.length);
1565 		printf("    data=");
1566 		print_escaped(content->literal_data_body.data,
1567 			      content->literal_data_body.length);
1568 		printf("\n");
1569 		break;
1570 
1571 	case OPS_PTAG_CT_SIGNATURE_HEADER:
1572 		print_tagname("SIGNATURE");
1573 		print_indent();
1574 		print_unsigned_int("Signature Version",
1575 				   content->signature.info.version);
1576 		if (content->signature.info.creation_time_set)
1577 			print_time("Signature Creation Time", content->signature.info.creation_time);
1578 
1579 		print_string_and_value("Signature Type",
1580 			    __ops_show_sig_type(content->signature.info.type),
1581 				       content->signature.info.type);
1582 
1583 		if (content->signature.info.signer_id_set)
1584 			print_hexdump_data("Signer ID",
1585 					   content->signature.info.signer_id,
1586 				  sizeof(content->signature.info.signer_id));
1587 
1588 		print_string_and_value("Public Key Algorithm",
1589 			__ops_show_pka(content->signature.info.key_algorithm),
1590 				     content->signature.info.key_algorithm);
1591 		print_string_and_value("Hash Algorithm",
1592 				       __ops_show_hash_algorithm(content->signature.info.hash_algorithm),
1593 				    content->signature.info.hash_algorithm);
1594 
1595 		break;
1596 
1597 	case OPS_PTAG_CT_SIGNATURE_FOOTER:
1598 		print_indent();
1599 		print_hexdump_data("hash2", &content->signature.hash2[0], 2);
1600 
1601 		switch (content->signature.info.key_algorithm) {
1602 		case OPS_PKA_RSA:
1603 			print_bn("sig", content->signature.info.signature.rsa.sig);
1604 			break;
1605 
1606 		case OPS_PKA_DSA:
1607 			print_bn("r", content->signature.info.signature.dsa.r);
1608 			print_bn("s", content->signature.info.signature.dsa.s);
1609 			break;
1610 
1611 		case OPS_PKA_ELGAMAL_ENCRYPT_OR_SIGN:
1612 			print_bn("r", content->signature.info.signature.elgamal.r);
1613 			print_bn("s", content->signature.info.signature.elgamal.s);
1614 			break;
1615 
1616 		case OPS_PKA_PRIVATE00:
1617 		case OPS_PKA_PRIVATE01:
1618 		case OPS_PKA_PRIVATE02:
1619 		case OPS_PKA_PRIVATE03:
1620 		case OPS_PKA_PRIVATE04:
1621 		case OPS_PKA_PRIVATE05:
1622 		case OPS_PKA_PRIVATE06:
1623 		case OPS_PKA_PRIVATE07:
1624 		case OPS_PKA_PRIVATE08:
1625 		case OPS_PKA_PRIVATE09:
1626 		case OPS_PKA_PRIVATE10:
1627 			print_data("Private/Experimental",
1628 			   &content->signature.info.signature.unknown.data);
1629 			break;
1630 
1631 		default:
1632 			assert(0);
1633 		}
1634 		break;
1635 
1636 	case OPS_PARSER_CMD_GET_SK_PASSPHRASE:
1637 		if (cbinfo->cryptinfo.cb_get_passphrase) {
1638 			return cbinfo->cryptinfo.cb_get_passphrase(contents, cbinfo);
1639 		}
1640 		break;
1641 
1642 	case OPS_PTAG_CT_SECRET_KEY:
1643 	case OPS_PTAG_CT_ENCRYPTED_SECRET_KEY:
1644 		__ops_print_secret_key_verbose(contents->tag, &content->secret_key);
1645 		break;
1646 
1647 	case OPS_PTAG_CT_ARMOUR_HEADER:
1648 		print_tagname("ARMOUR HEADER");
1649 		print_string("type", content->armour_header.type);
1650 		break;
1651 
1652 	case OPS_PTAG_CT_SIGNED_CLEARTEXT_HEADER:
1653 		print_tagname("SIGNED CLEARTEXT HEADER");
1654 		print_headers(&content->signed_cleartext_header.headers);
1655 		break;
1656 
1657 	case OPS_PTAG_CT_SIGNED_CLEARTEXT_BODY:
1658 		print_tagname("SIGNED CLEARTEXT BODY");
1659 		print_block("signed cleartext", content->signed_cleartext_body.data,
1660 			    content->signed_cleartext_body.length);
1661 		break;
1662 
1663 	case OPS_PTAG_CT_SIGNED_CLEARTEXT_TRAILER:
1664 		print_tagname("SIGNED CLEARTEXT TRAILER");
1665 		printf("hash algorithm: %d\n",
1666 		       content->signed_cleartext_trailer.hash->algorithm);
1667 		printf("\n");
1668 		break;
1669 
1670 	case OPS_PTAG_CT_UNARMOURED_TEXT:
1671 		if (!unarmoured) {
1672 			print_tagname("UNARMOURED TEXT");
1673 			unarmoured = true;
1674 		}
1675 		putchar('[');
1676 		print_escaped(content->unarmoured_text.data,
1677 			      content->unarmoured_text.length);
1678 		putchar(']');
1679 		break;
1680 
1681 	case OPS_PTAG_CT_ARMOUR_TRAILER:
1682 		print_tagname("ARMOUR TRAILER");
1683 		print_string("type", content->armour_header.type);
1684 		break;
1685 
1686 	case OPS_PTAG_CT_PK_SESSION_KEY:
1687 	case OPS_PTAG_CT_ENCRYPTED_PK_SESSION_KEY:
1688 		__ops_print_pk_session_key(contents->tag, &content->pk_session_key);
1689 		break;
1690 
1691 	case OPS_PARSER_CMD_GET_SECRET_KEY:
1692 		__ops_print_pk_session_key(OPS_PTAG_CT_ENCRYPTED_PK_SESSION_KEY,
1693 				    content->get_secret_key.pk_session_key);
1694 		return get_secret_key_cb(contents, cbinfo);
1695 
1696 	default:
1697 		print_tagname("UNKNOWN PACKET TYPE");
1698 		fprintf(stderr, "packet-dump: unknown tag=%d (0x%x)\n", contents->tag,
1699 			contents->tag);
1700 		exit(1);
1701 	}
1702 #endif				/* XXX */
1703 	return OPS_RELEASE_MEMORY;
1704 }
1705 
1706 /**
1707 \ingroup Core_Print
1708 \param filename
1709 \param armour
1710 \param keyring
1711 \param cb_get_passphrase
1712 */
1713 void
1714 __ops_list_packets(char *filename, bool armour, __ops_keyring_t * keyring, __ops_parse_cb_t * cb_get_passphrase)
1715 {
1716 	int             fd = 0;
1717 	__ops_parse_info_t *pinfo = NULL;
1718 	const bool accumulate = true;
1719 
1720 	fd = __ops_setup_file_read(&pinfo, filename, NULL, cb_list_packets, accumulate);
1721 	__ops_parse_options(pinfo, OPS_PTAG_SS_ALL, OPS_PARSE_PARSED);
1722 	pinfo->cryptinfo.keyring = keyring;
1723 	pinfo->cryptinfo.cb_get_passphrase = cb_get_passphrase;
1724 
1725 	if (armour)
1726 		__ops_reader_push_dearmour(pinfo);
1727 
1728 	__ops_parse_and_print_errors(pinfo);
1729 
1730 	__ops_teardown_file_read(pinfo, fd);
1731 }
1732