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 */ 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 fwrite(content->unarmoured_text.data, 1, 290 content->unarmoured_text.length, stdout); 291 break; 292 293 case PGP_PTAG_CT_PK_SESSION_KEY: 294 return pgp_pk_sesskey_cb(pkt, cbinfo); 295 296 case PGP_GET_SECKEY: 297 if (cbinfo->sshseckey) { 298 *content->get_seckey.seckey = cbinfo->sshseckey; 299 return PGP_KEEP_MEMORY; 300 } 301 return pgp_get_seckey_cb(pkt, cbinfo); 302 303 case PGP_GET_PASSPHRASE: 304 return cbinfo->cryptinfo.getpassphrase(pkt, cbinfo); 305 306 case PGP_PTAG_CT_LITDATA_BODY: 307 return pgp_litdata_cb(pkt, cbinfo); 308 309 case PGP_PTAG_CT_ARMOUR_HEADER: 310 case PGP_PTAG_CT_ARMOUR_TRAILER: 311 case PGP_PTAG_CT_ENCRYPTED_PK_SESSION_KEY: 312 case PGP_PTAG_CT_COMPRESSED: 313 case PGP_PTAG_CT_LITDATA_HEADER: 314 case PGP_PTAG_CT_SE_IP_DATA_BODY: 315 case PGP_PTAG_CT_SE_IP_DATA_HEADER: 316 case PGP_PTAG_CT_SE_DATA_BODY: 317 case PGP_PTAG_CT_SE_DATA_HEADER: 318 /* Ignore these packets */ 319 /* They're handled in parse_packet() */ 320 /* and nothing else needs to be done */ 321 break; 322 323 default: 324 if (pgp_get_debug_level(__FILE__)) { 325 fprintf(stderr, "Unexpected packet tag=%d (0x%x)\n", 326 pkt->tag, 327 pkt->tag); 328 } 329 break; 330 } 331 332 return PGP_RELEASE_MEMORY; 333 } 334 335 /** 336 \ingroup HighLevel_Crypto 337 Encrypt a file 338 \param infile Name of file to be encrypted 339 \param outfile Name of file to write to. If NULL, name is constructed from infile 340 \param pubkey Public Key to encrypt file for 341 \param use_armour Write armoured text, if set 342 \param allow_overwrite Allow output file to be overwrwritten if it exists 343 \return 1 if OK; else 0 344 */ 345 unsigned 346 pgp_encrypt_file(pgp_io_t *io, 347 const char *infile, 348 const char *outfile, 349 const pgp_key_t *key, 350 const unsigned use_armour, 351 const unsigned allow_overwrite, 352 const char *cipher) 353 { 354 pgp_output_t *output; 355 pgp_memory_t *inmem; 356 int fd_out; 357 358 __PGP_USED(io); 359 inmem = pgp_memory_new(); 360 if (!pgp_mem_readfile(inmem, infile)) { 361 return 0; 362 } 363 fd_out = pgp_setup_file_write(&output, outfile, allow_overwrite); 364 if (fd_out < 0) { 365 pgp_memory_free(inmem); 366 return 0; 367 } 368 369 /* set armoured/not armoured here */ 370 if (use_armour) { 371 pgp_writer_push_armor_msg(output); 372 } 373 374 /* Push the encrypted writer */ 375 if (!pgp_push_enc_se_ip(output, key, cipher)) { 376 pgp_memory_free(inmem); 377 return 0; 378 } 379 380 /* This does the writing */ 381 pgp_write(output, pgp_mem_data(inmem), (unsigned)pgp_mem_len(inmem)); 382 383 /* tidy up */ 384 pgp_memory_free(inmem); 385 pgp_teardown_file_write(output, fd_out); 386 387 return 1; 388 } 389 390 /* encrypt the contents of the input buffer, and return the mem structure */ 391 pgp_memory_t * 392 pgp_encrypt_buf(pgp_io_t *io, 393 const void *input, 394 const size_t insize, 395 const pgp_key_t *pubkey, 396 const unsigned use_armour, 397 const char *cipher) 398 { 399 pgp_output_t *output; 400 pgp_memory_t *outmem; 401 402 __PGP_USED(io); 403 if (input == NULL) { 404 (void) fprintf(io->errs, 405 "pgp_encrypt_buf: null memory\n"); 406 return 0; 407 } 408 409 pgp_setup_memory_write(&output, &outmem, insize); 410 411 /* set armoured/not armoured here */ 412 if (use_armour) { 413 pgp_writer_push_armor_msg(output); 414 } 415 416 /* Push the encrypted writer */ 417 pgp_push_enc_se_ip(output, pubkey, cipher); 418 419 /* This does the writing */ 420 pgp_write(output, input, (unsigned)insize); 421 422 /* tidy up */ 423 pgp_writer_close(output); 424 pgp_output_delete(output); 425 426 return outmem; 427 } 428 429 /** 430 \ingroup HighLevel_Crypto 431 \brief Decrypt a file. 432 \param infile Name of file to be decrypted 433 \param outfile Name of file to write to. If NULL, the filename is constructed from the input filename, following GPG conventions. 434 \param keyring Keyring to use 435 \param use_armour Expect armoured text, if set 436 \param allow_overwrite Allow output file to overwritten, if set. 437 \param getpassfunc Callback to use to get passphrase 438 */ 439 440 unsigned 441 pgp_decrypt_file(pgp_io_t *io, 442 const char *infile, 443 const char *outfile, 444 pgp_keyring_t *secring, 445 pgp_keyring_t *pubring, 446 const unsigned use_armour, 447 const unsigned allow_overwrite, 448 const unsigned sshkeys, 449 void *passfp, 450 int numtries, 451 pgp_cbfunc_t *getpassfunc) 452 { 453 pgp_stream_t *parse = NULL; 454 const int printerrors = 1; 455 char *filename = NULL; 456 int fd_in; 457 int fd_out; 458 459 /* setup for reading from given input file */ 460 fd_in = pgp_setup_file_read(io, &parse, infile, 461 NULL, 462 write_parsed_cb, 463 0); 464 if (fd_in < 0) { 465 perror(infile); 466 return 0; 467 } 468 /* setup output filename */ 469 if (outfile) { 470 fd_out = pgp_setup_file_write(&parse->cbinfo.output, outfile, 471 allow_overwrite); 472 if (fd_out < 0) { 473 perror(outfile); 474 pgp_teardown_file_read(parse, fd_in); 475 return 0; 476 } 477 } else { 478 const int suffixlen = 4; 479 const char *suffix = infile + strlen(infile) - suffixlen; 480 unsigned filenamelen; 481 482 if (strcmp(suffix, ".gpg") == 0 || 483 strcmp(suffix, ".asc") == 0) { 484 filenamelen = (unsigned)(strlen(infile) - strlen(suffix)); 485 if ((filename = calloc(1, filenamelen + 1)) == NULL) { 486 (void) fprintf(stderr, "can't allocate %" PRIsize "d bytes\n", 487 (size_t)(filenamelen + 1)); 488 return 0; 489 } 490 (void) strncpy(filename, infile, filenamelen); 491 filename[filenamelen] = 0x0; 492 } 493 494 fd_out = pgp_setup_file_write(&parse->cbinfo.output, 495 filename, allow_overwrite); 496 if (fd_out < 0) { 497 perror(filename); 498 free(filename); 499 pgp_teardown_file_read(parse, fd_in); 500 return 0; 501 } 502 } 503 504 /* \todo check for suffix matching armour param */ 505 506 /* setup for writing decrypted contents to given output file */ 507 508 /* setup keyring and passphrase callback */ 509 parse->cbinfo.cryptinfo.secring = secring; 510 parse->cbinfo.passfp = passfp; 511 parse->cbinfo.cryptinfo.getpassphrase = getpassfunc; 512 parse->cbinfo.cryptinfo.pubring = pubring; 513 parse->cbinfo.sshseckey = (sshkeys) ? &secring->keys[0].key.seckey : NULL; 514 parse->cbinfo.numtries = numtries; 515 516 /* Set up armour/passphrase options */ 517 if (use_armour) { 518 pgp_reader_push_dearmour(parse); 519 } 520 521 /* Do it */ 522 pgp_parse(parse, printerrors); 523 524 /* Unsetup */ 525 if (use_armour) { 526 pgp_reader_pop_dearmour(parse); 527 } 528 529 /* if we didn't get the passphrase, unlink output file */ 530 if (!parse->cbinfo.gotpass) { 531 (void) unlink((filename) ? filename : outfile); 532 } 533 534 if (filename) { 535 pgp_teardown_file_write(parse->cbinfo.output, fd_out); 536 free(filename); 537 } 538 pgp_teardown_file_read(parse, fd_in); 539 /* \todo cleardown crypt */ 540 541 return 1; 542 } 543 544 /* decrypt an area of memory */ 545 pgp_memory_t * 546 pgp_decrypt_buf(pgp_io_t *io, 547 const void *input, 548 const size_t insize, 549 pgp_keyring_t *secring, 550 pgp_keyring_t *pubring, 551 const unsigned use_armour, 552 const unsigned sshkeys, 553 void *passfp, 554 int numtries, 555 pgp_cbfunc_t *getpassfunc) 556 { 557 pgp_stream_t *parse = NULL; 558 pgp_memory_t *outmem; 559 pgp_memory_t *inmem; 560 const int printerrors = 1; 561 562 if (input == NULL) { 563 (void) fprintf(io->errs, 564 "pgp_encrypt_buf: null memory\n"); 565 return 0; 566 } 567 568 inmem = pgp_memory_new(); 569 pgp_memory_add(inmem, input, insize); 570 571 /* set up to read from memory */ 572 pgp_setup_memory_read(io, &parse, inmem, 573 NULL, 574 write_parsed_cb, 575 0); 576 577 /* setup for writing decrypted contents to given output file */ 578 pgp_setup_memory_write(&parse->cbinfo.output, &outmem, insize); 579 580 /* setup keyring and passphrase callback */ 581 parse->cbinfo.cryptinfo.secring = secring; 582 parse->cbinfo.cryptinfo.pubring = pubring; 583 parse->cbinfo.passfp = passfp; 584 parse->cbinfo.cryptinfo.getpassphrase = getpassfunc; 585 parse->cbinfo.sshseckey = (sshkeys) ? &secring->keys[0].key.seckey : NULL; 586 parse->cbinfo.numtries = numtries; 587 588 /* Set up armour/passphrase options */ 589 if (use_armour) { 590 pgp_reader_push_dearmour(parse); 591 } 592 593 /* Do it */ 594 pgp_parse(parse, printerrors); 595 596 /* Unsetup */ 597 if (use_armour) { 598 pgp_reader_pop_dearmour(parse); 599 } 600 601 /* tidy up */ 602 pgp_teardown_memory_read(parse, inmem); 603 604 pgp_writer_close(parse->cbinfo.output); 605 pgp_output_delete(parse->cbinfo.output); 606 607 /* if we didn't get the passphrase, return NULL */ 608 return (parse->cbinfo.gotpass) ? outmem : NULL; 609 } 610