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