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