xref: /netbsd-src/crypto/external/bsd/netpgp/dist/src/lib/reader.c (revision 93bf6008f8b7982c1d1a9486e4a4a0e687fe36eb)
1 /*
2  * Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
3  * All rights reserved.
4  * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
5  * their moral rights under the UK Copyright Design and Patents Act 1988 to
6  * be recorded as the authors of this copyright work.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
9  * use this file except in compliance with the License.
10  *
11  * You may obtain a copy of the License at
12  *     http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  *
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  */
21 #include "config.h"
22 
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 
26 #ifdef HAVE_SYS_MMAN_H
27 #include <sys/mman.h>
28 #endif
29 
30 #ifdef HAVE_SYS_PARAM_H
31 #include <sys/param.h>
32 #endif
33 
34 #include <fcntl.h>
35 
36 #ifdef HAVE_UNISTD_H
37 #include <unistd.h>
38 #endif
39 
40 #ifdef HAVE_DIRECT_H
41 #include <direct.h>
42 #endif
43 
44 #ifdef HAVE_ASSERT_H
45 #include <assert.h>
46 #endif
47 
48 #ifdef HAVE_INTTYPES_H
49 #include <inttypes.h>
50 #endif
51 
52 #ifdef HAVE_OPENSSL_IDEA_H
53 #include <openssl/cast.h>
54 #endif
55 
56 #ifdef HAVE_OPENSSL_IDEA_H
57 #include <openssl/idea.h>
58 #endif
59 
60 #ifdef HAVE_OPENSSL_AES_H
61 #include <openssl/aes.h>
62 #endif
63 
64 #ifdef HAVE_OPENSSL_DES_H
65 #include <openssl/des.h>
66 #endif
67 
68 #include <string.h>
69 #include <stdarg.h>
70 #include <stdlib.h>
71 #include <stdio.h>
72 
73 #ifdef HAVE_TERMIOS_H
74 #include <termios.h>
75 #endif
76 
77 #ifdef HAVE_ERRNO_H
78 #include <errno.h>
79 #endif
80 
81 #ifdef HAVE_UNISTD_H
82 #include <unistd.h>
83 #endif
84 
85 #ifdef HAVE_LIMITS_H
86 #include <limits.h>
87 #endif
88 
89 #include "errors.h"
90 #include "crypto.h"
91 #include "create.h"
92 #include "signature.h"
93 #include "packet.h"
94 #include "packet-parse.h"
95 #include "packet-show.h"
96 #include "packet.h"
97 #include "keyring.h"
98 
99 #include "readerwriter.h"
100 #include "netpgpdefs.h"
101 #include "version.h"
102 #include "parse_local.h"
103 
104 
105 /**
106  * \ingroup Internal_Readers_Generic
107  * \brief Starts reader stack
108  * \param pinfo Parse settings
109  * \param reader Reader to use
110  * \param destroyer Destroyer to use
111  * \param vp Reader-specific arg
112  */
113 void
114 __ops_reader_set(__ops_parse_info_t * pinfo, __ops_reader_t * reader, __ops_reader_destroyer_t * destroyer, void *vp)
115 {
116 	pinfo->rinfo.reader = reader;
117 	pinfo->rinfo.destroyer = destroyer;
118 	pinfo->rinfo.arg = vp;
119 }
120 
121 /**
122  * \ingroup Internal_Readers_Generic
123  * \brief Adds to reader stack
124  * \param pinfo Parse settings
125  * \param reader Reader to use
126  * \param destroyer Reader's destroyer
127  * \param vp Reader-specific arg
128  */
129 void
130 __ops_reader_push(__ops_parse_info_t * pinfo, __ops_reader_t * reader, __ops_reader_destroyer_t * destroyer, void *vp)
131 {
132 	__ops_reader_info_t *rinfo = calloc(1, sizeof(*rinfo));
133 
134 	*rinfo = pinfo->rinfo;
135 	(void) memset(&pinfo->rinfo, 0x0, sizeof(pinfo->rinfo));
136 	pinfo->rinfo.next = rinfo;
137 	pinfo->rinfo.pinfo = pinfo;
138 
139 	/* should copy accumulate flags from other reader? RW */
140 	pinfo->rinfo.accumulate = rinfo->accumulate;
141 
142 	__ops_reader_set(pinfo, reader, destroyer, vp);
143 }
144 
145 /**
146  * \ingroup Internal_Readers_Generic
147  * \brief Removes from reader stack
148  * \param pinfo Parse settings
149  */
150 void
151 __ops_reader_pop(__ops_parse_info_t * pinfo)
152 {
153 	__ops_reader_info_t *next = pinfo->rinfo.next;
154 
155 	pinfo->rinfo = *next;
156 	free(next);
157 }
158 
159 /**
160  * \ingroup Internal_Readers_Generic
161  * \brief Gets arg from reader
162  * \param rinfo Reader info
163  * \return Pointer to reader info's arg
164  */
165 void           *
166 __ops_reader_get_arg(__ops_reader_info_t * rinfo)
167 {
168 	return rinfo->arg;
169 }
170 
171 /**************************************************************************/
172 
173 #define CRC24_POLY 0x1864cfbL
174 
175 /**
176  * \struct dearmour_t
177  */
178 typedef struct {
179 	enum {
180 		OUTSIDE_BLOCK = 0,
181 		BASE64,
182 		AT_TRAILER_NAME,
183 	}               state;
184 
185 	enum {
186 		NONE = 0,
187 		BEGIN_PGP_MESSAGE,
188 		BEGIN_PGP_PUBLIC_KEY_BLOCK,
189 		BEGIN_PGP_PRIVATE_KEY_BLOCK,
190 		BEGIN_PGP_MULTI,
191 		BEGIN_PGP_SIGNATURE,
192 
193 		END_PGP_MESSAGE,
194 		END_PGP_PUBLIC_KEY_BLOCK,
195 		END_PGP_PRIVATE_KEY_BLOCK,
196 		END_PGP_MULTI,
197 		END_PGP_SIGNATURE,
198 
199 		BEGIN_PGP_SIGNED_MESSAGE
200 	}               lastseen;
201 
202 	__ops_parse_info_t *parse_info;
203 	unsigned   seen_nl:1;
204 	unsigned   prev_nl:1;
205 	unsigned   allow_headers_without_gap:1;	/* !< allow headers in
206 							 * armoured data that
207 							 * are not separated
208 							 * from the data by a
209 							 * blank line */
210 	unsigned   allow_no_gap:1;	/* !< allow no blank line at the
211 					 * start of armoured data */
212 	unsigned   allow_trailing_whitespace:1;	/* !< allow armoured
213 							 * stuff to have
214 							 * trailing whitespace
215 							 * where we wouldn't
216 							 * strictly expect it */
217 
218 	/* it is an error to get a cleartext message without a sig */
219 	unsigned   expect_sig:1;
220 	unsigned   got_sig:1;
221 
222 	/* base64 stuff */
223 	unsigned        buffered;
224 	unsigned char   buffer[3];
225 	bool   eof64;
226 	unsigned long   checksum;
227 	unsigned long   read_checksum;
228 	/* unarmoured text blocks */
229 	unsigned char   unarmoured[NETPGP_BUFSIZ];
230 	size_t          num_unarmoured;
231 	/* pushed back data (stored backwards) */
232 	unsigned char  *pushed_back;
233 	unsigned        npushed_back;
234 	/* armoured block headers */
235 	__ops_headers_t   headers;
236 }               dearmour_t;
237 
238 static void
239 push_back(dearmour_t * dearmour, const unsigned char *buf,
240 	  unsigned length)
241 {
242 	unsigned        n;
243 
244 	assert(!dearmour->pushed_back);
245 	dearmour->pushed_back = calloc(1, length);
246 	for (n = 0; n < length; ++n) {
247 		dearmour->pushed_back[n] = buf[length - n - 1];
248 	}
249 	dearmour->npushed_back = length;
250 }
251 
252 static int
253 set_lastseen_headerline(dearmour_t * dearmour, char *buf, __ops_error_t ** errors)
254 {
255 	const char     *begin_msg = "BEGIN PGP MESSAGE";
256 	const char     *begin_public = "BEGIN PGP PUBLIC KEY BLOCK";
257 	const char     *begin_private = "BEGIN PGP PRIVATE KEY BLOCK";
258 	const char     *begin_multi = "BEGIN PGP MESSAGE, PART ";
259 	const char     *begin_sig = "BEGIN PGP SIGNATURE";
260 
261 	const char     *end_msg = "END PGP MESSAGE";
262 	const char     *end_public = "END PGP PUBLIC KEY BLOCK";
263 	const char     *end_private = "END PGP PRIVATE KEY BLOCK";
264 	const char     *end_multi = "END PGP MESSAGE, PART ";
265 	const char     *end_sig = "END PGP SIGNATURE";
266 
267 	const char     *begin_signed_msg = "BEGIN PGP SIGNED MESSAGE";
268 
269 	int             prev = dearmour->lastseen;
270 
271 	if (!strncmp(buf, begin_msg, strlen(begin_msg)))
272 		dearmour->lastseen = BEGIN_PGP_MESSAGE;
273 	else if (!strncmp(buf, begin_public, strlen(begin_public)))
274 		dearmour->lastseen = BEGIN_PGP_PUBLIC_KEY_BLOCK;
275 	else if (!strncmp(buf, begin_private, strlen(begin_private)))
276 		dearmour->lastseen = BEGIN_PGP_PRIVATE_KEY_BLOCK;
277 	else if (!strncmp(buf, begin_multi, strlen(begin_multi)))
278 		dearmour->lastseen = BEGIN_PGP_MULTI;
279 	else if (!strncmp(buf, begin_sig, strlen(begin_sig)))
280 		dearmour->lastseen = BEGIN_PGP_SIGNATURE;
281 
282 	else if (!strncmp(buf, end_msg, strlen(end_msg)))
283 		dearmour->lastseen = END_PGP_MESSAGE;
284 	else if (!strncmp(buf, end_public, strlen(end_public)))
285 		dearmour->lastseen = END_PGP_PUBLIC_KEY_BLOCK;
286 	else if (!strncmp(buf, end_private, strlen(end_private)))
287 		dearmour->lastseen = END_PGP_PRIVATE_KEY_BLOCK;
288 	else if (!strncmp(buf, end_multi, strlen(end_multi)))
289 		dearmour->lastseen = END_PGP_MULTI;
290 	else if (!strncmp(buf, end_sig, strlen(end_sig)))
291 		dearmour->lastseen = END_PGP_SIGNATURE;
292 
293 	else if (!strncmp(buf, begin_signed_msg, strlen(begin_signed_msg)))
294 		dearmour->lastseen = BEGIN_PGP_SIGNED_MESSAGE;
295 
296 	else {
297 		OPS_ERROR_1(errors, OPS_E_R_BAD_FORMAT, "Unrecognised Header Line %s", buf);
298 		return 0;
299 	}
300 
301 	if (__ops_get_debug_level(__FILE__))
302 		printf("set header: buf=%s, dearmour->lastseen=%d, prev=%d\n", buf, dearmour->lastseen, prev);
303 
304 	switch (dearmour->lastseen) {
305 	case NONE:
306 		OPS_ERROR_1(errors, OPS_E_R_BAD_FORMAT, "Unrecognised last seen Header Line %s", buf);
307 		break;
308 
309 	case END_PGP_MESSAGE:
310 		if (prev != BEGIN_PGP_MESSAGE)
311 			OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, "Got END PGP MESSAGE, but not after BEGIN");
312 		break;
313 
314 	case END_PGP_PUBLIC_KEY_BLOCK:
315 		if (prev != BEGIN_PGP_PUBLIC_KEY_BLOCK)
316 			OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, "Got END PGP PUBLIC KEY BLOCK, but not after BEGIN");
317 		break;
318 
319 	case END_PGP_PRIVATE_KEY_BLOCK:
320 		if (prev != BEGIN_PGP_PRIVATE_KEY_BLOCK)
321 			OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, "Got END PGP PRIVATE KEY BLOCK, but not after BEGIN");
322 		break;
323 
324 	case BEGIN_PGP_MULTI:
325 	case END_PGP_MULTI:
326 		OPS_ERROR(errors, OPS_E_R_UNSUPPORTED, "Multi-part messages are not yet supported");
327 		break;
328 
329 	case END_PGP_SIGNATURE:
330 		if (prev != BEGIN_PGP_SIGNATURE)
331 			OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, "Got END PGP SIGNATURE, but not after BEGIN");
332 		break;
333 
334 	case BEGIN_PGP_MESSAGE:
335 	case BEGIN_PGP_PUBLIC_KEY_BLOCK:
336 	case BEGIN_PGP_PRIVATE_KEY_BLOCK:
337 	case BEGIN_PGP_SIGNATURE:
338 	case BEGIN_PGP_SIGNED_MESSAGE:
339 		break;
340 	}
341 
342 	return 1;
343 }
344 
345 static int
346 read_char(dearmour_t * dearmour, __ops_error_t ** errors,
347 	  __ops_reader_info_t * rinfo,
348 	  __ops_parse_cb_info_t * cbinfo,
349 	  bool skip)
350 {
351 	unsigned char   c[1];
352 
353 	do {
354 		if (dearmour->npushed_back) {
355 			c[0] = dearmour->pushed_back[--dearmour->npushed_back];
356 			if (!dearmour->npushed_back) {
357 				free(dearmour->pushed_back);
358 				dearmour->pushed_back = NULL;
359 			}
360 		}
361 		/*
362 		 * XXX: should __ops_stacked_read exist? Shouldn't this be a
363 		 * limited_read?
364 		 */
365 		else if (__ops_stacked_read(c, 1, errors, rinfo, cbinfo) != 1)
366 			return -1;
367 	}
368 	while (skip && c[0] == '\r');
369 
370 	dearmour->prev_nl = dearmour->seen_nl;
371 	dearmour->seen_nl = c[0] == '\n';
372 
373 	return c[0];
374 }
375 
376 static int
377 eat_whitespace(int first,
378 	       dearmour_t * dearmour, __ops_error_t ** errors,
379 	       __ops_reader_info_t * rinfo,
380 	       __ops_parse_cb_info_t * cbinfo,
381 	       bool skip)
382 {
383 	int             c = first;
384 
385 	while (c == ' ' || c == '\t')
386 		c = read_char(dearmour, errors, rinfo, cbinfo, skip);
387 
388 	return c;
389 }
390 
391 static int
392 read_and_eat_whitespace(dearmour_t * dearmour,
393 			__ops_error_t ** errors,
394 			__ops_reader_info_t * rinfo,
395 			__ops_parse_cb_info_t * cbinfo,
396 			bool skip)
397 {
398 	int             c;
399 
400 	do {
401 		c = read_char(dearmour, errors, rinfo, cbinfo, skip);
402 	} while (c == ' ' || c == '\t');
403 
404 	return c;
405 }
406 
407 static void
408 flush(dearmour_t * dearmour, __ops_parse_cb_info_t * cbinfo)
409 {
410 	__ops_parser_content_t content;
411 
412 	if (dearmour->num_unarmoured == 0)
413 		return;
414 
415 	content.u.unarmoured_text.data = dearmour->unarmoured;
416 	content.u.unarmoured_text.length = dearmour->num_unarmoured;
417 	CALLBACK(cbinfo, OPS_PTAG_CT_UNARMOURED_TEXT, &content);
418 	dearmour->num_unarmoured = 0;
419 }
420 
421 static int
422 unarmoured_read_char(dearmour_t * dearmour, __ops_error_t ** errors,
423 		     __ops_reader_info_t * rinfo,
424 		     __ops_parse_cb_info_t * cbinfo,
425 		     bool skip)
426 {
427 	int             c;
428 
429 	do {
430 		c = read_char(dearmour, errors, rinfo, cbinfo, false);
431 		if (c < 0) {
432 			return c;
433 		}
434 		dearmour->unarmoured[dearmour->num_unarmoured++] = c;
435 		if (dearmour->num_unarmoured == sizeof(dearmour->unarmoured)) {
436 			flush(dearmour, cbinfo);
437 		}
438 	} while (skip && c == '\r');
439 
440 	return c;
441 }
442 
443 /**
444  * \param headers
445  * \param key
446  *
447  * \return header value if found, otherwise NULL
448  */
449 static const char *
450 __ops_find_header(__ops_headers_t * headers, const char *key)
451 {
452 	unsigned        n;
453 
454 	for (n = 0; n < headers->nheaders; ++n) {
455 		if (strcmp(headers->headers[n].key, key) == 0) {
456 			return headers->headers[n].value;
457 		}
458 	}
459 	return NULL;
460 }
461 
462 /**
463  * \param dest
464  * \param src
465  */
466 static void
467 __ops_dup_headers(__ops_headers_t * dest, const __ops_headers_t * src)
468 {
469 	unsigned        n;
470 
471 	dest->headers = calloc(src->nheaders, sizeof(*dest->headers));
472 	dest->nheaders = src->nheaders;
473 
474 	for (n = 0; n < src->nheaders; ++n) {
475 		dest->headers[n].key = strdup(src->headers[n].key);
476 		dest->headers[n].value = strdup(src->headers[n].value);
477 	}
478 }
479 
480 /*
481  * Note that this skips CRs so implementations always see just straight LFs
482  * as line terminators
483  */
484 static int
485 process_dash_escaped(dearmour_t * dearmour, __ops_error_t ** errors,
486 		     __ops_reader_info_t * rinfo,
487 		     __ops_parse_cb_info_t * cbinfo)
488 {
489 	__ops_parser_content_t content;
490 	__ops_parser_content_t content2;
491 	__ops_signed_cleartext_body_t *body = &content.u.signed_cleartext_body;
492 	__ops_signed_cleartext_trailer_t *trailer
493 	= &content2.u.signed_cleartext_trailer;
494 	const char     *hashstr;
495 	__ops_hash_t     *hash;
496 	int             total;
497 
498 	hash = calloc(1, sizeof(*hash));
499 	hashstr = __ops_find_header(&dearmour->headers, "Hash");
500 	if (hashstr) {
501 		__ops_hash_algorithm_t alg;
502 
503 		alg = __ops_hash_algorithm_from_text(hashstr);
504 
505 		if (!__ops_is_hash_alg_supported(&alg)) {
506 			free(hash);
507 			OPS_ERROR_1(errors, OPS_E_R_BAD_FORMAT, "Unsupported hash algorithm '%s'", hashstr);
508 			return -1;
509 		}
510 		if (alg == OPS_HASH_UNKNOWN) {
511 			free(hash);
512 			OPS_ERROR_1(errors, OPS_E_R_BAD_FORMAT, "Unknown hash algorithm '%s'", hashstr);
513 			return -1;
514 		}
515 		__ops_hash_any(hash, alg);
516 	} else
517 		__ops_hash_md5(hash);
518 
519 	hash->init(hash);
520 
521 	body->length = 0;
522 	total = 0;
523 	for (;;) {
524 		int             c;
525 		unsigned        count;
526 
527 		if ((c = read_char(dearmour, errors, rinfo, cbinfo, true)) < 0)
528 			return -1;
529 		if (dearmour->prev_nl && c == '-') {
530 			if ((c = read_char(dearmour, errors, rinfo, cbinfo, false)) < 0)
531 				return -1;
532 			if (c != ' ') {
533 				/* then this had better be a trailer! */
534 				if (c != '-')
535 					OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, "Bad dash-escaping");
536 				for (count = 2; count < 5; ++count) {
537 					if ((c = read_char(dearmour, errors, rinfo, cbinfo, false)) < 0) {
538 						return -1;
539 					}
540 					if (c != '-') {
541 						OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, "Bad dash-escaping (2)");
542 					}
543 				}
544 				dearmour->state = AT_TRAILER_NAME;
545 				break;
546 			}
547 			/* otherwise we read the next character */
548 			if ((c = read_char(dearmour, errors, rinfo, cbinfo, false)) < 0) {
549 				return -1;
550 			}
551 		}
552 		if (c == '\n' && body->length) {
553 			assert(memchr(body->data + 1, '\n', body->length - 1) == NULL);
554 			if (body->data[0] == '\n') {
555 				hash->add(hash, (const unsigned char *) "\r", 1);
556 			}
557 			hash->add(hash, body->data, body->length);
558 			if (__ops_get_debug_level(__FILE__)) {
559 				fprintf(stderr, "Got body:\n%s\n", body->data);
560 			}
561 			CALLBACK(cbinfo, OPS_PTAG_CT_SIGNED_CLEARTEXT_BODY, &content);
562 			body->length = 0;
563 		}
564 		body->data[body->length++] = c;
565 		++total;
566 		if (body->length == sizeof(body->data)) {
567 			if (__ops_get_debug_level(__FILE__)) {
568 				fprintf(stderr, "Got body (2):\n%s\n", body->data);
569 			}
570 			CALLBACK(cbinfo, OPS_PTAG_CT_SIGNED_CLEARTEXT_BODY, &content);
571 			body->length = 0;
572 		}
573 	}
574 
575 	assert(body->data[0] == '\n');
576 	assert(body->length == 1);
577 	/* don't send that one character, because its part of the trailer. */
578 
579 	trailer->hash = hash;
580 	CALLBACK(cbinfo, OPS_PTAG_CT_SIGNED_CLEARTEXT_TRAILER, &content2);
581 
582 	return total;
583 }
584 
585 static int
586 add_header(dearmour_t * dearmour, const char *key, const char
587 	   *value)
588 {
589 	/*
590          * Check that the header is valid
591          */
592 	if (strcmp(key, "Version") == 0 || strcmp(key, "Comment") == 0 ||
593 	    strcmp(key, "MessageID") == 0 || strcmp(key, "Hash") == 0 ||
594 	    strcmp(key, "Charset") == 0) {
595 		dearmour->headers.headers = realloc(dearmour->headers.headers,
596 					       (dearmour->headers.nheaders + 1)
597 					    * sizeof(*dearmour->headers.headers));
598 		dearmour->headers.headers[dearmour->headers.nheaders].key = strdup(key);
599 		dearmour->headers.headers[dearmour->headers.nheaders].value = strdup(value);
600 		++dearmour->headers.nheaders;
601 		return 1;
602 	} else {
603 		return 0;
604 	}
605 }
606 
607 /* \todo what does a return value of 0 indicate? 1 is good, -1 is bad */
608 static int
609 parse_headers(dearmour_t * dearmour, __ops_error_t ** errors,
610 	      __ops_reader_info_t * rinfo, __ops_parse_cb_info_t * cbinfo)
611 {
612 	unsigned        nbuf;
613 	unsigned        size;
614 	char           *buf;
615 	bool   		first = true;
616 	int             rtn = 1;
617 
618 	buf = NULL;
619 	nbuf = size = 0;
620 
621 	for (;;) {
622 		int             c;
623 
624 		if ((c = read_char(dearmour, errors, rinfo, cbinfo, true)) < 0) {
625 			OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, "Unexpected EOF");
626 			rtn = -1;
627 			break;
628 		}
629 		if (c == '\n') {
630 			char           *s;
631 
632 			if (nbuf == 0) {
633 				break;
634 			}
635 
636 			assert(nbuf < size);
637 			buf[nbuf] = '\0';
638 
639 			s = strchr(buf, ':');
640 			if (!s)
641 				if (!first && !dearmour->allow_headers_without_gap) {
642 					/*
643 					 * then we have seriously malformed
644 					 * armour
645 					 */
646 					OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, "No colon in armour header");
647 					rtn = -1;
648 					break;
649 				} else {
650 					if (first &&
651 					    !(dearmour->allow_headers_without_gap || dearmour->allow_no_gap)) {
652 						OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, "No colon in armour header (2)");
653 						/*
654 						 * then we have a nasty
655 						 * armoured block with no
656 						 */
657 						/*
658 						 * headers, not even a blank
659 						 * line.
660 						 */
661 						buf[nbuf] = '\n';
662 						push_back(dearmour, (unsigned char *) buf, nbuf + 1);
663 						rtn = -1;
664 						break;
665 					}
666 				}
667 			else {
668 				*s = '\0';
669 				if (s[1] != ' ') {
670 					OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, "No space in armour header");
671 					rtn = -1;
672 					goto end;
673 				}
674 				if (!add_header(dearmour, buf, s + 2)) {
675 					OPS_ERROR_1(errors, OPS_E_R_BAD_FORMAT, "Invalid header %s", buf);
676 					rtn = -1;
677 					goto end;
678 				}
679 				nbuf = 0;
680 			}
681 			first = false;
682 		} else {
683 			if (size <= nbuf + 1) {
684 				size += size + 80;
685 				buf = realloc(buf, size);
686 			}
687 			buf[nbuf++] = c;
688 		}
689 	}
690 
691 end:
692 	free(buf);
693 
694 	return rtn;
695 }
696 
697 static int
698 read4(dearmour_t * dearmour, __ops_error_t ** errors,
699       __ops_reader_info_t * rinfo, __ops_parse_cb_info_t * cbinfo,
700       int *pc, unsigned *pn, unsigned long *pl)
701 {
702 	int             n, c;
703 	unsigned long   l = 0;
704 
705 	for (n = 0; n < 4; ++n) {
706 		c = read_char(dearmour, errors, rinfo, cbinfo, true);
707 		if (c < 0) {
708 			dearmour->eof64 = true;
709 			return -1;
710 		}
711 		if (c == '-' || c == '=') {
712 			break;
713 		}
714 		l <<= 6;
715 		if (c >= 'A' && c <= 'Z')
716 			l += c - 'A';
717 		else if (c >= 'a' && c <= 'z')
718 			l += c - 'a' + 26;
719 		else if (c >= '0' && c <= '9')
720 			l += c - '0' + 52;
721 		else if (c == '+')
722 			l += 62;
723 		else if (c == '/')
724 			l += 63;
725 		else {
726 			--n;
727 			l >>= 6;
728 		}
729 	}
730 
731 	*pc = c;
732 	*pn = n;
733 	*pl = l;
734 
735 	return 4;
736 }
737 
738 unsigned
739 __ops_crc24(unsigned checksum, unsigned char c)
740 {
741 	unsigned        i;
742 
743 	checksum ^= c << 16;
744 	for (i = 0; i < 8; i++) {
745 		checksum <<= 1;
746 		if (checksum & 0x1000000)
747 			checksum ^= CRC24_POLY;
748 	}
749 	return checksum & 0xffffffL;
750 }
751 
752 static int
753 decode64(dearmour_t * dearmour, __ops_error_t ** errors,
754 	 __ops_reader_info_t * rinfo, __ops_parse_cb_info_t * cbinfo)
755 {
756 	unsigned        n;
757 	int             n2;
758 	unsigned long   l;
759 	int             c;
760 	int             ret;
761 
762 	assert(dearmour->buffered == 0);
763 
764 	ret = read4(dearmour, errors, rinfo, cbinfo, &c, &n, &l);
765 	if (ret < 0) {
766 		OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, "Badly formed base64");
767 		return 0;
768 	}
769 	if (n == 3) {
770 		if (c != '=') {
771 			OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, "Badly terminated base64 (2)");
772 			return 0;
773 		}
774 		dearmour->buffered = 2;
775 		dearmour->eof64 = true;
776 		l >>= 2;
777 	} else if (n == 2) {
778 		if (c != '=') {
779 			OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, "Badly terminated base64 (3)");
780 			return 0;
781 		}
782 		dearmour->buffered = 1;
783 		dearmour->eof64 = true;
784 		l >>= 4;
785 		c = read_char(dearmour, errors, rinfo, cbinfo, false);
786 		if (c != '=') {
787 			OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, "Badly terminated base64");
788 			return 0;
789 		}
790 	} else if (n == 0) {
791 		if (!dearmour->prev_nl || c != '=') {
792 			OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, "Badly terminated base64 (4)");
793 			return 0;
794 		}
795 		dearmour->buffered = 0;
796 	} else {
797 		assert(n == 4);
798 		dearmour->buffered = 3;
799 		assert(c != '-' && c != '=');
800 	}
801 
802 	if (dearmour->buffered < 3 && dearmour->buffered > 0) {
803 		/* then we saw padding */
804 		assert(c == '=');
805 		c = read_and_eat_whitespace(dearmour, errors, rinfo, cbinfo, true);
806 		if (c != '\n') {
807 			OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, "No newline at base64 end");
808 			return 0;
809 		}
810 		c = read_char(dearmour, errors, rinfo, cbinfo, false);
811 		if (c != '=') {
812 			OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, "No checksum at base64 end");
813 			return 0;
814 		}
815 	}
816 	if (c == '=') {
817 		/* now we are at the checksum */
818 		ret = read4(dearmour, errors, rinfo, cbinfo, &c, &n, &dearmour->read_checksum);
819 		if (ret < 0 || n != 4) {
820 			OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, "Error in checksum");
821 			return 0;
822 		}
823 		c = read_char(dearmour, errors, rinfo, cbinfo, true);
824 		if (dearmour->allow_trailing_whitespace)
825 			c = eat_whitespace(c, dearmour, errors, rinfo, cbinfo, true);
826 		if (c != '\n') {
827 			OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, "Badly terminated checksum");
828 			return 0;
829 		}
830 		c = read_char(dearmour, errors, rinfo, cbinfo, false);
831 		if (c != '-') {
832 			OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, "Bad base64 trailer (2)");
833 			return 0;
834 		}
835 	}
836 	if (c == '-') {
837 		for (n = 0; n < 4; ++n)
838 			if (read_char(dearmour, errors, rinfo, cbinfo, false) != '-') {
839 				OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, "Bad base64 trailer");
840 				return 0;
841 			}
842 		dearmour->eof64 = true;
843 	} else
844 		assert(dearmour->buffered);
845 
846 	for (n = 0; n < dearmour->buffered; ++n) {
847 		dearmour->buffer[n] = l;
848 		l >>= 8;
849 	}
850 
851 	for (n2 = dearmour->buffered - 1; n2 >= 0; --n2)
852 		dearmour->checksum = __ops_crc24(dearmour->checksum, dearmour->buffer[n2]);
853 
854 	if (dearmour->eof64 && dearmour->read_checksum != dearmour->checksum) {
855 		OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, "Checksum mismatch");
856 		return 0;
857 	}
858 	return 1;
859 }
860 
861 static void
862 base64(dearmour_t * dearmour)
863 {
864 	dearmour->state = BASE64;
865 	dearmour->checksum = CRC24_INIT;
866 	dearmour->eof64 = false;
867 	dearmour->buffered = 0;
868 }
869 
870 /* This reader is rather strange in that it can generate callbacks for */
871 /* content - this is because plaintext is not encapsulated in PGP */
872 /* packets... it also calls back for the text between the blocks. */
873 
874 static int
875 armoured_data_reader(void *dest_, size_t length, __ops_error_t ** errors,
876 		     __ops_reader_info_t * rinfo,
877 		     __ops_parse_cb_info_t * cbinfo)
878 {
879 	dearmour_t *dearmour = __ops_reader_get_arg(rinfo);
880 	__ops_parser_content_t content;
881 	int             ret;
882 	bool   first;
883 	unsigned char  *dest = dest_;
884 	int             saved = length;
885 
886 	if (dearmour->eof64 && !dearmour->buffered)
887 		assert(dearmour->state == OUTSIDE_BLOCK || dearmour->state == AT_TRAILER_NAME);
888 
889 	while (length > 0) {
890 		unsigned        count;
891 		unsigned        n;
892 		char            buf[1024];
893 		int             c;
894 
895 		flush(dearmour, cbinfo);
896 		switch (dearmour->state) {
897 		case OUTSIDE_BLOCK:
898 			/*
899 			 * This code returns EOF rather than EARLY_EOF
900 			 * because if we don't see a header line at all, then
901 			 * it is just an EOF (and not a BLOCK_END)
902 			 */
903 			while (!dearmour->seen_nl) {
904 				if ((c = unarmoured_read_char(dearmour, errors, rinfo, cbinfo, true)) < 0) {
905 					return 0;
906 				}
907 			}
908 
909 			/*
910 			 * flush at this point so we definitely have room for
911 			 * the header, and so we can easily erase it from the
912 			 * buffer
913 			 */
914 			flush(dearmour, cbinfo);
915 			/* Find and consume the 5 leading '-' */
916 			for (count = 0; count < 5; ++count) {
917 				if ((c = unarmoured_read_char(dearmour, errors, rinfo, cbinfo, false)) < 0) {
918 					return 0;
919 				}
920 				if (c != '-') {
921 					goto reloop;
922 				}
923 			}
924 
925 			/* Now find the block type */
926 			for (n = 0; n < sizeof(buf) - 1;) {
927 				if ((c = unarmoured_read_char(dearmour, errors, rinfo, cbinfo, false)) < 0) {
928 					return 0;
929 				}
930 				if (c == '-') {
931 					goto got_minus;
932 				}
933 				buf[n++] = c;
934 			}
935 			/* then I guess this wasn't a proper header */
936 			break;
937 
938 	got_minus:
939 			buf[n] = '\0';
940 
941 			/* Consume trailing '-' */
942 			for (count = 1; count < 5; ++count) {
943 				if ((c = unarmoured_read_char(dearmour, errors, rinfo, cbinfo, false)) < 0) {
944 					return 0;
945 				}
946 				if (c != '-') {
947 					/* wasn't a header after all */
948 					goto reloop;
949 				}
950 			}
951 
952 			/* Consume final NL */
953 			if ((c = unarmoured_read_char(dearmour, errors, rinfo, cbinfo, true)) < 0) {
954 				return 0;
955 			}
956 			if (dearmour->allow_trailing_whitespace) {
957 				if ((c = eat_whitespace(c, dearmour, errors, rinfo, cbinfo,
958 							true)) < 0) {
959 					return 0;
960 				}
961 			}
962 			if (c != '\n') {
963 				/* wasn't a header line after all */
964 				break;
965 			}
966 
967 			/*
968 			 * Now we've seen the header, scrub it from the
969 			 * buffer
970 			 */
971 			dearmour->num_unarmoured = 0;
972 
973 			/*
974 			 * But now we've seen a header line, then errors are
975 			 * EARLY_EOF
976 			 */
977 			if ((ret = parse_headers(dearmour, errors, rinfo, cbinfo)) <= 0) {
978 				return -1;
979 			}
980 
981 			if (!set_lastseen_headerline(dearmour, buf, errors)) {
982 				return -1;
983 			}
984 
985 			if (!strcmp(buf, "BEGIN PGP SIGNED MESSAGE")) {
986 				__ops_dup_headers(&content.u.signed_cleartext_header.headers, &dearmour->headers);
987 				CALLBACK(cbinfo, OPS_PTAG_CT_SIGNED_CLEARTEXT_HEADER, &content);
988 				ret = process_dash_escaped(dearmour, errors, rinfo, cbinfo);
989 				if (ret <= 0) {
990 					return ret;
991 				}
992 			} else {
993 				content.u.armour_header.type = buf;
994 				content.u.armour_header.headers = dearmour->headers;
995 				(void) memset(&dearmour->headers, 0x0, sizeof(dearmour->headers));
996 				CALLBACK(cbinfo, OPS_PTAG_CT_ARMOUR_HEADER, &content);
997 				base64(dearmour);
998 			}
999 			break;
1000 
1001 		case BASE64:
1002 			first = true;
1003 			while (length > 0) {
1004 				if (!dearmour->buffered) {
1005 					if (!dearmour->eof64) {
1006 						ret = decode64(dearmour, errors, rinfo, cbinfo);
1007 						if (ret <= 0) {
1008 							return ret;
1009 						}
1010 					}
1011 					if (!dearmour->buffered) {
1012 						assert(dearmour->eof64);
1013 						if (first) {
1014 							dearmour->state = AT_TRAILER_NAME;
1015 							goto reloop;
1016 						}
1017 						return -1;
1018 					}
1019 				}
1020 				assert(dearmour->buffered);
1021 				*dest = dearmour->buffer[--dearmour->buffered];
1022 				++dest;
1023 				--length;
1024 				first = false;
1025 			}
1026 			if (dearmour->eof64 && !dearmour->buffered) {
1027 				dearmour->state = AT_TRAILER_NAME;
1028 			}
1029 			break;
1030 
1031 		case AT_TRAILER_NAME:
1032 			for (n = 0; n < sizeof(buf) - 1;) {
1033 				if ((c = read_char(dearmour, errors, rinfo, cbinfo, false)) < 0) {
1034 					return -1;
1035 				}
1036 				if (c == '-') {
1037 					goto got_minus2;
1038 				}
1039 				buf[n++] = c;
1040 			}
1041 			/* then I guess this wasn't a proper trailer */
1042 			OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, "Bad ASCII armour trailer");
1043 			break;
1044 
1045 got_minus2:
1046 			buf[n] = '\0';
1047 
1048 			if (!set_lastseen_headerline(dearmour, buf, errors)) {
1049 				return -1;
1050 			}
1051 
1052 			/* Consume trailing '-' */
1053 			for (count = 1; count < 5; ++count) {
1054 				if ((c = read_char(dearmour, errors, rinfo, cbinfo, false)) < 0) {
1055 					return -1;
1056 				}
1057 				if (c != '-') {
1058 					/* wasn't a trailer after all */
1059 					OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, "Bad ASCII armour trailer (2)");
1060 				}
1061 			}
1062 
1063 			/* Consume final NL */
1064 			if ((c = read_char(dearmour, errors, rinfo, cbinfo, true)) < 0) {
1065 				return -1;
1066 			}
1067 			if (dearmour->allow_trailing_whitespace) {
1068 				if ((c = eat_whitespace(c, dearmour, errors, rinfo, cbinfo,
1069 							true)) < 0) {
1070 					return 0;
1071 				}
1072 			}
1073 			if (c != '\n') {
1074 				/* wasn't a trailer line after all */
1075 				OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, "Bad ASCII armour trailer (3)");
1076 			}
1077 
1078 			if (strncmp(buf, "BEGIN ", 6) == 0) {
1079 				if (!set_lastseen_headerline(dearmour, buf, errors)) {
1080 					return -1;
1081 				}
1082 				if ((ret = parse_headers(dearmour, errors, rinfo, cbinfo)) <= 0) {
1083 					return ret;
1084 				}
1085 				content.u.armour_header.type = buf;
1086 				content.u.armour_header.headers = dearmour->headers;
1087 				(void) memset(&dearmour->headers, 0x0, sizeof(dearmour->headers));
1088 				CALLBACK(cbinfo, OPS_PTAG_CT_ARMOUR_HEADER, &content);
1089 				base64(dearmour);
1090 			} else {
1091 				content.u.armour_trailer.type = buf;
1092 				CALLBACK(cbinfo, OPS_PTAG_CT_ARMOUR_TRAILER, &content);
1093 				dearmour->state = OUTSIDE_BLOCK;
1094 			}
1095 			break;
1096 		}
1097 reloop:
1098 		continue;
1099 	}
1100 
1101 	return saved;
1102 }
1103 
1104 static void
1105 armoured_data_destroyer(__ops_reader_info_t * rinfo)
1106 {
1107 	free(__ops_reader_get_arg(rinfo));
1108 }
1109 
1110 /**
1111  * \ingroup Core_Readers_Armour
1112  * \brief Pushes dearmouring reader onto stack
1113  * \param parse_info Usual structure containing information about to how to do the parse
1114  * \sa __ops_reader_pop_dearmour()
1115  */
1116 void
1117 __ops_reader_push_dearmour(__ops_parse_info_t * parse_info)
1118 /*
1119  * This function originally had these parameters to cater for packets which
1120  * didn't strictly match the RFC. The initial 0.5 release is only going to
1121  * support strict checking. If it becomes desirable to support loose checking
1122  * of armoured packets and these params are reinstated, parse_headers() must
1123  * be fixed so that these flags work correctly.
1124  *
1125  * // Allow headers in armoured data that are not separated from the data by a
1126  * blank line bool without_gap,
1127  *
1128  * // Allow no blank line at the start of armoured data bool no_gap,
1129  *
1130  * //Allow armoured data to have trailing whitespace where we strictly would not
1131  * expect it			      bool trailing_whitespace
1132  */
1133 {
1134 	dearmour_t *dearmour;
1135 
1136 	dearmour = calloc(1, sizeof(*dearmour));
1137 	dearmour->seen_nl = true;
1138 	/*
1139 	    dearmour->allow_headers_without_gap=without_gap;
1140 	    dearmour->allow_no_gap=no_gap;
1141 	    dearmour->allow_trailing_whitespace=trailing_whitespace;
1142 	*/
1143 	dearmour->expect_sig = false;
1144 	dearmour->got_sig = false;
1145 
1146 	__ops_reader_push(parse_info, armoured_data_reader, armoured_data_destroyer, dearmour);
1147 }
1148 
1149 /**
1150  * \ingroup Core_Readers_Armour
1151  * \brief Pops dearmour reader from stock
1152  * \param pinfo
1153  * \sa __ops_reader_push_dearmour()
1154  */
1155 void
1156 __ops_reader_pop_dearmour(__ops_parse_info_t * pinfo)
1157 {
1158 	dearmour_t *dearmour = __ops_reader_get_arg(__ops_parse_get_rinfo(pinfo));
1159 	free(dearmour);
1160 	__ops_reader_pop(pinfo);
1161 }
1162 
1163 /**************************************************************************/
1164 
1165 /* this is used for *decrypting* */
1166 typedef struct {
1167 	unsigned char   decrypted[1024];
1168 	size_t          decrypted_count;
1169 	size_t          decrypted_offset;
1170 	__ops_crypt_t    *decrypt;
1171 	__ops_region_t   *region;
1172 	unsigned   prev_read_was_plain:1;
1173 }               encrypted_t;
1174 
1175 static int
1176 encrypted_data_reader(void *dest, size_t length, __ops_error_t ** errors,
1177 		      __ops_reader_info_t * rinfo,
1178 		      __ops_parse_cb_info_t * cbinfo)
1179 {
1180 	encrypted_t *encrypted = __ops_reader_get_arg(rinfo);
1181 	int             saved = length;
1182 	char           *cdest;
1183 
1184 	/*
1185 	 * V3 MPIs have the count plain and the cipher is reset after each
1186 	 * count
1187 	 */
1188 	if (encrypted->prev_read_was_plain && !rinfo->pinfo->reading_mpi_length) {
1189 		assert(rinfo->pinfo->reading_v3_secret);
1190 		encrypted->decrypt->decrypt_resync(encrypted->decrypt);
1191 		encrypted->prev_read_was_plain = false;
1192 	} else if (rinfo->pinfo->reading_v3_secret &&
1193 		   rinfo->pinfo->reading_mpi_length) {
1194 		encrypted->prev_read_was_plain = true;
1195 	}
1196 	while (length > 0) {
1197 		if (encrypted->decrypted_count) {
1198 			unsigned        n;
1199 
1200 			/*
1201 			 * if we are reading v3 we should never read more
1202 			 * than
1203 			 */
1204 			/* we're asked for */
1205 			assert(length >= encrypted->decrypted_count
1206 			       || (!rinfo->pinfo->reading_v3_secret
1207 				   && !rinfo->pinfo->exact_read));
1208 
1209 			n = MIN(length, encrypted->decrypted_count);
1210 
1211 			(void) memcpy(dest, encrypted->decrypted + encrypted->decrypted_offset, n);
1212 			encrypted->decrypted_count -= n;
1213 			encrypted->decrypted_offset += n;
1214 			length -= n;
1215 			cdest = dest;
1216 			cdest += n;
1217 			dest = cdest;
1218 		} else {
1219 			unsigned        n = encrypted->region->length;
1220 			unsigned char   buffer[1024];
1221 
1222 			if (!n) {
1223 				return -1;
1224 			}
1225 			if (!encrypted->region->indeterminate) {
1226 				n -= encrypted->region->length_read;
1227 				if (n == 0)
1228 					return saved - length;
1229 				if (n > sizeof(buffer))
1230 					n = sizeof(buffer);
1231 			} else {
1232 				n = sizeof(buffer);
1233 			}
1234 
1235 			/*
1236 			 * we can only read as much as we're asked for in v3
1237 			 * keys
1238 			 */
1239 			/* because they're partially unencrypted! */
1240 			if ((rinfo->pinfo->reading_v3_secret || rinfo->pinfo->exact_read)
1241 			    && n > length)
1242 				n = length;
1243 
1244 			if (!__ops_stacked_limited_read(buffer, n, encrypted->region, errors, rinfo,
1245 						      cbinfo)) {
1246 				return -1;
1247 			}
1248 			if (!rinfo->pinfo->reading_v3_secret ||
1249 			    !rinfo->pinfo->reading_mpi_length) {
1250 				encrypted->decrypted_count = __ops_decrypt_se_ip(encrypted->decrypt,
1251 							     encrypted->decrypted,
1252 								 buffer, n);
1253 
1254 				if (__ops_get_debug_level(__FILE__)) {
1255 					int             i;
1256 
1257 					(void) fprintf(stderr, "READING:\nencrypted: ");
1258 					for (i = 0; i < 16; i++) {
1259 						(void) fprintf(stderr, "%2x ", buffer[i]);
1260 					}
1261 					(void) fprintf(stderr, "\ndecrypted: ");
1262 					for (i = 0; i < 16; i++) {
1263 						(void) fprintf(stderr, "%2x ", encrypted->decrypted[i]);
1264 					}
1265 					(void) fprintf(stderr, "\n");
1266 				}
1267 			} else {
1268 				(void) memcpy(&encrypted->decrypted[encrypted->decrypted_offset], buffer, n);
1269 				encrypted->decrypted_count = n;
1270 			}
1271 
1272 			assert(encrypted->decrypted_count > 0);
1273 
1274 			encrypted->decrypted_offset = 0;
1275 		}
1276 	}
1277 
1278 	return saved;
1279 }
1280 
1281 static void
1282 encrypted_data_destroyer(__ops_reader_info_t * rinfo)
1283 {
1284 	free(__ops_reader_get_arg(rinfo));
1285 }
1286 
1287 /**
1288  * \ingroup Core_Readers_SE
1289  * \brief Pushes decryption reader onto stack
1290  * \sa __ops_reader_pop_decrypt()
1291  */
1292 void
1293 __ops_reader_push_decrypt(__ops_parse_info_t * pinfo, __ops_crypt_t * decrypt,
1294 			__ops_region_t * region)
1295 {
1296 	encrypted_t *encrypted = calloc(1, sizeof(*encrypted));
1297 
1298 	encrypted->decrypt = decrypt;
1299 	encrypted->region = region;
1300 
1301 	__ops_decrypt_init(encrypted->decrypt);
1302 
1303 	__ops_reader_push(pinfo, encrypted_data_reader, encrypted_data_destroyer, encrypted);
1304 }
1305 
1306 /**
1307  * \ingroup Core_Readers_Encrypted
1308  * \brief Pops decryption reader from stack
1309  * \sa __ops_reader_push_decrypt()
1310  */
1311 void
1312 __ops_reader_pop_decrypt(__ops_parse_info_t * pinfo)
1313 {
1314 	encrypted_t *encrypted = __ops_reader_get_arg(__ops_parse_get_rinfo(pinfo));
1315 
1316 	encrypted->decrypt->decrypt_finish(encrypted->decrypt);
1317 	free(encrypted);
1318 
1319 	__ops_reader_pop(pinfo);
1320 }
1321 
1322 /**************************************************************************/
1323 
1324 typedef struct {
1325 	/* boolean: false once we've done the preamble/MDC checks */
1326 	/* and are reading from the plaintext */
1327 	int             passed_checks;
1328 	unsigned char  *plaintext;
1329 	size_t          plaintext_available;
1330 	size_t          plaintext_offset;
1331 	__ops_region_t   *region;
1332 	__ops_crypt_t    *decrypt;
1333 }               decrypt_se_ip_t;
1334 
1335 static int
1336 se_ip_data_reader(void *dest_, size_t len, __ops_error_t ** errors,
1337 		  __ops_reader_info_t * rinfo,
1338 		  __ops_parse_cb_info_t * cbinfo)
1339 {
1340 
1341 	/*
1342           Gets entire SE_IP data packet.
1343           Verifies leading preamble
1344           Verifies trailing MDC packet
1345           Then passes up plaintext as requested
1346         */
1347 
1348 	unsigned int    n = 0;
1349 
1350 	__ops_region_t    decrypted_region;
1351 
1352 	decrypt_se_ip_t *se_ip = __ops_reader_get_arg(rinfo);
1353 
1354 	if (!se_ip->passed_checks) {
1355 		unsigned char  *buf = NULL;
1356 
1357 		__ops_hash_t      hash;
1358 		unsigned char   hashed[SHA_DIGEST_LENGTH];
1359 
1360 		size_t          b;
1361 		size_t          sz_preamble;
1362 		size_t          sz_mdc_hash;
1363 		size_t          sz_mdc;
1364 		size_t          sz_plaintext;
1365 
1366 		unsigned char  *preamble;
1367 		unsigned char  *plaintext;
1368 		unsigned char  *mdc;
1369 		unsigned char  *mdc_hash;
1370 
1371 		__ops_hash_any(&hash, OPS_HASH_SHA1);
1372 		hash.init(&hash);
1373 
1374 		__ops_init_subregion(&decrypted_region, NULL);
1375 		decrypted_region.length = se_ip->region->length - se_ip->region->length_read;
1376 		buf = calloc(1, decrypted_region.length);
1377 
1378 		/* read entire SE IP packet */
1379 
1380 		if (!__ops_stacked_limited_read(buf, decrypted_region.length, &decrypted_region, errors, rinfo, cbinfo)) {
1381 			free(buf);
1382 			return -1;
1383 		}
1384 		if (__ops_get_debug_level(__FILE__)) {
1385 			unsigned int    i = 0;
1386 			fprintf(stderr, "\n\nentire SE IP packet (len=%d):\n", decrypted_region.length);
1387 			for (i = 0; i < decrypted_region.length; i++) {
1388 				fprintf(stderr, "0x%02x ", buf[i]);
1389 				if (!((i + 1) % 8))
1390 					fprintf(stderr, "\n");
1391 			}
1392 			fprintf(stderr, "\n");
1393 			fprintf(stderr, "\n");
1394 		}
1395 		/* verify leading preamble */
1396 
1397 		if (__ops_get_debug_level(__FILE__)) {
1398 			unsigned int    i = 0;
1399 			fprintf(stderr, "\npreamble: ");
1400 			for (i = 0; i < se_ip->decrypt->blocksize + 2; i++)
1401 				fprintf(stderr, " 0x%02x", buf[i]);
1402 			fprintf(stderr, "\n");
1403 		}
1404 		b = se_ip->decrypt->blocksize;
1405 		if (buf[b - 2] != buf[b] || buf[b - 1] != buf[b + 1]) {
1406 			fprintf(stderr, "Bad symmetric decrypt (%02x%02x vs %02x%02x)\n",
1407 				buf[b - 2], buf[b - 1], buf[b], buf[b + 1]);
1408 			OPS_ERROR(errors, OPS_E_PROTO_BAD_SYMMETRIC_DECRYPT, "Bad symmetric decrypt when parsing SE IP packet");
1409 			free(buf);
1410 			return -1;
1411 		}
1412 		/* Verify trailing MDC hash */
1413 
1414 		sz_preamble = se_ip->decrypt->blocksize + 2;
1415 		sz_mdc_hash = OPS_SHA1_HASH_SIZE;
1416 		sz_mdc = 1 + 1 + sz_mdc_hash;
1417 		sz_plaintext = decrypted_region.length - sz_preamble - sz_mdc;
1418 
1419 		preamble = buf;
1420 		plaintext = buf + sz_preamble;
1421 		mdc = plaintext + sz_plaintext;
1422 		mdc_hash = mdc + 2;
1423 
1424 #ifdef DEBUG
1425 		if (__ops_get_debug_level(__FILE__)) {
1426 			unsigned int    i = 0;
1427 
1428 			fprintf(stderr, "\nplaintext (len=%" PRIsize "u): ", sz_plaintext);
1429 			for (i = 0; i < sz_plaintext; i++)
1430 				fprintf(stderr, " 0x%02x", plaintext[i]);
1431 			fprintf(stderr, "\n");
1432 
1433 			fprintf(stderr, "\nmdc (len=%" PRIsize "u): ", sz_mdc);
1434 			for (i = 0; i < sz_mdc; i++)
1435 				fprintf(stderr, " 0x%02x", mdc[i]);
1436 			fprintf(stderr, "\n");
1437 		}
1438 #endif				/* DEBUG */
1439 
1440 		__ops_calc_mdc_hash(preamble, sz_preamble, plaintext, sz_plaintext, &hashed[0]);
1441 
1442 		if (memcmp(mdc_hash, hashed, OPS_SHA1_HASH_SIZE)) {
1443 			OPS_ERROR(errors, OPS_E_V_BAD_HASH, "Bad hash in MDC packet");
1444 			free(buf);
1445 			return 0;
1446 		}
1447 		/* all done with the checks */
1448 		/* now can start reading from the plaintext */
1449 		assert(!se_ip->plaintext);
1450 		se_ip->plaintext = calloc(1, sz_plaintext);
1451 		memcpy(se_ip->plaintext, plaintext, sz_plaintext);
1452 		se_ip->plaintext_available = sz_plaintext;
1453 
1454 		se_ip->passed_checks = 1;
1455 
1456 		free(buf);
1457 	}
1458 	n = len;
1459 	if (n > se_ip->plaintext_available) {
1460 		n = se_ip->plaintext_available;
1461 	}
1462 
1463 	memcpy(dest_, se_ip->plaintext + se_ip->plaintext_offset, n);
1464 	se_ip->plaintext_available -= n;
1465 	se_ip->plaintext_offset += n;
1466 	len -= n;
1467 
1468 	return n;
1469 }
1470 
1471 static void
1472 se_ip_data_destroyer(__ops_reader_info_t * rinfo)
1473 {
1474 	decrypt_se_ip_t *se_ip = __ops_reader_get_arg(rinfo);
1475 	free(se_ip->plaintext);
1476 	free(se_ip);
1477 	/* free(__ops_reader_get_arg(rinfo)); */
1478 }
1479 
1480 /**
1481    \ingroup Internal_Readers_SEIP
1482 */
1483 void
1484 __ops_reader_push_se_ip_data(__ops_parse_info_t * pinfo, __ops_crypt_t * decrypt,
1485 			   __ops_region_t * region)
1486 {
1487 	decrypt_se_ip_t *se_ip = calloc(1, sizeof(*se_ip));
1488 	se_ip->region = region;
1489 	se_ip->decrypt = decrypt;
1490 
1491 	__ops_reader_push(pinfo, se_ip_data_reader, se_ip_data_destroyer, se_ip);
1492 }
1493 
1494 /**
1495    \ingroup Internal_Readers_SEIP
1496  */
1497 void
1498 __ops_reader_pop_se_ip_data(__ops_parse_info_t * pinfo)
1499 {
1500 	/*
1501 	 * decrypt_se_ip_t
1502 	 * *se_ip=__ops_reader_get_arg(__ops_parse_get_rinfo(pinfo));
1503 	 */
1504 	/* free(se_ip); */
1505 	__ops_reader_pop(pinfo);
1506 }
1507 
1508 /**************************************************************************/
1509 
1510 /** Arguments for reader_fd
1511  */
1512 typedef struct mmap_reader_t {
1513 	void		*mem;		/* memory mapped file */
1514 	uint64_t	 size;		/* size of file */
1515 	uint64_t	 offset;	/* current offset in file */
1516 	int		 fd;		/* file descriptor */
1517 } mmap_reader_t;
1518 
1519 
1520 /**
1521  * \ingroup Core_Readers
1522  *
1523  * __ops_reader_fd() attempts to read up to "plength" bytes from the file
1524  * descriptor in "parse_info" into the buffer starting at "dest" using the
1525  * rules contained in "flags"
1526  *
1527  * \param	dest	Pointer to previously allocated buffer
1528  * \param	plength Number of bytes to try to read
1529  * \param	flags	Rules about reading to use
1530  * \param	rinfo	Reader info
1531  * \param	cbinfo	Callback info
1532  *
1533  * \return	n	Number of bytes read
1534  *
1535  * OPS_R_EARLY_EOF and OPS_R_ERROR push errors on the stack
1536  */
1537 static int
1538 fd_reader(void *dest, size_t length, __ops_error_t ** errors,
1539 	  __ops_reader_info_t * rinfo, __ops_parse_cb_info_t * cbinfo)
1540 {
1541 	mmap_reader_t *reader = __ops_reader_get_arg(rinfo);
1542 	int             n = read(reader->fd, dest, length);
1543 
1544 	OPS_USED(cbinfo);
1545 
1546 	if (n == 0)
1547 		return 0;
1548 
1549 	if (n < 0) {
1550 		OPS_SYSTEM_ERROR_1(errors, OPS_E_R_READ_FAILED, "read",
1551 				   "file descriptor %d", reader->fd);
1552 		return -1;
1553 	}
1554 	return n;
1555 }
1556 
1557 static void
1558 reader_fd_destroyer(__ops_reader_info_t * rinfo)
1559 {
1560 	free(__ops_reader_get_arg(rinfo));
1561 }
1562 
1563 /**
1564    \ingroup Core_Readers_First
1565    \brief Starts stack with file reader
1566 */
1567 
1568 void
1569 __ops_reader_set_fd(__ops_parse_info_t * pinfo, int fd)
1570 {
1571 	mmap_reader_t *reader = calloc(1, sizeof(*reader));
1572 
1573 	reader->fd = fd;
1574 	__ops_reader_set(pinfo, fd_reader, reader_fd_destroyer, reader);
1575 }
1576 
1577 /**************************************************************************/
1578 
1579 typedef struct {
1580 	const unsigned char *buffer;
1581 	size_t          length;
1582 	size_t          offset;
1583 }               reader_mem_t;
1584 
1585 static int
1586 mem_reader(void *dest, size_t length, __ops_error_t ** errors,
1587 	   __ops_reader_info_t * rinfo, __ops_parse_cb_info_t * cbinfo)
1588 {
1589 	reader_mem_t *reader = __ops_reader_get_arg(rinfo);
1590 	unsigned        n;
1591 
1592 	OPS_USED(cbinfo);
1593 	OPS_USED(errors);
1594 
1595 	if (reader->offset + length > reader->length)
1596 		n = reader->length - reader->offset;
1597 	else
1598 		n = length;
1599 
1600 	if (n == 0)
1601 		return 0;
1602 
1603 	memcpy(dest, reader->buffer + reader->offset, n);
1604 	reader->offset += n;
1605 
1606 	return n;
1607 }
1608 
1609 static void
1610 mem_destroyer(__ops_reader_info_t * rinfo)
1611 {
1612 	free(__ops_reader_get_arg(rinfo));
1613 }
1614 
1615 /**
1616    \ingroup Core_Readers_First
1617    \brief Starts stack with memory reader
1618 */
1619 
1620 void
1621 __ops_reader_set_memory(__ops_parse_info_t * pinfo, const void *buffer,
1622 		      size_t length)
1623 {
1624 	reader_mem_t *mem = calloc(1, sizeof(*mem));
1625 
1626 	mem->buffer = buffer;
1627 	mem->length = length;
1628 	mem->offset = 0;
1629 	__ops_reader_set(pinfo, mem_reader, mem_destroyer, mem);
1630 }
1631 
1632 /**************************************************************************/
1633 
1634 /**
1635  \ingroup Core_Writers
1636  \brief Create and initialise cinfo and mem; Set for writing to mem
1637  \param cinfo Address where new cinfo pointer will be set
1638  \param mem Address when new mem pointer will be set
1639  \param bufsz Initial buffer size (will automatically be increased when necessary)
1640  \note It is the caller's responsiblity to free cinfo and mem.
1641  \sa __ops_teardown_memory_write()
1642 */
1643 void
1644 __ops_setup_memory_write(__ops_create_info_t ** cinfo, __ops_memory_t ** mem, size_t bufsz)
1645 {
1646 	/*
1647          * initialise needed structures for writing to memory
1648          */
1649 
1650 	*cinfo = __ops_create_info_new();
1651 	*mem = __ops_memory_new();
1652 
1653 	__ops_memory_init(*mem, bufsz);
1654 
1655 	__ops_writer_set_memory(*cinfo, *mem);
1656 }
1657 
1658 /**
1659    \ingroup Core_Writers
1660    \brief Closes writer and frees cinfo and mem
1661    \param cinfo
1662    \param mem
1663    \sa __ops_setup_memory_write()
1664 */
1665 void
1666 __ops_teardown_memory_write(__ops_create_info_t * cinfo, __ops_memory_t * mem)
1667 {
1668 	__ops_writer_close(cinfo);/* new */
1669 	__ops_create_info_delete(cinfo);
1670 	__ops_memory_free(mem);
1671 }
1672 
1673 /**
1674    \ingroup Core_Readers
1675    \brief Create parse_info and sets to read from memory
1676    \param pinfo Address where new parse_info will be set
1677    \param mem Memory to read from
1678    \param arg Reader-specific arg
1679    \param callback Callback to use with reader
1680    \param accumulate Set if we need to accumulate as we read. (Usually false unless doing signature verification)
1681    \note It is the caller's responsiblity to free parse_info
1682    \sa __ops_teardown_memory_read()
1683 */
1684 void
1685 __ops_setup_memory_read(__ops_parse_info_t ** pinfo, __ops_memory_t * mem,
1686 		      void *vp,
1687 		      __ops_parse_cb_return_t callback(const __ops_parser_content_t *, __ops_parse_cb_info_t *),
1688 		      bool accumulate)
1689 {
1690 	/*
1691          * initialise needed structures for reading
1692          */
1693 
1694 	*pinfo = __ops_parse_info_new();
1695 	__ops_parse_cb_set(*pinfo, callback, vp);
1696 	__ops_reader_set_memory(*pinfo,
1697 			      __ops_memory_get_data(mem),
1698 			      __ops_memory_get_length(mem));
1699 
1700 	if (accumulate)
1701 		(*pinfo)->rinfo.accumulate = true;
1702 }
1703 
1704 /**
1705    \ingroup Core_Readers
1706    \brief Frees pinfo and mem
1707    \param pinfo
1708    \param mem
1709    \sa __ops_setup_memory_read()
1710 */
1711 void
1712 __ops_teardown_memory_read(__ops_parse_info_t * pinfo, __ops_memory_t * mem)
1713 {
1714 	__ops_parse_info_delete(pinfo);
1715 	__ops_memory_free(mem);
1716 }
1717 
1718 /**
1719  \ingroup Core_Writers
1720  \brief Create and initialise cinfo and mem; Set for writing to file
1721  \param cinfo Address where new cinfo pointer will be set
1722  \param filename File to write to
1723  \param allow_overwrite Allows file to be overwritten, if set.
1724  \return Newly-opened file descriptor
1725  \note It is the caller's responsiblity to free cinfo and to close fd.
1726  \sa __ops_teardown_file_write()
1727 */
1728 int
1729 __ops_setup_file_write(__ops_create_info_t ** cinfo, const char *filename, bool allow_overwrite)
1730 {
1731 	int             fd = 0;
1732 	int             flags = 0;
1733 
1734 	/*
1735          * initialise needed structures for writing to file
1736          */
1737 
1738 	flags = O_WRONLY | O_CREAT;
1739 	if (allow_overwrite == true)
1740 		flags |= O_TRUNC;
1741 	else
1742 		flags |= O_EXCL;
1743 
1744 #ifdef O_BINARY
1745 	flags |= O_BINARY;
1746 #endif
1747 
1748 	fd = open(filename, flags, 0600);
1749 	if (fd < 0) {
1750 		perror(filename);
1751 		return fd;
1752 	}
1753 	*cinfo = __ops_create_info_new();
1754 
1755 	__ops_writer_set_fd(*cinfo, fd);
1756 
1757 	return fd;
1758 }
1759 
1760 /**
1761    \ingroup Core_Writers
1762    \brief Closes writer, frees info, closes fd
1763    \param cinfo
1764    \param fd
1765 */
1766 void
1767 __ops_teardown_file_write(__ops_create_info_t * cinfo, int fd)
1768 {
1769 	__ops_writer_close(cinfo);
1770 	close(fd);
1771 	__ops_create_info_delete(cinfo);
1772 }
1773 
1774 /**
1775    \ingroup Core_Writers
1776    \brief As __ops_setup_file_write, but appends to file
1777 */
1778 int
1779 __ops_setup_file_append(__ops_create_info_t ** cinfo, const char *filename)
1780 {
1781 	int             fd;
1782 	/*
1783          * initialise needed structures for writing to file
1784          */
1785 
1786 #ifdef O_BINARY
1787 	fd = open(filename, O_WRONLY | O_APPEND | O_BINARY, 0600);
1788 #else
1789 	fd = open(filename, O_WRONLY | O_APPEND, 0600);
1790 #endif
1791 	if (fd < 0) {
1792 		perror(filename);
1793 		return fd;
1794 	}
1795 	*cinfo = __ops_create_info_new();
1796 
1797 	__ops_writer_set_fd(*cinfo, fd);
1798 
1799 	return fd;
1800 }
1801 
1802 /**
1803    \ingroup Core_Writers
1804    \brief As __ops_teardown_file_write()
1805 */
1806 void
1807 __ops_teardown_file_append(__ops_create_info_t * cinfo, int fd)
1808 {
1809 	__ops_teardown_file_write(cinfo, fd);
1810 }
1811 
1812 /**
1813    \ingroup Core_Readers
1814    \brief Creates parse_info, opens file, and sets to read from file
1815    \param pinfo Address where new parse_info will be set
1816    \param filename Name of file to read
1817    \param vp Reader-specific arg
1818    \param callback Callback to use when reading
1819    \param accumulate Set if we need to accumulate as we read. (Usually false unless doing signature verification)
1820    \note It is the caller's responsiblity to free parse_info and to close fd
1821    \sa __ops_teardown_file_read()
1822 */
1823 
1824 int
1825 __ops_setup_file_read(__ops_parse_info_t ** pinfo, const char *filename,
1826 		    void *vp,
1827 		    __ops_parse_cb_return_t callback(const __ops_parser_content_t *, __ops_parse_cb_info_t *),
1828 		    bool accumulate)
1829 {
1830 	int             fd = 0;
1831 	/*
1832          * initialise needed structures for reading
1833          */
1834 
1835 #ifdef O_BINARY
1836 	fd = open(filename, O_RDONLY | O_BINARY);
1837 #else
1838 	fd = open(filename, O_RDONLY);
1839 #endif
1840 	if (fd < 0) {
1841 		perror(filename);
1842 		return fd;
1843 	}
1844 	*pinfo = __ops_parse_info_new();
1845 	__ops_parse_cb_set(*pinfo, callback, vp);
1846 #ifdef USE_MMAP_FOR_FILES
1847 	__ops_reader_set_mmap(*pinfo, fd);
1848 #else
1849 	__ops_reader_set_fd(*pinfo, fd);
1850 #endif
1851 
1852 	if (accumulate) {
1853 		(*pinfo)->rinfo.accumulate = true;
1854 	}
1855 
1856 	if (__ops_get_debug_level(__FILE__)) {
1857 		printf("__ops_setup_file_read: accumulate %d\n", accumulate);
1858 	}
1859 	return fd;
1860 }
1861 
1862 /**
1863    \ingroup Core_Readers
1864    \brief Frees pinfo and closes fd
1865    \param pinfo
1866    \param fd
1867    \sa __ops_setup_file_read()
1868 */
1869 void
1870 __ops_teardown_file_read(__ops_parse_info_t * pinfo, int fd)
1871 {
1872 	close(fd);
1873 	__ops_parse_info_delete(pinfo);
1874 }
1875 
1876 __ops_parse_cb_return_t
1877 literal_data_cb(const __ops_parser_content_t *contents, __ops_parse_cb_info_t *cbinfo)
1878 {
1879 	const __ops_parser_content_union_t *content = &contents->u;
1880 
1881 	OPS_USED(cbinfo);
1882 
1883 	if (__ops_get_debug_level(__FILE__)) {
1884 		printf("literal_data_cb: ");
1885 		__ops_print_packet(contents);
1886 	}
1887 	/* Read data from packet into static buffer */
1888 	switch (contents->tag) {
1889 	case OPS_PTAG_CT_LITERAL_DATA_BODY:
1890 		/* if writer enabled, use it */
1891 		if (cbinfo->cinfo) {
1892 			if (__ops_get_debug_level(__FILE__)) {
1893 				printf("literal_data_cb: length is %d\n",
1894 				  content->literal_data_body.length);
1895 			}
1896 			__ops_write(content->literal_data_body.data,
1897 				  content->literal_data_body.length,
1898 				  cbinfo->cinfo);
1899 		}
1900 		break;
1901 
1902 	case OPS_PTAG_CT_LITERAL_DATA_HEADER:
1903 		/* ignore */
1904 		break;
1905 
1906 	default:
1907 		break;
1908 	}
1909 
1910 	return OPS_RELEASE_MEMORY;
1911 }
1912 
1913 __ops_parse_cb_return_t
1914 pk_session_key_cb(const __ops_parser_content_t * contents, __ops_parse_cb_info_t * cbinfo)
1915 {
1916 	const __ops_parser_content_union_t *content = &contents->u;
1917 
1918 	OPS_USED(cbinfo);
1919 
1920 	if (__ops_get_debug_level(__FILE__)) {
1921 		__ops_print_packet(contents);
1922 	}
1923 	/* Read data from packet into static buffer */
1924 	switch (contents->tag) {
1925 	case OPS_PTAG_CT_PK_SESSION_KEY:
1926 		if (__ops_get_debug_level(__FILE__)) {
1927 			printf("OPS_PTAG_CT_PK_SESSION_KEY\n");
1928 		}
1929 		assert(cbinfo->cryptinfo.keyring);
1930 		cbinfo->cryptinfo.keydata = __ops_keyring_find_key_by_id(cbinfo->cryptinfo.keyring,
1931 					    content->pk_session_key.key_id);
1932 		if (!cbinfo->cryptinfo.keydata)
1933 			break;
1934 		break;
1935 
1936 	default:
1937 		/* return callback_general(contents,cbinfo); */
1938 		break;
1939 	}
1940 
1941 	return OPS_RELEASE_MEMORY;
1942 }
1943 
1944 /**
1945  \ingroup Core_Callbacks
1946 
1947 \brief Callback to get secret key, decrypting if necessary.
1948 
1949 @verbatim
1950  This callback does the following:
1951  * finds the session key in the keyring
1952  * gets a passphrase if required
1953  * decrypts the secret key, if necessary
1954  * sets the secret_key in the content struct
1955 @endverbatim
1956 */
1957 
1958 __ops_parse_cb_return_t
1959 get_secret_key_cb(const __ops_parser_content_t * contents, __ops_parse_cb_info_t * cbinfo)
1960 {
1961 	const __ops_parser_content_union_t *content = &contents->u;
1962 	const __ops_secret_key_t *secret;
1963 	__ops_parser_content_t seckey;
1964 
1965 	OPS_USED(cbinfo);
1966 
1967 	if (__ops_get_debug_level(__FILE__)) {
1968 		__ops_print_packet(contents);
1969 	}
1970 	switch (contents->tag) {
1971 	case OPS_PARSER_CMD_GET_SECRET_KEY:
1972 		cbinfo->cryptinfo.keydata = __ops_keyring_find_key_by_id(cbinfo->cryptinfo.keyring, content->get_secret_key.pk_session_key->key_id);
1973 		if (!cbinfo->cryptinfo.keydata || !__ops_is_key_secret(cbinfo->cryptinfo.keydata))
1974 			return 0;
1975 
1976 		/* now get the key from the data */
1977 		secret = __ops_get_secret_key_from_data(cbinfo->cryptinfo.keydata);
1978 		while (!secret) {
1979 			if (!cbinfo->cryptinfo.passphrase) {
1980 				(void) memset(&seckey, 0x0, sizeof(seckey));
1981 				seckey.u.secret_key_passphrase.passphrase = &cbinfo->cryptinfo.passphrase;
1982 				CALLBACK(cbinfo, OPS_PARSER_CMD_GET_SK_PASSPHRASE, &seckey);
1983 				if (!cbinfo->cryptinfo.passphrase) {
1984 					fprintf(stderr, "can't get passphrase\n");
1985 					assert(0);
1986 				}
1987 			}
1988 			/* then it must be encrypted */
1989 			secret = __ops_decrypt_secret_key_from_data(cbinfo->cryptinfo.keydata, cbinfo->cryptinfo.passphrase);
1990 		}
1991 
1992 		*content->get_secret_key.secret_key = secret;
1993 		break;
1994 
1995 	default:
1996 		/* return callback_general(contents,cbinfo); */
1997 		break;
1998 	}
1999 
2000 	return OPS_RELEASE_MEMORY;
2001 }
2002 
2003 char           *
2004 __ops_malloc_passphrase(char *pp)
2005 {
2006 	size_t          n;
2007 	char           *passphrase;
2008 
2009 	n = strlen(pp);
2010 	if ((passphrase = calloc(1, n + 1)) != NULL) {
2011 		(void) memcpy(passphrase, pp, n);
2012 		passphrase[n] = 0x0;
2013 	}
2014 	return passphrase;
2015 }
2016 
2017 /**
2018  \ingroup HighLevel_Callbacks
2019  \brief Callback to use when you need to prompt user for passphrase
2020  \param contents
2021  \param cbinfo
2022 */
2023 __ops_parse_cb_return_t
2024 get_passphrase_cb(const __ops_parser_content_t *contents, __ops_parse_cb_info_t *cbinfo)
2025 {
2026 	const __ops_parser_content_union_t *content = &contents->u;
2027 
2028 	OPS_USED(cbinfo);
2029 	if (__ops_get_debug_level(__FILE__)) {
2030 		__ops_print_packet(contents);
2031 	}
2032 	switch (contents->tag) {
2033 	case OPS_PARSER_CMD_GET_SK_PASSPHRASE:
2034 		*(content->secret_key_passphrase.passphrase) =
2035 			__ops_malloc_passphrase(getpass("netpgp passphrase: "));
2036 		return OPS_KEEP_MEMORY;
2037 
2038 	default:
2039 		/* return callback_general(contents,cbinfo); */
2040 		break;
2041 	}
2042 
2043 	return OPS_RELEASE_MEMORY;
2044 }
2045 
2046 bool
2047 __ops_reader_set_accumulate(__ops_parse_info_t * pinfo, bool state)
2048 {
2049 	pinfo->rinfo.accumulate = state;
2050 	return state;
2051 }
2052 
2053 /**************************************************************************/
2054 
2055 static int
2056 hash_reader(void *dest, size_t length, __ops_error_t ** errors,
2057 	    __ops_reader_info_t * rinfo, __ops_parse_cb_info_t * cbinfo)
2058 {
2059 	__ops_hash_t     *hash = __ops_reader_get_arg(rinfo);
2060 	int             r = __ops_stacked_read(dest, length, errors, rinfo, cbinfo);
2061 
2062 	if (r <= 0)
2063 		return r;
2064 
2065 	hash->add(hash, dest, r);
2066 
2067 	return r;
2068 }
2069 
2070 /**
2071    \ingroup Internal_Readers_Hash
2072    \brief Push hashed data reader on stack
2073 */
2074 void
2075 __ops_reader_push_hash(__ops_parse_info_t * pinfo, __ops_hash_t * hash)
2076 {
2077 	hash->init(hash);
2078 	__ops_reader_push(pinfo, hash_reader, NULL, hash);
2079 }
2080 
2081 /**
2082    \ingroup Internal_Readers_Hash
2083    \brief Pop hashed data reader from stack
2084 */
2085 void
2086 __ops_reader_pop_hash(__ops_parse_info_t * pinfo)
2087 {
2088 	__ops_reader_pop(pinfo);
2089 }
2090 
2091 /* read memory from the previously mmap-ed file */
2092 static int
2093 mmap_reader(void *dest, size_t length, __ops_error_t **errors,
2094 	  __ops_reader_info_t *rinfo, __ops_parse_cb_info_t *cbinfo)
2095 {
2096 	mmap_reader_t	*mem = __ops_reader_get_arg(rinfo);
2097 	char		*cmem = mem->mem;
2098 	int		 n = MIN(length, mem->size - mem->offset);
2099 
2100 	OPS_USED(cbinfo);
2101 	if (n > 0) {
2102 		(void) memcpy(dest, &cmem[mem->offset], n);
2103 		mem->offset += n;
2104 	}
2105 	return n;
2106 }
2107 
2108 /* tear down the mmap, close the fd */
2109 static void
2110 mmap_destroyer(__ops_reader_info_t * rinfo)
2111 {
2112 	mmap_reader_t *mem = __ops_reader_get_arg(rinfo);
2113 
2114 	(void) munmap(mem->mem, mem->size);
2115 	(void) close(mem->fd);
2116 	free(__ops_reader_get_arg(rinfo));
2117 }
2118 
2119 /* set up the file to use mmap-ed memory if available, file IO otherwise */
2120 void
2121 __ops_reader_set_mmap(__ops_parse_info_t * pinfo, int fd)
2122 {
2123 	mmap_reader_t	*mem = calloc(1, sizeof(*mem));
2124 	struct stat	 st;
2125 
2126 	if (fstat(fd, &st) == 0) {
2127 		mem->size = st.st_size;
2128 		mem->offset = 0;
2129 		mem->fd = fd;
2130 		mem->mem = mmap(NULL, (size_t)st.st_size, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, 0);
2131 		if (mem->mem == MAP_FAILED) {
2132 			__ops_reader_set(pinfo, fd_reader, reader_fd_destroyer, mem);
2133 		} else {
2134 			__ops_reader_set(pinfo, mmap_reader, mmap_destroyer, mem);
2135 		}
2136 	}
2137 }
2138