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.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
pgp_decrypt_decode_mpi(uint8_t * buf,unsigned buflen,const BIGNUM * g_to_k,const BIGNUM * encmpi,const pgp_seckey_t * seckey)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
pgp_rsa_encrypt_mpi(const uint8_t * encoded_m_buf,const size_t sz_encoded_m_buf,const pgp_pubkey_t * pubkey,pgp_pk_sesskey_params_t * skp)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
pgp_elgamal_encrypt_mpi(const uint8_t * encoded_m_buf,const size_t sz_encoded_m_buf,const pgp_pubkey_t * pubkey,pgp_pk_sesskey_params_t * skp)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
write_parsed_cb(const pgp_packet_t * pkt,pgp_cbdata_t * cbinfo)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
pgp_encrypt_file(pgp_io_t * io,const char * infile,const char * outfile,const pgp_key_t * key,const unsigned use_armour,const unsigned allow_overwrite,const char * cipher)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 *
pgp_encrypt_buf(pgp_io_t * io,const void * input,const size_t insize,const pgp_key_t * pubkey,const unsigned use_armour,const char * cipher)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
pgp_decrypt_file(pgp_io_t * io,const char * infile,const char * outfile,pgp_keyring_t * secring,pgp_keyring_t * pubring,const unsigned use_armour,const unsigned allow_overwrite,const unsigned sshkeys,void * passfp,int numtries,pgp_cbfunc_t * getpassfunc)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 *
pgp_decrypt_buf(pgp_io_t * io,const void * input,const size_t insize,pgp_keyring_t * secring,pgp_keyring_t * pubring,const unsigned use_armour,const unsigned sshkeys,void * passfp,int numtries,pgp_cbfunc_t * getpassfunc)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