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 #include "config.h"
     50 
     51 #ifdef HAVE_SYS_CDEFS_H
     52 #include <sys/cdefs.h>
     53 #endif
     54 
     55 #if defined(__NetBSD__)
     56 __COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved.");
     57 __RCSID("$NetBSD: crypto.c,v 1.36 2014/02/17 07:39:19 agc Exp $");
     58 #endif
     59 
     60 #include <sys/types.h>
     61 #include <sys/stat.h>
     62 
     63 #ifdef HAVE_UNISTD_H
     64 #include <unistd.h>
     65 #endif
     66 
     67 #include <string.h>
     68 
     69 #include "types.h"
     70 #include "crypto.h"
     71 #include "readerwriter.h"
     72 #include "memory.h"
     73 #include "netpgpdefs.h"
     74 #include "signature.h"
     75 
     76 /**
     77 \ingroup Core_MPI
     78 \brief Decrypt and unencode MPI
     79 \param buf Buffer in which to write decrypted unencoded MPI
     80 \param buflen Length of buffer
     81 \param encmpi
     82 \param seckey
     83 \return length of MPI
     84 \note only RSA at present
     85 */
     86 int
     87 pgp_decrypt_decode_mpi(uint8_t *buf,
     88 				unsigned buflen,
     89 				const BIGNUM *g_to_k,
     90 				const BIGNUM *encmpi,
     91 				const pgp_seckey_t *seckey)
     92 {
     93 	unsigned        mpisize;
     94 	uint8_t		encmpibuf[NETPGP_BUFSIZ];
     95 	uint8_t		mpibuf[NETPGP_BUFSIZ];
     96 	uint8_t		gkbuf[NETPGP_BUFSIZ];
     97 	int             i;
     98 	int             n;
     99 
    100 	mpisize = (unsigned)BN_num_bytes(encmpi);
    101 	/* MPI can't be more than 65,536 */
    102 	if (mpisize > sizeof(encmpibuf)) {
    103 		(void) fprintf(stderr, "mpisize too big %u\n", mpisize);
    104 		return -1;
    105 	}
    106 	switch (seckey->pubkey.alg) {
    107 	case PGP_PKA_RSA:
    108 		BN_bn2bin(encmpi, encmpibuf);
    109 		if (pgp_get_debug_level(__FILE__)) {
    110 			hexdump(stderr, "encrypted", encmpibuf, 16);
    111 		}
    112 		n = pgp_rsa_private_decrypt(mpibuf, encmpibuf,
    113 					(unsigned)(BN_num_bits(encmpi) + 7) / 8,
    114 					&seckey->key.rsa, &seckey->pubkey.key.rsa);
    115 		if (n == -1) {
    116 			(void) fprintf(stderr, "ops_rsa_private_decrypt failure\n");
    117 			return -1;
    118 		}
    119 		if (pgp_get_debug_level(__FILE__)) {
    120 			hexdump(stderr, "decrypted", mpibuf, 16);
    121 		}
    122 		if (n <= 0) {
    123 			return -1;
    124 		}
    125 		/* Decode EME-PKCS1_V1_5 (RFC 2437). */
    126 		if (mpibuf[0] != 0 || mpibuf[1] != 2) {
    127 			return -1;
    128 		}
    129 		/* Skip the random bytes. */
    130 		for (i = 2; i < n && mpibuf[i]; ++i) {
    131 		}
    132 		if (i == n || i < 10) {
    133 			return -1;
    134 		}
    135 		/* Skip the zero */
    136 		i += 1;
    137 		/* this is the unencoded m buf */
    138 		if ((unsigned) (n - i) <= buflen) {
    139 			(void) memcpy(buf, mpibuf + i, (unsigned)(n - i)); /* XXX - Flexelint */
    140 		}
    141 		if (pgp_get_debug_level(__FILE__)) {
    142 			hexdump(stderr, "decoded m", buf, (size_t)(n - i));
    143 		}
    144 		return n - i;
    145 	case PGP_PKA_DSA:
    146 	case PGP_PKA_ELGAMAL:
    147 		(void) BN_bn2bin(g_to_k, gkbuf);
    148 		(void) BN_bn2bin(encmpi, encmpibuf);
    149 		if (pgp_get_debug_level(__FILE__)) {
    150 			hexdump(stderr, "encrypted", encmpibuf, 16);
    151 		}
    152 		n = pgp_elgamal_private_decrypt(mpibuf, gkbuf, encmpibuf,
    153 					(unsigned)BN_num_bytes(encmpi),
    154 					&seckey->key.elgamal, &seckey->pubkey.key.elgamal);
    155 		if (n == -1) {
    156 			(void) fprintf(stderr, "ops_elgamal_private_decrypt failure\n");
    157 			return -1;
    158 		}
    159 		if (pgp_get_debug_level(__FILE__)) {
    160 			hexdump(stderr, "decrypted", mpibuf, 16);
    161 		}
    162 		if (n <= 0) {
    163 			return -1;
    164 		}
    165 		/* Decode EME-PKCS1_V1_5 (RFC 2437). */
    166 		if (mpibuf[0] != 2) {
    167 			fprintf(stderr, "mpibuf mismatch\n");
    168 			return -1;
    169 		}
    170 		/* Skip the random bytes. */
    171 		for (i = 1; i < n && mpibuf[i]; ++i) {
    172 		}
    173 		if (i == n || i < 10) {
    174 			fprintf(stderr, "175 n %d\n", n);
    175 			return -1;
    176 		}
    177 		/* Skip the zero */
    178 		i += 1;
    179 		/* this is the unencoded m buf */
    180 		if ((unsigned) (n - i) <= buflen) {
    181 			(void) memcpy(buf, mpibuf + i, (unsigned)(n - i)); /* XXX - Flexelint */
    182 		}
    183 		if (pgp_get_debug_level(__FILE__)) {
    184 			hexdump(stderr, "decoded m", buf, (size_t)(n - i));
    185 		}
    186 		return n - i;
    187 	default:
    188 		(void) fprintf(stderr, "pubkey algorithm wrong\n");
    189 		return -1;
    190 	}
    191 }
    192 
    193 /**
    194 \ingroup Core_MPI
    195 \brief RSA-encrypt an MPI
    196 */
    197 unsigned
    198 pgp_rsa_encrypt_mpi(const uint8_t *encoded_m_buf,
    199 		    const size_t sz_encoded_m_buf,
    200 		    const pgp_pubkey_t * pubkey,
    201 		    pgp_pk_sesskey_params_t * skp)
    202 {
    203 
    204 	uint8_t   encmpibuf[NETPGP_BUFSIZ];
    205 	int             n;
    206 
    207 	if (sz_encoded_m_buf != (size_t)BN_num_bytes(pubkey->key.rsa.n)) {
    208 		(void) fprintf(stderr, "sz_encoded_m_buf wrong\n");
    209 		return 0;
    210 	}
    211 
    212 	n = pgp_rsa_public_encrypt(encmpibuf, encoded_m_buf,
    213 				sz_encoded_m_buf, &pubkey->key.rsa);
    214 	if (n == -1) {
    215 		(void) fprintf(stderr, "pgp_rsa_public_encrypt failure\n");
    216 		return 0;
    217 	}
    218 
    219 	if (n <= 0)
    220 		return 0;
    221 
    222 	skp->rsa.encrypted_m = BN_bin2bn(encmpibuf, n, NULL);
    223 
    224 	if (pgp_get_debug_level(__FILE__)) {
    225 		hexdump(stderr, "encrypted mpi", encmpibuf, 16);
    226 	}
    227 	return 1;
    228 }
    229 
    230 /**
    231 \ingroup Core_MPI
    232 \brief Elgamal-encrypt an MPI
    233 */
    234 unsigned
    235 pgp_elgamal_encrypt_mpi(const uint8_t *encoded_m_buf,
    236 		    const size_t sz_encoded_m_buf,
    237 		    const pgp_pubkey_t * pubkey,
    238 		    pgp_pk_sesskey_params_t * skp)
    239 {
    240 
    241 	uint8_t   encmpibuf[NETPGP_BUFSIZ];
    242 	uint8_t   g_to_k[NETPGP_BUFSIZ];
    243 	int             n;
    244 
    245 	if (sz_encoded_m_buf != (size_t)BN_num_bytes(pubkey->key.elgamal.p)) {
    246 		(void) fprintf(stderr, "sz_encoded_m_buf wrong\n");
    247 		return 0;
    248 	}
    249 
    250 	n = pgp_elgamal_public_encrypt(g_to_k, encmpibuf, encoded_m_buf,
    251 				sz_encoded_m_buf, &pubkey->key.elgamal);
    252 	if (n == -1) {
    253 		(void) fprintf(stderr, "pgp_elgamal_public_encrypt failure\n");
    254 		return 0;
    255 	}
    256 
    257 	if (n <= 0)
    258 		return 0;
    259 
    260 	skp->elgamal.g_to_k = BN_bin2bn(g_to_k, n / 2, NULL);
    261 	skp->elgamal.encrypted_m = BN_bin2bn(encmpibuf, n / 2, NULL);
    262 
    263 	if (pgp_get_debug_level(__FILE__)) {
    264 		hexdump(stderr, "encrypted mpi", encmpibuf, 16);
    265 	}
    266 	return 1;
    267 }
    268 
    269 static pgp_cb_ret_t
    270 write_parsed_cb(const pgp_packet_t *pkt, pgp_cbdata_t *cbinfo)
    271 {
    272 	const pgp_contents_t	*content = &pkt->u;
    273 
    274 	if (pgp_get_debug_level(__FILE__)) {
    275 		printf("write_parsed_cb: ");
    276 		pgp_print_packet(&cbinfo->printstate, pkt);
    277 	}
    278 	if (pkt->tag != PGP_PTAG_CT_UNARMOURED_TEXT && cbinfo->printstate.skipping) {
    279 		puts("...end of skip");
    280 		cbinfo->printstate.skipping = 0;
    281 	}
    282 	switch (pkt->tag) {
    283 	case PGP_PTAG_CT_UNARMOURED_TEXT:
    284 		printf("PGP_PTAG_CT_UNARMOURED_TEXT\n");
    285 		if (!cbinfo->printstate.skipping) {
    286 			puts("Skipping...");
    287 			cbinfo->printstate.skipping = 1;
    288 		}
    289 		if (fwrite(content->unarmoured_text.data, 1,
    290 		       content->unarmoured_text.length, stdout) != content->unarmoured_text.length) {
    291 			fprintf(stderr, "unable to write unarmoured text data\n");
    292 			cbinfo->printstate.skipping = 1;
    293 		}
    294 		break;
    295 
    296 	case PGP_PTAG_CT_PK_SESSION_KEY:
    297 		return pgp_pk_sesskey_cb(pkt, cbinfo);
    298 
    299 	case PGP_GET_SECKEY:
    300 		if (cbinfo->sshseckey) {
    301 			*content->get_seckey.seckey = cbinfo->sshseckey;
    302 			return PGP_KEEP_MEMORY;
    303 		}
    304 		return pgp_get_seckey_cb(pkt, cbinfo);
    305 
    306 	case PGP_GET_PASSPHRASE:
    307 		return cbinfo->cryptinfo.getpassphrase(pkt, cbinfo);
    308 
    309 	case PGP_PTAG_CT_LITDATA_BODY:
    310 		return pgp_litdata_cb(pkt, cbinfo);
    311 
    312 	case PGP_PTAG_CT_ARMOUR_HEADER:
    313 	case PGP_PTAG_CT_ARMOUR_TRAILER:
    314 	case PGP_PTAG_CT_ENCRYPTED_PK_SESSION_KEY:
    315 	case PGP_PTAG_CT_COMPRESSED:
    316 	case PGP_PTAG_CT_LITDATA_HEADER:
    317 	case PGP_PTAG_CT_SE_IP_DATA_BODY:
    318 	case PGP_PTAG_CT_SE_IP_DATA_HEADER:
    319 	case PGP_PTAG_CT_SE_DATA_BODY:
    320 	case PGP_PTAG_CT_SE_DATA_HEADER:
    321 		/* Ignore these packets  */
    322 		/* They're handled in parse_packet() */
    323 		/* and nothing else needs to be done */
    324 		break;
    325 
    326 	default:
    327 		if (pgp_get_debug_level(__FILE__)) {
    328 			fprintf(stderr, "Unexpected packet tag=%d (0x%x)\n",
    329 				pkt->tag,
    330 				pkt->tag);
    331 		}
    332 		break;
    333 	}
    334 
    335 	return PGP_RELEASE_MEMORY;
    336 }
    337 
    338 /**
    339 \ingroup HighLevel_Crypto
    340 Encrypt a file
    341 \param infile Name of file to be encrypted
    342 \param outfile Name of file to write to. If NULL, name is constructed from infile
    343 \param pubkey Public Key to encrypt file for
    344 \param use_armour Write armoured text, if set
    345 \param allow_overwrite Allow output file to be overwrwritten if it exists
    346 \return 1 if OK; else 0
    347 */
    348 unsigned
    349 pgp_encrypt_file(pgp_io_t *io,
    350 			const char *infile,
    351 			const char *outfile,
    352 			const pgp_key_t *key,
    353 			const unsigned use_armour,
    354 			const unsigned allow_overwrite,
    355 			const char *cipher)
    356 {
    357 	pgp_output_t	*output;
    358 	pgp_memory_t	*inmem;
    359 	int		 fd_out;
    360 
    361 	__PGP_USED(io);
    362 	inmem = pgp_memory_new();
    363 	if (!pgp_mem_readfile(inmem, infile)) {
    364 		return 0;
    365 	}
    366 	fd_out = pgp_setup_file_write(&output, outfile, allow_overwrite);
    367 	if (fd_out < 0) {
    368 		pgp_memory_free(inmem);
    369 		return 0;
    370 	}
    371 
    372 	/* set armoured/not armoured here */
    373 	if (use_armour) {
    374 		pgp_writer_push_armor_msg(output);
    375 	}
    376 
    377 	/* Push the encrypted writer */
    378 	if (!pgp_push_enc_se_ip(output, key, cipher)) {
    379 		pgp_memory_free(inmem);
    380 		return 0;
    381 	}
    382 
    383 	/* This does the writing */
    384 	pgp_write(output, pgp_mem_data(inmem), (unsigned)pgp_mem_len(inmem));
    385 
    386 	/* tidy up */
    387 	pgp_memory_free(inmem);
    388 	pgp_teardown_file_write(output, fd_out);
    389 
    390 	return 1;
    391 }
    392 
    393 /* encrypt the contents of the input buffer, and return the mem structure */
    394 pgp_memory_t *
    395 pgp_encrypt_buf(pgp_io_t *io,
    396 			const void *input,
    397 			const size_t insize,
    398 			const pgp_key_t *pubkey,
    399 			const unsigned use_armour,
    400 			const char *cipher)
    401 {
    402 	pgp_output_t	*output;
    403 	pgp_memory_t	*outmem;
    404 
    405 	__PGP_USED(io);
    406 	if (input == NULL) {
    407 		(void) fprintf(io->errs,
    408 			"pgp_encrypt_buf: null memory\n");
    409 		return 0;
    410 	}
    411 
    412 	pgp_setup_memory_write(&output, &outmem, insize);
    413 
    414 	/* set armoured/not armoured here */
    415 	if (use_armour) {
    416 		pgp_writer_push_armor_msg(output);
    417 	}
    418 
    419 	/* Push the encrypted writer */
    420 	pgp_push_enc_se_ip(output, pubkey, cipher);
    421 
    422 	/* This does the writing */
    423 	pgp_write(output, input, (unsigned)insize);
    424 
    425 	/* tidy up */
    426 	pgp_writer_close(output);
    427 	pgp_output_delete(output);
    428 
    429 	return outmem;
    430 }
    431 
    432 /**
    433    \ingroup HighLevel_Crypto
    434    \brief Decrypt a file.
    435    \param infile Name of file to be decrypted
    436    \param outfile Name of file to write to. If NULL, the filename is constructed from the input filename, following GPG conventions.
    437    \param keyring Keyring to use
    438    \param use_armour Expect armoured text, if set
    439    \param allow_overwrite Allow output file to overwritten, if set.
    440    \param getpassfunc Callback to use to get passphrase
    441 */
    442 
    443 unsigned
    444 pgp_decrypt_file(pgp_io_t *io,
    445 			const char *infile,
    446 			const char *outfile,
    447 			pgp_keyring_t *secring,
    448 			pgp_keyring_t *pubring,
    449 			const unsigned use_armour,
    450 			const unsigned allow_overwrite,
    451 			const unsigned sshkeys,
    452 			void *passfp,
    453 			int numtries,
    454 			pgp_cbfunc_t *getpassfunc)
    455 {
    456 	pgp_stream_t	*parse = NULL;
    457 	const int	 printerrors = 1;
    458 	char		*filename = NULL;
    459 	int		 fd_in;
    460 	int		 fd_out;
    461 
    462 	/* setup for reading from given input file */
    463 	fd_in = pgp_setup_file_read(io, &parse, infile,
    464 				    NULL,
    465 				    write_parsed_cb,
    466 				    0);
    467 	if (fd_in < 0) {
    468 		perror(infile);
    469 		return 0;
    470 	}
    471 	/* setup output filename */
    472 	if (outfile) {
    473 		fd_out = pgp_setup_file_write(&parse->cbinfo.output, outfile,
    474 				allow_overwrite);
    475 		if (fd_out < 0) {
    476 			perror(outfile);
    477 			pgp_teardown_file_read(parse, fd_in);
    478 			return 0;
    479 		}
    480 	} else {
    481 		const int	suffixlen = 4;
    482 		const char     *suffix = infile + strlen(infile) - suffixlen;
    483 		unsigned	filenamelen;
    484 
    485 		if (strcmp(suffix, ".gpg") == 0 ||
    486 		    strcmp(suffix, ".asc") == 0) {
    487 			filenamelen = (unsigned)(strlen(infile) - strlen(suffix));
    488 			if ((filename = calloc(1, filenamelen + 1)) == NULL) {
    489 				(void) fprintf(stderr, "can't allocate %" PRIsize "d bytes\n",
    490 					(size_t)(filenamelen + 1));
    491 				return 0;
    492 			}
    493 			(void) strncpy(filename, infile, filenamelen);
    494 			filename[filenamelen] = 0x0;
    495 		}
    496 
    497 		fd_out = pgp_setup_file_write(&parse->cbinfo.output,
    498 					filename, allow_overwrite);
    499 		if (fd_out < 0) {
    500 			perror(filename);
    501 			free(filename);
    502 			pgp_teardown_file_read(parse, fd_in);
    503 			return 0;
    504 		}
    505 	}
    506 
    507 	/* \todo check for suffix matching armour param */
    508 
    509 	/* setup for writing decrypted contents to given output file */
    510 
    511 	/* setup keyring and passphrase callback */
    512 	parse->cbinfo.cryptinfo.secring = secring;
    513 	parse->cbinfo.passfp = passfp;
    514 	parse->cbinfo.cryptinfo.getpassphrase = getpassfunc;
    515 	parse->cbinfo.cryptinfo.pubring = pubring;
    516 	parse->cbinfo.sshseckey = (sshkeys) ? &secring->keys[0].key.seckey : NULL;
    517 	parse->cbinfo.numtries = numtries;
    518 
    519 	/* Set up armour/passphrase options */
    520 	if (use_armour) {
    521 		pgp_reader_push_dearmour(parse);
    522 	}
    523 
    524 	/* Do it */
    525 	pgp_parse(parse, printerrors);
    526 
    527 	/* Unsetup */
    528 	if (use_armour) {
    529 		pgp_reader_pop_dearmour(parse);
    530 	}
    531 
    532 	/* if we didn't get the passphrase, unlink output file */
    533 	if (!parse->cbinfo.gotpass) {
    534 		(void) unlink((filename) ? filename : outfile);
    535 	}
    536 
    537 	if (filename) {
    538 		pgp_teardown_file_write(parse->cbinfo.output, fd_out);
    539 		free(filename);
    540 	}
    541 	pgp_teardown_file_read(parse, fd_in);
    542 	/* \todo cleardown crypt */
    543 
    544 	return 1;
    545 }
    546 
    547 /* decrypt an area of memory */
    548 pgp_memory_t *
    549 pgp_decrypt_buf(pgp_io_t *io,
    550 			const void *input,
    551 			const size_t insize,
    552 			pgp_keyring_t *secring,
    553 			pgp_keyring_t *pubring,
    554 			const unsigned use_armour,
    555 			const unsigned sshkeys,
    556 			void *passfp,
    557 			int numtries,
    558 			pgp_cbfunc_t *getpassfunc)
    559 {
    560 	pgp_stream_t	*parse = NULL;
    561 	pgp_memory_t	*outmem;
    562 	pgp_memory_t	*inmem;
    563 	const int	 printerrors = 1;
    564 
    565 	if (input == NULL) {
    566 		(void) fprintf(io->errs,
    567 			"pgp_encrypt_buf: null memory\n");
    568 		return 0;
    569 	}
    570 
    571 	inmem = pgp_memory_new();
    572 	pgp_memory_add(inmem, input, insize);
    573 
    574 	/* set up to read from memory */
    575 	pgp_setup_memory_read(io, &parse, inmem,
    576 				    NULL,
    577 				    write_parsed_cb,
    578 				    0);
    579 
    580 	/* setup for writing decrypted contents to given output file */
    581 	pgp_setup_memory_write(&parse->cbinfo.output, &outmem, insize);
    582 
    583 	/* setup keyring and passphrase callback */
    584 	parse->cbinfo.cryptinfo.secring = secring;
    585 	parse->cbinfo.cryptinfo.pubring = pubring;
    586 	parse->cbinfo.passfp = passfp;
    587 	parse->cbinfo.cryptinfo.getpassphrase = getpassfunc;
    588 	parse->cbinfo.sshseckey = (sshkeys) ? &secring->keys[0].key.seckey : NULL;
    589 	parse->cbinfo.numtries = numtries;
    590 
    591 	/* Set up armour/passphrase options */
    592 	if (use_armour) {
    593 		pgp_reader_push_dearmour(parse);
    594 	}
    595 
    596 	/* Do it */
    597 	pgp_parse(parse, printerrors);
    598 
    599 	/* Unsetup */
    600 	if (use_armour) {
    601 		pgp_reader_pop_dearmour(parse);
    602 	}
    603 
    604 	/* tidy up */
    605 	pgp_teardown_memory_read(parse, inmem);
    606 
    607 	pgp_writer_close(parse->cbinfo.output);
    608 	pgp_output_delete(parse->cbinfo.output);
    609 
    610 	/* if we didn't get the passphrase, return NULL */
    611 	return (parse->cbinfo.gotpass) ? outmem : NULL;
    612 }
    613