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#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.35 2011/01/02 18:13:10 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*/
86int
87pgp_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*/
197unsigned
198pgp_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*/
234unsigned
235pgp_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
269static pgp_cb_ret_t
270write_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
340Encrypt 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*/
348unsigned
349pgp_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 */
394pgp_memory_t *
395pgp_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
443unsigned
444pgp_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 */
548pgp_memory_t *
549pgp_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