1/*-
2 * Copyright (c) 2012 Alistair Crooks <agc@NetBSD.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25#include <sys/types.h>
26#include <sys/stat.h>
27#include <sys/param.h>
28#include <sys/mman.h>
29
30#include <bzlib.h>
31#include <err.h>
32#include <inttypes.h>
33#include <stdarg.h>
34#include <stdio.h>
35#include <stdlib.h>
36#include <string.h>
37#include <time.h>
38#include <unistd.h>
39#include <zlib.h>
40
41#include "array.h"
42#include "bn.h"
43#include "b64.h"
44#include "digest.h"
45#include "pgpsum.h"
46#include "rsa.h"
47#include "verify.h"
48
49#ifndef USE_ARG
50#define USE_ARG(x)	/*LINTED*/(void)&(x)
51#endif
52
53#ifndef __printflike
54#define __printflike(n, m)		__attribute__((format(printf,n,m)))
55#endif
56
57#define BITS_TO_BYTES(b)		(((b) + (CHAR_BIT - 1)) / CHAR_BIT)
58
59/* packet types */
60#define SIGNATURE_PKT			2
61#define ONEPASS_SIGNATURE_PKT		4
62#define PUBKEY_PKT			6
63#define COMPRESSED_DATA_PKT		8
64#define MARKER_PKT			10
65#define LITDATA_PKT			11
66#define TRUST_PKT			12
67#define USERID_PKT			13
68#define PUB_SUBKEY_PKT			14
69#define USER_ATTRIBUTE_PKT		17
70
71/* only allow certain packets at certain times */
72#define PUBRING_ALLOWED			"\002\006\014\015\016\021"
73#define SIGNATURE_ALLOWED		"\002\004\010\013"
74
75/* actions to do on close */
76#define FREE_MEM			0x01
77#define UNMAP_MEM			0x02
78
79/* types of pubkey we encounter */
80#define PUBKEY_RSA_ENCRYPT_OR_SIGN	1
81#define PUBKEY_RSA_ENCRYPT		2
82#define PUBKEY_RSA_SIGN			3
83#define PUBKEY_ELGAMAL_ENCRYPT		16
84#define PUBKEY_DSA			17
85#define PUBKEY_ELLIPTIC_CURVE		18
86#define PUBKEY_ECDSA			19
87#define PUBKEY_ELGAMAL_ENCRYPT_OR_SIGN	20
88
89/* hash algorithm definitions */
90#define PGPV_HASH_MD5			1
91#define PGPV_HASH_SHA1			2
92#define PGPV_HASH_RIPEMD		3
93#define PGPV_HASH_SHA256		8
94#define PGPV_HASH_SHA384		9
95#define PGPV_HASH_SHA512		10
96
97/* pubkey defs for bignums */
98#define RSA_N				0
99#define RSA_E				1
100#define DSA_P				0
101#define DSA_Q				1
102#define DSA_G				2
103#define DSA_Y				3
104#define ELGAMAL_P			0
105#define ELGAMAL_G			1
106#define ELGAMAL_Y			2
107
108/* sesskey indices */
109#define RSA_SESSKEY_ENCRYPTED_M		0
110#define RSA_SESSKEY_M			1
111#define ELGAMAL_SESSKEY_G_TO_K		0
112#define ELGAMAL_SESSKEY_ENCRYPTED_M	1
113
114/* seckey indices */
115#define RSA_SECKEY_D			0
116#define RSA_SECKEY_P			1
117#define RSA_SECKEY_Q			2
118#define RSA_SECKEY_U			3
119#define DSA_SECKEY_X			0
120#define ELGAMAL_SECKEY_X		0
121
122/* signature mpi indices in bignumber array */
123#define RSA_SIG				0
124#define DSA_R				0
125#define DSA_S				1
126#define ELGAMAL_SIG_R			0
127#define ELGAMAL_SIG_S			1
128
129/* signature types */
130#define SIGTYPE_BINARY_DOC		0x00	/* Signature of a binary document */
131#define SIGTYPE_TEXT			0x01	/* Signature of a canonical text document */
132#define SIGTYPE_STANDALONE		0x02	/* Standalone signature */
133
134#define SIGTYPE_GENERIC_USERID		0x10	/* Generic certification of a User ID and Public Key packet */
135#define SIGTYPE_PERSONA_USERID		0x11	/* Persona certification of a User ID and Public Key packet */
136#define SIGTYPE_CASUAL_USERID		0x12	/* Casual certification of a User ID and Public Key packet */
137#define SIGTYPE_POSITIVE_USERID		0x13	/* Positive certification of a User ID and Public Key packet */
138
139#define SIGTYPE_SUBKEY_BINDING		0x18	/* Subkey Binding Signature */
140#define SIGTYPE_PRIMARY_KEY_BINDING	0x19	/* Primary Key Binding Signature */
141#define SIGTYPE_DIRECT_KEY		0x1f	/* Signature directly on a key */
142
143#define SIGTYPE_KEY_REVOCATION		0x20	/* Key revocation signature */
144#define SIGTYPE_SUBKEY_REVOCATION	0x28	/* Subkey revocation signature */
145#define SIGTYPE_CERT_REVOCATION		0x30	/* Certification revocation signature */
146
147#define SIGTYPE_TIMESTAMP_SIG		0x40	/* Timestamp signature */
148#define SIGTYPE_3RDPARTY		0x50	/* Third-Party Confirmation signature */
149
150/* Forward declarations */
151static int read_all_packets(pgpv_t */*pgp*/, pgpv_mem_t */*mem*/, const char */*op*/);
152static int read_binary_file(pgpv_t */*pgp*/, const char */*op*/, const char */*fmt*/, ...)
153    __printflike(3, 4);
154static int read_binary_memory(pgpv_t */*pgp*/, const char */*op*/, const void */*memory*/, size_t /*size*/);
155static int pgpv_find_keyid(pgpv_t */*pgp*/, const char */*strkeyid*/, uint8_t */*keyid*/);
156
157/* read a file into the pgpv_mem_t struct */
158static int
159read_file(pgpv_t *pgp, const char *f)
160{
161	struct stat	 st;
162	pgpv_mem_t	*mem;
163
164	ARRAY_EXPAND(pgp->areas);
165	ARRAY_COUNT(pgp->areas) += 1;
166	mem = &ARRAY_LAST(pgp->areas);
167	memset(mem, 0x0, sizeof(*mem));
168	if ((mem->fp = fopen(f, "r")) == NULL) {
169		warn("can't read '%s'", f);
170		return 0;
171	}
172	fstat(fileno(mem->fp), &st);
173	mem->size = (size_t)st.st_size;
174	mem->mem = mmap(NULL, mem->size, PROT_READ, MAP_SHARED, fileno(mem->fp), 0);
175	mem->dealloc = UNMAP_MEM;
176	return 1;
177}
178
179/* DTRT and free resources */
180static int
181closemem(pgpv_mem_t *mem)
182{
183	switch(mem->dealloc) {
184	case FREE_MEM:
185		free(mem->mem);
186		mem->size = 0;
187		break;
188	case UNMAP_MEM:
189		munmap(mem->mem, mem->size);
190		fclose(mem->fp);
191		break;
192	}
193	return 1;
194}
195
196/* make a reference to a memory area, and its offset */
197static void
198make_ref(pgpv_t *pgp, uint8_t mement, pgpv_ref_t *ref)
199{
200	ref->mem = mement;
201	ref->offset = ARRAY_ELEMENT(pgp->areas, ref->mem).cc;
202	ref->vp = pgp;
203}
204
205/* return the pointer we wanted originally */
206static uint8_t *
207get_ref(pgpv_ref_t *ref)
208{
209	pgpv_mem_t	*mem;
210	pgpv_t		*pgp = (pgpv_t *)ref->vp;
211
212	mem = &ARRAY_ELEMENT(pgp->areas, ref->mem);
213	return &mem->mem[ref->offset];
214}
215
216#define IS_PARTIAL(x)		((x) >= 224 && (x) < 255)
217#define DECODE_PARTIAL(x)	(1 << ((x) & 0x1f))
218
219#define PKT_LENGTH(m, off)						\
220	((m[off] < 192) ? (m[off]) : 					\
221	 (m[off] < 224) ? ((m[off] - 192) << 8) + (m[off + 1]) + 192 :	\
222	 (m[off + 1] << 24) | ((m[off + 2]) << 16) | ((m[off + 3]) << 8)  | (m[off + 4]))
223
224#define PKT_LENGTH_LENGTH(m, off)					\
225	((m[off] < 192) ? 1 : (m[off] < 224) ? 2 : 5)
226
227/* fix up partial body lengths, return new size */
228static size_t
229fixup_partials(pgpv_t *pgp, uint8_t *p, size_t totlen, size_t filesize, size_t *cc)
230{
231	pgpv_mem_t	*mem;
232	size_t		 partial;
233	size_t		 newcc;
234
235	if (totlen > filesize) {
236		printf("fixup_partial: filesize %zu is less than encoded size %zu\n", filesize, totlen);
237		return 0;
238	}
239	ARRAY_EXPAND(pgp->areas);
240	ARRAY_COUNT(pgp->areas) += 1;
241	mem = &ARRAY_LAST(pgp->areas);
242	mem->size = totlen;
243	if ((mem->mem = calloc(1, mem->size + 5)) == NULL) {
244		printf("fixup_partial: can't allocate %zu length\n", totlen);
245		return 0;
246	}
247	newcc = 0;
248	mem->dealloc = FREE_MEM;
249	for (*cc = 0 ; *cc < totlen ; newcc += partial, *cc += partial + 1) {
250		if (IS_PARTIAL(p[*cc])) {
251			partial = DECODE_PARTIAL(p[*cc]);
252			memcpy(&mem->mem[newcc], &p[*cc + 1], partial);
253		} else {
254			partial = PKT_LENGTH(p, *cc);
255			*cc += PKT_LENGTH_LENGTH(p, *cc);
256			memcpy(&mem->mem[newcc], &p[*cc], partial);
257			newcc += partial;
258			*cc += partial;
259			break;
260		}
261	}
262	return newcc;
263}
264
265/* get the weirdo packet length */
266static size_t
267get_pkt_len(uint8_t newfmt, uint8_t *p, size_t filesize, int isprimary)
268{
269	size_t	lenbytes;
270	size_t	len;
271
272	if (newfmt) {
273		if (IS_PARTIAL(*p)) {
274			if (!isprimary) {
275				/* for sub-packets, only 1, 2 or 4 byte sizes allowed */
276				return ((*p - 192) << 8) + *(p + 1) + 192;
277			}
278			lenbytes = 1;
279			for (len = DECODE_PARTIAL(*p) ; IS_PARTIAL(p[len + lenbytes]) ; lenbytes++) {
280				len += DECODE_PARTIAL(p[len + lenbytes]);
281			}
282			len += get_pkt_len(newfmt, &p[len + lenbytes], filesize, 1);
283			return len;
284		}
285		return PKT_LENGTH(p, 0);
286	} else {
287		switch(*--p & 0x3) {
288		case 0:
289			return *(p + 1);
290		case 1:
291			return (*(p + 1) << 8) | *(p + 2);
292		case 2:
293			return (*(p + 1) << 24) | (*(p + 2) << 16) | (*(p + 3) << 8)  | *(p + 4);
294		default:
295			return filesize;
296		}
297	}
298}
299
300/* get the length of the packet length field */
301static unsigned
302get_pkt_len_len(uint8_t newfmt, uint8_t *p, int isprimary)
303{
304	if (newfmt) {
305		if (IS_PARTIAL(*p)) {
306			return (isprimary) ? 1 : 2;
307		}
308		return PKT_LENGTH_LENGTH(p, 0);
309	} else {
310		switch(*--p & 0x3) {
311		case 0:
312			return 1;
313		case 1:
314			return 2;
315		case 2:
316			return 4;
317		default:
318			return 0;
319		}
320	}
321}
322
323/* copy the 32bit integer in memory in network order */
324static unsigned
325fmt_32(uint8_t *p, uint32_t a)
326{
327	a = htonl(a);
328	memcpy(p, &a, sizeof(a));
329	return sizeof(a);
330}
331
332/* copy the 16bit integer in memory in network order */
333static unsigned
334fmt_16(uint8_t *p, uint16_t a)
335{
336	a = htons(a);
337	memcpy(p, &a, sizeof(a));
338	return sizeof(a);
339}
340
341/* format a binary string in memory */
342static size_t
343fmt_binary(char *s, size_t size, const uint8_t *bin, unsigned len)
344{
345	unsigned	i;
346	size_t		cc;
347
348	for (cc = 0, i = 0 ; i < len && cc < size ; i++) {
349		cc += snprintf(&s[cc], size - cc, "%02x", bin[i]);
350	}
351	return cc;
352}
353
354/* format an mpi into memory */
355static unsigned
356fmt_binary_mpi(pgpv_bignum_t *mpi, uint8_t *p, size_t size)
357{
358	unsigned	 bytes;
359	BIGNUM		*bn;
360
361	bytes = BITS_TO_BYTES(mpi->bits);
362	if ((size_t)bytes + 2 + 1 > size) {
363		warn("truncated mpi");
364		return 0;
365	}
366	bn = (BIGNUM *)mpi->bn;
367	if (bn == NULL || BN_is_zero(bn)) {
368		fmt_32(p, 0);
369		return 2 + 1;
370	}
371	fmt_16(p, mpi->bits);
372	BN_bn2bin(bn, &p[2]);
373	return bytes + 2;
374}
375
376/* dump an mpi value onto stdout */
377static size_t
378fmt_mpi(char *s, size_t size, pgpv_bignum_t *bn, const char *name, int pbits)
379{
380	size_t	 cc;
381	char	*buf;
382
383	cc = snprintf(s, size, "%s=", name);
384	if (pbits) {
385		cc += snprintf(&s[cc], size - cc, "[%u bits] ", bn->bits);
386	}
387	buf = BN_bn2hex(bn->bn);
388	cc += snprintf(&s[cc], size - cc, "%s\n", buf);
389	free(buf);
390	return cc;
391}
392
393#define ALG_IS_RSA(alg)	(((alg) == PUBKEY_RSA_ENCRYPT_OR_SIGN) ||	\
394			 ((alg) == PUBKEY_RSA_ENCRYPT) ||		\
395			 ((alg) == PUBKEY_RSA_SIGN))
396
397#define ALG_IS_DSA(alg)	((alg) == PUBKEY_DSA)
398
399/* format key mpis into memory */
400static unsigned
401fmt_key_mpis(pgpv_pubkey_t *pubkey, uint8_t *buf, size_t size)
402{
403	size_t	cc;
404
405	cc = 0;
406	buf[cc++] = pubkey->version;
407	cc += fmt_32(&buf[cc], (uint32_t)pubkey->birth);
408	buf[cc++] = pubkey->keyalg;
409	switch(pubkey->keyalg) {
410	case PUBKEY_RSA_ENCRYPT_OR_SIGN:
411	case PUBKEY_RSA_ENCRYPT:
412	case PUBKEY_RSA_SIGN:
413		cc += fmt_binary_mpi(&pubkey->bn[RSA_N], &buf[cc], size - cc);
414		cc += fmt_binary_mpi(&pubkey->bn[RSA_E], &buf[cc], size - cc);
415		break;
416	case PUBKEY_DSA:
417		cc += fmt_binary_mpi(&pubkey->bn[DSA_P], &buf[cc], size - cc);
418		cc += fmt_binary_mpi(&pubkey->bn[DSA_Q], &buf[cc], size - cc);
419		cc += fmt_binary_mpi(&pubkey->bn[DSA_G], &buf[cc], size - cc);
420		cc += fmt_binary_mpi(&pubkey->bn[DSA_Y], &buf[cc], size - cc);
421		break;
422	default:
423		cc += fmt_binary_mpi(&pubkey->bn[ELGAMAL_P], &buf[cc], size - cc);
424		cc += fmt_binary_mpi(&pubkey->bn[ELGAMAL_G], &buf[cc], size - cc);
425		cc += fmt_binary_mpi(&pubkey->bn[ELGAMAL_Y], &buf[cc], size - cc);
426		break;
427	}
428	return (unsigned)cc;
429}
430
431/* calculate the fingerprint, RFC 4880, section 12.2 */
432static int
433pgpv_calc_fingerprint(pgpv_fingerprint_t *fingerprint, pgpv_pubkey_t *pubkey)
434{
435	digest_t	 fphash;
436	uint16_t	 cc;
437	uint8_t		 ch = 0x99;
438	uint8_t		 buf[8192 + 2 + 1];
439	uint8_t		 len[2];
440
441	memset(&fphash, 0x0, sizeof(fphash));
442	if (pubkey->version == 4) {
443		/* v4 keys */
444		fingerprint->hashalg = digest_get_alg("sha1");
445		digest_init(&fphash, (unsigned)fingerprint->hashalg);
446		cc = fmt_key_mpis(pubkey, buf, sizeof(buf));
447		digest_update(&fphash, &ch, 1);
448		fmt_16(len, cc);
449		digest_update(&fphash, len, 2);
450		digest_update(&fphash, buf, cc);
451		fingerprint->len = digest_final(fingerprint->v, &fphash);
452		return 1;
453	}
454	if (ALG_IS_RSA(pubkey->keyalg)) {
455		/* v3 keys are RSA */
456		fingerprint->hashalg = digest_get_alg("md5");
457		digest_init(&fphash, (unsigned)fingerprint->hashalg);
458		if (pubkey->bn[RSA_N].bn && pubkey->bn[RSA_E].bn) {
459			cc = fmt_binary_mpi(&pubkey->bn[RSA_N], buf, sizeof(buf));
460			digest_update(&fphash, &buf[2], cc - 2);
461			cc = fmt_binary_mpi(&pubkey->bn[RSA_E], buf, sizeof(buf));
462			digest_update(&fphash, &buf[2], cc - 2);
463			fingerprint->len = digest_final(fingerprint->v, &fphash);
464			return 1;
465		}
466	}
467	if (pubkey->bn[RSA_N].bn) {
468		if ((cc = fmt_binary_mpi(&pubkey->bn[RSA_N], buf, sizeof(buf))) >= PGPV_KEYID_LEN) {
469			memcpy(fingerprint->v, &buf[cc - PGPV_KEYID_LEN], PGPV_KEYID_LEN);
470			fingerprint->len = PGPV_KEYID_LEN;
471			return 1;
472		}
473	}
474	/* exhausted all avenues, really */
475	memset(fingerprint->v, 0xff, fingerprint->len = PGPV_KEYID_LEN);
476	return 1;
477}
478
479/* format a fingerprint into memory */
480static size_t
481fmt_fingerprint(char *s, size_t size, pgpv_fingerprint_t *fingerprint, const char *name)
482{
483	unsigned	i;
484	size_t		cc;
485
486	cc = snprintf(s, size, "%s ", name);
487	for (i = 0 ; i < fingerprint->len ; i++) {
488		cc += snprintf(&s[cc], size - cc, "%02hhx%s",
489			fingerprint->v[i], (i % 2 == 1) ? " " : "");
490	}
491	cc += snprintf(&s[cc], size - cc, "\n");
492	return cc;
493}
494
495/* calculate keyid from a pubkey */
496static int
497pgpv_calc_keyid(pgpv_pubkey_t *key)
498{
499	pgpv_calc_fingerprint(&key->fingerprint, key);
500	memcpy(key->keyid, &key->fingerprint.v[key->fingerprint.len - PGPV_KEYID_LEN], PGPV_KEYID_LEN);
501	return 1;
502}
503
504/* convert a hex string to a 64bit key id (in big endian byte order */
505static void
506str_to_keyid(const char *s, uint8_t *keyid)
507{
508	uint64_t	u64;
509
510	u64 = (uint64_t)strtoull(s, NULL, 16);
511	u64 =   ((u64 & 0x00000000000000FFUL) << 56) |
512		((u64 & 0x000000000000FF00UL) << 40) |
513		((u64 & 0x0000000000FF0000UL) << 24) |
514		((u64 & 0x00000000FF000000UL) <<  8) |
515		((u64 & 0x000000FF00000000UL) >>  8) |
516		((u64 & 0x0000FF0000000000UL) >> 24) |
517		((u64 & 0x00FF000000000000UL) >> 40) |
518		((u64 & 0xFF00000000000000UL) >> 56);
519	memcpy(keyid, &u64, PGPV_KEYID_LEN);
520}
521
522#define PKT_ALWAYS_ON			0x80
523#define PKT_NEWFMT_MASK			0x40
524#define PKT_NEWFMT_TAG_MASK		0x3f
525#define PKT_OLDFMT_TAG_MASK		0x3c
526
527#define SUBPKT_CRITICAL_MASK		0x80
528#define SUBPKT_TAG_MASK			0x7f
529
530#define SUBPKT_SIG_BIRTH		2
531#define SUBPKT_SIG_EXPIRY		3
532#define SUBPKT_EXPORT_CERT		4
533#define SUBPKT_TRUST_SIG		5
534#define SUBPKT_REGEXP			6
535#define SUBPKT_REVOCABLE		7
536#define SUBPKT_KEY_EXPIRY		9
537#define SUBPKT_BWD_COMPAT		10
538#define SUBPKT_PREF_SYMMETRIC_ALG	11
539#define SUBPKT_REVOCATION_KEY		12
540#define SUBPKT_ISSUER			16
541#define SUBPKT_NOTATION			20
542#define SUBPKT_PREF_HASH_ALG		21
543#define SUBPKT_PREF_COMPRESS_ALG	22
544#define SUBPKT_KEY_SERVER_PREFS		23
545#define SUBPKT_PREF_KEY_SERVER		24
546#define SUBPKT_PRIMARY_USER_ID		25
547#define SUBPKT_POLICY_URI		26
548#define SUBPKT_KEY_FLAGS		27
549#define SUBPKT_SIGNER_ID		28
550#define SUBPKT_REVOCATION_REASON	29
551#define SUBPKT_FEATURES			30
552#define SUBPKT_SIGNATURE_TARGET		31
553#define SUBPKT_EMBEDDED_SIGNATURE	32
554
555#define UNCOMPRESSED			0
556#define ZIP_COMPRESSION			1
557#define ZLIB_COMPRESSION		2
558#define BZIP2_COMPRESSION		3
559
560/* get a 16 bit integer, in host order */
561static uint16_t
562get_16(uint8_t *p)
563{
564	uint16_t	u16;
565
566	memcpy(&u16, p, sizeof(u16));
567	return ntohs(u16);
568}
569
570/* get a 32 bit integer, in host order */
571static uint32_t
572get_32(uint8_t *p)
573{
574	uint32_t	u32;
575
576	memcpy(&u32, p, sizeof(u32));
577	return ntohl(u32);
578}
579
580#define HOURSECS	(int64_t)(60 * 60)
581#define DAYSECS		(int64_t)(24 * 60 * 60)
582#define MONSECS		(int64_t)(30 * DAYSECS)
583#define YEARSECS	(int64_t)(365 * DAYSECS)
584
585/* format (human readable) time into memory */
586static size_t
587fmt_time(char *s, size_t size, const char *header, int64_t n, const char *trailer, int relative)
588{
589	struct tm	tm;
590	time_t		elapsed;
591	time_t		now;
592	time_t		t;
593	size_t		cc;
594
595	t = (time_t)n;
596	now = time(NULL);
597	elapsed = now - t;
598	gmtime_r(&t, &tm);
599	cc = snprintf(s, size, "%s%04d-%02d-%02d", header,
600		tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
601	if (relative) {
602		cc += snprintf(&s[cc], size - cc, " (%lldy %lldm %lldd %lldh %s)",
603			llabs((long long)elapsed / YEARSECS),
604			llabs(((long long)elapsed % YEARSECS) / MONSECS),
605			llabs(((long long)elapsed % MONSECS) / DAYSECS),
606			llabs(((long long)elapsed % DAYSECS) / HOURSECS),
607			(now > t) ? "ago" : "ahead");
608	}
609	cc += snprintf(&s[cc], size - cc, "%s", trailer);
610	return cc;
611}
612
613/* dump key mpis to stdout */
614static void
615print_key_mpis(pgpv_bignum_t *v, uint8_t keyalg)
616{
617	char	s[8192];
618
619	switch(keyalg) {
620	case PUBKEY_RSA_ENCRYPT_OR_SIGN:
621	case PUBKEY_RSA_ENCRYPT:
622	case PUBKEY_RSA_SIGN:
623		fmt_mpi(s, sizeof(s), &v[RSA_N], "rsa.n", 1);
624		printf("%s", s);
625		fmt_mpi(s, sizeof(s), &v[RSA_E], "rsa.e", 1);
626		printf("%s", s);
627		break;
628	case PUBKEY_ELGAMAL_ENCRYPT:
629		fmt_mpi(s, sizeof(s), &v[ELGAMAL_P], "elgamal.p", 1);
630		printf("%s", s);
631		fmt_mpi(s, sizeof(s), &v[ELGAMAL_Y], "elgamal.y", 1);
632		printf("%s", s);
633		break;
634	case PUBKEY_DSA:
635		fmt_mpi(s, sizeof(s), &v[DSA_P], "dsa.p", 1);
636		printf("%s", s);
637		fmt_mpi(s, sizeof(s), &v[DSA_Q], "dsa.q", 1);
638		printf("%s", s);
639		fmt_mpi(s, sizeof(s), &v[DSA_G], "dsa.g", 1);
640		printf("%s", s);
641		fmt_mpi(s, sizeof(s), &v[DSA_Y], "dsa.y", 1);
642		printf("%s", s);
643		break;
644	default:
645		printf("hi, unusual keyalg %u\n", keyalg);
646		break;
647	}
648}
649
650/* get an mpi, including 2 byte length */
651static int
652get_mpi(pgpv_bignum_t *mpi, uint8_t *p, size_t pktlen, size_t *off)
653{
654	size_t	bytes;
655
656	mpi->bits = get_16(p);
657	if ((bytes = (size_t)BITS_TO_BYTES(mpi->bits)) > pktlen) {
658		return 0;
659	}
660	*off += sizeof(mpi->bits);
661	mpi->bn = BN_bin2bn(&p[sizeof(mpi->bits)], (int)bytes, NULL);
662	*off += bytes;
663	return 1;
664}
665
666/* read mpis in signature */
667static int
668read_signature_mpis(pgpv_sigpkt_t *sigpkt, uint8_t *p, size_t pktlen)
669{
670	size_t	off;
671
672	off = 0;
673	switch(sigpkt->sig.keyalg) {
674	case PUBKEY_RSA_ENCRYPT_OR_SIGN:
675	case PUBKEY_RSA_SIGN:
676	case PUBKEY_RSA_ENCRYPT:
677		if (!get_mpi(&sigpkt->sig.bn[RSA_SIG], p, pktlen, &off)) {
678			printf("sigpkt->version %d, rsa sig weird\n", sigpkt->sig.version);
679			return 0;
680		}
681		break;
682	case PUBKEY_DSA:
683	case PUBKEY_ECDSA:
684	case PUBKEY_ELGAMAL_ENCRYPT_OR_SIGN: /* deprecated */
685		if (!get_mpi(&sigpkt->sig.bn[DSA_R], p, pktlen, &off) ||
686		    !get_mpi(&sigpkt->sig.bn[DSA_S], &p[off], pktlen, &off)) {
687			printf("sigpkt->version %d, dsa/elgamal sig weird\n", sigpkt->sig.version);
688			return 0;
689		}
690		break;
691	default:
692		printf("weird type of sig! %d\n", sigpkt->sig.keyalg);
693		return 0;
694	}
695	return 1;
696}
697
698/* add the signature sub packet to the signature packet */
699static int
700add_subpacket(pgpv_sigpkt_t *sigpkt, uint8_t tag, uint8_t *p, uint16_t len)
701{
702	pgpv_sigsubpkt_t	subpkt;
703
704	memset(&subpkt, 0x0, sizeof(subpkt));
705	subpkt.s.size = len;
706	subpkt.critical = 0;
707	subpkt.tag = tag;
708	subpkt.s.data = p;
709	ARRAY_APPEND(sigpkt->subpkts, subpkt);
710	return 1;
711}
712
713/* read the subpackets in the signature */
714static int
715read_sig_subpackets(pgpv_sigpkt_t *sigpkt, uint8_t *p, size_t pktlen)
716{
717	pgpv_sigsubpkt_t	 subpkt;
718	const int		 is_subpkt = 0;
719	unsigned		 lenlen;
720	unsigned		 i;
721	uint8_t			*start;
722
723	start = p;
724	for (i = 0 ; (unsigned)(p - start) < sigpkt->subslen ; i++) {
725		memset(&subpkt, 0x0, sizeof(subpkt));
726		subpkt.s.size = get_pkt_len(1, p, 0, is_subpkt);
727		lenlen = get_pkt_len_len(1, p, is_subpkt);
728		if (lenlen > pktlen) {
729			printf("weird lenlen %u\n", lenlen);
730			return 0;
731		}
732		p += lenlen;
733		subpkt.critical = (*p & SUBPKT_CRITICAL_MASK);
734		subpkt.tag = (*p & SUBPKT_TAG_MASK);
735		p += 1;
736		switch(subpkt.tag) {
737		case SUBPKT_SIG_BIRTH:
738			sigpkt->sig.birth = (int64_t)get_32(p);
739			break;
740		case SUBPKT_SIG_EXPIRY:
741			sigpkt->sig.expiry = (int64_t)get_32(p);
742			break;
743		case SUBPKT_KEY_EXPIRY:
744			sigpkt->sig.keyexpiry = (int64_t)get_32(p);
745			break;
746		case SUBPKT_ISSUER:
747			sigpkt->sig.signer = p;
748			break;
749		case SUBPKT_SIGNER_ID:
750			sigpkt->sig.signer = p;
751			break;
752		case SUBPKT_TRUST_SIG:
753			sigpkt->sig.trustsig = *p;
754			break;
755		case SUBPKT_REGEXP:
756			sigpkt->sig.regexp = (char *)(void *)p;
757			break;
758		case SUBPKT_REVOCABLE:
759			sigpkt->sig.revocable = *p;
760			break;
761		case SUBPKT_PREF_SYMMETRIC_ALG:
762			sigpkt->sig.pref_symm_alg = *p;
763			break;
764		case SUBPKT_REVOCATION_KEY:
765			sigpkt->sig.revoke_sensitive = (*p & 0x40);
766			sigpkt->sig.revoke_alg = p[1];
767			sigpkt->sig.revoke_fingerprint = &p[2];
768			break;
769		case SUBPKT_NOTATION:
770			sigpkt->sig.notation = *p;
771			break;
772		case SUBPKT_PREF_HASH_ALG:
773			sigpkt->sig.pref_hash_alg = *p;
774			break;
775		case SUBPKT_PREF_COMPRESS_ALG:
776			sigpkt->sig.pref_compress_alg = *p;
777			break;
778		case SUBPKT_PREF_KEY_SERVER:
779			sigpkt->sig.pref_key_server = (char *)(void *)p;
780			break;
781		case SUBPKT_KEY_SERVER_PREFS:
782			sigpkt->sig.key_server_modify = *p;
783			break;
784		case SUBPKT_KEY_FLAGS:
785			sigpkt->sig.type_key = *p;
786			break;
787		case SUBPKT_PRIMARY_USER_ID:
788			sigpkt->sig.primary_userid = *p;
789			break;
790		case SUBPKT_POLICY_URI:
791			sigpkt->sig.policy = (char *)(void *)p;
792			break;
793		case SUBPKT_FEATURES:
794			sigpkt->sig.features = (char *)(void *)p;
795			break;
796		case SUBPKT_REVOCATION_REASON:
797			sigpkt->sig.revoked = *p++ + 1;
798			sigpkt->sig.why_revoked = (char *)(void *)p;
799			break;
800		default:
801			printf("Ignoring unusual/reserved signature subpacket %d\n", subpkt.tag);
802			break;
803		}
804		subpkt.s.data = p;
805		p += subpkt.s.size - 1;
806		ARRAY_APPEND(sigpkt->subpkts, subpkt);
807	}
808	return 1;
809}
810
811/* parse signature packet */
812static int
813read_sigpkt(pgpv_t *pgp, uint8_t mement, pgpv_sigpkt_t *sigpkt, uint8_t *p, size_t pktlen)
814{
815	unsigned	 lenlen;
816	uint8_t		*base;
817
818	make_ref(pgp, mement, &sigpkt->sig.hashstart);
819	base = p;
820	switch(sigpkt->sig.version = *p++) {
821	case 2:
822	case 3:
823		if ((lenlen = *p++) != 5) {
824			printf("read_sigpkt: hashed length not 5\n");
825			return 0;
826		}
827		sigpkt->sig.hashlen = lenlen;
828		/* put birthtime into a subpacket */
829		sigpkt->sig.type = *p++;
830		add_subpacket(sigpkt, SUBPKT_SIG_BIRTH, p, sizeof(uint32_t));
831		sigpkt->sig.birth = (int64_t)get_32(p);
832		p += sizeof(uint32_t);
833		sigpkt->sig.signer = p;
834		add_subpacket(sigpkt, SUBPKT_SIGNER_ID, p, PGPV_KEYID_LEN);
835		p += PGPV_KEYID_LEN;
836		sigpkt->sig.keyalg = *p++;
837		sigpkt->sig.hashalg = *p++;
838		sigpkt->sig.hash2 = p;
839		if (!read_signature_mpis(sigpkt, sigpkt->sig.mpi = p + 2, pktlen)) {
840			printf("read_sigpkt: can't read sigs v3\n");
841			return 0;
842		}
843		break;
844	case 4:
845		sigpkt->sig.type = *p++;
846		sigpkt->sig.keyalg = *p++;
847		sigpkt->sig.hashalg = *p++;
848		sigpkt->subslen = get_16(p);
849		p += sizeof(sigpkt->subslen);
850		if (!read_sig_subpackets(sigpkt, p, pktlen)) {
851			printf("read_sigpkt: can't read sig subpackets, v4\n");
852			return 0;
853		}
854		if (!sigpkt->sig.signer) {
855			sigpkt->sig.signer = get_ref(&sigpkt->sig.hashstart) + 16;
856		}
857		p += sigpkt->subslen;
858		sigpkt->sig.hashlen = (unsigned)(p - base);
859		sigpkt->unhashlen = get_16(p);
860		p += sizeof(sigpkt->unhashlen) + sigpkt->unhashlen;
861		sigpkt->sig.hash2 = p;
862		if (!read_signature_mpis(sigpkt, sigpkt->sig.mpi = p + 2, pktlen)) {
863			printf("read_sigpkt: can't read sigs, v4\n");
864			return 0;
865		}
866		break;
867	default:
868		printf("read_sigpkt: unusual signature version (%u)\n", sigpkt->sig.version);
869		break;
870	}
871	return 1;
872}
873
874
875/* this parses compressed data, decompresses it, and calls the parser again */
876static int
877read_compressed(pgpv_t *pgp, pgpv_compress_t *compressed, uint8_t *p, size_t len)
878{
879	pgpv_mem_t	*unzmem;
880	bz_stream	 bz;
881	z_stream	 z;
882	int		 ok = 0;
883
884	compressed->compalg = *p;
885	compressed->s.size = len;
886	if ((compressed->s.data = calloc(1, len)) == NULL) {
887		printf("read_compressed: can't allocate %zu length\n", len);
888		return 0;
889	}
890	switch(compressed->compalg) {
891	case UNCOMPRESSED:
892		printf("not implemented %d compression yet\n", compressed->compalg);
893		return 0;
894	default:
895		break;
896	}
897	ARRAY_EXPAND(pgp->areas);
898	ARRAY_COUNT(pgp->areas) += 1;
899	unzmem = &ARRAY_LAST(pgp->areas);
900	unzmem->size = len * 10;
901	unzmem->dealloc = FREE_MEM;
902	if ((unzmem->mem = calloc(1, unzmem->size)) == NULL) {
903		printf("read_compressed: calloc failed!\n");
904		return 0;
905	}
906	switch(compressed->compalg) {
907	case ZIP_COMPRESSION:
908	case ZLIB_COMPRESSION:
909		memset(&z, 0x0, sizeof(z));
910		z.next_in = p + 1;
911		z.avail_in = (unsigned)(len - 1);
912		z.total_in = (unsigned)(len - 1);
913		z.next_out = unzmem->mem;
914		z.avail_out = (unsigned)unzmem->size;
915		z.total_out = (unsigned)unzmem->size;
916		break;
917	case BZIP2_COMPRESSION:
918		memset(&bz, 0x0, sizeof(bz));
919		bz.avail_in = (unsigned)(len - 1);
920		bz.next_in = (char *)(void *)p + 1;
921		bz.next_out = (char *)(void *)unzmem->mem;
922		bz.avail_out = (unsigned)unzmem->size;
923		break;
924	}
925	switch(compressed->compalg) {
926	case ZIP_COMPRESSION:
927		ok = (inflateInit2(&z, -15) == Z_OK);
928		break;
929	case ZLIB_COMPRESSION:
930		ok = (inflateInit(&z) == Z_OK);
931		break;
932	case BZIP2_COMPRESSION:
933		ok = (BZ2_bzDecompressInit(&bz, 1, 0) == BZ_OK);
934		break;
935	}
936	if (!ok) {
937		printf("read_compressed: initialisation failed!\n");
938		return 0;
939	}
940	switch(compressed->compalg) {
941	case ZIP_COMPRESSION:
942	case ZLIB_COMPRESSION:
943		ok = (inflate(&z, Z_FINISH) == Z_STREAM_END);
944		unzmem->size = z.total_out;
945		break;
946	case BZIP2_COMPRESSION:
947		ok = (BZ2_bzDecompress(&bz) == BZ_STREAM_END);
948		unzmem->size = ((uint64_t)bz.total_out_hi32 << 32) | bz.total_out_lo32;
949		break;
950	}
951	if (!ok) {
952		printf("read_compressed: inflate failed!\n");
953		return 0;
954	}
955	return 1;
956}
957
958/* parse one pass signature packet */
959static int
960read_onepass_sig(pgpv_onepass_t *onepasspkt, uint8_t *mem)
961{
962	onepasspkt->version = mem[0];
963	onepasspkt->type = mem[1];
964	onepasspkt->hashalg = mem[2];
965	onepasspkt->keyalg = mem[3];
966	memcpy(onepasspkt->keyid, &mem[4], sizeof(onepasspkt->keyid));
967	onepasspkt->nested = mem[12];
968	return 1;
969}
970
971/* parse public key packet */
972static int
973read_pubkey(pgpv_pubkey_t *pubkey, uint8_t *mem, size_t pktlen, int pbn)
974{
975	size_t		 off;
976
977	off = 0;
978	pubkey->version = mem[off++];
979	pubkey->birth = get_32(&mem[off]);
980	off += 4;
981	if (pubkey->version == 2 || pubkey->version == 3) {
982		pubkey->expiry = get_16(&mem[off]) * DAYSECS;
983		off += 2;
984	}
985	if ((pubkey->keyalg = mem[off++]) == 0) {
986		pubkey->keyalg = PUBKEY_RSA_ENCRYPT_OR_SIGN;
987		printf("got unusual pubkey keyalg %u\n", mem[off - 1]);
988	}
989	switch(pubkey->keyalg) {
990	case PUBKEY_RSA_ENCRYPT_OR_SIGN:
991	case PUBKEY_RSA_ENCRYPT:
992	case PUBKEY_RSA_SIGN:
993		if (!get_mpi(&pubkey->bn[RSA_N], &mem[off], pktlen, &off) ||
994		    !get_mpi(&pubkey->bn[RSA_E], &mem[off], pktlen, &off)) {
995			return 0;
996		}
997		break;
998	case PUBKEY_ELGAMAL_ENCRYPT:
999	case PUBKEY_ELGAMAL_ENCRYPT_OR_SIGN:
1000		if (!get_mpi(&pubkey->bn[ELGAMAL_P], &mem[off], pktlen, &off) ||
1001		    !get_mpi(&pubkey->bn[ELGAMAL_Y], &mem[off], pktlen, &off)) {
1002			return 0;
1003		}
1004		break;
1005	case PUBKEY_DSA:
1006		if (!get_mpi(&pubkey->bn[DSA_P], &mem[off], pktlen, &off) ||
1007		    !get_mpi(&pubkey->bn[DSA_Q], &mem[off], pktlen, &off) ||
1008		    !get_mpi(&pubkey->bn[DSA_G], &mem[off], pktlen, &off) ||
1009		    !get_mpi(&pubkey->bn[DSA_Y], &mem[off], pktlen, &off)) {
1010			return 0;
1011		}
1012		break;
1013	default:
1014		printf("hi, different type of pubkey here %u\n", pubkey->keyalg);
1015		break;
1016	}
1017	if (pbn) {
1018		print_key_mpis(pubkey->bn, pubkey->keyalg);
1019	}
1020	return 1;
1021}
1022
1023/* parse a user attribute */
1024static int
1025read_userattr(pgpv_userattr_t *userattr, uint8_t *p, size_t pktlen)
1026{
1027	pgpv_string_t	subattr;
1028	const int 	is_subpkt = 0;
1029	const int	indian = 1;
1030	unsigned	lenlen;
1031	uint16_t	imagelen;
1032	size_t		cc;
1033
1034	userattr->len = pktlen;
1035	for (cc = 0 ; cc < pktlen ; cc += subattr.size + lenlen + 1) {
1036		subattr.size = get_pkt_len(1, p, 0, is_subpkt);
1037		lenlen = get_pkt_len_len(1, p, is_subpkt);
1038		if (lenlen > pktlen) {
1039			printf("weird lenlen %u\n", lenlen);
1040			return 0;
1041		}
1042		p += lenlen;
1043		if (*p++ != 1) {
1044			printf("image type (%u) != 1. weird packet\n", *(p - 1));
1045		}
1046		memcpy(&imagelen, p, sizeof(imagelen));
1047		if (!*(const char *)(const void *)&indian) {
1048			/* big endian - byteswap length */
1049			imagelen = (((unsigned)imagelen & 0xff) << 8) | (((unsigned)imagelen >> 8) & 0xff);
1050		}
1051		subattr.data = p + 3;
1052		p += subattr.size;
1053		ARRAY_APPEND(userattr->subattrs, subattr);
1054	}
1055	return 1;
1056}
1057
1058#define LITDATA_BINARY	'b'
1059#define LITDATA_TEXT	't'
1060#define LITDATA_UTF8	'u'
1061
1062/* parse literal packet */
1063static int
1064read_litdata(pgpv_t *pgp, pgpv_litdata_t *litdata, uint8_t *p, size_t size)
1065{
1066	size_t	cc;
1067
1068	cc = 0;
1069	switch(litdata->format = p[cc++]) {
1070	case LITDATA_BINARY:
1071	case LITDATA_TEXT:
1072	case LITDATA_UTF8:
1073		litdata->namelen = 0;
1074		break;
1075	default:
1076		printf("weird litdata format %u\n", litdata->format);
1077		break;
1078	}
1079	litdata->namelen = p[cc++];
1080	litdata->filename = &p[cc];
1081	cc += litdata->namelen;
1082	litdata->secs = get_32(&p[cc]);
1083	cc += 4;
1084	litdata->s.data = &p[cc];
1085	litdata->len = litdata->s.size = size - cc;
1086	litdata->mem = ARRAY_COUNT(pgp->areas) - 1;
1087	litdata->offset = cc;
1088	return 1;
1089}
1090
1091/* parse a single packet */
1092static int
1093read_pkt(pgpv_t *pgp, pgpv_mem_t *mem)
1094{
1095	const int	 isprimary = 1;
1096	pgpv_pkt_t	 pkt;
1097	pgpv_mem_t	*newmem;
1098	unsigned	 lenlen;
1099	uint8_t		 ispartial;
1100	size_t		 size;
1101
1102	memset(&pkt, 0x0, sizeof(pkt));
1103	pkt.tag = mem->mem[mem->cc++];
1104	if (!(pkt.tag & PKT_ALWAYS_ON)) {
1105		printf("BAD PACKET - bit 7 not 1, offset %zu!\n", mem->cc - 1);
1106	}
1107	pkt.newfmt = (pkt.tag & PKT_NEWFMT_MASK);
1108	pkt.tag = (pkt.newfmt) ?
1109		(pkt.tag & PKT_NEWFMT_TAG_MASK) :
1110		(((unsigned)pkt.tag & PKT_OLDFMT_TAG_MASK) >> 2);
1111	ispartial = (pkt.newfmt && IS_PARTIAL(mem->mem[mem->cc]));
1112	pkt.s.size = get_pkt_len(pkt.newfmt, &mem->mem[mem->cc], mem->size - mem->cc, isprimary);
1113	lenlen = get_pkt_len_len(pkt.newfmt, &mem->mem[mem->cc], isprimary);
1114	pkt.offset = mem->cc;
1115	mem->cc += lenlen;
1116	pkt.mement = (uint8_t)(mem - ARRAY_ARRAY(pgp->areas));
1117	pkt.s.data = &mem->mem[mem->cc];
1118	if (strchr(mem->allowed, pkt.tag) == NULL) {
1119		printf("packet %d not allowed for operation %s\n", pkt.tag, pgp->op);
1120		return 0;
1121	}
1122	size = pkt.s.size;
1123	if (ispartial) {
1124		pkt.s.size = fixup_partials(pgp, &mem->mem[mem->cc - lenlen], pkt.s.size, mem->size, &size);
1125		newmem = &ARRAY_LAST(pgp->areas);
1126		pkt.mement = (uint8_t)(newmem - ARRAY_ARRAY(pgp->areas));
1127		pkt.s.data = newmem->mem;
1128		size -= 1;
1129	}
1130	switch(pkt.tag) {
1131	case SIGNATURE_PKT:
1132		if (!read_sigpkt(pgp, pkt.mement, &pkt.u.sigpkt, pkt.s.data, pkt.s.size)) {
1133			return 0;
1134		}
1135		break;
1136	case ONEPASS_SIGNATURE_PKT:
1137		read_onepass_sig(&pkt.u.onepass, pkt.s.data);
1138		break;
1139	case PUBKEY_PKT:
1140	case PUB_SUBKEY_PKT:
1141		break;
1142	case LITDATA_PKT:
1143		read_litdata(pgp, &pkt.u.litdata, pkt.s.data, pkt.s.size);
1144		break;
1145	case TRUST_PKT:
1146		pkt.u.trust.level = pkt.s.data[0];
1147		pkt.u.trust.amount = pkt.s.data[1];
1148		break;
1149	case USERID_PKT:
1150		pkt.u.userid.size = pkt.s.size;
1151		pkt.u.userid.data = pkt.s.data;
1152		break;
1153	case COMPRESSED_DATA_PKT:
1154		read_compressed(pgp, &pkt.u.compressed, pkt.s.data, pkt.s.size);
1155		ARRAY_APPEND(pgp->pkts, pkt);
1156		read_all_packets(pgp, &ARRAY_LAST(pgp->areas), pgp->op);
1157		break;
1158	case USER_ATTRIBUTE_PKT:
1159		read_userattr(&pkt.u.userattr, pkt.s.data, pkt.s.size);
1160		break;
1161	default:
1162		printf("hi, need to implement %d, offset %zu\n", pkt.tag, mem->cc);
1163		break;
1164	}
1165	mem->cc += size;
1166	if (pkt.tag != COMPRESSED_DATA_PKT) {
1167		/* compressed was added earlier to preserve pkt ordering */
1168		ARRAY_APPEND(pgp->pkts, pkt);
1169	}
1170	return 1;
1171}
1172
1173/* checks the tag type of a packet */
1174static int
1175pkt_is(pgpv_t *pgp, int wanted)
1176{
1177	return (ARRAY_ELEMENT(pgp->pkts, pgp->pkt).tag == wanted);
1178}
1179
1180/* checks the packet is a signature packet, and the signature type is the expected one */
1181static int
1182pkt_sigtype_is(pgpv_t *pgp, int wanted)
1183{
1184	if (!pkt_is(pgp, SIGNATURE_PKT)) {
1185		return 0;
1186	}
1187	return (ARRAY_ELEMENT(pgp->pkts, pgp->pkt).u.sigpkt.sig.type == wanted);
1188}
1189
1190/* check for expected type of packet, and move to the next */
1191static int
1192pkt_accept(pgpv_t *pgp, int expected)
1193{
1194	int	got;
1195
1196	if ((got = ARRAY_ELEMENT(pgp->pkts, pgp->pkt).tag) == expected) {
1197		pgp->pkt += 1;
1198		return 1;
1199	}
1200	printf("problem at token %zu, expcted %d, got %d\n", pgp->pkt, expected, got);
1201	return 0;
1202}
1203
1204/* recognise signature (and trust) packet */
1205static int
1206recog_signature(pgpv_t *pgp, pgpv_signature_t *signature)
1207{
1208	if (!pkt_is(pgp, SIGNATURE_PKT)) {
1209		printf("recog_signature: not a signature packet\n");
1210		return 0;
1211	}
1212	memcpy(signature, &ARRAY_ELEMENT(pgp->pkts, pgp->pkt).u.sigpkt.sig, sizeof(*signature));
1213	pgp->pkt += 1;
1214	if (pkt_is(pgp, TRUST_PKT)) {
1215		pkt_accept(pgp, TRUST_PKT);
1216	}
1217	return 1;
1218}
1219
1220/* recognise user id packet */
1221static int
1222recog_userid(pgpv_t *pgp, pgpv_signed_userid_t *userid)
1223{
1224	pgpv_signature_t	 signature;
1225	pgpv_pkt_t		*pkt;
1226
1227	memset(userid, 0x0, sizeof(*userid));
1228	if (!pkt_is(pgp, USERID_PKT)) {
1229		printf("recog_userid: not %d\n", USERID_PKT);
1230		return 0;
1231	}
1232	pkt = &ARRAY_ELEMENT(pgp->pkts, pgp->pkt);
1233	userid->userid.size = pkt->s.size;
1234	userid->userid.data = pkt->s.data;
1235	pgp->pkt += 1;
1236	while (pkt_is(pgp, SIGNATURE_PKT)) {
1237		if (!recog_signature(pgp, &signature)) {
1238			printf("recog_userid: can't recognise signature/trust\n");
1239			return 0;
1240		}
1241		ARRAY_APPEND(userid->sigs, signature);
1242		if (signature.primary_userid) {
1243			userid->primary_userid = signature.primary_userid;
1244		}
1245		if (signature.revoked) {
1246			userid->revoked = signature.revoked;
1247		}
1248	}
1249	return 1;
1250}
1251
1252/* recognise user attributes packet */
1253static int
1254recog_userattr(pgpv_t *pgp, pgpv_signed_userattr_t *userattr)
1255{
1256	pgpv_signature_t	 signature;
1257
1258	memset(userattr, 0x0, sizeof(*userattr));
1259	if (!pkt_is(pgp, USER_ATTRIBUTE_PKT)) {
1260		printf("recog_userattr: not %d\n", USER_ATTRIBUTE_PKT);
1261		return 0;
1262	}
1263	userattr->userattr = ARRAY_ELEMENT(pgp->pkts, pgp->pkt).u.userattr;
1264	pgp->pkt += 1;
1265	while (pkt_is(pgp, SIGNATURE_PKT)) {
1266		if (!recog_signature(pgp, &signature)) {
1267			printf("recog_userattr: can't recognise signature/trust\n");
1268			return 0;
1269		}
1270		ARRAY_APPEND(userattr->sigs, signature);
1271		if (signature.revoked) {
1272			userattr->revoked = signature.revoked;
1273		}
1274	}
1275	return 1;
1276}
1277
1278/* recognise a sub key */
1279static int
1280recog_subkey(pgpv_t *pgp, pgpv_signed_subkey_t *subkey)
1281{
1282	pgpv_signature_t	 signature;
1283	pgpv_pkt_t		*pkt;
1284
1285	pkt = &ARRAY_ELEMENT(pgp->pkts, pgp->pkt);
1286	memset(subkey, 0x0, sizeof(*subkey));
1287	read_pubkey(&subkey->subkey, pkt->s.data, pkt->s.size, 0);
1288	pgp->pkt += 1;
1289	if (pkt_sigtype_is(pgp, SIGTYPE_KEY_REVOCATION) ||
1290	    pkt_sigtype_is(pgp, SIGTYPE_SUBKEY_REVOCATION) ||
1291	    pkt_sigtype_is(pgp, SIGTYPE_CERT_REVOCATION)) {
1292		recog_signature(pgp, &signature);
1293		subkey->revoc_self_sig = signature;
1294	}
1295	do {
1296		if (!pkt_is(pgp, SIGNATURE_PKT)) {
1297			printf("recog_subkey: not signature packet at %zu\n", pgp->pkt);
1298			return 0;
1299		}
1300		if (!recog_signature(pgp, &signature)) {
1301			printf("recog_subkey: bad signature/trust at %zu\n", pgp->pkt);
1302			return 0;
1303		}
1304		ARRAY_APPEND(subkey->sigs, signature);
1305		if (signature.keyexpiry) {
1306			/* XXX - check it's a good key expiry */
1307			subkey->subkey.expiry = signature.keyexpiry;
1308		}
1309	} while (pkt_is(pgp, SIGNATURE_PKT));
1310	return 1;
1311}
1312
1313/* use a sparse map for the text strings here to save space */
1314static const char	*keyalgs[] = {
1315	"[Unknown]",
1316	"RSA (Encrypt or Sign)",
1317	"RSA (Encrypt Only)",
1318	"RSA (Sign Only)",
1319	"Elgamal (Encrypt Only)",
1320	"DSA",
1321	"Elliptic Curve",
1322	"ECDSA",
1323	"Elgamal (Encrypt or Sign)"
1324};
1325
1326#define MAX_KEYALG	21
1327
1328static const char *keyalgmap = "\0\01\02\03\0\0\0\0\0\0\0\0\0\0\0\0\04\05\06\07\010\011";
1329
1330/* return human readable name for key algorithm */
1331static const char *
1332fmtkeyalg(uint8_t keyalg)
1333{
1334	return keyalgs[(uint8_t)keyalgmap[(keyalg >= MAX_KEYALG) ? 0 : keyalg]];
1335}
1336
1337/* return the number of bits in the public key */
1338static unsigned
1339numkeybits(const pgpv_pubkey_t *pubkey)
1340{
1341	switch(pubkey->keyalg) {
1342	case PUBKEY_RSA_ENCRYPT_OR_SIGN:
1343	case PUBKEY_RSA_ENCRYPT:
1344	case PUBKEY_RSA_SIGN:
1345		return pubkey->bn[RSA_N].bits;
1346	case PUBKEY_DSA:
1347	case PUBKEY_ECDSA:
1348		return BITS_TO_BYTES(pubkey->bn[DSA_Q].bits) * 64;
1349	case PUBKEY_ELGAMAL_ENCRYPT:
1350	case PUBKEY_ELGAMAL_ENCRYPT_OR_SIGN:
1351		return pubkey->bn[ELGAMAL_P].bits;
1352	default:
1353		return 0;
1354	}
1355}
1356
1357/* print a public key */
1358static size_t
1359fmt_pubkey(char *s, size_t size, pgpv_pubkey_t *pubkey, const char *leader)
1360{
1361	size_t	cc;
1362
1363	cc = snprintf(s, size, "%s %u/%s ", leader, numkeybits(pubkey), fmtkeyalg(pubkey->keyalg));
1364	cc += fmt_binary(&s[cc], size - cc, pubkey->keyid, PGPV_KEYID_LEN);
1365	cc += fmt_time(&s[cc], size - cc, " ", pubkey->birth, "", 0);
1366	if (pubkey->expiry) {
1367		cc += fmt_time(&s[cc], size - cc, " [Expiry ", pubkey->birth + pubkey->expiry, "]", 0);
1368	}
1369	cc += snprintf(&s[cc], size - cc, "\n");
1370	cc += fmt_fingerprint(&s[cc], size - cc, &pubkey->fingerprint, "fingerprint: ");
1371	return cc;
1372}
1373
1374/* we add 1 to revocation value to denote compromised */
1375#define COMPROMISED	(0x02 + 1)
1376
1377/* format a userid - used to order the userids when formatting */
1378static size_t
1379fmt_userid(char *s, size_t size, pgpv_primarykey_t *primary, uint8_t u)
1380{
1381	pgpv_signed_userid_t	*userid;
1382
1383	userid = &ARRAY_ELEMENT(primary->signed_userids, u);
1384	return snprintf(s, size, "uid              %.*s%s\n",
1385			(int)userid->userid.size, userid->userid.data,
1386			(userid->revoked == COMPROMISED) ? " [COMPROMISED AND REVOKED]" :
1387			(userid->revoked) ? " [REVOKED]" : "");
1388}
1389
1390/* print a primary key, per RFC 4880 */
1391static size_t
1392fmt_primary(char *s, size_t size, pgpv_primarykey_t *primary)
1393{
1394	unsigned	 i;
1395	size_t		 cc;
1396
1397	cc = fmt_pubkey(s, size, &primary->primary, "signature ");
1398	cc += fmt_userid(&s[cc], size - cc, primary, primary->primary_userid);
1399	for (i = 0 ; i < ARRAY_COUNT(primary->signed_userids) ; i++) {
1400		if (i != primary->primary_userid) {
1401			cc += fmt_userid(&s[cc], size - cc, primary, i);
1402		}
1403	}
1404	for (i = 0 ; i < ARRAY_COUNT(primary->signed_subkeys) ; i++) {
1405		cc += fmt_pubkey(&s[cc], size - cc, &ARRAY_ELEMENT(primary->signed_subkeys, i).subkey, "encryption");
1406	}
1407	cc += snprintf(&s[cc], size - cc, "\n");
1408	return cc;
1409}
1410
1411
1412/* check the padding on the signature */
1413static int
1414rsa_padding_check_none(uint8_t *to, int tlen, const uint8_t *from, int flen, int num)
1415{
1416	USE_ARG(num);
1417	if (flen > tlen) {
1418		printf("from length larger than to length\n");
1419		return -1;
1420	}
1421	(void) memset(to, 0x0, tlen - flen);
1422	(void) memcpy(to + tlen - flen, from, flen);
1423	return tlen;
1424}
1425
1426#define RSA_MAX_MODULUS_BITS	16384
1427#define RSA_SMALL_MODULUS_BITS	3072
1428#define RSA_MAX_PUBEXP_BITS	64 /* exponent limit enforced for "large" modulus only */
1429
1430/* check against the exponent/moudulo operation */
1431static int
1432lowlevel_rsa_public_check(const uint8_t *encbuf, int enclen, uint8_t *dec, const rsa_pubkey_t *rsa)
1433{
1434	uint8_t		*decbuf;
1435	BIGNUM		*decbn;
1436	BIGNUM		*encbn;
1437	int		 decbytes;
1438	int		 nbytes;
1439	int		 r;
1440
1441	nbytes = 0;
1442	r = -1;
1443	decbuf = NULL;
1444	decbn = encbn = NULL;
1445	if (BN_num_bits(rsa->n) > RSA_MAX_MODULUS_BITS) {
1446		printf("rsa r modulus too large\n");
1447		goto err;
1448	}
1449	if (BN_cmp(rsa->n, rsa->e) <= 0) {
1450		printf("rsa r bad n value\n");
1451		goto err;
1452	}
1453	if (BN_num_bits(rsa->n) > RSA_SMALL_MODULUS_BITS &&
1454	    BN_num_bits(rsa->e) > RSA_MAX_PUBEXP_BITS) {
1455		printf("rsa r bad exponent limit\n");
1456		goto err;
1457	}
1458	if ((encbn = BN_new()) == NULL ||
1459	    (decbn = BN_new()) == NULL ||
1460	    (decbuf = calloc(1, nbytes = BN_num_bytes(rsa->n))) == NULL) {
1461		printf("allocation failure\n");
1462		goto err;
1463	}
1464	if (enclen > nbytes) {
1465		printf("rsa r > mod len\n");
1466		goto err;
1467	}
1468	if (BN_bin2bn(encbuf, enclen, encbn) == NULL) {
1469		printf("null encrypted BN\n");
1470		goto err;
1471	}
1472	if (BN_cmp(encbn, rsa->n) >= 0) {
1473		printf("rsa r data too large for modulus\n");
1474		goto err;
1475	}
1476	if (BN_mod_exp(decbn, encbn, rsa->e, rsa->n, NULL) < 0) {
1477		printf("BN_mod_exp < 0\n");
1478		goto err;
1479	}
1480	decbytes = BN_num_bytes(decbn);
1481	(void) BN_bn2bin(decbn, decbuf);
1482	if ((r = rsa_padding_check_none(dec, nbytes, decbuf, decbytes, 0)) < 0) {
1483		printf("rsa r padding check failed\n");
1484	}
1485err:
1486	BN_free(encbn);
1487	BN_free(decbn);
1488	if (decbuf != NULL) {
1489		(void) memset(decbuf, 0x0, nbytes);
1490		free(decbuf);
1491	}
1492	return r;
1493}
1494
1495/* verify */
1496static int
1497rsa_public_decrypt(int enclen, const unsigned char *enc, unsigned char *dec, RSA *rsa, int padding)
1498{
1499	rsa_pubkey_t	pub;
1500	int		ret;
1501
1502	if (enc == NULL || dec == NULL || rsa == NULL) {
1503		return 0;
1504	}
1505	USE_ARG(padding);
1506	(void) memset(&pub, 0x0, sizeof(pub));
1507	pub.n = BN_dup(rsa->n);
1508	pub.e = BN_dup(rsa->e);
1509	ret = lowlevel_rsa_public_check(enc, enclen, dec, &pub);
1510	BN_free(pub.n);
1511	BN_free(pub.e);
1512	return ret;
1513}
1514
1515#define SUBKEY_LEN(x)	(80 + 80)
1516#define SIG_LEN		80
1517#define UID_LEN		80
1518
1519/* return worst case number of bytes needed to format a primary key */
1520static size_t
1521estimate_primarykey_size(pgpv_primarykey_t *primary)
1522{
1523	size_t		cc;
1524
1525	cc = SUBKEY_LEN("signature") +
1526		(ARRAY_COUNT(primary->signed_userids) * UID_LEN) +
1527		(ARRAY_COUNT(primary->signed_subkeys) * SUBKEY_LEN("encrypt uids"));
1528	return cc;
1529}
1530
1531/* use public decrypt to verify a signature */
1532static int
1533pgpv_rsa_public_decrypt(uint8_t *out, const uint8_t *in, size_t length, const pgpv_pubkey_t *pubkey)
1534{
1535	RSA            *orsa;
1536	int             n;
1537
1538	if ((orsa = calloc(1, sizeof(*orsa))) == NULL) {
1539		return 0;
1540	}
1541	orsa->n = pubkey->bn[RSA_N].bn;
1542	orsa->e = pubkey->bn[RSA_E].bn;
1543	n = rsa_public_decrypt((int)length, in, out, orsa, RSA_NO_PADDING);
1544	orsa->n = orsa->e = NULL;
1545	free(orsa);
1546	return n;
1547}
1548
1549/* verify rsa signature */
1550static int
1551rsa_verify(uint8_t *calculated, unsigned calclen, uint8_t hashalg, pgpv_bignum_t *bn, pgpv_pubkey_t *pubkey)
1552{
1553	unsigned	 prefixlen;
1554	unsigned	 decryptc;
1555	unsigned	 i;
1556	uint8_t		 decrypted[8192];
1557	uint8_t		 sigbn[8192];
1558	uint8_t		 prefix[64];
1559	size_t		 keysize;
1560
1561	keysize = BITS_TO_BYTES(pubkey->bn[RSA_N].bits);
1562	BN_bn2bin(bn[RSA_SIG].bn, sigbn);
1563	decryptc = pgpv_rsa_public_decrypt(decrypted, sigbn, BITS_TO_BYTES(bn[RSA_SIG].bits), pubkey);
1564	if (decryptc != keysize || (decrypted[0] != 0 || decrypted[1] != 1)) {
1565		return 0;
1566	}
1567	if ((prefixlen = digest_get_prefix((unsigned)hashalg, prefix, sizeof(prefix))) == 0) {
1568		printf("rsa_verify: unknown hash algorithm: %d\n", hashalg);
1569		return 0;
1570	}
1571	for (i = 2 ; i < keysize - prefixlen - calclen - 1 ; i++) {
1572		if (decrypted[i] != 0xff) {
1573			return 0;
1574		}
1575	}
1576	if (decrypted[i++] != 0x0) {
1577		return 0;
1578	}
1579	if (memcmp(&decrypted[i], prefix, prefixlen) != 0) {
1580		printf("rsa_verify: wrong hash algorithm\n");
1581		return 0;
1582	}
1583	return memcmp(&decrypted[i + prefixlen], calculated, calclen) == 0;
1584}
1585
1586/* return 1 if bn <= 0 */
1587static int
1588bignum_is_bad(BIGNUM *bn)
1589{
1590	return BN_is_zero(bn) || BN_is_negative(bn);
1591}
1592
1593#define BAD_BIGNUM(s, k)	\
1594	(bignum_is_bad((s)->bn) || BN_cmp((s)->bn, (k)->bn) >= 0)
1595
1596#ifndef DSA_MAX_MODULUS_BITS
1597#define DSA_MAX_MODULUS_BITS      10000
1598#endif
1599
1600/* verify DSA signature */
1601static int
1602verify_dsa_sig(uint8_t *calculated, unsigned calclen, pgpv_bignum_t *sig, pgpv_pubkey_t *pubkey)
1603{
1604	unsigned	  qbits;
1605	uint8_t		  calcnum[128];
1606	uint8_t		  signum[128];
1607	BIGNUM		 *M;
1608	BIGNUM		 *W;
1609	BIGNUM		 *t1;
1610	int		  ret;
1611
1612	if (pubkey->bn[DSA_P].bn == NULL ||
1613	    pubkey->bn[DSA_Q].bn == NULL ||
1614	    pubkey->bn[DSA_G].bn == NULL) {
1615		return 0;
1616	}
1617	M = W = t1 = NULL;
1618	qbits = pubkey->bn[DSA_Q].bits;
1619	switch(qbits) {
1620	case 160:
1621	case 224:
1622	case 256:
1623		break;
1624	default:
1625		printf("dsa: bad # of Q bits\n");
1626		return 0;
1627	}
1628	if (pubkey->bn[DSA_P].bits > DSA_MAX_MODULUS_BITS) {
1629		printf("dsa: p too large\n");
1630		return 0;
1631	}
1632	if (calclen > SHA256_DIGEST_LENGTH) {
1633		printf("dsa: digest too long\n");
1634		return 0;
1635	}
1636	ret = 0;
1637	if ((M = BN_new()) == NULL || (W = BN_new()) == NULL || (t1 = BN_new()) == NULL ||
1638	    BAD_BIGNUM(&sig[DSA_R], &pubkey->bn[DSA_Q]) ||
1639	    BAD_BIGNUM(&sig[DSA_S], &pubkey->bn[DSA_Q]) ||
1640	    BN_mod_inverse(W, sig[DSA_S].bn, pubkey->bn[DSA_Q].bn, NULL) == NULL) {
1641		goto done;
1642	}
1643	if (calclen > qbits / 8) {
1644		calclen = qbits / 8;
1645	}
1646	if (BN_bin2bn(calculated, (int)calclen, M) == NULL ||
1647	    !BN_mod_mul(M, M, W, pubkey->bn[DSA_Q].bn, NULL) ||
1648	    !BN_mod_mul(W, sig[DSA_R].bn, W, pubkey->bn[DSA_Q].bn, NULL) ||
1649	    !BN_mod_exp(t1, pubkey->bn[DSA_G].bn, M, pubkey->bn[DSA_P].bn, NULL) ||
1650	    !BN_mod_exp(W, pubkey->bn[DSA_Y].bn, W, pubkey->bn[DSA_P].bn, NULL) ||
1651	    !BN_mod_mul(t1, t1, W, pubkey->bn[DSA_P].bn, NULL) ||
1652	    !BN_div(NULL, t1, t1, pubkey->bn[DSA_Q].bn, NULL)) {
1653		goto done;
1654	}
1655	/* only compare the first q bits */
1656	BN_bn2bin(t1, calcnum);
1657	BN_bn2bin(sig[DSA_R].bn, signum);
1658	ret = memcmp(calcnum, signum, BITS_TO_BYTES(qbits)) == 0;
1659done:
1660	if (M) {
1661		BN_free(M);
1662	}
1663	if (W) {
1664		BN_free(W);
1665	}
1666	if (t1) {
1667		BN_free(t1);
1668	}
1669	return ret;
1670}
1671
1672#define TIME_SNPRINTF(_cc, _buf, _size, _fmt, _val)	do {		\
1673	time_t	 _t;							\
1674	char	*_s;							\
1675									\
1676	_t = _val;							\
1677	_s = ctime(&_t);						\
1678	_cc += snprintf(_buf, _size, _fmt, _s);				\
1679} while(/*CONSTCOND*/0)
1680
1681/* check dates on signature and key are valid */
1682static size_t
1683valid_dates(pgpv_signature_t *signature, pgpv_pubkey_t *pubkey, char *buf, size_t size)
1684{
1685	time_t	 now;
1686	time_t	 t;
1687	size_t	 cc;
1688
1689	cc = 0;
1690	if (signature->birth < pubkey->birth) {
1691		TIME_SNPRINTF(cc, buf, size, "Signature time (%.24s) was before pubkey creation ", signature->birth);
1692		TIME_SNPRINTF(cc, &buf[cc], size - cc, "(%s)\n", pubkey->birth);
1693		return cc;
1694	}
1695	now = time(NULL);
1696	if (signature->expiry != 0) {
1697		if ((t = signature->birth + signature->expiry) < now) {
1698			TIME_SNPRINTF(cc, buf, size, "Signature expired on %.24s\n", t);
1699			return cc;
1700		}
1701	}
1702	if (now < signature->birth) {
1703		TIME_SNPRINTF(cc, buf, size, "Signature not valid before %.24s\n", signature->birth);
1704		return cc;
1705	}
1706	return 0;
1707}
1708
1709/* check if the signing key has expired */
1710static int
1711key_expired(pgpv_pubkey_t *pubkey, char *buf, size_t size)
1712{
1713	time_t	 now;
1714	time_t	 t;
1715	size_t	 cc;
1716
1717	now = time(NULL);
1718	cc = 0;
1719	if (pubkey->expiry != 0) {
1720		if ((t = pubkey->birth + pubkey->expiry) < now) {
1721			TIME_SNPRINTF(cc, buf, size, "Pubkey expired on %.24s\n", t);
1722			return (int)cc;
1723		}
1724	}
1725	if (now < pubkey->birth) {
1726		TIME_SNPRINTF(cc, buf, size, "Pubkey not valid before %.24s\n", pubkey->birth);
1727		return (int)cc;
1728	}
1729	return 0;
1730}
1731
1732/* find the leading onepass packet */
1733static size_t
1734find_onepass(pgpv_cursor_t *cursor, size_t datastart)
1735{
1736	size_t	pkt;
1737
1738	for (pkt = datastart ; pkt < ARRAY_COUNT(cursor->pgp->pkts) ; pkt++) {
1739		if (ARRAY_ELEMENT(cursor->pgp->pkts, pkt).tag == ONEPASS_SIGNATURE_PKT) {
1740			return pkt + 1;
1741		}
1742	}
1743	snprintf(cursor->why, sizeof(cursor->why), "No signature to verify");
1744	return 0;
1745}
1746
1747static const char	*armor_begins[] = {
1748	"-----BEGIN PGP SIGNED MESSAGE-----\n",
1749	"-----BEGIN PGP MESSAGE-----\n",
1750	NULL
1751};
1752
1753/* return non-zero if the buf introduces an armored message */
1754static int
1755is_armored(const char *buf, size_t size)
1756{
1757	const char	**arm;
1758	const char	 *nl;
1759	size_t		  n;
1760
1761	if ((nl = memchr(buf, '\n', size)) == NULL) {
1762		return 0;
1763	}
1764	n = (size_t)(nl - buf);
1765	for (arm = armor_begins ; *arm ; arm++) {
1766		if (strncmp(buf, *arm, n) == 0) {
1767			return 1;
1768		}
1769	}
1770	return 0;
1771}
1772
1773#define SIGSTART	"-----BEGIN PGP SIGNATURE-----\n"
1774#define SIGEND		"-----END PGP SIGNATURE-----\n"
1775
1776/* for ascii armor, we don't get a onepass packet - make one */
1777static const char 	*cons_onepass = "\304\015\003\0\0\0\0\377\377\377\377\377\377\377\377\1";
1778
1779/* read ascii armor */
1780static int
1781read_ascii_armor(pgpv_cursor_t *cursor, pgpv_mem_t *mem, const char *filename)
1782{
1783	pgpv_onepass_t	*onepass;
1784	pgpv_sigpkt_t	*sigpkt;
1785	pgpv_pkt_t	 litdata;
1786	uint8_t		 binsig[8192];
1787	uint8_t		*datastart;
1788	uint8_t		*sigend;
1789	uint8_t		*p;
1790	size_t		 binsigsize;
1791
1792	/* cons up litdata pkt */
1793	memset(&litdata, 0x0, sizeof(litdata));
1794	litdata.u.litdata.mem = ARRAY_COUNT(cursor->pgp->areas) - 1;
1795	p = mem->mem;
1796	/* jump over signed message line */
1797	if ((p = memmem(mem->mem, mem->size, "\n\n",  2)) == NULL) {
1798		snprintf(cursor->why, sizeof(cursor->why), "malformed armor at offset 0");
1799		return 0;
1800	}
1801	p += 2;
1802	litdata.tag = LITDATA_PKT;
1803	litdata.s.data = p;
1804	litdata.u.litdata.offset = (size_t)(p - mem->mem);
1805	litdata.u.litdata.filename = (uint8_t *)strdup(filename);
1806	if ((p = memmem(datastart = p, mem->size - litdata.offset, SIGSTART, strlen(SIGSTART))) == NULL) {
1807		snprintf(cursor->why, sizeof(cursor->why),
1808			"malformed armor - no sig - at %zu", (size_t)(p - mem->mem));
1809		return 0;
1810	}
1811	litdata.u.litdata.len = litdata.s.size = (size_t)(p - datastart);
1812	p += strlen(SIGSTART);
1813	if ((p = memmem(p, mem->size, "\n\n",  2)) == NULL) {
1814		snprintf(cursor->why, sizeof(cursor->why),
1815			"malformed armed signature at %zu", (size_t)(p - mem->mem));
1816		return 0;
1817	}
1818	p += 2;
1819	sigend = memmem(p, mem->size, SIGEND, strlen(SIGEND));
1820	binsigsize = b64decode((char *)p, (size_t)(sigend - p), binsig, sizeof(binsig));
1821
1822	read_binary_memory(cursor->pgp, "signature", cons_onepass, 15);
1823	ARRAY_APPEND(cursor->pgp->pkts, litdata);
1824	read_binary_memory(cursor->pgp, "signature", binsig, binsigsize - 3);
1825	/* XXX - hardwired - 3 is format and length */
1826
1827	/* fix up packets in the packet array now we have them there */
1828	onepass = &ARRAY_ELEMENT(cursor->pgp->pkts, ARRAY_COUNT(cursor->pgp->pkts) - 1 - 2).u.onepass;
1829	sigpkt = &ARRAY_LAST(cursor->pgp->pkts).u.sigpkt;
1830	memcpy(onepass->keyid, sigpkt->sig.signer, sizeof(onepass->keyid));
1831	onepass->hashalg = sigpkt->sig.hashalg;
1832	onepass->keyalg = sigpkt->sig.keyalg;
1833	return 1;
1834}
1835
1836/* read ascii armor from a file */
1837static int
1838read_ascii_armor_file(pgpv_cursor_t *cursor, const char *filename)
1839{
1840	/* cons up litdata pkt */
1841	read_file(cursor->pgp, filename);
1842	return read_ascii_armor(cursor, &ARRAY_LAST(cursor->pgp->areas), filename);
1843}
1844
1845/* read ascii armor from memory */
1846static int
1847read_ascii_armor_memory(pgpv_cursor_t *cursor, const void *p, size_t size)
1848{
1849	pgpv_mem_t	*mem;
1850
1851	/* cons up litdata pkt */
1852	ARRAY_EXPAND(cursor->pgp->areas);
1853	ARRAY_COUNT(cursor->pgp->areas) += 1;
1854	mem = &ARRAY_LAST(cursor->pgp->areas);
1855	memset(mem, 0x0, sizeof(*mem));
1856	mem->size = size;
1857	mem->mem = __UNCONST(p);
1858	mem->dealloc = 0;
1859	return read_ascii_armor(cursor, mem, "[stdin]");
1860}
1861
1862/* set up the data to verify */
1863static int
1864setup_data(pgpv_cursor_t *cursor, pgpv_t *pgp, const void *p, ssize_t size)
1865{
1866	FILE		*fp;
1867	char		 buf[BUFSIZ];
1868
1869	if (cursor == NULL || pgp == NULL || p == NULL) {
1870		return 0;
1871	}
1872	memset(cursor, 0x0, sizeof(*cursor));
1873	ARRAY_APPEND(pgp->datastarts, pgp->pkt);
1874	cursor->pgp = pgp;
1875	if (size < 0) {
1876		/* we have a file name in p */
1877		if ((fp = fopen(p, "r")) == NULL) {
1878			snprintf(cursor->why, sizeof(cursor->why), "No such file '%s'", (const char *)p);
1879			return 0;
1880		}
1881		if (fgets(buf, (int)sizeof(buf), fp) == NULL) {
1882			fclose(fp);
1883			snprintf(cursor->why, sizeof(cursor->why), "can't read file '%s'", (const char *)p);
1884			return 0;
1885		}
1886		if (is_armored(buf, sizeof(buf))) {
1887			read_ascii_armor_file(cursor, p);
1888		} else {
1889			read_binary_file(pgp, "signature", "%s", (const char *)p);
1890		}
1891		fclose(fp);
1892	} else {
1893		if (is_armored(p, (size_t)size)) {
1894			read_ascii_armor_memory(cursor, p, (size_t)size);
1895		} else {
1896			read_binary_memory(pgp, "signature", p, (size_t)size);
1897		}
1898	}
1899	return 1;
1900}
1901
1902/* get the data and size from litdata packet */
1903static uint8_t *
1904get_literal_data(pgpv_cursor_t *cursor, pgpv_litdata_t *litdata, size_t *size)
1905{
1906	pgpv_mem_t	*mem;
1907
1908	if (litdata->s.data == NULL && litdata->s.size == 0) {
1909		mem = &ARRAY_ELEMENT(cursor->pgp->areas, litdata->mem);
1910		*size = litdata->len;
1911		return &mem->mem[litdata->offset];
1912	}
1913	*size = litdata->s.size;
1914	return litdata->s.data;
1915}
1916
1917/*
1918RFC 4880 describes the structure of v4 keys as:
1919
1920           Primary-Key
1921              [Revocation Self Signature]
1922              [Direct Key Signature...]
1923               User ID [Signature ...]
1924              [User ID [Signature ...] ...]
1925              [User Attribute [Signature ...] ...]
1926              [[Subkey [Binding-Signature-Revocation]
1927                      Primary-Key-Binding-Signature] ...]
1928
1929and that's implemented below as a recursive descent parser.
1930It has had to be modified, though: see the comment
1931
1932	some keys out there have user ids where they shouldn't
1933
1934to look like:
1935
1936           Primary-Key
1937              [Revocation Self Signature]
1938              [Direct Key Signature...]
1939              [User ID [Signature ...]
1940                 [User ID [Signature ...] ...]
1941                 [User Attribute [Signature ...] ...]
1942                 [Subkey [Binding-Signature-Revocation]
1943                        Primary-Key-Binding-Signature] ...]
1944
1945to accommodate keyrings set up by gpg
1946*/
1947
1948/* recognise a primary key */
1949static int
1950recog_primary_key(pgpv_t *pgp, pgpv_primarykey_t *primary)
1951{
1952	pgpv_signed_userattr_t	 userattr;
1953	pgpv_signed_userid_t	 userid;
1954	pgpv_signed_subkey_t	 subkey;
1955	pgpv_signature_t	 signature;
1956	pgpv_pkt_t		*pkt;
1957
1958	pkt = &ARRAY_ELEMENT(pgp->pkts, pgp->pkt);
1959	memset(primary, 0x0, sizeof(*primary));
1960	read_pubkey(&primary->primary, pkt->s.data, pkt->s.size, 0);
1961	pgp->pkt += 1;
1962	if (pkt_sigtype_is(pgp, SIGTYPE_KEY_REVOCATION)) {
1963		if (!recog_signature(pgp, &primary->revoc_self_sig)) {
1964			printf("recog_primary_key: no signature/trust at PGPV_SIGTYPE_KEY_REVOCATION\n");
1965			return 0;
1966		}
1967	}
1968	while (pkt_sigtype_is(pgp, SIGTYPE_DIRECT_KEY)) {
1969		if (!recog_signature(pgp, &signature)) {
1970			printf("recog_primary_key: no signature/trust at PGPV_SIGTYPE_DIRECT_KEY\n");
1971			return 0;
1972		}
1973		if (signature.keyexpiry) {
1974			/* XXX - check it's a good key expiry */
1975			primary->primary.expiry = signature.keyexpiry;
1976		}
1977		ARRAY_APPEND(primary->direct_sigs, signature);
1978	}
1979	/* some keys out there have user ids where they shouldn't */
1980	do {
1981		if (!recog_userid(pgp, &userid)) {
1982			printf("recog_primary_key: not userid\n");
1983			return 0;
1984		}
1985		ARRAY_APPEND(primary->signed_userids, userid);
1986		if (userid.primary_userid) {
1987			primary->primary_userid = ARRAY_COUNT(primary->signed_userids) - 1;
1988		}
1989		while (pkt_is(pgp, USERID_PKT)) {
1990			if (!recog_userid(pgp, &userid)) {
1991				printf("recog_primary_key: not signed secondary userid\n");
1992				return 0;
1993			}
1994			ARRAY_APPEND(primary->signed_userids, userid);
1995			if (userid.primary_userid) {
1996				primary->primary_userid = ARRAY_COUNT(primary->signed_userids) - 1;
1997			}
1998		}
1999		while (pkt_is(pgp, USER_ATTRIBUTE_PKT)) {
2000			if (!recog_userattr(pgp, &userattr)) {
2001				printf("recog_primary_key: not signed user attribute\n");
2002				return 0;
2003			}
2004			ARRAY_APPEND(primary->signed_userattrs, userattr);
2005		}
2006		while (pkt_is(pgp, PUB_SUBKEY_PKT)) {
2007			if (!recog_subkey(pgp, &subkey)) {
2008				printf("recog_primary_key: not signed public subkey\n");
2009				return 0;
2010			}
2011			pgpv_calc_keyid(&subkey.subkey);
2012			ARRAY_APPEND(primary->signed_subkeys, subkey);
2013		}
2014	} while (pgp->pkt < ARRAY_COUNT(pgp->pkts) && pkt_is(pgp, USERID_PKT));
2015	primary->fmtsize = estimate_primarykey_size(primary);
2016	return 1;
2017}
2018
2019/* parse all of the packets for a given operation */
2020static int
2021read_all_packets(pgpv_t *pgp, pgpv_mem_t *mem, const char *op)
2022{
2023	pgpv_primarykey_t	 primary;
2024
2025	if (op == NULL) {
2026		return 0;
2027	}
2028	if (strcmp(pgp->op = op, "pubring") == 0) {
2029		mem->allowed = PUBRING_ALLOWED;
2030		/* pubrings have thousands of small packets */
2031		ARRAY_EXPAND_SIZED(pgp->pkts, 0, 5000);
2032	} else if (strcmp(op, "signature") == 0) {
2033		mem->allowed = SIGNATURE_ALLOWED;
2034	} else {
2035		mem->allowed = "";
2036	}
2037	for (mem->cc = 0; mem->cc < mem->size ; ) {
2038		if (!read_pkt(pgp, mem)) {
2039			return 0;
2040		}
2041	}
2042	if (strcmp(op, "pubring") == 0) {
2043		for (pgp->pkt = 0; pgp->pkt < ARRAY_COUNT(pgp->pkts) && recog_primary_key(pgp, &primary) ; ) {
2044			pgpv_calc_keyid(&primary.primary);
2045			ARRAY_APPEND(pgp->primaries, primary);
2046		}
2047		if (pgp->pkt < ARRAY_COUNT(pgp->pkts)) {
2048			printf("short pubring recognition???\n");
2049		}
2050	}
2051	pgp->pkt = ARRAY_COUNT(pgp->pkts);
2052	return 1;
2053}
2054
2055/* create a filename, read it, and then parse according to "op" */
2056static int
2057read_binary_file(pgpv_t *pgp, const char *op, const char *fmt, ...)
2058{
2059	va_list	args;
2060	char	buf[1024];
2061
2062	va_start(args, fmt);
2063	vsnprintf(buf, sizeof(buf), fmt, args);
2064	va_end(args);
2065	if (!read_file(pgp, buf)) {
2066		return 0;
2067	}
2068	return read_all_packets(pgp, &ARRAY_LAST(pgp->areas), op);
2069}
2070
2071/* parse memory according to "op" */
2072static int
2073read_binary_memory(pgpv_t *pgp, const char *op, const void *memory, size_t size)
2074{
2075	pgpv_mem_t	*mem;
2076
2077	ARRAY_EXPAND(pgp->areas);
2078	ARRAY_COUNT(pgp->areas) += 1;
2079	mem = &ARRAY_LAST(pgp->areas);
2080	memset(mem, 0x0, sizeof(*mem));
2081	mem->size = size;
2082	mem->mem = __UNCONST(memory);
2083	mem->dealloc = 0;
2084	return read_all_packets(pgp, mem, op);
2085}
2086
2087/* fixup the detached signature packets */
2088static int
2089fixup_detached(pgpv_cursor_t *cursor, const char *f)
2090{
2091	pgpv_onepass_t	*onepass;
2092	const char	*dot;
2093	pgpv_pkt_t	 sigpkt;
2094	pgpv_pkt_t	 litdata;
2095	pgpv_mem_t	*mem;
2096	size_t		 el;
2097	char		 original[MAXPATHLEN];
2098
2099	/* cons up litdata pkt */
2100	if ((dot = strrchr(f, '.')) == NULL || strcasecmp(dot, ".sig") != 0) {
2101		printf("weird filename '%s'\n", f);
2102		return 0;
2103	}
2104	/* hold sigpkt in a temp var while we insert onepass and litdata */
2105	el = ARRAY_COUNT(cursor->pgp->pkts) - 1;
2106	sigpkt = ARRAY_ELEMENT(cursor->pgp->pkts, el);
2107	ARRAY_DELETE(cursor->pgp->pkts, el);
2108	ARRAY_EXPAND(cursor->pgp->pkts);
2109	/* get onepass packet, append to packets */
2110	read_binary_memory(cursor->pgp, "signature", cons_onepass, 15);
2111	onepass = &ARRAY_ELEMENT(cursor->pgp->pkts, el).u.onepass;
2112	/* read the original file into litdata */
2113	snprintf(original, sizeof(original), "%.*s", (int)(dot - f), f);
2114	if (!read_file(cursor->pgp, original)) {
2115		printf("can't read file '%s'\n", original);
2116		return 0;
2117	}
2118	memset(&litdata, 0x0, sizeof(litdata));
2119	mem = &ARRAY_LAST(cursor->pgp->areas);
2120	litdata.tag = LITDATA_PKT;
2121	litdata.s.data = mem->mem;
2122	litdata.u.litdata.format = LITDATA_BINARY;
2123	litdata.u.litdata.offset = 0;
2124	litdata.u.litdata.filename = (uint8_t *)strdup(original);
2125	litdata.u.litdata.mem = ARRAY_COUNT(cursor->pgp->areas) - 1;
2126	litdata.u.litdata.len = litdata.s.size = mem->size;
2127	ARRAY_APPEND(cursor->pgp->pkts, litdata);
2128	ARRAY_APPEND(cursor->pgp->pkts, sigpkt);
2129	memcpy(onepass->keyid, sigpkt.u.sigpkt.sig.signer, sizeof(onepass->keyid));
2130	onepass->hashalg = sigpkt.u.sigpkt.sig.hashalg;
2131	onepass->keyalg = sigpkt.u.sigpkt.sig.keyalg;
2132	return 1;
2133}
2134
2135/* match the calculated signature against the oen in the signature packet */
2136static int
2137match_sig(pgpv_cursor_t *cursor, pgpv_signature_t *signature, pgpv_pubkey_t *pubkey, uint8_t *data, size_t size)
2138{
2139	unsigned	calclen;
2140	uint8_t		calculated[64];
2141	int		match;
2142
2143	calclen = pgpv_digest_memory(calculated, sizeof(calculated),
2144		data, size,
2145		get_ref(&signature->hashstart), signature->hashlen,
2146		(signature->type == SIGTYPE_TEXT) ? 't' : 'b');
2147	if (ALG_IS_RSA(signature->keyalg)) {
2148		match = rsa_verify(calculated, calclen, signature->hashalg, signature->bn, pubkey);
2149	} else if (ALG_IS_DSA(signature->keyalg)) {
2150		match = verify_dsa_sig(calculated, calclen, signature->bn, pubkey);
2151	} else {
2152		snprintf(cursor->why, sizeof(cursor->why), "Signature type %u not recognised", signature->keyalg);
2153		return 0;
2154	}
2155	if (!match && signature->type == SIGTYPE_TEXT) {
2156		/* second try for cleartext data, ignoring trailing whitespace */
2157		calclen = pgpv_digest_memory(calculated, sizeof(calculated),
2158			data, size,
2159			get_ref(&signature->hashstart), signature->hashlen, 'w');
2160		if (ALG_IS_RSA(signature->keyalg)) {
2161			match = rsa_verify(calculated, calclen, signature->hashalg, signature->bn, pubkey);
2162		} else if (ALG_IS_DSA(signature->keyalg)) {
2163			match = verify_dsa_sig(calculated, calclen, signature->bn, pubkey);
2164		}
2165	}
2166	if (!match) {
2167		snprintf(cursor->why, sizeof(cursor->why), "Signature on data did not match");
2168		return 0;
2169	}
2170	if (valid_dates(signature, pubkey, cursor->why, sizeof(cursor->why)) > 0) {
2171		return 0;
2172	}
2173	if (key_expired(pubkey, cursor->why, sizeof(cursor->why))) {
2174		return 0;
2175	}
2176	if (signature->revoked) {
2177		snprintf(cursor->why, sizeof(cursor->why), "Signature was revoked");
2178		return 0;
2179	}
2180	return 1;
2181}
2182
2183/* check return value from getenv */
2184static const char *
2185nonnull_getenv(const char *key)
2186{
2187	char	*value;
2188
2189	return ((value = getenv(key)) == NULL) ? "" : value;
2190}
2191
2192/************************************************************************/
2193/* start of exported functions */
2194/************************************************************************/
2195
2196/* close all stuff */
2197int
2198pgpv_close(pgpv_t *pgp)
2199{
2200	unsigned	i;
2201
2202	if (pgp == NULL) {
2203		return 0;
2204	}
2205	for (i = 0 ; i < ARRAY_COUNT(pgp->areas) ; i++) {
2206		if (ARRAY_ELEMENT(pgp->areas, i).size > 0) {
2207			closemem(&ARRAY_ELEMENT(pgp->areas, i));
2208		}
2209	}
2210	return 1;
2211}
2212
2213/* return the formatted entry for the primary key desired */
2214size_t
2215pgpv_get_entry(pgpv_t *pgp, unsigned ent, char **ret)
2216{
2217	size_t	cc;
2218
2219	if (ret == NULL || pgp == NULL || ent >= ARRAY_COUNT(pgp->primaries)) {
2220		return 0;
2221	}
2222	*ret = NULL;
2223	cc = ARRAY_ELEMENT(pgp->primaries, ent).fmtsize;
2224	if ((*ret = calloc(1, cc)) == NULL) {
2225		return 0;
2226	}
2227	return fmt_primary(*ret, cc, &ARRAY_ELEMENT(pgp->primaries, ent));
2228}
2229
2230/* find key id */
2231int
2232pgpv_find_keyid(pgpv_t *pgp, const char *strkeyid, uint8_t *keyid)
2233{
2234	unsigned	 i;
2235	uint8_t		 binkeyid[PGPV_KEYID_LEN];
2236	size_t		 off;
2237	size_t		 cmp;
2238
2239	if (strkeyid == NULL && keyid == NULL) {
2240		return 0;
2241	}
2242	if (strkeyid) {
2243		str_to_keyid(strkeyid, binkeyid);
2244		cmp = strlen(strkeyid) / 2;
2245	} else {
2246		memcpy(binkeyid, keyid, sizeof(binkeyid));
2247		cmp = PGPV_KEYID_LEN;
2248	}
2249	off = PGPV_KEYID_LEN - cmp;
2250	for (i = 0 ; i < ARRAY_COUNT(pgp->primaries) ; i++) {
2251		if (memcmp(&ARRAY_ELEMENT(pgp->primaries, i).primary.keyid[off], &binkeyid[off], cmp) == 0) {
2252			return i;
2253		}
2254	}
2255	return -1;
2256}
2257
2258/* verify the signed packets we have */
2259size_t
2260pgpv_verify(pgpv_cursor_t *cursor, pgpv_t *pgp, const void *p, ssize_t size)
2261{
2262	pgpv_signature_t	*signature;
2263	pgpv_onepass_t		*onepass;
2264	pgpv_litdata_t		*litdata;
2265	pgpv_pubkey_t		*pubkey;
2266	unsigned		 primary;
2267	uint8_t			*data;
2268	size_t			 pkt;
2269	size_t			 insize;
2270	char			 strkeyid[PGPV_STR_KEYID_LEN];
2271	int			 j;
2272
2273	if (cursor == NULL || pgp == NULL || p == NULL) {
2274		return 0;
2275	}
2276	if (!setup_data(cursor, pgp, p, size)) {
2277		snprintf(cursor->why, sizeof(cursor->why), "No input data");
2278		return 0;
2279	}
2280	if (ARRAY_COUNT(cursor->pgp->pkts) == ARRAY_LAST(cursor->pgp->datastarts) + 1) {
2281		/* got detached signature here */
2282		if (!fixup_detached(cursor, p)) {
2283			snprintf(cursor->why, sizeof(cursor->why), "Can't read signed file '%s'", (const char *)p);
2284			return 0;
2285		}
2286	}
2287	if ((pkt = find_onepass(cursor, ARRAY_LAST(cursor->pgp->datastarts))) == 0) {
2288		snprintf(cursor->why, sizeof(cursor->why), "No signature found");
2289		return 0;
2290	}
2291	pkt -= 1;
2292	onepass = &ARRAY_ELEMENT(cursor->pgp->pkts, pkt).u.onepass;
2293	litdata = &ARRAY_ELEMENT(cursor->pgp->pkts, pkt + 1).u.litdata;
2294	signature = &ARRAY_ELEMENT(cursor->pgp->pkts, pkt + 2).u.sigpkt.sig;
2295	/* sanity check values in signature and onepass agree */
2296	if (signature->birth == 0) {
2297		fmt_time(cursor->why, sizeof(cursor->why), "Signature creation time [",
2298			signature->birth, "] out of range", 0);
2299		return 0;
2300	}
2301	if (memcmp(onepass->keyid, signature->signer, PGPV_KEYID_LEN) != 0) {
2302		fmt_binary(strkeyid, sizeof(strkeyid), onepass->keyid, (unsigned)sizeof(onepass->keyid));
2303		snprintf(cursor->why, sizeof(cursor->why), "Signature key id %s does not match onepass keyid",
2304			strkeyid);
2305		return 0;
2306	}
2307	if (onepass->hashalg != signature->hashalg) {
2308		snprintf(cursor->why, sizeof(cursor->why), "Signature hashalg %u does not match onepass hashalg %u",
2309			signature->hashalg, onepass->hashalg);
2310		return 0;
2311	}
2312	if (onepass->keyalg != signature->keyalg) {
2313		snprintf(cursor->why, sizeof(cursor->why), "Signature keyalg %u does not match onepass keyalg %u",
2314			signature->keyalg, onepass->keyalg);
2315		return 0;
2316	}
2317	if ((j = pgpv_find_keyid(cursor->pgp, NULL, onepass->keyid)) < 0) {
2318		fmt_binary(strkeyid, sizeof(strkeyid), onepass->keyid, (unsigned)sizeof(onepass->keyid));
2319		snprintf(cursor->why, sizeof(cursor->why), "Signature key id %s not found ", strkeyid);
2320		return 0;
2321	}
2322	primary = (unsigned)j;
2323	pubkey = &ARRAY_ELEMENT(cursor->pgp->primaries, primary).primary;
2324	cursor->sigtime = signature->birth;
2325	/* calc hash on data packet */
2326	data = get_literal_data(cursor, litdata, &insize);
2327	if (!match_sig(cursor, signature, pubkey, data, insize)) {
2328		return 0;
2329	}
2330	ARRAY_APPEND(cursor->datacookies, pkt);
2331	ARRAY_APPEND(cursor->found, primary);
2332	return pkt + 1;
2333}
2334
2335/* set up the pubkey keyring */
2336int
2337pgpv_read_pubring(pgpv_t *pgp, const void *keyring, ssize_t size)
2338{
2339	if (pgp == NULL) {
2340		return 0;
2341	}
2342	if (keyring) {
2343		return (size > 0) ?
2344			read_binary_memory(pgp, "pubring", keyring, (size_t)size) :
2345			read_binary_file(pgp, "pubring", "%s", (const char *)keyring);
2346	}
2347	return read_binary_file(pgp, "pubring", "%s/%s", nonnull_getenv("HOME"), ".gnupg/pubring.gpg");
2348}
2349
2350/* get verified data as a string, return its size */
2351size_t
2352pgpv_get_verified(pgpv_cursor_t *cursor, size_t cookie, char **ret)
2353{
2354	pgpv_litdata_t		*litdata;
2355	uint8_t			*data;
2356	size_t			 size;
2357	size_t			 pkt;
2358
2359	if (ret == NULL || cursor == NULL || cookie == 0) {
2360		return 0;
2361	}
2362	*ret = NULL;
2363	if ((pkt = find_onepass(cursor, cookie - 1)) == 0) {
2364		return 0;
2365	}
2366	litdata = &ARRAY_ELEMENT(cursor->pgp->pkts, pkt).u.litdata;
2367	data = get_literal_data(cursor, litdata, &size);
2368	if ((*ret = calloc(1, size)) == NULL) {
2369		return 0;
2370	}
2371	memcpy(*ret, data, size);
2372	return size;
2373}
2374