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