packet-print.c revision 1.7.2.2
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
43static int      indent = 0;
44
45static void print_bn(const char *, const BIGNUM *);
46static void print_hex(const unsigned char *, size_t);
47static void print_hexdump(const char *, const unsigned char *, unsigned int);
48static void print_hexdump_data(const char *, const unsigned char *, unsigned int);
49static void     print_indent(void);
50static void     print_name(const char *);
51static void print_string_and_value(const char *, const char *, unsigned char);
52static void     print_tagname(const char *);
53static void print_time(const char *, time_t);
54static void     print_time_short(time_t);
55static void print_unsigned_int(const char *, unsigned int);
56static void     showtime(const char *, time_t);
57static 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
67void
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*/
90void
91__ops_print_public_key(const __ops_public_key_t * pkey)
92{
93	printf("------- PUBLIC KEY ------\n");
94	print_unsigned_int("Version", (unsigned)pkey->version);
95	print_time("Creation Time", pkey->creation_time);
96	if (pkey->version == OPS_V3)
97		print_unsigned_int("Days Valid", pkey->days_valid);
98
99	print_string_and_value("Algorithm", __ops_show_pka(pkey->algorithm),
100			       pkey->algorithm);
101
102	switch (pkey->algorithm) {
103	case OPS_PKA_DSA:
104		print_bn("p", pkey->key.dsa.p);
105		print_bn("q", pkey->key.dsa.q);
106		print_bn("g", pkey->key.dsa.g);
107		print_bn("y", pkey->key.dsa.y);
108		break;
109
110	case OPS_PKA_RSA:
111	case OPS_PKA_RSA_ENCRYPT_ONLY:
112	case OPS_PKA_RSA_SIGN_ONLY:
113		print_bn("n", pkey->key.rsa.n);
114		print_bn("e", pkey->key.rsa.e);
115		break;
116
117	case OPS_PKA_ELGAMAL:
118	case OPS_PKA_ELGAMAL_ENCRYPT_OR_SIGN:
119		print_bn("p", pkey->key.elgamal.p);
120		print_bn("g", pkey->key.elgamal.g);
121		print_bn("y", pkey->key.elgamal.y);
122		break;
123
124	default:
125		assert( /* CONSTCOND */ 0);
126	}
127
128	printf("------- end of PUBLIC KEY ------\n");
129}
130
131/**
132   \ingroup Core_Print
133
134   Prints a secret key
135
136   \param key Ptr to public key
137*/
138
139void
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/*
166void
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*/
182static 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
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_packet_t * packet)
367{
368	unsigned char  *cur;
369	unsigned	rem;
370	int             i;
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
388static void
389print_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
400static void
401print_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
408static void
409print_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
415static void
416print_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 = (int)(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
441static void
442print_boolean(const char *name, unsigned char boolval)
443{
444	print_name(name);
445	printf("%s\n", (boolval) ? "Yes" : "No");
446}
447
448static void
449print_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
481static void
482print_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
490static void
491print_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*/
524static 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
560static void
561start_subpacket(int 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
570static void
571end_subpacket(void)
572{
573	indent--;
574}
575
576/**
577\ingroup Core_Print
578\param contents
579*/
580int
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				   (unsigned)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",
724			(unsigned)content->compressed.type);
725		break;
726
727	case OPS_PTAG_CT_ONE_PASS_SIGNATURE:
728		print_tagname("ONE PASS SIGNATURE");
729
730		print_unsigned_int("Version",
731			(unsigned)content->one_pass_signature.version);
732		print_string_and_value("Signature Type",
733		    __ops_show_sig_type(content->one_pass_signature.sig_type),
734				       content->one_pass_signature.sig_type);
735		print_string_and_value("Hash Algorithm",
736				       __ops_show_hash_algorithm(content->one_pass_signature.hash_algorithm),
737				content->one_pass_signature.hash_algorithm);
738		print_string_and_value("Public Key Algorithm",
739		    __ops_show_pka(content->one_pass_signature.key_algorithm),
740				 content->one_pass_signature.key_algorithm);
741		print_hexdump_data("Signer ID",
742				   content->one_pass_signature.keyid,
743				   sizeof(content->one_pass_signature.keyid));
744
745		print_unsigned_int("Nested",
746				   content->one_pass_signature.nested);
747		break;
748
749	case OPS_PTAG_CT_USER_ATTRIBUTE:
750		print_tagname("USER ATTRIBUTE");
751		print_hexdump("User Attribute",
752			      content->user_attribute.data.contents,
753			      content->user_attribute.data.len);
754		break;
755
756	case OPS_PTAG_RAW_SS:
757		assert(!contents->critical);
758		start_subpacket(contents->tag);
759		print_unsigned_int("Raw Signature Subpacket: tag",
760			(unsigned)(content->ss_raw.tag -
761		   	OPS_PTAG_SIGNATURE_SUBPACKET_BASE));
762		print_hexdump("Raw Data",
763			      content->ss_raw.raw,
764			      content->ss_raw.length);
765		break;
766
767	case OPS_PTAG_SS_CREATION_TIME:
768		start_subpacket(contents->tag);
769		print_time("Signature Creation Time", content->ss_time.time);
770		end_subpacket();
771		break;
772
773	case OPS_PTAG_SS_EXPIRATION_TIME:
774		start_subpacket(contents->tag);
775		print_duration("Signature Expiration Time", content->ss_time.time);
776		end_subpacket();
777		break;
778
779	case OPS_PTAG_SS_KEY_EXPIRATION_TIME:
780		start_subpacket(contents->tag);
781		print_duration("Key Expiration Time", content->ss_time.time);
782		end_subpacket();
783		break;
784
785	case OPS_PTAG_SS_TRUST:
786		start_subpacket(contents->tag);
787		print_string("Trust Signature", "");
788		print_unsigned_int("Level",
789				   (unsigned)content->ss_trust.level);
790		print_unsigned_int("Amount",
791				   (unsigned)content->ss_trust.amount);
792		end_subpacket();
793		break;
794
795	case OPS_PTAG_SS_REVOCABLE:
796		start_subpacket(contents->tag);
797		print_boolean("Revocable", content->ss_revocable.revocable);
798		end_subpacket();
799		break;
800
801	case OPS_PTAG_SS_REVOCATION_KEY:
802		start_subpacket(contents->tag);
803		/* not yet tested */
804		printf("  revocation key: class=0x%x",
805		       content->ss_revocation_key.class);
806		if (content->ss_revocation_key.class & 0x40)
807			printf(" (sensitive)");
808		printf(", algid=0x%x",
809		       content->ss_revocation_key.algid);
810		printf(", fingerprint=");
811		hexdump(content->ss_revocation_key.fingerprint, 20, "");
812		printf("\n");
813		end_subpacket();
814		break;
815
816	case OPS_PTAG_SS_ISSUER_KEY_ID:
817		start_subpacket(contents->tag);
818		print_hexdump("Issuer Key Id",
819			      &content->ss_issuer_key_id.key_id[0],
820			      sizeof(content->ss_issuer_key_id.key_id));
821		end_subpacket();
822		break;
823
824	case OPS_PTAG_SS_PREFERRED_SKA:
825		start_subpacket(contents->tag);
826		print_data("Preferred Symmetric Algorithms",
827			   &content->ss_preferred_ska.data);
828
829		text = __ops_showall_ss_preferred_ska(content->ss_preferred_ska);
830		print_text_breakdown(text);
831		__ops_text_free(text);
832
833		end_subpacket();
834		break;
835
836	case OPS_PTAG_SS_PRIMARY_USER_ID:
837		start_subpacket(contents->tag);
838		print_boolean("Primary User ID",
839			      content->ss_primary_user_id.primary_user_id);
840		end_subpacket();
841		break;
842
843	case OPS_PTAG_SS_PREFERRED_HASH:
844		start_subpacket(contents->tag);
845		print_data("Preferred Hash Algorithms",
846			   &content->ss_preferred_hash.data);
847
848		text = __ops_showall_ss_preferred_hash(content->ss_preferred_hash);
849		print_text_breakdown(text);
850		__ops_text_free(text);
851		end_subpacket();
852		break;
853
854	case OPS_PTAG_SS_PREFERRED_COMPRESSION:
855		start_subpacket(contents->tag);
856		print_data("Preferred Compression Algorithms",
857			   &content->ss_preferred_compression.data);
858
859		text = __ops_showall_ss_preferred_compression(content->ss_preferred_compression);
860		print_text_breakdown(text);
861		__ops_text_free(text);
862		end_subpacket();
863		break;
864
865	case OPS_PTAG_SS_KEY_FLAGS:
866		start_subpacket(contents->tag);
867		print_data("Key Flags", &content->ss_key_flags.data);
868
869		text = __ops_showall_ss_key_flags(content->ss_key_flags);
870		print_text_breakdown(text);
871		__ops_text_free(text);
872
873		end_subpacket();
874		break;
875
876	case OPS_PTAG_SS_KEY_SERVER_PREFS:
877		start_subpacket(contents->tag);
878		print_data("Key Server Preferences",
879			   &content->ss_key_server_prefs.data);
880
881		text = __ops_showall_ss_key_server_prefs(content->ss_key_server_prefs);
882		print_text_breakdown(text);
883		__ops_text_free(text);
884
885		end_subpacket();
886		break;
887
888	case OPS_PTAG_SS_FEATURES:
889		start_subpacket(contents->tag);
890		print_data("Features",
891			   &content->ss_features.data);
892
893		text = __ops_showall_ss_features(content->ss_features);
894		print_text_breakdown(text);
895		__ops_text_free(text);
896
897		end_subpacket();
898		break;
899
900	case OPS_PTAG_SS_NOTATION_DATA:
901		start_subpacket(contents->tag);
902		print_indent();
903		printf("Notation Data:\n");
904
905		indent++;
906		print_data("Flags",
907			   &content->ss_notation_data.flags);
908		text = __ops_showall_ss_notation_data_flags(content->ss_notation_data);
909		print_text_breakdown(text);
910		__ops_text_free(text);
911
912		/* xxx - TODO: print out UTF - rachel */
913
914		print_data("Name",
915			   &content->ss_notation_data.name);
916
917		print_data("Value",
918			   &content->ss_notation_data.value);
919
920		indent--;
921		end_subpacket();
922		break;
923
924	case OPS_PTAG_SS_REGEXP:
925		start_subpacket(contents->tag);
926		print_hexdump("Regular Expression",
927			      (unsigned char *) content->ss_regexp.text,
928			      strlen(content->ss_regexp.text));
929		print_string(NULL,
930			     content->ss_regexp.text);
931		end_subpacket();
932		break;
933
934	case OPS_PTAG_SS_POLICY_URI:
935		start_subpacket(contents->tag);
936		print_string("Policy URL",
937			     content->ss_policy_url.text);
938		end_subpacket();
939		break;
940
941	case OPS_PTAG_SS_SIGNERS_USER_ID:
942		start_subpacket(contents->tag);
943		print_utf8_string("Signer's User ID", content->ss_signers_user_id.user_id);
944		end_subpacket();
945		break;
946
947	case OPS_PTAG_SS_PREFERRED_KEY_SERVER:
948		start_subpacket(contents->tag);
949		print_string("Preferred Key Server",
950			     content->ss_preferred_key_server.text);
951		end_subpacket();
952		break;
953
954	case OPS_PTAG_SS_EMBEDDED_SIGNATURE:
955		start_subpacket(contents->tag);
956		end_subpacket();/* \todo print out contents? */
957		break;
958
959	case OPS_PTAG_SS_USERDEFINED00:
960	case OPS_PTAG_SS_USERDEFINED01:
961	case OPS_PTAG_SS_USERDEFINED02:
962	case OPS_PTAG_SS_USERDEFINED03:
963	case OPS_PTAG_SS_USERDEFINED04:
964	case OPS_PTAG_SS_USERDEFINED05:
965	case OPS_PTAG_SS_USERDEFINED06:
966	case OPS_PTAG_SS_USERDEFINED07:
967	case OPS_PTAG_SS_USERDEFINED08:
968	case OPS_PTAG_SS_USERDEFINED09:
969	case OPS_PTAG_SS_USERDEFINED10:
970		start_subpacket(contents->tag);
971		print_hexdump("Internal or user-defined",
972			      content->ss_userdefined.data.contents,
973			      content->ss_userdefined.data.len);
974		end_subpacket();
975		break;
976
977	case OPS_PTAG_SS_RESERVED:
978		start_subpacket(contents->tag);
979		print_hexdump("Reserved",
980			      content->ss_userdefined.data.contents,
981			      content->ss_userdefined.data.len);
982		end_subpacket();
983		break;
984
985	case OPS_PTAG_SS_REVOCATION_REASON:
986		start_subpacket(contents->tag);
987		print_hexdump("Revocation Reason",
988			      &content->ss_revocation_reason.code,
989			      1);
990		str = __ops_show_ss_rr_code(content->ss_revocation_reason.code);
991		print_string(NULL, str);
992		/* xxx - todo : output text as UTF-8 string */
993		end_subpacket();
994		break;
995
996	case OPS_PTAG_CT_LITERAL_DATA_HEADER:
997		print_tagname("LITERAL DATA HEADER");
998		printf("  literal data header format=%c filename='%s'\n",
999		       content->literal_data_header.format,
1000		       content->literal_data_header.filename);
1001		showtime("    modification time",
1002			 content->literal_data_header.modification_time);
1003		printf("\n");
1004		break;
1005
1006	case OPS_PTAG_CT_LITERAL_DATA_BODY:
1007		print_tagname("LITERAL DATA BODY");
1008		printf("  literal data body length=%d\n",
1009		       content->literal_data_body.length);
1010		printf("    data=");
1011		print_escaped(content->literal_data_body.data,
1012			      content->literal_data_body.length);
1013		printf("\n");
1014		break;
1015
1016	case OPS_PTAG_CT_SIGNATURE_HEADER:
1017		print_tagname("SIGNATURE");
1018		print_indent();
1019		print_unsigned_int("Signature Version",
1020				   (unsigned)content->signature.info.version);
1021		if (content->signature.info.creation_time_set)
1022			print_time("Signature Creation Time",
1023				content->signature.info.creation_time);
1024
1025		print_string_and_value("Signature Type",
1026			    __ops_show_sig_type(content->signature.info.type),
1027				       content->signature.info.type);
1028
1029		if (content->signature.info.signer_id_set)
1030			print_hexdump_data("Signer ID",
1031					   content->signature.info.signer_id,
1032				  sizeof(content->signature.info.signer_id));
1033
1034		print_string_and_value("Public Key Algorithm",
1035			__ops_show_pka(content->signature.info.key_algorithm),
1036				     content->signature.info.key_algorithm);
1037		print_string_and_value("Hash Algorithm",
1038				       __ops_show_hash_algorithm(content->signature.info.hash_algorithm),
1039				    content->signature.info.hash_algorithm);
1040
1041		break;
1042
1043	case OPS_PTAG_CT_SIGNATURE_FOOTER:
1044		print_indent();
1045		print_hexdump_data("hash2", &content->signature.hash2[0], 2);
1046
1047		switch (content->signature.info.key_algorithm) {
1048		case OPS_PKA_RSA:
1049			print_bn("sig", content->signature.info.signature.rsa.sig);
1050			break;
1051
1052		case OPS_PKA_DSA:
1053			print_bn("r", content->signature.info.signature.dsa.r);
1054			print_bn("s", content->signature.info.signature.dsa.s);
1055			break;
1056
1057		case OPS_PKA_ELGAMAL_ENCRYPT_OR_SIGN:
1058			print_bn("r", content->signature.info.signature.elgamal.r);
1059			print_bn("s", content->signature.info.signature.elgamal.s);
1060			break;
1061
1062		case OPS_PKA_PRIVATE00:
1063		case OPS_PKA_PRIVATE01:
1064		case OPS_PKA_PRIVATE02:
1065		case OPS_PKA_PRIVATE03:
1066		case OPS_PKA_PRIVATE04:
1067		case OPS_PKA_PRIVATE05:
1068		case OPS_PKA_PRIVATE06:
1069		case OPS_PKA_PRIVATE07:
1070		case OPS_PKA_PRIVATE08:
1071		case OPS_PKA_PRIVATE09:
1072		case OPS_PKA_PRIVATE10:
1073			print_data("Private/Experimental",
1074			   &content->signature.info.signature.unknown.data);
1075			break;
1076
1077		default:
1078			assert( /* CONSTCOND */ 0);
1079		}
1080		break;
1081
1082	case OPS_PARSER_CMD_GET_SK_PASSPHRASE:
1083		print_tagname("OPS_PARSER_CMD_GET_SK_PASSPHRASE");
1084		break;
1085
1086	case OPS_PTAG_CT_SECRET_KEY:
1087		print_tagname("OPS_PTAG_CT_SECRET_KEY");
1088		__ops_print_secret_key_verbose(contents->tag, &content->secret_key);
1089		break;
1090
1091	case OPS_PTAG_CT_ENCRYPTED_SECRET_KEY:
1092		print_tagname("OPS_PTAG_CT_ENCRYPTED_SECRET_KEY");
1093		__ops_print_secret_key_verbose(contents->tag, &content->secret_key);
1094		break;
1095
1096	case OPS_PTAG_CT_ARMOUR_HEADER:
1097		print_tagname("ARMOUR HEADER");
1098		print_string("type", content->armour_header.type);
1099		break;
1100
1101	case OPS_PTAG_CT_SIGNED_CLEARTEXT_HEADER:
1102		print_tagname("SIGNED CLEARTEXT HEADER");
1103		print_headers(&content->signed_cleartext_header.headers);
1104		break;
1105
1106	case OPS_PTAG_CT_SIGNED_CLEARTEXT_BODY:
1107		print_tagname("SIGNED CLEARTEXT BODY");
1108		print_block("signed cleartext", content->signed_cleartext_body.data,
1109			    content->signed_cleartext_body.length);
1110		break;
1111
1112	case OPS_PTAG_CT_SIGNED_CLEARTEXT_TRAILER:
1113		print_tagname("SIGNED CLEARTEXT TRAILER");
1114		printf("hash algorithm: %d\n",
1115		       content->signed_cleartext_trailer.hash->algorithm);
1116		printf("\n");
1117		break;
1118
1119	case OPS_PTAG_CT_UNARMOURED_TEXT:
1120		if (!unarmoured) {
1121			print_tagname("UNARMOURED TEXT");
1122			unarmoured = true;
1123		}
1124		putchar('[');
1125		print_escaped(content->unarmoured_text.data,
1126			      content->unarmoured_text.length);
1127		putchar(']');
1128		break;
1129
1130	case OPS_PTAG_CT_ARMOUR_TRAILER:
1131		print_tagname("ARMOUR TRAILER");
1132		print_string("type", content->armour_header.type);
1133		break;
1134
1135	case OPS_PTAG_CT_PK_SESSION_KEY:
1136	case OPS_PTAG_CT_ENCRYPTED_PK_SESSION_KEY:
1137		__ops_print_pk_session_key(contents->tag, &content->pk_session_key);
1138		break;
1139
1140	case OPS_PARSER_CMD_GET_SECRET_KEY:
1141		__ops_print_pk_session_key(OPS_PTAG_CT_ENCRYPTED_PK_SESSION_KEY,
1142				    content->get_secret_key.pk_session_key);
1143		break;
1144
1145	default:
1146		print_tagname("UNKNOWN PACKET TYPE");
1147		fprintf(stderr, "__ops_print_packet: unknown tag=%d (0x%x)\n", contents->tag,
1148			contents->tag);
1149		exit(1);
1150	}
1151	return 1;
1152}
1153
1154static __ops_parse_cb_return_t
1155cb_list_packets(const __ops_parser_content_t * contents, __ops_parse_cb_info_t * cbinfo)
1156{
1157	OPS_USED(cbinfo);
1158
1159	__ops_print_packet(contents);
1160#ifdef XXX
1161	if (unarmoured && contents->tag != OPS_PTAG_CT_UNARMOURED_TEXT) {
1162		unarmoured = false;
1163		puts("UNARMOURED TEXT ends");
1164	}
1165	switch (contents->tag) {
1166	case OPS_PARSER_ERROR:
1167		printf("parse error: %s\n", content->error.error);
1168		break;
1169
1170	case OPS_PARSER_ERRCODE:
1171		printf("parse error: %s\n",
1172		       __ops_errcode(content->errcode.errcode));
1173		break;
1174
1175	case OPS_PARSER_PACKET_END:
1176		print_packet_hex(&content->packet);
1177		break;
1178
1179	case OPS_PARSER_PTAG:
1180		if (content->ptag.content_tag == OPS_PTAG_CT_PUBLIC_KEY) {
1181			indent = 0;
1182			printf("\n*** NEXT KEY ***\n");
1183		}
1184		printf("\n");
1185		print_indent();
1186		printf("==== ptag new_format=%d content_tag=%d length_type=%d"
1187		       " length=0x%x (%d) position=0x%x (%d)\n", content->ptag.new_format,
1188		       content->ptag.content_tag, content->ptag.length_type,
1189		       content->ptag.length, content->ptag.length,
1190		       content->ptag.position, content->ptag.position);
1191		print_tagname(__ops_show_packet_tag(content->ptag.content_tag));
1192		break;
1193
1194	case OPS_PTAG_CT_SE_DATA_HEADER:
1195		print_tagname("SYMMETRIC ENCRYPTED DATA");
1196		break;
1197
1198	case OPS_PTAG_CT_SE_IP_DATA_HEADER:
1199		print_tagname("SYMMETRIC ENCRYPTED INTEGRITY PROTECTED DATA HEADER");
1200		printf("Version: %d\n", content->se_ip_data_header.version);
1201		break;
1202
1203	case OPS_PTAG_CT_SE_IP_DATA_BODY:
1204		print_tagname("SYMMETRIC ENCRYPTED INTEGRITY PROTECTED DATA BODY");
1205		printf("  data body length=%d\n",
1206		       content->se_data_body.length);
1207		printf("    data=");
1208		hexdump(content->se_data_body.data,
1209			content->se_data_body.length, "");
1210		printf("\n");
1211		break;
1212
1213	case OPS_PTAG_CT_PUBLIC_KEY:
1214	case OPS_PTAG_CT_PUBLIC_SUBKEY:
1215		if (contents->tag == OPS_PTAG_CT_PUBLIC_KEY)
1216			print_tagname("PUBLIC KEY");
1217		else
1218			print_tagname("PUBLIC SUBKEY");
1219
1220		__ops_print_public_key(&content->public_key);
1221		break;
1222
1223	case OPS_PTAG_CT_TRUST:
1224		print_tagname("TRUST");
1225		print_data("Trust", &content->trust.data);
1226		break;
1227
1228	case OPS_PTAG_CT_USER_ID:
1229		/* XXX: how do we print UTF-8? */
1230		print_tagname("USER ID");
1231		print_utf8_string("user_id", content->user_id.user_id);
1232		break;
1233
1234	case OPS_PTAG_CT_SIGNATURE:
1235		print_tagname("SIGNATURE");
1236		print_indent();
1237		print_unsigned_int("Signature Version",
1238				   content->signature.info.version);
1239		if (content->signature.info.creation_time_set)
1240			print_time("Signature Creation Time",
1241				   content->signature.info.creation_time);
1242
1243		print_string_and_value("Signature Type",
1244			    __ops_show_sig_type(content->signature.info.type),
1245				       content->signature.info.type);
1246
1247		if (content->signature.info.signer_id_set)
1248			print_hexdump_data("Signer ID",
1249					   content->signature.info.signer_id,
1250				  sizeof(content->signature.info.signer_id));
1251
1252		print_string_and_value("Public Key Algorithm",
1253			__ops_show_pka(content->signature.info.key_algorithm),
1254				     content->signature.info.key_algorithm);
1255		print_string_and_value("Hash Algorithm",
1256				       __ops_show_hash_algorithm(content->signature.info.hash_algorithm),
1257				    content->signature.info.hash_algorithm);
1258		print_unsigned_int("Hashed data len", content->signature.info.v4_hashed_data_length);
1259
1260		print_indent();
1261		print_hexdump_data("hash2", &content->signature.hash2[0], 2);
1262
1263		switch (content->signature.info.key_algorithm) {
1264		case OPS_PKA_RSA:
1265		case OPS_PKA_RSA_SIGN_ONLY:
1266			print_bn("sig", content->signature.info.signature.rsa.sig);
1267			break;
1268
1269		case OPS_PKA_DSA:
1270			print_bn("r", content->signature.info.signature.dsa.r);
1271			print_bn("s", content->signature.info.signature.dsa.s);
1272			break;
1273
1274		case OPS_PKA_ELGAMAL_ENCRYPT_OR_SIGN:
1275			print_bn("r", content->signature.info.signature.elgamal.r);
1276			print_bn("s", content->signature.info.signature.elgamal.s);
1277			break;
1278
1279		default:
1280			assert(0);
1281		}
1282
1283		if (content->signature.hash)
1284			printf("data hash is set\n");
1285
1286		break;
1287
1288	case OPS_PTAG_CT_COMPRESSED:
1289		print_tagname("COMPRESSED");
1290		print_unsigned_int("Compressed Data Type", content->compressed.type);
1291		break;
1292
1293	case OPS_PTAG_CT_ONE_PASS_SIGNATURE:
1294		print_tagname("ONE PASS SIGNATURE");
1295
1296		print_unsigned_int("Version", content->one_pass_signature.version);
1297		print_string_and_value("Signature Type",
1298		    __ops_show_sig_type(content->one_pass_signature.sig_type),
1299				       content->one_pass_signature.sig_type);
1300		print_string_and_value("Hash Algorithm",
1301				       __ops_show_hash_algorithm(content->one_pass_signature.hash_algorithm),
1302				content->one_pass_signature.hash_algorithm);
1303		print_string_and_value("Public Key Algorithm",
1304		    __ops_show_pka(content->one_pass_signature.key_algorithm),
1305				 content->one_pass_signature.key_algorithm);
1306		print_hexdump_data("Signer ID",
1307				   content->one_pass_signature.keyid,
1308				   sizeof(content->one_pass_signature.keyid));
1309
1310		print_unsigned_int("Nested",
1311				   content->one_pass_signature.nested);
1312		break;
1313
1314	case OPS_PTAG_CT_USER_ATTRIBUTE:
1315		print_tagname("USER ATTRIBUTE");
1316		print_hexdump("User Attribute",
1317			      content->user_attribute.data.contents,
1318			      content->user_attribute.data.len);
1319		break;
1320
1321	case OPS_PTAG_RAW_SS:
1322		assert(!contents->critical);
1323		start_subpacket(contents->tag);
1324		print_unsigned_int("Raw Signature Subpacket: tag",
1325		   content->ss_raw.tag - OPS_PTAG_SIGNATURE_SUBPACKET_BASE);
1326		print_hexdump("Raw Data",
1327			      content->ss_raw.raw,
1328			      content->ss_raw.length);
1329		break;
1330
1331	case OPS_PTAG_SS_CREATION_TIME:
1332		start_subpacket(contents->tag);
1333		print_time("Signature Creation Time", content->ss_time.time);
1334		end_subpacket();
1335		break;
1336
1337	case OPS_PTAG_SS_EXPIRATION_TIME:
1338		start_subpacket(contents->tag);
1339		print_duration("Signature Expiration Time", content->ss_time.time);
1340		end_subpacket();
1341		break;
1342
1343	case OPS_PTAG_SS_KEY_EXPIRATION_TIME:
1344		start_subpacket(contents->tag);
1345		print_duration("Key Expiration Time", content->ss_time.time);
1346		end_subpacket();
1347		break;
1348
1349	case OPS_PTAG_SS_TRUST:
1350		start_subpacket(contents->tag);
1351		print_string("Trust Signature", "");
1352		print_unsigned_int("Level",
1353				   content->ss_trust.level);
1354		print_unsigned_int("Amount",
1355				   content->ss_trust.amount);
1356		end_subpacket();
1357		break;
1358
1359	case OPS_PTAG_SS_REVOCABLE:
1360		start_subpacket(contents->tag);
1361		print_boolean("Revocable", content->ss_revocable.revocable);
1362		end_subpacket();
1363		break;
1364
1365	case OPS_PTAG_SS_REVOCATION_KEY:
1366		start_subpacket(contents->tag);
1367		/* not yet tested */
1368		printf("  revocation key: class=0x%x",
1369		       content->ss_revocation_key.class);
1370		if (content->ss_revocation_key.class & 0x40)
1371			printf(" (sensitive)");
1372		printf(", algid=0x%x",
1373		       content->ss_revocation_key.algid);
1374		printf(", fingerprint=");
1375		hexdump(content->ss_revocation_key.fingerprint, 20, "");
1376		printf("\n");
1377		end_subpacket();
1378		break;
1379
1380	case OPS_PTAG_SS_ISSUER_KEY_ID:
1381		start_subpacket(contents->tag);
1382		print_hexdump("Issuer Key Id",
1383			      &content->ss_issuer_key_id.key_id[0],
1384			      sizeof(content->ss_issuer_key_id.key_id));
1385		end_subpacket();
1386		break;
1387
1388	case OPS_PTAG_SS_PREFERRED_SKA:
1389		start_subpacket(contents->tag);
1390		print_data("Preferred Symmetric Algorithms",
1391			   &content->ss_preferred_ska.data);
1392
1393		text = __ops_showall_ss_preferred_ska(content->ss_preferred_ska);
1394		print_text_breakdown(text);
1395		__ops_text_free(text);
1396
1397		end_subpacket();
1398		break;
1399
1400	case OPS_PTAG_SS_PRIMARY_USER_ID:
1401		start_subpacket(contents->tag);
1402		print_boolean("Primary User ID",
1403			      content->ss_primary_user_id.primary_user_id);
1404		end_subpacket();
1405		break;
1406
1407	case OPS_PTAG_SS_PREFERRED_HASH:
1408		start_subpacket(contents->tag);
1409		print_data("Preferred Hash Algorithms",
1410			   &content->ss_preferred_hash.data);
1411
1412		text = __ops_showall_ss_preferred_hash(content->ss_preferred_hash);
1413		print_text_breakdown(text);
1414		__ops_text_free(text);
1415		end_subpacket();
1416		break;
1417
1418	case OPS_PTAG_SS_PREFERRED_COMPRESSION:
1419		start_subpacket(contents->tag);
1420		print_data("Preferred Compression Algorithms",
1421			   &content->ss_preferred_compression.data);
1422
1423		text = __ops_showall_ss_preferred_compression(content->ss_preferred_compression);
1424		print_text_breakdown(text);
1425		__ops_text_free(text);
1426		end_subpacket();
1427		break;
1428
1429	case OPS_PTAG_SS_KEY_FLAGS:
1430		start_subpacket(contents->tag);
1431		print_data("Key Flags", &content->ss_key_flags.data);
1432
1433		text = __ops_showall_ss_key_flags(content->ss_key_flags);
1434		print_text_breakdown(text);
1435		__ops_text_free(text);
1436
1437		end_subpacket();
1438		break;
1439
1440	case OPS_PTAG_SS_KEY_SERVER_PREFS:
1441		start_subpacket(contents->tag);
1442		print_data("Key Server Preferences",
1443			   &content->ss_key_server_prefs.data);
1444
1445		text = __ops_showall_ss_key_server_prefs(content->ss_key_server_prefs);
1446		print_text_breakdown(text);
1447		__ops_text_free(text);
1448
1449		end_subpacket();
1450		break;
1451
1452	case OPS_PTAG_SS_FEATURES:
1453		start_subpacket(contents->tag);
1454		print_data("Features",
1455			   &content->ss_features.data);
1456
1457		text = __ops_showall_ss_features(content->ss_features);
1458		print_text_breakdown(text);
1459		__ops_text_free(text);
1460
1461		end_subpacket();
1462		break;
1463
1464	case OPS_PTAG_SS_NOTATION_DATA:
1465		start_subpacket(contents->tag);
1466		print_indent();
1467		printf("Notation Data:\n");
1468
1469		indent++;
1470		print_data("Flags",
1471			   &content->ss_notation_data.flags);
1472		text = __ops_showall_ss_notation_data_flags(content->ss_notation_data);
1473		print_text_breakdown(text);
1474		__ops_text_free(text);
1475
1476		/* xxx - TODO: print out UTF - rachel */
1477
1478		print_data("Name",
1479			   &content->ss_notation_data.name);
1480
1481		print_data("Value",
1482			   &content->ss_notation_data.value);
1483
1484		indent--;
1485		end_subpacket();
1486		break;
1487
1488	case OPS_PTAG_SS_REGEXP:
1489		start_subpacket(contents->tag);
1490		print_hexdump("Regular Expression",
1491			      (unsigned char *) content->ss_regexp.text,
1492			      strlen(content->ss_regexp.text));
1493		print_string(NULL,
1494			     content->ss_regexp.text);
1495		end_subpacket();
1496		break;
1497
1498	case OPS_PTAG_SS_POLICY_URL:
1499		start_subpacket(contents->tag);
1500		print_string("Policy URL",
1501			     content->ss_policy_url.text);
1502		end_subpacket();
1503		break;
1504
1505	case OPS_PTAG_SS_SIGNERS_USER_ID:
1506		start_subpacket(contents->tag);
1507		print_utf8_string("Signer's User ID", content->ss_signers_user_id.user_id);
1508		end_subpacket();
1509		break;
1510
1511	case OPS_PTAG_SS_PREFERRED_KEY_SERVER:
1512		start_subpacket(contents->tag);
1513		print_string("Preferred Key Server",
1514			     content->ss_preferred_key_server.text);
1515		end_subpacket();
1516		break;
1517
1518	case OPS_PTAG_SS_USERDEFINED00:
1519	case OPS_PTAG_SS_USERDEFINED01:
1520	case OPS_PTAG_SS_USERDEFINED02:
1521	case OPS_PTAG_SS_USERDEFINED03:
1522	case OPS_PTAG_SS_USERDEFINED04:
1523	case OPS_PTAG_SS_USERDEFINED05:
1524	case OPS_PTAG_SS_USERDEFINED06:
1525	case OPS_PTAG_SS_USERDEFINED07:
1526	case OPS_PTAG_SS_USERDEFINED08:
1527	case OPS_PTAG_SS_USERDEFINED09:
1528	case OPS_PTAG_SS_USERDEFINED10:
1529		start_subpacket(contents->tag);
1530		print_hexdump("Internal or user-defined",
1531			      content->ss_userdefined.data.contents,
1532			      content->ss_userdefined.data.len);
1533		end_subpacket();
1534		break;
1535
1536	case OPS_PTAG_SS_RESERVED:
1537		start_subpacket(contents->tag);
1538		print_hexdump("Reserved",
1539			      content->ss_userdefined.data.contents,
1540			      content->ss_userdefined.data.len);
1541		end_subpacket();
1542		break;
1543
1544	case OPS_PTAG_SS_REVOCATION_REASON:
1545		start_subpacket(contents->tag);
1546		print_hexdump("Revocation Reason",
1547			      &content->ss_revocation_reason.code,
1548			      1);
1549		str = __ops_show_ss_rr_code(content->ss_revocation_reason.code);
1550		print_string(NULL, str);
1551		/* xxx - todo : output text as UTF-8 string */
1552		end_subpacket();
1553		break;
1554
1555	case OPS_PTAG_CT_LITERAL_DATA_HEADER:
1556		print_tagname("LITERAL DATA HEADER");
1557		printf("  literal data header format=%c filename='%s'\n",
1558		       content->literal_data_header.format,
1559		       content->literal_data_header.filename);
1560		print_time("    modification time",
1561			   content->literal_data_header.modification_time);
1562		printf("\n");
1563		break;
1564
1565	case OPS_PTAG_CT_LITERAL_DATA_BODY:
1566		print_tagname("LITERAL DATA BODY");
1567		printf("  literal data body length=%d\n",
1568		       content->literal_data_body.length);
1569		printf("    data=");
1570		print_escaped(content->literal_data_body.data,
1571			      content->literal_data_body.length);
1572		printf("\n");
1573		break;
1574
1575	case OPS_PTAG_CT_SIGNATURE_HEADER:
1576		print_tagname("SIGNATURE");
1577		print_indent();
1578		print_unsigned_int("Signature Version",
1579				   content->signature.info.version);
1580		if (content->signature.info.creation_time_set)
1581			print_time("Signature Creation Time", content->signature.info.creation_time);
1582
1583		print_string_and_value("Signature Type",
1584			    __ops_show_sig_type(content->signature.info.type),
1585				       content->signature.info.type);
1586
1587		if (content->signature.info.signer_id_set)
1588			print_hexdump_data("Signer ID",
1589					   content->signature.info.signer_id,
1590				  sizeof(content->signature.info.signer_id));
1591
1592		print_string_and_value("Public Key Algorithm",
1593			__ops_show_pka(content->signature.info.key_algorithm),
1594				     content->signature.info.key_algorithm);
1595		print_string_and_value("Hash Algorithm",
1596				       __ops_show_hash_algorithm(content->signature.info.hash_algorithm),
1597				    content->signature.info.hash_algorithm);
1598
1599		break;
1600
1601	case OPS_PTAG_CT_SIGNATURE_FOOTER:
1602		print_indent();
1603		print_hexdump_data("hash2", &content->signature.hash2[0], 2);
1604
1605		switch (content->signature.info.key_algorithm) {
1606		case OPS_PKA_RSA:
1607			print_bn("sig", content->signature.info.signature.rsa.sig);
1608			break;
1609
1610		case OPS_PKA_DSA:
1611			print_bn("r", content->signature.info.signature.dsa.r);
1612			print_bn("s", content->signature.info.signature.dsa.s);
1613			break;
1614
1615		case OPS_PKA_ELGAMAL_ENCRYPT_OR_SIGN:
1616			print_bn("r", content->signature.info.signature.elgamal.r);
1617			print_bn("s", content->signature.info.signature.elgamal.s);
1618			break;
1619
1620		case OPS_PKA_PRIVATE00:
1621		case OPS_PKA_PRIVATE01:
1622		case OPS_PKA_PRIVATE02:
1623		case OPS_PKA_PRIVATE03:
1624		case OPS_PKA_PRIVATE04:
1625		case OPS_PKA_PRIVATE05:
1626		case OPS_PKA_PRIVATE06:
1627		case OPS_PKA_PRIVATE07:
1628		case OPS_PKA_PRIVATE08:
1629		case OPS_PKA_PRIVATE09:
1630		case OPS_PKA_PRIVATE10:
1631			print_data("Private/Experimental",
1632			   &content->signature.info.signature.unknown.data);
1633			break;
1634
1635		default:
1636			assert(0);
1637		}
1638		break;
1639
1640	case OPS_PARSER_CMD_GET_SK_PASSPHRASE:
1641		if (cbinfo->cryptinfo.cb_get_passphrase) {
1642			return cbinfo->cryptinfo.cb_get_passphrase(contents, cbinfo);
1643		}
1644		break;
1645
1646	case OPS_PTAG_CT_SECRET_KEY:
1647	case OPS_PTAG_CT_ENCRYPTED_SECRET_KEY:
1648		__ops_print_secret_key_verbose(contents->tag, &content->secret_key);
1649		break;
1650
1651	case OPS_PTAG_CT_ARMOUR_HEADER:
1652		print_tagname("ARMOUR HEADER");
1653		print_string("type", content->armour_header.type);
1654		break;
1655
1656	case OPS_PTAG_CT_SIGNED_CLEARTEXT_HEADER:
1657		print_tagname("SIGNED CLEARTEXT HEADER");
1658		print_headers(&content->signed_cleartext_header.headers);
1659		break;
1660
1661	case OPS_PTAG_CT_SIGNED_CLEARTEXT_BODY:
1662		print_tagname("SIGNED CLEARTEXT BODY");
1663		print_block("signed cleartext", content->signed_cleartext_body.data,
1664			    content->signed_cleartext_body.length);
1665		break;
1666
1667	case OPS_PTAG_CT_SIGNED_CLEARTEXT_TRAILER:
1668		print_tagname("SIGNED CLEARTEXT TRAILER");
1669		printf("hash algorithm: %d\n",
1670		       content->signed_cleartext_trailer.hash->algorithm);
1671		printf("\n");
1672		break;
1673
1674	case OPS_PTAG_CT_UNARMOURED_TEXT:
1675		if (!unarmoured) {
1676			print_tagname("UNARMOURED TEXT");
1677			unarmoured = true;
1678		}
1679		putchar('[');
1680		print_escaped(content->unarmoured_text.data,
1681			      content->unarmoured_text.length);
1682		putchar(']');
1683		break;
1684
1685	case OPS_PTAG_CT_ARMOUR_TRAILER:
1686		print_tagname("ARMOUR TRAILER");
1687		print_string("type", content->armour_header.type);
1688		break;
1689
1690	case OPS_PTAG_CT_PK_SESSION_KEY:
1691	case OPS_PTAG_CT_ENCRYPTED_PK_SESSION_KEY:
1692		__ops_print_pk_session_key(contents->tag, &content->pk_session_key);
1693		break;
1694
1695	case OPS_PARSER_CMD_GET_SECRET_KEY:
1696		__ops_print_pk_session_key(OPS_PTAG_CT_ENCRYPTED_PK_SESSION_KEY,
1697				    content->get_secret_key.pk_session_key);
1698		return get_secret_key_cb(contents, cbinfo);
1699
1700	default:
1701		print_tagname("UNKNOWN PACKET TYPE");
1702		fprintf(stderr, "packet-dump: unknown tag=%d (0x%x)\n", contents->tag,
1703			contents->tag);
1704		exit(1);
1705	}
1706#endif				/* XXX */
1707	return OPS_RELEASE_MEMORY;
1708}
1709
1710/**
1711\ingroup Core_Print
1712\param filename
1713\param armour
1714\param keyring
1715\param cb_get_passphrase
1716*/
1717void
1718__ops_list_packets(char *filename, bool armour, __ops_keyring_t * keyring, __ops_parse_cb_t * cb_get_passphrase)
1719{
1720	int             fd = 0;
1721	__ops_parse_info_t *pinfo = NULL;
1722	const bool accumulate = true;
1723
1724	fd = __ops_setup_file_read(&pinfo, filename, NULL, cb_list_packets, accumulate);
1725	__ops_parse_options(pinfo, OPS_PTAG_SS_ALL, OPS_PARSE_PARSED);
1726	pinfo->cryptinfo.keyring = keyring;
1727	pinfo->cryptinfo.cb_get_passphrase = cb_get_passphrase;
1728
1729	if (armour)
1730		__ops_reader_push_dearmour(pinfo);
1731
1732	__ops_parse_and_print_errors(pinfo);
1733
1734	__ops_teardown_file_read(pinfo, fd);
1735}
1736