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