Home | History | Annotate | Line # | Download | only in lib
      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 (at) 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
     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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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           *
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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