1 /*-
2  * Copyright (c) 2009 The NetBSD Foundation, Inc.
3  * All rights reserved.
4  *
5  * This code is derived from software contributed to The NetBSD Foundation
6  * by Alistair Crooks (agc@NetBSD.org)
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
18  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
21  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  */
29 /*
30  * Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
31  * All rights reserved.
32  * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
33  * their moral rights under the UK Copyright Design and Patents Act 1988 to
34  * be recorded as the authors of this copyright work.
35  *
36  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
37  * use this file except in compliance with the License.
38  *
39  * You may obtain a copy of the License at
40  *     http://www.apache.org/licenses/LICENSE-2.0
41  *
42  * Unless required by applicable law or agreed to in writing, software
43  * distributed under the License is distributed on an "AS IS" BASIS,
44  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
45  *
46  * See the License for the specific language governing permissions and
47  * limitations under the License.
48  */
49 
50 /** \file
51  * This file contains the base functions used by the writers.
52  */
53 #include "config.h"
54 
55 #ifdef HAVE_SYS_CDEFS_H
56 #include <sys/cdefs.h>
57 #endif
58 
59 #if defined(__NetBSD__)
60 __COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved.");
61 __RCSID("$NetBSD: writer.c,v 1.33 2012/03/05 02:20:18 christos Exp $");
62 #endif
63 
64 #include <sys/types.h>
65 
66 #include <stdlib.h>
67 #include <string.h>
68 
69 #ifdef HAVE_UNISTD_H
70 #include <unistd.h>
71 #endif
72 
73 #ifdef HAVE_OPENSSL_CAST_H
74 #include <openssl/cast.h>
75 #endif
76 
77 #include "create.h"
78 #include "writer.h"
79 #include "keyring.h"
80 #include "signature.h"
81 #include "packet.h"
82 #include "packet-parse.h"
83 #include "readerwriter.h"
84 #include "memory.h"
85 #include "netpgpdefs.h"
86 #include "version.h"
87 #include "netpgpdigest.h"
88 
89 
90 /*
91  * return 1 if OK, otherwise 0
92  */
93 static unsigned
base_write(pgp_output_t * out,const void * src,unsigned len)94 base_write(pgp_output_t *out, const void *src, unsigned len)
95 {
96 	return out->writer.writer(src, len, &out->errors, &out->writer);
97 }
98 
99 /**
100  * \ingroup Core_WritePackets
101  *
102  * \param src
103  * \param len
104  * \param output
105  * \return 1 if OK, otherwise 0
106  */
107 
108 unsigned
pgp_write(pgp_output_t * output,const void * src,unsigned len)109 pgp_write(pgp_output_t *output, const void *src, unsigned len)
110 {
111 	return base_write(output, src, len);
112 }
113 
114 /**
115  * \ingroup Core_WritePackets
116  * \param n
117  * \param len
118  * \param output
119  * \return 1 if OK, otherwise 0
120  */
121 
122 unsigned
pgp_write_scalar(pgp_output_t * output,unsigned n,unsigned len)123 pgp_write_scalar(pgp_output_t *output, unsigned n, unsigned len)
124 {
125 	uint8_t   c;
126 
127 	while (len-- > 0) {
128 		c = n >> (len * 8);
129 		if (!base_write(output, &c, 1)) {
130 			return 0;
131 		}
132 	}
133 	return 1;
134 }
135 
136 /**
137  * \ingroup Core_WritePackets
138  * \param bn
139  * \param output
140  * \return 1 if OK, otherwise 0
141  */
142 
143 unsigned
pgp_write_mpi(pgp_output_t * output,const BIGNUM * bn)144 pgp_write_mpi(pgp_output_t *output, const BIGNUM *bn)
145 {
146 	unsigned	bits;
147 	uint8_t		buf[NETPGP_BUFSIZ];
148 
149 	bits = (unsigned)BN_num_bits(bn);
150 	if (bits > 65535) {
151 		(void) fprintf(stderr, "pgp_write_mpi: too large %u\n", bits);
152 		return 0;
153 	}
154 	BN_bn2bin(bn, buf);
155 	return pgp_write_scalar(output, bits, 2) &&
156 		pgp_write(output, buf, (bits + 7) / 8);
157 }
158 
159 /**
160  * \ingroup Core_WritePackets
161  * \param tag
162  * \param output
163  * \return 1 if OK, otherwise 0
164  */
165 
166 unsigned
pgp_write_ptag(pgp_output_t * output,pgp_content_enum tag)167 pgp_write_ptag(pgp_output_t *output, pgp_content_enum tag)
168 {
169 	uint8_t   c;
170 
171 	c = tag | PGP_PTAG_ALWAYS_SET | PGP_PTAG_NEW_FORMAT;
172 	return base_write(output, &c, 1);
173 }
174 
175 /**
176  * \ingroup Core_WritePackets
177  * \param len
178  * \param output
179  * \return 1 if OK, otherwise 0
180  */
181 
182 unsigned
pgp_write_length(pgp_output_t * output,unsigned len)183 pgp_write_length(pgp_output_t *output, unsigned len)
184 {
185 	uint8_t   c[2];
186 
187 	if (len < 192) {
188 		c[0] = len;
189 		return base_write(output, c, 1);
190 	}
191 	if (len < 8192 + 192) {
192 		c[0] = ((len - 192) >> 8) + 192;
193 		c[1] = (len - 192) % 256;
194 		return base_write(output, c, 2);
195 	}
196 	return pgp_write_scalar(output, 0xff, 1) &&
197 		pgp_write_scalar(output, len, 4);
198 }
199 
200 /*
201  * Note that we finalise from the top down, so we don't use writers below
202  * that have already been finalised
203  */
204 unsigned
pgp_writer_info_finalise(pgp_error_t ** errors,pgp_writer_t * writer)205 pgp_writer_info_finalise(pgp_error_t **errors, pgp_writer_t *writer)
206 {
207 	unsigned   ret = 1;
208 
209 	if (writer->finaliser) {
210 		ret = writer->finaliser(errors, writer);
211 		writer->finaliser = NULL;
212 	}
213 	if (writer->next && !pgp_writer_info_finalise(errors, writer->next)) {
214 		writer->finaliser = NULL;
215 		return 0;
216 	}
217 	return ret;
218 }
219 
220 void
pgp_writer_info_delete(pgp_writer_t * writer)221 pgp_writer_info_delete(pgp_writer_t *writer)
222 {
223 	/* we should have finalised before deleting */
224 	if (writer->finaliser) {
225 		(void) fprintf(stderr, "pgp_writer_info_delete: not done\n");
226 		return;
227 	}
228 	if (writer->next) {
229 		pgp_writer_info_delete(writer->next);
230 		free(writer->next);
231 		writer->next = NULL;
232 	}
233 	if (writer->destroyer) {
234 		writer->destroyer(writer);
235 		writer->destroyer = NULL;
236 	}
237 	writer->writer = NULL;
238 }
239 
240 /**
241  * \ingroup Core_Writers
242  *
243  * Set a writer in output. There should not be another writer set.
244  *
245  * \param output The output structure
246  * \param writer
247  * \param finaliser
248  * \param destroyer
249  * \param arg The argument for the writer and destroyer
250  */
251 void
pgp_writer_set(pgp_output_t * output,pgp_writer_func_t * writer,pgp_writer_finaliser_t * finaliser,pgp_writer_destroyer_t * destroyer,void * arg)252 pgp_writer_set(pgp_output_t *output,
253 	       pgp_writer_func_t *writer,
254 	       pgp_writer_finaliser_t *finaliser,
255 	       pgp_writer_destroyer_t *destroyer,
256 	       void *arg)
257 {
258 	if (output->writer.writer) {
259 		(void) fprintf(stderr, "pgp_writer_set: already set\n");
260 	} else {
261 		output->writer.writer = writer;
262 		output->writer.finaliser = finaliser;
263 		output->writer.destroyer = destroyer;
264 		output->writer.arg = arg;
265 	}
266 }
267 
268 /**
269  * \ingroup Core_Writers
270  *
271  * Push a writer in output. There must already be another writer set.
272  *
273  * \param output The output structure
274  * \param writer
275  * \param finaliser
276  * \param destroyer
277  * \param arg The argument for the writer and destroyer
278  */
279 void
pgp_writer_push(pgp_output_t * output,pgp_writer_func_t * writer,pgp_writer_finaliser_t * finaliser,pgp_writer_destroyer_t * destroyer,void * arg)280 pgp_writer_push(pgp_output_t *output,
281 		pgp_writer_func_t *writer,
282 		pgp_writer_finaliser_t *finaliser,
283 		pgp_writer_destroyer_t *destroyer,
284 		void *arg)
285 {
286 	pgp_writer_t *copy;
287 
288 	if ((copy = calloc(1, sizeof(*copy))) == NULL) {
289 		(void) fprintf(stderr, "pgp_writer_push: bad alloc\n");
290 	} else if (output->writer.writer == NULL) {
291 		(void) fprintf(stderr, "pgp_writer_push: no orig writer\n");
292 	} else {
293 		*copy = output->writer;
294 		output->writer.next = copy;
295 
296 		output->writer.writer = writer;
297 		output->writer.finaliser = finaliser;
298 		output->writer.destroyer = destroyer;
299 		output->writer.arg = arg;
300 	}
301 }
302 
303 void
pgp_writer_pop(pgp_output_t * output)304 pgp_writer_pop(pgp_output_t *output)
305 {
306 	pgp_writer_t *next;
307 
308 	/* Make sure the finaliser has been called. */
309 	if (output->writer.finaliser) {
310 		(void) fprintf(stderr,
311 			"pgp_writer_pop: finaliser not called\n");
312 	} else if (output->writer.next == NULL) {
313 		(void) fprintf(stderr,
314 			"pgp_writer_pop: not a stacked writer\n");
315 	} else {
316 		if (output->writer.destroyer) {
317 			output->writer.destroyer(&output->writer);
318 		}
319 		next = output->writer.next;
320 		output->writer = *next;
321 		free(next);
322 	}
323 }
324 
325 /**
326  * \ingroup Core_Writers
327  *
328  * Close the writer currently set in output.
329  *
330  * \param output The output structure
331  */
332 unsigned
pgp_writer_close(pgp_output_t * output)333 pgp_writer_close(pgp_output_t *output)
334 {
335 	unsigned   ret;
336 
337 	ret = pgp_writer_info_finalise(&output->errors, &output->writer);
338 	pgp_writer_info_delete(&output->writer);
339 	return ret;
340 }
341 
342 /**
343  * \ingroup Core_Writers
344  *
345  * Get the arg supplied to pgp_createinfo_set_writer().
346  *
347  * \param writer The writer_info structure
348  * \return The arg
349  */
350 void           *
pgp_writer_get_arg(pgp_writer_t * writer)351 pgp_writer_get_arg(pgp_writer_t *writer)
352 {
353 	return writer->arg;
354 }
355 
356 /**
357  * \ingroup Core_Writers
358  *
359  * Write to the next writer down in the stack.
360  *
361  * \param src The data to write.
362  * \param len The length of src.
363  * \param errors A place to store errors.
364  * \param writer The writer_info structure.
365  * \return Success - if 0, then errors should contain the error.
366  */
367 static unsigned
stacked_write(pgp_writer_t * writer,const void * src,unsigned len,pgp_error_t ** errors)368 stacked_write(pgp_writer_t *writer, const void *src, unsigned len,
369 		  pgp_error_t ** errors)
370 {
371 	return writer->next->writer(src, len, errors, writer->next);
372 }
373 
374 /**
375  * \ingroup Core_Writers
376  *
377  * Free the arg. Many writers just have a calloc()ed lump of storage, this
378  * function releases it.
379  *
380  * \param writer the info structure.
381  */
382 static void
generic_destroyer(pgp_writer_t * writer)383 generic_destroyer(pgp_writer_t *writer)
384 {
385 	free(pgp_writer_get_arg(writer));
386 }
387 
388 /**
389  * \ingroup Core_Writers
390  *
391  * A writer that just writes to the next one down. Useful for when you
392  * want to insert just a finaliser into the stack.
393  */
394 unsigned
pgp_writer_passthrough(const uint8_t * src,unsigned len,pgp_error_t ** errors,pgp_writer_t * writer)395 pgp_writer_passthrough(const uint8_t *src,
396 		       unsigned len,
397 		       pgp_error_t **errors,
398 		       pgp_writer_t *writer)
399 {
400 	return stacked_write(writer, src, len, errors);
401 }
402 
403 /**************************************************************************/
404 
405 /**
406  * \struct dashesc_t
407  */
408 typedef struct {
409 	unsigned   		 seen_nl:1;
410 	unsigned		 seen_cr:1;
411 	pgp_create_sig_t	*sig;
412 	pgp_memory_t		*trailing;
413 } dashesc_t;
414 
415 static unsigned
dash_esc_writer(const uint8_t * src,unsigned len,pgp_error_t ** errors,pgp_writer_t * writer)416 dash_esc_writer(const uint8_t *src,
417 		    unsigned len,
418 		    pgp_error_t **errors,
419 		    pgp_writer_t *writer)
420 {
421 	dashesc_t	*dash = pgp_writer_get_arg(writer);
422 	unsigned        n;
423 
424 	if (pgp_get_debug_level(__FILE__)) {
425 		unsigned    i = 0;
426 
427 		(void) fprintf(stderr, "dash_esc_writer writing %u:\n", len);
428 		for (i = 0; i < len; i++) {
429 			fprintf(stderr, "0x%02x ", src[i]);
430 			if (((i + 1) % 16) == 0) {
431 				(void) fprintf(stderr, "\n");
432 			} else if (((i + 1) % 8) == 0) {
433 				(void) fprintf(stderr, "  ");
434 			}
435 		}
436 		(void) fprintf(stderr, "\n");
437 	}
438 	/* XXX: make this efficient */
439 	for (n = 0; n < len; ++n) {
440 		unsigned        l;
441 
442 		if (dash->seen_nl) {
443 			if (src[n] == '-' &&
444 			    !stacked_write(writer, "- ", 2, errors)) {
445 				return 0;
446 			}
447 			dash->seen_nl = 0;
448 		}
449 		dash->seen_nl = src[n] == '\n';
450 
451 		if (dash->seen_nl && !dash->seen_cr) {
452 			if (!stacked_write(writer, "\r", 1, errors)) {
453 				return 0;
454 			}
455 			pgp_sig_add_data(dash->sig, "\r", 1);
456 		}
457 		dash->seen_cr = src[n] == '\r';
458 
459 		if (!stacked_write(writer, &src[n], 1, errors)) {
460 			return 0;
461 		}
462 
463 		/* trailing whitespace isn't included in the signature */
464 		if (src[n] == ' ' || src[n] == '\t') {
465 			pgp_memory_add(dash->trailing, &src[n], 1);
466 		} else {
467 			if ((l = (unsigned)pgp_mem_len(dash->trailing)) != 0) {
468 				if (!dash->seen_nl && !dash->seen_cr) {
469 					pgp_sig_add_data(dash->sig,
470 					pgp_mem_data(dash->trailing), l);
471 				}
472 				pgp_memory_clear(dash->trailing);
473 			}
474 			pgp_sig_add_data(dash->sig, &src[n], 1);
475 		}
476 	}
477 	return 1;
478 }
479 
480 /**
481  * \param writer
482  */
483 static void
dash_escaped_destroyer(pgp_writer_t * writer)484 dash_escaped_destroyer(pgp_writer_t *writer)
485 {
486 	dashesc_t	*dash;
487 
488 	dash = pgp_writer_get_arg(writer);
489 	pgp_memory_free(dash->trailing);
490 	free(dash);
491 }
492 
493 /**
494  * \ingroup Core_WritersNext
495  * \brief Push Clearsigned Writer onto stack
496  * \param output
497  * \param sig
498  */
499 unsigned
pgp_writer_push_clearsigned(pgp_output_t * output,pgp_create_sig_t * sig)500 pgp_writer_push_clearsigned(pgp_output_t *output, pgp_create_sig_t *sig)
501 {
502 	static const char     header[] =
503 		"-----BEGIN PGP SIGNED MESSAGE-----\r\nHash: ";
504 	const char     *hash;
505 	dashesc_t      *dash;
506 	unsigned	ret;
507 
508 	hash = pgp_text_from_hash(pgp_sig_get_hash(sig));
509 	if ((dash = calloc(1, sizeof(*dash))) == NULL) {
510 		PGP_ERROR_1(&output->errors, PGP_E_W, "%s", "Bad alloc");
511 		return 0;
512 	}
513 	ret = (pgp_write(output, header, (unsigned)(sizeof(header) - 1)) &&
514 		pgp_write(output, hash, (unsigned)strlen(hash)) &&
515 		pgp_write(output, "\r\n\r\n", 4));
516 
517 	if (ret == 0) {
518 		PGP_ERROR_1(&output->errors, PGP_E_W, "%s",
519 			"Error pushing clearsigned header");
520 		free(dash);
521 		return ret;
522 	}
523 	dash->seen_nl = 1;
524 	dash->sig = sig;
525 	dash->trailing = pgp_memory_new();
526 	pgp_writer_push(output, dash_esc_writer, NULL,
527 			dash_escaped_destroyer, dash);
528 	return ret;
529 }
530 
531 
532 /**
533  * \struct base64_t
534  */
535 typedef struct {
536 	unsigned	pos;
537 	uint8_t		t;
538 	unsigned	checksum;
539 } base64_t;
540 
541 static const char     b64map[] =
542 	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
543 
544 static unsigned
base64_writer(const uint8_t * src,unsigned len,pgp_error_t ** errors,pgp_writer_t * writer)545 base64_writer(const uint8_t *src,
546 	      unsigned len,
547 	      pgp_error_t **errors,
548 	      pgp_writer_t *writer)
549 {
550 	base64_t	*base64;
551 	unsigned         n;
552 
553 	base64 = pgp_writer_get_arg(writer);
554 	for (n = 0; n < len;) {
555 		base64->checksum = pgp_crc24(base64->checksum, src[n]);
556 		if (base64->pos == 0) {
557 			/* XXXXXX00 00000000 00000000 */
558 			if (!stacked_write(writer,
559 					&b64map[(unsigned)src[n] >> 2],
560 					1, errors)) {
561 				return 0;
562 			}
563 
564 			/* 000000XX xxxx0000 00000000 */
565 			base64->t = (src[n++] & 3) << 4;
566 			base64->pos = 1;
567 		} else if (base64->pos == 1) {
568 			/* 000000xx XXXX0000 00000000 */
569 			base64->t += (unsigned)src[n] >> 4;
570 			if (!stacked_write(writer, &b64map[base64->t], 1,
571 					errors)) {
572 				return 0;
573 			}
574 
575 			/* 00000000 0000XXXX xx000000 */
576 			base64->t = (src[n++] & 0xf) << 2;
577 			base64->pos = 2;
578 		} else if (base64->pos == 2) {
579 			/* 00000000 0000xxxx XX000000 */
580 			base64->t += (unsigned)src[n] >> 6;
581 			if (!stacked_write(writer, &b64map[base64->t], 1,
582 					errors)) {
583 				return 0;
584 			}
585 
586 			/* 00000000 00000000 00XXXXXX */
587 			if (!stacked_write(writer,
588 					&b64map[src[n++] & 0x3f], 1, errors)) {
589 				return 0;
590 			}
591 
592 			base64->pos = 0;
593 		}
594 	}
595 
596 	return 1;
597 }
598 
599 static unsigned
sig_finaliser(pgp_error_t ** errors,pgp_writer_t * writer)600 sig_finaliser(pgp_error_t **errors, pgp_writer_t *writer)
601 {
602 	static const char	trail[] = "\r\n-----END PGP SIGNATURE-----\r\n";
603 	base64_t		*base64;
604 	uint8_t			c[3];
605 
606 	base64 = pgp_writer_get_arg(writer);
607 	if (base64->pos) {
608 		if (!stacked_write(writer, &b64map[base64->t], 1, errors)) {
609 			return 0;
610 		}
611 		if (base64->pos == 1 &&
612 		    !stacked_write(writer, "==", 2, errors)) {
613 			return 0;
614 		}
615 		if (base64->pos == 2 &&
616 		    !stacked_write(writer, "=", 1, errors)) {
617 			return 0;
618 		}
619 	}
620 	/* Ready for the checksum */
621 	if (!stacked_write(writer, "\r\n=", 3, errors)) {
622 		return 0;
623 	}
624 
625 	base64->pos = 0;		/* get ready to write the checksum */
626 
627 	c[0] = base64->checksum >> 16;
628 	c[1] = base64->checksum >> 8;
629 	c[2] = base64->checksum;
630 	/* push the checksum through our own writer */
631 	if (!base64_writer(c, 3, errors, writer)) {
632 		return 0;
633 	}
634 
635 	return stacked_write(writer, trail, (unsigned)(sizeof(trail) - 1), errors);
636 }
637 
638 /**
639  * \struct linebreak_t
640  */
641 typedef struct {
642 	unsigned        pos;
643 } linebreak_t;
644 
645 #define BREAKPOS	76
646 
647 static unsigned
linebreak_writer(const uint8_t * src,unsigned len,pgp_error_t ** errors,pgp_writer_t * writer)648 linebreak_writer(const uint8_t *src,
649 		 unsigned len,
650 		 pgp_error_t **errors,
651 		 pgp_writer_t *writer)
652 {
653 	linebreak_t	*linebreak;
654 	unsigned         n;
655 
656 	linebreak = pgp_writer_get_arg(writer);
657 	for (n = 0; n < len; ++n, ++linebreak->pos) {
658 		if (src[n] == '\r' || src[n] == '\n') {
659 			linebreak->pos = 0;
660 		}
661 		if (linebreak->pos == BREAKPOS) {
662 			if (!stacked_write(writer, "\r\n", 2, errors)) {
663 				return 0;
664 			}
665 			linebreak->pos = 0;
666 		}
667 		if (!stacked_write(writer, &src[n], 1, errors)) {
668 			return 0;
669 		}
670 	}
671 
672 	return 1;
673 }
674 
675 /**
676  * \ingroup Core_WritersNext
677  * \brief Push armoured signature on stack
678  * \param output
679  */
680 unsigned
pgp_writer_use_armored_sig(pgp_output_t * output)681 pgp_writer_use_armored_sig(pgp_output_t *output)
682 {
683 	static const char     header[] =
684 			"\r\n-----BEGIN PGP SIGNATURE-----\r\nVersion: "
685 			NETPGP_VERSION_STRING
686 			"\r\n\r\n";
687 	linebreak_t	*linebreak;
688 	base64_t   	*base64;
689 
690 	pgp_writer_pop(output);
691 	if (pgp_write(output, header, (unsigned)(sizeof(header) - 1)) == 0) {
692 		PGP_ERROR_1(&output->errors, PGP_E_W, "%s",
693 			"Error switching to armoured signature");
694 		return 0;
695 	}
696 	if ((linebreak = calloc(1, sizeof(*linebreak))) == NULL) {
697 		PGP_ERROR_1(&output->errors, PGP_E_W, "%s",
698 			"pgp_writer_use_armored_sig: Bad alloc");
699 		return 0;
700 	}
701 	pgp_writer_push(output, linebreak_writer, NULL,
702 			generic_destroyer,
703 			linebreak);
704 	base64 = calloc(1, sizeof(*base64));
705 	if (!base64) {
706 		PGP_MEMORY_ERROR(&output->errors);
707 		return 0;
708 	}
709 	base64->checksum = CRC24_INIT;
710 	pgp_writer_push(output, base64_writer, sig_finaliser,
711 			generic_destroyer, base64);
712 	return 1;
713 }
714 
715 static unsigned
armoured_message_finaliser(pgp_error_t ** errors,pgp_writer_t * writer)716 armoured_message_finaliser(pgp_error_t **errors, pgp_writer_t *writer)
717 {
718 	/* TODO: This is same as sig_finaliser apart from trailer. */
719 	static const char	 trailer[] =
720 			"\r\n-----END PGP MESSAGE-----\r\n";
721 	base64_t		*base64;
722 	uint8_t			 c[3];
723 
724 	base64 = pgp_writer_get_arg(writer);
725 	if (base64->pos) {
726 		if (!stacked_write(writer, &b64map[base64->t], 1, errors)) {
727 			return 0;
728 		}
729 		if (base64->pos == 1 &&
730 		    !stacked_write(writer, "==", 2, errors)) {
731 			return 0;
732 		}
733 		if (base64->pos == 2 &&
734 		    !stacked_write(writer, "=", 1, errors)) {
735 			return 0;
736 		}
737 	}
738 	/* Ready for the checksum */
739 	if (!stacked_write(writer, "\r\n=", 3, errors)) {
740 		return 0;
741 	}
742 
743 	base64->pos = 0;		/* get ready to write the checksum */
744 
745 	c[0] = base64->checksum >> 16;
746 	c[1] = base64->checksum >> 8;
747 	c[2] = base64->checksum;
748 	/* push the checksum through our own writer */
749 	if (!base64_writer(c, 3, errors, writer)) {
750 		return 0;
751 	}
752 
753 	return stacked_write(writer, trailer, (unsigned)strlen(trailer), errors);
754 }
755 
756 /**
757  \ingroup Core_WritersNext
758  \brief Write a PGP MESSAGE
759  \todo replace with generic function
760 */
761 void
pgp_writer_push_armor_msg(pgp_output_t * output)762 pgp_writer_push_armor_msg(pgp_output_t *output)
763 {
764 	static const char	 header[] = "-----BEGIN PGP MESSAGE-----\r\n";
765 	linebreak_t		*linebreak;
766 	base64_t		*base64;
767 
768 	pgp_write(output, header, (unsigned)(sizeof(header) - 1));
769 	pgp_write(output, "\r\n", 2);
770 	if ((linebreak = calloc(1, sizeof(*linebreak))) == NULL) {
771 		(void) fprintf(stderr,
772 			"pgp_writer_push_armor_msg: bad lb alloc\n");
773 		return;
774 	}
775 	pgp_writer_push(output, linebreak_writer, NULL,
776 		generic_destroyer,
777 		linebreak);
778 	if ((base64 = calloc(1, sizeof(*base64))) == NULL) {
779 		(void) fprintf(stderr,
780 			"pgp_writer_push_armor_msg: bad alloc\n");
781 		return;
782 	}
783 	base64->checksum = CRC24_INIT;
784 	pgp_writer_push(output, base64_writer,
785 		armoured_message_finaliser, generic_destroyer,
786 		base64);
787 }
788 
789 static unsigned
armoured_finaliser(pgp_armor_type_t type,pgp_error_t ** errors,pgp_writer_t * writer)790 armoured_finaliser(pgp_armor_type_t type,
791 			pgp_error_t **errors,
792 			pgp_writer_t *writer)
793 {
794 	static const char     tail_pubkey[] =
795 			"\r\n-----END PGP PUBLIC KEY BLOCK-----\r\n";
796 	static const char     tail_private_key[] =
797 			"\r\n-----END PGP PRIVATE KEY BLOCK-----\r\n";
798 	const char		*tail = NULL;
799 	unsigned		 tailsize = 0;
800 	base64_t		*base64;
801 	uint8_t		 	 c[3];
802 
803 	switch (type) {
804 	case PGP_PGP_PUBLIC_KEY_BLOCK:
805 		tail = tail_pubkey;
806 		tailsize = sizeof(tail_pubkey) - 1;
807 		break;
808 
809 	case PGP_PGP_PRIVATE_KEY_BLOCK:
810 		tail = tail_private_key;
811 		tailsize = sizeof(tail_private_key) - 1;
812 		break;
813 
814 	default:
815 		(void) fprintf(stderr, "armoured_finaliser: unusual type\n");
816 		return 0;
817 	}
818 	base64 = pgp_writer_get_arg(writer);
819 	if (base64->pos) {
820 		if (!stacked_write(writer, &b64map[base64->t], 1,
821 					errors)) {
822 			return 0;
823 		}
824 		if (base64->pos == 1 && !stacked_write(writer, "==", 2,
825 				errors)) {
826 			return 0;
827 		}
828 		if (base64->pos == 2 && !stacked_write(writer, "=", 1,
829 				errors)) {
830 			return 0;
831 		}
832 	}
833 	/* Ready for the checksum */
834 	if (!stacked_write(writer, "\r\n=", 3, errors)) {
835 		return 0;
836 	}
837 	base64->pos = 0;		/* get ready to write the checksum */
838 	c[0] = base64->checksum >> 16;
839 	c[1] = base64->checksum >> 8;
840 	c[2] = base64->checksum;
841 	/* push the checksum through our own writer */
842 	if (!base64_writer(c, 3, errors, writer)) {
843 		return 0;
844 	}
845 	return stacked_write(writer, tail, tailsize, errors);
846 }
847 
848 static unsigned
armored_pubkey_fini(pgp_error_t ** errors,pgp_writer_t * writer)849 armored_pubkey_fini(pgp_error_t **errors, pgp_writer_t *writer)
850 {
851 	return armoured_finaliser(PGP_PGP_PUBLIC_KEY_BLOCK, errors, writer);
852 }
853 
854 static unsigned
armored_privkey_fini(pgp_error_t ** errors,pgp_writer_t * writer)855 armored_privkey_fini(pgp_error_t **errors, pgp_writer_t *writer)
856 {
857 	return armoured_finaliser(PGP_PGP_PRIVATE_KEY_BLOCK, errors, writer);
858 }
859 
860 /* \todo use this for other armoured types */
861 /**
862  \ingroup Core_WritersNext
863  \brief Push Armoured Writer on stack (generic)
864 */
865 void
pgp_writer_push_armoured(pgp_output_t * output,pgp_armor_type_t type)866 pgp_writer_push_armoured(pgp_output_t *output, pgp_armor_type_t type)
867 {
868 	static char     hdr_pubkey[] =
869 			"-----BEGIN PGP PUBLIC KEY BLOCK-----\r\nVersion: "
870 			NETPGP_VERSION_STRING
871 			"\r\n\r\n";
872 	static char     hdr_private_key[] =
873 			"-----BEGIN PGP PRIVATE KEY BLOCK-----\r\nVersion: "
874 			NETPGP_VERSION_STRING
875 			"\r\n\r\n";
876 	unsigned    	 hdrsize = 0;
877 	unsigned	(*finaliser) (pgp_error_t **, pgp_writer_t *);
878 	base64_t	*base64;
879 	linebreak_t	*linebreak;
880 	char           *header = NULL;
881 
882 	finaliser = NULL;
883 	switch (type) {
884 	case PGP_PGP_PUBLIC_KEY_BLOCK:
885 		header = hdr_pubkey;
886 		hdrsize = sizeof(hdr_pubkey) - 1;
887 		finaliser = armored_pubkey_fini;
888 		break;
889 
890 	case PGP_PGP_PRIVATE_KEY_BLOCK:
891 		header = hdr_private_key;
892 		hdrsize = sizeof(hdr_private_key) - 1;
893 		finaliser = armored_privkey_fini;
894 		break;
895 
896 	default:
897 		(void) fprintf(stderr,
898 			"pgp_writer_push_armoured: unusual type\n");
899 		return;
900 	}
901 	if ((linebreak = calloc(1, sizeof(*linebreak))) == NULL) {
902 		(void) fprintf(stderr,
903 			"pgp_writer_push_armoured: bad alloc\n");
904 		return;
905 	}
906 	pgp_write(output, header, hdrsize);
907 	pgp_writer_push(output, linebreak_writer, NULL,
908 			generic_destroyer,
909 			linebreak);
910 	if ((base64 = calloc(1, sizeof(*base64))) == NULL) {
911 		(void) fprintf(stderr,
912 			"pgp_writer_push_armoured: bad alloc\n");
913 		return;
914 	}
915 	base64->checksum = CRC24_INIT;
916 	pgp_writer_push(output, base64_writer, finaliser,
917 			generic_destroyer, base64);
918 }
919 
920 /**************************************************************************/
921 
922 typedef struct {
923 	pgp_crypt_t    *crypt;
924 	int             free_crypt;
925 } crypt_t;
926 
927 /*
928  * This writer simply takes plaintext as input,
929  * encrypts it with the given key
930  * and outputs the resulting encrypted text
931  */
932 static unsigned
encrypt_writer(const uint8_t * src,unsigned len,pgp_error_t ** errors,pgp_writer_t * writer)933 encrypt_writer(const uint8_t *src,
934 	       unsigned len,
935 	       pgp_error_t **errors,
936 	       pgp_writer_t *writer)
937 {
938 #define BUFSZ 1024		/* arbitrary number */
939 	uint8_t		encbuf[BUFSZ];
940 	unsigned        remaining;
941 	unsigned        done = 0;
942 	crypt_t		*pgp_encrypt;
943 
944 	remaining = len;
945 	pgp_encrypt = (crypt_t *) pgp_writer_get_arg(writer);
946 	if (!pgp_is_sa_supported(pgp_encrypt->crypt->alg)) {
947 		(void) fprintf(stderr, "encrypt_writer: not supported\n");
948 		return 0;
949 	}
950 	while (remaining > 0) {
951 		unsigned        size = (remaining < BUFSZ) ? remaining : BUFSZ;
952 
953 		/* memcpy(buf,src,size); // \todo copy needed here? */
954 		pgp_encrypt->crypt->cfb_encrypt(pgp_encrypt->crypt, encbuf,
955 					src + done, size);
956 
957 		if (pgp_get_debug_level(__FILE__)) {
958 			hexdump(stderr, "unencrypted", &src[done], 16);
959 			hexdump(stderr, "encrypted", encbuf, 16);
960 		}
961 		if (!stacked_write(writer, encbuf, size, errors)) {
962 			if (pgp_get_debug_level(__FILE__)) {
963 				fprintf(stderr,
964 					"encrypted_writer: stacked write\n");
965 			}
966 			return 0;
967 		}
968 		remaining -= size;
969 		done += size;
970 	}
971 
972 	return 1;
973 }
974 
975 static void
encrypt_destroyer(pgp_writer_t * writer)976 encrypt_destroyer(pgp_writer_t *writer)
977 {
978 	crypt_t    *pgp_encrypt;
979 
980 	pgp_encrypt = (crypt_t *) pgp_writer_get_arg(writer);
981 	if (pgp_encrypt->free_crypt) {
982 		free(pgp_encrypt->crypt);
983 	}
984 	free(pgp_encrypt);
985 }
986 
987 /**
988 \ingroup Core_WritersNext
989 \brief Push Encrypted Writer onto stack (create SE packets)
990 */
991 void
pgp_push_enc_crypt(pgp_output_t * output,pgp_crypt_t * pgp_crypt)992 pgp_push_enc_crypt(pgp_output_t *output, pgp_crypt_t *pgp_crypt)
993 {
994 	/* Create encrypt to be used with this writer */
995 	/* Remember to free this in the destroyer */
996 	crypt_t    *pgp_encrypt;
997 
998 	if ((pgp_encrypt = calloc(1, sizeof(*pgp_encrypt))) == NULL) {
999 		(void) fprintf(stderr, "pgp_push_enc_crypt: bad alloc\n");
1000 	} else {
1001 		/* Setup the encrypt */
1002 		pgp_encrypt->crypt = pgp_crypt;
1003 		pgp_encrypt->free_crypt = 0;
1004 		/* And push writer on stack */
1005 		pgp_writer_push(output, encrypt_writer, NULL,
1006 			encrypt_destroyer, pgp_encrypt);
1007 	}
1008 }
1009 
1010 /**************************************************************************/
1011 
1012 typedef struct {
1013 	pgp_crypt_t    *crypt;
1014 } encrypt_se_ip_t;
1015 
1016 static unsigned	encrypt_se_ip_writer(const uint8_t *,
1017 		     unsigned,
1018 		     pgp_error_t **,
1019 		     pgp_writer_t *);
1020 static void     encrypt_se_ip_destroyer(pgp_writer_t *);
1021 
1022 /* */
1023 
1024 /**
1025 \ingroup Core_WritersNext
1026 \brief Push Encrypted SE IP Writer onto stack
1027 */
1028 int
pgp_push_enc_se_ip(pgp_output_t * output,const pgp_key_t * pubkey,const char * cipher)1029 pgp_push_enc_se_ip(pgp_output_t *output, const pgp_key_t *pubkey, const char *cipher)
1030 {
1031 	pgp_pk_sesskey_t *encrypted_pk_sesskey;
1032 	encrypt_se_ip_t *se_ip;
1033 	pgp_crypt_t	*encrypted;
1034 	uint8_t		*iv;
1035 
1036 	if ((se_ip = calloc(1, sizeof(*se_ip))) == NULL) {
1037 		(void) fprintf(stderr, "pgp_push_enc_se_ip: bad alloc\n");
1038 		return 0;
1039 	}
1040 
1041 	/* Create and write encrypted PK session key */
1042 	if ((encrypted_pk_sesskey = pgp_create_pk_sesskey(pubkey, cipher)) == NULL) {
1043 		(void) fprintf(stderr, "pgp_push_enc_se_ip: null pk sesskey\n");
1044 		return 0;
1045 	}
1046 	pgp_write_pk_sesskey(output, encrypted_pk_sesskey);
1047 
1048 	/* Setup the se_ip */
1049 	if ((encrypted = calloc(1, sizeof(*encrypted))) == NULL) {
1050 		free(se_ip);
1051 		(void) fprintf(stderr, "pgp_push_enc_se_ip: bad alloc\n");
1052 		return 0;
1053 	}
1054 	pgp_crypt_any(encrypted, encrypted_pk_sesskey->symm_alg);
1055 	if ((iv = calloc(1, encrypted->blocksize)) == NULL) {
1056 		free(se_ip);
1057 		free(encrypted);
1058 		(void) fprintf(stderr, "pgp_push_enc_se_ip: bad alloc\n");
1059 		return 0;
1060 	}
1061 	encrypted->set_iv(encrypted, iv);
1062 	encrypted->set_crypt_key(encrypted, &encrypted_pk_sesskey->key[0]);
1063 	pgp_encrypt_init(encrypted);
1064 
1065 	se_ip->crypt = encrypted;
1066 
1067 	/* And push writer on stack */
1068 	pgp_writer_push(output, encrypt_se_ip_writer, NULL,
1069 			encrypt_se_ip_destroyer, se_ip);
1070 	/* tidy up */
1071 	free(encrypted_pk_sesskey);
1072 	free(iv);
1073 	return 1;
1074 }
1075 
1076 static unsigned
encrypt_se_ip_writer(const uint8_t * src,unsigned len,pgp_error_t ** errors,pgp_writer_t * writer)1077 encrypt_se_ip_writer(const uint8_t *src,
1078 		     unsigned len,
1079 		     pgp_error_t **errors,
1080 		     pgp_writer_t *writer)
1081 {
1082 	const unsigned	 bufsz = 128;
1083 	encrypt_se_ip_t	*se_ip = pgp_writer_get_arg(writer);
1084 	pgp_output_t	*litoutput;
1085 	pgp_output_t	*zoutput;
1086 	pgp_output_t	*output;
1087 	pgp_memory_t	*litmem;
1088 	pgp_memory_t	*zmem;
1089 	pgp_memory_t	*localmem;
1090 	unsigned	 ret = 1;
1091 
1092 	pgp_setup_memory_write(&litoutput, &litmem, bufsz);
1093 	pgp_setup_memory_write(&zoutput, &zmem, bufsz);
1094 	pgp_setup_memory_write(&output, &localmem, bufsz);
1095 
1096 	/* create literal data packet from source data */
1097 	pgp_write_litdata(litoutput, src, (const int)len, PGP_LDT_BINARY);
1098 	if (pgp_mem_len(litmem) <= len) {
1099 		(void) fprintf(stderr, "encrypt_se_ip_writer: bad len\n");
1100 		return 0;
1101 	}
1102 
1103 	/* create compressed packet from literal data packet */
1104 	pgp_writez(zoutput, pgp_mem_data(litmem), (unsigned)pgp_mem_len(litmem));
1105 
1106 	/* create SE IP packet set from this compressed literal data */
1107 	pgp_write_se_ip_pktset(output, pgp_mem_data(zmem),
1108 			       (unsigned)pgp_mem_len(zmem),
1109 			       se_ip->crypt);
1110 	if (pgp_mem_len(localmem) <= pgp_mem_len(zmem)) {
1111 		(void) fprintf(stderr,
1112 				"encrypt_se_ip_writer: bad comp len\n");
1113 		return 0;
1114 	}
1115 
1116 	/* now write memory to next writer */
1117 	ret = stacked_write(writer, pgp_mem_data(localmem),
1118 				(unsigned)pgp_mem_len(localmem), errors);
1119 
1120 	pgp_memory_free(localmem);
1121 	pgp_memory_free(zmem);
1122 	pgp_memory_free(litmem);
1123 
1124 	return ret;
1125 }
1126 
1127 static void
encrypt_se_ip_destroyer(pgp_writer_t * writer)1128 encrypt_se_ip_destroyer(pgp_writer_t *writer)
1129 {
1130 	encrypt_se_ip_t	*se_ip;
1131 
1132 	se_ip = pgp_writer_get_arg(writer);
1133 	free(se_ip->crypt);
1134 	free(se_ip);
1135 }
1136 
1137 unsigned
pgp_write_se_ip_pktset(pgp_output_t * output,const uint8_t * data,const unsigned len,pgp_crypt_t * crypted)1138 pgp_write_se_ip_pktset(pgp_output_t *output,
1139 			const uint8_t *data,
1140 			const unsigned len,
1141 			pgp_crypt_t *crypted)
1142 {
1143 	pgp_output_t	*mdcoutput;
1144 	pgp_memory_t	*mdc;
1145 	uint8_t		 hashed[PGP_SHA1_HASH_SIZE];
1146 	uint8_t		*preamble;
1147 	const size_t	 mdcsize = 1 + 1 + PGP_SHA1_HASH_SIZE;
1148 	size_t		 preamblesize;
1149 	size_t		 bufsize;
1150 
1151 	preamblesize = crypted->blocksize + 2;
1152 	if ((preamble = calloc(1, preamblesize)) == NULL) {
1153 		(void) fprintf(stderr, "pgp_write_se_ip_pktset: bad alloc\n");
1154 		return 0;
1155 	}
1156 	bufsize = preamblesize + len + mdcsize;
1157 
1158 	if (!pgp_write_ptag(output, PGP_PTAG_CT_SE_IP_DATA) ||
1159 	    !pgp_write_length(output, (unsigned)(1 + bufsize)) ||
1160 	    !pgp_write_scalar(output, PGP_SE_IP_DATA_VERSION, 1)) {
1161 		free(preamble);
1162 		return 0;
1163 	}
1164 	pgp_random(preamble, crypted->blocksize);
1165 	preamble[crypted->blocksize] = preamble[crypted->blocksize - 2];
1166 	preamble[crypted->blocksize + 1] = preamble[crypted->blocksize - 1];
1167 
1168 	if (pgp_get_debug_level(__FILE__)) {
1169 		hexdump(stderr, "preamble", preamble, preamblesize);
1170 	}
1171 
1172 	/* now construct MDC packet and add to the end of the buffer */
1173 	pgp_setup_memory_write(&mdcoutput, &mdc, mdcsize);
1174 	pgp_calc_mdc_hash(preamble, preamblesize, data, len, hashed);
1175 	pgp_write_mdc(mdcoutput, hashed);
1176 
1177 	if (pgp_get_debug_level(__FILE__)) {
1178 		hexdump(stderr, "plaintext", data, len);
1179 		hexdump(stderr, "mdc", pgp_mem_data(mdc), PGP_SHA1_HASH_SIZE + 1 + 1);
1180 	}
1181 
1182 	/* and write it out */
1183 	pgp_push_enc_crypt(output, crypted);
1184 	if (pgp_get_debug_level(__FILE__)) {
1185 		(void) fprintf(stderr,
1186 			"writing %" PRIsize "u + %u + %" PRIsize "u\n",
1187 			preamblesize, len, pgp_mem_len(mdc));
1188 	}
1189 	if (!pgp_write(output, preamble, (unsigned)preamblesize) ||
1190 	    !pgp_write(output, data, len) ||
1191 	    !pgp_write(output, pgp_mem_data(mdc), (unsigned)pgp_mem_len(mdc))) {
1192 		/* \todo fix cleanup here and in old code functions */
1193 		return 0;
1194 	}
1195 
1196 	pgp_writer_pop(output);
1197 
1198 	/* cleanup  */
1199 	pgp_teardown_memory_write(mdcoutput, mdc);
1200 	free(preamble);
1201 
1202 	return 1;
1203 }
1204 
1205 typedef struct {
1206 	int             fd;
1207 } writer_fd_t;
1208 
1209 static unsigned
fd_writer(const uint8_t * src,unsigned len,pgp_error_t ** errors,pgp_writer_t * writer)1210 fd_writer(const uint8_t *src, unsigned len,
1211 	  pgp_error_t **errors,
1212 	  pgp_writer_t *writer)
1213 {
1214 	writer_fd_t	*writerfd;
1215 	int              n;
1216 
1217 	writerfd = pgp_writer_get_arg(writer);
1218 	n = (int)write(writerfd->fd, src, len);
1219 	if (n == -1) {
1220 		PGP_SYSTEM_ERROR_1(errors, PGP_E_W_WRITE_FAILED, "write",
1221 				   "file descriptor %d", writerfd->fd);
1222 		return 0;
1223 	}
1224 	if ((unsigned) n != len) {
1225 		PGP_ERROR_1(errors, PGP_E_W_WRITE_TOO_SHORT,
1226 			    "file descriptor %d", writerfd->fd);
1227 		return 0;
1228 	}
1229 	return 1;
1230 }
1231 
1232 static void
writer_fd_destroyer(pgp_writer_t * writer)1233 writer_fd_destroyer(pgp_writer_t *writer)
1234 {
1235 	free(pgp_writer_get_arg(writer));
1236 }
1237 
1238 /**
1239  * \ingroup Core_WritersFirst
1240  * \brief Write to a File
1241  *
1242  * Set the writer in output to be a stock writer that writes to a file
1243  * descriptor. If another writer has already been set, then that is
1244  * first destroyed.
1245  *
1246  * \param output The output structure
1247  * \param fd The file descriptor
1248  *
1249  */
1250 
1251 void
pgp_writer_set_fd(pgp_output_t * output,int fd)1252 pgp_writer_set_fd(pgp_output_t *output, int fd)
1253 {
1254 	writer_fd_t	*writer;
1255 
1256 	if ((writer = calloc(1, sizeof(*writer))) == NULL) {
1257 		(void) fprintf(stderr, "pgp_writer_set_fd: bad alloc\n");
1258 	} else {
1259 		writer->fd = fd;
1260 		pgp_writer_set(output, fd_writer, NULL, writer_fd_destroyer, writer);
1261 	}
1262 }
1263 
1264 static unsigned
memory_writer(const uint8_t * src,unsigned len,pgp_error_t ** errors,pgp_writer_t * writer)1265 memory_writer(const uint8_t *src,
1266 		unsigned len,
1267 		pgp_error_t **errors,
1268 		pgp_writer_t *writer)
1269 {
1270 	pgp_memory_t   *mem;
1271 
1272 	__PGP_USED(errors);
1273 	mem = pgp_writer_get_arg(writer);
1274 	pgp_memory_add(mem, src, len);
1275 	return 1;
1276 }
1277 
1278 /**
1279  * \ingroup Core_WritersFirst
1280  * \brief Write to memory
1281  *
1282  * Set a memory writer.
1283  *
1284  * \param output The output structure
1285  * \param mem The memory structure
1286  * \note It is the caller's responsiblity to call pgp_memory_free(mem)
1287  * \sa pgp_memory_free()
1288  */
1289 
1290 void
pgp_writer_set_memory(pgp_output_t * output,pgp_memory_t * mem)1291 pgp_writer_set_memory(pgp_output_t *output, pgp_memory_t *mem)
1292 {
1293 	pgp_writer_set(output, memory_writer, NULL, NULL, mem);
1294 }
1295 
1296 /**************************************************************************/
1297 
1298 typedef struct {
1299 	pgp_hash_alg_t	 hash_alg;
1300 	pgp_hash_t		 hash;
1301 	uint8_t			*hashed;
1302 } skey_checksum_t;
1303 
1304 static unsigned
skey_checksum_writer(const uint8_t * src,const unsigned len,pgp_error_t ** errors,pgp_writer_t * writer)1305 skey_checksum_writer(const uint8_t *src,
1306 	const unsigned len,
1307 	pgp_error_t **errors,
1308 	pgp_writer_t *writer)
1309 {
1310 	skey_checksum_t	*sum;
1311 	unsigned	 ret = 1;
1312 
1313 	sum = pgp_writer_get_arg(writer);
1314 	/* add contents to hash */
1315 	sum->hash.add(&sum->hash, src, len);
1316 	/* write to next stacked writer */
1317 	ret = stacked_write(writer, src, len, errors);
1318 	/* tidy up and return */
1319 	return ret;
1320 }
1321 
1322 static unsigned
skey_checksum_finaliser(pgp_error_t ** errors,pgp_writer_t * writer)1323 skey_checksum_finaliser(pgp_error_t **errors, pgp_writer_t *writer)
1324 {
1325 	skey_checksum_t *sum;
1326 
1327 	sum = pgp_writer_get_arg(writer);
1328 	if (errors && *errors) {
1329 		printf("errors in skey_checksum_finaliser\n");
1330 	}
1331 	(*sum->hash.finish)(&sum->hash, sum->hashed);
1332 	return 1;
1333 }
1334 
1335 static void
skey_checksum_destroyer(pgp_writer_t * writer)1336 skey_checksum_destroyer(pgp_writer_t *writer)
1337 {
1338 	skey_checksum_t *sum;
1339 
1340 	sum = pgp_writer_get_arg(writer);
1341 	free(sum);
1342 }
1343 
1344 /**
1345 \ingroup Core_WritersNext
1346 \param output
1347 \param seckey
1348 */
1349 void
pgp_push_checksum_writer(pgp_output_t * output,pgp_seckey_t * seckey)1350 pgp_push_checksum_writer(pgp_output_t *output, pgp_seckey_t *seckey)
1351 {
1352 	/* XXX: push a SHA-1 checksum writer (and change s2k to 254). */
1353 	skey_checksum_t *sum;
1354 	unsigned	 hashsize;
1355 
1356 	if ((sum = calloc(1, sizeof(*sum))) == NULL) {
1357 		(void) fprintf(stderr,
1358 			"pgp_push_checksum_writer: bad alloc\n");
1359 	} else {
1360 		/* configure the arg */
1361 		/* Hardcoded SHA1 for just now */
1362 		sum->hash_alg = PGP_HASH_SHA1;
1363 		hashsize = pgp_hash_size(sum->hash_alg);
1364 		if ((sum->hashed = seckey->checkhash) == NULL) {
1365 			sum->hashed = seckey->checkhash = calloc(1, hashsize);
1366 		}
1367 		/* init the hash */
1368 		pgp_hash_any(&sum->hash, sum->hash_alg);
1369 		if (!sum->hash.init(&sum->hash)) {
1370 			(void) fprintf(stderr,
1371 				"pgp_push_checksum_writer: bad hash init\n");
1372 			/* just continue and die */
1373 			/* XXX - agc - no way to return failure */
1374 		}
1375 		pgp_writer_push(output, skey_checksum_writer,
1376 			skey_checksum_finaliser, skey_checksum_destroyer, sum);
1377 	}
1378 }
1379 
1380 /**************************************************************************/
1381 
1382 #define MAX_PARTIAL_DATA_LENGTH 1073741824
1383 
1384 typedef struct {
1385 	pgp_crypt_t	*crypt;
1386 	pgp_memory_t	*mem_data;
1387 	pgp_memory_t	*litmem;
1388 	pgp_output_t	*litoutput;
1389 	pgp_memory_t	*se_ip_mem;
1390 	pgp_output_t	*se_ip_out;
1391 	pgp_hash_t	 hash;
1392 } str_enc_se_ip_t;
1393 
1394 
1395 static unsigned
1396 str_enc_se_ip_writer(const uint8_t *src,
1397 			    unsigned len,
1398 			    pgp_error_t **errors,
1399 			    pgp_writer_t *writer);
1400 
1401 static unsigned
1402 str_enc_se_ip_finaliser(pgp_error_t **errors,
1403 			       pgp_writer_t * writer);
1404 
1405 static void     str_enc_se_ip_destroyer(pgp_writer_t *writer);
1406 
1407 /* */
1408 
1409 /**
1410 \ingroup Core_WritersNext
1411 \param output
1412 \param pubkey
1413 */
1414 void
pgp_push_stream_enc_se_ip(pgp_output_t * output,const pgp_key_t * pubkey,const char * cipher)1415 pgp_push_stream_enc_se_ip(pgp_output_t *output, const pgp_key_t *pubkey, const char *cipher)
1416 {
1417 	pgp_pk_sesskey_t	*encrypted_pk_sesskey;
1418 	str_enc_se_ip_t		*se_ip;
1419 	const unsigned	 	 bufsz = 1024;
1420 	pgp_crypt_t		*encrypted;
1421 	uint8_t			*iv;
1422 
1423 	if ((se_ip = calloc(1, sizeof(*se_ip))) == NULL) {
1424 		(void) fprintf(stderr,
1425 			"pgp_push_stream_enc_se_ip: bad alloc\n");
1426 		return;
1427 	}
1428 	encrypted_pk_sesskey = pgp_create_pk_sesskey(pubkey, cipher);
1429 	pgp_write_pk_sesskey(output, encrypted_pk_sesskey);
1430 
1431 	/* Setup the se_ip */
1432 	if ((encrypted = calloc(1, sizeof(*encrypted))) == NULL) {
1433 		free(se_ip);
1434 		(void) fprintf(stderr,
1435 			"pgp_push_stream_enc_se_ip: bad alloc\n");
1436 		return;
1437 	}
1438 	pgp_crypt_any(encrypted, encrypted_pk_sesskey->symm_alg);
1439 	if ((iv = calloc(1, encrypted->blocksize)) == NULL) {
1440 		free(encrypted);
1441 		free(se_ip);
1442 		(void) fprintf(stderr,
1443 			"pgp_push_stream_enc_se_ip: bad alloc\n");
1444 		return;
1445 	}
1446 	encrypted->set_iv(encrypted, iv);
1447 	encrypted->set_crypt_key(encrypted, &encrypted_pk_sesskey->key[0]);
1448 	pgp_encrypt_init(encrypted);
1449 
1450 	se_ip->crypt = encrypted;
1451 
1452 	se_ip->mem_data = pgp_memory_new();
1453 	pgp_memory_init(se_ip->mem_data, bufsz);
1454 
1455 	se_ip->litmem = NULL;
1456 	se_ip->litoutput = NULL;
1457 
1458 	pgp_setup_memory_write(&se_ip->se_ip_out, &se_ip->se_ip_mem, bufsz);
1459 
1460 	/* And push writer on stack */
1461 	pgp_writer_push(output,
1462 			str_enc_se_ip_writer,
1463 			str_enc_se_ip_finaliser,
1464 			str_enc_se_ip_destroyer, se_ip);
1465 	/* tidy up */
1466 	free(encrypted_pk_sesskey);
1467 	free(iv);
1468 }
1469 
1470 
1471 /* calculate the partial data length */
1472 static unsigned
partial_data_len(unsigned len)1473 partial_data_len(unsigned len)
1474 {
1475 	unsigned	mask;
1476 	int		i;
1477 
1478 	if (len == 0) {
1479 		(void) fprintf(stderr, "partial_data_len: 0 len\n");
1480 		return 0;
1481 	}
1482 	if (len > MAX_PARTIAL_DATA_LENGTH) {
1483 		return MAX_PARTIAL_DATA_LENGTH;
1484 	}
1485 	mask = MAX_PARTIAL_DATA_LENGTH;
1486 	for (i = 0; i <= 30; i++) {
1487 		if (mask & len) {
1488 			break;
1489 		}
1490 		mask >>= 1;
1491 	}
1492 	return mask;
1493 }
1494 
1495 static unsigned
write_partial_len(pgp_output_t * output,unsigned len)1496 write_partial_len(pgp_output_t *output, unsigned len)
1497 {
1498 	/* len must be a power of 2 from 0 to 30 */
1499 	uint8_t	c;
1500 	int	i;
1501 
1502 	for (i = 0; i <= 30; i++) {
1503 		if ((len >> i) & 1) {
1504 			break;
1505 		}
1506 	}
1507 	c = 224 + i;
1508 	return pgp_write(output, &c, 1);
1509 }
1510 
1511 static unsigned
stream_write_litdata(pgp_output_t * output,const uint8_t * data,unsigned len)1512 stream_write_litdata(pgp_output_t *output,
1513 			const uint8_t *data,
1514 			unsigned len)
1515 {
1516 	size_t          pdlen;
1517 
1518 	while (len > 0) {
1519 		pdlen = partial_data_len(len);
1520 		write_partial_len(output, (unsigned)pdlen);
1521 		pgp_write(output, data, (unsigned)pdlen);
1522 		data += pdlen;
1523 		len -= (unsigned)pdlen;
1524 	}
1525 	return 1;
1526 }
1527 
1528 static unsigned
stream_write_litdata_first(pgp_output_t * output,const uint8_t * data,unsigned len,const pgp_litdata_enum type)1529 stream_write_litdata_first(pgp_output_t *output,
1530 				const uint8_t *data,
1531 				unsigned len,
1532 				const pgp_litdata_enum type)
1533 {
1534 	/* \todo add filename  */
1535 	/* \todo add date */
1536 	/* \todo do we need to check text data for <cr><lf> line endings ? */
1537 
1538 	unsigned	sz_towrite;
1539 	size_t		sz_pd;
1540 
1541 	sz_towrite = 1 + 1 + 4 + len;
1542 	sz_pd = (size_t)partial_data_len(sz_towrite);
1543 	if (sz_pd < 512) {
1544 		(void) fprintf(stderr,
1545 			"stream_write_litdata_first: bad sz_pd\n");
1546 		return 0;
1547 	}
1548 	pgp_write_ptag(output, PGP_PTAG_CT_LITDATA);
1549 	write_partial_len(output, (unsigned)sz_pd);
1550 	pgp_write_scalar(output, (unsigned)type, 1);
1551 	pgp_write_scalar(output, 0, 1);
1552 	pgp_write_scalar(output, 0, 4);
1553 	pgp_write(output, data, (unsigned)(sz_pd - 6));
1554 
1555 	data += (sz_pd - 6);
1556 	sz_towrite -= (unsigned)sz_pd;
1557 
1558 	return stream_write_litdata(output, data, (unsigned)sz_towrite);
1559 }
1560 
1561 static unsigned
stream_write_litdata_last(pgp_output_t * output,const uint8_t * data,unsigned len)1562 stream_write_litdata_last(pgp_output_t *output,
1563 				const uint8_t *data,
1564 				unsigned len)
1565 {
1566 	pgp_write_length(output, len);
1567 	return pgp_write(output, data, len);
1568 }
1569 
1570 static unsigned
stream_write_se_ip(pgp_output_t * output,const uint8_t * data,unsigned len,str_enc_se_ip_t * se_ip)1571 stream_write_se_ip(pgp_output_t *output,
1572 			const uint8_t *data,
1573 			unsigned len,
1574 			str_enc_se_ip_t *se_ip)
1575 {
1576 	size_t          pdlen;
1577 
1578 	while (len > 0) {
1579 		pdlen = partial_data_len(len);
1580 		write_partial_len(output, (unsigned)pdlen);
1581 
1582 		pgp_push_enc_crypt(output, se_ip->crypt);
1583 		pgp_write(output, data, (unsigned)pdlen);
1584 		pgp_writer_pop(output);
1585 
1586 		se_ip->hash.add(&se_ip->hash, data, (unsigned)pdlen);
1587 
1588 		data += pdlen;
1589 		len -= (unsigned)pdlen;
1590 	}
1591 	return 1;
1592 }
1593 
1594 static unsigned
stream_write_se_ip_first(pgp_output_t * output,const uint8_t * data,unsigned len,str_enc_se_ip_t * se_ip)1595 stream_write_se_ip_first(pgp_output_t *output,
1596 			const uint8_t *data,
1597 			unsigned len,
1598 			str_enc_se_ip_t *se_ip)
1599 {
1600 	uint8_t	*preamble;
1601 	size_t	blocksize;
1602 	size_t 	preamblesize;
1603 	size_t 	sz_towrite;
1604 	size_t 	sz_pd;
1605 
1606 	blocksize = se_ip->crypt->blocksize;
1607 	preamblesize = blocksize + 2;
1608 	sz_towrite = preamblesize + 1 + len;
1609 	if ((preamble = calloc(1, preamblesize)) == NULL) {
1610 		(void) fprintf(stderr,
1611 			"stream_write_se_ip_first: bad alloc\n");
1612 		return 0;
1613 	}
1614 	sz_pd = (size_t)partial_data_len((unsigned)sz_towrite);
1615 	if (sz_pd < 512) {
1616 		free(preamble);
1617 		(void) fprintf(stderr,
1618 			"stream_write_se_ip_first: bad sz_pd\n");
1619 		return 0;
1620 	}
1621 	pgp_write_ptag(output, PGP_PTAG_CT_SE_IP_DATA);
1622 	write_partial_len(output, (unsigned)sz_pd);
1623 	pgp_write_scalar(output, PGP_SE_IP_DATA_VERSION, 1);
1624 	pgp_push_enc_crypt(output, se_ip->crypt);
1625 
1626 	pgp_random(preamble, blocksize);
1627 	preamble[blocksize] = preamble[blocksize - 2];
1628 	preamble[blocksize + 1] = preamble[blocksize - 1];
1629 	pgp_hash_any(&se_ip->hash, PGP_HASH_SHA1);
1630 	if (!se_ip->hash.init(&se_ip->hash)) {
1631 		free(preamble);
1632 		(void) fprintf(stderr,
1633 			"stream_write_se_ip_first: bad hash init\n");
1634 		return 0;
1635 	}
1636 	pgp_write(output, preamble, (unsigned)preamblesize);
1637 	se_ip->hash.add(&se_ip->hash, preamble, (unsigned)preamblesize);
1638 	pgp_write(output, data, (unsigned)(sz_pd - preamblesize - 1));
1639 	se_ip->hash.add(&se_ip->hash, data, (unsigned)(sz_pd - preamblesize - 1));
1640 	data += (sz_pd - preamblesize - 1);
1641 	sz_towrite -= sz_pd;
1642 	pgp_writer_pop(output);
1643 	stream_write_se_ip(output, data, (unsigned)sz_towrite, se_ip);
1644 	free(preamble);
1645 	return 1;
1646 }
1647 
1648 static unsigned
stream_write_se_ip_last(pgp_output_t * output,const uint8_t * data,unsigned len,str_enc_se_ip_t * se_ip)1649 stream_write_se_ip_last(pgp_output_t *output,
1650 			const uint8_t *data,
1651 			unsigned len,
1652 			str_enc_se_ip_t *se_ip)
1653 {
1654 	pgp_output_t	*mdcoutput;
1655 	pgp_memory_t	*mdcmem;
1656 	const size_t	 mdcsize = 1 + 1 + PGP_SHA1_HASH_SIZE;
1657 	uint8_t		 c;
1658 	uint8_t		 hashed[PGP_SHA1_HASH_SIZE];
1659 	size_t		 bufsize = len + mdcsize;
1660 
1661 	se_ip->hash.add(&se_ip->hash, data, len);
1662 
1663 	/* MDC packet tag */
1664 	c = MDC_PKT_TAG;
1665 	se_ip->hash.add(&se_ip->hash, &c, 1);
1666 
1667 	/* MDC packet len */
1668 	c = PGP_SHA1_HASH_SIZE;
1669 	se_ip->hash.add(&se_ip->hash, &c, 1);
1670 
1671 	/* finish */
1672 	se_ip->hash.finish(&se_ip->hash, hashed);
1673 
1674 	pgp_setup_memory_write(&mdcoutput, &mdcmem, mdcsize);
1675 	pgp_write_mdc(mdcoutput, hashed);
1676 
1677 	/* write length of last se_ip chunk */
1678 	pgp_write_length(output, (unsigned)bufsize);
1679 
1680 	/* encode everting */
1681 	pgp_push_enc_crypt(output, se_ip->crypt);
1682 
1683 	pgp_write(output, data, len);
1684 	pgp_write(output, pgp_mem_data(mdcmem), (unsigned)pgp_mem_len(mdcmem));
1685 
1686 	pgp_writer_pop(output);
1687 
1688 	pgp_teardown_memory_write(mdcoutput, mdcmem);
1689 
1690 	return 1;
1691 }
1692 
1693 static unsigned
str_enc_se_ip_writer(const uint8_t * src,unsigned len,pgp_error_t ** errors,pgp_writer_t * writer)1694 str_enc_se_ip_writer(const uint8_t *src,
1695 			    unsigned len,
1696 			    pgp_error_t **errors,
1697 			    pgp_writer_t *writer)
1698 {
1699 	str_enc_se_ip_t	*se_ip;
1700 	unsigned	 ret;
1701 	size_t           datalength;
1702 
1703 	se_ip = pgp_writer_get_arg(writer);
1704 	ret = 1;
1705 	if (se_ip->litoutput == NULL) {
1706 		/* first literal data chunk is not yet written */
1707 
1708 		pgp_memory_add(se_ip->mem_data, src, len);
1709 		datalength = pgp_mem_len(se_ip->mem_data);
1710 
1711 		/* 4.2.2.4. Partial Body Lengths */
1712 		/* The first partial length MUST be at least 512 octets long. */
1713 		if (datalength < 512) {
1714 			return 1;	/* will wait for more data or
1715 						 * end of stream             */
1716 		}
1717 		pgp_setup_memory_write(&se_ip->litoutput,
1718 				&se_ip->litmem, datalength + 32);
1719 		stream_write_litdata_first(se_ip->litoutput,
1720 				pgp_mem_data(se_ip->mem_data),
1721 				(unsigned)datalength,
1722 				PGP_LDT_BINARY);
1723 
1724 		stream_write_se_ip_first(se_ip->se_ip_out,
1725 				pgp_mem_data(se_ip->litmem),
1726 				(unsigned)pgp_mem_len(se_ip->litmem), se_ip);
1727 	} else {
1728 		stream_write_litdata(se_ip->litoutput, src, len);
1729 		stream_write_se_ip(se_ip->se_ip_out,
1730 				pgp_mem_data(se_ip->litmem),
1731 				(unsigned)pgp_mem_len(se_ip->litmem), se_ip);
1732 	}
1733 
1734 	/* now write memory to next writer */
1735 	ret = stacked_write(writer, pgp_mem_data(se_ip->se_ip_mem),
1736 				(unsigned)pgp_mem_len(se_ip->se_ip_mem), errors);
1737 
1738 	pgp_memory_clear(se_ip->litmem);
1739 	pgp_memory_clear(se_ip->se_ip_mem);
1740 
1741 	return ret;
1742 }
1743 
1744 /* write last chunk of data */
1745 static unsigned
str_enc_se_ip_finaliser(pgp_error_t ** errors,pgp_writer_t * writer)1746 str_enc_se_ip_finaliser(pgp_error_t **errors, pgp_writer_t *writer)
1747 {
1748 	str_enc_se_ip_t	*se_ip;
1749 
1750 	se_ip = pgp_writer_get_arg(writer);
1751 	if (se_ip->litoutput == NULL) {
1752 		/* first literal data chunk was not written */
1753 		/* so we know the total length of data, write a simple packet */
1754 
1755 		/* create literal data packet from buffered data */
1756 		pgp_setup_memory_write(&se_ip->litoutput, &se_ip->litmem,
1757 				 pgp_mem_len(se_ip->mem_data) + 32);
1758 
1759 		pgp_write_litdata(se_ip->litoutput,
1760 			pgp_mem_data(se_ip->mem_data),
1761 			(const int)pgp_mem_len(se_ip->mem_data),
1762 			PGP_LDT_BINARY);
1763 
1764 		/* create SE IP packet set from this literal data */
1765 		pgp_write_se_ip_pktset(se_ip->se_ip_out,
1766 				pgp_mem_data(se_ip->litmem),
1767 				(unsigned)pgp_mem_len(se_ip->litmem),
1768 				se_ip->crypt);
1769 
1770 	} else {
1771 		/* finish writing */
1772 		stream_write_litdata_last(se_ip->litoutput, NULL, 0);
1773 		stream_write_se_ip_last(se_ip->se_ip_out,
1774 				pgp_mem_data(se_ip->litmem),
1775 				(unsigned)pgp_mem_len(se_ip->litmem), se_ip);
1776 	}
1777 
1778 	/* now write memory to next writer */
1779 	return stacked_write(writer, pgp_mem_data(se_ip->se_ip_mem),
1780 				 (unsigned)pgp_mem_len(se_ip->se_ip_mem), errors);
1781 }
1782 
1783 static void
str_enc_se_ip_destroyer(pgp_writer_t * writer)1784 str_enc_se_ip_destroyer(pgp_writer_t *writer)
1785 {
1786 	str_enc_se_ip_t *se_ip;
1787 
1788 	se_ip = pgp_writer_get_arg(writer);
1789 	pgp_memory_free(se_ip->mem_data);
1790 	pgp_teardown_memory_write(se_ip->litoutput, se_ip->litmem);
1791 	pgp_teardown_memory_write(se_ip->se_ip_out, se_ip->se_ip_mem);
1792 
1793 	se_ip->crypt->decrypt_finish(se_ip->crypt);
1794 
1795 	free(se_ip->crypt);
1796 	free(se_ip);
1797 }
1798