1*ebfedea0SLionel Sambuc /*-
2*ebfedea0SLionel Sambuc * Copyright (c) 2009 The NetBSD Foundation, Inc.
3*ebfedea0SLionel Sambuc * All rights reserved.
4*ebfedea0SLionel Sambuc *
5*ebfedea0SLionel Sambuc * This code is derived from software contributed to The NetBSD Foundation
6*ebfedea0SLionel Sambuc * by Alistair Crooks (agc@NetBSD.org)
7*ebfedea0SLionel Sambuc *
8*ebfedea0SLionel Sambuc * Redistribution and use in source and binary forms, with or without
9*ebfedea0SLionel Sambuc * modification, are permitted provided that the following conditions
10*ebfedea0SLionel Sambuc * are met:
11*ebfedea0SLionel Sambuc * 1. Redistributions of source code must retain the above copyright
12*ebfedea0SLionel Sambuc * notice, this list of conditions and the following disclaimer.
13*ebfedea0SLionel Sambuc * 2. Redistributions in binary form must reproduce the above copyright
14*ebfedea0SLionel Sambuc * notice, this list of conditions and the following disclaimer in the
15*ebfedea0SLionel Sambuc * documentation and/or other materials provided with the distribution.
16*ebfedea0SLionel Sambuc *
17*ebfedea0SLionel Sambuc * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
18*ebfedea0SLionel Sambuc * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19*ebfedea0SLionel Sambuc * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20*ebfedea0SLionel Sambuc * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
21*ebfedea0SLionel Sambuc * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22*ebfedea0SLionel Sambuc * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23*ebfedea0SLionel Sambuc * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24*ebfedea0SLionel Sambuc * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25*ebfedea0SLionel Sambuc * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26*ebfedea0SLionel Sambuc * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27*ebfedea0SLionel Sambuc * POSSIBILITY OF SUCH DAMAGE.
28*ebfedea0SLionel Sambuc */
29*ebfedea0SLionel Sambuc /*
30*ebfedea0SLionel Sambuc * Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
31*ebfedea0SLionel Sambuc * All rights reserved.
32*ebfedea0SLionel Sambuc * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
33*ebfedea0SLionel Sambuc * their moral rights under the UK Copyright Design and Patents Act 1988 to
34*ebfedea0SLionel Sambuc * be recorded as the authors of this copyright work.
35*ebfedea0SLionel Sambuc *
36*ebfedea0SLionel Sambuc * Licensed under the Apache License, Version 2.0 (the "License"); you may not
37*ebfedea0SLionel Sambuc * use this file except in compliance with the License.
38*ebfedea0SLionel Sambuc *
39*ebfedea0SLionel Sambuc * You may obtain a copy of the License at
40*ebfedea0SLionel Sambuc * http://www.apache.org/licenses/LICENSE-2.0
41*ebfedea0SLionel Sambuc *
42*ebfedea0SLionel Sambuc * Unless required by applicable law or agreed to in writing, software
43*ebfedea0SLionel Sambuc * distributed under the License is distributed on an "AS IS" BASIS,
44*ebfedea0SLionel Sambuc * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
45*ebfedea0SLionel Sambuc *
46*ebfedea0SLionel Sambuc * See the License for the specific language governing permissions and
47*ebfedea0SLionel Sambuc * limitations under the License.
48*ebfedea0SLionel Sambuc */
49*ebfedea0SLionel Sambuc #include "config.h"
50*ebfedea0SLionel Sambuc
51*ebfedea0SLionel Sambuc #ifdef HAVE_SYS_CDEFS_H
52*ebfedea0SLionel Sambuc #include <sys/cdefs.h>
53*ebfedea0SLionel Sambuc #endif
54*ebfedea0SLionel Sambuc
55*ebfedea0SLionel Sambuc #if defined(__NetBSD__)
56*ebfedea0SLionel Sambuc __COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved.");
57*ebfedea0SLionel Sambuc __RCSID("$NetBSD: reader.c,v 1.49 2012/03/05 02:20:18 christos Exp $");
58*ebfedea0SLionel Sambuc #endif
59*ebfedea0SLionel Sambuc
60*ebfedea0SLionel Sambuc #include <sys/types.h>
61*ebfedea0SLionel Sambuc #include <sys/stat.h>
62*ebfedea0SLionel Sambuc
63*ebfedea0SLionel Sambuc #ifdef HAVE_SYS_MMAN_H
64*ebfedea0SLionel Sambuc #include <sys/mman.h>
65*ebfedea0SLionel Sambuc #endif
66*ebfedea0SLionel Sambuc
67*ebfedea0SLionel Sambuc #ifdef HAVE_SYS_PARAM_H
68*ebfedea0SLionel Sambuc #include <sys/param.h>
69*ebfedea0SLionel Sambuc #endif
70*ebfedea0SLionel Sambuc
71*ebfedea0SLionel Sambuc #ifdef HAVE_FCNTL_H
72*ebfedea0SLionel Sambuc #include <fcntl.h>
73*ebfedea0SLionel Sambuc #endif
74*ebfedea0SLionel Sambuc
75*ebfedea0SLionel Sambuc #ifdef HAVE_UNISTD_H
76*ebfedea0SLionel Sambuc #include <unistd.h>
77*ebfedea0SLionel Sambuc #endif
78*ebfedea0SLionel Sambuc
79*ebfedea0SLionel Sambuc #ifdef HAVE_DIRECT_H
80*ebfedea0SLionel Sambuc #include <direct.h>
81*ebfedea0SLionel Sambuc #endif
82*ebfedea0SLionel Sambuc
83*ebfedea0SLionel Sambuc #ifdef HAVE_INTTYPES_H
84*ebfedea0SLionel Sambuc #include <inttypes.h>
85*ebfedea0SLionel Sambuc #endif
86*ebfedea0SLionel Sambuc
87*ebfedea0SLionel Sambuc #ifdef HAVE_OPENSSL_IDEA_H
88*ebfedea0SLionel Sambuc #include <openssl/cast.h>
89*ebfedea0SLionel Sambuc #endif
90*ebfedea0SLionel Sambuc
91*ebfedea0SLionel Sambuc #ifdef HAVE_OPENSSL_IDEA_H
92*ebfedea0SLionel Sambuc #include <openssl/idea.h>
93*ebfedea0SLionel Sambuc #endif
94*ebfedea0SLionel Sambuc
95*ebfedea0SLionel Sambuc #ifdef HAVE_OPENSSL_AES_H
96*ebfedea0SLionel Sambuc #include <openssl/aes.h>
97*ebfedea0SLionel Sambuc #endif
98*ebfedea0SLionel Sambuc
99*ebfedea0SLionel Sambuc #ifdef HAVE_OPENSSL_DES_H
100*ebfedea0SLionel Sambuc #include <openssl/des.h>
101*ebfedea0SLionel Sambuc #endif
102*ebfedea0SLionel Sambuc
103*ebfedea0SLionel Sambuc #include <string.h>
104*ebfedea0SLionel Sambuc #include <stdlib.h>
105*ebfedea0SLionel Sambuc #include <stdio.h>
106*ebfedea0SLionel Sambuc
107*ebfedea0SLionel Sambuc #ifdef HAVE_TERMIOS_H
108*ebfedea0SLionel Sambuc #include <termios.h>
109*ebfedea0SLionel Sambuc #endif
110*ebfedea0SLionel Sambuc
111*ebfedea0SLionel Sambuc #ifdef HAVE_ERRNO_H
112*ebfedea0SLionel Sambuc #include <errno.h>
113*ebfedea0SLionel Sambuc #endif
114*ebfedea0SLionel Sambuc
115*ebfedea0SLionel Sambuc #ifdef HAVE_UNISTD_H
116*ebfedea0SLionel Sambuc #include <unistd.h>
117*ebfedea0SLionel Sambuc #endif
118*ebfedea0SLionel Sambuc
119*ebfedea0SLionel Sambuc #ifdef HAVE_LIMITS_H
120*ebfedea0SLionel Sambuc #include <limits.h>
121*ebfedea0SLionel Sambuc #endif
122*ebfedea0SLionel Sambuc
123*ebfedea0SLionel Sambuc #include "errors.h"
124*ebfedea0SLionel Sambuc #include "crypto.h"
125*ebfedea0SLionel Sambuc #include "create.h"
126*ebfedea0SLionel Sambuc #include "signature.h"
127*ebfedea0SLionel Sambuc #include "packet.h"
128*ebfedea0SLionel Sambuc #include "packet-parse.h"
129*ebfedea0SLionel Sambuc #include "packet-show.h"
130*ebfedea0SLionel Sambuc #include "packet.h"
131*ebfedea0SLionel Sambuc #include "keyring.h"
132*ebfedea0SLionel Sambuc #include "readerwriter.h"
133*ebfedea0SLionel Sambuc #include "netpgpsdk.h"
134*ebfedea0SLionel Sambuc #include "netpgpdefs.h"
135*ebfedea0SLionel Sambuc #include "netpgpdigest.h"
136*ebfedea0SLionel Sambuc
137*ebfedea0SLionel Sambuc /* data from partial blocks is queued up in virtual block in stream */
138*ebfedea0SLionel Sambuc static int
read_partial_data(pgp_stream_t * stream,void * dest,size_t length)139*ebfedea0SLionel Sambuc read_partial_data(pgp_stream_t *stream, void *dest, size_t length)
140*ebfedea0SLionel Sambuc {
141*ebfedea0SLionel Sambuc unsigned n;
142*ebfedea0SLionel Sambuc
143*ebfedea0SLionel Sambuc if (pgp_get_debug_level(__FILE__)) {
144*ebfedea0SLionel Sambuc (void) fprintf(stderr, "fd_reader: coalesced data, off %d\n",
145*ebfedea0SLionel Sambuc stream->virtualoff);
146*ebfedea0SLionel Sambuc }
147*ebfedea0SLionel Sambuc n = MIN(stream->virtualc - stream->virtualoff, (unsigned)length);
148*ebfedea0SLionel Sambuc (void) memcpy(dest, &stream->virtualpkt[stream->virtualoff], n);
149*ebfedea0SLionel Sambuc stream->virtualoff += n;
150*ebfedea0SLionel Sambuc if (stream->virtualoff == stream->virtualc) {
151*ebfedea0SLionel Sambuc free(stream->virtualpkt);
152*ebfedea0SLionel Sambuc stream->virtualpkt = NULL;
153*ebfedea0SLionel Sambuc stream->virtualc = stream->virtualoff = 0;
154*ebfedea0SLionel Sambuc }
155*ebfedea0SLionel Sambuc return (int)n;
156*ebfedea0SLionel Sambuc }
157*ebfedea0SLionel Sambuc
158*ebfedea0SLionel Sambuc /* get a pass phrase from the user */
159*ebfedea0SLionel Sambuc int
pgp_getpassphrase(void * in,char * phrase,size_t size)160*ebfedea0SLionel Sambuc pgp_getpassphrase(void *in, char *phrase, size_t size)
161*ebfedea0SLionel Sambuc {
162*ebfedea0SLionel Sambuc char *p;
163*ebfedea0SLionel Sambuc
164*ebfedea0SLionel Sambuc if (in == NULL) {
165*ebfedea0SLionel Sambuc while ((p = getpass("netpgp passphrase: ")) == NULL) {
166*ebfedea0SLionel Sambuc }
167*ebfedea0SLionel Sambuc (void) snprintf(phrase, size, "%s", p);
168*ebfedea0SLionel Sambuc } else {
169*ebfedea0SLionel Sambuc if (fgets(phrase, (int)size, in) == NULL) {
170*ebfedea0SLionel Sambuc return 0;
171*ebfedea0SLionel Sambuc }
172*ebfedea0SLionel Sambuc phrase[strlen(phrase) - 1] = 0x0;
173*ebfedea0SLionel Sambuc }
174*ebfedea0SLionel Sambuc return 1;
175*ebfedea0SLionel Sambuc }
176*ebfedea0SLionel Sambuc
177*ebfedea0SLionel Sambuc /**
178*ebfedea0SLionel Sambuc * \ingroup Internal_Readers_Generic
179*ebfedea0SLionel Sambuc * \brief Starts reader stack
180*ebfedea0SLionel Sambuc * \param stream Parse settings
181*ebfedea0SLionel Sambuc * \param reader Reader to use
182*ebfedea0SLionel Sambuc * \param destroyer Destroyer to use
183*ebfedea0SLionel Sambuc * \param vp Reader-specific arg
184*ebfedea0SLionel Sambuc */
185*ebfedea0SLionel Sambuc void
pgp_reader_set(pgp_stream_t * stream,pgp_reader_func_t * reader,pgp_reader_destroyer_t * destroyer,void * vp)186*ebfedea0SLionel Sambuc pgp_reader_set(pgp_stream_t *stream,
187*ebfedea0SLionel Sambuc pgp_reader_func_t *reader,
188*ebfedea0SLionel Sambuc pgp_reader_destroyer_t *destroyer,
189*ebfedea0SLionel Sambuc void *vp)
190*ebfedea0SLionel Sambuc {
191*ebfedea0SLionel Sambuc stream->readinfo.reader = reader;
192*ebfedea0SLionel Sambuc stream->readinfo.destroyer = destroyer;
193*ebfedea0SLionel Sambuc stream->readinfo.arg = vp;
194*ebfedea0SLionel Sambuc }
195*ebfedea0SLionel Sambuc
196*ebfedea0SLionel Sambuc /**
197*ebfedea0SLionel Sambuc * \ingroup Internal_Readers_Generic
198*ebfedea0SLionel Sambuc * \brief Adds to reader stack
199*ebfedea0SLionel Sambuc * \param stream Parse settings
200*ebfedea0SLionel Sambuc * \param reader Reader to use
201*ebfedea0SLionel Sambuc * \param destroyer Reader's destroyer
202*ebfedea0SLionel Sambuc * \param vp Reader-specific arg
203*ebfedea0SLionel Sambuc */
204*ebfedea0SLionel Sambuc void
pgp_reader_push(pgp_stream_t * stream,pgp_reader_func_t * reader,pgp_reader_destroyer_t * destroyer,void * vp)205*ebfedea0SLionel Sambuc pgp_reader_push(pgp_stream_t *stream,
206*ebfedea0SLionel Sambuc pgp_reader_func_t *reader,
207*ebfedea0SLionel Sambuc pgp_reader_destroyer_t *destroyer,
208*ebfedea0SLionel Sambuc void *vp)
209*ebfedea0SLionel Sambuc {
210*ebfedea0SLionel Sambuc pgp_reader_t *readinfo;
211*ebfedea0SLionel Sambuc
212*ebfedea0SLionel Sambuc if ((readinfo = calloc(1, sizeof(*readinfo))) == NULL) {
213*ebfedea0SLionel Sambuc (void) fprintf(stderr, "pgp_reader_push: bad alloc\n");
214*ebfedea0SLionel Sambuc } else {
215*ebfedea0SLionel Sambuc *readinfo = stream->readinfo;
216*ebfedea0SLionel Sambuc (void) memset(&stream->readinfo, 0x0, sizeof(stream->readinfo));
217*ebfedea0SLionel Sambuc stream->readinfo.next = readinfo;
218*ebfedea0SLionel Sambuc stream->readinfo.parent = stream;
219*ebfedea0SLionel Sambuc
220*ebfedea0SLionel Sambuc /* should copy accumulate flags from other reader? RW */
221*ebfedea0SLionel Sambuc stream->readinfo.accumulate = readinfo->accumulate;
222*ebfedea0SLionel Sambuc
223*ebfedea0SLionel Sambuc pgp_reader_set(stream, reader, destroyer, vp);
224*ebfedea0SLionel Sambuc }
225*ebfedea0SLionel Sambuc }
226*ebfedea0SLionel Sambuc
227*ebfedea0SLionel Sambuc /**
228*ebfedea0SLionel Sambuc * \ingroup Internal_Readers_Generic
229*ebfedea0SLionel Sambuc * \brief Removes from reader stack
230*ebfedea0SLionel Sambuc * \param stream Parse settings
231*ebfedea0SLionel Sambuc */
232*ebfedea0SLionel Sambuc void
pgp_reader_pop(pgp_stream_t * stream)233*ebfedea0SLionel Sambuc pgp_reader_pop(pgp_stream_t *stream)
234*ebfedea0SLionel Sambuc {
235*ebfedea0SLionel Sambuc pgp_reader_t *next = stream->readinfo.next;
236*ebfedea0SLionel Sambuc
237*ebfedea0SLionel Sambuc stream->readinfo = *next;
238*ebfedea0SLionel Sambuc free(next);
239*ebfedea0SLionel Sambuc }
240*ebfedea0SLionel Sambuc
241*ebfedea0SLionel Sambuc /**
242*ebfedea0SLionel Sambuc * \ingroup Internal_Readers_Generic
243*ebfedea0SLionel Sambuc * \brief Gets arg from reader
244*ebfedea0SLionel Sambuc * \param readinfo Reader info
245*ebfedea0SLionel Sambuc * \return Pointer to reader info's arg
246*ebfedea0SLionel Sambuc */
247*ebfedea0SLionel Sambuc void *
pgp_reader_get_arg(pgp_reader_t * readinfo)248*ebfedea0SLionel Sambuc pgp_reader_get_arg(pgp_reader_t *readinfo)
249*ebfedea0SLionel Sambuc {
250*ebfedea0SLionel Sambuc return readinfo->arg;
251*ebfedea0SLionel Sambuc }
252*ebfedea0SLionel Sambuc
253*ebfedea0SLionel Sambuc /**************************************************************************/
254*ebfedea0SLionel Sambuc
255*ebfedea0SLionel Sambuc #define CRC24_POLY 0x1864cfbL
256*ebfedea0SLionel Sambuc
257*ebfedea0SLionel Sambuc enum {
258*ebfedea0SLionel Sambuc NONE = 0,
259*ebfedea0SLionel Sambuc BEGIN_PGP_MESSAGE,
260*ebfedea0SLionel Sambuc BEGIN_PGP_PUBLIC_KEY_BLOCK,
261*ebfedea0SLionel Sambuc BEGIN_PGP_PRIVATE_KEY_BLOCK,
262*ebfedea0SLionel Sambuc BEGIN_PGP_MULTI,
263*ebfedea0SLionel Sambuc BEGIN_PGP_SIGNATURE,
264*ebfedea0SLionel Sambuc
265*ebfedea0SLionel Sambuc END_PGP_MESSAGE,
266*ebfedea0SLionel Sambuc END_PGP_PUBLIC_KEY_BLOCK,
267*ebfedea0SLionel Sambuc END_PGP_PRIVATE_KEY_BLOCK,
268*ebfedea0SLionel Sambuc END_PGP_MULTI,
269*ebfedea0SLionel Sambuc END_PGP_SIGNATURE,
270*ebfedea0SLionel Sambuc
271*ebfedea0SLionel Sambuc BEGIN_PGP_SIGNED_MESSAGE
272*ebfedea0SLionel Sambuc };
273*ebfedea0SLionel Sambuc
274*ebfedea0SLionel Sambuc /**
275*ebfedea0SLionel Sambuc * \struct dearmour_t
276*ebfedea0SLionel Sambuc */
277*ebfedea0SLionel Sambuc typedef struct {
278*ebfedea0SLionel Sambuc enum {
279*ebfedea0SLionel Sambuc OUTSIDE_BLOCK = 0,
280*ebfedea0SLionel Sambuc BASE64,
281*ebfedea0SLionel Sambuc AT_TRAILER_NAME
282*ebfedea0SLionel Sambuc } state;
283*ebfedea0SLionel Sambuc int lastseen;
284*ebfedea0SLionel Sambuc pgp_stream_t *parse_info;
285*ebfedea0SLionel Sambuc unsigned seen_nl:1;
286*ebfedea0SLionel Sambuc unsigned prev_nl:1;
287*ebfedea0SLionel Sambuc unsigned allow_headers_without_gap:1;
288*ebfedea0SLionel Sambuc /* !< allow headers in armoured data that are
289*ebfedea0SLionel Sambuc * not separated from the data by a blank line
290*ebfedea0SLionel Sambuc * */
291*ebfedea0SLionel Sambuc unsigned allow_no_gap:1;
292*ebfedea0SLionel Sambuc /* !< allow no blank line at the start of
293*ebfedea0SLionel Sambuc * armoured data */
294*ebfedea0SLionel Sambuc unsigned allow_trailing_whitespace:1;
295*ebfedea0SLionel Sambuc /* !< allow armoured stuff to have trailing
296*ebfedea0SLionel Sambuc * whitespace where we wouldn't strictly expect
297*ebfedea0SLionel Sambuc * it */
298*ebfedea0SLionel Sambuc /* it is an error to get a cleartext message without a sig */
299*ebfedea0SLionel Sambuc unsigned expect_sig:1;
300*ebfedea0SLionel Sambuc unsigned got_sig:1;
301*ebfedea0SLionel Sambuc /* base64 stuff */
302*ebfedea0SLionel Sambuc unsigned buffered;
303*ebfedea0SLionel Sambuc uint8_t buffer[3];
304*ebfedea0SLionel Sambuc unsigned eof64;
305*ebfedea0SLionel Sambuc uint32_t checksum;
306*ebfedea0SLionel Sambuc uint32_t read_checksum;
307*ebfedea0SLionel Sambuc /* unarmoured text blocks */
308*ebfedea0SLionel Sambuc uint8_t unarmoured[NETPGP_BUFSIZ];
309*ebfedea0SLionel Sambuc size_t unarmoredc;
310*ebfedea0SLionel Sambuc /* pushed back data (stored backwards) */
311*ebfedea0SLionel Sambuc uint8_t *pushback;
312*ebfedea0SLionel Sambuc unsigned pushbackc;
313*ebfedea0SLionel Sambuc /* armoured block headers */
314*ebfedea0SLionel Sambuc pgp_headers_t headers;
315*ebfedea0SLionel Sambuc } dearmour_t;
316*ebfedea0SLionel Sambuc
317*ebfedea0SLionel Sambuc static void
push_back(dearmour_t * dearmour,const uint8_t * buf,unsigned length)318*ebfedea0SLionel Sambuc push_back(dearmour_t *dearmour, const uint8_t *buf,
319*ebfedea0SLionel Sambuc unsigned length)
320*ebfedea0SLionel Sambuc {
321*ebfedea0SLionel Sambuc unsigned n;
322*ebfedea0SLionel Sambuc
323*ebfedea0SLionel Sambuc if (dearmour->pushback) {
324*ebfedea0SLionel Sambuc (void) fprintf(stderr, "push_back: already pushed back\n");
325*ebfedea0SLionel Sambuc } else if ((dearmour->pushback = calloc(1, length)) == NULL) {
326*ebfedea0SLionel Sambuc (void) fprintf(stderr, "push_back: bad alloc\n");
327*ebfedea0SLionel Sambuc } else {
328*ebfedea0SLionel Sambuc for (n = 0; n < length; ++n) {
329*ebfedea0SLionel Sambuc dearmour->pushback[n] = buf[(length - n) - 1];
330*ebfedea0SLionel Sambuc }
331*ebfedea0SLionel Sambuc dearmour->pushbackc = length;
332*ebfedea0SLionel Sambuc }
333*ebfedea0SLionel Sambuc }
334*ebfedea0SLionel Sambuc
335*ebfedea0SLionel Sambuc /* this struct holds a textual header line */
336*ebfedea0SLionel Sambuc typedef struct headerline_t {
337*ebfedea0SLionel Sambuc const char *s; /* the header line */
338*ebfedea0SLionel Sambuc size_t len; /* its length */
339*ebfedea0SLionel Sambuc int type; /* the defined type */
340*ebfedea0SLionel Sambuc } headerline_t;
341*ebfedea0SLionel Sambuc
342*ebfedea0SLionel Sambuc static headerline_t headerlines[] = {
343*ebfedea0SLionel Sambuc { "BEGIN PGP MESSAGE", 17, BEGIN_PGP_MESSAGE },
344*ebfedea0SLionel Sambuc { "BEGIN PGP PUBLIC KEY BLOCK", 26, BEGIN_PGP_PUBLIC_KEY_BLOCK },
345*ebfedea0SLionel Sambuc { "BEGIN PGP PRIVATE KEY BLOCK",27, BEGIN_PGP_PRIVATE_KEY_BLOCK },
346*ebfedea0SLionel Sambuc { "BEGIN PGP MESSAGE, PART ", 25, BEGIN_PGP_MULTI },
347*ebfedea0SLionel Sambuc { "BEGIN PGP SIGNATURE", 19, BEGIN_PGP_SIGNATURE },
348*ebfedea0SLionel Sambuc
349*ebfedea0SLionel Sambuc { "END PGP MESSAGE", 15, END_PGP_MESSAGE },
350*ebfedea0SLionel Sambuc { "END PGP PUBLIC KEY BLOCK", 24, END_PGP_PUBLIC_KEY_BLOCK },
351*ebfedea0SLionel Sambuc { "END PGP PRIVATE KEY BLOCK", 25, END_PGP_PRIVATE_KEY_BLOCK },
352*ebfedea0SLionel Sambuc { "END PGP MESSAGE, PART ", 22, END_PGP_MULTI },
353*ebfedea0SLionel Sambuc { "END PGP SIGNATURE", 17, END_PGP_SIGNATURE },
354*ebfedea0SLionel Sambuc
355*ebfedea0SLionel Sambuc { "BEGIN PGP SIGNED MESSAGE", 24, BEGIN_PGP_SIGNED_MESSAGE },
356*ebfedea0SLionel Sambuc
357*ebfedea0SLionel Sambuc { NULL, 0, -1 }
358*ebfedea0SLionel Sambuc };
359*ebfedea0SLionel Sambuc
360*ebfedea0SLionel Sambuc /* search through the table of header lines */
361*ebfedea0SLionel Sambuc static int
findheaderline(char * headerline)362*ebfedea0SLionel Sambuc findheaderline(char *headerline)
363*ebfedea0SLionel Sambuc {
364*ebfedea0SLionel Sambuc headerline_t *hp;
365*ebfedea0SLionel Sambuc
366*ebfedea0SLionel Sambuc for (hp = headerlines ; hp->s ; hp++) {
367*ebfedea0SLionel Sambuc if (strncmp(headerline, hp->s, hp->len) == 0) {
368*ebfedea0SLionel Sambuc break;
369*ebfedea0SLionel Sambuc }
370*ebfedea0SLionel Sambuc }
371*ebfedea0SLionel Sambuc return hp->type;
372*ebfedea0SLionel Sambuc }
373*ebfedea0SLionel Sambuc
374*ebfedea0SLionel Sambuc static int
set_lastseen_headerline(dearmour_t * dearmour,char * hdr,pgp_error_t ** errors)375*ebfedea0SLionel Sambuc set_lastseen_headerline(dearmour_t *dearmour, char *hdr, pgp_error_t **errors)
376*ebfedea0SLionel Sambuc {
377*ebfedea0SLionel Sambuc int lastseen;
378*ebfedea0SLionel Sambuc int prev;
379*ebfedea0SLionel Sambuc
380*ebfedea0SLionel Sambuc prev = dearmour->lastseen;
381*ebfedea0SLionel Sambuc if ((lastseen = findheaderline(hdr)) == -1) {
382*ebfedea0SLionel Sambuc PGP_ERROR_1(errors, PGP_E_R_BAD_FORMAT,
383*ebfedea0SLionel Sambuc "Unrecognised Header Line %s", hdr);
384*ebfedea0SLionel Sambuc return 0;
385*ebfedea0SLionel Sambuc }
386*ebfedea0SLionel Sambuc dearmour->lastseen = lastseen;
387*ebfedea0SLionel Sambuc if (pgp_get_debug_level(__FILE__)) {
388*ebfedea0SLionel Sambuc printf("set header: hdr=%s, dearmour->lastseen=%d, prev=%d\n",
389*ebfedea0SLionel Sambuc hdr, dearmour->lastseen, prev);
390*ebfedea0SLionel Sambuc }
391*ebfedea0SLionel Sambuc switch (dearmour->lastseen) {
392*ebfedea0SLionel Sambuc case NONE:
393*ebfedea0SLionel Sambuc PGP_ERROR_1(errors, PGP_E_R_BAD_FORMAT,
394*ebfedea0SLionel Sambuc "Unrecognised last seen Header Line %s", hdr);
395*ebfedea0SLionel Sambuc break;
396*ebfedea0SLionel Sambuc
397*ebfedea0SLionel Sambuc case END_PGP_MESSAGE:
398*ebfedea0SLionel Sambuc if (prev != BEGIN_PGP_MESSAGE) {
399*ebfedea0SLionel Sambuc PGP_ERROR_1(errors, PGP_E_R_BAD_FORMAT, "%s",
400*ebfedea0SLionel Sambuc "Got END PGP MESSAGE, but not after BEGIN");
401*ebfedea0SLionel Sambuc }
402*ebfedea0SLionel Sambuc break;
403*ebfedea0SLionel Sambuc
404*ebfedea0SLionel Sambuc case END_PGP_PUBLIC_KEY_BLOCK:
405*ebfedea0SLionel Sambuc if (prev != BEGIN_PGP_PUBLIC_KEY_BLOCK) {
406*ebfedea0SLionel Sambuc PGP_ERROR_1(errors, PGP_E_R_BAD_FORMAT, "%s",
407*ebfedea0SLionel Sambuc "Got END PGP PUBLIC KEY BLOCK, but not after BEGIN");
408*ebfedea0SLionel Sambuc }
409*ebfedea0SLionel Sambuc break;
410*ebfedea0SLionel Sambuc
411*ebfedea0SLionel Sambuc case END_PGP_PRIVATE_KEY_BLOCK:
412*ebfedea0SLionel Sambuc if (prev != BEGIN_PGP_PRIVATE_KEY_BLOCK) {
413*ebfedea0SLionel Sambuc PGP_ERROR_1(errors, PGP_E_R_BAD_FORMAT, "%s",
414*ebfedea0SLionel Sambuc "Got END PGP PRIVATE KEY BLOCK, but not after BEGIN");
415*ebfedea0SLionel Sambuc }
416*ebfedea0SLionel Sambuc break;
417*ebfedea0SLionel Sambuc
418*ebfedea0SLionel Sambuc case BEGIN_PGP_MULTI:
419*ebfedea0SLionel Sambuc case END_PGP_MULTI:
420*ebfedea0SLionel Sambuc PGP_ERROR_1(errors, PGP_E_R_UNSUPPORTED, "%s",
421*ebfedea0SLionel Sambuc "Multi-part messages are not yet supported");
422*ebfedea0SLionel Sambuc break;
423*ebfedea0SLionel Sambuc
424*ebfedea0SLionel Sambuc case END_PGP_SIGNATURE:
425*ebfedea0SLionel Sambuc if (prev != BEGIN_PGP_SIGNATURE) {
426*ebfedea0SLionel Sambuc PGP_ERROR_1(errors, PGP_E_R_BAD_FORMAT, "%s",
427*ebfedea0SLionel Sambuc "Got END PGP SIGNATURE, but not after BEGIN");
428*ebfedea0SLionel Sambuc }
429*ebfedea0SLionel Sambuc break;
430*ebfedea0SLionel Sambuc
431*ebfedea0SLionel Sambuc case BEGIN_PGP_MESSAGE:
432*ebfedea0SLionel Sambuc case BEGIN_PGP_PUBLIC_KEY_BLOCK:
433*ebfedea0SLionel Sambuc case BEGIN_PGP_PRIVATE_KEY_BLOCK:
434*ebfedea0SLionel Sambuc case BEGIN_PGP_SIGNATURE:
435*ebfedea0SLionel Sambuc case BEGIN_PGP_SIGNED_MESSAGE:
436*ebfedea0SLionel Sambuc break;
437*ebfedea0SLionel Sambuc }
438*ebfedea0SLionel Sambuc return 1;
439*ebfedea0SLionel Sambuc }
440*ebfedea0SLionel Sambuc
441*ebfedea0SLionel Sambuc static int
read_char(pgp_stream_t * stream,dearmour_t * dearmour,pgp_error_t ** errors,pgp_reader_t * readinfo,pgp_cbdata_t * cbinfo,unsigned skip)442*ebfedea0SLionel Sambuc read_char(pgp_stream_t *stream, dearmour_t *dearmour,
443*ebfedea0SLionel Sambuc pgp_error_t **errors,
444*ebfedea0SLionel Sambuc pgp_reader_t *readinfo,
445*ebfedea0SLionel Sambuc pgp_cbdata_t *cbinfo,
446*ebfedea0SLionel Sambuc unsigned skip)
447*ebfedea0SLionel Sambuc {
448*ebfedea0SLionel Sambuc uint8_t c;
449*ebfedea0SLionel Sambuc
450*ebfedea0SLionel Sambuc do {
451*ebfedea0SLionel Sambuc if (dearmour->pushbackc) {
452*ebfedea0SLionel Sambuc c = dearmour->pushback[--dearmour->pushbackc];
453*ebfedea0SLionel Sambuc if (dearmour->pushbackc == 0) {
454*ebfedea0SLionel Sambuc free(dearmour->pushback);
455*ebfedea0SLionel Sambuc dearmour->pushback = NULL;
456*ebfedea0SLionel Sambuc }
457*ebfedea0SLionel Sambuc } else if (pgp_stacked_read(stream, &c, 1, errors, readinfo,
458*ebfedea0SLionel Sambuc cbinfo) != 1) {
459*ebfedea0SLionel Sambuc return -1;
460*ebfedea0SLionel Sambuc }
461*ebfedea0SLionel Sambuc } while (skip && c == '\r');
462*ebfedea0SLionel Sambuc dearmour->prev_nl = dearmour->seen_nl;
463*ebfedea0SLionel Sambuc dearmour->seen_nl = c == '\n';
464*ebfedea0SLionel Sambuc return c;
465*ebfedea0SLionel Sambuc }
466*ebfedea0SLionel Sambuc
467*ebfedea0SLionel Sambuc static int
eat_whitespace(pgp_stream_t * stream,int first,dearmour_t * dearmour,pgp_error_t ** errors,pgp_reader_t * readinfo,pgp_cbdata_t * cbinfo,unsigned skip)468*ebfedea0SLionel Sambuc eat_whitespace(pgp_stream_t *stream, int first,
469*ebfedea0SLionel Sambuc dearmour_t *dearmour,
470*ebfedea0SLionel Sambuc pgp_error_t **errors,
471*ebfedea0SLionel Sambuc pgp_reader_t *readinfo,
472*ebfedea0SLionel Sambuc pgp_cbdata_t *cbinfo,
473*ebfedea0SLionel Sambuc unsigned skip)
474*ebfedea0SLionel Sambuc {
475*ebfedea0SLionel Sambuc int c = first;
476*ebfedea0SLionel Sambuc
477*ebfedea0SLionel Sambuc while (c == ' ' || c == '\t') {
478*ebfedea0SLionel Sambuc c = read_char(stream, dearmour, errors, readinfo, cbinfo, skip);
479*ebfedea0SLionel Sambuc }
480*ebfedea0SLionel Sambuc return c;
481*ebfedea0SLionel Sambuc }
482*ebfedea0SLionel Sambuc
483*ebfedea0SLionel Sambuc static int
read_and_eat_whitespace(pgp_stream_t * stream,dearmour_t * dearmour,pgp_error_t ** errors,pgp_reader_t * readinfo,pgp_cbdata_t * cbinfo,unsigned skip)484*ebfedea0SLionel Sambuc read_and_eat_whitespace(pgp_stream_t *stream, dearmour_t *dearmour,
485*ebfedea0SLionel Sambuc pgp_error_t **errors,
486*ebfedea0SLionel Sambuc pgp_reader_t *readinfo,
487*ebfedea0SLionel Sambuc pgp_cbdata_t *cbinfo,
488*ebfedea0SLionel Sambuc unsigned skip)
489*ebfedea0SLionel Sambuc {
490*ebfedea0SLionel Sambuc int c;
491*ebfedea0SLionel Sambuc
492*ebfedea0SLionel Sambuc do {
493*ebfedea0SLionel Sambuc c = read_char(stream, dearmour, errors, readinfo, cbinfo, skip);
494*ebfedea0SLionel Sambuc } while (c == ' ' || c == '\t');
495*ebfedea0SLionel Sambuc return c;
496*ebfedea0SLionel Sambuc }
497*ebfedea0SLionel Sambuc
498*ebfedea0SLionel Sambuc static void
flush(dearmour_t * dearmour,pgp_cbdata_t * cbinfo)499*ebfedea0SLionel Sambuc flush(dearmour_t *dearmour, pgp_cbdata_t *cbinfo)
500*ebfedea0SLionel Sambuc {
501*ebfedea0SLionel Sambuc pgp_packet_t content;
502*ebfedea0SLionel Sambuc
503*ebfedea0SLionel Sambuc if (dearmour->unarmoredc > 0) {
504*ebfedea0SLionel Sambuc content.u.unarmoured_text.data = dearmour->unarmoured;
505*ebfedea0SLionel Sambuc content.u.unarmoured_text.length = (unsigned)dearmour->unarmoredc;
506*ebfedea0SLionel Sambuc CALLBACK(PGP_PTAG_CT_UNARMOURED_TEXT, cbinfo, &content);
507*ebfedea0SLionel Sambuc dearmour->unarmoredc = 0;
508*ebfedea0SLionel Sambuc }
509*ebfedea0SLionel Sambuc }
510*ebfedea0SLionel Sambuc
511*ebfedea0SLionel Sambuc static int
unarmoured_read_char(pgp_stream_t * stream,dearmour_t * dearmour,pgp_error_t ** errors,pgp_reader_t * readinfo,pgp_cbdata_t * cbinfo,unsigned skip)512*ebfedea0SLionel Sambuc unarmoured_read_char(pgp_stream_t *stream, dearmour_t *dearmour,
513*ebfedea0SLionel Sambuc pgp_error_t **errors,
514*ebfedea0SLionel Sambuc pgp_reader_t *readinfo,
515*ebfedea0SLionel Sambuc pgp_cbdata_t *cbinfo,
516*ebfedea0SLionel Sambuc unsigned skip)
517*ebfedea0SLionel Sambuc {
518*ebfedea0SLionel Sambuc int c;
519*ebfedea0SLionel Sambuc
520*ebfedea0SLionel Sambuc do {
521*ebfedea0SLionel Sambuc c = read_char(stream, dearmour, errors, readinfo, cbinfo, 0);
522*ebfedea0SLionel Sambuc if (c < 0) {
523*ebfedea0SLionel Sambuc return c;
524*ebfedea0SLionel Sambuc }
525*ebfedea0SLionel Sambuc dearmour->unarmoured[dearmour->unarmoredc++] = c;
526*ebfedea0SLionel Sambuc if (dearmour->unarmoredc == sizeof(dearmour->unarmoured)) {
527*ebfedea0SLionel Sambuc flush(dearmour, cbinfo);
528*ebfedea0SLionel Sambuc }
529*ebfedea0SLionel Sambuc } while (skip && c == '\r');
530*ebfedea0SLionel Sambuc return c;
531*ebfedea0SLionel Sambuc }
532*ebfedea0SLionel Sambuc
533*ebfedea0SLionel Sambuc /**
534*ebfedea0SLionel Sambuc * \param headers
535*ebfedea0SLionel Sambuc * \param key
536*ebfedea0SLionel Sambuc *
537*ebfedea0SLionel Sambuc * \return header value if found, otherwise NULL
538*ebfedea0SLionel Sambuc */
539*ebfedea0SLionel Sambuc static const char *
find_header(pgp_headers_t * headers,const char * key)540*ebfedea0SLionel Sambuc find_header(pgp_headers_t *headers, const char *key)
541*ebfedea0SLionel Sambuc {
542*ebfedea0SLionel Sambuc unsigned n;
543*ebfedea0SLionel Sambuc
544*ebfedea0SLionel Sambuc for (n = 0; n < headers->headerc; ++n) {
545*ebfedea0SLionel Sambuc if (strcmp(headers->headers[n].key, key) == 0) {
546*ebfedea0SLionel Sambuc return headers->headers[n].value;
547*ebfedea0SLionel Sambuc }
548*ebfedea0SLionel Sambuc }
549*ebfedea0SLionel Sambuc return NULL;
550*ebfedea0SLionel Sambuc }
551*ebfedea0SLionel Sambuc
552*ebfedea0SLionel Sambuc /**
553*ebfedea0SLionel Sambuc * \param dest
554*ebfedea0SLionel Sambuc * \param src
555*ebfedea0SLionel Sambuc */
556*ebfedea0SLionel Sambuc static void
dup_headers(pgp_headers_t * dest,const pgp_headers_t * src)557*ebfedea0SLionel Sambuc dup_headers(pgp_headers_t *dest, const pgp_headers_t *src)
558*ebfedea0SLionel Sambuc {
559*ebfedea0SLionel Sambuc unsigned n;
560*ebfedea0SLionel Sambuc
561*ebfedea0SLionel Sambuc if ((dest->headers = calloc(src->headerc, sizeof(*dest->headers))) == NULL) {
562*ebfedea0SLionel Sambuc (void) fprintf(stderr, "dup_headers: bad alloc\n");
563*ebfedea0SLionel Sambuc } else {
564*ebfedea0SLionel Sambuc dest->headerc = src->headerc;
565*ebfedea0SLionel Sambuc for (n = 0; n < src->headerc; ++n) {
566*ebfedea0SLionel Sambuc dest->headers[n].key = netpgp_strdup(src->headers[n].key);
567*ebfedea0SLionel Sambuc dest->headers[n].value = netpgp_strdup(src->headers[n].value);
568*ebfedea0SLionel Sambuc }
569*ebfedea0SLionel Sambuc }
570*ebfedea0SLionel Sambuc }
571*ebfedea0SLionel Sambuc
572*ebfedea0SLionel Sambuc /*
573*ebfedea0SLionel Sambuc * Note that this skips CRs so implementations always see just straight LFs
574*ebfedea0SLionel Sambuc * as line terminators
575*ebfedea0SLionel Sambuc */
576*ebfedea0SLionel Sambuc static int
process_dash_escaped(pgp_stream_t * stream,dearmour_t * dearmour,pgp_error_t ** errors,pgp_reader_t * readinfo,pgp_cbdata_t * cbinfo)577*ebfedea0SLionel Sambuc process_dash_escaped(pgp_stream_t *stream, dearmour_t *dearmour,
578*ebfedea0SLionel Sambuc pgp_error_t **errors,
579*ebfedea0SLionel Sambuc pgp_reader_t *readinfo,
580*ebfedea0SLionel Sambuc pgp_cbdata_t *cbinfo)
581*ebfedea0SLionel Sambuc {
582*ebfedea0SLionel Sambuc pgp_fixed_body_t *body;
583*ebfedea0SLionel Sambuc pgp_packet_t content2;
584*ebfedea0SLionel Sambuc pgp_packet_t content;
585*ebfedea0SLionel Sambuc const char *hashstr;
586*ebfedea0SLionel Sambuc pgp_hash_t *hash;
587*ebfedea0SLionel Sambuc int total;
588*ebfedea0SLionel Sambuc
589*ebfedea0SLionel Sambuc body = &content.u.cleartext_body;
590*ebfedea0SLionel Sambuc if ((hash = calloc(1, sizeof(*hash))) == NULL) {
591*ebfedea0SLionel Sambuc PGP_ERROR_1(errors, PGP_E_R_BAD_FORMAT, "%s",
592*ebfedea0SLionel Sambuc "process_dash_escaped: bad alloc");
593*ebfedea0SLionel Sambuc return -1;
594*ebfedea0SLionel Sambuc }
595*ebfedea0SLionel Sambuc hashstr = find_header(&dearmour->headers, "Hash");
596*ebfedea0SLionel Sambuc if (hashstr) {
597*ebfedea0SLionel Sambuc pgp_hash_alg_t alg;
598*ebfedea0SLionel Sambuc
599*ebfedea0SLionel Sambuc alg = pgp_str_to_hash_alg(hashstr);
600*ebfedea0SLionel Sambuc if (!pgp_is_hash_alg_supported(&alg)) {
601*ebfedea0SLionel Sambuc free(hash);
602*ebfedea0SLionel Sambuc PGP_ERROR_1(errors, PGP_E_R_BAD_FORMAT,
603*ebfedea0SLionel Sambuc "Unsupported hash algorithm '%s'", hashstr);
604*ebfedea0SLionel Sambuc return -1;
605*ebfedea0SLionel Sambuc }
606*ebfedea0SLionel Sambuc if (alg == PGP_HASH_UNKNOWN) {
607*ebfedea0SLionel Sambuc free(hash);
608*ebfedea0SLionel Sambuc PGP_ERROR_1(errors, PGP_E_R_BAD_FORMAT,
609*ebfedea0SLionel Sambuc "Unknown hash algorithm '%s'", hashstr);
610*ebfedea0SLionel Sambuc return -1;
611*ebfedea0SLionel Sambuc }
612*ebfedea0SLionel Sambuc pgp_hash_any(hash, alg);
613*ebfedea0SLionel Sambuc } else {
614*ebfedea0SLionel Sambuc pgp_hash_md5(hash);
615*ebfedea0SLionel Sambuc }
616*ebfedea0SLionel Sambuc
617*ebfedea0SLionel Sambuc if (!hash->init(hash)) {
618*ebfedea0SLionel Sambuc PGP_ERROR_1(errors, PGP_E_R_BAD_FORMAT, "%s",
619*ebfedea0SLionel Sambuc "can't initialise hash");
620*ebfedea0SLionel Sambuc return -1;
621*ebfedea0SLionel Sambuc }
622*ebfedea0SLionel Sambuc
623*ebfedea0SLionel Sambuc body->length = 0;
624*ebfedea0SLionel Sambuc total = 0;
625*ebfedea0SLionel Sambuc for (;;) {
626*ebfedea0SLionel Sambuc int c;
627*ebfedea0SLionel Sambuc unsigned count;
628*ebfedea0SLionel Sambuc
629*ebfedea0SLionel Sambuc c = read_char(stream, dearmour, errors, readinfo, cbinfo, 1);
630*ebfedea0SLionel Sambuc if (c < 0) {
631*ebfedea0SLionel Sambuc return -1;
632*ebfedea0SLionel Sambuc }
633*ebfedea0SLionel Sambuc if (dearmour->prev_nl && c == '-') {
634*ebfedea0SLionel Sambuc if ((c = read_char(stream, dearmour, errors, readinfo, cbinfo,
635*ebfedea0SLionel Sambuc 0)) < 0) {
636*ebfedea0SLionel Sambuc return -1;
637*ebfedea0SLionel Sambuc }
638*ebfedea0SLionel Sambuc if (c != ' ') {
639*ebfedea0SLionel Sambuc /* then this had better be a trailer! */
640*ebfedea0SLionel Sambuc if (c != '-') {
641*ebfedea0SLionel Sambuc PGP_ERROR_1(errors, PGP_E_R_BAD_FORMAT,
642*ebfedea0SLionel Sambuc "%s", "Bad dash-escaping");
643*ebfedea0SLionel Sambuc }
644*ebfedea0SLionel Sambuc for (count = 2; count < 5; ++count) {
645*ebfedea0SLionel Sambuc if ((c = read_char(stream, dearmour, errors,
646*ebfedea0SLionel Sambuc readinfo, cbinfo, 0)) < 0) {
647*ebfedea0SLionel Sambuc return -1;
648*ebfedea0SLionel Sambuc }
649*ebfedea0SLionel Sambuc if (c != '-') {
650*ebfedea0SLionel Sambuc PGP_ERROR_1(errors,
651*ebfedea0SLionel Sambuc PGP_E_R_BAD_FORMAT, "%s",
652*ebfedea0SLionel Sambuc "Bad dash-escaping (2)");
653*ebfedea0SLionel Sambuc }
654*ebfedea0SLionel Sambuc }
655*ebfedea0SLionel Sambuc dearmour->state = AT_TRAILER_NAME;
656*ebfedea0SLionel Sambuc break;
657*ebfedea0SLionel Sambuc }
658*ebfedea0SLionel Sambuc /* otherwise we read the next character */
659*ebfedea0SLionel Sambuc if ((c = read_char(stream, dearmour, errors, readinfo, cbinfo,
660*ebfedea0SLionel Sambuc 0)) < 0) {
661*ebfedea0SLionel Sambuc return -1;
662*ebfedea0SLionel Sambuc }
663*ebfedea0SLionel Sambuc }
664*ebfedea0SLionel Sambuc if (c == '\n' && body->length) {
665*ebfedea0SLionel Sambuc if (memchr(body->data + 1, '\n', body->length - 1)
666*ebfedea0SLionel Sambuc != NULL) {
667*ebfedea0SLionel Sambuc (void) fprintf(stderr,
668*ebfedea0SLionel Sambuc "process_dash_escaped: newline found\n");
669*ebfedea0SLionel Sambuc return -1;
670*ebfedea0SLionel Sambuc }
671*ebfedea0SLionel Sambuc if (body->data[0] == '\n') {
672*ebfedea0SLionel Sambuc hash->add(hash, (const uint8_t *)"\r", 1);
673*ebfedea0SLionel Sambuc }
674*ebfedea0SLionel Sambuc hash->add(hash, body->data, body->length);
675*ebfedea0SLionel Sambuc if (pgp_get_debug_level(__FILE__)) {
676*ebfedea0SLionel Sambuc fprintf(stderr, "Got body:\n%s\n", body->data);
677*ebfedea0SLionel Sambuc }
678*ebfedea0SLionel Sambuc CALLBACK(PGP_PTAG_CT_SIGNED_CLEARTEXT_BODY, cbinfo,
679*ebfedea0SLionel Sambuc &content);
680*ebfedea0SLionel Sambuc body->length = 0;
681*ebfedea0SLionel Sambuc }
682*ebfedea0SLionel Sambuc body->data[body->length++] = c;
683*ebfedea0SLionel Sambuc total += 1;
684*ebfedea0SLionel Sambuc if (body->length == sizeof(body->data)) {
685*ebfedea0SLionel Sambuc if (pgp_get_debug_level(__FILE__)) {
686*ebfedea0SLionel Sambuc (void) fprintf(stderr, "Got body (2):\n%s\n",
687*ebfedea0SLionel Sambuc body->data);
688*ebfedea0SLionel Sambuc }
689*ebfedea0SLionel Sambuc CALLBACK(PGP_PTAG_CT_SIGNED_CLEARTEXT_BODY, cbinfo,
690*ebfedea0SLionel Sambuc &content);
691*ebfedea0SLionel Sambuc body->length = 0;
692*ebfedea0SLionel Sambuc }
693*ebfedea0SLionel Sambuc }
694*ebfedea0SLionel Sambuc if (body->data[0] != '\n') {
695*ebfedea0SLionel Sambuc (void) fprintf(stderr,
696*ebfedea0SLionel Sambuc "process_dash_escaped: no newline in body data\n");
697*ebfedea0SLionel Sambuc return -1;
698*ebfedea0SLionel Sambuc }
699*ebfedea0SLionel Sambuc if (body->length != 1) {
700*ebfedea0SLionel Sambuc (void) fprintf(stderr,
701*ebfedea0SLionel Sambuc "process_dash_escaped: bad body length\n");
702*ebfedea0SLionel Sambuc return -1;
703*ebfedea0SLionel Sambuc }
704*ebfedea0SLionel Sambuc /* don't send that one character, because it's part of the trailer */
705*ebfedea0SLionel Sambuc (void) memset(&content2, 0x0, sizeof(content2));
706*ebfedea0SLionel Sambuc CALLBACK(PGP_PTAG_CT_SIGNED_CLEARTEXT_TRAILER, cbinfo, &content2);
707*ebfedea0SLionel Sambuc return total;
708*ebfedea0SLionel Sambuc }
709*ebfedea0SLionel Sambuc
710*ebfedea0SLionel Sambuc static int
add_header(dearmour_t * dearmour,const char * key,const char * value)711*ebfedea0SLionel Sambuc add_header(dearmour_t *dearmour, const char *key, const char *value)
712*ebfedea0SLionel Sambuc {
713*ebfedea0SLionel Sambuc int n;
714*ebfedea0SLionel Sambuc
715*ebfedea0SLionel Sambuc /*
716*ebfedea0SLionel Sambuc * Check that the header is valid
717*ebfedea0SLionel Sambuc */
718*ebfedea0SLionel Sambuc if (strcmp(key, "Version") == 0 ||
719*ebfedea0SLionel Sambuc strcmp(key, "Comment") == 0 ||
720*ebfedea0SLionel Sambuc strcmp(key, "MessageID") == 0 ||
721*ebfedea0SLionel Sambuc strcmp(key, "Hash") == 0 ||
722*ebfedea0SLionel Sambuc strcmp(key, "Charset") == 0) {
723*ebfedea0SLionel Sambuc n = dearmour->headers.headerc;
724*ebfedea0SLionel Sambuc dearmour->headers.headers = realloc(dearmour->headers.headers,
725*ebfedea0SLionel Sambuc (n + 1) * sizeof(*dearmour->headers.headers));
726*ebfedea0SLionel Sambuc if (dearmour->headers.headers == NULL) {
727*ebfedea0SLionel Sambuc (void) fprintf(stderr, "add_header: bad alloc\n");
728*ebfedea0SLionel Sambuc return 0;
729*ebfedea0SLionel Sambuc }
730*ebfedea0SLionel Sambuc dearmour->headers.headers[n].key = netpgp_strdup(key);
731*ebfedea0SLionel Sambuc dearmour->headers.headers[n].value = netpgp_strdup(value);
732*ebfedea0SLionel Sambuc dearmour->headers.headerc = n + 1;
733*ebfedea0SLionel Sambuc return 1;
734*ebfedea0SLionel Sambuc }
735*ebfedea0SLionel Sambuc return 0;
736*ebfedea0SLionel Sambuc }
737*ebfedea0SLionel Sambuc
738*ebfedea0SLionel Sambuc /* \todo what does a return value of 0 indicate? 1 is good, -1 is bad */
739*ebfedea0SLionel Sambuc static int
parse_headers(pgp_stream_t * stream,dearmour_t * dearmour,pgp_error_t ** errors,pgp_reader_t * readinfo,pgp_cbdata_t * cbinfo)740*ebfedea0SLionel Sambuc parse_headers(pgp_stream_t *stream, dearmour_t *dearmour, pgp_error_t **errors,
741*ebfedea0SLionel Sambuc pgp_reader_t * readinfo, pgp_cbdata_t * cbinfo)
742*ebfedea0SLionel Sambuc {
743*ebfedea0SLionel Sambuc unsigned nbuf;
744*ebfedea0SLionel Sambuc unsigned size;
745*ebfedea0SLionel Sambuc unsigned first = 1;
746*ebfedea0SLionel Sambuc char *buf;
747*ebfedea0SLionel Sambuc int ret = 1;
748*ebfedea0SLionel Sambuc
749*ebfedea0SLionel Sambuc nbuf = 0;
750*ebfedea0SLionel Sambuc size = 80;
751*ebfedea0SLionel Sambuc if ((buf = calloc(1, size)) == NULL) {
752*ebfedea0SLionel Sambuc (void) fprintf(stderr, "parse_headers: bad calloc\n");
753*ebfedea0SLionel Sambuc return -1;
754*ebfedea0SLionel Sambuc }
755*ebfedea0SLionel Sambuc for (;;) {
756*ebfedea0SLionel Sambuc int c;
757*ebfedea0SLionel Sambuc
758*ebfedea0SLionel Sambuc if ((c = read_char(stream, dearmour, errors, readinfo, cbinfo, 1)) < 0) {
759*ebfedea0SLionel Sambuc PGP_ERROR_1(errors, PGP_E_R_BAD_FORMAT,
760*ebfedea0SLionel Sambuc "%s", "Unexpected EOF");
761*ebfedea0SLionel Sambuc ret = -1;
762*ebfedea0SLionel Sambuc break;
763*ebfedea0SLionel Sambuc }
764*ebfedea0SLionel Sambuc if (c == '\n') {
765*ebfedea0SLionel Sambuc char *s;
766*ebfedea0SLionel Sambuc
767*ebfedea0SLionel Sambuc if (nbuf == 0) {
768*ebfedea0SLionel Sambuc break;
769*ebfedea0SLionel Sambuc }
770*ebfedea0SLionel Sambuc
771*ebfedea0SLionel Sambuc if (nbuf >= size) {
772*ebfedea0SLionel Sambuc (void) fprintf(stderr,
773*ebfedea0SLionel Sambuc "parse_headers: bad size\n");
774*ebfedea0SLionel Sambuc return -1;
775*ebfedea0SLionel Sambuc }
776*ebfedea0SLionel Sambuc buf[nbuf] = '\0';
777*ebfedea0SLionel Sambuc
778*ebfedea0SLionel Sambuc if ((s = strchr(buf, ':')) == NULL) {
779*ebfedea0SLionel Sambuc if (!first && !dearmour->allow_headers_without_gap) {
780*ebfedea0SLionel Sambuc /*
781*ebfedea0SLionel Sambuc * then we have seriously malformed
782*ebfedea0SLionel Sambuc * armour
783*ebfedea0SLionel Sambuc */
784*ebfedea0SLionel Sambuc PGP_ERROR_1(errors, PGP_E_R_BAD_FORMAT,
785*ebfedea0SLionel Sambuc "%s", "No colon in armour header");
786*ebfedea0SLionel Sambuc ret = -1;
787*ebfedea0SLionel Sambuc break;
788*ebfedea0SLionel Sambuc } else {
789*ebfedea0SLionel Sambuc if (first &&
790*ebfedea0SLionel Sambuc !(dearmour->allow_headers_without_gap || dearmour->allow_no_gap)) {
791*ebfedea0SLionel Sambuc PGP_ERROR_1(errors,
792*ebfedea0SLionel Sambuc PGP_E_R_BAD_FORMAT,
793*ebfedea0SLionel Sambuc "%s", "No colon in"
794*ebfedea0SLionel Sambuc " armour header (2)");
795*ebfedea0SLionel Sambuc /*
796*ebfedea0SLionel Sambuc * then we have a nasty
797*ebfedea0SLionel Sambuc * armoured block with no
798*ebfedea0SLionel Sambuc * headers, not even a blank
799*ebfedea0SLionel Sambuc * line.
800*ebfedea0SLionel Sambuc */
801*ebfedea0SLionel Sambuc buf[nbuf] = '\n';
802*ebfedea0SLionel Sambuc push_back(dearmour, (uint8_t *) buf, nbuf + 1);
803*ebfedea0SLionel Sambuc ret = -1;
804*ebfedea0SLionel Sambuc break;
805*ebfedea0SLionel Sambuc }
806*ebfedea0SLionel Sambuc }
807*ebfedea0SLionel Sambuc } else {
808*ebfedea0SLionel Sambuc *s = '\0';
809*ebfedea0SLionel Sambuc if (s[1] != ' ') {
810*ebfedea0SLionel Sambuc PGP_ERROR_1(errors, PGP_E_R_BAD_FORMAT,
811*ebfedea0SLionel Sambuc "%s", "No space in armour header");
812*ebfedea0SLionel Sambuc ret = -1;
813*ebfedea0SLionel Sambuc goto end;
814*ebfedea0SLionel Sambuc }
815*ebfedea0SLionel Sambuc if (!add_header(dearmour, buf, s + 2)) {
816*ebfedea0SLionel Sambuc PGP_ERROR_1(errors, PGP_E_R_BAD_FORMAT, "Invalid header %s", buf);
817*ebfedea0SLionel Sambuc ret = -1;
818*ebfedea0SLionel Sambuc goto end;
819*ebfedea0SLionel Sambuc }
820*ebfedea0SLionel Sambuc nbuf = 0;
821*ebfedea0SLionel Sambuc }
822*ebfedea0SLionel Sambuc first = 0;
823*ebfedea0SLionel Sambuc } else {
824*ebfedea0SLionel Sambuc if (size <= nbuf + 1) {
825*ebfedea0SLionel Sambuc size += size + 80;
826*ebfedea0SLionel Sambuc buf = realloc(buf, size);
827*ebfedea0SLionel Sambuc if (buf == NULL) {
828*ebfedea0SLionel Sambuc (void) fprintf(stderr, "bad alloc\n");
829*ebfedea0SLionel Sambuc ret = -1;
830*ebfedea0SLionel Sambuc goto end;
831*ebfedea0SLionel Sambuc }
832*ebfedea0SLionel Sambuc }
833*ebfedea0SLionel Sambuc buf[nbuf++] = c;
834*ebfedea0SLionel Sambuc }
835*ebfedea0SLionel Sambuc }
836*ebfedea0SLionel Sambuc
837*ebfedea0SLionel Sambuc end:
838*ebfedea0SLionel Sambuc free(buf);
839*ebfedea0SLionel Sambuc
840*ebfedea0SLionel Sambuc return ret;
841*ebfedea0SLionel Sambuc }
842*ebfedea0SLionel Sambuc
843*ebfedea0SLionel Sambuc static int
read4(pgp_stream_t * stream,dearmour_t * dearmour,pgp_error_t ** errors,pgp_reader_t * readinfo,pgp_cbdata_t * cbinfo,int * pc,unsigned * pn,uint32_t * pl)844*ebfedea0SLionel Sambuc read4(pgp_stream_t *stream, dearmour_t *dearmour, pgp_error_t **errors,
845*ebfedea0SLionel Sambuc pgp_reader_t *readinfo, pgp_cbdata_t *cbinfo,
846*ebfedea0SLionel Sambuc int *pc, unsigned *pn, uint32_t *pl)
847*ebfedea0SLionel Sambuc {
848*ebfedea0SLionel Sambuc int n, c;
849*ebfedea0SLionel Sambuc uint32_t l = 0;
850*ebfedea0SLionel Sambuc
851*ebfedea0SLionel Sambuc for (n = 0; n < 4; ++n) {
852*ebfedea0SLionel Sambuc c = read_char(stream, dearmour, errors, readinfo, cbinfo, 1);
853*ebfedea0SLionel Sambuc if (c < 0) {
854*ebfedea0SLionel Sambuc dearmour->eof64 = 1;
855*ebfedea0SLionel Sambuc return -1;
856*ebfedea0SLionel Sambuc }
857*ebfedea0SLionel Sambuc if (c == '-' || c == '=') {
858*ebfedea0SLionel Sambuc break;
859*ebfedea0SLionel Sambuc }
860*ebfedea0SLionel Sambuc l <<= 6;
861*ebfedea0SLionel Sambuc if (c >= 'A' && c <= 'Z') {
862*ebfedea0SLionel Sambuc l += (uint32_t)(c - 'A');
863*ebfedea0SLionel Sambuc } else if (c >= 'a' && c <= 'z') {
864*ebfedea0SLionel Sambuc l += (uint32_t)(c - 'a') + 26;
865*ebfedea0SLionel Sambuc } else if (c >= '0' && c <= '9') {
866*ebfedea0SLionel Sambuc l += (uint32_t)(c - '0') + 52;
867*ebfedea0SLionel Sambuc } else if (c == '+') {
868*ebfedea0SLionel Sambuc l += 62;
869*ebfedea0SLionel Sambuc } else if (c == '/') {
870*ebfedea0SLionel Sambuc l += 63;
871*ebfedea0SLionel Sambuc } else {
872*ebfedea0SLionel Sambuc --n;
873*ebfedea0SLionel Sambuc l >>= 6;
874*ebfedea0SLionel Sambuc }
875*ebfedea0SLionel Sambuc }
876*ebfedea0SLionel Sambuc
877*ebfedea0SLionel Sambuc *pc = c;
878*ebfedea0SLionel Sambuc *pn = n;
879*ebfedea0SLionel Sambuc *pl = l;
880*ebfedea0SLionel Sambuc
881*ebfedea0SLionel Sambuc return 4;
882*ebfedea0SLionel Sambuc }
883*ebfedea0SLionel Sambuc
884*ebfedea0SLionel Sambuc unsigned
pgp_crc24(unsigned checksum,uint8_t c)885*ebfedea0SLionel Sambuc pgp_crc24(unsigned checksum, uint8_t c)
886*ebfedea0SLionel Sambuc {
887*ebfedea0SLionel Sambuc unsigned i;
888*ebfedea0SLionel Sambuc
889*ebfedea0SLionel Sambuc checksum ^= c << 16;
890*ebfedea0SLionel Sambuc for (i = 0; i < 8; i++) {
891*ebfedea0SLionel Sambuc checksum <<= 1;
892*ebfedea0SLionel Sambuc if (checksum & 0x1000000)
893*ebfedea0SLionel Sambuc checksum ^= CRC24_POLY;
894*ebfedea0SLionel Sambuc }
895*ebfedea0SLionel Sambuc return (unsigned)(checksum & 0xffffffL);
896*ebfedea0SLionel Sambuc }
897*ebfedea0SLionel Sambuc
898*ebfedea0SLionel Sambuc static int
decode64(pgp_stream_t * stream,dearmour_t * dearmour,pgp_error_t ** errors,pgp_reader_t * readinfo,pgp_cbdata_t * cbinfo)899*ebfedea0SLionel Sambuc decode64(pgp_stream_t *stream, dearmour_t *dearmour, pgp_error_t **errors,
900*ebfedea0SLionel Sambuc pgp_reader_t *readinfo, pgp_cbdata_t *cbinfo)
901*ebfedea0SLionel Sambuc {
902*ebfedea0SLionel Sambuc unsigned n;
903*ebfedea0SLionel Sambuc int n2;
904*ebfedea0SLionel Sambuc uint32_t l;
905*ebfedea0SLionel Sambuc int c;
906*ebfedea0SLionel Sambuc int ret;
907*ebfedea0SLionel Sambuc
908*ebfedea0SLionel Sambuc if (dearmour->buffered) {
909*ebfedea0SLionel Sambuc (void) fprintf(stderr, "decode64: bad dearmour->buffered\n");
910*ebfedea0SLionel Sambuc return 0;
911*ebfedea0SLionel Sambuc }
912*ebfedea0SLionel Sambuc
913*ebfedea0SLionel Sambuc ret = read4(stream, dearmour, errors, readinfo, cbinfo, &c, &n, &l);
914*ebfedea0SLionel Sambuc if (ret < 0) {
915*ebfedea0SLionel Sambuc PGP_ERROR_1(errors, PGP_E_R_BAD_FORMAT, "%s",
916*ebfedea0SLionel Sambuc "Badly formed base64");
917*ebfedea0SLionel Sambuc return 0;
918*ebfedea0SLionel Sambuc }
919*ebfedea0SLionel Sambuc if (n == 3) {
920*ebfedea0SLionel Sambuc if (c != '=') {
921*ebfedea0SLionel Sambuc PGP_ERROR_1(errors, PGP_E_R_BAD_FORMAT,
922*ebfedea0SLionel Sambuc "%s", "Badly terminated base64 (2)");
923*ebfedea0SLionel Sambuc return 0;
924*ebfedea0SLionel Sambuc }
925*ebfedea0SLionel Sambuc dearmour->buffered = 2;
926*ebfedea0SLionel Sambuc dearmour->eof64 = 1;
927*ebfedea0SLionel Sambuc l >>= 2;
928*ebfedea0SLionel Sambuc } else if (n == 2) {
929*ebfedea0SLionel Sambuc if (c != '=') {
930*ebfedea0SLionel Sambuc PGP_ERROR_1(errors, PGP_E_R_BAD_FORMAT,
931*ebfedea0SLionel Sambuc "%s", "Badly terminated base64 (3)");
932*ebfedea0SLionel Sambuc return 0;
933*ebfedea0SLionel Sambuc }
934*ebfedea0SLionel Sambuc dearmour->buffered = 1;
935*ebfedea0SLionel Sambuc dearmour->eof64 = 1;
936*ebfedea0SLionel Sambuc l >>= 4;
937*ebfedea0SLionel Sambuc c = read_char(stream, dearmour, errors, readinfo, cbinfo, 0);
938*ebfedea0SLionel Sambuc if (c != '=') {
939*ebfedea0SLionel Sambuc PGP_ERROR_1(errors, PGP_E_R_BAD_FORMAT,
940*ebfedea0SLionel Sambuc "%s", "Badly terminated base64");
941*ebfedea0SLionel Sambuc return 0;
942*ebfedea0SLionel Sambuc }
943*ebfedea0SLionel Sambuc } else if (n == 0) {
944*ebfedea0SLionel Sambuc if (!dearmour->prev_nl || c != '=') {
945*ebfedea0SLionel Sambuc PGP_ERROR_1(errors, PGP_E_R_BAD_FORMAT,
946*ebfedea0SLionel Sambuc "%s", "Badly terminated base64 (4)");
947*ebfedea0SLionel Sambuc return 0;
948*ebfedea0SLionel Sambuc }
949*ebfedea0SLionel Sambuc dearmour->buffered = 0;
950*ebfedea0SLionel Sambuc } else {
951*ebfedea0SLionel Sambuc if (n != 4) {
952*ebfedea0SLionel Sambuc (void) fprintf(stderr,
953*ebfedea0SLionel Sambuc "decode64: bad n (!= 4)\n");
954*ebfedea0SLionel Sambuc return 0;
955*ebfedea0SLionel Sambuc }
956*ebfedea0SLionel Sambuc dearmour->buffered = 3;
957*ebfedea0SLionel Sambuc if (c == '-' || c == '=') {
958*ebfedea0SLionel Sambuc (void) fprintf(stderr, "decode64: bad c\n");
959*ebfedea0SLionel Sambuc return 0;
960*ebfedea0SLionel Sambuc }
961*ebfedea0SLionel Sambuc }
962*ebfedea0SLionel Sambuc
963*ebfedea0SLionel Sambuc if (dearmour->buffered < 3 && dearmour->buffered > 0) {
964*ebfedea0SLionel Sambuc /* then we saw padding */
965*ebfedea0SLionel Sambuc if (c != '=') {
966*ebfedea0SLionel Sambuc (void) fprintf(stderr, "decode64: bad c (=)\n");
967*ebfedea0SLionel Sambuc return 0;
968*ebfedea0SLionel Sambuc }
969*ebfedea0SLionel Sambuc c = read_and_eat_whitespace(stream, dearmour, errors, readinfo, cbinfo,
970*ebfedea0SLionel Sambuc 1);
971*ebfedea0SLionel Sambuc if (c != '\n') {
972*ebfedea0SLionel Sambuc PGP_ERROR_1(errors, PGP_E_R_BAD_FORMAT,
973*ebfedea0SLionel Sambuc "%s", "No newline at base64 end");
974*ebfedea0SLionel Sambuc return 0;
975*ebfedea0SLionel Sambuc }
976*ebfedea0SLionel Sambuc c = read_char(stream, dearmour, errors, readinfo, cbinfo, 0);
977*ebfedea0SLionel Sambuc if (c != '=') {
978*ebfedea0SLionel Sambuc PGP_ERROR_1(errors, PGP_E_R_BAD_FORMAT,
979*ebfedea0SLionel Sambuc "%s", "No checksum at base64 end");
980*ebfedea0SLionel Sambuc return 0;
981*ebfedea0SLionel Sambuc }
982*ebfedea0SLionel Sambuc }
983*ebfedea0SLionel Sambuc if (c == '=') {
984*ebfedea0SLionel Sambuc /* now we are at the checksum */
985*ebfedea0SLionel Sambuc ret = read4(stream, dearmour, errors, readinfo, cbinfo, &c, &n,
986*ebfedea0SLionel Sambuc &dearmour->read_checksum);
987*ebfedea0SLionel Sambuc if (ret < 0 || n != 4) {
988*ebfedea0SLionel Sambuc PGP_ERROR_1(errors, PGP_E_R_BAD_FORMAT,
989*ebfedea0SLionel Sambuc "%s", "Error in checksum");
990*ebfedea0SLionel Sambuc return 0;
991*ebfedea0SLionel Sambuc }
992*ebfedea0SLionel Sambuc c = read_char(stream, dearmour, errors, readinfo, cbinfo, 1);
993*ebfedea0SLionel Sambuc if (dearmour->allow_trailing_whitespace)
994*ebfedea0SLionel Sambuc c = eat_whitespace(stream, c, dearmour, errors, readinfo, cbinfo,
995*ebfedea0SLionel Sambuc 1);
996*ebfedea0SLionel Sambuc if (c != '\n') {
997*ebfedea0SLionel Sambuc PGP_ERROR_1(errors, PGP_E_R_BAD_FORMAT,
998*ebfedea0SLionel Sambuc "%s", "Badly terminated checksum");
999*ebfedea0SLionel Sambuc return 0;
1000*ebfedea0SLionel Sambuc }
1001*ebfedea0SLionel Sambuc c = read_char(stream, dearmour, errors, readinfo, cbinfo, 0);
1002*ebfedea0SLionel Sambuc if (c != '-') {
1003*ebfedea0SLionel Sambuc PGP_ERROR_1(errors, PGP_E_R_BAD_FORMAT,
1004*ebfedea0SLionel Sambuc "%s", "Bad base64 trailer (2)");
1005*ebfedea0SLionel Sambuc return 0;
1006*ebfedea0SLionel Sambuc }
1007*ebfedea0SLionel Sambuc }
1008*ebfedea0SLionel Sambuc if (c == '-') {
1009*ebfedea0SLionel Sambuc for (n = 0; n < 4; ++n)
1010*ebfedea0SLionel Sambuc if (read_char(stream, dearmour, errors, readinfo, cbinfo,
1011*ebfedea0SLionel Sambuc 0) != '-') {
1012*ebfedea0SLionel Sambuc PGP_ERROR_1(errors, PGP_E_R_BAD_FORMAT, "%s",
1013*ebfedea0SLionel Sambuc "Bad base64 trailer");
1014*ebfedea0SLionel Sambuc return 0;
1015*ebfedea0SLionel Sambuc }
1016*ebfedea0SLionel Sambuc dearmour->eof64 = 1;
1017*ebfedea0SLionel Sambuc } else {
1018*ebfedea0SLionel Sambuc if (!dearmour->buffered) {
1019*ebfedea0SLionel Sambuc (void) fprintf(stderr, "decode64: not buffered\n");
1020*ebfedea0SLionel Sambuc return 0;
1021*ebfedea0SLionel Sambuc }
1022*ebfedea0SLionel Sambuc }
1023*ebfedea0SLionel Sambuc
1024*ebfedea0SLionel Sambuc for (n = 0; n < dearmour->buffered; ++n) {
1025*ebfedea0SLionel Sambuc dearmour->buffer[n] = (uint8_t)l;
1026*ebfedea0SLionel Sambuc l >>= 8;
1027*ebfedea0SLionel Sambuc }
1028*ebfedea0SLionel Sambuc
1029*ebfedea0SLionel Sambuc for (n2 = dearmour->buffered - 1; n2 >= 0; --n2)
1030*ebfedea0SLionel Sambuc dearmour->checksum = pgp_crc24((unsigned)dearmour->checksum,
1031*ebfedea0SLionel Sambuc dearmour->buffer[n2]);
1032*ebfedea0SLionel Sambuc
1033*ebfedea0SLionel Sambuc if (dearmour->eof64 && dearmour->read_checksum != dearmour->checksum) {
1034*ebfedea0SLionel Sambuc PGP_ERROR_1(errors, PGP_E_R_BAD_FORMAT, "%s",
1035*ebfedea0SLionel Sambuc "Checksum mismatch");
1036*ebfedea0SLionel Sambuc return 0;
1037*ebfedea0SLionel Sambuc }
1038*ebfedea0SLionel Sambuc return 1;
1039*ebfedea0SLionel Sambuc }
1040*ebfedea0SLionel Sambuc
1041*ebfedea0SLionel Sambuc static void
base64(dearmour_t * dearmour)1042*ebfedea0SLionel Sambuc base64(dearmour_t *dearmour)
1043*ebfedea0SLionel Sambuc {
1044*ebfedea0SLionel Sambuc dearmour->state = BASE64;
1045*ebfedea0SLionel Sambuc dearmour->checksum = CRC24_INIT;
1046*ebfedea0SLionel Sambuc dearmour->eof64 = 0;
1047*ebfedea0SLionel Sambuc dearmour->buffered = 0;
1048*ebfedea0SLionel Sambuc }
1049*ebfedea0SLionel Sambuc
1050*ebfedea0SLionel Sambuc /* This reader is rather strange in that it can generate callbacks for */
1051*ebfedea0SLionel Sambuc /* content - this is because plaintext is not encapsulated in PGP */
1052*ebfedea0SLionel Sambuc /* packets... it also calls back for the text between the blocks. */
1053*ebfedea0SLionel Sambuc
1054*ebfedea0SLionel Sambuc static int
armoured_data_reader(pgp_stream_t * stream,void * dest_,size_t length,pgp_error_t ** errors,pgp_reader_t * readinfo,pgp_cbdata_t * cbinfo)1055*ebfedea0SLionel Sambuc armoured_data_reader(pgp_stream_t *stream, void *dest_, size_t length, pgp_error_t **errors,
1056*ebfedea0SLionel Sambuc pgp_reader_t *readinfo,
1057*ebfedea0SLionel Sambuc pgp_cbdata_t *cbinfo)
1058*ebfedea0SLionel Sambuc {
1059*ebfedea0SLionel Sambuc pgp_packet_t content;
1060*ebfedea0SLionel Sambuc dearmour_t *dearmour;
1061*ebfedea0SLionel Sambuc unsigned first;
1062*ebfedea0SLionel Sambuc uint8_t *dest = dest_;
1063*ebfedea0SLionel Sambuc char buf[1024];
1064*ebfedea0SLionel Sambuc int saved;
1065*ebfedea0SLionel Sambuc int ret;
1066*ebfedea0SLionel Sambuc
1067*ebfedea0SLionel Sambuc dearmour = pgp_reader_get_arg(readinfo);
1068*ebfedea0SLionel Sambuc saved = (int)length;
1069*ebfedea0SLionel Sambuc if (dearmour->eof64 && !dearmour->buffered) {
1070*ebfedea0SLionel Sambuc if (dearmour->state != OUTSIDE_BLOCK &&
1071*ebfedea0SLionel Sambuc dearmour->state != AT_TRAILER_NAME) {
1072*ebfedea0SLionel Sambuc (void) fprintf(stderr,
1073*ebfedea0SLionel Sambuc "armoured_data_reader: bad dearmour state\n");
1074*ebfedea0SLionel Sambuc return 0;
1075*ebfedea0SLionel Sambuc }
1076*ebfedea0SLionel Sambuc }
1077*ebfedea0SLionel Sambuc
1078*ebfedea0SLionel Sambuc while (length > 0) {
1079*ebfedea0SLionel Sambuc unsigned count;
1080*ebfedea0SLionel Sambuc unsigned n;
1081*ebfedea0SLionel Sambuc int c;
1082*ebfedea0SLionel Sambuc
1083*ebfedea0SLionel Sambuc flush(dearmour, cbinfo);
1084*ebfedea0SLionel Sambuc switch (dearmour->state) {
1085*ebfedea0SLionel Sambuc case OUTSIDE_BLOCK:
1086*ebfedea0SLionel Sambuc /*
1087*ebfedea0SLionel Sambuc * This code returns EOF rather than EARLY_EOF
1088*ebfedea0SLionel Sambuc * because if we don't see a header line at all, then
1089*ebfedea0SLionel Sambuc * it is just an EOF (and not a BLOCK_END)
1090*ebfedea0SLionel Sambuc */
1091*ebfedea0SLionel Sambuc while (!dearmour->seen_nl) {
1092*ebfedea0SLionel Sambuc if ((c = unarmoured_read_char(stream, dearmour, errors,
1093*ebfedea0SLionel Sambuc readinfo, cbinfo, 1)) < 0) {
1094*ebfedea0SLionel Sambuc return 0;
1095*ebfedea0SLionel Sambuc }
1096*ebfedea0SLionel Sambuc }
1097*ebfedea0SLionel Sambuc
1098*ebfedea0SLionel Sambuc /*
1099*ebfedea0SLionel Sambuc * flush at this point so we definitely have room for
1100*ebfedea0SLionel Sambuc * the header, and so we can easily erase it from the
1101*ebfedea0SLionel Sambuc * buffer
1102*ebfedea0SLionel Sambuc */
1103*ebfedea0SLionel Sambuc flush(dearmour, cbinfo);
1104*ebfedea0SLionel Sambuc /* Find and consume the 5 leading '-' */
1105*ebfedea0SLionel Sambuc for (count = 0; count < 5; ++count) {
1106*ebfedea0SLionel Sambuc if ((c = unarmoured_read_char(stream, dearmour, errors,
1107*ebfedea0SLionel Sambuc readinfo, cbinfo, 0)) < 0) {
1108*ebfedea0SLionel Sambuc return 0;
1109*ebfedea0SLionel Sambuc }
1110*ebfedea0SLionel Sambuc if (c != '-') {
1111*ebfedea0SLionel Sambuc goto reloop;
1112*ebfedea0SLionel Sambuc }
1113*ebfedea0SLionel Sambuc }
1114*ebfedea0SLionel Sambuc
1115*ebfedea0SLionel Sambuc /* Now find the block type */
1116*ebfedea0SLionel Sambuc for (n = 0; n < sizeof(buf) - 1;) {
1117*ebfedea0SLionel Sambuc if ((c = unarmoured_read_char(stream, dearmour, errors,
1118*ebfedea0SLionel Sambuc readinfo, cbinfo, 0)) < 0) {
1119*ebfedea0SLionel Sambuc return 0;
1120*ebfedea0SLionel Sambuc }
1121*ebfedea0SLionel Sambuc if (c == '-') {
1122*ebfedea0SLionel Sambuc goto got_minus;
1123*ebfedea0SLionel Sambuc }
1124*ebfedea0SLionel Sambuc buf[n++] = c;
1125*ebfedea0SLionel Sambuc }
1126*ebfedea0SLionel Sambuc /* then I guess this wasn't a proper header */
1127*ebfedea0SLionel Sambuc break;
1128*ebfedea0SLionel Sambuc
1129*ebfedea0SLionel Sambuc got_minus:
1130*ebfedea0SLionel Sambuc buf[n] = '\0';
1131*ebfedea0SLionel Sambuc
1132*ebfedea0SLionel Sambuc /* Consume trailing '-' */
1133*ebfedea0SLionel Sambuc for (count = 1; count < 5; ++count) {
1134*ebfedea0SLionel Sambuc if ((c = unarmoured_read_char(stream, dearmour, errors,
1135*ebfedea0SLionel Sambuc readinfo, cbinfo, 0)) < 0) {
1136*ebfedea0SLionel Sambuc return 0;
1137*ebfedea0SLionel Sambuc }
1138*ebfedea0SLionel Sambuc if (c != '-') {
1139*ebfedea0SLionel Sambuc /* wasn't a header after all */
1140*ebfedea0SLionel Sambuc goto reloop;
1141*ebfedea0SLionel Sambuc }
1142*ebfedea0SLionel Sambuc }
1143*ebfedea0SLionel Sambuc
1144*ebfedea0SLionel Sambuc /* Consume final NL */
1145*ebfedea0SLionel Sambuc if ((c = unarmoured_read_char(stream, dearmour, errors, readinfo,
1146*ebfedea0SLionel Sambuc cbinfo, 1)) < 0) {
1147*ebfedea0SLionel Sambuc return 0;
1148*ebfedea0SLionel Sambuc }
1149*ebfedea0SLionel Sambuc if (dearmour->allow_trailing_whitespace) {
1150*ebfedea0SLionel Sambuc if ((c = eat_whitespace(stream, c, dearmour, errors,
1151*ebfedea0SLionel Sambuc readinfo, cbinfo, 1)) < 0) {
1152*ebfedea0SLionel Sambuc return 0;
1153*ebfedea0SLionel Sambuc }
1154*ebfedea0SLionel Sambuc }
1155*ebfedea0SLionel Sambuc if (c != '\n') {
1156*ebfedea0SLionel Sambuc /* wasn't a header line after all */
1157*ebfedea0SLionel Sambuc break;
1158*ebfedea0SLionel Sambuc }
1159*ebfedea0SLionel Sambuc
1160*ebfedea0SLionel Sambuc /*
1161*ebfedea0SLionel Sambuc * Now we've seen the header, scrub it from the
1162*ebfedea0SLionel Sambuc * buffer
1163*ebfedea0SLionel Sambuc */
1164*ebfedea0SLionel Sambuc dearmour->unarmoredc = 0;
1165*ebfedea0SLionel Sambuc
1166*ebfedea0SLionel Sambuc /*
1167*ebfedea0SLionel Sambuc * But now we've seen a header line, then errors are
1168*ebfedea0SLionel Sambuc * EARLY_EOF
1169*ebfedea0SLionel Sambuc */
1170*ebfedea0SLionel Sambuc if ((ret = parse_headers(stream, dearmour, errors, readinfo,
1171*ebfedea0SLionel Sambuc cbinfo)) <= 0) {
1172*ebfedea0SLionel Sambuc return -1;
1173*ebfedea0SLionel Sambuc }
1174*ebfedea0SLionel Sambuc
1175*ebfedea0SLionel Sambuc if (!set_lastseen_headerline(dearmour, buf, errors)) {
1176*ebfedea0SLionel Sambuc return -1;
1177*ebfedea0SLionel Sambuc }
1178*ebfedea0SLionel Sambuc
1179*ebfedea0SLionel Sambuc if (strcmp(buf, "BEGIN PGP SIGNED MESSAGE") == 0) {
1180*ebfedea0SLionel Sambuc dup_headers(&content.u.cleartext_head,
1181*ebfedea0SLionel Sambuc &dearmour->headers);
1182*ebfedea0SLionel Sambuc CALLBACK(PGP_PTAG_CT_SIGNED_CLEARTEXT_HEADER,
1183*ebfedea0SLionel Sambuc cbinfo,
1184*ebfedea0SLionel Sambuc &content);
1185*ebfedea0SLionel Sambuc ret = process_dash_escaped(stream, dearmour, errors,
1186*ebfedea0SLionel Sambuc readinfo, cbinfo);
1187*ebfedea0SLionel Sambuc if (ret <= 0) {
1188*ebfedea0SLionel Sambuc return ret;
1189*ebfedea0SLionel Sambuc }
1190*ebfedea0SLionel Sambuc } else {
1191*ebfedea0SLionel Sambuc content.u.armour_header.type = buf;
1192*ebfedea0SLionel Sambuc content.u.armour_header.headers =
1193*ebfedea0SLionel Sambuc dearmour->headers;
1194*ebfedea0SLionel Sambuc (void) memset(&dearmour->headers, 0x0,
1195*ebfedea0SLionel Sambuc sizeof(dearmour->headers));
1196*ebfedea0SLionel Sambuc CALLBACK(PGP_PTAG_CT_ARMOUR_HEADER, cbinfo,
1197*ebfedea0SLionel Sambuc &content);
1198*ebfedea0SLionel Sambuc base64(dearmour);
1199*ebfedea0SLionel Sambuc }
1200*ebfedea0SLionel Sambuc break;
1201*ebfedea0SLionel Sambuc
1202*ebfedea0SLionel Sambuc case BASE64:
1203*ebfedea0SLionel Sambuc first = 1;
1204*ebfedea0SLionel Sambuc while (length > 0) {
1205*ebfedea0SLionel Sambuc if (!dearmour->buffered) {
1206*ebfedea0SLionel Sambuc if (!dearmour->eof64) {
1207*ebfedea0SLionel Sambuc ret = decode64(stream, dearmour,
1208*ebfedea0SLionel Sambuc errors, readinfo, cbinfo);
1209*ebfedea0SLionel Sambuc if (ret <= 0) {
1210*ebfedea0SLionel Sambuc return ret;
1211*ebfedea0SLionel Sambuc }
1212*ebfedea0SLionel Sambuc }
1213*ebfedea0SLionel Sambuc if (!dearmour->buffered) {
1214*ebfedea0SLionel Sambuc if (!dearmour->eof64) {
1215*ebfedea0SLionel Sambuc (void) fprintf(stderr,
1216*ebfedea0SLionel Sambuc "armoured_data_reader: bad dearmour eof64\n");
1217*ebfedea0SLionel Sambuc return 0;
1218*ebfedea0SLionel Sambuc }
1219*ebfedea0SLionel Sambuc if (first) {
1220*ebfedea0SLionel Sambuc dearmour->state =
1221*ebfedea0SLionel Sambuc AT_TRAILER_NAME;
1222*ebfedea0SLionel Sambuc goto reloop;
1223*ebfedea0SLionel Sambuc }
1224*ebfedea0SLionel Sambuc return -1;
1225*ebfedea0SLionel Sambuc }
1226*ebfedea0SLionel Sambuc }
1227*ebfedea0SLionel Sambuc if (!dearmour->buffered) {
1228*ebfedea0SLionel Sambuc (void) fprintf(stderr,
1229*ebfedea0SLionel Sambuc "armoured_data_reader: bad dearmour buffered\n");
1230*ebfedea0SLionel Sambuc return 0;
1231*ebfedea0SLionel Sambuc }
1232*ebfedea0SLionel Sambuc *dest = dearmour->buffer[--dearmour->buffered];
1233*ebfedea0SLionel Sambuc ++dest;
1234*ebfedea0SLionel Sambuc --length;
1235*ebfedea0SLionel Sambuc first = 0;
1236*ebfedea0SLionel Sambuc }
1237*ebfedea0SLionel Sambuc if (dearmour->eof64 && !dearmour->buffered) {
1238*ebfedea0SLionel Sambuc dearmour->state = AT_TRAILER_NAME;
1239*ebfedea0SLionel Sambuc }
1240*ebfedea0SLionel Sambuc break;
1241*ebfedea0SLionel Sambuc
1242*ebfedea0SLionel Sambuc case AT_TRAILER_NAME:
1243*ebfedea0SLionel Sambuc for (n = 0; n < sizeof(buf) - 1;) {
1244*ebfedea0SLionel Sambuc if ((c = read_char(stream, dearmour, errors, readinfo,
1245*ebfedea0SLionel Sambuc cbinfo, 0)) < 0) {
1246*ebfedea0SLionel Sambuc return -1;
1247*ebfedea0SLionel Sambuc }
1248*ebfedea0SLionel Sambuc if (c == '-') {
1249*ebfedea0SLionel Sambuc goto got_minus2;
1250*ebfedea0SLionel Sambuc }
1251*ebfedea0SLionel Sambuc buf[n++] = c;
1252*ebfedea0SLionel Sambuc }
1253*ebfedea0SLionel Sambuc /* then I guess this wasn't a proper trailer */
1254*ebfedea0SLionel Sambuc PGP_ERROR_1(errors, PGP_E_R_BAD_FORMAT, "%s",
1255*ebfedea0SLionel Sambuc "Bad ASCII armour trailer");
1256*ebfedea0SLionel Sambuc break;
1257*ebfedea0SLionel Sambuc
1258*ebfedea0SLionel Sambuc got_minus2:
1259*ebfedea0SLionel Sambuc buf[n] = '\0';
1260*ebfedea0SLionel Sambuc
1261*ebfedea0SLionel Sambuc if (!set_lastseen_headerline(dearmour, buf, errors)) {
1262*ebfedea0SLionel Sambuc return -1;
1263*ebfedea0SLionel Sambuc }
1264*ebfedea0SLionel Sambuc
1265*ebfedea0SLionel Sambuc /* Consume trailing '-' */
1266*ebfedea0SLionel Sambuc for (count = 1; count < 5; ++count) {
1267*ebfedea0SLionel Sambuc if ((c = read_char(stream, dearmour, errors, readinfo,
1268*ebfedea0SLionel Sambuc cbinfo, 0)) < 0) {
1269*ebfedea0SLionel Sambuc return -1;
1270*ebfedea0SLionel Sambuc }
1271*ebfedea0SLionel Sambuc if (c != '-') {
1272*ebfedea0SLionel Sambuc /* wasn't a trailer after all */
1273*ebfedea0SLionel Sambuc PGP_ERROR_1(errors, PGP_E_R_BAD_FORMAT,
1274*ebfedea0SLionel Sambuc "%s",
1275*ebfedea0SLionel Sambuc "Bad ASCII armour trailer (2)");
1276*ebfedea0SLionel Sambuc }
1277*ebfedea0SLionel Sambuc }
1278*ebfedea0SLionel Sambuc
1279*ebfedea0SLionel Sambuc /* Consume final NL */
1280*ebfedea0SLionel Sambuc if ((c = read_char(stream, dearmour, errors, readinfo, cbinfo,
1281*ebfedea0SLionel Sambuc 1)) < 0) {
1282*ebfedea0SLionel Sambuc return -1;
1283*ebfedea0SLionel Sambuc }
1284*ebfedea0SLionel Sambuc if (dearmour->allow_trailing_whitespace) {
1285*ebfedea0SLionel Sambuc if ((c = eat_whitespace(stream, c, dearmour, errors,
1286*ebfedea0SLionel Sambuc readinfo, cbinfo, 1)) < 0) {
1287*ebfedea0SLionel Sambuc return 0;
1288*ebfedea0SLionel Sambuc }
1289*ebfedea0SLionel Sambuc }
1290*ebfedea0SLionel Sambuc if (c != '\n') {
1291*ebfedea0SLionel Sambuc /* wasn't a trailer line after all */
1292*ebfedea0SLionel Sambuc PGP_ERROR_1(errors, PGP_E_R_BAD_FORMAT,
1293*ebfedea0SLionel Sambuc "%s", "Bad ASCII armour trailer (3)");
1294*ebfedea0SLionel Sambuc }
1295*ebfedea0SLionel Sambuc
1296*ebfedea0SLionel Sambuc if (strncmp(buf, "BEGIN ", 6) == 0) {
1297*ebfedea0SLionel Sambuc if (!set_lastseen_headerline(dearmour, buf,
1298*ebfedea0SLionel Sambuc errors)) {
1299*ebfedea0SLionel Sambuc return -1;
1300*ebfedea0SLionel Sambuc }
1301*ebfedea0SLionel Sambuc if ((ret = parse_headers(stream, dearmour, errors,
1302*ebfedea0SLionel Sambuc readinfo, cbinfo)) <= 0) {
1303*ebfedea0SLionel Sambuc return ret;
1304*ebfedea0SLionel Sambuc }
1305*ebfedea0SLionel Sambuc content.u.armour_header.type = buf;
1306*ebfedea0SLionel Sambuc content.u.armour_header.headers =
1307*ebfedea0SLionel Sambuc dearmour->headers;
1308*ebfedea0SLionel Sambuc (void) memset(&dearmour->headers, 0x0,
1309*ebfedea0SLionel Sambuc sizeof(dearmour->headers));
1310*ebfedea0SLionel Sambuc CALLBACK(PGP_PTAG_CT_ARMOUR_HEADER, cbinfo,
1311*ebfedea0SLionel Sambuc &content);
1312*ebfedea0SLionel Sambuc base64(dearmour);
1313*ebfedea0SLionel Sambuc } else {
1314*ebfedea0SLionel Sambuc content.u.armour_trailer = buf;
1315*ebfedea0SLionel Sambuc CALLBACK(PGP_PTAG_CT_ARMOUR_TRAILER, cbinfo,
1316*ebfedea0SLionel Sambuc &content);
1317*ebfedea0SLionel Sambuc dearmour->state = OUTSIDE_BLOCK;
1318*ebfedea0SLionel Sambuc }
1319*ebfedea0SLionel Sambuc break;
1320*ebfedea0SLionel Sambuc }
1321*ebfedea0SLionel Sambuc reloop:
1322*ebfedea0SLionel Sambuc continue;
1323*ebfedea0SLionel Sambuc }
1324*ebfedea0SLionel Sambuc
1325*ebfedea0SLionel Sambuc return saved;
1326*ebfedea0SLionel Sambuc }
1327*ebfedea0SLionel Sambuc
1328*ebfedea0SLionel Sambuc static void
armoured_data_destroyer(pgp_reader_t * readinfo)1329*ebfedea0SLionel Sambuc armoured_data_destroyer(pgp_reader_t *readinfo)
1330*ebfedea0SLionel Sambuc {
1331*ebfedea0SLionel Sambuc free(pgp_reader_get_arg(readinfo));
1332*ebfedea0SLionel Sambuc }
1333*ebfedea0SLionel Sambuc
1334*ebfedea0SLionel Sambuc /**
1335*ebfedea0SLionel Sambuc * \ingroup Core_Readers_Armour
1336*ebfedea0SLionel Sambuc * \brief Pushes dearmouring reader onto stack
1337*ebfedea0SLionel Sambuc * \param parse_info Usual structure containing information about to how to do the parse
1338*ebfedea0SLionel Sambuc * \sa pgp_reader_pop_dearmour()
1339*ebfedea0SLionel Sambuc */
1340*ebfedea0SLionel Sambuc void
pgp_reader_push_dearmour(pgp_stream_t * parse_info)1341*ebfedea0SLionel Sambuc pgp_reader_push_dearmour(pgp_stream_t *parse_info)
1342*ebfedea0SLionel Sambuc /*
1343*ebfedea0SLionel Sambuc * This function originally had these params to cater for packets which
1344*ebfedea0SLionel Sambuc * didn't strictly match the RFC. The initial 0.5 release is only going to
1345*ebfedea0SLionel Sambuc * support strict checking. If it becomes desirable to support loose checking
1346*ebfedea0SLionel Sambuc * of armoured packets and these params are reinstated, parse_headers() must
1347*ebfedea0SLionel Sambuc * be fixed so that these flags work correctly.
1348*ebfedea0SLionel Sambuc *
1349*ebfedea0SLionel Sambuc * // Allow headers in armoured data that are not separated from the data by a
1350*ebfedea0SLionel Sambuc * blank line unsigned without_gap,
1351*ebfedea0SLionel Sambuc *
1352*ebfedea0SLionel Sambuc * // Allow no blank line at the start of armoured data unsigned no_gap,
1353*ebfedea0SLionel Sambuc *
1354*ebfedea0SLionel Sambuc * //Allow armoured data to have trailing whitespace where we strictly would not
1355*ebfedea0SLionel Sambuc * expect it unsigned trailing_whitespace
1356*ebfedea0SLionel Sambuc */
1357*ebfedea0SLionel Sambuc {
1358*ebfedea0SLionel Sambuc dearmour_t *dearmour;
1359*ebfedea0SLionel Sambuc
1360*ebfedea0SLionel Sambuc if ((dearmour = calloc(1, sizeof(*dearmour))) == NULL) {
1361*ebfedea0SLionel Sambuc (void) fprintf(stderr, "pgp_reader_push_dearmour: bad alloc\n");
1362*ebfedea0SLionel Sambuc } else {
1363*ebfedea0SLionel Sambuc dearmour->seen_nl = 1;
1364*ebfedea0SLionel Sambuc /*
1365*ebfedea0SLionel Sambuc dearmour->allow_headers_without_gap=without_gap;
1366*ebfedea0SLionel Sambuc dearmour->allow_no_gap=no_gap;
1367*ebfedea0SLionel Sambuc dearmour->allow_trailing_whitespace=trailing_whitespace;
1368*ebfedea0SLionel Sambuc */
1369*ebfedea0SLionel Sambuc dearmour->expect_sig = 0;
1370*ebfedea0SLionel Sambuc dearmour->got_sig = 0;
1371*ebfedea0SLionel Sambuc
1372*ebfedea0SLionel Sambuc pgp_reader_push(parse_info, armoured_data_reader,
1373*ebfedea0SLionel Sambuc armoured_data_destroyer, dearmour);
1374*ebfedea0SLionel Sambuc }
1375*ebfedea0SLionel Sambuc }
1376*ebfedea0SLionel Sambuc
1377*ebfedea0SLionel Sambuc /**
1378*ebfedea0SLionel Sambuc * \ingroup Core_Readers_Armour
1379*ebfedea0SLionel Sambuc * \brief Pops dearmour reader from stock
1380*ebfedea0SLionel Sambuc * \param stream
1381*ebfedea0SLionel Sambuc * \sa pgp_reader_push_dearmour()
1382*ebfedea0SLionel Sambuc */
1383*ebfedea0SLionel Sambuc void
pgp_reader_pop_dearmour(pgp_stream_t * stream)1384*ebfedea0SLionel Sambuc pgp_reader_pop_dearmour(pgp_stream_t *stream)
1385*ebfedea0SLionel Sambuc {
1386*ebfedea0SLionel Sambuc dearmour_t *dearmour;
1387*ebfedea0SLionel Sambuc
1388*ebfedea0SLionel Sambuc dearmour = pgp_reader_get_arg(pgp_readinfo(stream));
1389*ebfedea0SLionel Sambuc free(dearmour);
1390*ebfedea0SLionel Sambuc pgp_reader_pop(stream);
1391*ebfedea0SLionel Sambuc }
1392*ebfedea0SLionel Sambuc
1393*ebfedea0SLionel Sambuc /**************************************************************************/
1394*ebfedea0SLionel Sambuc
1395*ebfedea0SLionel Sambuc /* this is actually used for *decrypting* */
1396*ebfedea0SLionel Sambuc typedef struct {
1397*ebfedea0SLionel Sambuc uint8_t decrypted[1024 * 15];
1398*ebfedea0SLionel Sambuc size_t c;
1399*ebfedea0SLionel Sambuc size_t off;
1400*ebfedea0SLionel Sambuc pgp_crypt_t *decrypt;
1401*ebfedea0SLionel Sambuc pgp_region_t *region;
1402*ebfedea0SLionel Sambuc unsigned prevplain:1;
1403*ebfedea0SLionel Sambuc } encrypted_t;
1404*ebfedea0SLionel Sambuc
1405*ebfedea0SLionel Sambuc static int
encrypted_data_reader(pgp_stream_t * stream,void * dest,size_t length,pgp_error_t ** errors,pgp_reader_t * readinfo,pgp_cbdata_t * cbinfo)1406*ebfedea0SLionel Sambuc encrypted_data_reader(pgp_stream_t *stream, void *dest,
1407*ebfedea0SLionel Sambuc size_t length,
1408*ebfedea0SLionel Sambuc pgp_error_t **errors,
1409*ebfedea0SLionel Sambuc pgp_reader_t *readinfo,
1410*ebfedea0SLionel Sambuc pgp_cbdata_t *cbinfo)
1411*ebfedea0SLionel Sambuc {
1412*ebfedea0SLionel Sambuc encrypted_t *encrypted;
1413*ebfedea0SLionel Sambuc char *cdest;
1414*ebfedea0SLionel Sambuc int saved;
1415*ebfedea0SLionel Sambuc
1416*ebfedea0SLionel Sambuc encrypted = pgp_reader_get_arg(readinfo);
1417*ebfedea0SLionel Sambuc saved = (int)length;
1418*ebfedea0SLionel Sambuc /*
1419*ebfedea0SLionel Sambuc * V3 MPIs have the count plain and the cipher is reset after each
1420*ebfedea0SLionel Sambuc * count
1421*ebfedea0SLionel Sambuc */
1422*ebfedea0SLionel Sambuc if (encrypted->prevplain && !readinfo->parent->reading_mpi_len) {
1423*ebfedea0SLionel Sambuc if (!readinfo->parent->reading_v3_secret) {
1424*ebfedea0SLionel Sambuc (void) fprintf(stderr,
1425*ebfedea0SLionel Sambuc "encrypted_data_reader: bad v3 secret\n");
1426*ebfedea0SLionel Sambuc return -1;
1427*ebfedea0SLionel Sambuc }
1428*ebfedea0SLionel Sambuc encrypted->decrypt->decrypt_resync(encrypted->decrypt);
1429*ebfedea0SLionel Sambuc encrypted->prevplain = 0;
1430*ebfedea0SLionel Sambuc } else if (readinfo->parent->reading_v3_secret &&
1431*ebfedea0SLionel Sambuc readinfo->parent->reading_mpi_len) {
1432*ebfedea0SLionel Sambuc encrypted->prevplain = 1;
1433*ebfedea0SLionel Sambuc }
1434*ebfedea0SLionel Sambuc while (length > 0) {
1435*ebfedea0SLionel Sambuc if (encrypted->c) {
1436*ebfedea0SLionel Sambuc unsigned n;
1437*ebfedea0SLionel Sambuc
1438*ebfedea0SLionel Sambuc /*
1439*ebfedea0SLionel Sambuc * if we are reading v3 we should never read
1440*ebfedea0SLionel Sambuc * more than we're asked for */
1441*ebfedea0SLionel Sambuc if (length < encrypted->c &&
1442*ebfedea0SLionel Sambuc (readinfo->parent->reading_v3_secret ||
1443*ebfedea0SLionel Sambuc readinfo->parent->exact_read)) {
1444*ebfedea0SLionel Sambuc (void) fprintf(stderr,
1445*ebfedea0SLionel Sambuc "encrypted_data_reader: bad v3 read\n");
1446*ebfedea0SLionel Sambuc return 0;
1447*ebfedea0SLionel Sambuc }
1448*ebfedea0SLionel Sambuc n = (int)MIN(length, encrypted->c);
1449*ebfedea0SLionel Sambuc (void) memcpy(dest,
1450*ebfedea0SLionel Sambuc encrypted->decrypted + encrypted->off, n);
1451*ebfedea0SLionel Sambuc encrypted->c -= n;
1452*ebfedea0SLionel Sambuc encrypted->off += n;
1453*ebfedea0SLionel Sambuc length -= n;
1454*ebfedea0SLionel Sambuc cdest = dest;
1455*ebfedea0SLionel Sambuc cdest += n;
1456*ebfedea0SLionel Sambuc dest = cdest;
1457*ebfedea0SLionel Sambuc } else {
1458*ebfedea0SLionel Sambuc unsigned n = encrypted->region->length;
1459*ebfedea0SLionel Sambuc uint8_t buffer[1024];
1460*ebfedea0SLionel Sambuc
1461*ebfedea0SLionel Sambuc if (!n) {
1462*ebfedea0SLionel Sambuc return -1;
1463*ebfedea0SLionel Sambuc }
1464*ebfedea0SLionel Sambuc if (!encrypted->region->indeterminate) {
1465*ebfedea0SLionel Sambuc n -= encrypted->region->readc;
1466*ebfedea0SLionel Sambuc if (n == 0) {
1467*ebfedea0SLionel Sambuc return (int)(saved - length);
1468*ebfedea0SLionel Sambuc }
1469*ebfedea0SLionel Sambuc if (n > sizeof(buffer)) {
1470*ebfedea0SLionel Sambuc n = sizeof(buffer);
1471*ebfedea0SLionel Sambuc }
1472*ebfedea0SLionel Sambuc } else {
1473*ebfedea0SLionel Sambuc n = sizeof(buffer);
1474*ebfedea0SLionel Sambuc }
1475*ebfedea0SLionel Sambuc
1476*ebfedea0SLionel Sambuc /*
1477*ebfedea0SLionel Sambuc * we can only read as much as we're asked for
1478*ebfedea0SLionel Sambuc * in v3 keys because they're partially
1479*ebfedea0SLionel Sambuc * unencrypted! */
1480*ebfedea0SLionel Sambuc if ((readinfo->parent->reading_v3_secret ||
1481*ebfedea0SLionel Sambuc readinfo->parent->exact_read) && n > length) {
1482*ebfedea0SLionel Sambuc n = (unsigned)length;
1483*ebfedea0SLionel Sambuc }
1484*ebfedea0SLionel Sambuc
1485*ebfedea0SLionel Sambuc if (!pgp_stacked_limited_read(stream, buffer, n,
1486*ebfedea0SLionel Sambuc encrypted->region, errors, readinfo, cbinfo)) {
1487*ebfedea0SLionel Sambuc return -1;
1488*ebfedea0SLionel Sambuc }
1489*ebfedea0SLionel Sambuc if (!readinfo->parent->reading_v3_secret ||
1490*ebfedea0SLionel Sambuc !readinfo->parent->reading_mpi_len) {
1491*ebfedea0SLionel Sambuc encrypted->c =
1492*ebfedea0SLionel Sambuc pgp_decrypt_se_ip(encrypted->decrypt,
1493*ebfedea0SLionel Sambuc encrypted->decrypted, buffer, n);
1494*ebfedea0SLionel Sambuc
1495*ebfedea0SLionel Sambuc if (pgp_get_debug_level(__FILE__)) {
1496*ebfedea0SLionel Sambuc hexdump(stderr, "encrypted", buffer, 16);
1497*ebfedea0SLionel Sambuc hexdump(stderr, "decrypted", encrypted->decrypted, 16);
1498*ebfedea0SLionel Sambuc }
1499*ebfedea0SLionel Sambuc } else {
1500*ebfedea0SLionel Sambuc (void) memcpy(
1501*ebfedea0SLionel Sambuc &encrypted->decrypted[encrypted->off], buffer, n);
1502*ebfedea0SLionel Sambuc encrypted->c = n;
1503*ebfedea0SLionel Sambuc }
1504*ebfedea0SLionel Sambuc
1505*ebfedea0SLionel Sambuc if (encrypted->c == 0) {
1506*ebfedea0SLionel Sambuc (void) fprintf(stderr,
1507*ebfedea0SLionel Sambuc "encrypted_data_reader: 0 decrypted count\n");
1508*ebfedea0SLionel Sambuc return 0;
1509*ebfedea0SLionel Sambuc }
1510*ebfedea0SLionel Sambuc
1511*ebfedea0SLionel Sambuc encrypted->off = 0;
1512*ebfedea0SLionel Sambuc }
1513*ebfedea0SLionel Sambuc }
1514*ebfedea0SLionel Sambuc
1515*ebfedea0SLionel Sambuc return saved;
1516*ebfedea0SLionel Sambuc }
1517*ebfedea0SLionel Sambuc
1518*ebfedea0SLionel Sambuc static void
encrypted_data_destroyer(pgp_reader_t * readinfo)1519*ebfedea0SLionel Sambuc encrypted_data_destroyer(pgp_reader_t *readinfo)
1520*ebfedea0SLionel Sambuc {
1521*ebfedea0SLionel Sambuc free(pgp_reader_get_arg(readinfo));
1522*ebfedea0SLionel Sambuc }
1523*ebfedea0SLionel Sambuc
1524*ebfedea0SLionel Sambuc /**
1525*ebfedea0SLionel Sambuc * \ingroup Core_Readers_SE
1526*ebfedea0SLionel Sambuc * \brief Pushes decryption reader onto stack
1527*ebfedea0SLionel Sambuc * \sa pgp_reader_pop_decrypt()
1528*ebfedea0SLionel Sambuc */
1529*ebfedea0SLionel Sambuc void
pgp_reader_push_decrypt(pgp_stream_t * stream,pgp_crypt_t * decrypt,pgp_region_t * region)1530*ebfedea0SLionel Sambuc pgp_reader_push_decrypt(pgp_stream_t *stream, pgp_crypt_t *decrypt,
1531*ebfedea0SLionel Sambuc pgp_region_t *region)
1532*ebfedea0SLionel Sambuc {
1533*ebfedea0SLionel Sambuc encrypted_t *encrypted;
1534*ebfedea0SLionel Sambuc
1535*ebfedea0SLionel Sambuc if ((encrypted = calloc(1, sizeof(*encrypted))) == NULL) {
1536*ebfedea0SLionel Sambuc (void) fprintf(stderr, "pgp_reader_push_decrypted: bad alloc\n");
1537*ebfedea0SLionel Sambuc } else {
1538*ebfedea0SLionel Sambuc encrypted->decrypt = decrypt;
1539*ebfedea0SLionel Sambuc encrypted->region = region;
1540*ebfedea0SLionel Sambuc pgp_decrypt_init(encrypted->decrypt);
1541*ebfedea0SLionel Sambuc pgp_reader_push(stream, encrypted_data_reader,
1542*ebfedea0SLionel Sambuc encrypted_data_destroyer, encrypted);
1543*ebfedea0SLionel Sambuc }
1544*ebfedea0SLionel Sambuc }
1545*ebfedea0SLionel Sambuc
1546*ebfedea0SLionel Sambuc /**
1547*ebfedea0SLionel Sambuc * \ingroup Core_Readers_Encrypted
1548*ebfedea0SLionel Sambuc * \brief Pops decryption reader from stack
1549*ebfedea0SLionel Sambuc * \sa pgp_reader_push_decrypt()
1550*ebfedea0SLionel Sambuc */
1551*ebfedea0SLionel Sambuc void
pgp_reader_pop_decrypt(pgp_stream_t * stream)1552*ebfedea0SLionel Sambuc pgp_reader_pop_decrypt(pgp_stream_t *stream)
1553*ebfedea0SLionel Sambuc {
1554*ebfedea0SLionel Sambuc encrypted_t *encrypted;
1555*ebfedea0SLionel Sambuc
1556*ebfedea0SLionel Sambuc encrypted = pgp_reader_get_arg(pgp_readinfo(stream));
1557*ebfedea0SLionel Sambuc encrypted->decrypt->decrypt_finish(encrypted->decrypt);
1558*ebfedea0SLionel Sambuc free(encrypted);
1559*ebfedea0SLionel Sambuc pgp_reader_pop(stream);
1560*ebfedea0SLionel Sambuc }
1561*ebfedea0SLionel Sambuc
1562*ebfedea0SLionel Sambuc /**************************************************************************/
1563*ebfedea0SLionel Sambuc
1564*ebfedea0SLionel Sambuc typedef struct {
1565*ebfedea0SLionel Sambuc /* boolean: 0 once we've done the preamble/MDC checks */
1566*ebfedea0SLionel Sambuc /* and are reading from the plaintext */
1567*ebfedea0SLionel Sambuc int passed_checks;
1568*ebfedea0SLionel Sambuc uint8_t *plaintext;
1569*ebfedea0SLionel Sambuc size_t plaintext_available;
1570*ebfedea0SLionel Sambuc size_t plaintext_offset;
1571*ebfedea0SLionel Sambuc pgp_region_t *region;
1572*ebfedea0SLionel Sambuc pgp_crypt_t *decrypt;
1573*ebfedea0SLionel Sambuc } decrypt_se_ip_t;
1574*ebfedea0SLionel Sambuc
1575*ebfedea0SLionel Sambuc /*
1576*ebfedea0SLionel Sambuc Gets entire SE_IP data packet.
1577*ebfedea0SLionel Sambuc Verifies leading preamble
1578*ebfedea0SLionel Sambuc Verifies trailing MDC packet
1579*ebfedea0SLionel Sambuc Then passes up plaintext as requested
1580*ebfedea0SLionel Sambuc */
1581*ebfedea0SLionel Sambuc static int
se_ip_data_reader(pgp_stream_t * stream,void * dest_,size_t len,pgp_error_t ** errors,pgp_reader_t * readinfo,pgp_cbdata_t * cbinfo)1582*ebfedea0SLionel Sambuc se_ip_data_reader(pgp_stream_t *stream, void *dest_,
1583*ebfedea0SLionel Sambuc size_t len,
1584*ebfedea0SLionel Sambuc pgp_error_t **errors,
1585*ebfedea0SLionel Sambuc pgp_reader_t *readinfo,
1586*ebfedea0SLionel Sambuc pgp_cbdata_t *cbinfo)
1587*ebfedea0SLionel Sambuc {
1588*ebfedea0SLionel Sambuc decrypt_se_ip_t *se_ip;
1589*ebfedea0SLionel Sambuc pgp_region_t decrypted_region;
1590*ebfedea0SLionel Sambuc unsigned n = 0;
1591*ebfedea0SLionel Sambuc
1592*ebfedea0SLionel Sambuc se_ip = pgp_reader_get_arg(readinfo);
1593*ebfedea0SLionel Sambuc if (!se_ip->passed_checks) {
1594*ebfedea0SLionel Sambuc uint8_t *buf = NULL;
1595*ebfedea0SLionel Sambuc uint8_t hashed[PGP_SHA1_HASH_SIZE];
1596*ebfedea0SLionel Sambuc uint8_t *preamble;
1597*ebfedea0SLionel Sambuc uint8_t *plaintext;
1598*ebfedea0SLionel Sambuc uint8_t *mdc;
1599*ebfedea0SLionel Sambuc uint8_t *mdc_hash;
1600*ebfedea0SLionel Sambuc pgp_hash_t hash;
1601*ebfedea0SLionel Sambuc size_t b;
1602*ebfedea0SLionel Sambuc size_t sz_preamble;
1603*ebfedea0SLionel Sambuc size_t sz_mdc_hash;
1604*ebfedea0SLionel Sambuc size_t sz_mdc;
1605*ebfedea0SLionel Sambuc size_t sz_plaintext;
1606*ebfedea0SLionel Sambuc
1607*ebfedea0SLionel Sambuc pgp_hash_any(&hash, PGP_HASH_SHA1);
1608*ebfedea0SLionel Sambuc if (!hash.init(&hash)) {
1609*ebfedea0SLionel Sambuc (void) fprintf(stderr,
1610*ebfedea0SLionel Sambuc "se_ip_data_reader: can't init hash\n");
1611*ebfedea0SLionel Sambuc return -1;
1612*ebfedea0SLionel Sambuc }
1613*ebfedea0SLionel Sambuc
1614*ebfedea0SLionel Sambuc pgp_init_subregion(&decrypted_region, NULL);
1615*ebfedea0SLionel Sambuc decrypted_region.length =
1616*ebfedea0SLionel Sambuc se_ip->region->length - se_ip->region->readc;
1617*ebfedea0SLionel Sambuc if ((buf = calloc(1, decrypted_region.length)) == NULL) {
1618*ebfedea0SLionel Sambuc (void) fprintf(stderr, "se_ip_data_reader: bad alloc\n");
1619*ebfedea0SLionel Sambuc return -1;
1620*ebfedea0SLionel Sambuc }
1621*ebfedea0SLionel Sambuc
1622*ebfedea0SLionel Sambuc /* read entire SE IP packet */
1623*ebfedea0SLionel Sambuc if (!pgp_stacked_limited_read(stream, buf, decrypted_region.length,
1624*ebfedea0SLionel Sambuc &decrypted_region, errors, readinfo, cbinfo)) {
1625*ebfedea0SLionel Sambuc free(buf);
1626*ebfedea0SLionel Sambuc return -1;
1627*ebfedea0SLionel Sambuc }
1628*ebfedea0SLionel Sambuc if (pgp_get_debug_level(__FILE__)) {
1629*ebfedea0SLionel Sambuc hexdump(stderr, "SE IP packet", buf, decrypted_region.length);
1630*ebfedea0SLionel Sambuc }
1631*ebfedea0SLionel Sambuc /* verify leading preamble */
1632*ebfedea0SLionel Sambuc if (pgp_get_debug_level(__FILE__)) {
1633*ebfedea0SLionel Sambuc hexdump(stderr, "preamble", buf, se_ip->decrypt->blocksize);
1634*ebfedea0SLionel Sambuc }
1635*ebfedea0SLionel Sambuc b = se_ip->decrypt->blocksize;
1636*ebfedea0SLionel Sambuc if (buf[b - 2] != buf[b] || buf[b - 1] != buf[b + 1]) {
1637*ebfedea0SLionel Sambuc fprintf(stderr,
1638*ebfedea0SLionel Sambuc "Bad symmetric decrypt (%02x%02x vs %02x%02x)\n",
1639*ebfedea0SLionel Sambuc buf[b - 2], buf[b - 1], buf[b], buf[b + 1]);
1640*ebfedea0SLionel Sambuc PGP_ERROR_1(errors, PGP_E_PROTO_BAD_SYMMETRIC_DECRYPT,
1641*ebfedea0SLionel Sambuc "%s", "Bad symmetric decrypt when parsing SE IP"
1642*ebfedea0SLionel Sambuc " packet");
1643*ebfedea0SLionel Sambuc free(buf);
1644*ebfedea0SLionel Sambuc return -1;
1645*ebfedea0SLionel Sambuc }
1646*ebfedea0SLionel Sambuc /* Verify trailing MDC hash */
1647*ebfedea0SLionel Sambuc
1648*ebfedea0SLionel Sambuc sz_preamble = se_ip->decrypt->blocksize + 2;
1649*ebfedea0SLionel Sambuc sz_mdc_hash = PGP_SHA1_HASH_SIZE;
1650*ebfedea0SLionel Sambuc sz_mdc = 1 + 1 + sz_mdc_hash;
1651*ebfedea0SLionel Sambuc sz_plaintext = (decrypted_region.length - sz_preamble) - sz_mdc;
1652*ebfedea0SLionel Sambuc
1653*ebfedea0SLionel Sambuc preamble = buf;
1654*ebfedea0SLionel Sambuc plaintext = buf + sz_preamble;
1655*ebfedea0SLionel Sambuc mdc = plaintext + sz_plaintext;
1656*ebfedea0SLionel Sambuc mdc_hash = mdc + 2;
1657*ebfedea0SLionel Sambuc
1658*ebfedea0SLionel Sambuc if (pgp_get_debug_level(__FILE__)) {
1659*ebfedea0SLionel Sambuc hexdump(stderr, "plaintext", plaintext, sz_plaintext);
1660*ebfedea0SLionel Sambuc hexdump(stderr, "mdc", mdc, sz_mdc);
1661*ebfedea0SLionel Sambuc }
1662*ebfedea0SLionel Sambuc pgp_calc_mdc_hash(preamble, sz_preamble, plaintext,
1663*ebfedea0SLionel Sambuc (unsigned)sz_plaintext, hashed);
1664*ebfedea0SLionel Sambuc
1665*ebfedea0SLionel Sambuc if (memcmp(mdc_hash, hashed, PGP_SHA1_HASH_SIZE) != 0) {
1666*ebfedea0SLionel Sambuc PGP_ERROR_1(errors, PGP_E_V_BAD_HASH, "%s",
1667*ebfedea0SLionel Sambuc "Bad hash in MDC packet");
1668*ebfedea0SLionel Sambuc free(buf);
1669*ebfedea0SLionel Sambuc return 0;
1670*ebfedea0SLionel Sambuc }
1671*ebfedea0SLionel Sambuc /* all done with the checks */
1672*ebfedea0SLionel Sambuc /* now can start reading from the plaintext */
1673*ebfedea0SLionel Sambuc if (se_ip->plaintext) {
1674*ebfedea0SLionel Sambuc (void) fprintf(stderr,
1675*ebfedea0SLionel Sambuc "se_ip_data_reader: bad plaintext\n");
1676*ebfedea0SLionel Sambuc return 0;
1677*ebfedea0SLionel Sambuc }
1678*ebfedea0SLionel Sambuc if ((se_ip->plaintext = calloc(1, sz_plaintext)) == NULL) {
1679*ebfedea0SLionel Sambuc (void) fprintf(stderr,
1680*ebfedea0SLionel Sambuc "se_ip_data_reader: bad alloc\n");
1681*ebfedea0SLionel Sambuc return 0;
1682*ebfedea0SLionel Sambuc }
1683*ebfedea0SLionel Sambuc memcpy(se_ip->plaintext, plaintext, sz_plaintext);
1684*ebfedea0SLionel Sambuc se_ip->plaintext_available = sz_plaintext;
1685*ebfedea0SLionel Sambuc
1686*ebfedea0SLionel Sambuc se_ip->passed_checks = 1;
1687*ebfedea0SLionel Sambuc
1688*ebfedea0SLionel Sambuc free(buf);
1689*ebfedea0SLionel Sambuc }
1690*ebfedea0SLionel Sambuc n = (unsigned)len;
1691*ebfedea0SLionel Sambuc if (n > se_ip->plaintext_available) {
1692*ebfedea0SLionel Sambuc n = (unsigned)se_ip->plaintext_available;
1693*ebfedea0SLionel Sambuc }
1694*ebfedea0SLionel Sambuc
1695*ebfedea0SLionel Sambuc memcpy(dest_, se_ip->plaintext + se_ip->plaintext_offset, n);
1696*ebfedea0SLionel Sambuc se_ip->plaintext_available -= n;
1697*ebfedea0SLionel Sambuc se_ip->plaintext_offset += n;
1698*ebfedea0SLionel Sambuc /* len -= n; - not used at all, for info only */
1699*ebfedea0SLionel Sambuc
1700*ebfedea0SLionel Sambuc return n;
1701*ebfedea0SLionel Sambuc }
1702*ebfedea0SLionel Sambuc
1703*ebfedea0SLionel Sambuc static void
se_ip_data_destroyer(pgp_reader_t * readinfo)1704*ebfedea0SLionel Sambuc se_ip_data_destroyer(pgp_reader_t *readinfo)
1705*ebfedea0SLionel Sambuc {
1706*ebfedea0SLionel Sambuc decrypt_se_ip_t *se_ip;
1707*ebfedea0SLionel Sambuc
1708*ebfedea0SLionel Sambuc se_ip = pgp_reader_get_arg(readinfo);
1709*ebfedea0SLionel Sambuc free(se_ip->plaintext);
1710*ebfedea0SLionel Sambuc free(se_ip);
1711*ebfedea0SLionel Sambuc }
1712*ebfedea0SLionel Sambuc
1713*ebfedea0SLionel Sambuc /**
1714*ebfedea0SLionel Sambuc \ingroup Internal_Readers_SEIP
1715*ebfedea0SLionel Sambuc */
1716*ebfedea0SLionel Sambuc void
pgp_reader_push_se_ip_data(pgp_stream_t * stream,pgp_crypt_t * decrypt,pgp_region_t * region)1717*ebfedea0SLionel Sambuc pgp_reader_push_se_ip_data(pgp_stream_t *stream, pgp_crypt_t *decrypt,
1718*ebfedea0SLionel Sambuc pgp_region_t * region)
1719*ebfedea0SLionel Sambuc {
1720*ebfedea0SLionel Sambuc decrypt_se_ip_t *se_ip;
1721*ebfedea0SLionel Sambuc
1722*ebfedea0SLionel Sambuc if ((se_ip = calloc(1, sizeof(*se_ip))) == NULL) {
1723*ebfedea0SLionel Sambuc (void) fprintf(stderr, "pgp_reader_push_se_ip_data: bad alloc\n");
1724*ebfedea0SLionel Sambuc } else {
1725*ebfedea0SLionel Sambuc se_ip->region = region;
1726*ebfedea0SLionel Sambuc se_ip->decrypt = decrypt;
1727*ebfedea0SLionel Sambuc pgp_reader_push(stream, se_ip_data_reader, se_ip_data_destroyer,
1728*ebfedea0SLionel Sambuc se_ip);
1729*ebfedea0SLionel Sambuc }
1730*ebfedea0SLionel Sambuc }
1731*ebfedea0SLionel Sambuc
1732*ebfedea0SLionel Sambuc /**
1733*ebfedea0SLionel Sambuc \ingroup Internal_Readers_SEIP
1734*ebfedea0SLionel Sambuc */
1735*ebfedea0SLionel Sambuc void
pgp_reader_pop_se_ip_data(pgp_stream_t * stream)1736*ebfedea0SLionel Sambuc pgp_reader_pop_se_ip_data(pgp_stream_t *stream)
1737*ebfedea0SLionel Sambuc {
1738*ebfedea0SLionel Sambuc /*
1739*ebfedea0SLionel Sambuc * decrypt_se_ip_t
1740*ebfedea0SLionel Sambuc * *se_ip=pgp_reader_get_arg(pgp_readinfo(stream));
1741*ebfedea0SLionel Sambuc */
1742*ebfedea0SLionel Sambuc /* free(se_ip); */
1743*ebfedea0SLionel Sambuc pgp_reader_pop(stream);
1744*ebfedea0SLionel Sambuc }
1745*ebfedea0SLionel Sambuc
1746*ebfedea0SLionel Sambuc /**************************************************************************/
1747*ebfedea0SLionel Sambuc
1748*ebfedea0SLionel Sambuc /** Arguments for reader_fd
1749*ebfedea0SLionel Sambuc */
1750*ebfedea0SLionel Sambuc typedef struct mmap_reader_t {
1751*ebfedea0SLionel Sambuc void *mem; /* memory mapped file */
1752*ebfedea0SLionel Sambuc uint64_t size; /* size of file */
1753*ebfedea0SLionel Sambuc uint64_t offset; /* current offset in file */
1754*ebfedea0SLionel Sambuc int fd; /* file descriptor */
1755*ebfedea0SLionel Sambuc } mmap_reader_t;
1756*ebfedea0SLionel Sambuc
1757*ebfedea0SLionel Sambuc
1758*ebfedea0SLionel Sambuc /**
1759*ebfedea0SLionel Sambuc * \ingroup Core_Readers
1760*ebfedea0SLionel Sambuc *
1761*ebfedea0SLionel Sambuc * pgp_reader_fd() attempts to read up to "plength" bytes from the file
1762*ebfedea0SLionel Sambuc * descriptor in "parse_info" into the buffer starting at "dest" using the
1763*ebfedea0SLionel Sambuc * rules contained in "flags"
1764*ebfedea0SLionel Sambuc *
1765*ebfedea0SLionel Sambuc * \param dest Pointer to previously allocated buffer
1766*ebfedea0SLionel Sambuc * \param plength Number of bytes to try to read
1767*ebfedea0SLionel Sambuc * \param flags Rules about reading to use
1768*ebfedea0SLionel Sambuc * \param readinfo Reader info
1769*ebfedea0SLionel Sambuc * \param cbinfo Callback info
1770*ebfedea0SLionel Sambuc *
1771*ebfedea0SLionel Sambuc * \return n Number of bytes read
1772*ebfedea0SLionel Sambuc *
1773*ebfedea0SLionel Sambuc * PGP_R_EARLY_EOF and PGP_R_ERROR push errors on the stack
1774*ebfedea0SLionel Sambuc */
1775*ebfedea0SLionel Sambuc static int
fd_reader(pgp_stream_t * stream,void * dest,size_t length,pgp_error_t ** errors,pgp_reader_t * readinfo,pgp_cbdata_t * cbinfo)1776*ebfedea0SLionel Sambuc fd_reader(pgp_stream_t *stream, void *dest, size_t length, pgp_error_t **errors,
1777*ebfedea0SLionel Sambuc pgp_reader_t *readinfo, pgp_cbdata_t *cbinfo)
1778*ebfedea0SLionel Sambuc {
1779*ebfedea0SLionel Sambuc mmap_reader_t *reader;
1780*ebfedea0SLionel Sambuc int n;
1781*ebfedea0SLionel Sambuc
1782*ebfedea0SLionel Sambuc __PGP_USED(cbinfo);
1783*ebfedea0SLionel Sambuc reader = pgp_reader_get_arg(readinfo);
1784*ebfedea0SLionel Sambuc if (!stream->coalescing && stream->virtualc && stream->virtualoff < stream->virtualc) {
1785*ebfedea0SLionel Sambuc n = read_partial_data(stream, dest, length);
1786*ebfedea0SLionel Sambuc } else {
1787*ebfedea0SLionel Sambuc n = (int)read(reader->fd, dest, length);
1788*ebfedea0SLionel Sambuc }
1789*ebfedea0SLionel Sambuc if (n == 0) {
1790*ebfedea0SLionel Sambuc return 0;
1791*ebfedea0SLionel Sambuc }
1792*ebfedea0SLionel Sambuc if (n < 0) {
1793*ebfedea0SLionel Sambuc PGP_SYSTEM_ERROR_1(errors, PGP_E_R_READ_FAILED, "read",
1794*ebfedea0SLionel Sambuc "file descriptor %d", reader->fd);
1795*ebfedea0SLionel Sambuc return -1;
1796*ebfedea0SLionel Sambuc }
1797*ebfedea0SLionel Sambuc return n;
1798*ebfedea0SLionel Sambuc }
1799*ebfedea0SLionel Sambuc
1800*ebfedea0SLionel Sambuc static void
reader_fd_destroyer(pgp_reader_t * readinfo)1801*ebfedea0SLionel Sambuc reader_fd_destroyer(pgp_reader_t *readinfo)
1802*ebfedea0SLionel Sambuc {
1803*ebfedea0SLionel Sambuc free(pgp_reader_get_arg(readinfo));
1804*ebfedea0SLionel Sambuc }
1805*ebfedea0SLionel Sambuc
1806*ebfedea0SLionel Sambuc /**
1807*ebfedea0SLionel Sambuc \ingroup Core_Readers_First
1808*ebfedea0SLionel Sambuc \brief Starts stack with file reader
1809*ebfedea0SLionel Sambuc */
1810*ebfedea0SLionel Sambuc
1811*ebfedea0SLionel Sambuc void
pgp_reader_set_fd(pgp_stream_t * stream,int fd)1812*ebfedea0SLionel Sambuc pgp_reader_set_fd(pgp_stream_t *stream, int fd)
1813*ebfedea0SLionel Sambuc {
1814*ebfedea0SLionel Sambuc mmap_reader_t *reader;
1815*ebfedea0SLionel Sambuc
1816*ebfedea0SLionel Sambuc if ((reader = calloc(1, sizeof(*reader))) == NULL) {
1817*ebfedea0SLionel Sambuc (void) fprintf(stderr, "pgp_reader_set_fd: bad alloc\n");
1818*ebfedea0SLionel Sambuc } else {
1819*ebfedea0SLionel Sambuc reader->fd = fd;
1820*ebfedea0SLionel Sambuc pgp_reader_set(stream, fd_reader, reader_fd_destroyer, reader);
1821*ebfedea0SLionel Sambuc }
1822*ebfedea0SLionel Sambuc }
1823*ebfedea0SLionel Sambuc
1824*ebfedea0SLionel Sambuc /**************************************************************************/
1825*ebfedea0SLionel Sambuc
1826*ebfedea0SLionel Sambuc typedef struct {
1827*ebfedea0SLionel Sambuc const uint8_t *buffer;
1828*ebfedea0SLionel Sambuc size_t length;
1829*ebfedea0SLionel Sambuc size_t offset;
1830*ebfedea0SLionel Sambuc } reader_mem_t;
1831*ebfedea0SLionel Sambuc
1832*ebfedea0SLionel Sambuc static int
mem_reader(pgp_stream_t * stream,void * dest,size_t length,pgp_error_t ** errors,pgp_reader_t * readinfo,pgp_cbdata_t * cbinfo)1833*ebfedea0SLionel Sambuc mem_reader(pgp_stream_t *stream, void *dest, size_t length, pgp_error_t **errors,
1834*ebfedea0SLionel Sambuc pgp_reader_t *readinfo, pgp_cbdata_t *cbinfo)
1835*ebfedea0SLionel Sambuc {
1836*ebfedea0SLionel Sambuc reader_mem_t *reader = pgp_reader_get_arg(readinfo);
1837*ebfedea0SLionel Sambuc unsigned n;
1838*ebfedea0SLionel Sambuc
1839*ebfedea0SLionel Sambuc __PGP_USED(cbinfo);
1840*ebfedea0SLionel Sambuc __PGP_USED(errors);
1841*ebfedea0SLionel Sambuc if (!stream->coalescing && stream->virtualc && stream->virtualoff < stream->virtualc) {
1842*ebfedea0SLionel Sambuc n = read_partial_data(stream, dest, length);
1843*ebfedea0SLionel Sambuc } else {
1844*ebfedea0SLionel Sambuc if (reader->offset + length > reader->length) {
1845*ebfedea0SLionel Sambuc n = (unsigned)(reader->length - reader->offset);
1846*ebfedea0SLionel Sambuc } else {
1847*ebfedea0SLionel Sambuc n = (unsigned)length;
1848*ebfedea0SLionel Sambuc }
1849*ebfedea0SLionel Sambuc if (n == (unsigned)0) {
1850*ebfedea0SLionel Sambuc return 0;
1851*ebfedea0SLionel Sambuc }
1852*ebfedea0SLionel Sambuc memcpy(dest, reader->buffer + reader->offset, n);
1853*ebfedea0SLionel Sambuc reader->offset += n;
1854*ebfedea0SLionel Sambuc }
1855*ebfedea0SLionel Sambuc return n;
1856*ebfedea0SLionel Sambuc }
1857*ebfedea0SLionel Sambuc
1858*ebfedea0SLionel Sambuc static void
mem_destroyer(pgp_reader_t * readinfo)1859*ebfedea0SLionel Sambuc mem_destroyer(pgp_reader_t *readinfo)
1860*ebfedea0SLionel Sambuc {
1861*ebfedea0SLionel Sambuc free(pgp_reader_get_arg(readinfo));
1862*ebfedea0SLionel Sambuc }
1863*ebfedea0SLionel Sambuc
1864*ebfedea0SLionel Sambuc /**
1865*ebfedea0SLionel Sambuc \ingroup Core_Readers_First
1866*ebfedea0SLionel Sambuc \brief Starts stack with memory reader
1867*ebfedea0SLionel Sambuc */
1868*ebfedea0SLionel Sambuc
1869*ebfedea0SLionel Sambuc void
pgp_reader_set_memory(pgp_stream_t * stream,const void * buffer,size_t length)1870*ebfedea0SLionel Sambuc pgp_reader_set_memory(pgp_stream_t *stream, const void *buffer,
1871*ebfedea0SLionel Sambuc size_t length)
1872*ebfedea0SLionel Sambuc {
1873*ebfedea0SLionel Sambuc reader_mem_t *mem;
1874*ebfedea0SLionel Sambuc
1875*ebfedea0SLionel Sambuc if ((mem = calloc(1, sizeof(*mem))) == NULL) {
1876*ebfedea0SLionel Sambuc (void) fprintf(stderr, "pgp_reader_set_memory: bad alloc\n");
1877*ebfedea0SLionel Sambuc } else {
1878*ebfedea0SLionel Sambuc mem->buffer = buffer;
1879*ebfedea0SLionel Sambuc mem->length = length;
1880*ebfedea0SLionel Sambuc mem->offset = 0;
1881*ebfedea0SLionel Sambuc pgp_reader_set(stream, mem_reader, mem_destroyer, mem);
1882*ebfedea0SLionel Sambuc }
1883*ebfedea0SLionel Sambuc }
1884*ebfedea0SLionel Sambuc
1885*ebfedea0SLionel Sambuc /**************************************************************************/
1886*ebfedea0SLionel Sambuc
1887*ebfedea0SLionel Sambuc /**
1888*ebfedea0SLionel Sambuc \ingroup Core_Writers
1889*ebfedea0SLionel Sambuc \brief Create and initialise output and mem; Set for writing to mem
1890*ebfedea0SLionel Sambuc \param output Address where new output pointer will be set
1891*ebfedea0SLionel Sambuc \param mem Address when new mem pointer will be set
1892*ebfedea0SLionel Sambuc \param bufsz Initial buffer size (will automatically be increased when necessary)
1893*ebfedea0SLionel Sambuc \note It is the caller's responsiblity to free output and mem.
1894*ebfedea0SLionel Sambuc \sa pgp_teardown_memory_write()
1895*ebfedea0SLionel Sambuc */
1896*ebfedea0SLionel Sambuc void
pgp_setup_memory_write(pgp_output_t ** output,pgp_memory_t ** mem,size_t bufsz)1897*ebfedea0SLionel Sambuc pgp_setup_memory_write(pgp_output_t **output, pgp_memory_t **mem, size_t bufsz)
1898*ebfedea0SLionel Sambuc {
1899*ebfedea0SLionel Sambuc /*
1900*ebfedea0SLionel Sambuc * initialise needed structures for writing to memory
1901*ebfedea0SLionel Sambuc */
1902*ebfedea0SLionel Sambuc
1903*ebfedea0SLionel Sambuc *output = pgp_output_new();
1904*ebfedea0SLionel Sambuc *mem = pgp_memory_new();
1905*ebfedea0SLionel Sambuc
1906*ebfedea0SLionel Sambuc pgp_memory_init(*mem, bufsz);
1907*ebfedea0SLionel Sambuc
1908*ebfedea0SLionel Sambuc pgp_writer_set_memory(*output, *mem);
1909*ebfedea0SLionel Sambuc }
1910*ebfedea0SLionel Sambuc
1911*ebfedea0SLionel Sambuc /**
1912*ebfedea0SLionel Sambuc \ingroup Core_Writers
1913*ebfedea0SLionel Sambuc \brief Closes writer and frees output and mem
1914*ebfedea0SLionel Sambuc \param output
1915*ebfedea0SLionel Sambuc \param mem
1916*ebfedea0SLionel Sambuc \sa pgp_setup_memory_write()
1917*ebfedea0SLionel Sambuc */
1918*ebfedea0SLionel Sambuc void
pgp_teardown_memory_write(pgp_output_t * output,pgp_memory_t * mem)1919*ebfedea0SLionel Sambuc pgp_teardown_memory_write(pgp_output_t *output, pgp_memory_t *mem)
1920*ebfedea0SLionel Sambuc {
1921*ebfedea0SLionel Sambuc pgp_writer_close(output);/* new */
1922*ebfedea0SLionel Sambuc pgp_output_delete(output);
1923*ebfedea0SLionel Sambuc pgp_memory_free(mem);
1924*ebfedea0SLionel Sambuc }
1925*ebfedea0SLionel Sambuc
1926*ebfedea0SLionel Sambuc /**
1927*ebfedea0SLionel Sambuc \ingroup Core_Readers
1928*ebfedea0SLionel Sambuc \brief Create parse_info and sets to read from memory
1929*ebfedea0SLionel Sambuc \param stream Address where new parse_info will be set
1930*ebfedea0SLionel Sambuc \param mem Memory to read from
1931*ebfedea0SLionel Sambuc \param arg Reader-specific arg
1932*ebfedea0SLionel Sambuc \param callback Callback to use with reader
1933*ebfedea0SLionel Sambuc \param accumulate Set if we need to accumulate as we read. (Usually 0 unless doing signature verification)
1934*ebfedea0SLionel Sambuc \note It is the caller's responsiblity to free parse_info
1935*ebfedea0SLionel Sambuc \sa pgp_teardown_memory_read()
1936*ebfedea0SLionel Sambuc */
1937*ebfedea0SLionel Sambuc void
pgp_setup_memory_read(pgp_io_t * io,pgp_stream_t ** stream,pgp_memory_t * mem,void * vp,pgp_cb_ret_t callback (const pgp_packet_t *,pgp_cbdata_t *),unsigned accumulate)1938*ebfedea0SLionel Sambuc pgp_setup_memory_read(pgp_io_t *io,
1939*ebfedea0SLionel Sambuc pgp_stream_t **stream,
1940*ebfedea0SLionel Sambuc pgp_memory_t *mem,
1941*ebfedea0SLionel Sambuc void *vp,
1942*ebfedea0SLionel Sambuc pgp_cb_ret_t callback(const pgp_packet_t *,
1943*ebfedea0SLionel Sambuc pgp_cbdata_t *),
1944*ebfedea0SLionel Sambuc unsigned accumulate)
1945*ebfedea0SLionel Sambuc {
1946*ebfedea0SLionel Sambuc *stream = pgp_new(sizeof(**stream));
1947*ebfedea0SLionel Sambuc (*stream)->io = (*stream)->cbinfo.io = io;
1948*ebfedea0SLionel Sambuc pgp_set_callback(*stream, callback, vp);
1949*ebfedea0SLionel Sambuc pgp_reader_set_memory(*stream,
1950*ebfedea0SLionel Sambuc pgp_mem_data(mem),
1951*ebfedea0SLionel Sambuc pgp_mem_len(mem));
1952*ebfedea0SLionel Sambuc if (accumulate) {
1953*ebfedea0SLionel Sambuc (*stream)->readinfo.accumulate = 1;
1954*ebfedea0SLionel Sambuc }
1955*ebfedea0SLionel Sambuc }
1956*ebfedea0SLionel Sambuc
1957*ebfedea0SLionel Sambuc /**
1958*ebfedea0SLionel Sambuc \ingroup Core_Readers
1959*ebfedea0SLionel Sambuc \brief Frees stream and mem
1960*ebfedea0SLionel Sambuc \param stream
1961*ebfedea0SLionel Sambuc \param mem
1962*ebfedea0SLionel Sambuc \sa pgp_setup_memory_read()
1963*ebfedea0SLionel Sambuc */
1964*ebfedea0SLionel Sambuc void
pgp_teardown_memory_read(pgp_stream_t * stream,pgp_memory_t * mem)1965*ebfedea0SLionel Sambuc pgp_teardown_memory_read(pgp_stream_t *stream, pgp_memory_t *mem)
1966*ebfedea0SLionel Sambuc {
1967*ebfedea0SLionel Sambuc pgp_stream_delete(stream);
1968*ebfedea0SLionel Sambuc pgp_memory_free(mem);
1969*ebfedea0SLionel Sambuc }
1970*ebfedea0SLionel Sambuc
1971*ebfedea0SLionel Sambuc /**
1972*ebfedea0SLionel Sambuc \ingroup Core_Writers
1973*ebfedea0SLionel Sambuc \brief Create and initialise output and mem; Set for writing to file
1974*ebfedea0SLionel Sambuc \param output Address where new output pointer will be set
1975*ebfedea0SLionel Sambuc \param filename File to write to
1976*ebfedea0SLionel Sambuc \param allow_overwrite Allows file to be overwritten, if set.
1977*ebfedea0SLionel Sambuc \return Newly-opened file descriptor
1978*ebfedea0SLionel Sambuc \note It is the caller's responsiblity to free output and to close fd.
1979*ebfedea0SLionel Sambuc \sa pgp_teardown_file_write()
1980*ebfedea0SLionel Sambuc */
1981*ebfedea0SLionel Sambuc int
pgp_setup_file_write(pgp_output_t ** output,const char * filename,unsigned allow_overwrite)1982*ebfedea0SLionel Sambuc pgp_setup_file_write(pgp_output_t **output, const char *filename,
1983*ebfedea0SLionel Sambuc unsigned allow_overwrite)
1984*ebfedea0SLionel Sambuc {
1985*ebfedea0SLionel Sambuc int fd = 0;
1986*ebfedea0SLionel Sambuc int flags = 0;
1987*ebfedea0SLionel Sambuc
1988*ebfedea0SLionel Sambuc /*
1989*ebfedea0SLionel Sambuc * initialise needed structures for writing to file
1990*ebfedea0SLionel Sambuc */
1991*ebfedea0SLionel Sambuc if (filename == NULL) {
1992*ebfedea0SLionel Sambuc /* write to stdout */
1993*ebfedea0SLionel Sambuc fd = STDOUT_FILENO;
1994*ebfedea0SLionel Sambuc } else {
1995*ebfedea0SLionel Sambuc flags = O_WRONLY | O_CREAT;
1996*ebfedea0SLionel Sambuc if (allow_overwrite)
1997*ebfedea0SLionel Sambuc flags |= O_TRUNC;
1998*ebfedea0SLionel Sambuc else
1999*ebfedea0SLionel Sambuc flags |= O_EXCL;
2000*ebfedea0SLionel Sambuc #ifdef O_BINARY
2001*ebfedea0SLionel Sambuc flags |= O_BINARY;
2002*ebfedea0SLionel Sambuc #endif
2003*ebfedea0SLionel Sambuc fd = open(filename, flags, 0600);
2004*ebfedea0SLionel Sambuc if (fd < 0) {
2005*ebfedea0SLionel Sambuc perror(filename);
2006*ebfedea0SLionel Sambuc return fd;
2007*ebfedea0SLionel Sambuc }
2008*ebfedea0SLionel Sambuc }
2009*ebfedea0SLionel Sambuc *output = pgp_output_new();
2010*ebfedea0SLionel Sambuc pgp_writer_set_fd(*output, fd);
2011*ebfedea0SLionel Sambuc return fd;
2012*ebfedea0SLionel Sambuc }
2013*ebfedea0SLionel Sambuc
2014*ebfedea0SLionel Sambuc /**
2015*ebfedea0SLionel Sambuc \ingroup Core_Writers
2016*ebfedea0SLionel Sambuc \brief Closes writer, frees info, closes fd
2017*ebfedea0SLionel Sambuc \param output
2018*ebfedea0SLionel Sambuc \param fd
2019*ebfedea0SLionel Sambuc */
2020*ebfedea0SLionel Sambuc void
pgp_teardown_file_write(pgp_output_t * output,int fd)2021*ebfedea0SLionel Sambuc pgp_teardown_file_write(pgp_output_t *output, int fd)
2022*ebfedea0SLionel Sambuc {
2023*ebfedea0SLionel Sambuc pgp_writer_close(output);
2024*ebfedea0SLionel Sambuc close(fd);
2025*ebfedea0SLionel Sambuc pgp_output_delete(output);
2026*ebfedea0SLionel Sambuc }
2027*ebfedea0SLionel Sambuc
2028*ebfedea0SLionel Sambuc /**
2029*ebfedea0SLionel Sambuc \ingroup Core_Writers
2030*ebfedea0SLionel Sambuc \brief As pgp_setup_file_write, but appends to file
2031*ebfedea0SLionel Sambuc */
2032*ebfedea0SLionel Sambuc int
pgp_setup_file_append(pgp_output_t ** output,const char * filename)2033*ebfedea0SLionel Sambuc pgp_setup_file_append(pgp_output_t **output, const char *filename)
2034*ebfedea0SLionel Sambuc {
2035*ebfedea0SLionel Sambuc int fd;
2036*ebfedea0SLionel Sambuc
2037*ebfedea0SLionel Sambuc /*
2038*ebfedea0SLionel Sambuc * initialise needed structures for writing to file
2039*ebfedea0SLionel Sambuc */
2040*ebfedea0SLionel Sambuc #ifdef O_BINARY
2041*ebfedea0SLionel Sambuc fd = open(filename, O_WRONLY | O_APPEND | O_BINARY, 0600);
2042*ebfedea0SLionel Sambuc #else
2043*ebfedea0SLionel Sambuc fd = open(filename, O_WRONLY | O_APPEND, 0600);
2044*ebfedea0SLionel Sambuc #endif
2045*ebfedea0SLionel Sambuc if (fd >= 0) {
2046*ebfedea0SLionel Sambuc *output = pgp_output_new();
2047*ebfedea0SLionel Sambuc pgp_writer_set_fd(*output, fd);
2048*ebfedea0SLionel Sambuc }
2049*ebfedea0SLionel Sambuc return fd;
2050*ebfedea0SLionel Sambuc }
2051*ebfedea0SLionel Sambuc
2052*ebfedea0SLionel Sambuc /**
2053*ebfedea0SLionel Sambuc \ingroup Core_Writers
2054*ebfedea0SLionel Sambuc \brief As pgp_teardown_file_write()
2055*ebfedea0SLionel Sambuc */
2056*ebfedea0SLionel Sambuc void
pgp_teardown_file_append(pgp_output_t * output,int fd)2057*ebfedea0SLionel Sambuc pgp_teardown_file_append(pgp_output_t *output, int fd)
2058*ebfedea0SLionel Sambuc {
2059*ebfedea0SLionel Sambuc pgp_teardown_file_write(output, fd);
2060*ebfedea0SLionel Sambuc }
2061*ebfedea0SLionel Sambuc
2062*ebfedea0SLionel Sambuc /**
2063*ebfedea0SLionel Sambuc \ingroup Core_Readers
2064*ebfedea0SLionel Sambuc \brief Creates parse_info, opens file, and sets to read from file
2065*ebfedea0SLionel Sambuc \param stream Address where new parse_info will be set
2066*ebfedea0SLionel Sambuc \param filename Name of file to read
2067*ebfedea0SLionel Sambuc \param vp Reader-specific arg
2068*ebfedea0SLionel Sambuc \param callback Callback to use when reading
2069*ebfedea0SLionel Sambuc \param accumulate Set if we need to accumulate as we read. (Usually 0 unless doing signature verification)
2070*ebfedea0SLionel Sambuc \note It is the caller's responsiblity to free parse_info and to close fd
2071*ebfedea0SLionel Sambuc \sa pgp_teardown_file_read()
2072*ebfedea0SLionel Sambuc */
2073*ebfedea0SLionel Sambuc int
pgp_setup_file_read(pgp_io_t * io,pgp_stream_t ** stream,const char * filename,void * vp,pgp_cb_ret_t callback (const pgp_packet_t *,pgp_cbdata_t *),unsigned accumulate)2074*ebfedea0SLionel Sambuc pgp_setup_file_read(pgp_io_t *io,
2075*ebfedea0SLionel Sambuc pgp_stream_t **stream,
2076*ebfedea0SLionel Sambuc const char *filename,
2077*ebfedea0SLionel Sambuc void *vp,
2078*ebfedea0SLionel Sambuc pgp_cb_ret_t callback(const pgp_packet_t *,
2079*ebfedea0SLionel Sambuc pgp_cbdata_t *),
2080*ebfedea0SLionel Sambuc unsigned accumulate)
2081*ebfedea0SLionel Sambuc {
2082*ebfedea0SLionel Sambuc int fd;
2083*ebfedea0SLionel Sambuc
2084*ebfedea0SLionel Sambuc #ifdef O_BINARY
2085*ebfedea0SLionel Sambuc fd = open(filename, O_RDONLY | O_BINARY);
2086*ebfedea0SLionel Sambuc #else
2087*ebfedea0SLionel Sambuc fd = open(filename, O_RDONLY);
2088*ebfedea0SLionel Sambuc #endif
2089*ebfedea0SLionel Sambuc if (fd < 0) {
2090*ebfedea0SLionel Sambuc (void) fprintf(io->errs, "can't open \"%s\"\n", filename);
2091*ebfedea0SLionel Sambuc return fd;
2092*ebfedea0SLionel Sambuc }
2093*ebfedea0SLionel Sambuc *stream = pgp_new(sizeof(**stream));
2094*ebfedea0SLionel Sambuc (*stream)->io = (*stream)->cbinfo.io = io;
2095*ebfedea0SLionel Sambuc pgp_set_callback(*stream, callback, vp);
2096*ebfedea0SLionel Sambuc #ifdef USE_MMAP_FOR_FILES
2097*ebfedea0SLionel Sambuc pgp_reader_set_mmap(*stream, fd);
2098*ebfedea0SLionel Sambuc #else
2099*ebfedea0SLionel Sambuc pgp_reader_set_fd(*stream, fd);
2100*ebfedea0SLionel Sambuc #endif
2101*ebfedea0SLionel Sambuc if (accumulate) {
2102*ebfedea0SLionel Sambuc (*stream)->readinfo.accumulate = 1;
2103*ebfedea0SLionel Sambuc }
2104*ebfedea0SLionel Sambuc return fd;
2105*ebfedea0SLionel Sambuc }
2106*ebfedea0SLionel Sambuc
2107*ebfedea0SLionel Sambuc /**
2108*ebfedea0SLionel Sambuc \ingroup Core_Readers
2109*ebfedea0SLionel Sambuc \brief Frees stream and closes fd
2110*ebfedea0SLionel Sambuc \param stream
2111*ebfedea0SLionel Sambuc \param fd
2112*ebfedea0SLionel Sambuc \sa pgp_setup_file_read()
2113*ebfedea0SLionel Sambuc */
2114*ebfedea0SLionel Sambuc void
pgp_teardown_file_read(pgp_stream_t * stream,int fd)2115*ebfedea0SLionel Sambuc pgp_teardown_file_read(pgp_stream_t *stream, int fd)
2116*ebfedea0SLionel Sambuc {
2117*ebfedea0SLionel Sambuc close(fd);
2118*ebfedea0SLionel Sambuc pgp_stream_delete(stream);
2119*ebfedea0SLionel Sambuc }
2120*ebfedea0SLionel Sambuc
2121*ebfedea0SLionel Sambuc pgp_cb_ret_t
pgp_litdata_cb(const pgp_packet_t * pkt,pgp_cbdata_t * cbinfo)2122*ebfedea0SLionel Sambuc pgp_litdata_cb(const pgp_packet_t *pkt, pgp_cbdata_t *cbinfo)
2123*ebfedea0SLionel Sambuc {
2124*ebfedea0SLionel Sambuc const pgp_contents_t *content = &pkt->u;
2125*ebfedea0SLionel Sambuc
2126*ebfedea0SLionel Sambuc if (pgp_get_debug_level(__FILE__)) {
2127*ebfedea0SLionel Sambuc printf("pgp_litdata_cb: ");
2128*ebfedea0SLionel Sambuc pgp_print_packet(&cbinfo->printstate, pkt);
2129*ebfedea0SLionel Sambuc }
2130*ebfedea0SLionel Sambuc /* Read data from packet into static buffer */
2131*ebfedea0SLionel Sambuc switch (pkt->tag) {
2132*ebfedea0SLionel Sambuc case PGP_PTAG_CT_LITDATA_BODY:
2133*ebfedea0SLionel Sambuc /* if writer enabled, use it */
2134*ebfedea0SLionel Sambuc if (cbinfo->output) {
2135*ebfedea0SLionel Sambuc if (pgp_get_debug_level(__FILE__)) {
2136*ebfedea0SLionel Sambuc printf("pgp_litdata_cb: length is %u\n",
2137*ebfedea0SLionel Sambuc content->litdata_body.length);
2138*ebfedea0SLionel Sambuc }
2139*ebfedea0SLionel Sambuc pgp_write(cbinfo->output,
2140*ebfedea0SLionel Sambuc content->litdata_body.data,
2141*ebfedea0SLionel Sambuc content->litdata_body.length);
2142*ebfedea0SLionel Sambuc }
2143*ebfedea0SLionel Sambuc break;
2144*ebfedea0SLionel Sambuc
2145*ebfedea0SLionel Sambuc case PGP_PTAG_CT_LITDATA_HEADER:
2146*ebfedea0SLionel Sambuc /* ignore */
2147*ebfedea0SLionel Sambuc break;
2148*ebfedea0SLionel Sambuc
2149*ebfedea0SLionel Sambuc default:
2150*ebfedea0SLionel Sambuc break;
2151*ebfedea0SLionel Sambuc }
2152*ebfedea0SLionel Sambuc
2153*ebfedea0SLionel Sambuc return PGP_RELEASE_MEMORY;
2154*ebfedea0SLionel Sambuc }
2155*ebfedea0SLionel Sambuc
2156*ebfedea0SLionel Sambuc pgp_cb_ret_t
pgp_pk_sesskey_cb(const pgp_packet_t * pkt,pgp_cbdata_t * cbinfo)2157*ebfedea0SLionel Sambuc pgp_pk_sesskey_cb(const pgp_packet_t *pkt, pgp_cbdata_t *cbinfo)
2158*ebfedea0SLionel Sambuc {
2159*ebfedea0SLionel Sambuc const pgp_contents_t *content = &pkt->u;
2160*ebfedea0SLionel Sambuc unsigned from;
2161*ebfedea0SLionel Sambuc pgp_io_t *io;
2162*ebfedea0SLionel Sambuc
2163*ebfedea0SLionel Sambuc io = cbinfo->io;
2164*ebfedea0SLionel Sambuc if (pgp_get_debug_level(__FILE__)) {
2165*ebfedea0SLionel Sambuc pgp_print_packet(&cbinfo->printstate, pkt);
2166*ebfedea0SLionel Sambuc }
2167*ebfedea0SLionel Sambuc /* Read data from packet into static buffer */
2168*ebfedea0SLionel Sambuc switch (pkt->tag) {
2169*ebfedea0SLionel Sambuc case PGP_PTAG_CT_PK_SESSION_KEY:
2170*ebfedea0SLionel Sambuc if (pgp_get_debug_level(__FILE__)) {
2171*ebfedea0SLionel Sambuc printf("PGP_PTAG_CT_PK_SESSION_KEY\n");
2172*ebfedea0SLionel Sambuc }
2173*ebfedea0SLionel Sambuc if (!cbinfo->cryptinfo.secring) {
2174*ebfedea0SLionel Sambuc (void) fprintf(io->errs,
2175*ebfedea0SLionel Sambuc "pgp_pk_sesskey_cb: bad keyring\n");
2176*ebfedea0SLionel Sambuc return (pgp_cb_ret_t)0;
2177*ebfedea0SLionel Sambuc }
2178*ebfedea0SLionel Sambuc from = 0;
2179*ebfedea0SLionel Sambuc cbinfo->cryptinfo.keydata =
2180*ebfedea0SLionel Sambuc pgp_getkeybyid(io, cbinfo->cryptinfo.secring,
2181*ebfedea0SLionel Sambuc content->pk_sesskey.key_id, &from, NULL);
2182*ebfedea0SLionel Sambuc if (!cbinfo->cryptinfo.keydata) {
2183*ebfedea0SLionel Sambuc break;
2184*ebfedea0SLionel Sambuc }
2185*ebfedea0SLionel Sambuc break;
2186*ebfedea0SLionel Sambuc
2187*ebfedea0SLionel Sambuc default:
2188*ebfedea0SLionel Sambuc break;
2189*ebfedea0SLionel Sambuc }
2190*ebfedea0SLionel Sambuc
2191*ebfedea0SLionel Sambuc return PGP_RELEASE_MEMORY;
2192*ebfedea0SLionel Sambuc }
2193*ebfedea0SLionel Sambuc
2194*ebfedea0SLionel Sambuc /**
2195*ebfedea0SLionel Sambuc \ingroup Core_Callbacks
2196*ebfedea0SLionel Sambuc
2197*ebfedea0SLionel Sambuc \brief Callback to get secret key, decrypting if necessary.
2198*ebfedea0SLionel Sambuc
2199*ebfedea0SLionel Sambuc @verbatim
2200*ebfedea0SLionel Sambuc This callback does the following:
2201*ebfedea0SLionel Sambuc * finds the session key in the keyring
2202*ebfedea0SLionel Sambuc * gets a passphrase if required
2203*ebfedea0SLionel Sambuc * decrypts the secret key, if necessary
2204*ebfedea0SLionel Sambuc * sets the seckey in the content struct
2205*ebfedea0SLionel Sambuc @endverbatim
2206*ebfedea0SLionel Sambuc */
2207*ebfedea0SLionel Sambuc
2208*ebfedea0SLionel Sambuc pgp_cb_ret_t
pgp_get_seckey_cb(const pgp_packet_t * pkt,pgp_cbdata_t * cbinfo)2209*ebfedea0SLionel Sambuc pgp_get_seckey_cb(const pgp_packet_t *pkt, pgp_cbdata_t *cbinfo)
2210*ebfedea0SLionel Sambuc {
2211*ebfedea0SLionel Sambuc const pgp_contents_t *content = &pkt->u;
2212*ebfedea0SLionel Sambuc const pgp_seckey_t *secret;
2213*ebfedea0SLionel Sambuc const pgp_key_t *pubkey;
2214*ebfedea0SLionel Sambuc const pgp_key_t *keypair;
2215*ebfedea0SLionel Sambuc unsigned from;
2216*ebfedea0SLionel Sambuc pgp_io_t *io;
2217*ebfedea0SLionel Sambuc int i;
2218*ebfedea0SLionel Sambuc
2219*ebfedea0SLionel Sambuc io = cbinfo->io;
2220*ebfedea0SLionel Sambuc if (pgp_get_debug_level(__FILE__)) {
2221*ebfedea0SLionel Sambuc pgp_print_packet(&cbinfo->printstate, pkt);
2222*ebfedea0SLionel Sambuc }
2223*ebfedea0SLionel Sambuc switch (pkt->tag) {
2224*ebfedea0SLionel Sambuc case PGP_GET_SECKEY:
2225*ebfedea0SLionel Sambuc /* print key from pubring */
2226*ebfedea0SLionel Sambuc from = 0;
2227*ebfedea0SLionel Sambuc pubkey = pgp_getkeybyid(io, cbinfo->cryptinfo.pubring,
2228*ebfedea0SLionel Sambuc content->get_seckey.pk_sesskey->key_id,
2229*ebfedea0SLionel Sambuc &from, NULL);
2230*ebfedea0SLionel Sambuc /* validate key from secring */
2231*ebfedea0SLionel Sambuc from = 0;
2232*ebfedea0SLionel Sambuc cbinfo->cryptinfo.keydata =
2233*ebfedea0SLionel Sambuc pgp_getkeybyid(io, cbinfo->cryptinfo.secring,
2234*ebfedea0SLionel Sambuc content->get_seckey.pk_sesskey->key_id,
2235*ebfedea0SLionel Sambuc &from, NULL);
2236*ebfedea0SLionel Sambuc if (!cbinfo->cryptinfo.keydata ||
2237*ebfedea0SLionel Sambuc !pgp_is_key_secret(cbinfo->cryptinfo.keydata)) {
2238*ebfedea0SLionel Sambuc return (pgp_cb_ret_t)0;
2239*ebfedea0SLionel Sambuc }
2240*ebfedea0SLionel Sambuc keypair = cbinfo->cryptinfo.keydata;
2241*ebfedea0SLionel Sambuc if (pubkey == NULL) {
2242*ebfedea0SLionel Sambuc pubkey = keypair;
2243*ebfedea0SLionel Sambuc }
2244*ebfedea0SLionel Sambuc secret = NULL;
2245*ebfedea0SLionel Sambuc cbinfo->gotpass = 0;
2246*ebfedea0SLionel Sambuc for (i = 0 ; cbinfo->numtries == -1 || i < cbinfo->numtries ; i++) {
2247*ebfedea0SLionel Sambuc /* print out the user id */
2248*ebfedea0SLionel Sambuc pgp_print_keydata(io, cbinfo->cryptinfo.pubring, pubkey,
2249*ebfedea0SLionel Sambuc "signature ", &pubkey->key.pubkey, 0);
2250*ebfedea0SLionel Sambuc /* now decrypt key */
2251*ebfedea0SLionel Sambuc secret = pgp_decrypt_seckey(keypair, cbinfo->passfp);
2252*ebfedea0SLionel Sambuc if (secret != NULL) {
2253*ebfedea0SLionel Sambuc break;
2254*ebfedea0SLionel Sambuc }
2255*ebfedea0SLionel Sambuc (void) fprintf(io->errs, "Bad passphrase\n");
2256*ebfedea0SLionel Sambuc }
2257*ebfedea0SLionel Sambuc if (secret == NULL) {
2258*ebfedea0SLionel Sambuc (void) fprintf(io->errs, "Exhausted passphrase attempts\n");
2259*ebfedea0SLionel Sambuc return (pgp_cb_ret_t)PGP_RELEASE_MEMORY;
2260*ebfedea0SLionel Sambuc }
2261*ebfedea0SLionel Sambuc cbinfo->gotpass = 1;
2262*ebfedea0SLionel Sambuc *content->get_seckey.seckey = secret;
2263*ebfedea0SLionel Sambuc break;
2264*ebfedea0SLionel Sambuc
2265*ebfedea0SLionel Sambuc default:
2266*ebfedea0SLionel Sambuc break;
2267*ebfedea0SLionel Sambuc }
2268*ebfedea0SLionel Sambuc
2269*ebfedea0SLionel Sambuc return PGP_RELEASE_MEMORY;
2270*ebfedea0SLionel Sambuc }
2271*ebfedea0SLionel Sambuc
2272*ebfedea0SLionel Sambuc /**
2273*ebfedea0SLionel Sambuc \ingroup HighLevel_Callbacks
2274*ebfedea0SLionel Sambuc \brief Callback to use when you need to prompt user for passphrase
2275*ebfedea0SLionel Sambuc \param contents
2276*ebfedea0SLionel Sambuc \param cbinfo
2277*ebfedea0SLionel Sambuc */
2278*ebfedea0SLionel Sambuc pgp_cb_ret_t
get_passphrase_cb(const pgp_packet_t * pkt,pgp_cbdata_t * cbinfo)2279*ebfedea0SLionel Sambuc get_passphrase_cb(const pgp_packet_t *pkt, pgp_cbdata_t *cbinfo)
2280*ebfedea0SLionel Sambuc {
2281*ebfedea0SLionel Sambuc const pgp_contents_t *content = &pkt->u;
2282*ebfedea0SLionel Sambuc pgp_io_t *io;
2283*ebfedea0SLionel Sambuc
2284*ebfedea0SLionel Sambuc io = cbinfo->io;
2285*ebfedea0SLionel Sambuc if (pgp_get_debug_level(__FILE__)) {
2286*ebfedea0SLionel Sambuc pgp_print_packet(&cbinfo->printstate, pkt);
2287*ebfedea0SLionel Sambuc }
2288*ebfedea0SLionel Sambuc if (cbinfo->cryptinfo.keydata == NULL) {
2289*ebfedea0SLionel Sambuc (void) fprintf(io->errs, "get_passphrase_cb: NULL keydata\n");
2290*ebfedea0SLionel Sambuc } else {
2291*ebfedea0SLionel Sambuc pgp_print_keydata(io, cbinfo->cryptinfo.pubring, cbinfo->cryptinfo.keydata, "signature ",
2292*ebfedea0SLionel Sambuc &cbinfo->cryptinfo.keydata->key.pubkey, 0);
2293*ebfedea0SLionel Sambuc }
2294*ebfedea0SLionel Sambuc switch (pkt->tag) {
2295*ebfedea0SLionel Sambuc case PGP_GET_PASSPHRASE:
2296*ebfedea0SLionel Sambuc *(content->skey_passphrase.passphrase) =
2297*ebfedea0SLionel Sambuc netpgp_strdup(getpass("netpgp passphrase: "));
2298*ebfedea0SLionel Sambuc return PGP_KEEP_MEMORY;
2299*ebfedea0SLionel Sambuc default:
2300*ebfedea0SLionel Sambuc break;
2301*ebfedea0SLionel Sambuc }
2302*ebfedea0SLionel Sambuc return PGP_RELEASE_MEMORY;
2303*ebfedea0SLionel Sambuc }
2304*ebfedea0SLionel Sambuc
2305*ebfedea0SLionel Sambuc unsigned
pgp_reader_set_accumulate(pgp_stream_t * stream,unsigned state)2306*ebfedea0SLionel Sambuc pgp_reader_set_accumulate(pgp_stream_t *stream, unsigned state)
2307*ebfedea0SLionel Sambuc {
2308*ebfedea0SLionel Sambuc return stream->readinfo.accumulate = state;
2309*ebfedea0SLionel Sambuc }
2310*ebfedea0SLionel Sambuc
2311*ebfedea0SLionel Sambuc /**************************************************************************/
2312*ebfedea0SLionel Sambuc
2313*ebfedea0SLionel Sambuc static int
hash_reader(pgp_stream_t * stream,void * dest,size_t length,pgp_error_t ** errors,pgp_reader_t * readinfo,pgp_cbdata_t * cbinfo)2314*ebfedea0SLionel Sambuc hash_reader(pgp_stream_t *stream, void *dest,
2315*ebfedea0SLionel Sambuc size_t length,
2316*ebfedea0SLionel Sambuc pgp_error_t **errors,
2317*ebfedea0SLionel Sambuc pgp_reader_t *readinfo,
2318*ebfedea0SLionel Sambuc pgp_cbdata_t *cbinfo)
2319*ebfedea0SLionel Sambuc {
2320*ebfedea0SLionel Sambuc pgp_hash_t *hash = pgp_reader_get_arg(readinfo);
2321*ebfedea0SLionel Sambuc int r;
2322*ebfedea0SLionel Sambuc
2323*ebfedea0SLionel Sambuc r = pgp_stacked_read(stream, dest, length, errors, readinfo, cbinfo);
2324*ebfedea0SLionel Sambuc if (r <= 0) {
2325*ebfedea0SLionel Sambuc return r;
2326*ebfedea0SLionel Sambuc }
2327*ebfedea0SLionel Sambuc hash->add(hash, dest, (unsigned)r);
2328*ebfedea0SLionel Sambuc return r;
2329*ebfedea0SLionel Sambuc }
2330*ebfedea0SLionel Sambuc
2331*ebfedea0SLionel Sambuc /**
2332*ebfedea0SLionel Sambuc \ingroup Internal_Readers_Hash
2333*ebfedea0SLionel Sambuc \brief Push hashed data reader on stack
2334*ebfedea0SLionel Sambuc */
2335*ebfedea0SLionel Sambuc void
pgp_reader_push_hash(pgp_stream_t * stream,pgp_hash_t * hash)2336*ebfedea0SLionel Sambuc pgp_reader_push_hash(pgp_stream_t *stream, pgp_hash_t *hash)
2337*ebfedea0SLionel Sambuc {
2338*ebfedea0SLionel Sambuc if (!hash->init(hash)) {
2339*ebfedea0SLionel Sambuc (void) fprintf(stderr, "pgp_reader_push_hash: can't init hash\n");
2340*ebfedea0SLionel Sambuc /* just continue and die */
2341*ebfedea0SLionel Sambuc /* XXX - agc - no way to return failure */
2342*ebfedea0SLionel Sambuc }
2343*ebfedea0SLionel Sambuc pgp_reader_push(stream, hash_reader, NULL, hash);
2344*ebfedea0SLionel Sambuc }
2345*ebfedea0SLionel Sambuc
2346*ebfedea0SLionel Sambuc /**
2347*ebfedea0SLionel Sambuc \ingroup Internal_Readers_Hash
2348*ebfedea0SLionel Sambuc \brief Pop hashed data reader from stack
2349*ebfedea0SLionel Sambuc */
2350*ebfedea0SLionel Sambuc void
pgp_reader_pop_hash(pgp_stream_t * stream)2351*ebfedea0SLionel Sambuc pgp_reader_pop_hash(pgp_stream_t *stream)
2352*ebfedea0SLionel Sambuc {
2353*ebfedea0SLionel Sambuc pgp_reader_pop(stream);
2354*ebfedea0SLionel Sambuc }
2355*ebfedea0SLionel Sambuc
2356*ebfedea0SLionel Sambuc /* read memory from the previously mmap-ed file */
2357*ebfedea0SLionel Sambuc static int
mmap_reader(pgp_stream_t * stream,void * dest,size_t length,pgp_error_t ** errors,pgp_reader_t * readinfo,pgp_cbdata_t * cbinfo)2358*ebfedea0SLionel Sambuc mmap_reader(pgp_stream_t *stream, void *dest, size_t length, pgp_error_t **errors,
2359*ebfedea0SLionel Sambuc pgp_reader_t *readinfo, pgp_cbdata_t *cbinfo)
2360*ebfedea0SLionel Sambuc {
2361*ebfedea0SLionel Sambuc mmap_reader_t *mem = pgp_reader_get_arg(readinfo);
2362*ebfedea0SLionel Sambuc unsigned n;
2363*ebfedea0SLionel Sambuc char *cmem = mem->mem;
2364*ebfedea0SLionel Sambuc
2365*ebfedea0SLionel Sambuc __PGP_USED(errors);
2366*ebfedea0SLionel Sambuc __PGP_USED(cbinfo);
2367*ebfedea0SLionel Sambuc if (!stream->coalescing && stream->virtualc && stream->virtualoff < stream->virtualc) {
2368*ebfedea0SLionel Sambuc n = read_partial_data(stream, dest, length);
2369*ebfedea0SLionel Sambuc } else {
2370*ebfedea0SLionel Sambuc n = (unsigned)MIN(length, (unsigned)(mem->size - mem->offset));
2371*ebfedea0SLionel Sambuc if (n > 0) {
2372*ebfedea0SLionel Sambuc (void) memcpy(dest, &cmem[(int)mem->offset], (unsigned)n);
2373*ebfedea0SLionel Sambuc mem->offset += n;
2374*ebfedea0SLionel Sambuc }
2375*ebfedea0SLionel Sambuc }
2376*ebfedea0SLionel Sambuc return (int)n;
2377*ebfedea0SLionel Sambuc }
2378*ebfedea0SLionel Sambuc
2379*ebfedea0SLionel Sambuc /* tear down the mmap, close the fd */
2380*ebfedea0SLionel Sambuc static void
mmap_destroyer(pgp_reader_t * readinfo)2381*ebfedea0SLionel Sambuc mmap_destroyer(pgp_reader_t *readinfo)
2382*ebfedea0SLionel Sambuc {
2383*ebfedea0SLionel Sambuc mmap_reader_t *mem = pgp_reader_get_arg(readinfo);
2384*ebfedea0SLionel Sambuc
2385*ebfedea0SLionel Sambuc (void) munmap(mem->mem, (unsigned)mem->size);
2386*ebfedea0SLionel Sambuc (void) close(mem->fd);
2387*ebfedea0SLionel Sambuc free(pgp_reader_get_arg(readinfo));
2388*ebfedea0SLionel Sambuc }
2389*ebfedea0SLionel Sambuc
2390*ebfedea0SLionel Sambuc /* set up the file to use mmap-ed memory if available, file IO otherwise */
2391*ebfedea0SLionel Sambuc void
pgp_reader_set_mmap(pgp_stream_t * stream,int fd)2392*ebfedea0SLionel Sambuc pgp_reader_set_mmap(pgp_stream_t *stream, int fd)
2393*ebfedea0SLionel Sambuc {
2394*ebfedea0SLionel Sambuc mmap_reader_t *mem;
2395*ebfedea0SLionel Sambuc struct stat st;
2396*ebfedea0SLionel Sambuc
2397*ebfedea0SLionel Sambuc if (fstat(fd, &st) != 0) {
2398*ebfedea0SLionel Sambuc (void) fprintf(stderr, "pgp_reader_set_mmap: can't fstat\n");
2399*ebfedea0SLionel Sambuc } else if ((mem = calloc(1, sizeof(*mem))) == NULL) {
2400*ebfedea0SLionel Sambuc (void) fprintf(stderr, "pgp_reader_set_mmap: bad alloc\n");
2401*ebfedea0SLionel Sambuc } else {
2402*ebfedea0SLionel Sambuc mem->size = (uint64_t)st.st_size;
2403*ebfedea0SLionel Sambuc mem->offset = 0;
2404*ebfedea0SLionel Sambuc mem->fd = fd;
2405*ebfedea0SLionel Sambuc mem->mem = mmap(NULL, (size_t)st.st_size, PROT_READ,
2406*ebfedea0SLionel Sambuc MAP_PRIVATE | MAP_FILE, fd, 0);
2407*ebfedea0SLionel Sambuc if (mem->mem == MAP_FAILED) {
2408*ebfedea0SLionel Sambuc pgp_reader_set(stream, fd_reader, reader_fd_destroyer,
2409*ebfedea0SLionel Sambuc mem);
2410*ebfedea0SLionel Sambuc } else {
2411*ebfedea0SLionel Sambuc pgp_reader_set(stream, mmap_reader, mmap_destroyer,
2412*ebfedea0SLionel Sambuc mem);
2413*ebfedea0SLionel Sambuc }
2414*ebfedea0SLionel Sambuc }
2415*ebfedea0SLionel Sambuc }
2416