packet-print.c revision 1.26
1/*-
2 * Copyright (c) 2009 The NetBSD Foundation, Inc.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to The NetBSD Foundation
6 * by Alistair Crooks (agc@NetBSD.org)
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 */
29/*
30 * Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
31 * All rights reserved.
32 * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
33 * their moral rights under the UK Copyright Design and Patents Act 1988 to
34 * be recorded as the authors of this copyright work.
35 *
36 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
37 * use this file except in compliance with the License.
38 *
39 * You may obtain a copy of the License at
40 *     http://www.apache.org/licenses/LICENSE-2.0
41 *
42 * Unless required by applicable law or agreed to in writing, software
43 * distributed under the License is distributed on an "AS IS" BASIS,
44 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
45 *
46 * See the License for the specific language governing permissions and
47 * limitations under the License.
48 */
49
50/*
51 * ! \file \brief Standard API print functions
52 */
53#include "config.h"
54
55#ifdef HAVE_SYS_CDEFS_H
56#include <sys/cdefs.h>
57#endif
58
59#if defined(__NetBSD__)
60__COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved.");
61__RCSID("$NetBSD: packet-print.c,v 1.26 2010/02/12 03:38:48 agc Exp $");
62#endif
63
64#include <string.h>
65#include <stdio.h>
66
67#ifdef HAVE_UNISTD_H
68#include <unistd.h>
69#endif
70
71#include "crypto.h"
72#include "keyring.h"
73#include "packet-show.h"
74#include "signature.h"
75#include "readerwriter.h"
76#include "netpgpdefs.h"
77#include "netpgpsdk.h"
78#include "packet.h"
79#include "netpgpdigest.h"
80
81/* static functions */
82
83static void
84print_indent(int indent)
85{
86	int             i;
87
88	for (i = 0; i < indent; i++) {
89		printf("  ");
90	}
91}
92
93static void
94print_name(int indent, const char *name)
95{
96	print_indent(indent);
97	if (name) {
98		printf("%s: ", name);
99	}
100}
101
102static void
103print_hexdump(int indent, const char *name, const unsigned char *data, unsigned int len)
104{
105	print_name(indent, name);
106
107	printf("len=%u, data=0x", len);
108	hexdump(stdout, data, len, "");
109	printf("\n");
110}
111
112static void
113hexdump_data(int indent, const char *name, const unsigned char *data, unsigned len)
114{
115	print_name(indent, name);
116
117	printf("0x");
118	hexdump(stdout, data, len, "");
119	printf("\n");
120}
121
122static void
123print_uint(int indent, const char *name, unsigned int val)
124{
125	print_name(indent, name);
126	printf("%u\n", val);
127}
128
129static void
130showtime(const char *name, time_t t)
131{
132	printf("%s=%" PRItime "d (%.24s)", name, (long long) t, ctime(&t));
133}
134
135static void
136print_time(int indent, const char *name, time_t t)
137{
138	print_indent(indent);
139	printf("%s: ", name);
140	showtime("time", t);
141	printf("\n");
142}
143
144static void
145print_string_and_value(int indent, const char *name, const char *str, unsigned char value)
146{
147	print_name(indent, name);
148	printf("%s (0x%x)\n", str, value);
149}
150
151static void
152print_tagname(int indent, const char *str)
153{
154	print_indent(indent);
155	printf("%s packet\n", str);
156}
157
158static void
159print_data(int indent, const char *name, const __ops_data_t *data)
160{
161	print_hexdump(indent, name, data->contents, data->len);
162}
163
164static void
165print_bn(int indent, const char *name, const BIGNUM *bn)
166{
167	print_indent(indent);
168	printf("%s=", name);
169	if (bn) {
170		BN_print_fp(stdout, bn);
171		putchar('\n');
172	} else {
173		puts("(unset)");
174	}
175}
176
177static void
178print_packet_hex(const __ops_subpacket_t *pkt)
179{
180	unsigned char  *cur;
181	unsigned	rem;
182	unsigned	blksz = 4;
183	int             i;
184
185	printf("\nhexdump of packet contents follows:\n");
186	for (i = 1, cur = pkt->raw;
187	     cur < (pkt->raw + pkt->length);
188	     cur += blksz, i++) {
189		rem = pkt->raw + pkt->length - cur;
190		hexdump(stdout, cur, (rem <= blksz) ? rem : blksz, "");
191		printf(" ");
192		if (i % 8 == 0) {
193			printf("\n");
194		}
195
196	}
197	printf("\n");
198}
199
200static void
201print_escaped(const unsigned char *data, size_t length)
202{
203	while (length-- > 0) {
204		if ((*data >= 0x20 && *data < 0x7f && *data != '%') ||
205		    *data == '\n') {
206			putchar(*data);
207		} else {
208			printf("%%%02x", *data);
209		}
210		++data;
211	}
212}
213
214static void
215print_string(int indent, const char *name, const char *str)
216{
217	print_name(indent, name);
218	print_escaped((const unsigned char *) str, strlen(str));
219	putchar('\n');
220}
221
222static void
223print_utf8_string(int indent, const char *name, const unsigned char *str)
224{
225	/* \todo Do this better for non-English character sets */
226	print_string(indent, name, (const char *) str);
227}
228
229static void
230print_duration(int indent, const char *name, time_t t)
231{
232	int             mins, hours, days, years;
233
234	print_indent(indent);
235	printf("%s: ", name);
236	printf("duration %" PRItime "d seconds", (long long) t);
237
238	mins = (int)(t / 60);
239	hours = mins / 60;
240	days = hours / 24;
241	years = days / 365;
242
243	printf(" (approx. ");
244	if (years) {
245		printf("%d %s", years, years == 1 ? "year" : "years");
246	} else if (days) {
247		printf("%d %s", days, days == 1 ? "day" : "days");
248	} else if (hours) {
249		printf("%d %s", hours, hours == 1 ? "hour" : "hours");
250	}
251	printf(")\n");
252}
253
254static void
255print_boolean(int indent, const char *name, unsigned char boolval)
256{
257	print_name(indent, name);
258	printf("%s\n", (boolval) ? "Yes" : "No");
259}
260
261static void
262print_text_breakdown(int indent, __ops_text_t *text)
263{
264	const char     *prefix = ".. ";
265	unsigned        i;
266
267	/* these were recognised */
268	for (i = 0; i < text->known.used; i++) {
269		print_indent(indent);
270		printf("%s", prefix);
271		printf("%s\n", text->known.strings[i]);
272	}
273	/*
274	 * these were not recognised. the strings will contain the hex value
275	 * of the unrecognised value in string format - see
276	 * process_octet_str()
277	 */
278	if (text->unknown.used) {
279		printf("\n");
280		print_indent(indent);
281		printf("Not Recognised: ");
282	}
283	for (i = 0; i < text->unknown.used; i++) {
284		print_indent(indent);
285		printf("%s", prefix);
286		printf("%s\n", text->unknown.strings[i]);
287	}
288}
289
290static void
291print_headers(const __ops_headers_t *h)
292{
293	unsigned        i;
294
295	for (i = 0; i < h->headerc; ++i) {
296		printf("%s=%s\n", h->headers[i].key, h->headers[i].value);
297	}
298}
299
300static void
301print_block(int indent, const char *name, const unsigned char *str, size_t length)
302{
303	int             o = length;
304
305	print_indent(indent);
306	printf(">>>>> %s >>>>>\n", name);
307
308	print_indent(indent);
309	for (; length > 0; --length) {
310		if (*str >= 0x20 && *str < 0x7f && *str != '%') {
311			putchar(*str);
312		} else if (*str == '\n') {
313			putchar(*str);
314			print_indent(indent);
315		} else {
316			printf("%%%02x", *str);
317		}
318		++str;
319	}
320	if (o && str[-1] != '\n') {
321		putchar('\n');
322		print_indent(indent);
323		fputs("[no newline]", stdout);
324	} else {
325		print_indent(indent);
326	}
327	printf("<<<<< %s <<<<<\n", name);
328}
329
330/* return the number of bits in the public key */
331static int
332numkeybits(const __ops_pubkey_t *pubkey)
333{
334	switch(pubkey->alg) {
335	case OPS_PKA_RSA:
336	case OPS_PKA_RSA_ENCRYPT_ONLY:
337	case OPS_PKA_RSA_SIGN_ONLY:
338		return BN_num_bytes(pubkey->key.rsa.n) * 8;
339	case OPS_PKA_DSA:
340		switch(BN_num_bytes(pubkey->key.dsa.q)) {
341		case 20:
342			return 1024;
343		case 28:
344			return 2048;
345		case 32:
346			return 3072;
347		default:
348			return 0;
349		}
350	case OPS_PKA_ELGAMAL:
351		return BN_num_bytes(pubkey->key.elgamal.y) * 8;
352	default:
353		return -1;
354	}
355}
356
357/* return the hexdump as a string */
358static char *
359strhexdump(char *dest, const unsigned char *src, size_t length, const char *sep)
360{
361	unsigned i;
362	int	n;
363
364	for (n = 0, i = 0 ; i < length ; i += 2) {
365		n += snprintf(&dest[n], 3, "%02x", *src++);
366		n += snprintf(&dest[n], 10, "%02x%s", *src++, sep);
367	}
368	return dest;
369}
370
371/* return the time as a string */
372static char *
373ptimestr(char *dest, size_t size, time_t t)
374{
375	struct tm      *tm;
376
377	tm = gmtime(&t);
378	(void) snprintf(dest, size, "%04d-%02d-%02d",
379		tm->tm_year + 1900,
380		tm->tm_mon + 1,
381		tm->tm_mday);
382	return dest;
383}
384
385#ifndef KB
386#define KB(x)	((x) * 1024)
387#endif
388
389/* print into a string (malloc'ed) the pubkeydata */
390int
391__ops_sprint_keydata(const __ops_key_t *key, char **buf, const char *header,
392		const __ops_pubkey_t *pubkey)
393{
394	unsigned	 i;
395	char		 uidbuf[KB(128)];
396	char		 keyid[OPS_KEY_ID_SIZE * 3];
397	char		 fp[(OPS_FINGERPRINT_SIZE * 3) + 1];
398	char		 t[32];
399	int		 n;
400
401	for (i = 0, n = 0; i < key->uidc; i++) {
402		n += snprintf(&uidbuf[n], sizeof(uidbuf) - n,
403			"uid              %s\n", key->uids[i].userid);
404	}
405	return __ops_asprintf(buf, "%s %d/%s %s %s\nKey fingerprint: %s\n%s",
406		header,
407		numkeybits(pubkey),
408		__ops_show_pka(pubkey->alg),
409		strhexdump(keyid, key->key_id, OPS_KEY_ID_SIZE, ""),
410		ptimestr(t, sizeof(t), pubkey->birthtime),
411		strhexdump(fp, key->fingerprint.fingerprint, OPS_FINGERPRINT_SIZE, " "),
412		uidbuf);
413}
414
415int
416__ops_hkp_sprint_keydata(const __ops_key_t *key, char **buf,
417		const __ops_pubkey_t *pubkey)
418{
419	unsigned	 i;
420	char		 uidbuf[KB(128)];
421	char		 fp[(OPS_FINGERPRINT_SIZE * 3) + 1];
422	int		 n;
423
424	for (i = 0, n = 0; i < key->uidc; i++) {
425		n += snprintf(&uidbuf[n], sizeof(uidbuf) - n,
426			"uid:%s:%lld:%lld:\n",
427			key->uids[i].userid,
428			(long long)pubkey->birthtime,
429			(long long)0);
430	}
431	return __ops_asprintf(buf, "pub:%s:%d:%d:%lld:%lld\n%s",
432		strhexdump(fp, key->fingerprint.fingerprint, OPS_FINGERPRINT_SIZE, ""),
433		pubkey->alg,
434		numkeybits(pubkey),
435		(long long)pubkey->birthtime,
436		(long long)0,
437		uidbuf);
438}
439
440/* print the key data for a pub or sec key */
441void
442__ops_print_keydata(__ops_io_t *io, const __ops_key_t *key, const char *header,
443		const __ops_pubkey_t *pubkey)
444{
445	char	*cp;
446
447	if (__ops_sprint_keydata(key, &cp, header, pubkey)) {
448		(void) fprintf(io->res, "%s", cp);
449		free(cp);
450	}
451}
452
453/**
454\ingroup Core_Print
455\param pubkey
456*/
457void
458__ops_print_pubkey(const __ops_pubkey_t *pubkey)
459{
460	printf("------- PUBLIC KEY ------\n");
461	print_uint(0, "Version", (unsigned)pubkey->version);
462	print_time(0, "Creation Time", pubkey->birthtime);
463	if (pubkey->version == OPS_V3) {
464		print_uint(0, "Days Valid", pubkey->days_valid);
465	}
466	print_string_and_value(0, "Algorithm", __ops_show_pka(pubkey->alg),
467			       pubkey->alg);
468	switch (pubkey->alg) {
469	case OPS_PKA_DSA:
470		print_bn(0, "p", pubkey->key.dsa.p);
471		print_bn(0, "q", pubkey->key.dsa.q);
472		print_bn(0, "g", pubkey->key.dsa.g);
473		print_bn(0, "y", pubkey->key.dsa.y);
474		break;
475
476	case OPS_PKA_RSA:
477	case OPS_PKA_RSA_ENCRYPT_ONLY:
478	case OPS_PKA_RSA_SIGN_ONLY:
479		print_bn(0, "n", pubkey->key.rsa.n);
480		print_bn(0, "e", pubkey->key.rsa.e);
481		break;
482
483	case OPS_PKA_ELGAMAL:
484	case OPS_PKA_ELGAMAL_ENCRYPT_OR_SIGN:
485		print_bn(0, "p", pubkey->key.elgamal.p);
486		print_bn(0, "g", pubkey->key.elgamal.g);
487		print_bn(0, "y", pubkey->key.elgamal.y);
488		break;
489
490	default:
491		(void) fprintf(stderr,
492			"__ops_print_pubkey: Unusual algorithm\n");
493	}
494
495	printf("------- end of PUBLIC KEY ------\n");
496}
497
498int
499__ops_sprint_pubkey(const __ops_key_t *key, char *out, size_t outsize)
500{
501	char	fp[(OPS_FINGERPRINT_SIZE * 3) + 1];
502	int	cc;
503
504	cc = snprintf(out, outsize, "key:%s:%d:%lld:%lld:%d:\n",
505		strhexdump(fp, key->fingerprint.fingerprint, OPS_FINGERPRINT_SIZE, ""),
506		key->key.pubkey.version,
507		(long long)key->key.pubkey.birthtime,
508		(long long)key->key.pubkey.days_valid,
509		key->key.pubkey.alg);
510	switch (key->key.pubkey.alg) {
511	case OPS_PKA_DSA:
512		cc += snprintf(&out[cc], outsize - cc,
513			"pubkey:p=%s:q=%s:g=%s:y=%s\n",
514			BN_bn2hex(key->key.pubkey.key.dsa.p),
515			BN_bn2hex(key->key.pubkey.key.dsa.q),
516			BN_bn2hex(key->key.pubkey.key.dsa.g),
517			BN_bn2hex(key->key.pubkey.key.dsa.y));
518		break;
519	case OPS_PKA_RSA:
520	case OPS_PKA_RSA_ENCRYPT_ONLY:
521	case OPS_PKA_RSA_SIGN_ONLY:
522		cc += snprintf(&out[cc], outsize - cc,
523			"pubkey:n=%s:e=%s\n",
524			BN_bn2hex(key->key.pubkey.key.rsa.n),
525			BN_bn2hex(key->key.pubkey.key.rsa.e));
526		break;
527	case OPS_PKA_ELGAMAL:
528	case OPS_PKA_ELGAMAL_ENCRYPT_OR_SIGN:
529		cc += snprintf(&out[cc], outsize - cc,
530			"pubkey:p=%s:g=%s:y=%s\n",
531			BN_bn2hex(key->key.pubkey.key.elgamal.p),
532			BN_bn2hex(key->key.pubkey.key.elgamal.g),
533			BN_bn2hex(key->key.pubkey.key.elgamal.y));
534		break;
535	default:
536		(void) fprintf(stderr,
537			"__ops_print_pubkey: Unusual algorithm\n");
538	}
539	return cc;
540}
541
542/**
543\ingroup Core_Print
544\param type
545\param seckey
546*/
547static void
548__ops_print_seckey_verbose(const __ops_content_tag_t type,
549				const __ops_seckey_t *seckey)
550{
551	printf("------- SECRET KEY or ENCRYPTED SECRET KEY ------\n");
552	print_tagname(0, (type == OPS_PTAG_CT_SECRET_KEY) ?
553			"SECRET_KEY" :
554			"ENCRYPTED_SECRET_KEY");
555	/* __ops_print_pubkey(key); */
556	printf("S2K Usage: %d\n", seckey->s2k_usage);
557	if (seckey->s2k_usage != OPS_S2KU_NONE) {
558		printf("S2K Specifier: %d\n", seckey->s2k_specifier);
559		printf("Symmetric algorithm: %d (%s)\n", seckey->alg,
560		       __ops_show_symm_alg(seckey->alg));
561		printf("Hash algorithm: %d (%s)\n", seckey->hash_alg,
562		       __ops_show_hash_alg((unsigned char)seckey->hash_alg));
563		if (seckey->s2k_specifier != OPS_S2KS_SIMPLE) {
564			print_hexdump(0, "Salt", seckey->salt,
565					sizeof(seckey->salt));
566		}
567		if (seckey->s2k_specifier == OPS_S2KS_ITERATED_AND_SALTED) {
568			printf("Octet count: %u\n", seckey->octetc);
569		}
570		print_hexdump(0, "IV", seckey->iv, __ops_block_size(seckey->alg));
571	}
572	/* no more set if encrypted */
573	if (type == OPS_PTAG_CT_ENCRYPTED_SECRET_KEY) {
574		return;
575	}
576	switch (seckey->pubkey.alg) {
577	case OPS_PKA_RSA:
578		print_bn(0, "d", seckey->key.rsa.d);
579		print_bn(0, "p", seckey->key.rsa.p);
580		print_bn(0, "q", seckey->key.rsa.q);
581		print_bn(0, "u", seckey->key.rsa.u);
582		break;
583
584	case OPS_PKA_DSA:
585		print_bn(0, "x", seckey->key.dsa.x);
586		break;
587
588	default:
589		(void) fprintf(stderr,
590			"__ops_print_seckey_verbose: unusual algorithm\n");
591	}
592	if (seckey->s2k_usage == OPS_S2KU_ENCRYPTED_AND_HASHED) {
593		print_hexdump(0, "Checkhash", seckey->checkhash,
594				OPS_CHECKHASH_SIZE);
595	} else {
596		printf("Checksum: %04x\n", seckey->checksum);
597	}
598	printf("------- end of SECRET KEY or ENCRYPTED SECRET KEY ------\n");
599}
600
601
602/**
603\ingroup Core_Print
604\param tag
605\param key
606*/
607static void
608__ops_print_pk_sesskey(__ops_content_tag_t tag,
609			 const __ops_pk_sesskey_t * key)
610{
611	print_tagname(0, (tag == OPS_PTAG_CT_PK_SESSION_KEY) ?
612		"PUBLIC KEY SESSION KEY" :
613		"ENCRYPTED PUBLIC KEY SESSION KEY");
614	printf("Version: %d\n", key->version);
615	print_hexdump(0, "Key ID", key->key_id, sizeof(key->key_id));
616	printf("Algorithm: %d (%s)\n", key->alg,
617	       __ops_show_pka(key->alg));
618	switch (key->alg) {
619	case OPS_PKA_RSA:
620		print_bn(0, "encrypted_m", key->params.rsa.encrypted_m);
621		break;
622
623	case OPS_PKA_ELGAMAL:
624		print_bn(0, "g_to_k", key->params.elgamal.g_to_k);
625		print_bn(0, "encrypted_m", key->params.elgamal.encrypted_m);
626		break;
627
628	default:
629		(void) fprintf(stderr,
630			"__ops_print_pk_sesskey: unusual algorithm\n");
631	}
632	if (tag == OPS_PTAG_CT_PK_SESSION_KEY) {
633		printf("Symmetric algorithm: %d (%s)\n", key->symm_alg,
634		       __ops_show_symm_alg(key->symm_alg));
635		print_hexdump(0, "Key", key->key, __ops_key_size(key->symm_alg));
636		printf("Checksum: %04x\n", key->checksum);
637	}
638}
639
640static void
641start_subpacket(int *indent, int type)
642{
643	*indent += 1;
644	print_indent(*indent);
645	printf("-- %s (type 0x%02x)\n",
646	       __ops_show_ss_type((__ops_ss_type_t)type),
647	       type - OPS_PTAG_SIG_SUBPKT_BASE);
648}
649
650static void
651end_subpacket(int *indent)
652{
653	*indent -= 1;
654}
655
656/**
657\ingroup Core_Print
658\param contents
659*/
660int
661__ops_print_packet(__ops_printstate_t *print, const __ops_packet_t *pkt)
662{
663	const __ops_contents_t	*content = &pkt->u;
664	__ops_text_t		*text;
665	const char		*str;
666
667	if (print->unarmoured && pkt->tag != OPS_PTAG_CT_UNARMOURED_TEXT) {
668		print->unarmoured = 0;
669		puts("UNARMOURED TEXT ends");
670	}
671	if (pkt->tag == OPS_PARSER_PTAG) {
672		printf("=> OPS_PARSER_PTAG: %s\n",
673			__ops_show_packet_tag((__ops_packet_tag_t)content->ptag.type));
674	} else {
675		printf("=> %s\n", __ops_show_packet_tag(pkt->tag));
676	}
677
678	switch (pkt->tag) {
679	case OPS_PARSER_ERROR:
680		printf("parse error: %s\n", content->error.error);
681		break;
682
683	case OPS_PARSER_ERRCODE:
684		printf("parse error: %s\n",
685		       __ops_errcode(content->errcode.errcode));
686		break;
687
688	case OPS_PARSER_PACKET_END:
689		print_packet_hex(&content->packet);
690		break;
691
692	case OPS_PARSER_PTAG:
693		if (content->ptag.type == OPS_PTAG_CT_PUBLIC_KEY) {
694			print->indent = 0;
695			printf("\n*** NEXT KEY ***\n");
696		}
697		printf("\n");
698		print_indent(print->indent);
699		printf("==== ptag new_format=%u type=%u length_type=%d"
700		       " length=0x%x (%u) position=0x%x (%u)\n",
701		       content->ptag.new_format,
702		       content->ptag.type, content->ptag.length_type,
703		       content->ptag.length, content->ptag.length,
704		       content->ptag.position, content->ptag.position);
705		print_tagname(print->indent, __ops_show_packet_tag((__ops_packet_tag_t)content->ptag.type));
706		break;
707
708	case OPS_PTAG_CT_SE_DATA_HEADER:
709		print_tagname(print->indent, "SYMMETRIC ENCRYPTED DATA");
710		break;
711
712	case OPS_PTAG_CT_SE_IP_DATA_HEADER:
713		print_tagname(print->indent,
714			"SYMMETRIC ENCRYPTED INTEGRITY PROTECTED DATA HEADER");
715		printf("Version: %d\n", content->se_ip_data_header.version);
716		break;
717
718	case OPS_PTAG_CT_SE_IP_DATA_BODY:
719		print_tagname(print->indent,
720			"SYMMETRIC ENCRYPTED INTEGRITY PROTECTED DATA BODY");
721		printf("  data body length=%u\n",
722		       content->se_data_body.length);
723		printf("    data=");
724		hexdump(stdout, content->se_data_body.data,
725			content->se_data_body.length, "");
726		printf("\n");
727		break;
728
729	case OPS_PTAG_CT_PUBLIC_KEY:
730	case OPS_PTAG_CT_PUBLIC_SUBKEY:
731		print_tagname(print->indent, (pkt->tag == OPS_PTAG_CT_PUBLIC_KEY) ?
732			"PUBLIC KEY" :
733			"PUBLIC SUBKEY");
734		__ops_print_pubkey(&content->pubkey);
735		break;
736
737	case OPS_PTAG_CT_TRUST:
738		print_tagname(print->indent, "TRUST");
739		print_data(print->indent, "Trust", &content->trust.data);
740		break;
741
742	case OPS_PTAG_CT_USER_ID:
743		print_tagname(print->indent, "USER ID");
744		print_utf8_string(print->indent, "userid", content->userid.userid);
745		break;
746
747	case OPS_PTAG_CT_SIGNATURE:
748		print_tagname(print->indent, "SIGNATURE");
749		print_indent(print->indent);
750		print_uint(print->indent, "Signature Version",
751				   (unsigned)content->sig.info.version);
752		if (content->sig.info.birthtime_set) {
753			print_time(print->indent, "Signature Creation Time",
754				   content->sig.info.birthtime);
755		}
756		if (content->sig.info.duration_set) {
757			print_uint(print->indent, "Signature Duration",
758				   (unsigned)content->sig.info.duration);
759		}
760
761		print_string_and_value(print->indent, "Signature Type",
762			    __ops_show_sig_type(content->sig.info.type),
763				       content->sig.info.type);
764
765		if (content->sig.info.signer_id_set) {
766			hexdump_data(print->indent, "Signer ID",
767					   content->sig.info.signer_id,
768				  sizeof(content->sig.info.signer_id));
769		}
770
771		print_string_and_value(print->indent, "Public Key Algorithm",
772			__ops_show_pka(content->sig.info.key_alg),
773				     content->sig.info.key_alg);
774		print_string_and_value(print->indent, "Hash Algorithm",
775			__ops_show_hash_alg((unsigned char)
776				content->sig.info.hash_alg),
777			(unsigned char)content->sig.info.hash_alg);
778		print_uint(print->indent, "Hashed data len",
779			content->sig.info.v4_hashlen);
780		print_indent(print->indent);
781		hexdump_data(print->indent, "hash2", &content->sig.hash2[0], 2);
782		switch (content->sig.info.key_alg) {
783		case OPS_PKA_RSA:
784		case OPS_PKA_RSA_SIGN_ONLY:
785			print_bn(print->indent, "sig", content->sig.info.sig.rsa.sig);
786			break;
787
788		case OPS_PKA_DSA:
789			print_bn(print->indent, "r", content->sig.info.sig.dsa.r);
790			print_bn(print->indent, "s", content->sig.info.sig.dsa.s);
791			break;
792
793		case OPS_PKA_ELGAMAL_ENCRYPT_OR_SIGN:
794			print_bn(print->indent, "r", content->sig.info.sig.elgamal.r);
795			print_bn(print->indent, "s", content->sig.info.sig.elgamal.s);
796			break;
797
798		default:
799			(void) fprintf(stderr,
800				"__ops_print_packet: Unusual algorithm\n");
801			return 0;
802		}
803
804		if (content->sig.hash)
805			printf("data hash is set\n");
806
807		break;
808
809	case OPS_PTAG_CT_COMPRESSED:
810		print_tagname(print->indent, "COMPRESSED");
811		print_uint(print->indent, "Compressed Data Type",
812			(unsigned)content->compressed.type);
813		break;
814
815	case OPS_PTAG_CT_1_PASS_SIG:
816		print_tagname(print->indent, "ONE PASS SIGNATURE");
817
818		print_uint(print->indent, "Version", (unsigned)content->one_pass_sig.version);
819		print_string_and_value(print->indent, "Signature Type",
820		    __ops_show_sig_type(content->one_pass_sig.sig_type),
821				       content->one_pass_sig.sig_type);
822		print_string_and_value(print->indent, "Hash Algorithm",
823			__ops_show_hash_alg((unsigned char)content->one_pass_sig.hash_alg),
824			(unsigned char)content->one_pass_sig.hash_alg);
825		print_string_and_value(print->indent, "Public Key Algorithm",
826			__ops_show_pka(content->one_pass_sig.key_alg),
827			content->one_pass_sig.key_alg);
828		hexdump_data(print->indent, "Signer ID",
829				   content->one_pass_sig.keyid,
830				   sizeof(content->one_pass_sig.keyid));
831		print_uint(print->indent, "Nested", content->one_pass_sig.nested);
832		break;
833
834	case OPS_PTAG_CT_USER_ATTR:
835		print_tagname(print->indent, "USER ATTRIBUTE");
836		print_hexdump(print->indent, "User Attribute",
837			      content->userattr.data.contents,
838			      content->userattr.data.len);
839		break;
840
841	case OPS_PTAG_RAW_SS:
842		if (pkt->critical) {
843			(void) fprintf(stderr, "contents are critical\n");
844			return 0;
845		}
846		start_subpacket(&print->indent, pkt->tag);
847		print_uint(print->indent, "Raw Signature Subpacket: tag",
848			(unsigned)(content->ss_raw.tag -
849		   	(unsigned)OPS_PTAG_SIG_SUBPKT_BASE));
850		print_hexdump(print->indent, "Raw Data",
851			      content->ss_raw.raw,
852			      content->ss_raw.length);
853		break;
854
855	case OPS_PTAG_SS_CREATION_TIME:
856		start_subpacket(&print->indent, pkt->tag);
857		print_time(print->indent, "Signature Creation Time", content->ss_time.time);
858		end_subpacket(&print->indent);
859		break;
860
861	case OPS_PTAG_SS_EXPIRATION_TIME:
862		start_subpacket(&print->indent, pkt->tag);
863		print_duration(print->indent, "Signature Expiration Time",
864			content->ss_time.time);
865		end_subpacket(&print->indent);
866		break;
867
868	case OPS_PTAG_SS_KEY_EXPIRY:
869		start_subpacket(&print->indent, pkt->tag);
870		print_duration(print->indent, "Key Expiration Time", content->ss_time.time);
871		end_subpacket(&print->indent);
872		break;
873
874	case OPS_PTAG_SS_TRUST:
875		start_subpacket(&print->indent, pkt->tag);
876		print_string(print->indent, "Trust Signature", "");
877		print_uint(print->indent, "Level", (unsigned)content->ss_trust.level);
878		print_uint(print->indent, "Amount", (unsigned)content->ss_trust.amount);
879		end_subpacket(&print->indent);
880		break;
881
882	case OPS_PTAG_SS_REVOCABLE:
883		start_subpacket(&print->indent, pkt->tag);
884		print_boolean(print->indent, "Revocable", content->ss_revocable.revocable);
885		end_subpacket(&print->indent);
886		break;
887
888	case OPS_PTAG_SS_REVOCATION_KEY:
889		start_subpacket(&print->indent, pkt->tag);
890		/* not yet tested */
891		printf("  revocation key: class=0x%x",
892		       content->ss_revocation_key.class);
893		if (content->ss_revocation_key.class & 0x40) {
894			printf(" (sensitive)");
895		}
896		printf(", algid=0x%x", content->ss_revocation_key.algid);
897		printf(", fingerprint=");
898		hexdump(stdout, content->ss_revocation_key.fingerprint,
899				OPS_FINGERPRINT_SIZE, "");
900		printf("\n");
901		end_subpacket(&print->indent);
902		break;
903
904	case OPS_PTAG_SS_ISSUER_KEY_ID:
905		start_subpacket(&print->indent, pkt->tag);
906		print_hexdump(print->indent, "Issuer Key Id",
907			      &content->ss_issuer.key_id[0],
908			      sizeof(content->ss_issuer.key_id));
909		end_subpacket(&print->indent);
910		break;
911
912	case OPS_PTAG_SS_PREFERRED_SKA:
913		start_subpacket(&print->indent, pkt->tag);
914		print_data(print->indent, "Preferred Symmetric Algorithms",
915			   &content->ss_skapref.data);
916
917		text = __ops_showall_ss_skapref(content->ss_skapref);
918		print_text_breakdown(print->indent, text);
919		__ops_text_free(text);
920
921		end_subpacket(&print->indent);
922		break;
923
924	case OPS_PTAG_SS_PRIMARY_USER_ID:
925		start_subpacket(&print->indent, pkt->tag);
926		print_boolean(print->indent, "Primary User ID",
927			      content->ss_primary_userid.primary_userid);
928		end_subpacket(&print->indent);
929		break;
930
931	case OPS_PTAG_SS_PREFERRED_HASH:
932		start_subpacket(&print->indent, pkt->tag);
933		print_data(print->indent, "Preferred Hash Algorithms",
934			   &content->ss_hashpref.data);
935
936		text = __ops_showall_ss_hashpref(content->ss_hashpref);
937		print_text_breakdown(print->indent, text);
938		__ops_text_free(text);
939		end_subpacket(&print->indent);
940		break;
941
942	case OPS_PTAG_SS_PREF_COMPRESS:
943		start_subpacket(&print->indent, pkt->tag);
944		print_data(print->indent, "Preferred Compression Algorithms",
945			   &content->ss_zpref.data);
946
947		text = __ops_showall_ss_zpref(content->ss_zpref);
948		print_text_breakdown(print->indent, text);
949		__ops_text_free(text);
950		end_subpacket(&print->indent);
951		break;
952
953	case OPS_PTAG_SS_KEY_FLAGS:
954		start_subpacket(&print->indent, pkt->tag);
955		print_data(print->indent, "Key Flags", &content->ss_key_flags.data);
956
957		text = __ops_showall_ss_key_flags(content->ss_key_flags);
958		print_text_breakdown(print->indent, text);
959		__ops_text_free(text);
960
961		end_subpacket(&print->indent);
962		break;
963
964	case OPS_PTAG_SS_KEYSERV_PREFS:
965		start_subpacket(&print->indent, pkt->tag);
966		print_data(print->indent, "Key Server Preferences",
967			   &content->ss_key_server_prefs.data);
968
969		text = __ops_show_keyserv_prefs(content->ss_key_server_prefs);
970		print_text_breakdown(print->indent, text);
971		__ops_text_free(text);
972
973		end_subpacket(&print->indent);
974		break;
975
976	case OPS_PTAG_SS_FEATURES:
977		start_subpacket(&print->indent, pkt->tag);
978		print_data(print->indent, "Features",
979			   &content->ss_features.data);
980
981		text = __ops_showall_ss_features(content->ss_features);
982		print_text_breakdown(print->indent, text);
983		__ops_text_free(text);
984
985		end_subpacket(&print->indent);
986		break;
987
988	case OPS_PTAG_SS_NOTATION_DATA:
989		start_subpacket(&print->indent, pkt->tag);
990		print_indent(print->indent);
991		printf("Notation Data:\n");
992
993		print->indent++;
994		print_data(print->indent, "Flags", &content->ss_notation.flags);
995		text = __ops_showall_notation(content->ss_notation);
996		print_text_breakdown(print->indent, text);
997		__ops_text_free(text);
998
999		print_data(print->indent, "Name", &content->ss_notation.name);
1000
1001		print_data(print->indent, "Value", &content->ss_notation.value);
1002
1003		print->indent--;
1004		end_subpacket(&print->indent);
1005		break;
1006
1007	case OPS_PTAG_SS_REGEXP:
1008		start_subpacket(&print->indent, pkt->tag);
1009		print_hexdump(print->indent, "Regular Expression",
1010			      (unsigned char *) content->ss_regexp.regexp,
1011			      strlen(content->ss_regexp.regexp));
1012		print_string(print->indent, NULL, content->ss_regexp.regexp);
1013		end_subpacket(&print->indent);
1014		break;
1015
1016	case OPS_PTAG_SS_POLICY_URI:
1017		start_subpacket(&print->indent, pkt->tag);
1018		print_string(print->indent, "Policy URL", content->ss_policy.url);
1019		end_subpacket(&print->indent);
1020		break;
1021
1022	case OPS_PTAG_SS_SIGNERS_USER_ID:
1023		start_subpacket(&print->indent, pkt->tag);
1024		print_utf8_string(print->indent, "Signer's User ID",
1025			content->ss_signer.userid);
1026		end_subpacket(&print->indent);
1027		break;
1028
1029	case OPS_PTAG_SS_PREF_KEYSERV:
1030		start_subpacket(&print->indent, pkt->tag);
1031		print_string(print->indent, "Preferred Key Server", content->ss_keyserv.name);
1032		end_subpacket(&print->indent);
1033		break;
1034
1035	case OPS_PTAG_SS_EMBEDDED_SIGNATURE:
1036		start_subpacket(&print->indent, pkt->tag);
1037		end_subpacket(&print->indent);/* \todo print out contents? */
1038		break;
1039
1040	case OPS_PTAG_SS_USERDEFINED00:
1041	case OPS_PTAG_SS_USERDEFINED01:
1042	case OPS_PTAG_SS_USERDEFINED02:
1043	case OPS_PTAG_SS_USERDEFINED03:
1044	case OPS_PTAG_SS_USERDEFINED04:
1045	case OPS_PTAG_SS_USERDEFINED05:
1046	case OPS_PTAG_SS_USERDEFINED06:
1047	case OPS_PTAG_SS_USERDEFINED07:
1048	case OPS_PTAG_SS_USERDEFINED08:
1049	case OPS_PTAG_SS_USERDEFINED09:
1050	case OPS_PTAG_SS_USERDEFINED10:
1051		start_subpacket(&print->indent, pkt->tag);
1052		print_hexdump(print->indent, "Internal or user-defined",
1053			      content->ss_userdef.data.contents,
1054			      content->ss_userdef.data.len);
1055		end_subpacket(&print->indent);
1056		break;
1057
1058	case OPS_PTAG_SS_RESERVED:
1059		start_subpacket(&print->indent, pkt->tag);
1060		print_hexdump(print->indent, "Reserved",
1061			      content->ss_userdef.data.contents,
1062			      content->ss_userdef.data.len);
1063		end_subpacket(&print->indent);
1064		break;
1065
1066	case OPS_PTAG_SS_REVOCATION_REASON:
1067		start_subpacket(&print->indent, pkt->tag);
1068		print_hexdump(print->indent, "Revocation Reason",
1069			      &content->ss_revocation.code,
1070			      1);
1071		str = __ops_show_ss_rr_code(content->ss_revocation.code);
1072		print_string(print->indent, NULL, str);
1073		end_subpacket(&print->indent);
1074		break;
1075
1076	case OPS_PTAG_CT_LITDATA_HEADER:
1077		print_tagname(print->indent, "LITERAL DATA HEADER");
1078		printf("  literal data header format=%c filename='%s'\n",
1079		       content->litdata_header.format,
1080		       content->litdata_header.filename);
1081		showtime("    modification time",
1082			 content->litdata_header.mtime);
1083		printf("\n");
1084		break;
1085
1086	case OPS_PTAG_CT_LITDATA_BODY:
1087		print_tagname(print->indent, "LITERAL DATA BODY");
1088		printf("  literal data body length=%u\n",
1089		       content->litdata_body.length);
1090		printf("    data=");
1091		print_escaped(content->litdata_body.data,
1092			      content->litdata_body.length);
1093		printf("\n");
1094		break;
1095
1096	case OPS_PTAG_CT_SIGNATURE_HEADER:
1097		print_tagname(print->indent, "SIGNATURE");
1098		print_indent(print->indent);
1099		print_uint(print->indent, "Signature Version",
1100				   (unsigned)content->sig.info.version);
1101		if (content->sig.info.birthtime_set) {
1102			print_time(print->indent, "Signature Creation Time",
1103				content->sig.info.birthtime);
1104		}
1105		if (content->sig.info.duration_set) {
1106			print_uint(print->indent, "Signature Duration",
1107				   (unsigned)content->sig.info.duration);
1108		}
1109		print_string_and_value(print->indent, "Signature Type",
1110			    __ops_show_sig_type(content->sig.info.type),
1111				       content->sig.info.type);
1112		if (content->sig.info.signer_id_set) {
1113			hexdump_data(print->indent, "Signer ID",
1114				content->sig.info.signer_id,
1115				sizeof(content->sig.info.signer_id));
1116		}
1117		print_string_and_value(print->indent, "Public Key Algorithm",
1118			__ops_show_pka(content->sig.info.key_alg),
1119				     content->sig.info.key_alg);
1120		print_string_and_value(print->indent, "Hash Algorithm",
1121			__ops_show_hash_alg((unsigned char)content->sig.info.hash_alg),
1122			(unsigned char)content->sig.info.hash_alg);
1123		print_uint(print->indent, "Hashed data len",
1124			content->sig.info.v4_hashlen);
1125
1126		break;
1127
1128	case OPS_PTAG_CT_SIGNATURE_FOOTER:
1129		print_indent(print->indent);
1130		hexdump_data(print->indent, "hash2", &content->sig.hash2[0], 2);
1131
1132		switch (content->sig.info.key_alg) {
1133		case OPS_PKA_RSA:
1134			print_bn(print->indent, "sig", content->sig.info.sig.rsa.sig);
1135			break;
1136
1137		case OPS_PKA_DSA:
1138			print_bn(print->indent, "r", content->sig.info.sig.dsa.r);
1139			print_bn(print->indent, "s", content->sig.info.sig.dsa.s);
1140			break;
1141
1142		case OPS_PKA_ELGAMAL_ENCRYPT_OR_SIGN:
1143			print_bn(print->indent, "r", content->sig.info.sig.elgamal.r);
1144			print_bn(print->indent, "s", content->sig.info.sig.elgamal.s);
1145			break;
1146
1147		case OPS_PKA_PRIVATE00:
1148		case OPS_PKA_PRIVATE01:
1149		case OPS_PKA_PRIVATE02:
1150		case OPS_PKA_PRIVATE03:
1151		case OPS_PKA_PRIVATE04:
1152		case OPS_PKA_PRIVATE05:
1153		case OPS_PKA_PRIVATE06:
1154		case OPS_PKA_PRIVATE07:
1155		case OPS_PKA_PRIVATE08:
1156		case OPS_PKA_PRIVATE09:
1157		case OPS_PKA_PRIVATE10:
1158			print_data(print->indent, "Private/Experimental",
1159			   &content->sig.info.sig.unknown.data);
1160			break;
1161
1162		default:
1163			(void) fprintf(stderr,
1164				"__ops_print_packet: Unusual key algorithm\n");
1165			return 0;
1166		}
1167		break;
1168
1169	case OPS_GET_PASSPHRASE:
1170		print_tagname(print->indent, "OPS_GET_PASSPHRASE");
1171		break;
1172
1173	case OPS_PTAG_CT_SECRET_KEY:
1174		print_tagname(print->indent, "OPS_PTAG_CT_SECRET_KEY");
1175		__ops_print_seckey_verbose(pkt->tag, &content->seckey);
1176		break;
1177
1178	case OPS_PTAG_CT_ENCRYPTED_SECRET_KEY:
1179		print_tagname(print->indent, "OPS_PTAG_CT_ENCRYPTED_SECRET_KEY");
1180		__ops_print_seckey_verbose(pkt->tag, &content->seckey);
1181		break;
1182
1183	case OPS_PTAG_CT_ARMOUR_HEADER:
1184		print_tagname(print->indent, "ARMOUR HEADER");
1185		print_string(print->indent, "type", content->armour_header.type);
1186		break;
1187
1188	case OPS_PTAG_CT_SIGNED_CLEARTEXT_HEADER:
1189		print_tagname(print->indent, "SIGNED CLEARTEXT HEADER");
1190		print_headers(&content->cleartext_head.headers);
1191		break;
1192
1193	case OPS_PTAG_CT_SIGNED_CLEARTEXT_BODY:
1194		print_tagname(print->indent, "SIGNED CLEARTEXT BODY");
1195		print_block(print->indent, "signed cleartext", content->cleartext_body.data,
1196			    content->cleartext_body.length);
1197		break;
1198
1199	case OPS_PTAG_CT_SIGNED_CLEARTEXT_TRAILER:
1200		print_tagname(print->indent, "SIGNED CLEARTEXT TRAILER");
1201		printf("hash algorithm: %d\n",
1202		       content->cleartext_trailer.hash->alg);
1203		printf("\n");
1204		break;
1205
1206	case OPS_PTAG_CT_UNARMOURED_TEXT:
1207		if (!print->unarmoured) {
1208			print_tagname(print->indent, "UNARMOURED TEXT");
1209			print->unarmoured = 1;
1210		}
1211		putchar('[');
1212		print_escaped(content->unarmoured_text.data,
1213			      content->unarmoured_text.length);
1214		putchar(']');
1215		break;
1216
1217	case OPS_PTAG_CT_ARMOUR_TRAILER:
1218		print_tagname(print->indent, "ARMOUR TRAILER");
1219		print_string(print->indent, "type", content->armour_header.type);
1220		break;
1221
1222	case OPS_PTAG_CT_PK_SESSION_KEY:
1223	case OPS_PTAG_CT_ENCRYPTED_PK_SESSION_KEY:
1224		__ops_print_pk_sesskey(pkt->tag, &content->pk_sesskey);
1225		break;
1226
1227	case OPS_GET_SECKEY:
1228		__ops_print_pk_sesskey(OPS_PTAG_CT_ENCRYPTED_PK_SESSION_KEY,
1229				    content->get_seckey.pk_sesskey);
1230		break;
1231
1232	default:
1233		print_tagname(print->indent, "UNKNOWN PACKET TYPE");
1234		fprintf(stderr, "__ops_print_packet: unknown tag=%d (0x%x)\n",
1235			pkt->tag, pkt->tag);
1236		exit(EXIT_FAILURE);
1237	}
1238	return 1;
1239}
1240
1241static __ops_cb_ret_t
1242cb_list_packets(const __ops_packet_t *pkt, __ops_cbdata_t *cbinfo)
1243{
1244	__ops_print_packet(&cbinfo->printstate, pkt);
1245	return OPS_RELEASE_MEMORY;
1246}
1247
1248/**
1249\ingroup Core_Print
1250\param filename
1251\param armour
1252\param keyring
1253\param cb_get_passphrase
1254*/
1255int
1256__ops_list_packets(__ops_io_t *io,
1257			char *filename,
1258			unsigned armour,
1259			__ops_keyring_t *secring,
1260			__ops_keyring_t *pubring,
1261			void *passfp,
1262			__ops_cbfunc_t *cb_get_passphrase)
1263{
1264	__ops_stream_t	*stream = NULL;
1265	const unsigned	 accumulate = 1;
1266	const int	 printerrors = 1;
1267	int		 fd;
1268
1269	fd = __ops_setup_file_read(io, &stream, filename, NULL, cb_list_packets,
1270				accumulate);
1271	__ops_parse_options(stream, OPS_PTAG_SS_ALL, OPS_PARSE_PARSED);
1272	stream->cryptinfo.secring = secring;
1273	stream->cryptinfo.pubring = pubring;
1274	stream->cbinfo.passfp = passfp;
1275	stream->cryptinfo.getpassphrase = cb_get_passphrase;
1276	if (armour) {
1277		__ops_reader_push_dearmour(stream);
1278	}
1279	__ops_parse(stream, printerrors);
1280	__ops_teardown_file_read(stream, fd);
1281	return 1;
1282}
1283