xref: /netbsd-src/crypto/external/bsd/netpgp/dist/src/netpgpverify/libverify.c (revision 8ecbf5f02b752fcb7debe1a8fab1dc82602bc760)
1 /*-
2  * Copyright (c) 2012,2013,2014,2015,2016 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 "config.h"
26 
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <sys/param.h>
30 #include <sys/mman.h>
31 
32 #include <arpa/inet.h>
33 
34 #include <inttypes.h>
35 #include <limits.h>
36 #include <stdarg.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <time.h>
41 #include <unistd.h>
42 
43 #include "bzlib.h"
44 #include "zlib.h"
45 
46 #include "array.h"
47 #include "b64.h"
48 #include "bn.h"
49 #include "bufgap.h"
50 #include "digest.h"
51 #include "misc.h"
52 #include "pgpsum.h"
53 #include "rsa.h"
54 #include "verify.h"
55 
56 #ifndef PRIi64
57 #define PRIi64	"lld"
58 #endif
59 
60 /* 64bit key ids */
61 #define PGPV_KEYID_LEN		8
62 #define PGPV_STR_KEYID_LEN	(PGPV_KEYID_LEN + PGPV_KEYID_LEN + 1)
63 
64 /* bignum structure */
65 typedef struct pgpv_bignum_t {
66 	void			*bn;	/* hide the implementation details */
67 	uint16_t		 bits;	/* cached number of bits */
68 } pgpv_bignum_t;
69 
70 /* right now, our max binary digest length is 20 bytes */
71 #define PGPV_MAX_HASH_LEN	64
72 
73 /* fingerprint */
74 typedef struct pgpv_fingerprint_t {
75 	uint8_t			hashalg;	/* algorithm for digest */
76 	uint8_t			v[PGPV_MAX_HASH_LEN];	/* the digest */
77 	uint32_t		len;		/* its length */
78 } pgpv_fingerprint_t;
79 
80 /* specify size for array of bignums */
81 #define PGPV_MAX_PUBKEY_BN	4
82 
83 /* public key */
84 typedef struct pgpv_pubkey_t {
85 	pgpv_fingerprint_t	 fingerprint;	/* key fingerprint i.e. digest */
86 	uint8_t			 keyid[PGPV_KEYID_LEN];	/* last 8 bytes of v4 keys */
87 	int64_t		 	 birth;		/* creation time */
88 	int64_t			 expiry;	/* expiry time */
89 	pgpv_bignum_t		 bn[PGPV_MAX_PUBKEY_BN]; /* bignums */
90 	uint8_t			 keyalg;	/* key algorithm */
91 	uint8_t			 hashalg;	/* hash algorithm */
92 	uint8_t			 version;	/* key version */
93 } pgpv_pubkey_t;
94 
95 #define PGPV_MAX_SESSKEY_BN	2
96 
97 /* a (size, byte array) string */
98 typedef struct pgpv_string_t {
99 	size_t			 size;
100 	uint8_t			*data;
101 	uint8_t			 allocated;
102 } pgpv_string_t;
103 
104 typedef struct pgpv_ref_t {
105 	void			*vp;
106 	size_t			 offset;
107 	unsigned		 mem;
108 } pgpv_ref_t;
109 
110 #define PGPV_MAX_SECKEY_BN	4
111 
112 typedef struct pgpv_compress_t {
113 	pgpv_string_t		 s;
114 	uint8_t			 compalg;
115 } pgpv_compress_t;
116 
117 /* a packet dealing with trust */
118 typedef struct pgpv_trust_t {
119 	uint8_t			level;
120 	uint8_t			amount;
121 } pgpv_trust_t;
122 
123 /* a signature sub packet */
124 typedef struct pgpv_sigsubpkt_t {
125 	pgpv_string_t		 s;
126 	uint8_t			 tag;
127 	uint8_t			 critical;
128 } pgpv_sigsubpkt_t;
129 
130 #define PGPV_MAX_SIG_BN		2
131 
132 typedef struct pgpv_signature_t {
133 	uint8_t			 signer[PGPV_KEYID_LEN]; /* key id of signer */
134 	pgpv_ref_t		 hashstart;
135 	uint8_t			*hash2;
136 	uint8_t			*mpi;
137 	int64_t			 birth;
138 	int64_t			 keyexpiry;
139 	int64_t			 expiry;
140 	uint32_t		 hashlen;
141 	uint8_t			 version;
142 	uint8_t			 type;
143 	uint8_t			 keyalg;
144 	uint8_t			 hashalg;
145 	uint8_t			 trustlevel;
146 	uint8_t			 trustamount;
147 	pgpv_bignum_t		 bn[PGPV_MAX_SIG_BN];
148 	char			*regexp;
149 	char			*pref_key_server;
150 	char			*policy;
151 	char			*features;
152 	char			*why_revoked;
153 	uint8_t			*revoke_fingerprint;
154 	uint8_t			 revoke_alg;
155 	uint8_t			 revoke_sensitive;
156 	uint8_t			 trustsig;
157 	uint8_t			 revocable;
158 	uint8_t			 pref_symm_alg;
159 	uint8_t			 pref_hash_alg;
160 	uint8_t			 pref_compress_alg;
161 	uint8_t			 key_server_modify;
162 	uint8_t			 notation;
163 	uint8_t			 type_key;
164 	uint8_t			 primary_userid;
165 	uint8_t			 revoked;	/* subtract 1 to get real reason, 0 == not revoked */
166 } pgpv_signature_t;
167 
168 /* a signature packet */
169 typedef struct pgpv_sigpkt_t {
170 	pgpv_signature_t	 sig;
171 	uint16_t		 subslen;
172 	uint16_t		 unhashlen;
173 	ARRAY(uint64_t,	 	 subpackets);
174 } pgpv_sigpkt_t;
175 
176 /* a one-pass signature packet */
177 typedef struct pgpv_onepass_t {
178 	uint8_t			 keyid[PGPV_KEYID_LEN];
179 	uint8_t			 version;
180 	uint8_t			 type;
181 	uint8_t			 hashalg;
182 	uint8_t			 keyalg;
183 	uint8_t			 nested;
184 } pgpv_onepass_t;
185 
186 /* a literal data packet */
187 typedef struct pgpv_litdata_t {
188 	pgpv_string_t		 filename;
189 	pgpv_string_t		 s;
190 	uint32_t		 secs;
191 	uint8_t			 namelen;
192 	char			 format;
193 	unsigned		 mem;
194 	size_t			 offset;
195 	size_t			 len;
196 } pgpv_litdata_t;
197 
198 /* user attributes - images */
199 typedef struct pgpv_userattr_t {
200 	size_t 			 len;
201 	ARRAY(pgpv_string_t, 	 subattrs);
202 } pgpv_userattr_t;
203 
204 /* a general PGP packet */
205 typedef struct pgpv_pkt_t {
206 	uint8_t			 tag;
207 	uint8_t			 newfmt;
208 	uint8_t			 allocated;
209 	uint8_t			 mement;
210 	size_t			 offset;
211 	pgpv_string_t		 s;
212 	union {
213 		pgpv_sigpkt_t	sigpkt;
214 		pgpv_onepass_t	onepass;
215 		pgpv_litdata_t	litdata;
216 		pgpv_compress_t	compressed;
217 		pgpv_trust_t	trust;
218 		pgpv_pubkey_t	pubkey;
219 		pgpv_string_t	userid;
220 		pgpv_userattr_t	userattr;
221 	} u;
222 } pgpv_pkt_t;
223 
224 /* a memory structure */
225 typedef struct pgpv_mem_t {
226 	size_t			 size;
227 	size_t			 cc;
228 	uint8_t			*mem;
229 	FILE			*fp;
230 	uint8_t			 dealloc;
231 	const char		*allowed;	/* the types of packet that are allowed */
232 } pgpv_mem_t;
233 
234 /* packet parser */
235 
236 typedef struct pgpv_signed_userid_t {
237 	pgpv_string_t	 	 userid;
238 	ARRAY(uint64_t, 	 signatures);
239 	uint8_t			 primary_userid;
240 	uint8_t			 revoked;
241 } pgpv_signed_userid_t;
242 
243 typedef struct pgpv_signed_userattr_t {
244 	pgpv_userattr_t	 	 userattr;
245 	ARRAY(uint64_t, 	 signatures);
246 	uint8_t			 revoked;
247 } pgpv_signed_userattr_t;
248 
249 typedef struct pgpv_signed_subkey_t {
250 	pgpv_pubkey_t	 	 subkey;
251 	pgpv_signature_t 	 revoc_self_sig;
252 	ARRAY(uint64_t, 	 signatures);
253 } pgpv_signed_subkey_t;
254 
255 typedef struct pgpv_primarykey_t {
256 	pgpv_pubkey_t 		 primary;
257 	pgpv_signature_t 	 revoc_self_sig;
258 	ARRAY(uint64_t, 	 signatures);
259 	ARRAY(uint64_t, 	 signed_userids);
260 	ARRAY(uint64_t, 	 signed_userattrs);
261 	ARRAY(uint64_t, 	 signed_subkeys);
262 	size_t			 fmtsize;
263 	uint8_t			 primary_userid;
264 } pgpv_primarykey_t;
265 
266 /* everything stems from this structure */
267 struct pgpv_t {
268 	ARRAY(pgpv_pkt_t, 	 pkts);		/* packet array */
269 	ARRAY(pgpv_primarykey_t, primaries);	/* array of primary keys */
270 	ARRAY(pgpv_mem_t,	 areas);	/* areas we read packets from */
271 	ARRAY(size_t,	 	 datastarts);	/* starts of data packets */
272 	ARRAY(pgpv_signature_t,	 signatures);	/* all signatures */
273 	ARRAY(pgpv_signed_userid_t, signed_userids); /* all signed userids */
274 	ARRAY(pgpv_signed_userattr_t, signed_userattrs); /* all signed user attrs */
275 	ARRAY(pgpv_signed_subkey_t, signed_subkeys); /* all signed subkeys */
276 	ARRAY(pgpv_sigsubpkt_t,	 subpkts);	/* all sub packets */
277 	size_t		 	 pkt;		/* when parsing, current pkt number */
278 	const char		*op;		/* the operation we're doing */
279 	unsigned		 ssh;		/* using ssh keys */
280 };
281 
282 #define PGPV_REASON_LEN		128
283 
284 /* when searching, we define a cursor, and fill in an array of subscripts */
285 struct pgpv_cursor_t {
286 	pgpv_t			*pgp;			/* pointer to pgp tree */
287 	char			*field;			/* field we're searching on */
288 	char			*op;			/* operation we're doing */
289 	char			*value;			/* value we're searching for */
290 	void			*ptr;			/* for regexps etc */
291 	ARRAY(uint32_t,	 	 found);		/* array of matched pimary key subscripts */
292 	ARRAY(size_t,	 	 datacookies);		/* cookies to retrieve matched data */
293 	int64_t			 sigtime;		/* time of signature */
294 	char			 why[PGPV_REASON_LEN];	/* reason for bad signature */
295 };
296 
297 #ifndef USE_ARG
298 #define USE_ARG(x)	/*LINTED*/(void)&(x)
299 #endif
300 
301 #ifndef __dead
302 #define __dead				__attribute__((__noreturn__))
303 #endif
304 
305 #ifndef __printflike
306 #define __printflike(n, m)		__attribute__((format(printf,n,m)))
307 #endif
308 
309 #ifndef MIN
310 #define MIN(a,b)			(((a)<(b))?(a):(b))
311 #endif
312 
313 #ifndef howmany
314 #define howmany(x, y)   		(((x)+((y)-1))/(y))
315 #endif
316 
317 #define BITS_TO_BYTES(b)		(((b) + (CHAR_BIT - 1)) / CHAR_BIT)
318 
319 /* packet types */
320 #define SIGNATURE_PKT			2
321 #define ONEPASS_SIGNATURE_PKT		4
322 #define PUBKEY_PKT			6
323 #define COMPRESSED_DATA_PKT		8
324 #define MARKER_PKT			10
325 #define LITDATA_PKT			11
326 #define TRUST_PKT			12
327 #define USERID_PKT			13
328 #define PUB_SUBKEY_PKT			14
329 #define USER_ATTRIBUTE_PKT		17
330 
331 /* only allow certain packets at certain times */
332 #define PUBRING_ALLOWED			"\002\006\014\015\016\021"
333 #define SIGNATURE_ALLOWED		"\002\004\010\013"
334 
335 /* actions to do on close */
336 #define FREE_MEM			0x01
337 #define UNMAP_MEM			0x02
338 
339 /* types of pubkey we encounter */
340 #define PUBKEY_RSA_ENCRYPT_OR_SIGN	1
341 #define PUBKEY_RSA_ENCRYPT		2
342 #define PUBKEY_RSA_SIGN			3
343 #define PUBKEY_ELGAMAL_ENCRYPT		16
344 #define PUBKEY_DSA			17
345 #define PUBKEY_ECDH			18
346 #define PUBKEY_ECDSA			19
347 #define PUBKEY_ELGAMAL_ENCRYPT_OR_SIGN	20
348 
349 /* hash algorithm definitions */
350 #define PGPV_HASH_MD5			1
351 #define PGPV_HASH_SHA1			2
352 #define PGPV_HASH_RIPEMD		3
353 #define PGPV_HASH_SHA256		8
354 #define PGPV_HASH_SHA384		9
355 #define PGPV_HASH_SHA512		10
356 
357 /* pubkey defs for bignums */
358 #define RSA_N				0
359 #define RSA_E				1
360 #define DSA_P				0
361 #define DSA_Q				1
362 #define DSA_G				2
363 #define DSA_Y				3
364 #define ELGAMAL_P			0
365 #define ELGAMAL_G			1
366 #define ELGAMAL_Y			2
367 
368 /* sesskey indices */
369 #define RSA_SESSKEY_ENCRYPTED_M		0
370 #define RSA_SESSKEY_M			1
371 #define ELGAMAL_SESSKEY_G_TO_K		0
372 #define ELGAMAL_SESSKEY_ENCRYPTED_M	1
373 
374 /* seckey indices */
375 #define RSA_SECKEY_D			0
376 #define RSA_SECKEY_P			1
377 #define RSA_SECKEY_Q			2
378 #define RSA_SECKEY_U			3
379 #define DSA_SECKEY_X			0
380 #define ELGAMAL_SECKEY_X		0
381 
382 /* signature mpi indices in bignumber array */
383 #define RSA_SIG				0
384 #define DSA_R				0
385 #define DSA_S				1
386 #define ELGAMAL_SIG_R			0
387 #define ELGAMAL_SIG_S			1
388 
389 /* signature types */
390 #define SIGTYPE_BINARY_DOC		0x00	/* Signature of a binary document */
391 #define SIGTYPE_TEXT			0x01	/* Signature of a canonical text document */
392 #define SIGTYPE_STANDALONE		0x02	/* Standalone signature */
393 
394 #define SIGTYPE_GENERIC_USERID		0x10	/* Generic certification of a User ID and Public Key packet */
395 #define SIGTYPE_PERSONA_USERID		0x11	/* Persona certification of a User ID and Public Key packet */
396 #define SIGTYPE_CASUAL_USERID		0x12	/* Casual certification of a User ID and Public Key packet */
397 #define SIGTYPE_POSITIVE_USERID		0x13	/* Positive certification of a User ID and Public Key packet */
398 
399 #define SIGTYPE_SUBKEY_BINDING		0x18	/* Subkey Binding Signature */
400 #define SIGTYPE_PRIMARY_KEY_BINDING	0x19	/* Primary Key Binding Signature */
401 #define SIGTYPE_DIRECT_KEY		0x1f	/* Signature directly on a key */
402 
403 #define SIGTYPE_KEY_REVOCATION		0x20	/* Key revocation signature */
404 #define SIGTYPE_SUBKEY_REVOCATION	0x28	/* Subkey revocation signature */
405 #define SIGTYPE_CERT_REVOCATION		0x30	/* Certification revocation signature */
406 
407 #define SIGTYPE_TIMESTAMP_SIG		0x40	/* Timestamp signature */
408 #define SIGTYPE_3RDPARTY		0x50	/* Third-Party Confirmation signature */
409 
410 /* Forward declarations */
411 static int read_all_packets(pgpv_t */*pgp*/, pgpv_mem_t */*mem*/, const char */*op*/);
412 static int read_binary_file(pgpv_t */*pgp*/, const char */*op*/, const char */*fmt*/, ...) __printflike(3, 4);
413 static int read_binary_memory(pgpv_t */*pgp*/, const char */*op*/, const void */*memory*/, size_t /*size*/);
414 
415 /* output buffer structure */
416 typedef struct obuf_t {
417 	size_t	 alloc;		/* amount of memory allocated */
418 	size_t	 c;		/* # of chars used so far */
419 	uint8_t	*v;		/* array of bytes */
420 	uint32_t endian;	/* byte order of output stream */
421 } obuf_t;
422 
423 /* grow the buffer, if needed */
424 static int
425 growbuf(obuf_t *obuf, size_t cc)
426 {
427 	size_t	 newalloc;
428 	uint8_t	*newv;
429 
430 	if (obuf->c + cc > obuf->alloc) {
431 		newalloc = howmany(obuf->alloc + cc, 128) * 128;
432 		newv = realloc(obuf->v, newalloc);
433 		if (newv == NULL) {
434 			return 0;
435 		}
436 		obuf->v = newv;
437 		obuf->alloc = newalloc;
438 	}
439 	return 1;
440 }
441 
442 /* add a fixed-length area of memory */
443 static int
444 obuf_add_mem(obuf_t *obuf, const void *s, size_t len)
445 {
446 	if (obuf && s && len > 0) {
447 		if (!growbuf(obuf, len)) {
448 			return 0;
449 		}
450 		memcpy(&obuf->v[obuf->c], s, len);
451 		obuf->c += len;
452 		return 1;
453 	}
454 	return 0;
455 }
456 
457 /* read a file into the pgpv_mem_t struct */
458 static int
459 read_file(pgpv_t *pgp, const char *f)
460 {
461 	struct stat	 st;
462 	pgpv_mem_t	*mem;
463 
464 	ARRAY_EXPAND(pgp->areas);
465 	ARRAY_COUNT(pgp->areas) += 1;
466 	mem = &ARRAY_LAST(pgp->areas);
467 	memset(mem, 0x0, sizeof(*mem));
468 	if ((mem->fp = fopen(f, "r")) == NULL) {
469 		fprintf(stderr, "can't read '%s'", f);
470 		return 0;
471 	}
472 	fstat(fileno(mem->fp), &st);
473 	mem->size = (size_t)st.st_size;
474 	mem->mem = mmap(NULL, mem->size, PROT_READ, MAP_SHARED, fileno(mem->fp), 0);
475 	mem->dealloc = UNMAP_MEM;
476 	return 1;
477 }
478 
479 /* DTRT and free resources */
480 static int
481 closemem(pgpv_mem_t *mem)
482 {
483 	switch(mem->dealloc) {
484 	case FREE_MEM:
485 		free(mem->mem);
486 		mem->size = 0;
487 		break;
488 	case UNMAP_MEM:
489 		munmap(mem->mem, mem->size);
490 		fclose(mem->fp);
491 		break;
492 	}
493 	return 1;
494 }
495 
496 /* make a reference to a memory area, and its offset */
497 static void
498 make_ref(pgpv_t *pgp, uint8_t mement, pgpv_ref_t *ref)
499 {
500 	ref->mem = mement;
501 	ref->offset = ARRAY_ELEMENT(pgp->areas, ref->mem).cc;
502 	ref->vp = pgp;
503 }
504 
505 /* return the pointer we wanted originally */
506 static uint8_t *
507 get_ref(pgpv_ref_t *ref)
508 {
509 	pgpv_mem_t	*mem;
510 	pgpv_t		*pgp = (pgpv_t *)ref->vp;
511 
512 	mem = &ARRAY_ELEMENT(pgp->areas, ref->mem);
513 	return &mem->mem[ref->offset];
514 }
515 
516 #define IS_PARTIAL(x)		((x) >= 224 && (x) < 255)
517 #define DECODE_PARTIAL(x)	(1 << ((x) & 0x1f))
518 
519 #define PKT_LENGTH(m, off)						\
520 	((m[off] < 192) ? (m[off]) : 					\
521 	 (m[off] < 224) ? ((m[off] - 192) << 8) + (m[off + 1]) + 192 :	\
522 	 (m[off + 1] << 24) | ((m[off + 2]) << 16) | ((m[off + 3]) << 8)  | (m[off + 4]))
523 
524 #define PKT_LENGTH_LENGTH(m, off)					\
525 	((m[off] < 192) ? 1 : (m[off] < 224) ? 2 : 5)
526 
527 /* fix up partial body lengths, return new size */
528 static size_t
529 fixup_partials(pgpv_t *pgp, uint8_t *p, size_t totlen, size_t filesize, size_t *cc)
530 {
531 	pgpv_mem_t	*mem;
532 	size_t		 partial;
533 	size_t		 newcc;
534 
535 	if (totlen > filesize) {
536 		printf("fixup_partial: filesize %zu is less than encoded size %zu\n", filesize, totlen);
537 		return 0;
538 	}
539 	ARRAY_EXPAND(pgp->areas);
540 	ARRAY_COUNT(pgp->areas) += 1;
541 	mem = &ARRAY_LAST(pgp->areas);
542 	mem->size = totlen;
543 	if ((mem->mem = calloc(1, mem->size + 5)) == NULL) {
544 		printf("fixup_partial: can't allocate %zu length\n", totlen);
545 		return 0;
546 	}
547 	newcc = 0;
548 	mem->dealloc = FREE_MEM;
549 	for (*cc = 0 ; *cc < totlen ; newcc += partial, *cc += partial + 1) {
550 		if (IS_PARTIAL(p[*cc])) {
551 			partial = DECODE_PARTIAL(p[*cc]);
552 			memcpy(&mem->mem[newcc], &p[*cc + 1], partial);
553 		} else {
554 			partial = PKT_LENGTH(p, *cc);
555 			*cc += PKT_LENGTH_LENGTH(p, *cc);
556 			memcpy(&mem->mem[newcc], &p[*cc], partial);
557 			newcc += partial;
558 			*cc += partial;
559 			break;
560 		}
561 	}
562 	return newcc;
563 }
564 
565 /* get the weirdo packet length */
566 static size_t
567 get_pkt_len(uint8_t newfmt, uint8_t *p, size_t filesize, int isprimary)
568 {
569 	size_t	lenbytes;
570 	size_t	len;
571 
572 	if (newfmt) {
573 		if (IS_PARTIAL(*p)) {
574 			if (!isprimary) {
575 				/* for sub-packets, only 1, 2 or 4 byte sizes allowed */
576 				return ((*p - 192) << 8) + *(p + 1) + 192;
577 			}
578 			lenbytes = 1;
579 			for (len = DECODE_PARTIAL(*p) ; IS_PARTIAL(p[len + lenbytes]) ; lenbytes++) {
580 				len += DECODE_PARTIAL(p[len + lenbytes]);
581 			}
582 			len += get_pkt_len(newfmt, &p[len + lenbytes], filesize, 1);
583 			return len;
584 		}
585 		return PKT_LENGTH(p, 0);
586 	} else {
587 		switch(*--p & 0x3) {
588 		case 0:
589 			return *(p + 1);
590 		case 1:
591 			return (*(p + 1) << 8) | *(p + 2);
592 		case 2:
593 			return (*(p + 1) << 24) | (*(p + 2) << 16) | (*(p + 3) << 8)  | *(p + 4);
594 		default:
595 			return filesize;
596 		}
597 	}
598 }
599 
600 static const uint8_t	base64s[] =
601 /* 000 */       "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
602 /* 016 */       "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
603 /* 032 */       "\0\0\0\0\0\0\0\0\0\0\0?\0\0\0@"
604 /* 048 */       "56789:;<=>\0\0\0\0\0\0"
605 /* 064 */       "\0\1\2\3\4\5\6\7\10\11\12\13\14\15\16\17"
606 /* 080 */       "\20\21\22\23\24\25\26\27\30\31\32\0\0\0\0\0"
607 /* 096 */       "\0\33\34\35\36\37 !\"#$%&'()"
608 /* 112 */       "*+,-./01234\0\0\0\0\0"
609 /* 128 */       "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
610 /* 144 */       "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
611 /* 160 */       "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
612 /* 176 */       "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
613 /* 192 */       "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
614 /* 208 */       "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
615 /* 224 */       "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
616 /* 240 */       "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
617 
618 
619 /* short function to decode from base64 */
620 /* inspired by an ancient copy of b64.c, then rewritten, the bugs are all mine */
621 static int
622 frombase64(char *dst, const char *src, size_t size, int flag)
623 {
624 	uint8_t	out[3];
625 	uint8_t	in[4];
626 	uint8_t	b;
627 	size_t	srcc;
628 	int	dstc;
629 	int	gotc;
630 	int	i;
631 
632 	USE_ARG(flag);
633 	for (dstc = 0, srcc = 0 ; srcc < size; ) {
634 		for (gotc = 0, i = 0; i < 4 && srcc < size; i++) {
635 			for (b = 0x0; srcc < size && b == 0x0 ; ) {
636 				b = base64s[(unsigned)src[srcc++]];
637 			}
638 			if (srcc < size) {
639 				gotc += 1;
640 				if (b) {
641 					in[i] = (uint8_t)(b - 1);
642 				}
643 			} else {
644 				in[i] = 0x0;
645 			}
646 		}
647 		if (gotc) {
648 			out[0] = (uint8_t)((unsigned)in[0] << 2 |
649 						(unsigned)in[1] >> 4);
650 			out[1] = (uint8_t)((unsigned)in[1] << 4 |
651 						(unsigned)in[2] >> 2);
652 			out[2] = (uint8_t)(((in[2] << 6) & 0xc0) | in[3]);
653 			for (i = 0; i < gotc - 1; i++) {
654 				*dst++ = out[i];
655 			}
656 			dstc += gotc - 1;
657 		}
658 	}
659 	return dstc;
660 }
661 
662 /* get the length of the packet length field */
663 static unsigned
664 get_pkt_len_len(uint8_t newfmt, uint8_t *p, int isprimary)
665 {
666 	if (newfmt) {
667 		if (IS_PARTIAL(*p)) {
668 			return (isprimary) ? 1 : 2;
669 		}
670 		return PKT_LENGTH_LENGTH(p, 0);
671 	} else {
672 		switch(*--p & 0x3) {
673 		case 0:
674 			return 1;
675 		case 1:
676 			return 2;
677 		case 2:
678 			return 4;
679 		default:
680 			return 0;
681 		}
682 	}
683 }
684 
685 /* copy the 32bit integer in memory in network order */
686 static unsigned
687 fmt_32(uint8_t *p, uint32_t a)
688 {
689 	a = pgp_hton32(a);
690 	memcpy(p, &a, sizeof(a));
691 	return sizeof(a);
692 }
693 
694 /* copy the 16bit integer in memory in network order */
695 static unsigned
696 fmt_16(uint8_t *p, uint16_t a)
697 {
698 	a = pgp_hton16(a);
699 	memcpy(p, &a, sizeof(a));
700 	return sizeof(a);
701 }
702 
703 /* format a binary string in memory */
704 static size_t
705 fmt_binary(obuf_t *obuf, const uint8_t *bin, unsigned len)
706 {
707 	unsigned	i;
708 	char		newbuf[3];
709 
710 	for (i = 0 ; i < len ; i++) {
711 		snprintf(newbuf, sizeof(newbuf), "%02hhx", bin[i]);
712 		if (!obuf_add_mem(obuf, newbuf, 2)) {
713 			return 0;
714 		}
715 	}
716 	return 1;
717 }
718 
719 /* format an mpi into memory */
720 static unsigned
721 fmt_binary_mpi(pgpv_bignum_t *mpi, uint8_t *p, size_t size)
722 {
723 	unsigned	 bytes;
724 	PGPV_BIGNUM		*bn;
725 
726 	bytes = BITS_TO_BYTES(mpi->bits);
727 	if ((size_t)bytes + 2 + 1 > size) {
728 		fprintf(stderr, "truncated mpi");
729 		return 0;
730 	}
731 	bn = (PGPV_BIGNUM *)mpi->bn;
732 	if (bn == NULL || PGPV_BN_is_zero(bn)) {
733 		fmt_32(p, 0);
734 		return 2 + 1;
735 	}
736 	fmt_16(p, mpi->bits);
737 	PGPV_BN_bn2bin(bn, &p[2]);
738 	return bytes + 2;
739 }
740 
741 /* dump an mpi value onto stdout */
742 static size_t
743 fmt_mpi(char *s, size_t size, pgpv_bignum_t *bn, const char *name, int pbits)
744 {
745 	size_t	 cc;
746 	char	*buf;
747 
748 	cc = snprintf(s, size, "%s=", name);
749 	if (pbits) {
750 		cc += snprintf(&s[cc], size - cc, "[%u bits] ", bn->bits);
751 	}
752 	buf = PGPV_BN_bn2hex(bn->bn);
753 	cc += snprintf(&s[cc], size - cc, "%s\n", buf);
754 	free(buf);
755 	return cc;
756 }
757 
758 #define ALG_IS_RSA(alg)	(((alg) == PUBKEY_RSA_ENCRYPT_OR_SIGN) ||	\
759 			 ((alg) == PUBKEY_RSA_ENCRYPT) ||		\
760 			 ((alg) == PUBKEY_RSA_SIGN))
761 
762 #define ALG_IS_DSA(alg)	((alg) == PUBKEY_DSA)
763 
764 /* format key mpis into memory */
765 static unsigned
766 fmt_key_mpis(pgpv_pubkey_t *pubkey, uint8_t *buf, size_t size)
767 {
768 	size_t	cc;
769 
770 	cc = 0;
771 	buf[cc++] = pubkey->version;
772 	cc += fmt_32(&buf[cc], (uint32_t)pubkey->birth); /* XXX - do this portably! */
773 	buf[cc++] = pubkey->keyalg;	/* XXX - sign, or encrypt and sign? */
774 	switch(pubkey->keyalg) {
775 	case PUBKEY_RSA_ENCRYPT_OR_SIGN:
776 	case PUBKEY_RSA_ENCRYPT:
777 	case PUBKEY_RSA_SIGN:
778 		cc += fmt_binary_mpi(&pubkey->bn[RSA_N], &buf[cc], size - cc);
779 		cc += fmt_binary_mpi(&pubkey->bn[RSA_E], &buf[cc], size - cc);
780 		break;
781 	case PUBKEY_DSA:
782 		cc += fmt_binary_mpi(&pubkey->bn[DSA_P], &buf[cc], size - cc);
783 		cc += fmt_binary_mpi(&pubkey->bn[DSA_Q], &buf[cc], size - cc);
784 		cc += fmt_binary_mpi(&pubkey->bn[DSA_G], &buf[cc], size - cc);
785 		cc += fmt_binary_mpi(&pubkey->bn[DSA_Y], &buf[cc], size - cc);
786 		break;
787 	default:
788 		cc += fmt_binary_mpi(&pubkey->bn[ELGAMAL_P], &buf[cc], size - cc);
789 		cc += fmt_binary_mpi(&pubkey->bn[ELGAMAL_G], &buf[cc], size - cc);
790 		cc += fmt_binary_mpi(&pubkey->bn[ELGAMAL_Y], &buf[cc], size - cc);
791 		break;
792 	}
793 	return (unsigned)cc;
794 }
795 
796 /* calculate the fingerprint, RFC 4880, section 12.2 */
797 static int
798 pgpv_calc_fingerprint(pgpv_fingerprint_t *fingerprint, pgpv_pubkey_t *pubkey, const char *hashtype)
799 {
800 	digest_t	 fphash;
801 	uint16_t	 cc;
802 	uint8_t		 ch = 0x99;
803 	uint8_t		 buf[8192 + 2 + 1];
804 	uint8_t		 len[2];
805 
806 	memset(&fphash, 0x0, sizeof(fphash));
807 	if (pubkey->version == 4) {
808 		/* v4 keys */
809 		fingerprint->hashalg = digest_get_alg(hashtype);
810 		digest_init(&fphash, (unsigned)fingerprint->hashalg);
811 		cc = fmt_key_mpis(pubkey, buf, sizeof(buf));
812 		digest_update(&fphash, &ch, 1);
813 		fmt_16(len, cc);
814 		digest_update(&fphash, len, 2);
815 		digest_update(&fphash, buf, (unsigned)cc);
816 		fingerprint->len = digest_final(fingerprint->v, &fphash);
817 		return 1;
818 	}
819 	if (ALG_IS_RSA(pubkey->keyalg)) {
820 		/* v3 keys are RSA */
821 		fingerprint->hashalg = digest_get_alg("md5");
822 		digest_init(&fphash, (unsigned)fingerprint->hashalg);
823 		if (pubkey->bn[RSA_N].bn && pubkey->bn[RSA_E].bn) {
824 			cc = fmt_binary_mpi(&pubkey->bn[RSA_N], buf, sizeof(buf));
825 			digest_update(&fphash, &buf[2], (unsigned)(cc - 2));
826 			cc = fmt_binary_mpi(&pubkey->bn[RSA_E], buf, sizeof(buf));
827 			digest_update(&fphash, &buf[2], (unsigned)(cc - 2));
828 			fingerprint->len = digest_final(fingerprint->v, &fphash);
829 			return 1;
830 		}
831 	}
832 	if (pubkey->bn[RSA_N].bn) {
833 		if ((cc = fmt_binary_mpi(&pubkey->bn[RSA_N], buf, sizeof(buf))) >= PGPV_KEYID_LEN) {
834 			memcpy(fingerprint->v, &buf[cc - PGPV_KEYID_LEN], PGPV_KEYID_LEN);
835 			fingerprint->len = PGPV_KEYID_LEN;
836 			return 1;
837 		}
838 	}
839 	/* exhausted all avenues, really */
840 	memset(fingerprint->v, 0xff, fingerprint->len = PGPV_KEYID_LEN);
841 	return 1;
842 }
843 
844 /* format a fingerprint into memory */
845 static int
846 fmt_fingerprint(obuf_t *obuf, pgpv_fingerprint_t *fingerprint, const char *name)
847 {
848 	unsigned	i;
849 	char		newbuf[3];
850 	int		cc;
851 
852 	if (!obuf_add_mem(obuf, name, strlen(name)) ||
853 	    !obuf_add_mem(obuf, " ", 1)) {
854 		return 0;
855 	}
856 	for (i = 0 ; i < fingerprint->len ; i++) {
857 		cc = snprintf(newbuf, sizeof(newbuf), "%02hhx",
858 			fingerprint->v[i]);
859 		if (!obuf_add_mem(obuf, newbuf, cc)) {
860 			return 0;
861 		}
862 		if (i % 2 == 1 && !obuf_add_mem(obuf, " ", 1)) {
863 			return 0;
864 		}
865 	}
866 	return obuf_add_mem(obuf, "\n", 1);
867 }
868 
869 /* calculate keyid from a pubkey */
870 static int
871 calc_keyid(pgpv_pubkey_t *key, const char *hashtype)
872 {
873 	pgpv_calc_fingerprint(&key->fingerprint, key, hashtype);
874 	memcpy(key->keyid, &key->fingerprint.v[key->fingerprint.len - PGPV_KEYID_LEN], PGPV_KEYID_LEN);
875 	return 1;
876 }
877 
878 /* convert a hex string to a 64bit key id (in big endian byte order */
879 static void
880 str_to_keyid(const char *s, uint8_t *keyid)
881 {
882 	uint64_t	u;
883 
884 	u = (uint64_t)strtoull(s, NULL, 16);
885 	u =     ((u & 0x00000000000000FFULL) << 56) |
886 		((u & 0x000000000000FF00ULL) << 40) |
887 		((u & 0x0000000000FF0000ULL) << 24) |
888 		((u & 0x00000000FF000000ULL) <<  8) |
889 		((u & 0x000000FF00000000ULL) >>  8) |
890 		((u & 0x0000FF0000000000ULL) >> 24) |
891 		((u & 0x00FF000000000000ULL) >> 40) |
892 		((u & 0xFF00000000000000ULL) >> 56);
893 	memcpy(keyid, &u, PGPV_KEYID_LEN);
894 }
895 
896 #define PKT_ALWAYS_ON			0x80
897 #define PKT_NEWFMT_MASK			0x40
898 #define PKT_NEWFMT_TAG_MASK		0x3f
899 #define PKT_OLDFMT_TAG_MASK		0x3c
900 
901 #define SUBPKT_CRITICAL_MASK		0x80
902 #define SUBPKT_TAG_MASK			0x7f
903 
904 #define SUBPKT_SIG_BIRTH		2
905 #define SUBPKT_SIG_EXPIRY		3
906 #define SUBPKT_EXPORT_CERT		4
907 #define SUBPKT_TRUST_SIG		5
908 #define SUBPKT_REGEXP			6
909 #define SUBPKT_REVOCABLE		7
910 #define SUBPKT_KEY_EXPIRY		9
911 #define SUBPKT_BWD_COMPAT		10
912 #define SUBPKT_PREF_SYMMETRIC_ALG	11
913 #define SUBPKT_REVOCATION_KEY		12
914 #define SUBPKT_ISSUER			16
915 #define SUBPKT_NOTATION			20
916 #define SUBPKT_PREF_HASH_ALG		21
917 #define SUBPKT_PREF_COMPRESS_ALG	22
918 #define SUBPKT_KEY_SERVER_PREFS		23
919 #define SUBPKT_PREF_KEY_SERVER		24
920 #define SUBPKT_PRIMARY_USER_ID		25
921 #define SUBPKT_POLICY_URI		26
922 #define SUBPKT_KEY_FLAGS		27
923 #define SUBPKT_SIGNER_ID		28
924 #define SUBPKT_REVOCATION_REASON	29
925 #define SUBPKT_FEATURES			30
926 #define SUBPKT_SIGNATURE_TARGET		31
927 #define SUBPKT_EMBEDDED_SIGNATURE	32
928 
929 #define UNCOMPRESSED			0
930 #define ZIP_COMPRESSION			1
931 #define ZLIB_COMPRESSION		2
932 #define BZIP2_COMPRESSION		3
933 
934 /* get a 16 bit integer, in host order */
935 static uint16_t
936 get_16(uint8_t *p)
937 {
938 	uint16_t	u16;
939 
940 	memcpy(&u16, p, sizeof(u16));
941 	return pgp_ntoh16(u16);
942 }
943 
944 /* get a 32 bit integer, in host order */
945 static uint32_t
946 get_32(uint8_t *p)
947 {
948 	uint32_t	u32;
949 
950 	memcpy(&u32, p, sizeof(u32));
951 	return pgp_ntoh32(u32);
952 }
953 
954 #define HOURSECS	(int64_t)(60 * 60)
955 #define DAYSECS		(int64_t)(24 * 60 * 60)
956 #define MONSECS		(int64_t)(30 * DAYSECS)
957 #define YEARSECS	(int64_t)(365 * DAYSECS)
958 
959 /* format (human readable) time into memory */
960 static size_t
961 fmt_time(obuf_t *obuf, const char *header, int64_t n, const char *trailer, int relative)
962 {
963 	struct tm	tm;
964 	time_t		elapsed;
965 	time_t		now;
966 	time_t		t;
967 	char		newbuf[128];
968 	int		cc;
969 
970 	t = (time_t)n;
971 	now = time(NULL);
972 	elapsed = now - t;
973 	gmtime_r(&t, &tm);
974 	cc = snprintf(newbuf, sizeof(newbuf), "%04d-%02d-%02d",
975 		tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
976 	if (!obuf_add_mem(obuf, header, strlen(header)) ||
977 	    !obuf_add_mem(obuf, newbuf, cc)) {
978 		return 0;
979 	}
980 	if (relative) {
981 		cc = snprintf(newbuf, sizeof(newbuf),
982 			" (%lldy %lldm %lldd %lldh %s)",
983 			llabs((long long)elapsed / YEARSECS),
984 			llabs(((long long)elapsed % YEARSECS) / MONSECS),
985 			llabs(((long long)elapsed % MONSECS) / DAYSECS),
986 			llabs(((long long)elapsed % DAYSECS) / HOURSECS),
987 			(now > t) ? "ago" : "ahead");
988 		if (!obuf_add_mem(obuf, newbuf, cc)) {
989 			return 0;
990 		}
991 	}
992 	return (*trailer) ? obuf_add_mem(obuf, trailer, strlen(trailer)) : 1;
993 }
994 
995 /* dump key mpis to stdout */
996 static void
997 print_key_mpis(pgpv_bignum_t *v, uint8_t keyalg)
998 {
999 	char	s[8192];
1000 
1001 	switch(keyalg) {
1002 	case PUBKEY_RSA_ENCRYPT_OR_SIGN:
1003 	case PUBKEY_RSA_ENCRYPT:
1004 	case PUBKEY_RSA_SIGN:
1005 		fmt_mpi(s, sizeof(s), &v[RSA_N], "rsa.n", 1);
1006 		printf("%s", s);
1007 		fmt_mpi(s, sizeof(s), &v[RSA_E], "rsa.e", 1);
1008 		printf("%s", s);
1009 		break;
1010 	case PUBKEY_ELGAMAL_ENCRYPT:
1011 		fmt_mpi(s, sizeof(s), &v[ELGAMAL_P], "elgamal.p", 1);
1012 		printf("%s", s);
1013 		fmt_mpi(s, sizeof(s), &v[ELGAMAL_Y], "elgamal.y", 1);
1014 		printf("%s", s);
1015 		break;
1016 	case PUBKEY_DSA:
1017 		fmt_mpi(s, sizeof(s), &v[DSA_P], "dsa.p", 1);
1018 		printf("%s", s);
1019 		fmt_mpi(s, sizeof(s), &v[DSA_Q], "dsa.q", 1);
1020 		printf("%s", s);
1021 		fmt_mpi(s, sizeof(s), &v[DSA_G], "dsa.g", 1);
1022 		printf("%s", s);
1023 		fmt_mpi(s, sizeof(s), &v[DSA_Y], "dsa.y", 1);
1024 		printf("%s", s);
1025 		break;
1026 	default:
1027 		printf("hi, unusual keyalg %u\n", keyalg);
1028 		break;
1029 	}
1030 }
1031 
1032 /* get an mpi, including 2 byte length */
1033 static int
1034 get_mpi(pgpv_bignum_t *mpi, uint8_t *p, size_t pktlen, size_t *off)
1035 {
1036 	size_t	bytes;
1037 
1038 	mpi->bits = get_16(p);
1039 	if ((bytes = (size_t)BITS_TO_BYTES(mpi->bits)) > pktlen) {
1040 		return 0;
1041 	}
1042 	*off += sizeof(mpi->bits);
1043 	mpi->bn = PGPV_BN_bin2bn(&p[sizeof(mpi->bits)], (int)bytes, NULL);
1044 	*off += bytes;
1045 	return 1;
1046 }
1047 
1048 /* read mpis in signature */
1049 static int
1050 read_signature_mpis(pgpv_sigpkt_t *sigpkt, uint8_t *p, size_t pktlen)
1051 {
1052 	size_t	off;
1053 
1054 	off = 0;
1055 	switch(sigpkt->sig.keyalg) {
1056 	case PUBKEY_RSA_ENCRYPT_OR_SIGN:
1057 	case PUBKEY_RSA_SIGN:
1058 	case PUBKEY_RSA_ENCRYPT:
1059 		if (!get_mpi(&sigpkt->sig.bn[RSA_SIG], p, pktlen, &off)) {
1060 			printf("sigpkt->version %d, rsa sig weird\n", sigpkt->sig.version);
1061 			return 0;
1062 		}
1063 		break;
1064 	case PUBKEY_DSA:
1065 	case PUBKEY_ECDSA:
1066 	case PUBKEY_ELGAMAL_ENCRYPT_OR_SIGN: /* deprecated */
1067 		if (!get_mpi(&sigpkt->sig.bn[DSA_R], p, pktlen, &off) ||
1068 		    !get_mpi(&sigpkt->sig.bn[DSA_S], &p[off], pktlen, &off)) {
1069 			printf("sigpkt->version %d, dsa/elgamal sig weird\n", sigpkt->sig.version);
1070 			return 0;
1071 		}
1072 		break;
1073 	default:
1074 		printf("weird type of sig! %d\n", sigpkt->sig.keyalg);
1075 		return 0;
1076 	}
1077 	return 1;
1078 }
1079 
1080 /* add the signature sub packet to the signature packet */
1081 static int
1082 add_subpacket(pgpv_t *pgp, pgpv_sigpkt_t *sigpkt, uint8_t tag, uint8_t *p, uint16_t len)
1083 {
1084 	pgpv_sigsubpkt_t	subpkt;
1085 
1086 	memset(&subpkt, 0x0, sizeof(subpkt));
1087 	subpkt.s.size = len;
1088 	subpkt.critical = 0;
1089 	subpkt.tag = tag;
1090 	subpkt.s.data = p;
1091 	ARRAY_APPEND(sigpkt->subpackets, ARRAY_COUNT(pgp->subpkts));
1092 	ARRAY_APPEND(pgp->subpkts, subpkt);
1093 	return 1;
1094 }
1095 
1096 /* read the subpackets in the signature */
1097 static int
1098 read_sig_subpackets(pgpv_t *pgp, pgpv_sigpkt_t *sigpkt, uint8_t *p, size_t pktlen)
1099 {
1100 	pgpv_sigsubpkt_t	 subpkt;
1101 	const int		 is_subpkt = 0;
1102 	unsigned		 lenlen;
1103 	unsigned		 i;
1104 	uint8_t			*start;
1105 
1106 	start = p;
1107 	for (i = 0 ; (unsigned)(p - start) < sigpkt->subslen ; i++) {
1108 		memset(&subpkt, 0x0, sizeof(subpkt));
1109 		subpkt.s.size = get_pkt_len(1, p, 0, is_subpkt);
1110 		lenlen = get_pkt_len_len(1, p, is_subpkt);
1111 		if (lenlen > pktlen) {
1112 			printf("weird lenlen %u\n", lenlen);
1113 			return 0;
1114 		}
1115 		p += lenlen;
1116 		subpkt.critical = (*p & SUBPKT_CRITICAL_MASK);
1117 		subpkt.tag = (*p & SUBPKT_TAG_MASK);
1118 		p += 1;
1119 		switch(subpkt.tag) {
1120 		case SUBPKT_SIG_BIRTH:
1121 			sigpkt->sig.birth = (int64_t)get_32(p);
1122 			break;
1123 		case SUBPKT_SIG_EXPIRY:
1124 			sigpkt->sig.expiry = (int64_t)get_32(p);
1125 			break;
1126 		case SUBPKT_KEY_EXPIRY:
1127 			sigpkt->sig.keyexpiry = (int64_t)get_32(p);
1128 			break;
1129 		case SUBPKT_ISSUER:
1130 			memcpy(sigpkt->sig.signer, p, sizeof(sigpkt->sig.signer));
1131 			break;
1132 		case SUBPKT_SIGNER_ID:
1133 			memcpy(sigpkt->sig.signer, p, sizeof(sigpkt->sig.signer));
1134 			break;
1135 		case SUBPKT_TRUST_SIG:
1136 			sigpkt->sig.trustsig = *p;
1137 			break;
1138 		case SUBPKT_REGEXP:
1139 			sigpkt->sig.regexp = (char *)(void *)p;
1140 			break;
1141 		case SUBPKT_REVOCABLE:
1142 			sigpkt->sig.revocable = *p;
1143 			break;
1144 		case SUBPKT_PREF_SYMMETRIC_ALG:
1145 			sigpkt->sig.pref_symm_alg = *p;
1146 			break;
1147 		case SUBPKT_REVOCATION_KEY:
1148 			sigpkt->sig.revoke_sensitive = (*p & 0x40);
1149 			sigpkt->sig.revoke_alg = p[1];
1150 			sigpkt->sig.revoke_fingerprint = &p[2];
1151 			break;
1152 		case SUBPKT_NOTATION:
1153 			sigpkt->sig.notation = *p;
1154 			break;
1155 		case SUBPKT_PREF_HASH_ALG:
1156 			sigpkt->sig.pref_hash_alg = *p;
1157 			break;
1158 		case SUBPKT_PREF_COMPRESS_ALG:
1159 			sigpkt->sig.pref_compress_alg = *p;
1160 			break;
1161 		case SUBPKT_PREF_KEY_SERVER:
1162 			sigpkt->sig.pref_key_server = (char *)(void *)p;
1163 			break;
1164 		case SUBPKT_KEY_SERVER_PREFS:
1165 			sigpkt->sig.key_server_modify = *p;
1166 			break;
1167 		case SUBPKT_KEY_FLAGS:
1168 			sigpkt->sig.type_key = *p;
1169 			break;
1170 		case SUBPKT_PRIMARY_USER_ID:
1171 			sigpkt->sig.primary_userid = *p;
1172 			break;
1173 		case SUBPKT_POLICY_URI:
1174 			sigpkt->sig.policy = (char *)(void *)p;
1175 			break;
1176 		case SUBPKT_FEATURES:
1177 			sigpkt->sig.features = (char *)(void *)p;
1178 			break;
1179 		case SUBPKT_REVOCATION_REASON:
1180 			sigpkt->sig.revoked = *p++ + 1;
1181 			sigpkt->sig.why_revoked = (char *)(void *)p;
1182 			break;
1183 		default:
1184 			printf("Ignoring unusual/reserved signature subpacket %d\n", subpkt.tag);
1185 			break;
1186 		}
1187 		subpkt.s.data = p;
1188 		p += subpkt.s.size - 1;
1189 		ARRAY_APPEND(sigpkt->subpackets, ARRAY_COUNT(pgp->subpkts));
1190 		ARRAY_APPEND(pgp->subpkts, subpkt);
1191 	}
1192 	return 1;
1193 }
1194 
1195 /* parse signature packet */
1196 static int
1197 read_sigpkt(pgpv_t *pgp, uint8_t mement, pgpv_sigpkt_t *sigpkt, uint8_t *p, size_t pktlen)
1198 {
1199 	unsigned	 lenlen;
1200 	uint8_t		*base;
1201 
1202 	make_ref(pgp, mement, &sigpkt->sig.hashstart);
1203 	base = p;
1204 	switch(sigpkt->sig.version = *p++) {
1205 	case 2:
1206 	case 3:
1207 		if ((lenlen = *p++) != 5) {
1208 			printf("read_sigpkt: hashed length not 5\n");
1209 			return 0;
1210 		}
1211 		sigpkt->sig.hashlen = lenlen;
1212 		/* put birthtime into a subpacket */
1213 		sigpkt->sig.type = *p++;
1214 		add_subpacket(pgp, sigpkt, SUBPKT_SIG_BIRTH, p, sizeof(uint32_t));
1215 		sigpkt->sig.birth = (int64_t)get_32(p);
1216 		p += sizeof(uint32_t);
1217 		memcpy(sigpkt->sig.signer, p, sizeof(sigpkt->sig.signer));
1218 		add_subpacket(pgp, sigpkt, SUBPKT_SIGNER_ID, p, PGPV_KEYID_LEN);
1219 		p += PGPV_KEYID_LEN;
1220 		sigpkt->sig.keyalg = *p++;
1221 		sigpkt->sig.hashalg = *p++;
1222 		sigpkt->sig.hash2 = p;
1223 		if (!read_signature_mpis(sigpkt, sigpkt->sig.mpi = p + 2, pktlen)) {
1224 			printf("read_sigpkt: can't read sigs v3\n");
1225 			return 0;
1226 		}
1227 		break;
1228 	case 4:
1229 		sigpkt->sig.type = *p++;
1230 		sigpkt->sig.keyalg = *p++;
1231 		sigpkt->sig.hashalg = *p++;
1232 		sigpkt->subslen = get_16(p);
1233 		p += sizeof(sigpkt->subslen);
1234 		if (!read_sig_subpackets(pgp, sigpkt, p, pktlen)) {
1235 			printf("read_sigpkt: can't read sig subpackets, v4\n");
1236 			return 0;
1237 		}
1238 		if (sigpkt->sig.signer[0] == 0x0) {
1239 			memcpy(sigpkt->sig.signer,
1240 				get_ref(&sigpkt->sig.hashstart) + 16,
1241 				sizeof(sigpkt->sig.signer));
1242 		}
1243 		p += sigpkt->subslen;
1244 		sigpkt->sig.hashlen = (unsigned)(p - base);
1245 		sigpkt->unhashlen = get_16(p);
1246 		p += sizeof(sigpkt->unhashlen) + sigpkt->unhashlen;
1247 		sigpkt->sig.hash2 = p;
1248 		if (!read_signature_mpis(sigpkt, sigpkt->sig.mpi = p + 2, pktlen)) {
1249 			printf("read_sigpkt: can't read sigs, v4\n");
1250 			return 0;
1251 		}
1252 		break;
1253 	default:
1254 		printf("read_sigpkt: unusual signature version (%u)\n", sigpkt->sig.version);
1255 		break;
1256 	}
1257 	return 1;
1258 }
1259 
1260 
1261 /* this parses compressed data, decompresses it, and calls the parser again */
1262 static int
1263 read_compressed(pgpv_t *pgp, pgpv_compress_t *compressed, uint8_t *p, size_t len)
1264 {
1265 	pgpv_mem_t	*unzmem;
1266 	bz_stream	 bz;
1267 	z_stream	 z;
1268 	int		 ok = 0;
1269 
1270 	compressed->compalg = *p;
1271 	compressed->s.size = len;
1272 	if ((compressed->s.data = calloc(1, len)) == NULL) {
1273 		printf("read_compressed: can't allocate %zu length\n", len);
1274 		return 0;
1275 	}
1276 	switch(compressed->compalg) {
1277 	case UNCOMPRESSED:
1278 		printf("not implemented %d compression yet\n", compressed->compalg);
1279 		return 0;
1280 	default:
1281 		break;
1282 	}
1283 	ARRAY_EXPAND(pgp->areas);
1284 	ARRAY_COUNT(pgp->areas) += 1;
1285 	unzmem = &ARRAY_LAST(pgp->areas);
1286 	unzmem->size = len * 10;
1287 	unzmem->dealloc = FREE_MEM;
1288 	if ((unzmem->mem = calloc(1, unzmem->size)) == NULL) {
1289 		printf("read_compressed: calloc failed!\n");
1290 		return 0;
1291 	}
1292 	switch(compressed->compalg) {
1293 	case ZIP_COMPRESSION:
1294 	case ZLIB_COMPRESSION:
1295 		memset(&z, 0x0, sizeof(z));
1296 		z.next_in = p + 1;
1297 		z.avail_in = (unsigned)(len - 1);
1298 		z.total_in = (unsigned)(len - 1);
1299 		z.next_out = unzmem->mem;
1300 		z.avail_out = (unsigned)unzmem->size;
1301 		z.total_out = (unsigned)unzmem->size;
1302 		break;
1303 	case BZIP2_COMPRESSION:
1304 		memset(&bz, 0x0, sizeof(bz));
1305 		bz.avail_in = (unsigned)(len - 1);
1306 		bz.next_in = (char *)(void *)p + 1;
1307 		bz.next_out = (char *)(void *)unzmem->mem;
1308 		bz.avail_out = (unsigned)unzmem->size;
1309 		break;
1310 	}
1311 	switch(compressed->compalg) {
1312 	case ZIP_COMPRESSION:
1313 		ok = (inflateInit2(&z, -15) == Z_OK);
1314 		break;
1315 	case ZLIB_COMPRESSION:
1316 		ok = (inflateInit(&z) == Z_OK);
1317 		break;
1318 	case BZIP2_COMPRESSION:
1319 		ok = (netpgpv_BZ2_bzDecompressInit(&bz, 1, 0) == BZ_OK);
1320 		break;
1321 	}
1322 	if (!ok) {
1323 		printf("read_compressed: initialisation failed!\n");
1324 		return 0;
1325 	}
1326 	switch(compressed->compalg) {
1327 	case ZIP_COMPRESSION:
1328 	case ZLIB_COMPRESSION:
1329 		ok = (inflate(&z, Z_FINISH) == Z_STREAM_END);
1330 		unzmem->size = z.total_out;
1331 		break;
1332 	case BZIP2_COMPRESSION:
1333 		ok = (netpgpv_BZ2_bzDecompress(&bz) == BZ_STREAM_END);
1334 		unzmem->size = ((uint64_t)bz.total_out_hi32 << 32) | bz.total_out_lo32;
1335 		break;
1336 	}
1337 	if (!ok) {
1338 		printf("read_compressed: inflate failed!\n");
1339 		return 0;
1340 	}
1341 	return 1;
1342 }
1343 
1344 /* parse one pass signature packet */
1345 static int
1346 read_onepass_sig(pgpv_onepass_t *onepasspkt, uint8_t *mem)
1347 {
1348 	onepasspkt->version = mem[0];
1349 	onepasspkt->type = mem[1];
1350 	onepasspkt->hashalg = mem[2];
1351 	onepasspkt->keyalg = mem[3];
1352 	memcpy(onepasspkt->keyid, &mem[4], sizeof(onepasspkt->keyid));
1353 	onepasspkt->nested = mem[12];
1354 	return 1;
1355 }
1356 
1357 /* parse public key packet */
1358 static int
1359 read_pubkey(pgpv_pubkey_t *pubkey, uint8_t *mem, size_t pktlen, int pbn)
1360 {
1361 	size_t		 off;
1362 
1363 	off = 0;
1364 	pubkey->version = mem[off++];
1365 	pubkey->birth = get_32(&mem[off]);
1366 	off += 4;
1367 	if (pubkey->version == 2 || pubkey->version == 3) {
1368 		pubkey->expiry = get_16(&mem[off]) * DAYSECS;
1369 		off += 2;
1370 	}
1371 	if ((pubkey->keyalg = mem[off++]) == 0) {
1372 		pubkey->keyalg = PUBKEY_RSA_ENCRYPT_OR_SIGN;
1373 		printf("got unusual pubkey keyalg %u\n", mem[off - 1]);
1374 	}
1375 	switch(pubkey->keyalg) {
1376 	case PUBKEY_RSA_ENCRYPT_OR_SIGN:
1377 	case PUBKEY_RSA_ENCRYPT:
1378 	case PUBKEY_RSA_SIGN:
1379 		if (!get_mpi(&pubkey->bn[RSA_N], &mem[off], pktlen, &off) ||
1380 		    !get_mpi(&pubkey->bn[RSA_E], &mem[off], pktlen, &off)) {
1381 			return 0;
1382 		}
1383 		break;
1384 	case PUBKEY_ELGAMAL_ENCRYPT:
1385 	case PUBKEY_ELGAMAL_ENCRYPT_OR_SIGN:
1386 		if (!get_mpi(&pubkey->bn[ELGAMAL_P], &mem[off], pktlen, &off) ||
1387 		    !get_mpi(&pubkey->bn[ELGAMAL_Y], &mem[off], pktlen, &off)) {
1388 			return 0;
1389 		}
1390 		break;
1391 	case PUBKEY_DSA:
1392 		if (!get_mpi(&pubkey->bn[DSA_P], &mem[off], pktlen, &off) ||
1393 		    !get_mpi(&pubkey->bn[DSA_Q], &mem[off], pktlen, &off) ||
1394 		    !get_mpi(&pubkey->bn[DSA_G], &mem[off], pktlen, &off) ||
1395 		    !get_mpi(&pubkey->bn[DSA_Y], &mem[off], pktlen, &off)) {
1396 			return 0;
1397 		}
1398 		break;
1399 	default:
1400 		printf("hi, different type of pubkey here %u\n", pubkey->keyalg);
1401 		break;
1402 	}
1403 	if (pbn) {
1404 		print_key_mpis(pubkey->bn, pubkey->keyalg);
1405 	}
1406 	return 1;
1407 }
1408 
1409 /* parse a user attribute */
1410 static int
1411 read_userattr(pgpv_userattr_t *userattr, uint8_t *p, size_t pktlen)
1412 {
1413 	pgpv_string_t	subattr;
1414 	const int 	is_subpkt = 0;
1415 	const int	indian = 1;
1416 	unsigned	lenlen;
1417 	uint16_t	imagelen;
1418 	size_t		cc;
1419 
1420 	userattr->len = pktlen;
1421 	for (cc = 0 ; cc < pktlen ; cc += subattr.size + lenlen + 1) {
1422 		subattr.size = get_pkt_len(1, p, 0, is_subpkt);
1423 		lenlen = get_pkt_len_len(1, p, is_subpkt);
1424 		if (lenlen > pktlen) {
1425 			printf("weird lenlen %u\n", lenlen);
1426 			return 0;
1427 		}
1428 		p += lenlen;
1429 		if (*p++ != 1) {
1430 			printf("image type (%u) != 1. weird packet\n", *(p - 1));
1431 		}
1432 		memcpy(&imagelen, p, sizeof(imagelen));
1433 		if (!*(const char *)(const void *)&indian) {
1434 			/* big endian - byteswap length */
1435 			imagelen = (((unsigned)imagelen & 0xff) << 8) | (((unsigned)imagelen >> 8) & 0xff);
1436 		}
1437 		subattr.data = p + 3;
1438 		p += subattr.size;
1439 		ARRAY_APPEND(userattr->subattrs, subattr);
1440 	}
1441 	return 1;
1442 }
1443 
1444 #define LITDATA_BINARY	'b'
1445 #define LITDATA_TEXT	't'
1446 #define LITDATA_UTF8	'u'
1447 
1448 /* parse literal packet */
1449 static int
1450 read_litdata(pgpv_t *pgp, pgpv_litdata_t *litdata, uint8_t *p, size_t size)
1451 {
1452 	size_t	cc;
1453 
1454 	cc = 0;
1455 	switch(litdata->format = p[cc++]) {
1456 	case LITDATA_BINARY:
1457 	case LITDATA_TEXT:
1458 	case LITDATA_UTF8:
1459 		litdata->namelen = 0;
1460 		break;
1461 	default:
1462 		printf("weird litdata format %u\n", litdata->format);
1463 		break;
1464 	}
1465 	litdata->filename.size = litdata->namelen = p[cc++];
1466 	litdata->filename.data = &p[cc];
1467 	litdata->filename.allocated = 0;
1468 	cc += litdata->namelen;
1469 	litdata->secs = get_32(&p[cc]);
1470 	cc += 4;
1471 	litdata->s.data = &p[cc];
1472 	litdata->len = litdata->s.size = size - cc;
1473 	litdata->mem = ARRAY_COUNT(pgp->areas) - 1;
1474 	litdata->offset = cc;
1475 	return 1;
1476 }
1477 
1478 /* parse a single packet */
1479 static int
1480 read_pkt(pgpv_t *pgp, pgpv_mem_t *mem)
1481 {
1482 	const int	 isprimary = 1;
1483 	pgpv_pkt_t	 pkt;
1484 	pgpv_mem_t	*newmem;
1485 	unsigned	 lenlen;
1486 	uint8_t		 ispartial;
1487 	size_t		 size;
1488 
1489 	memset(&pkt, 0x0, sizeof(pkt));
1490 	pkt.tag = mem->mem[mem->cc++];
1491 	if (!(pkt.tag & PKT_ALWAYS_ON)) {
1492 		printf("BAD PACKET - bit 7 not 1, offset %zu!\n", mem->cc - 1);
1493 	}
1494 	pkt.newfmt = (pkt.tag & PKT_NEWFMT_MASK);
1495 	pkt.tag = (pkt.newfmt) ?
1496 		(pkt.tag & PKT_NEWFMT_TAG_MASK) :
1497 		(((unsigned)pkt.tag & PKT_OLDFMT_TAG_MASK) >> 2);
1498 	ispartial = (pkt.newfmt && IS_PARTIAL(mem->mem[mem->cc]));
1499 	pkt.s.size = get_pkt_len(pkt.newfmt, &mem->mem[mem->cc], mem->size - mem->cc, isprimary);
1500 	lenlen = get_pkt_len_len(pkt.newfmt, &mem->mem[mem->cc], isprimary);
1501 	pkt.offset = mem->cc;
1502 	mem->cc += lenlen;
1503 	pkt.mement = (uint8_t)(mem - ARRAY_ARRAY(pgp->areas));
1504 	pkt.s.data = &mem->mem[mem->cc];
1505 	if (strchr(mem->allowed, pkt.tag) == NULL) {
1506 		printf("packet %d not allowed for operation %s\n", pkt.tag, pgp->op);
1507 		return 0;
1508 	}
1509 	size = pkt.s.size;
1510 	if (ispartial) {
1511 		pkt.s.size = fixup_partials(pgp, &mem->mem[mem->cc - lenlen], pkt.s.size, mem->size, &size);
1512 		newmem = &ARRAY_LAST(pgp->areas);
1513 		pkt.mement = (uint8_t)(newmem - ARRAY_ARRAY(pgp->areas));
1514 		pkt.s.data = newmem->mem;
1515 		size -= 1;
1516 	}
1517 	switch(pkt.tag) {
1518 	case SIGNATURE_PKT:
1519 		if (!read_sigpkt(pgp, pkt.mement, &pkt.u.sigpkt, pkt.s.data, pkt.s.size)) {
1520 			return 0;
1521 		}
1522 		break;
1523 	case ONEPASS_SIGNATURE_PKT:
1524 		read_onepass_sig(&pkt.u.onepass, pkt.s.data);
1525 		break;
1526 	case PUBKEY_PKT:
1527 	case PUB_SUBKEY_PKT:
1528 		break;
1529 	case LITDATA_PKT:
1530 		read_litdata(pgp, &pkt.u.litdata, pkt.s.data, pkt.s.size);
1531 		break;
1532 	case TRUST_PKT:
1533 		pkt.u.trust.level = pkt.s.data[0];
1534 		pkt.u.trust.amount = pkt.s.data[1];
1535 		break;
1536 	case USERID_PKT:
1537 		pkt.u.userid.size = pkt.s.size;
1538 		pkt.u.userid.data = pkt.s.data;
1539 		pkt.u.userid.allocated = 0;
1540 		break;
1541 	case COMPRESSED_DATA_PKT:
1542 		read_compressed(pgp, &pkt.u.compressed, pkt.s.data, pkt.s.size);
1543 		ARRAY_APPEND(pgp->pkts, pkt);
1544 		read_all_packets(pgp, &ARRAY_LAST(pgp->areas), pgp->op);
1545 		break;
1546 	case USER_ATTRIBUTE_PKT:
1547 		read_userattr(&pkt.u.userattr, pkt.s.data, pkt.s.size);
1548 		break;
1549 	default:
1550 		printf("hi, need to implement %d, offset %zu\n", pkt.tag, mem->cc);
1551 		break;
1552 	}
1553 	mem->cc += size;
1554 	if (pkt.tag != COMPRESSED_DATA_PKT) {
1555 		/* compressed was added earlier to preserve pkt ordering */
1556 		ARRAY_APPEND(pgp->pkts, pkt);
1557 	}
1558 	return 1;
1559 }
1560 
1561 /* checks the tag type of a packet */
1562 static int
1563 pkt_is(pgpv_t *pgp, int wanted)
1564 {
1565 	return (ARRAY_ELEMENT(pgp->pkts, pgp->pkt).tag == wanted);
1566 }
1567 
1568 /* checks the packet is a signature packet, and the signature type is the expected one */
1569 static int
1570 pkt_sigtype_is(pgpv_t *pgp, int wanted)
1571 {
1572 	if (!pkt_is(pgp, SIGNATURE_PKT)) {
1573 		return 0;
1574 	}
1575 	return (ARRAY_ELEMENT(pgp->pkts, pgp->pkt).u.sigpkt.sig.type == wanted);
1576 }
1577 
1578 /* check for expected type of packet, and move to the next */
1579 static int
1580 pkt_accept(pgpv_t *pgp, int expected)
1581 {
1582 	int	got;
1583 
1584 	if ((got = ARRAY_ELEMENT(pgp->pkts, pgp->pkt).tag) == expected) {
1585 		pgp->pkt += 1;
1586 		return 1;
1587 	}
1588 	printf("problem at token %zu, expcted %d, got %d\n", pgp->pkt, expected, got);
1589 	return 0;
1590 }
1591 
1592 /* recognise signature (and trust) packet */
1593 static int
1594 recog_signature(pgpv_t *pgp, pgpv_signature_t *signature)
1595 {
1596 	if (!pkt_is(pgp, SIGNATURE_PKT)) {
1597 		printf("recog_signature: not a signature packet\n");
1598 		return 0;
1599 	}
1600 	memcpy(signature, &ARRAY_ELEMENT(pgp->pkts, pgp->pkt).u.sigpkt.sig, sizeof(*signature));
1601 	pgp->pkt += 1;
1602 	if (pkt_is(pgp, TRUST_PKT)) {
1603 		pkt_accept(pgp, TRUST_PKT);
1604 	}
1605 	return 1;
1606 }
1607 
1608 /* recognise user id packet */
1609 static int
1610 recog_userid(pgpv_t *pgp, pgpv_signed_userid_t *userid)
1611 {
1612 	pgpv_signature_t	 signature;
1613 	pgpv_pkt_t		*pkt;
1614 
1615 	memset(userid, 0x0, sizeof(*userid));
1616 	if (!pkt_is(pgp, USERID_PKT)) {
1617 		printf("recog_userid: not %d\n", USERID_PKT);
1618 		return 0;
1619 	}
1620 	pkt = &ARRAY_ELEMENT(pgp->pkts, pgp->pkt);
1621 	userid->userid.size = pkt->s.size;
1622 	userid->userid.data = pkt->s.data;
1623 	userid->userid.allocated = 0;
1624 	pgp->pkt += 1;
1625 	while (pkt_is(pgp, SIGNATURE_PKT)) {
1626 		if (!recog_signature(pgp, &signature)) {
1627 			printf("recog_userid: can't recognise signature/trust\n");
1628 			return 0;
1629 		}
1630 		ARRAY_APPEND(userid->signatures, ARRAY_COUNT(pgp->signatures));
1631 		ARRAY_APPEND(pgp->signatures, signature);
1632 		if (signature.primary_userid) {
1633 			userid->primary_userid = signature.primary_userid;
1634 		}
1635 		if (signature.revoked) {
1636 			userid->revoked = signature.revoked;
1637 		}
1638 	}
1639 	return 1;
1640 }
1641 
1642 /* recognise user attributes packet */
1643 static int
1644 recog_userattr(pgpv_t *pgp, pgpv_signed_userattr_t *userattr)
1645 {
1646 	pgpv_signature_t	 signature;
1647 
1648 	memset(userattr, 0x0, sizeof(*userattr));
1649 	if (!pkt_is(pgp, USER_ATTRIBUTE_PKT)) {
1650 		printf("recog_userattr: not %d\n", USER_ATTRIBUTE_PKT);
1651 		return 0;
1652 	}
1653 	userattr->userattr = ARRAY_ELEMENT(pgp->pkts, pgp->pkt).u.userattr;
1654 	pgp->pkt += 1;
1655 	while (pkt_is(pgp, SIGNATURE_PKT)) {
1656 		if (!recog_signature(pgp, &signature)) {
1657 			printf("recog_userattr: can't recognise signature/trust\n");
1658 			return 0;
1659 		}
1660 		ARRAY_APPEND(userattr->signatures, ARRAY_COUNT(pgp->signatures));
1661 		ARRAY_APPEND(pgp->signatures, signature);
1662 		if (signature.revoked) {
1663 			userattr->revoked = signature.revoked;
1664 		}
1665 	}
1666 	return 1;
1667 }
1668 
1669 /* recognise a sub key */
1670 static int
1671 recog_subkey(pgpv_t *pgp, pgpv_signed_subkey_t *subkey)
1672 {
1673 	pgpv_signature_t	 signature;
1674 	pgpv_pkt_t		*pkt;
1675 
1676 	pkt = &ARRAY_ELEMENT(pgp->pkts, pgp->pkt);
1677 	memset(subkey, 0x0, sizeof(*subkey));
1678 	read_pubkey(&subkey->subkey, pkt->s.data, pkt->s.size, 0);
1679 	pgp->pkt += 1;
1680 	if (pkt_sigtype_is(pgp, SIGTYPE_KEY_REVOCATION) ||
1681 	    pkt_sigtype_is(pgp, SIGTYPE_SUBKEY_REVOCATION) ||
1682 	    pkt_sigtype_is(pgp, SIGTYPE_CERT_REVOCATION)) {
1683 		recog_signature(pgp, &signature);
1684 		subkey->revoc_self_sig = signature;
1685 	}
1686 	do {
1687 		if (!pkt_is(pgp, SIGNATURE_PKT)) {
1688 			printf("recog_subkey: not signature packet at %zu\n", pgp->pkt);
1689 			return 0;
1690 		}
1691 		if (!recog_signature(pgp, &signature)) {
1692 			printf("recog_subkey: bad signature/trust at %zu\n", pgp->pkt);
1693 			return 0;
1694 		}
1695 		ARRAY_APPEND(subkey->signatures, ARRAY_COUNT(pgp->signatures));
1696 		ARRAY_APPEND(pgp->signatures, signature);
1697 		if (signature.keyexpiry) {
1698 			/* XXX - check it's a good key expiry */
1699 			subkey->subkey.expiry = signature.keyexpiry;
1700 		}
1701 	} while (pkt_is(pgp, SIGNATURE_PKT));
1702 	return 1;
1703 }
1704 
1705 /* use a sparse map for the text strings here to save space */
1706 static const char	*keyalgs[] = {
1707 	"[Unknown]",
1708 	"RSA (Encrypt or Sign)",
1709 	"RSA (Encrypt Only)",
1710 	"RSA (Sign Only)",
1711 	"Elgamal (Encrypt Only)",
1712 	"DSA",
1713 	"Elliptic Curve",
1714 	"ECDSA",
1715 	"Elgamal (Encrypt or Sign)"
1716 };
1717 
1718 #define MAX_KEYALG	21
1719 
1720 static 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";
1721 
1722 /* return human readable name for key algorithm */
1723 static const char *
1724 fmtkeyalg(uint8_t keyalg)
1725 {
1726 	return keyalgs[(uint8_t)keyalgmap[(keyalg >= MAX_KEYALG) ? 0 : keyalg]];
1727 }
1728 
1729 /* return the number of bits in the public key */
1730 static unsigned
1731 numkeybits(const pgpv_pubkey_t *pubkey)
1732 {
1733 	switch(pubkey->keyalg) {
1734 	case PUBKEY_RSA_ENCRYPT_OR_SIGN:
1735 	case PUBKEY_RSA_ENCRYPT:
1736 	case PUBKEY_RSA_SIGN:
1737 		return pubkey->bn[RSA_N].bits;
1738 	case PUBKEY_DSA:
1739 	case PUBKEY_ECDSA:
1740 		return pubkey->bn[DSA_P].bits;
1741 		//return BITS_TO_BYTES(pubkey->bn[DSA_Q].bits) * 64;
1742 	case PUBKEY_ELGAMAL_ENCRYPT:
1743 	case PUBKEY_ELGAMAL_ENCRYPT_OR_SIGN:
1744 		return pubkey->bn[ELGAMAL_P].bits;
1745 	default:
1746 		return 0;
1747 	}
1748 }
1749 
1750 /* print a public key */
1751 static int
1752 fmt_pubkey(obuf_t *obuf, pgpv_pubkey_t *pubkey, const char *leader)
1753 {
1754 	char	newbuf[128];
1755 	int	cc;
1756 
1757 	cc = snprintf(newbuf, sizeof(newbuf), " %u/%s ",
1758 		numkeybits(pubkey), fmtkeyalg(pubkey->keyalg));
1759 	if (!obuf_add_mem(obuf, leader, strlen(leader)) ||
1760 	    !obuf_add_mem(obuf, newbuf, cc)) {
1761 		return 0;
1762 	}
1763 	if (!fmt_binary(obuf, pubkey->keyid, PGPV_KEYID_LEN)) {
1764 		return 0;
1765 	}
1766 	if (!fmt_time(obuf, " ", pubkey->birth, "", 0)) {
1767 		return 0;
1768 	}
1769 	if (pubkey->expiry) {
1770 		if (!fmt_time(obuf, " [Expiry ", pubkey->birth + pubkey->expiry, "]", 0)) {
1771 			return 0;
1772 		}
1773 	}
1774 	if (!obuf_add_mem(obuf, "\n", 1)) {
1775 		return 0;
1776 	}
1777 	return fmt_fingerprint(obuf, &pubkey->fingerprint, "fingerprint  ");
1778 }
1779 
1780 /* we add 1 to revocation value to denote compromised */
1781 #define COMPROMISED	(0x02 + 1)
1782 
1783 /* format a userid - used to order the userids when formatting */
1784 static int
1785 fmt_userid(obuf_t *obuf, pgpv_t *pgp, pgpv_primarykey_t *primary, uint8_t u)
1786 {
1787 	pgpv_signed_userid_t	*userid;
1788 	const char		*s;
1789 	uint64_t		 id;
1790 
1791 	id = ARRAY_ELEMENT(primary->signed_userids, u);
1792 	userid = &ARRAY_ELEMENT(pgp->signed_userids, id);
1793 	s = (userid->revoked == COMPROMISED) ? " [COMPROMISED AND REVOKED]\n" :
1794 		(userid->revoked) ? " [REVOKED]\n" : "\n";
1795 	return obuf_add_mem(obuf, "uid           ", 14) &&
1796 		obuf_add_mem(obuf, userid->userid.data, userid->userid.size) &&
1797 		obuf_add_mem(obuf, s, strlen(s));
1798 }
1799 
1800 /* format a trust sig - used to order the userids when formatting */
1801 static int
1802 fmt_trust(obuf_t *obuf, pgpv_signature_t *sig)
1803 {
1804 	if (!obuf_add_mem(obuf, "trust          ", 15) ||
1805 	    !fmt_binary(obuf, sig->signer, PGPV_KEYID_LEN)) {
1806 		return 0;
1807 	}
1808 	return obuf_add_mem(obuf, "\n", 1);
1809 }
1810 
1811 /* print a primary key, per RFC 4880 */
1812 static int
1813 fmt_primary(obuf_t *obuf, pgpv_t *pgp, pgpv_primarykey_t *primary, unsigned subkey, const char *modifiers)
1814 {
1815 	pgpv_signed_userid_t	*userid;
1816 	pgpv_signed_subkey_t	*signed_subkey;
1817 	pgpv_pubkey_t		*pubkey;
1818 	unsigned		 i;
1819 	unsigned		 j;
1820 	uint64_t		 id;
1821 
1822 	if (subkey == 0) {
1823 		pubkey = &primary->primary;
1824 	} else {
1825 		id = ARRAY_ELEMENT(primary->signed_subkeys, subkey);
1826 		pubkey = &ARRAY_ELEMENT(pgp->signed_subkeys, id).subkey;
1827 	}
1828 	if (!fmt_pubkey(obuf, pubkey, "signature    ")) {
1829 		return 0;
1830 	}
1831 	if (!fmt_userid(obuf, pgp, primary, primary->primary_userid)) {
1832 		return 0;
1833 	}
1834 	for (i = 0 ; i < ARRAY_COUNT(primary->signed_userids) ; i++) {
1835 		if (i != primary->primary_userid) {
1836 			if (!fmt_userid(obuf, pgp, primary, i)) {
1837 				return 0;
1838 			}
1839 			if (strcasecmp(modifiers, "trust") == 0) {
1840 				id = ARRAY_ELEMENT(primary->signed_userids, i);
1841 				userid = &ARRAY_ELEMENT(pgp->signed_userids, id);
1842 				for (j = 0 ; j < ARRAY_COUNT(userid->signatures) ; j++) {
1843 					if (!fmt_trust(obuf, &ARRAY_ELEMENT(pgp->signatures,
1844 							ARRAY_ELEMENT(userid->signatures, j)))) {
1845 						return 0;
1846 					}
1847 				}
1848 			}
1849 		}
1850 	}
1851 	if (strcasecmp(modifiers, "subkeys") == 0) {
1852 		for (i = 0 ; i < ARRAY_COUNT(primary->signed_subkeys) ; i++) {
1853 			id = ARRAY_ELEMENT(primary->signed_subkeys, i);
1854 			signed_subkey = &ARRAY_ELEMENT(pgp->signed_subkeys, id);
1855 			if (!fmt_pubkey(obuf, &signed_subkey->subkey, "encryption")) {
1856 				return 0;
1857 			}
1858 		}
1859 	}
1860 	return obuf_add_mem(obuf, "\n", 1);
1861 }
1862 
1863 
1864 /* check the padding on the signature */
1865 static int
1866 rsa_padding_check_none(uint8_t *to, int tlen, const uint8_t *from, int flen, int num)
1867 {
1868 	USE_ARG(num);
1869 	if (flen > tlen) {
1870 		printf("from length larger than to length\n");
1871 		return -1;
1872 	}
1873 	(void) memset(to, 0x0, (size_t)(tlen - flen));
1874 	(void) memcpy(to + tlen - flen, from, (size_t)flen);
1875 	return tlen;
1876 }
1877 
1878 #define RSA_MAX_MODULUS_BITS	16384
1879 #define RSA_SMALL_MODULUS_BITS	3072
1880 #define RSA_MAX_PUBEXP_BITS	64 /* exponent limit enforced for "large" modulus only */
1881 
1882 /* check against the exponent/moudulo operation */
1883 static int
1884 lowlevel_rsa_public_check(const uint8_t *encbuf, int enclen, uint8_t *dec, const netpgpv_rsa_pubkey_t *rsa)
1885 {
1886 	uint8_t		*decbuf;
1887 	PGPV_BIGNUM		*decbn;
1888 	PGPV_BIGNUM		*encbn;
1889 	int		 decbytes;
1890 	int		 nbytes;
1891 	int		 r;
1892 
1893 	nbytes = 0;
1894 	r = -1;
1895 	decbuf = NULL;
1896 	decbn = encbn = NULL;
1897 	if (PGPV_BN_num_bits(rsa->n) > RSA_MAX_MODULUS_BITS) {
1898 		printf("rsa r modulus too large\n");
1899 		goto err;
1900 	}
1901 	if (PGPV_BN_cmp(rsa->n, rsa->e) <= 0) {
1902 		printf("rsa r bad n value\n");
1903 		goto err;
1904 	}
1905 	if (PGPV_BN_num_bits(rsa->n) > RSA_SMALL_MODULUS_BITS &&
1906 	    PGPV_BN_num_bits(rsa->e) > RSA_MAX_PUBEXP_BITS) {
1907 		printf("rsa r bad exponent limit\n");
1908 		goto err;
1909 	}
1910 	nbytes = PGPV_BN_num_bytes(rsa->n);
1911 	if ((encbn = PGPV_BN_new()) == NULL ||
1912 	    (decbn = PGPV_BN_new()) == NULL ||
1913 	    (decbuf = calloc(1, (size_t)nbytes)) == NULL) {
1914 		printf("allocation failure\n");
1915 		goto err;
1916 	}
1917 	if (enclen > nbytes) {
1918 		printf("rsa r > mod len\n");
1919 		goto err;
1920 	}
1921 	if (PGPV_BN_bin2bn(encbuf, enclen, encbn) == NULL) {
1922 		printf("null encrypted BN\n");
1923 		goto err;
1924 	}
1925 	if (PGPV_BN_cmp(encbn, rsa->n) >= 0) {
1926 		printf("rsa r data too large for modulus\n");
1927 		goto err;
1928 	}
1929 	if (PGPV_BN_mod_exp(decbn, encbn, rsa->e, rsa->n, NULL) < 0) {
1930 		printf("PGPV_BN_mod_exp < 0\n");
1931 		goto err;
1932 	}
1933 	decbytes = PGPV_BN_num_bytes(decbn);
1934 	(void) PGPV_BN_bn2bin(decbn, decbuf);
1935 	if ((r = rsa_padding_check_none(dec, nbytes, decbuf, decbytes, 0)) < 0) {
1936 		printf("rsa r padding check failed\n");
1937 	}
1938 err:
1939 	PGPV_BN_clear_free(encbn);
1940 	PGPV_BN_clear_free(decbn);
1941 	if (decbuf != NULL) {
1942 		(void) memset(decbuf, 0x0, nbytes);
1943 		free(decbuf);
1944 	}
1945 	return r;
1946 }
1947 
1948 /* verify */
1949 static int
1950 rsa_public_decrypt(int enclen, const unsigned char *enc, unsigned char *dec, NETPGPV_RSA *rsa, int padding)
1951 {
1952 	netpgpv_rsa_pubkey_t	pub;
1953 	int			ret;
1954 
1955 	if (enc == NULL || dec == NULL || rsa == NULL) {
1956 		return 0;
1957 	}
1958 	USE_ARG(padding);
1959 	(void) memset(&pub, 0x0, sizeof(pub));
1960 	pub.n = PGPV_BN_dup(rsa->n);
1961 	pub.e = PGPV_BN_dup(rsa->e);
1962 	ret = lowlevel_rsa_public_check(enc, enclen, dec, &pub);
1963 	PGPV_BN_clear_free(pub.n);
1964 	PGPV_BN_clear_free(pub.e);
1965 	return ret;
1966 }
1967 
1968 #define SUBKEY_LEN(x)	(80 + 80)
1969 #define SIG_LEN		80
1970 #define UID_LEN		80
1971 
1972 /* return worst case number of bytes needed to format a primary key */
1973 static size_t
1974 estimate_primarykey_size(pgpv_primarykey_t *primary)
1975 {
1976 	size_t		cc;
1977 
1978 	cc = SUBKEY_LEN("signature") +
1979 		(ARRAY_COUNT(primary->signed_userids) * UID_LEN) +
1980 		(ARRAY_COUNT(primary->signed_subkeys) * SUBKEY_LEN("encrypt uids"));
1981 	return cc;
1982 }
1983 
1984 /* use public decrypt to verify a signature */
1985 static int
1986 pgpv_rsa_public_decrypt(uint8_t *out, const uint8_t *in, size_t length, const pgpv_pubkey_t *pubkey)
1987 {
1988 	NETPGPV_RSA    *orsa;
1989 	int             n;
1990 
1991 	if ((orsa = calloc(1, sizeof(*orsa))) == NULL) {
1992 		return 0;
1993 	}
1994 	orsa->n = pubkey->bn[RSA_N].bn;
1995 	orsa->e = pubkey->bn[RSA_E].bn;
1996 	n = rsa_public_decrypt((int)length, in, out, orsa, NETPGPV_RSA_NO_PADDING);
1997 	orsa->n = orsa->e = NULL;
1998 	free(orsa);
1999 	return n;
2000 }
2001 
2002 /* verify rsa signature */
2003 static int
2004 rsa_verify(uint8_t *calculated, unsigned calclen, uint8_t hashalg, pgpv_bignum_t *bn, pgpv_pubkey_t *pubkey)
2005 {
2006 	unsigned	 prefixlen;
2007 	unsigned	 decryptc;
2008 	unsigned	 i;
2009 	uint8_t		 decrypted[8192];
2010 	uint8_t		 sigbn[8192];
2011 	uint8_t		 prefix[64];
2012 	size_t		 keysize;
2013 
2014 	keysize = BITS_TO_BYTES(pubkey->bn[RSA_N].bits);
2015 	PGPV_BN_bn2bin(bn[RSA_SIG].bn, sigbn);
2016 	decryptc = pgpv_rsa_public_decrypt(decrypted, sigbn, BITS_TO_BYTES(bn[RSA_SIG].bits), pubkey);
2017 	if (decryptc != keysize || (decrypted[0] != 0 || decrypted[1] != 1)) {
2018 		return 0;
2019 	}
2020 	if ((prefixlen = digest_get_prefix((unsigned)hashalg, prefix, sizeof(prefix))) == 0) {
2021 		printf("rsa_verify: unknown hash algorithm: %d\n", hashalg);
2022 		return 0;
2023 	}
2024 	for (i = 2 ; i < keysize - prefixlen - calclen - 1 ; i++) {
2025 		if (decrypted[i] != 0xff) {
2026 			return 0;
2027 		}
2028 	}
2029 	if (decrypted[i++] != 0x0) {
2030 		return 0;
2031 	}
2032 	if (memcmp(&decrypted[i], prefix, prefixlen) != 0) {
2033 		printf("rsa_verify: wrong hash algorithm\n");
2034 		return 0;
2035 	}
2036 	return memcmp(&decrypted[i + prefixlen], calculated, calclen) == 0;
2037 }
2038 
2039 /* return 1 if bn <= 0 */
2040 static int
2041 bignum_is_bad(PGPV_BIGNUM *bn)
2042 {
2043 	return PGPV_BN_is_zero(bn) || PGPV_BN_is_negative(bn);
2044 }
2045 
2046 #define BAD_BIGNUM(s, k)	\
2047 	(bignum_is_bad((s)->bn) || PGPV_BN_cmp((s)->bn, (k)->bn) >= 0)
2048 
2049 #ifndef DSA_MAX_MODULUS_BITS
2050 #define DSA_MAX_MODULUS_BITS      10000
2051 #endif
2052 
2053 /* verify DSA signature */
2054 static int
2055 verify_dsa_sig(uint8_t *calculated, unsigned calclen, pgpv_bignum_t *sig, pgpv_pubkey_t *pubkey)
2056 {
2057 	PGPV_BIGNUM	 *M;
2058 	PGPV_BIGNUM	 *W;
2059 	PGPV_BIGNUM	 *t1;
2060 	unsigned	  qbits;
2061 	uint8_t		  calcnum[128];
2062 	uint8_t		  signum[128];
2063 	int		  ret;
2064 
2065 	if (pubkey->bn[DSA_P].bn == NULL ||
2066 	    pubkey->bn[DSA_Q].bn == NULL ||
2067 	    pubkey->bn[DSA_G].bn == NULL) {
2068 		return 0;
2069 	}
2070 	M = W = t1 = NULL;
2071 	qbits = pubkey->bn[DSA_Q].bits;
2072 	switch(qbits) {
2073 	case 160:
2074 	case 224:
2075 	case 256:
2076 		break;
2077 	default:
2078 		printf("dsa: bad # of Q bits\n");
2079 		return 0;
2080 	}
2081 	if (pubkey->bn[DSA_P].bits > DSA_MAX_MODULUS_BITS) {
2082 		printf("dsa: p too large\n");
2083 		return 0;
2084 	}
2085 	if (calclen > SHA256_DIGEST_LENGTH) {
2086 		printf("dsa: digest too long\n");
2087 		return 0;
2088 	}
2089 	ret = 0;
2090 	if ((M = PGPV_BN_new()) == NULL || (W = PGPV_BN_new()) == NULL || (t1 = PGPV_BN_new()) == NULL ||
2091 	    BAD_BIGNUM(&sig[DSA_R], &pubkey->bn[DSA_Q]) ||
2092 	    BAD_BIGNUM(&sig[DSA_S], &pubkey->bn[DSA_Q]) ||
2093 	    PGPV_BN_mod_inverse(W, sig[DSA_S].bn, pubkey->bn[DSA_Q].bn, NULL) == NULL) {
2094 		goto done;
2095 	}
2096 	if (calclen > qbits / 8) {
2097 		calclen = qbits / 8;
2098 	}
2099 	if (PGPV_BN_bin2bn(calculated, (int)calclen, M) == NULL ||
2100 	    !PGPV_BN_mod_mul(M, M, W, pubkey->bn[DSA_Q].bn, NULL) ||
2101 	    !PGPV_BN_mod_mul(W, sig[DSA_R].bn, W, pubkey->bn[DSA_Q].bn, NULL) ||
2102 	    !PGPV_BN_mod_exp(t1, pubkey->bn[DSA_G].bn, M, pubkey->bn[DSA_P].bn, NULL) ||
2103 	    !PGPV_BN_mod_exp(W, pubkey->bn[DSA_Y].bn, W, pubkey->bn[DSA_P].bn, NULL) ||
2104 	    !PGPV_BN_mod_mul(t1, t1, W, pubkey->bn[DSA_P].bn, NULL) ||
2105 	    !PGPV_BN_div(NULL, t1, t1, pubkey->bn[DSA_Q].bn, NULL)) {
2106 		goto done;
2107 	}
2108 	/* only compare the first q bits */
2109 	PGPV_BN_bn2bin(t1, calcnum);
2110 	PGPV_BN_bn2bin(sig[DSA_R].bn, signum);
2111 	ret = memcmp(calcnum, signum, BITS_TO_BYTES(qbits)) == 0;
2112 done:
2113 	if (M) {
2114 		PGPV_BN_clear_free(M);
2115 	}
2116 	if (W) {
2117 		PGPV_BN_clear_free(W);
2118 	}
2119 	if (t1) {
2120 		PGPV_BN_clear_free(t1);
2121 	}
2122 	return ret;
2123 }
2124 
2125 #define TIME_SNPRINTF(_cc, _buf, _size, _fmt, _val)	do {		\
2126 	time_t	 _t;							\
2127 	char	*_s;							\
2128 									\
2129 	_t = _val;							\
2130 	_s = ctime(&_t);						\
2131 	_cc += snprintf(_buf, _size, _fmt, _s);				\
2132 } while(/*CONSTCOND*/0)
2133 
2134 /* check dates on signature and key are valid */
2135 static size_t
2136 valid_dates(pgpv_signature_t *signature, pgpv_pubkey_t *pubkey, char *buf, size_t size)
2137 {
2138 	time_t	 now;
2139 	time_t	 t;
2140 	size_t	 cc;
2141 
2142 	cc = 0;
2143 	if (signature->birth < pubkey->birth) {
2144 		TIME_SNPRINTF(cc, buf, size, "Signature time (%.24s) was before pubkey creation ", signature->birth);
2145 		TIME_SNPRINTF(cc, &buf[cc], size - cc, "(%s)", pubkey->birth);
2146 		return cc;
2147 	}
2148 	now = time(NULL);
2149 	if (signature->expiry != 0) {
2150 		if ((t = signature->birth + signature->expiry) < now) {
2151 			TIME_SNPRINTF(cc, buf, size, "Signature expired on %.24s", t);
2152 			return cc;
2153 		}
2154 	}
2155 	if (now < signature->birth) {
2156 		TIME_SNPRINTF(cc, buf, size, "Signature not valid before %.24s", signature->birth);
2157 		return cc;
2158 	}
2159 	return 0;
2160 }
2161 
2162 /* check if the signing key has expired */
2163 static int
2164 key_expired(pgpv_pubkey_t *pubkey, char *buf, size_t size)
2165 {
2166 	time_t	 now;
2167 	time_t	 t;
2168 	size_t	 cc;
2169 
2170 	now = time(NULL);
2171 	cc = 0;
2172 	if (pubkey->expiry != 0) {
2173 		if ((t = pubkey->birth + pubkey->expiry) < now) {
2174 			TIME_SNPRINTF(cc, buf, size, "Pubkey expired on %.24s", t);
2175 			return (int)cc;
2176 		}
2177 	}
2178 	if (now < pubkey->birth) {
2179 		TIME_SNPRINTF(cc, buf, size, "Pubkey not valid before %.24s", pubkey->birth);
2180 		return (int)cc;
2181 	}
2182 	return 0;
2183 }
2184 
2185 /* find the leading onepass packet */
2186 static size_t
2187 find_onepass(pgpv_cursor_t *cursor, size_t datastart)
2188 {
2189 	size_t	pkt;
2190 
2191 	for (pkt = datastart ; pkt < ARRAY_COUNT(cursor->pgp->pkts) ; pkt++) {
2192 		if (ARRAY_ELEMENT(cursor->pgp->pkts, pkt).tag == ONEPASS_SIGNATURE_PKT) {
2193 			return pkt + 1;
2194 		}
2195 	}
2196 	snprintf(cursor->why, sizeof(cursor->why), "No signature to verify");
2197 	return 0;
2198 }
2199 
2200 static const char	*armor_begins[] = {
2201 	"-----BEGIN PGP SIGNED MESSAGE-----\n",
2202 	"-----BEGIN PGP MESSAGE-----\n",
2203 	NULL
2204 };
2205 
2206 /* return non-zero if the buf introduces an armored message */
2207 static int
2208 is_armored(const char *buf, size_t size)
2209 {
2210 	const char	**arm;
2211 	const char	 *nl;
2212 	size_t		  n;
2213 
2214 	if ((nl = memchr(buf, '\n', size)) == NULL) {
2215 		return 0;
2216 	}
2217 	n = (size_t)(nl - buf);
2218 	for (arm = armor_begins ; *arm ; arm++) {
2219 		if (strncmp(buf, *arm, n) == 0) {
2220 			return 1;
2221 		}
2222 	}
2223 	return 0;
2224 }
2225 
2226 /* find first occurrence of pat binary string in block */
2227 static void *
2228 find_bin_string(const void *blockarg, size_t blen, const void *pat, size_t plen)
2229 {
2230 	const uint8_t	*block;
2231 	const uint8_t	*bp;
2232 
2233 	if (plen == 0) {
2234 		return __UNCONST(blockarg);
2235 	}
2236 	if (blen < plen) {
2237 		return NULL;
2238 	}
2239 	for (bp = block = blockarg ; (size_t)(bp - block) < blen - plen + 1 ; bp++) {
2240 		if (memcmp(bp, pat, plen) == 0) {
2241 			return __UNCONST(bp);
2242 		}
2243 	}
2244 	return NULL;
2245 }
2246 
2247 /* store string in allocated memory */
2248 static uint8_t *
2249 pgpv_strdup(const char *s)
2250 {
2251 	uint8_t	*cp;
2252 	size_t	 len;
2253 
2254 	len = strlen(s);
2255 	if ((cp = calloc(len + 1, 1)) != NULL) {
2256 		memcpy(cp, s, len);
2257 	}
2258 	return cp;
2259 }
2260 
2261 #define SIGSTART	"-----BEGIN PGP SIGNATURE-----\n"
2262 #define SIGEND		"-----END PGP SIGNATURE-----\n"
2263 
2264 /* for ascii armor, we don't get a onepass packet - make one */
2265 static const char 	*cons_onepass = "\304\015\003\0\0\0\0\377\377\377\377\377\377\377\377\1";
2266 
2267 /* read ascii armor */
2268 static int
2269 read_ascii_armor(pgpv_cursor_t *cursor, pgpv_mem_t *mem, const char *filename)
2270 {
2271 	pgpv_onepass_t	*onepass;
2272 	pgpv_sigpkt_t	*sigpkt;
2273 	pgpv_pkt_t	 litdata;
2274 	uint8_t		 binsig[8192];
2275 	uint8_t		*datastart;
2276 	uint8_t		*sigend;
2277 	uint8_t		*p;
2278 	size_t		 binsigsize;
2279 
2280 	/* cons up litdata pkt */
2281 	memset(&litdata, 0x0, sizeof(litdata));
2282 	litdata.u.litdata.mem = ARRAY_COUNT(cursor->pgp->areas) - 1;
2283 	p = mem->mem;
2284 	/* jump over signed message line */
2285 	if ((p = find_bin_string(mem->mem, mem->size, "\n\n",  2)) == NULL) {
2286 		snprintf(cursor->why, sizeof(cursor->why), "malformed armor at offset 0");
2287 		return 0;
2288 	}
2289 	p += 2;
2290 	litdata.tag = LITDATA_PKT;
2291 	litdata.s.data = p;
2292 	litdata.u.litdata.offset = (size_t)(p - mem->mem);
2293 	litdata.u.litdata.filename.data = pgpv_strdup(filename);
2294 	litdata.u.litdata.filename.allocated = 1;
2295 	if ((p = find_bin_string(datastart = p, mem->size - litdata.offset, SIGSTART, sizeof(SIGSTART) - 1)) == NULL) {
2296 		snprintf(cursor->why, sizeof(cursor->why),
2297 			"malformed armor - no sig - at %zu", (size_t)(p - mem->mem));
2298 		return 0;
2299 	}
2300 	litdata.u.litdata.len = litdata.s.size = (size_t)(p - datastart);
2301 	/* this puts p at the newline character, so it will find \n\n if no version */
2302 	p += strlen(SIGSTART) - 1;
2303 	if ((p = find_bin_string(p, mem->size, "\n\n",  2)) == NULL) {
2304 		snprintf(cursor->why, sizeof(cursor->why),
2305 			"malformed armed signature at %zu", (size_t)(p - mem->mem));
2306 		return 0;
2307 	}
2308 	p += 2;
2309 	sigend = find_bin_string(p, mem->size, SIGEND, sizeof(SIGEND) - 1);
2310 	if (sigend == NULL) {
2311 		snprintf(cursor->why, sizeof(cursor->why),
2312 			"malformed armor - no end sig - at %zu",
2313 			(size_t)(p - mem->mem));
2314 		return 0;
2315 	}
2316 	binsigsize = netpgpv_b64decode((char *)p, (size_t)(sigend - p), binsig, sizeof(binsig));
2317 
2318 	read_binary_memory(cursor->pgp, "signature", cons_onepass, 15);
2319 	ARRAY_APPEND(cursor->pgp->pkts, litdata);
2320 	read_binary_memory(cursor->pgp, "signature", binsig, binsigsize - 3);
2321 	/* XXX - hardwired - 3 is format and length */
2322 
2323 	/* fix up packets in the packet array now we have them there */
2324 	onepass = &ARRAY_ELEMENT(cursor->pgp->pkts, ARRAY_COUNT(cursor->pgp->pkts) - 1 - 2).u.onepass;
2325 	sigpkt = &ARRAY_LAST(cursor->pgp->pkts).u.sigpkt;
2326 	memcpy(onepass->keyid, sigpkt->sig.signer, sizeof(onepass->keyid));
2327 	onepass->hashalg = sigpkt->sig.hashalg;
2328 	onepass->keyalg = sigpkt->sig.keyalg;
2329 	return 1;
2330 }
2331 
2332 /* read ascii armor from a file */
2333 static int
2334 read_ascii_armor_file(pgpv_cursor_t *cursor, const char *filename)
2335 {
2336 	/* cons up litdata pkt */
2337 	read_file(cursor->pgp, filename);
2338 	return read_ascii_armor(cursor, &ARRAY_LAST(cursor->pgp->areas), filename);
2339 }
2340 
2341 /* read ascii armor from memory */
2342 static int
2343 read_ascii_armor_memory(pgpv_cursor_t *cursor, const void *p, size_t size)
2344 {
2345 	pgpv_mem_t	*mem;
2346 
2347 	/* cons up litdata pkt */
2348 	ARRAY_EXPAND(cursor->pgp->areas);
2349 	ARRAY_COUNT(cursor->pgp->areas) += 1;
2350 	mem = &ARRAY_LAST(cursor->pgp->areas);
2351 	memset(mem, 0x0, sizeof(*mem));
2352 	mem->size = size;
2353 	mem->mem = __UNCONST(p);
2354 	mem->dealloc = 0;
2355 	return read_ascii_armor(cursor, mem, "[stdin]");
2356 }
2357 
2358 /* set up the data to verify */
2359 static int
2360 setup_data(pgpv_cursor_t *cursor, pgpv_t *pgp, const void *p, ssize_t size)
2361 {
2362 	FILE		*fp;
2363 	char		 buf[BUFSIZ];
2364 
2365 	if (cursor == NULL || pgp == NULL || p == NULL) {
2366 		return 0;
2367 	}
2368 	memset(cursor, 0x0, sizeof(*cursor));
2369 	ARRAY_APPEND(pgp->datastarts, pgp->pkt);
2370 	cursor->pgp = pgp;
2371 	if (size < 0) {
2372 		/* we have a file name in p */
2373 		if ((fp = fopen(p, "r")) == NULL) {
2374 			snprintf(cursor->why, sizeof(cursor->why), "No such file '%s'", (const char *)p);
2375 			return 0;
2376 		}
2377 		if (fgets(buf, (int)sizeof(buf), fp) == NULL) {
2378 			fclose(fp);
2379 			snprintf(cursor->why, sizeof(cursor->why), "can't read file '%s'", (const char *)p);
2380 			return 0;
2381 		}
2382 		if (is_armored(buf, sizeof(buf))) {
2383 			read_ascii_armor_file(cursor, p);
2384 		} else {
2385 			read_binary_file(pgp, "signature", "%s", (const char *)p);
2386 		}
2387 		fclose(fp);
2388 	} else {
2389 		if (is_armored(p, (size_t)size)) {
2390 			read_ascii_armor_memory(cursor, p, (size_t)size);
2391 		} else {
2392 			read_binary_memory(pgp, "signature", p, (size_t)size);
2393 		}
2394 	}
2395 	return 1;
2396 }
2397 
2398 /* get the data and size from litdata packet */
2399 static uint8_t *
2400 get_literal_data(pgpv_cursor_t *cursor, pgpv_litdata_t *litdata, size_t *size)
2401 {
2402 	pgpv_mem_t	*mem;
2403 
2404 	if (litdata->s.data == NULL && litdata->s.size == 0) {
2405 		mem = &ARRAY_ELEMENT(cursor->pgp->areas, litdata->mem);
2406 		*size = litdata->len;
2407 		return &mem->mem[litdata->offset];
2408 	}
2409 	*size = litdata->s.size;
2410 	return litdata->s.data;
2411 }
2412 
2413 /*
2414 RFC 4880 describes the structure of v4 keys as:
2415 
2416            Primary-Key
2417               [Revocation Self Signature]
2418               [Direct Key Signature...]
2419                User ID [Signature ...]
2420               [User ID [Signature ...] ...]
2421               [User Attribute [Signature ...] ...]
2422               [[Subkey [Binding-Signature-Revocation]
2423                       Primary-Key-Binding-Signature] ...]
2424 
2425 and that's implemented below as a recursive descent parser.
2426 It has had to be modified, though: see the comment
2427 
2428 	some keys out there have user ids where they shouldn't
2429 
2430 to look like:
2431 
2432            Primary-Key
2433               [Revocation Self Signature]
2434               [Direct Key Signature...]
2435               [User ID [Signature ...]
2436                  [User ID [Signature ...] ...]
2437                  [User Attribute [Signature ...] ...]
2438                  [Subkey [Binding-Signature-Revocation]
2439                         Primary-Key-Binding-Signature] ...]
2440 
2441 to accommodate keyrings set up by gpg
2442 */
2443 
2444 /* recognise a primary key */
2445 static int
2446 recog_primary_key(pgpv_t *pgp, pgpv_primarykey_t *primary)
2447 {
2448 	pgpv_signed_userattr_t	 userattr;
2449 	pgpv_signed_userid_t	 userid;
2450 	pgpv_signed_subkey_t	 subkey;
2451 	pgpv_signature_t	 signature;
2452 	pgpv_pkt_t		*pkt;
2453 
2454 	pkt = &ARRAY_ELEMENT(pgp->pkts, pgp->pkt);
2455 	memset(primary, 0x0, sizeof(*primary));
2456 	read_pubkey(&primary->primary, pkt->s.data, pkt->s.size, 0);
2457 	pgp->pkt += 1;
2458 	if (pkt_sigtype_is(pgp, SIGTYPE_KEY_REVOCATION)) {
2459 		if (!recog_signature(pgp, &primary->revoc_self_sig)) {
2460 			printf("recog_primary_key: no signature/trust at PGPV_SIGTYPE_KEY_REVOCATION\n");
2461 			return 0;
2462 		}
2463 	}
2464 	while (pkt_sigtype_is(pgp, SIGTYPE_DIRECT_KEY)) {
2465 		if (!recog_signature(pgp, &signature)) {
2466 			printf("recog_primary_key: no signature/trust at PGPV_SIGTYPE_DIRECT_KEY\n");
2467 			return 0;
2468 		}
2469 		if (signature.keyexpiry) {
2470 			/* XXX - check it's a good key expiry */
2471 			primary->primary.expiry = signature.keyexpiry;
2472 		}
2473 		ARRAY_APPEND(primary->signatures, ARRAY_COUNT(pgp->signatures));
2474 		ARRAY_APPEND(pgp->signatures, signature);
2475 	}
2476 	/* some keys out there have user ids where they shouldn't */
2477 	do {
2478 		if (!recog_userid(pgp, &userid)) {
2479 			printf("recog_primary_key: not userid\n");
2480 			return 0;
2481 		}
2482 		ARRAY_APPEND(primary->signed_userids, ARRAY_COUNT(pgp->signed_userids));
2483 		ARRAY_APPEND(pgp->signed_userids, userid);
2484 		if (userid.primary_userid) {
2485 			primary->primary_userid = ARRAY_COUNT(primary->signed_userids) - 1;
2486 		}
2487 		while (pkt_is(pgp, USERID_PKT)) {
2488 			if (!recog_userid(pgp, &userid)) {
2489 				printf("recog_primary_key: not signed secondary userid\n");
2490 				return 0;
2491 			}
2492 			ARRAY_APPEND(primary->signed_userids, ARRAY_COUNT(pgp->signed_userids));
2493 			ARRAY_APPEND(pgp->signed_userids, userid);
2494 			if (userid.primary_userid) {
2495 				primary->primary_userid = ARRAY_COUNT(primary->signed_userids) - 1;
2496 			}
2497 		}
2498 		while (pkt_is(pgp, USER_ATTRIBUTE_PKT)) {
2499 			if (!recog_userattr(pgp, &userattr)) {
2500 				printf("recog_primary_key: not signed user attribute\n");
2501 				return 0;
2502 			}
2503 			ARRAY_APPEND(primary->signed_userattrs, ARRAY_COUNT(pgp->signed_userattrs));
2504 			ARRAY_APPEND(pgp->signed_userattrs, userattr);
2505 		}
2506 		while (pkt_is(pgp, PUB_SUBKEY_PKT)) {
2507 			if (!recog_subkey(pgp, &subkey)) {
2508 				printf("recog_primary_key: not signed public subkey\n");
2509 				return 0;
2510 			}
2511 			calc_keyid(&subkey.subkey, "sha1");
2512 			ARRAY_APPEND(primary->signed_subkeys, ARRAY_COUNT(pgp->signed_subkeys));
2513 			ARRAY_APPEND(pgp->signed_subkeys, subkey);
2514 		}
2515 	} while (pgp->pkt < ARRAY_COUNT(pgp->pkts) && pkt_is(pgp, USERID_PKT));
2516 	primary->fmtsize = estimate_primarykey_size(primary);
2517 	return 1;
2518 }
2519 
2520 /* parse all of the packets for a given operation */
2521 static int
2522 read_all_packets(pgpv_t *pgp, pgpv_mem_t *mem, const char *op)
2523 {
2524 	pgpv_primarykey_t	 primary;
2525 
2526 	if (op == NULL) {
2527 		return 0;
2528 	}
2529 	if (strcmp(pgp->op = op, "pubring") == 0) {
2530 		mem->allowed = PUBRING_ALLOWED;
2531 		/* pubrings have thousands of small packets */
2532 		ARRAY_EXPAND_SIZED(pgp->pkts, 0, 5000);
2533 	} else if (strcmp(op, "signature") == 0) {
2534 		mem->allowed = SIGNATURE_ALLOWED;
2535 	} else {
2536 		mem->allowed = "";
2537 	}
2538 	for (mem->cc = 0; mem->cc < mem->size ; ) {
2539 		if (!read_pkt(pgp, mem)) {
2540 			return 0;
2541 		}
2542 	}
2543 	if (strcmp(op, "pubring") == 0) {
2544 		for (pgp->pkt = 0; pgp->pkt < ARRAY_COUNT(pgp->pkts) && recog_primary_key(pgp, &primary) ; ) {
2545 			calc_keyid(&primary.primary, "sha1");
2546 			ARRAY_APPEND(pgp->primaries, primary);
2547 		}
2548 		if (pgp->pkt < ARRAY_COUNT(pgp->pkts)) {
2549 			printf("short pubring recognition???\n");
2550 		}
2551 	}
2552 	pgp->pkt = ARRAY_COUNT(pgp->pkts);
2553 	return 1;
2554 }
2555 
2556 /* create a filename, read it, and then parse according to "op" */
2557 static int
2558 read_binary_file(pgpv_t *pgp, const char *op, const char *fmt, ...)
2559 {
2560 	va_list	args;
2561 	char	buf[1024];
2562 
2563 	va_start(args, fmt);
2564 	vsnprintf(buf, sizeof(buf), fmt, args);
2565 	va_end(args);
2566 	if (!read_file(pgp, buf)) {
2567 		return 0;
2568 	}
2569 	return read_all_packets(pgp, &ARRAY_LAST(pgp->areas), op);
2570 }
2571 
2572 /* get a bignum from the buffer gap */
2573 static int
2574 getbignum(pgpv_bignum_t *bignum, bufgap_t *bg, char *buf, const char *header)
2575 {
2576 	uint32_t	 len;
2577 
2578 	USE_ARG(header);
2579 	(void) bufgap_getbin(bg, &len, sizeof(len));
2580 	len = pgp_ntoh32(len);
2581 	(void) bufgap_seek(bg, sizeof(len), BGFromHere, BGByte);
2582 	(void) bufgap_getbin(bg, buf, len);
2583 	bignum->bn = PGPV_BN_bin2bn((const uint8_t *)buf, (int)len, NULL);
2584 	bignum->bits = PGPV_BN_num_bits(bignum->bn);
2585 	(void) bufgap_seek(bg, len, BGFromHere, BGByte);
2586 	return 1;
2587 }
2588 
2589 /* structure for searching for constant strings */
2590 typedef struct str_t {
2591 	const char	*s;		/* string */
2592 	size_t		 len;		/* its length */
2593 	int		 type;		/* return type */
2594 } str_t;
2595 
2596 static str_t	pkatypes[] = {
2597 	{	"ssh-rsa",	7,	PUBKEY_RSA_SIGN	},
2598 	{	"ssh-dss",	7,	PUBKEY_DSA	},
2599 	{	"ssh-dsa",	7,	PUBKEY_DSA	},
2600 	{	NULL,		0,	0		}
2601 };
2602 
2603 /* look for a string in the given array */
2604 static int
2605 findstr(str_t *array, const char *name)
2606 {
2607 	str_t	*sp;
2608 
2609 	for (sp = array ; sp->s ; sp++) {
2610 		if (strncmp(name, sp->s, sp->len) == 0) {
2611 			return sp->type;
2612 		}
2613 	}
2614 	return -1;
2615 }
2616 
2617 /* read public key from the ssh pubkey file */
2618 static __printflike(3, 4) int
2619 read_ssh_file(pgpv_t *pgp, pgpv_primarykey_t *primary, const char *fmt, ...)
2620 {
2621 	pgpv_signed_userid_t	 userid;
2622 	pgpv_pubkey_t		*pubkey;
2623 	struct stat		 st;
2624 	bufgap_t		 bg;
2625 	uint32_t		 len;
2626 	int64_t			 off;
2627 	va_list			 args;
2628 	char			 hostname[256];
2629 	char			 owner[256];
2630 	char			*space;
2631 	char		 	*buf;
2632 	char		 	*bin;
2633 	char			 newbuf[2048];
2634 	char			 f[1024];
2635 	int			 ok;
2636 	int			 cc;
2637 
2638 	USE_ARG(pgp);
2639 	memset(primary, 0x0, sizeof(*primary));
2640 	(void) memset(&bg, 0x0, sizeof(bg));
2641 	va_start(args, fmt);
2642 	vsnprintf(f, sizeof(f), fmt, args);
2643 	va_end(args);
2644 	if (!bufgap_open(&bg, f)) {
2645 		(void) fprintf(stderr, "pgp_ssh2pubkey: can't open '%s'\n", f);
2646 		return 0;
2647 	}
2648 	(void)stat(f, &st);
2649 	if ((buf = calloc(1, (size_t)st.st_size)) == NULL) {
2650 		(void) fprintf(stderr, "can't calloc %zu bytes for '%s'\n", (size_t)st.st_size, f);
2651 		bufgap_close(&bg);
2652 		return 0;
2653 	}
2654 	if ((bin = calloc(1, (size_t)st.st_size)) == NULL) {
2655 		(void) fprintf(stderr, "can't calloc %zu bytes for '%s'\n", (size_t)st.st_size, f);
2656 		(void) free(buf);
2657 		bufgap_close(&bg);
2658 		return 0;
2659 	}
2660 
2661 	/* move past ascii type of key */
2662 	while (bufgap_peek(&bg, 0) != ' ') {
2663 		if (!bufgap_seek(&bg, 1, BGFromHere, BGByte)) {
2664 			(void) fprintf(stderr, "bad key file '%s'\n", f);
2665 			(void) free(buf);
2666 			bufgap_close(&bg);
2667 			return 0;
2668 		}
2669 	}
2670 	if (!bufgap_seek(&bg, 1, BGFromHere, BGByte)) {
2671 		(void) fprintf(stderr, "bad key file '%s'\n", f);
2672 		(void) free(buf);
2673 		bufgap_close(&bg);
2674 		return 0;
2675 	}
2676 	off = bufgap_tell(&bg, BGFromBOF, BGByte);
2677 
2678 	if (bufgap_size(&bg, BGByte) - off < 10) {
2679 		(void) fprintf(stderr, "bad key file '%s'\n", f);
2680 		(void) free(buf);
2681 		bufgap_close(&bg);
2682 		return 0;
2683 	}
2684 
2685 	/* convert from base64 to binary */
2686 	cc = bufgap_getbin(&bg, buf, (size_t)bg.bcc);
2687 	if ((space = strchr(buf, ' ')) != NULL) {
2688 		cc = (int)(space - buf);
2689 	}
2690 	cc = frombase64(bin, buf, (size_t)cc, 0);
2691 	bufgap_delete(&bg, (uint64_t)bufgap_tell(&bg, BGFromEOF, BGByte));
2692 	bufgap_insert(&bg, bin, cc);
2693 	bufgap_seek(&bg, off, BGFromBOF, BGByte);
2694 
2695 	/* get the type of key */
2696 	(void) bufgap_getbin(&bg, &len, sizeof(len));
2697 	len = pgp_ntoh32(len);
2698 	if (len >= st.st_size) {
2699 		(void) fprintf(stderr, "bad public key file '%s'\n", f);
2700 		return 0;
2701 	}
2702 	(void) bufgap_seek(&bg, sizeof(len), BGFromHere, BGByte);
2703 	(void) bufgap_getbin(&bg, buf, len);
2704 	(void) bufgap_seek(&bg, len, BGFromHere, BGByte);
2705 
2706 	pubkey = &primary->primary;
2707 	pubkey->hashalg = digest_get_alg("sha256"); /* gets fixed up later */
2708 	pubkey->version = 4;
2709 	pubkey->birth = 0; /* gets fixed up later */
2710 	/* get key type */
2711 	ok = 1;
2712 	switch (pubkey->keyalg = findstr(pkatypes, buf)) {
2713 	case PUBKEY_RSA_ENCRYPT_OR_SIGN:
2714 	case PUBKEY_RSA_SIGN:
2715 		getbignum(&pubkey->bn[RSA_E], &bg, buf, "RSA E");
2716 		getbignum(&pubkey->bn[RSA_N], &bg, buf, "RSA N");
2717 		break;
2718 	case PUBKEY_DSA:
2719 		getbignum(&pubkey->bn[DSA_P], &bg, buf, "DSA P");
2720 		getbignum(&pubkey->bn[DSA_Q], &bg, buf, "DSA Q");
2721 		getbignum(&pubkey->bn[DSA_G], &bg, buf, "DSA G");
2722 		getbignum(&pubkey->bn[DSA_Y], &bg, buf, "DSA Y");
2723 		break;
2724 	default:
2725 		(void) fprintf(stderr, "Unrecognised pubkey type %d for '%s'\n",
2726 				pubkey->keyalg, f);
2727 		ok = 0;
2728 		break;
2729 	}
2730 
2731 	/* check for stragglers */
2732 	if (ok && bufgap_tell(&bg, BGFromEOF, BGByte) > 0) {
2733 		printf("%"PRIi64" bytes left\n", bufgap_tell(&bg, BGFromEOF, BGByte));
2734 		printf("[%s]\n", bufgap_getstr(&bg));
2735 		ok = 0;
2736 	}
2737 	if (ok) {
2738 		memset(&userid, 0x0, sizeof(userid));
2739 		(void) gethostname(hostname, sizeof(hostname));
2740 		if (strlen(space + 1) - 1 == 0) {
2741 			(void) snprintf(owner, sizeof(owner), "<root@%.*s>",
2742 					240, hostname);
2743 		} else {
2744 			(void) snprintf(owner, sizeof(owner), "<%.*s>",
2745 				(int)strlen(space + 1) - 1,
2746 				space + 1);
2747 		}
2748 		calc_keyid(pubkey, "sha1");
2749 		cc = snprintf(newbuf, sizeof(newbuf), "%s (%s) %s",
2750 			hostname, f, owner);
2751 		userid.userid.size = cc;
2752 		userid.userid.allocated = 1;
2753 		if ((userid.userid.data = calloc(1, cc + 1)) == NULL) {
2754 			ok = 0;
2755 		} else {
2756 			memcpy(userid.userid.data, newbuf, cc);
2757 			ARRAY_APPEND(primary->signed_userids, ARRAY_COUNT(pgp->signed_userids));
2758 			ARRAY_APPEND(pgp->signed_userids, userid);
2759 			primary->fmtsize = estimate_primarykey_size(primary) + 1024;
2760 		}
2761 	}
2762 	(void) free(bin);
2763 	(void) free(buf);
2764 	bufgap_close(&bg);
2765 	return ok;
2766 }
2767 
2768 /* parse memory according to "op" */
2769 static int
2770 read_binary_memory(pgpv_t *pgp, const char *op, const void *memory, size_t size)
2771 {
2772 	pgpv_mem_t	*mem;
2773 
2774 	ARRAY_EXPAND(pgp->areas);
2775 	ARRAY_COUNT(pgp->areas) += 1;
2776 	mem = &ARRAY_LAST(pgp->areas);
2777 	memset(mem, 0x0, sizeof(*mem));
2778 	mem->size = size;
2779 	mem->mem = __UNCONST(memory);
2780 	mem->dealloc = 0;
2781 	return read_all_packets(pgp, mem, op);
2782 }
2783 
2784 /* fixup the detached signature packets */
2785 static int
2786 fixup_detached(pgpv_cursor_t *cursor, const char *f)
2787 {
2788 	pgpv_onepass_t	*onepass;
2789 	const char	*dot;
2790 	pgpv_pkt_t	 sigpkt;
2791 	pgpv_pkt_t	 litdata;
2792 	pgpv_mem_t	*mem;
2793 	size_t		 el;
2794 	char		 original[MAXPATHLEN];
2795 
2796 	/* cons up litdata pkt */
2797 	if ((dot = strrchr(f, '.')) == NULL || strcasecmp(dot, ".sig") != 0) {
2798 		printf("weird filename '%s'\n", f);
2799 		return 0;
2800 	}
2801 	/* hold sigpkt in a temp var while we insert onepass and litdata */
2802 	el = ARRAY_COUNT(cursor->pgp->pkts) - 1;
2803 	sigpkt = ARRAY_ELEMENT(cursor->pgp->pkts, el);
2804 	ARRAY_DELETE(cursor->pgp->pkts, el);
2805 	ARRAY_EXPAND(cursor->pgp->pkts);
2806 	/* get onepass packet, append to packets */
2807 	read_binary_memory(cursor->pgp, "signature", cons_onepass, 15);
2808 	onepass = &ARRAY_ELEMENT(cursor->pgp->pkts, el).u.onepass;
2809 	/* read the original file into litdata */
2810 	snprintf(original, sizeof(original), "%.*s", (int)(dot - f), f);
2811 	if (!read_file(cursor->pgp, original)) {
2812 		printf("can't read file '%s'\n", original);
2813 		return 0;
2814 	}
2815 	memset(&litdata, 0x0, sizeof(litdata));
2816 	mem = &ARRAY_LAST(cursor->pgp->areas);
2817 	litdata.tag = LITDATA_PKT;
2818 	litdata.s.data = mem->mem;
2819 	litdata.u.litdata.format = LITDATA_BINARY;
2820 	litdata.u.litdata.offset = 0;
2821 	litdata.u.litdata.filename.data = pgpv_strdup(original);
2822 	litdata.u.litdata.filename.allocated = 1;
2823 	litdata.u.litdata.mem = ARRAY_COUNT(cursor->pgp->areas) - 1;
2824 	litdata.u.litdata.len = litdata.s.size = mem->size;
2825 	ARRAY_APPEND(cursor->pgp->pkts, litdata);
2826 	ARRAY_APPEND(cursor->pgp->pkts, sigpkt);
2827 	memcpy(onepass->keyid, sigpkt.u.sigpkt.sig.signer, sizeof(onepass->keyid));
2828 	onepass->hashalg = sigpkt.u.sigpkt.sig.hashalg;
2829 	onepass->keyalg = sigpkt.u.sigpkt.sig.keyalg;
2830 	return 1;
2831 }
2832 
2833 /* match the calculated signature against the one in the signature packet */
2834 static int
2835 match_sig(pgpv_cursor_t *cursor, pgpv_signature_t *signature, pgpv_pubkey_t *pubkey, uint8_t *data, size_t size)
2836 {
2837 	unsigned	calclen;
2838 	uint8_t		calculated[64];
2839 	int		match;
2840 
2841 	calclen = pgpv_digest_memory(calculated, sizeof(calculated),
2842 		data, size,
2843 		get_ref(&signature->hashstart), signature->hashlen,
2844 		(signature->type == SIGTYPE_TEXT) ? 't' : 'b');
2845 	if (ALG_IS_RSA(signature->keyalg)) {
2846 		match = rsa_verify(calculated, calclen, signature->hashalg, signature->bn, pubkey);
2847 	} else if (ALG_IS_DSA(signature->keyalg)) {
2848 		match = verify_dsa_sig(calculated, calclen, signature->bn, pubkey);
2849 	} else {
2850 		snprintf(cursor->why, sizeof(cursor->why), "Signature type %u not recognised", signature->keyalg);
2851 		return 0;
2852 	}
2853 	if (!match && signature->type == SIGTYPE_TEXT) {
2854 		/* second try for cleartext data, ignoring trailing whitespace */
2855 		calclen = pgpv_digest_memory(calculated, sizeof(calculated),
2856 			data, size,
2857 			get_ref(&signature->hashstart), signature->hashlen, 'w');
2858 		if (ALG_IS_RSA(signature->keyalg)) {
2859 			match = rsa_verify(calculated, calclen, signature->hashalg, signature->bn, pubkey);
2860 		} else if (ALG_IS_DSA(signature->keyalg)) {
2861 			match = verify_dsa_sig(calculated, calclen, signature->bn, pubkey);
2862 		}
2863 	}
2864 	if (!match) {
2865 		snprintf(cursor->why, sizeof(cursor->why), "Signature on data did not match");
2866 		return 0;
2867 	}
2868 	if (valid_dates(signature, pubkey, cursor->why, sizeof(cursor->why)) > 0) {
2869 		return 0;
2870 	}
2871 	if (key_expired(pubkey, cursor->why, sizeof(cursor->why))) {
2872 		return 0;
2873 	}
2874 	if (signature->revoked) {
2875 		snprintf(cursor->why, sizeof(cursor->why), "Signature was revoked");
2876 		return 0;
2877 	}
2878 	return 1;
2879 }
2880 
2881 /* fixup key id, with birth, keyalg and hashalg value from signature */
2882 static int
2883 fixup_ssh_keyid(pgpv_t *pgp, pgpv_signature_t *signature, const char *hashtype)
2884 {
2885 	pgpv_pubkey_t	*pubkey;
2886 	unsigned	 i;
2887 
2888 	for (i = 0 ; i < ARRAY_COUNT(pgp->primaries) ; i++) {
2889 		pubkey = &ARRAY_ELEMENT(pgp->primaries, i).primary;
2890 		pubkey->keyalg = signature->keyalg;
2891 		calc_keyid(pubkey, hashtype);
2892 	}
2893 	return 1;
2894 }
2895 
2896 /* find key id */
2897 static int
2898 find_keyid(pgpv_t *pgp, const char *strkeyid, uint8_t *keyid, unsigned *sub)
2899 {
2900 	pgpv_signed_subkey_t	*subkey;
2901 	pgpv_primarykey_t	*prim;
2902 	unsigned		 i;
2903 	unsigned		 j;
2904 	uint64_t		 n;
2905 	uint8_t			 binkeyid[PGPV_KEYID_LEN];
2906 	size_t			 off;
2907 	size_t			 cmp;
2908 
2909 	if (strkeyid == NULL && keyid == NULL) {
2910 		return 0;
2911 	}
2912 	if (strkeyid) {
2913 		str_to_keyid(strkeyid, binkeyid);
2914 		cmp = strlen(strkeyid) / 2;
2915 	} else {
2916 		memcpy(binkeyid, keyid, sizeof(binkeyid));
2917 		cmp = PGPV_KEYID_LEN;
2918 	}
2919 	*sub = 0;
2920 	off = PGPV_KEYID_LEN - cmp;
2921 	for (i = 0 ; i < ARRAY_COUNT(pgp->primaries) ; i++) {
2922 		prim = &ARRAY_ELEMENT(pgp->primaries, i);
2923 		if (memcmp(&prim->primary.keyid[off], &binkeyid[off], cmp) == 0) {
2924 			return i;
2925 		}
2926 		for (j = 0 ; j < ARRAY_COUNT(prim->signed_subkeys) ; j++) {
2927 			n = ARRAY_ELEMENT(prim->signed_subkeys, j);
2928 			subkey = &ARRAY_ELEMENT(pgp->signed_subkeys, n);
2929 			if (memcmp(&subkey->subkey.keyid[off], &binkeyid[off], cmp) == 0) {
2930 				*sub = j + 1;
2931 				return i;
2932 			}
2933 		}
2934 
2935 	}
2936 	return -1;
2937 }
2938 
2939 /* match the signature with the id indexed by 'primary' */
2940 static int
2941 match_sig_id(pgpv_cursor_t *cursor, pgpv_t *pgp, pgpv_signature_t *signature, pgpv_litdata_t *litdata, unsigned primary, unsigned sub)
2942 {
2943 	pgpv_primarykey_t	*prim;
2944 	pgpv_pubkey_t		*pubkey;
2945 	uint64_t		 n;
2946 	uint8_t			*data;
2947 	size_t			 insize;
2948 
2949 	cursor->sigtime = signature->birth;
2950 	/* calc hash on data packet */
2951 	data = get_literal_data(cursor, litdata, &insize);
2952 	if (sub == 0) {
2953 		pubkey = &ARRAY_ELEMENT(cursor->pgp->primaries, primary).primary;
2954 		return match_sig(cursor, signature, pubkey, data, insize);
2955 	}
2956 	prim = &ARRAY_ELEMENT(cursor->pgp->primaries, primary);
2957 	n = ARRAY_ELEMENT(prim->signed_subkeys, sub - 1);
2958 	pubkey = &ARRAY_ELEMENT(pgp->signed_subkeys, n).subkey;
2959 	return match_sig(cursor, signature, pubkey, data, insize);
2960 }
2961 
2962 /* return the packet type */
2963 static const char *
2964 get_packet_type(uint8_t tag)
2965 {
2966 	switch(tag) {
2967 	case SIGNATURE_PKT:
2968 		return "signature packet";
2969 	case ONEPASS_SIGNATURE_PKT:
2970 		return "onepass signature packet";
2971 	case PUBKEY_PKT:
2972 		return "pubkey packet";
2973 	case COMPRESSED_DATA_PKT:
2974 		return "compressed data packet";
2975 	case MARKER_PKT:
2976 		return "marker packet";
2977 	case LITDATA_PKT:
2978 		return "litdata packet";
2979 	case TRUST_PKT:
2980 		return "trust packet";
2981 	case USERID_PKT:
2982 		return "userid packet";
2983 	case PUB_SUBKEY_PKT:
2984 		return "public subkey packet";
2985 	case USER_ATTRIBUTE_PKT:
2986 		return "user attribute packet";
2987 	default:
2988 		return "[UNKNOWN]";
2989 	}
2990 }
2991 
2992 /* check return value from getenv */
2993 static const char *
2994 nonnull_getenv(const char *key)
2995 {
2996 	char	*value;
2997 
2998 	return ((value = getenv(key)) == NULL) ? "" : value;
2999 }
3000 
3001 /* free an array of bignums */
3002 static void
3003 free_bn_array(pgpv_bignum_t *v, unsigned n)
3004 {
3005 	unsigned	i;
3006 
3007 	for (i = 0 ; i < n ; i++) {
3008 		PGPV_BN_clear_free(v[i].bn);
3009 		v[i].bn = NULL;
3010 	}
3011 }
3012 
3013 /************************************************************************/
3014 /* start of exported functions */
3015 /************************************************************************/
3016 
3017 /* close all stuff */
3018 int
3019 pgpv_close(pgpv_t *pgp)
3020 {
3021 	pgpv_primarykey_t	*primary;
3022 	pgpv_pkt_t		*pkt;
3023 	uint64_t		 n;
3024 	unsigned		 i;
3025 	unsigned		 j;
3026 
3027 	if (pgp == NULL) {
3028 		return 0;
3029 	}
3030 	for (i = 0 ; i < ARRAY_COUNT(pgp->areas) ; i++) {
3031 		if (ARRAY_ELEMENT(pgp->areas, i).size > 0) {
3032 			closemem(&ARRAY_ELEMENT(pgp->areas, i));
3033 		}
3034 	}
3035         ARRAY_FREE(pgp->areas);
3036         for (i = 0 ; i < ARRAY_COUNT(pgp->pkts) ; i++) {
3037                 pkt = &ARRAY_ELEMENT(pgp->pkts, i);
3038                 switch(pkt->tag) {
3039                 case SIGNATURE_PKT:
3040                         ARRAY_FREE(pkt->u.sigpkt.subpackets);
3041                         break;
3042                 case LITDATA_PKT:
3043 			if (pkt->u.litdata.filename.allocated) {
3044 				free(pkt->u.litdata.filename.data);
3045 			}
3046                         break;
3047 		case PUBKEY_PKT:
3048 			free_bn_array(pkt->u.pubkey.bn, PGPV_MAX_PUBKEY_BN);
3049 			break;
3050                 case USERID_PKT:
3051 			if (pkt->u.userid.allocated) {
3052 				free(pkt->u.userid.data);
3053 			}
3054                         break;
3055                 case USER_ATTRIBUTE_PKT:
3056                         ARRAY_FREE(pkt->u.userattr.subattrs);
3057                         break;
3058                 }
3059         }
3060         ARRAY_FREE(pgp->pkts);
3061 	for (i = 0 ; i < ARRAY_COUNT(pgp->primaries) ; i++) {
3062 		primary = &ARRAY_ELEMENT(pgp->primaries, i);
3063 		free_bn_array(primary->primary.bn, PGPV_MAX_PUBKEY_BN);
3064 		ARRAY_FREE(primary->signatures);
3065 		for (j = 0 ; j < ARRAY_COUNT(primary->signed_userids) ; j++) {
3066 			n = ARRAY_ELEMENT(primary->signed_userids, j);
3067 			ARRAY_FREE(ARRAY_ELEMENT(pgp->signed_userids, n).signatures);
3068 		}
3069 		ARRAY_FREE(primary->signed_userids);
3070 		ARRAY_FREE(primary->signed_userattrs);
3071 		ARRAY_FREE(primary->signed_subkeys);
3072 	}
3073 	for (i = 0 ; i < ARRAY_COUNT(pgp->signatures) ; i++) {
3074 		free_bn_array(ARRAY_ELEMENT(pgp->signatures, i).bn, PGPV_MAX_SIG_BN);
3075 	}
3076 	for (i = 0 ; i < ARRAY_COUNT(pgp->signed_subkeys) ; i++) {
3077 		free_bn_array(ARRAY_ELEMENT(pgp->signed_subkeys, i).subkey.bn, PGPV_MAX_SIG_BN);
3078 	}
3079 	ARRAY_FREE(pgp->primaries);
3080 	ARRAY_FREE(pgp->datastarts);
3081 	ARRAY_FREE(pgp->signatures);
3082 	ARRAY_FREE(pgp->signed_userids);
3083 	ARRAY_FREE(pgp->signed_userattrs);
3084 	ARRAY_FREE(pgp->signed_subkeys);
3085 	ARRAY_FREE(pgp->subpkts);
3086 	return 1;
3087 }
3088 
3089 /* free resources attached to cursor */
3090 int
3091 pgpv_cursor_close(pgpv_cursor_t *cursor)
3092 {
3093 	if (cursor) {
3094 		ARRAY_FREE(cursor->datacookies);
3095 		ARRAY_FREE(cursor->found);
3096 	}
3097 	return 0;
3098 }
3099 
3100 /* return the formatted entry for the primary key desired */
3101 size_t
3102 pgpv_get_entry(pgpv_t *pgp, unsigned ent, char **s, const char *modifiers)
3103 {
3104 	unsigned	subkey;
3105 	unsigned	prim;
3106 	obuf_t		obuf;
3107 
3108 	prim = ((ent >> 8) & 0xffffff);
3109 	subkey = (ent & 0xff);
3110 	if (s == NULL || pgp == NULL || prim >= ARRAY_COUNT(pgp->primaries)) {
3111 		return 0;
3112 	}
3113 	*s = NULL;
3114 	if (modifiers == NULL || (strcasecmp(modifiers, "trust") != 0 && strcasecmp(modifiers, "subkeys") != 0)) {
3115 		modifiers = "no-subkeys";
3116 	}
3117 	memset(&obuf, 0x0, sizeof(obuf));
3118 	if (!fmt_primary(&obuf, pgp, &ARRAY_ELEMENT(pgp->primaries, prim), subkey, modifiers)) {
3119 		return 0;
3120 	}
3121 	*s = (char *)obuf.v;
3122 	return obuf.c;
3123 }
3124 
3125 /* make a new pgpv struct */
3126 pgpv_t *
3127 pgpv_new(void)
3128 {
3129 	return calloc(1, sizeof(pgpv_t));
3130 }
3131 
3132 /* make a new pgpv_cursor struct */
3133 pgpv_cursor_t *
3134 pgpv_new_cursor(void)
3135 {
3136 	return calloc(1, sizeof(pgpv_cursor_t));
3137 }
3138 
3139 /* get an element from the found array */
3140 int
3141 pgpv_get_cursor_element(pgpv_cursor_t *cursor, size_t element)
3142 {
3143 	if (cursor && element < ARRAY_COUNT(cursor->found)) {
3144 		return (int)ARRAY_ELEMENT(cursor->found, element);
3145 	}
3146 	return -1;
3147 }
3148 
3149 /* verify the signed packets we have */
3150 size_t
3151 pgpv_verify(pgpv_cursor_t *cursor, pgpv_t *pgp, const void *p, ssize_t size)
3152 {
3153 	pgpv_signature_t	*signature;
3154 	pgpv_onepass_t		*onepass;
3155 	pgpv_litdata_t		*litdata;
3156 	unsigned		 sub;
3157 	size_t			 pkt;
3158 	obuf_t			 obuf;
3159 	int			 j;
3160 
3161 	if (cursor == NULL || pgp == NULL || p == NULL) {
3162 		return 0;
3163 	}
3164 	if (!setup_data(cursor, pgp, p, size)) {
3165 		snprintf(cursor->why, sizeof(cursor->why), "No input data");
3166 		return 0;
3167 	}
3168 	if (ARRAY_COUNT(cursor->pgp->pkts) == ARRAY_LAST(cursor->pgp->datastarts) + 1) {
3169 		/* got detached signature here */
3170 		if (!fixup_detached(cursor, p)) {
3171 			snprintf(cursor->why, sizeof(cursor->why), "Can't read signed file '%s'", (const char *)p);
3172 			return 0;
3173 		}
3174 	}
3175 	if ((pkt = find_onepass(cursor, ARRAY_LAST(cursor->pgp->datastarts))) == 0) {
3176 		snprintf(cursor->why, sizeof(cursor->why), "No signature found");
3177 		return 0;
3178 	}
3179 	pkt -= 1;
3180 	onepass = &ARRAY_ELEMENT(cursor->pgp->pkts, pkt).u.onepass;
3181 	litdata = &ARRAY_ELEMENT(cursor->pgp->pkts, pkt + 1).u.litdata;
3182 	signature = &ARRAY_ELEMENT(cursor->pgp->pkts, pkt + 2).u.sigpkt.sig;
3183 	/* sanity check values in signature and onepass agree */
3184 	if (signature->birth == 0) {
3185 		if (!fmt_time(&obuf, "Signature creation time [",
3186 				signature->birth, "] out of range", 0)) {
3187 		}
3188 		snprintf(cursor->why, sizeof(cursor->why), "%.*s", (int)obuf.c, (char *)obuf.v);
3189 		return 0;
3190 	}
3191 	memset(&obuf, 0x0, sizeof(obuf));
3192 	if (memcmp(onepass->keyid, signature->signer, PGPV_KEYID_LEN) != 0) {
3193 		if (!fmt_binary(&obuf, onepass->keyid, (unsigned)sizeof(onepass->keyid))) {
3194 			snprintf(cursor->why, sizeof(cursor->why), "Memory allocation failure");
3195 			return 0;
3196 		}
3197 		snprintf(cursor->why, sizeof(cursor->why),
3198 			"Signature key id %.*s does not match onepass keyid",
3199 			(int)obuf.c, (char *)obuf.v);
3200 		return 0;
3201 	}
3202 	if (onepass->hashalg != signature->hashalg) {
3203 		snprintf(cursor->why, sizeof(cursor->why),
3204 			"Signature hashalg %u does not match onepass hashalg %u",
3205 			signature->hashalg, onepass->hashalg);
3206 		return 0;
3207 	}
3208 	if (onepass->keyalg != signature->keyalg) {
3209 		snprintf(cursor->why, sizeof(cursor->why),
3210 			"Signature keyalg %u does not match onepass keyalg %u",
3211 			signature->keyalg, onepass->keyalg);
3212 		return 0;
3213 	}
3214 	if (cursor->pgp->ssh) {
3215 		fixup_ssh_keyid(cursor->pgp, signature, "sha1");
3216 	}
3217 	sub = 0;
3218 	if ((j = find_keyid(cursor->pgp, NULL, onepass->keyid, &sub)) < 0) {
3219 		if (!fmt_binary(&obuf, onepass->keyid, (unsigned)sizeof(onepass->keyid))) {
3220 			snprintf(cursor->why, sizeof(cursor->why), "Memory allocation failure");
3221 			return 0;
3222 		}
3223 		snprintf(cursor->why, sizeof(cursor->why),
3224 			"Signature key id %.*s not found ",
3225 			(int)obuf.c, (char *)obuf.v);
3226 		return 0;
3227 	}
3228 	if (!match_sig_id(cursor, pgp, signature, litdata, (unsigned)j, sub)) {
3229 		return 0;
3230 	}
3231 	ARRAY_APPEND(cursor->datacookies, pkt);
3232 	j = ((j & 0xffffff) << 8) | (sub & 0xff);
3233 	ARRAY_APPEND(cursor->found, j);
3234 	return pkt + 1;
3235 }
3236 
3237 /* set up the pubkey keyring */
3238 int
3239 pgpv_read_pubring(pgpv_t *pgp, const void *keyring, ssize_t size)
3240 {
3241 	if (pgp == NULL) {
3242 		return 0;
3243 	}
3244 	if (keyring) {
3245 		return (size > 0) ?
3246 			read_binary_memory(pgp, "pubring", keyring, (size_t)size) :
3247 			read_binary_file(pgp, "pubring", "%s", (const char *)keyring);
3248 	}
3249 	return read_binary_file(pgp, "pubring", "%s/%s", nonnull_getenv("HOME"), ".gnupg/pubring.gpg");
3250 }
3251 
3252 /* set up the pubkey keyring from ssh pub key */
3253 int
3254 pgpv_read_ssh_pubkeys(pgpv_t *pgp, const void *keyring, ssize_t size)
3255 {
3256 	pgpv_primarykey_t	primary;
3257 
3258 	USE_ARG(size);
3259 	if (pgp == NULL) {
3260 		return 0;
3261 	}
3262 	if (keyring) {
3263 		if (!read_ssh_file(pgp, &primary, "%s", (const char *)keyring)) {
3264 			return 0;
3265 		}
3266 	} else if (!read_ssh_file(pgp, &primary, "%s/%s", nonnull_getenv("HOME"), ".ssh/id_rsa.pub")) {
3267 		return 0;
3268 	}
3269 	ARRAY_APPEND(pgp->primaries, primary);
3270 	pgp->ssh = 1;
3271 	return 1;
3272 }
3273 
3274 /* get verified data as a string, return its size */
3275 size_t
3276 pgpv_get_verified(pgpv_cursor_t *cursor, size_t cookie, char **ret)
3277 {
3278 	pgpv_litdata_t		*litdata;
3279 	uint8_t			*data;
3280 	size_t			 size;
3281 	size_t			 pkt;
3282 
3283 	if (ret == NULL || cursor == NULL || cookie == 0) {
3284 		return 0;
3285 	}
3286 	*ret = NULL;
3287 	if ((pkt = find_onepass(cursor, cookie - 1)) == 0) {
3288 		return 0;
3289 	}
3290 	litdata = &ARRAY_ELEMENT(cursor->pgp->pkts, pkt).u.litdata;
3291 	data = get_literal_data(cursor, litdata, &size);
3292 	if ((*ret = calloc(1, size)) == NULL) {
3293 		return 0;
3294 	}
3295 	memcpy(*ret, data, size);
3296 	return size;
3297 }
3298 
3299 #define KB(x)	((x) * 1024)
3300 
3301 /* dump all packets */
3302 size_t
3303 pgpv_dump(pgpv_t *pgp, char **data)
3304 {
3305 	ssize_t	 dumpc;
3306 	size_t	 alloc;
3307 	size_t	 pkt;
3308 	size_t	 cc;
3309 	size_t	 n;
3310 	char	 buf[800];
3311 	char	*newdata;
3312 
3313 	cc = alloc = 0;
3314 	*data = NULL;
3315 	for (pkt = 0 ; pkt < ARRAY_COUNT(pgp->pkts) ; pkt++) {
3316 		if (cc + KB(64) >= alloc) {
3317 			if ((newdata = realloc(*data, alloc + KB(64))) == NULL) {
3318 				return cc;
3319 			}
3320 			alloc += KB(64);
3321 			*data = newdata;
3322 		}
3323 		memset(buf, 0x0, sizeof(buf));
3324 		dumpc = netpgp_hexdump(ARRAY_ELEMENT(pgp->pkts, pkt).s.data,
3325 				MIN((sizeof(buf) / 80) * 16,
3326 				ARRAY_ELEMENT(pgp->pkts, pkt).s.size),
3327 				buf, sizeof(buf));
3328 		n = snprintf(&(*data)[cc], alloc - cc,
3329 			"[%zu] off %zu, len %zu, tag %u, %s\n%.*s",
3330 			pkt,
3331 			ARRAY_ELEMENT(pgp->pkts, pkt).offset,
3332 			ARRAY_ELEMENT(pgp->pkts, pkt).s.size,
3333 			ARRAY_ELEMENT(pgp->pkts, pkt).tag,
3334 			get_packet_type(ARRAY_ELEMENT(pgp->pkts, pkt).tag),
3335 			(int)dumpc, buf);
3336 		cc += n;
3337 	}
3338 	return cc;
3339 }
3340 
3341 /* return cursor field as a number */
3342 int64_t
3343 pgpv_get_cursor_num(pgpv_cursor_t *cursor, const char *field)
3344 {
3345 	if (cursor && field) {
3346 		if (strcmp(field, "sigtime") == 0) {
3347 			return cursor->sigtime;
3348 		}
3349 	}
3350 	return 0;
3351 }
3352 
3353 /* return cursor field as a string */
3354 char *
3355 pgpv_get_cursor_str(pgpv_cursor_t *cursor, const char *field)
3356 {
3357 	if (cursor && field) {
3358 		if (strcmp(field, "why") == 0) {
3359 			return cursor->why;
3360 		}
3361 	}
3362 	return 0;
3363 }
3364