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.24 2010/06/25 03:37:27 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 __ops_decrypt_decode_mpi(uint8_t *buf, 88 unsigned buflen, 89 const BIGNUM *encmpi, 90 const __ops_seckey_t *seckey) 91 { 92 uint8_t encmpibuf[NETPGP_BUFSIZ]; 93 uint8_t mpibuf[NETPGP_BUFSIZ]; 94 unsigned mpisize; 95 int n; 96 int i; 97 98 mpisize = (unsigned)BN_num_bytes(encmpi); 99 /* MPI can't be more than 65,536 */ 100 if (mpisize > sizeof(encmpibuf)) { 101 (void) fprintf(stderr, "mpisize too big %u\n", mpisize); 102 return -1; 103 } 104 BN_bn2bin(encmpi, encmpibuf); 105 106 if (seckey->pubkey.alg != OPS_PKA_RSA) { 107 (void) fprintf(stderr, "pubkey algorithm wrong\n"); 108 return -1; 109 } 110 111 if (__ops_get_debug_level(__FILE__)) { 112 hexdump(stderr, "encrypted", encmpibuf, 16); 113 } 114 n = __ops_rsa_private_decrypt(mpibuf, encmpibuf, 115 (unsigned)(BN_num_bits(encmpi) + 7) / 8, 116 &seckey->key.rsa, &seckey->pubkey.key.rsa); 117 if (n == -1) { 118 (void) fprintf(stderr, "ops_rsa_private_decrypt failure\n"); 119 return -1; 120 } 121 122 if (__ops_get_debug_level(__FILE__)) { 123 hexdump(stderr, "decrypted", mpibuf, 16); 124 } 125 if (n <= 0) { 126 return -1; 127 } 128 129 /* Decode EME-PKCS1_V1_5 (RFC 2437). */ 130 if (mpibuf[0] != 0 || mpibuf[1] != 2) { 131 return -1; 132 } 133 134 /* Skip the random bytes. */ 135 for (i = 2; i < n && mpibuf[i]; ++i) { 136 } 137 138 if (i == n || i < 10) { 139 return -1; 140 } 141 142 /* Skip the zero */ 143 i += 1; 144 145 /* this is the unencoded m buf */ 146 if ((unsigned) (n - i) <= buflen) { 147 (void) memcpy(buf, mpibuf + i, (unsigned)(n - i)); /* XXX - Flexelint */ 148 } 149 150 if (__ops_get_debug_level(__FILE__)) { 151 hexdump(stderr, "decoded m", buf, (size_t)(n - i)); 152 } 153 return n - i; 154 } 155 156 /** 157 \ingroup Core_MPI 158 \brief RSA-encrypt an MPI 159 */ 160 unsigned 161 __ops_rsa_encrypt_mpi(const uint8_t *encoded_m_buf, 162 const size_t sz_encoded_m_buf, 163 const __ops_pubkey_t * pubkey, 164 __ops_pk_sesskey_params_t * skp) 165 { 166 167 uint8_t encmpibuf[NETPGP_BUFSIZ]; 168 int n; 169 170 if (sz_encoded_m_buf != (size_t)BN_num_bytes(pubkey->key.rsa.n)) { 171 (void) fprintf(stderr, "sz_encoded_m_buf wrong\n"); 172 return 0; 173 } 174 175 n = __ops_rsa_public_encrypt(encmpibuf, encoded_m_buf, 176 sz_encoded_m_buf, &pubkey->key.rsa); 177 if (n == -1) { 178 (void) fprintf(stderr, "__ops_rsa_public_encrypt failure\n"); 179 return 0; 180 } 181 182 if (n <= 0) 183 return 0; 184 185 skp->rsa.encrypted_m = BN_bin2bn(encmpibuf, n, NULL); 186 187 if (__ops_get_debug_level(__FILE__)) { 188 hexdump(stderr, "encrypted mpi", encmpibuf, 16); 189 } 190 return 1; 191 } 192 193 static __ops_cb_ret_t 194 write_parsed_cb(const __ops_packet_t *pkt, __ops_cbdata_t *cbinfo) 195 { 196 const __ops_contents_t *content = &pkt->u; 197 198 if (__ops_get_debug_level(__FILE__)) { 199 printf("write_parsed_cb: "); 200 __ops_print_packet(&cbinfo->printstate, pkt); 201 } 202 if (pkt->tag != OPS_PTAG_CT_UNARMOURED_TEXT && cbinfo->printstate.skipping) { 203 puts("...end of skip"); 204 cbinfo->printstate.skipping = 0; 205 } 206 switch (pkt->tag) { 207 case OPS_PTAG_CT_UNARMOURED_TEXT: 208 printf("OPS_PTAG_CT_UNARMOURED_TEXT\n"); 209 if (!cbinfo->printstate.skipping) { 210 puts("Skipping..."); 211 cbinfo->printstate.skipping = 1; 212 } 213 fwrite(content->unarmoured_text.data, 1, 214 content->unarmoured_text.length, stdout); 215 break; 216 217 case OPS_PTAG_CT_PK_SESSION_KEY: 218 return pk_sesskey_cb(pkt, cbinfo); 219 220 case OPS_GET_SECKEY: 221 return get_seckey_cb(pkt, cbinfo); 222 223 case OPS_GET_PASSPHRASE: 224 return cbinfo->cryptinfo.getpassphrase(pkt, cbinfo); 225 226 case OPS_PTAG_CT_LITDATA_BODY: 227 return litdata_cb(pkt, cbinfo); 228 229 case OPS_PTAG_CT_ARMOUR_HEADER: 230 case OPS_PTAG_CT_ARMOUR_TRAILER: 231 case OPS_PTAG_CT_ENCRYPTED_PK_SESSION_KEY: 232 case OPS_PTAG_CT_COMPRESSED: 233 case OPS_PTAG_CT_LITDATA_HEADER: 234 case OPS_PTAG_CT_SE_IP_DATA_BODY: 235 case OPS_PTAG_CT_SE_IP_DATA_HEADER: 236 case OPS_PTAG_CT_SE_DATA_BODY: 237 case OPS_PTAG_CT_SE_DATA_HEADER: 238 /* Ignore these packets */ 239 /* They're handled in __ops_parse_packet() */ 240 /* and nothing else needs to be done */ 241 break; 242 243 default: 244 if (__ops_get_debug_level(__FILE__)) { 245 fprintf(stderr, "Unexpected packet tag=%d (0x%x)\n", 246 pkt->tag, 247 pkt->tag); 248 } 249 break; 250 } 251 252 return OPS_RELEASE_MEMORY; 253 } 254 255 /** 256 \ingroup HighLevel_Crypto 257 Encrypt a file 258 \param infile Name of file to be encrypted 259 \param outfile Name of file to write to. If NULL, name is constructed from infile 260 \param pubkey Public Key to encrypt file for 261 \param use_armour Write armoured text, if set 262 \param allow_overwrite Allow output file to be overwrwritten if it exists 263 \return 1 if OK; else 0 264 */ 265 unsigned 266 __ops_encrypt_file(__ops_io_t *io, 267 const char *infile, 268 const char *outfile, 269 const __ops_key_t *pubkey, 270 const unsigned use_armour, 271 const unsigned allow_overwrite) 272 { 273 __ops_output_t *output; 274 __ops_memory_t *inmem; 275 int fd_out; 276 277 __OPS_USED(io); 278 inmem = __ops_memory_new(); 279 if (!__ops_mem_readfile(inmem, infile)) { 280 return 0; 281 } 282 fd_out = __ops_setup_file_write(&output, outfile, allow_overwrite); 283 if (fd_out < 0) { 284 __ops_memory_free(inmem); 285 return 0; 286 } 287 288 /* set armoured/not armoured here */ 289 if (use_armour) { 290 __ops_writer_push_armor_msg(output); 291 } 292 293 /* Push the encrypted writer */ 294 __ops_push_enc_se_ip(output, pubkey); 295 296 /* This does the writing */ 297 __ops_write(output, __ops_mem_data(inmem), __ops_mem_len(inmem)); 298 299 /* tidy up */ 300 __ops_memory_free(inmem); 301 __ops_teardown_file_write(output, fd_out); 302 303 return 1; 304 } 305 306 /* encrypt the contents of the input buffer, and return the mem structure */ 307 __ops_memory_t * 308 __ops_encrypt_buf(__ops_io_t *io, 309 const void *input, 310 const size_t insize, 311 const __ops_key_t *pubkey, 312 const unsigned use_armour) 313 { 314 __ops_output_t *output; 315 __ops_memory_t *outmem; 316 317 __OPS_USED(io); 318 if (input == NULL) { 319 (void) fprintf(io->errs, 320 "__ops_encrypt_buf: null memory\n"); 321 return 0; 322 } 323 324 __ops_setup_memory_write(&output, &outmem, insize); 325 326 /* set armoured/not armoured here */ 327 if (use_armour) { 328 __ops_writer_push_armor_msg(output); 329 } 330 331 /* Push the encrypted writer */ 332 __ops_push_enc_se_ip(output, pubkey); 333 334 /* This does the writing */ 335 __ops_write(output, input, insize); 336 337 /* tidy up */ 338 __ops_writer_close(output); 339 __ops_output_delete(output); 340 341 return outmem; 342 } 343 344 /** 345 \ingroup HighLevel_Crypto 346 \brief Decrypt a file. 347 \param infile Name of file to be decrypted 348 \param outfile Name of file to write to. If NULL, the filename is constructed from the input filename, following GPG conventions. 349 \param keyring Keyring to use 350 \param use_armour Expect armoured text, if set 351 \param allow_overwrite Allow output file to overwritten, if set. 352 \param getpassfunc Callback to use to get passphrase 353 */ 354 355 unsigned 356 __ops_decrypt_file(__ops_io_t *io, 357 const char *infile, 358 const char *outfile, 359 __ops_keyring_t *secring, 360 __ops_keyring_t *pubring, 361 const unsigned use_armour, 362 const unsigned allow_overwrite, 363 void *passfp, 364 __ops_cbfunc_t *getpassfunc) 365 { 366 __ops_stream_t *parse = NULL; 367 const int printerrors = 1; 368 char *filename = NULL; 369 int fd_in; 370 int fd_out; 371 372 /* setup for reading from given input file */ 373 fd_in = __ops_setup_file_read(io, &parse, infile, 374 NULL, 375 write_parsed_cb, 376 0); 377 if (fd_in < 0) { 378 perror(infile); 379 return 0; 380 } 381 /* setup output filename */ 382 if (outfile) { 383 fd_out = __ops_setup_file_write(&parse->cbinfo.output, outfile, 384 allow_overwrite); 385 if (fd_out < 0) { 386 perror(outfile); 387 __ops_teardown_file_read(parse, fd_in); 388 return 0; 389 } 390 } else { 391 const int suffixlen = 4; 392 const char *suffix = infile + strlen(infile) - suffixlen; 393 unsigned filenamelen; 394 395 if (strcmp(suffix, ".gpg") == 0 || 396 strcmp(suffix, ".asc") == 0) { 397 filenamelen = strlen(infile) - strlen(suffix); 398 if ((filename = calloc(1, filenamelen + 1)) == NULL) { 399 (void) fprintf(stderr, "can't allocate %" PRIsize "d bytes\n", 400 (size_t)(filenamelen + 1)); 401 return 0; 402 } 403 (void) strncpy(filename, infile, filenamelen); 404 filename[filenamelen] = 0x0; 405 } 406 407 fd_out = __ops_setup_file_write(&parse->cbinfo.output, 408 filename, allow_overwrite); 409 if (fd_out < 0) { 410 perror(filename); 411 free(filename); 412 __ops_teardown_file_read(parse, fd_in); 413 return 0; 414 } 415 } 416 417 /* \todo check for suffix matching armour param */ 418 419 /* setup for writing decrypted contents to given output file */ 420 421 /* setup keyring and passphrase callback */ 422 parse->cbinfo.cryptinfo.secring = secring; 423 parse->cbinfo.passfp = passfp; 424 parse->cbinfo.cryptinfo.getpassphrase = getpassfunc; 425 parse->cbinfo.cryptinfo.pubring = pubring; 426 427 /* Set up armour/passphrase options */ 428 if (use_armour) { 429 __ops_reader_push_dearmour(parse); 430 } 431 432 /* Do it */ 433 __ops_parse(parse, printerrors); 434 435 /* Unsetup */ 436 if (use_armour) { 437 __ops_reader_pop_dearmour(parse); 438 } 439 440 if (filename) { 441 __ops_teardown_file_write(parse->cbinfo.output, fd_out); 442 free(filename); 443 } 444 __ops_teardown_file_read(parse, fd_in); 445 /* \todo cleardown crypt */ 446 447 return 1; 448 } 449 450 /* decrypt an area of memory */ 451 __ops_memory_t * 452 __ops_decrypt_buf(__ops_io_t *io, 453 const void *input, 454 const size_t insize, 455 __ops_keyring_t *secring, 456 __ops_keyring_t *pubring, 457 const unsigned use_armour, 458 void *passfp, 459 __ops_cbfunc_t *getpassfunc) 460 { 461 __ops_stream_t *parse = NULL; 462 __ops_memory_t *outmem; 463 __ops_memory_t *inmem; 464 const int printerrors = 1; 465 466 if (input == NULL) { 467 (void) fprintf(io->errs, 468 "__ops_encrypt_buf: null memory\n"); 469 return 0; 470 } 471 472 inmem = __ops_memory_new(); 473 __ops_memory_add(inmem, input, insize); 474 475 /* set up to read from memory */ 476 __ops_setup_memory_read(io, &parse, inmem, 477 NULL, 478 write_parsed_cb, 479 0); 480 481 /* setup for writing decrypted contents to given output file */ 482 __ops_setup_memory_write(&parse->cbinfo.output, &outmem, insize); 483 484 /* setup keyring and passphrase callback */ 485 parse->cbinfo.cryptinfo.secring = secring; 486 parse->cbinfo.cryptinfo.pubring = pubring; 487 parse->cbinfo.passfp = passfp; 488 parse->cbinfo.cryptinfo.getpassphrase = getpassfunc; 489 490 /* Set up armour/passphrase options */ 491 if (use_armour) { 492 __ops_reader_push_dearmour(parse); 493 } 494 495 /* Do it */ 496 __ops_parse(parse, printerrors); 497 498 /* Unsetup */ 499 if (use_armour) { 500 __ops_reader_pop_dearmour(parse); 501 } 502 503 /* tidy up */ 504 __ops_teardown_memory_read(parse, inmem); 505 __ops_memory_release(inmem); 506 free(inmem); 507 508 __ops_writer_close(parse->cbinfo.output); 509 __ops_output_delete(parse->cbinfo.output); 510 511 return outmem; 512 } 513 514