1 /* 2 * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) 3 * All rights reserved. 4 * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted 5 * their moral rights under the UK Copyright Design and Patents Act 1988 to 6 * be recorded as the authors of this copyright work. 7 * 8 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 9 * use this file except in compliance with the License. 10 * 11 * You may obtain a copy of the License at 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * 18 * See the License for the specific language governing permissions and 19 * limitations under the License. 20 */ 21 #include "config.h" 22 23 #include "crypto.h" 24 25 #include "readerwriter.h" 26 #include "memory.h" 27 #include "parse_local.h" 28 #include "netpgpdefs.h" 29 30 #ifdef HAVE_ASSERT_H 31 #include <assert.h> 32 #endif 33 34 #include <string.h> 35 #include <fcntl.h> 36 37 /** 38 \ingroup Core_MPI 39 \brief Decrypt and unencode MPI 40 \param buf Buffer in which to write decrypted unencoded MPI 41 \param buflen Length of buffer 42 \param encmpi 43 \param skey 44 \return length of MPI 45 \note only RSA at present 46 */ 47 int 48 __ops_decrypt_and_unencode_mpi(unsigned char *buf, unsigned buflen, const BIGNUM * encmpi, 49 const __ops_secret_key_t * skey) 50 { 51 unsigned char encmpibuf[NETPGP_BUFSIZ]; 52 unsigned char mpibuf[NETPGP_BUFSIZ]; 53 unsigned mpisize; 54 int n; 55 int i; 56 57 mpisize = BN_num_bytes(encmpi); 58 /* MPI can't be more than 65,536 */ 59 assert(mpisize <= sizeof(encmpibuf)); 60 BN_bn2bin(encmpi, encmpibuf); 61 62 assert(skey->public_key.algorithm == OPS_PKA_RSA); 63 64 if (__ops_get_debug_level(__FILE__)) { 65 fprintf(stderr, "\nDECRYPTING\n"); 66 fprintf(stderr, "encrypted data : "); 67 for (i = 0; i < 16; i++) { 68 fprintf(stderr, "%2x ", encmpibuf[i]); 69 } 70 fprintf(stderr, "\n"); 71 } 72 n = __ops_rsa_private_decrypt(mpibuf, encmpibuf, (BN_num_bits(encmpi) + 7) / 8, 73 &skey->key.rsa, &skey->public_key.key.rsa); 74 assert(n != -1); 75 76 if (__ops_get_debug_level(__FILE__)) { 77 fprintf(stderr, "decrypted encoded m buf : "); 78 for (i = 0; i < 16; i++) 79 fprintf(stderr, "%2x ", mpibuf[i]); 80 fprintf(stderr, "\n"); 81 } 82 if (n <= 0) 83 return -1; 84 85 if (__ops_get_debug_level(__FILE__)) { 86 printf(" decrypted=%d ", n); 87 hexdump(mpibuf, n, ""); 88 printf("\n"); 89 } 90 /* Decode EME-PKCS1_V1_5 (RFC 2437). */ 91 92 if (mpibuf[0] != 0 || mpibuf[1] != 2) 93 return false; 94 95 /* Skip the random bytes. */ 96 for (i = 2; i < n && mpibuf[i]; ++i); 97 98 if (i == n || i < 10) 99 return false; 100 101 /* Skip the zero */ 102 ++i; 103 104 /* this is the unencoded m buf */ 105 if ((unsigned) (n - i) <= buflen) 106 (void) memcpy(buf, mpibuf + i, n - i); 107 108 if (__ops_get_debug_level(__FILE__)) { 109 int j; 110 111 printf("decoded m buf:\n"); 112 for (j = 0; j < n - i; j++) 113 printf("%2x ", buf[j]); 114 printf("\n"); 115 } 116 return n - i; 117 } 118 119 /** 120 \ingroup Core_MPI 121 \brief RSA-encrypt an MPI 122 */ 123 bool 124 __ops_rsa_encrypt_mpi(const unsigned char *encoded_m_buf, 125 const size_t sz_encoded_m_buf, 126 const __ops_public_key_t * pkey, 127 __ops_pk_session_key_parameters_t * skp) 128 { 129 130 unsigned char encmpibuf[NETPGP_BUFSIZ]; 131 int n = 0; 132 133 assert(sz_encoded_m_buf == (size_t) BN_num_bytes(pkey->key.rsa.n)); 134 135 n = __ops_rsa_public_encrypt(encmpibuf, encoded_m_buf, sz_encoded_m_buf, &pkey->key.rsa); 136 assert(n != -1); 137 138 if (n <= 0) 139 return false; 140 141 skp->rsa.encrypted_m = BN_bin2bn(encmpibuf, n, NULL); 142 143 if (__ops_get_debug_level(__FILE__)) { 144 int i; 145 fprintf(stderr, "encrypted mpi buf : "); 146 for (i = 0; i < 16; i++) { 147 fprintf(stderr, "%2x ", encmpibuf[i]); 148 } 149 fprintf(stderr, "\n"); 150 } 151 return true; 152 } 153 154 static __ops_parse_cb_return_t 155 callback_write_parsed(const __ops_parser_content_t * contents, __ops_parse_cb_info_t * cbinfo); 156 157 /** 158 \ingroup HighLevel_Crypto 159 Encrypt a file 160 \param input_filename Name of file to be encrypted 161 \param output_filename Name of file to write to. If NULL, name is constructed from input_filename 162 \param pub_key Public Key to encrypt file for 163 \param use_armour Write armoured text, if set 164 \param allow_overwrite Allow output file to be overwrwritten if it exists 165 \return true if OK; else false 166 */ 167 bool 168 __ops_encrypt_file(const char *input_filename, const char *output_filename, const __ops_keydata_t * pub_key, const bool use_armour, const bool allow_overwrite) 169 { 170 int fd_in = 0; 171 int fd_out = 0; 172 173 __ops_create_info_t *create; 174 175 unsigned char *buf; 176 size_t bufsz; 177 int done; 178 179 #ifdef O_BINARY 180 fd_in = open(input_filename, O_RDONLY | O_BINARY); 181 #else 182 fd_in = open(input_filename, O_RDONLY); 183 #endif 184 if (fd_in < 0) { 185 perror(input_filename); 186 return false; 187 } 188 fd_out = __ops_setup_file_write(&create, output_filename, allow_overwrite); 189 if (fd_out < 0) 190 return false; 191 192 /* set armoured/not armoured here */ 193 if (use_armour) 194 __ops_writer_push_armoured_message(create); 195 196 /* Push the encrypted writer */ 197 __ops_writer_push_encrypt_se_ip(create, pub_key); 198 199 /* Do the writing */ 200 201 buf = NULL; 202 bufsz = 16; 203 done = 0; 204 for (;;) { 205 int n = 0; 206 207 buf = realloc(buf, done + bufsz); 208 209 n = read(fd_in, buf + done, bufsz); 210 if (!n) 211 break; 212 assert(n >= 0); 213 done += n; 214 } 215 216 /* This does the writing */ 217 __ops_write(buf, done, create); 218 219 /* tidy up */ 220 close(fd_in); 221 free(buf); 222 __ops_teardown_file_write(create, fd_out); 223 224 return true; 225 } 226 227 /** 228 \ingroup HighLevel_Crypto 229 \brief Decrypt a file. 230 \param input_filename Name of file to be decrypted 231 \param output_filename Name of file to write to. If NULL, the filename is constructed from the input filename, following GPG conventions. 232 \param keyring Keyring to use 233 \param use_armour Expect armoured text, if set 234 \param allow_overwrite Allow output file to overwritten, if set. 235 \param cb_get_passphrase Callback to use to get passphrase 236 */ 237 238 bool 239 __ops_decrypt_file(const char *input_filename, const char *output_filename, __ops_keyring_t * keyring, const bool use_armour, const bool allow_overwrite, __ops_parse_cb_t * cb_get_passphrase) 240 { 241 int fd_in = 0; 242 int fd_out = 0; 243 char *myfilename = NULL; 244 __ops_parse_info_t *parse = NULL; 245 246 /* setup for reading from given input file */ 247 fd_in = __ops_setup_file_read(&parse, input_filename, 248 NULL, 249 callback_write_parsed, 250 false); 251 if (fd_in < 0) { 252 perror(input_filename); 253 return false; 254 } 255 /* setup output filename */ 256 257 if (output_filename) { 258 fd_out = __ops_setup_file_write(&parse->cbinfo.cinfo, output_filename, allow_overwrite); 259 260 if (fd_out < 0) { 261 perror(output_filename); 262 __ops_teardown_file_read(parse, fd_in); 263 return false; 264 } 265 } else { 266 int suffixlen = 4; 267 const char *defaultsuffix = ".decrypted"; 268 const char *suffix = input_filename + strlen(input_filename) - suffixlen; 269 if (strcmp(suffix, ".gpg") == 0 || 270 strcmp(suffix, ".asc") == 0) { 271 myfilename = calloc(1, strlen(input_filename) - suffixlen + 1); 272 strncpy(myfilename, input_filename, strlen(input_filename) - suffixlen); 273 } else { 274 unsigned filenamelen = strlen(input_filename) + strlen(defaultsuffix) + 1; 275 276 myfilename = calloc(1, filenamelen); 277 snprintf(myfilename, filenamelen, "%s%s", input_filename, defaultsuffix); 278 } 279 280 fd_out = __ops_setup_file_write(&parse->cbinfo.cinfo, myfilename, allow_overwrite); 281 282 if (fd_out < 0) { 283 perror(myfilename); 284 free(myfilename); 285 __ops_teardown_file_read(parse, fd_in); 286 return false; 287 } 288 free(myfilename); 289 } 290 291 /* \todo check for suffix matching armour param */ 292 293 /* setup for writing decrypted contents to given output file */ 294 295 /* setup keyring and passphrase callback */ 296 parse->cbinfo.cryptinfo.keyring = keyring; 297 parse->cbinfo.cryptinfo.cb_get_passphrase = cb_get_passphrase; 298 299 /* Set up armour/passphrase options */ 300 301 if (use_armour) 302 __ops_reader_push_dearmour(parse); 303 304 /* Do it */ 305 306 __ops_parse_and_print_errors(parse); 307 308 /* Unsetup */ 309 310 if (use_armour) 311 __ops_reader_pop_dearmour(parse); 312 313 __ops_teardown_file_write(parse->cbinfo.cinfo, fd_out); 314 __ops_teardown_file_read(parse, fd_in); 315 /* \todo cleardown crypt */ 316 317 return true; 318 } 319 320 static __ops_parse_cb_return_t 321 callback_write_parsed(const __ops_parser_content_t *contents, __ops_parse_cb_info_t * cbinfo) 322 { 323 const __ops_parser_content_union_t *content = &contents->u; 324 static bool skipping; 325 326 OPS_USED(cbinfo); 327 328 if (__ops_get_debug_level(__FILE__)) { 329 printf("callback_write_parsed: "); 330 __ops_print_packet(contents); 331 } 332 if (contents->tag != OPS_PTAG_CT_UNARMOURED_TEXT && skipping) { 333 puts("...end of skip"); 334 skipping = false; 335 } 336 switch (contents->tag) { 337 case OPS_PTAG_CT_UNARMOURED_TEXT: 338 printf("OPS_PTAG_CT_UNARMOURED_TEXT\n"); 339 if (!skipping) { 340 puts("Skipping..."); 341 skipping = true; 342 } 343 fwrite(content->unarmoured_text.data, 1, 344 content->unarmoured_text.length, stdout); 345 break; 346 347 case OPS_PTAG_CT_PK_SESSION_KEY: 348 return pk_session_key_cb(contents, cbinfo); 349 350 case OPS_PARSER_CMD_GET_SECRET_KEY: 351 return get_secret_key_cb(contents, cbinfo); 352 353 case OPS_PARSER_CMD_GET_SK_PASSPHRASE: 354 /* 355 * return 356 * get_secret_key_cb(contents,cbinfo); 357 */ 358 return cbinfo->cryptinfo.cb_get_passphrase(contents, cbinfo); 359 360 case OPS_PTAG_CT_LITERAL_DATA_BODY: 361 return literal_data_cb(contents, cbinfo); 362 363 case OPS_PTAG_CT_ARMOUR_HEADER: 364 case OPS_PTAG_CT_ARMOUR_TRAILER: 365 case OPS_PTAG_CT_ENCRYPTED_PK_SESSION_KEY: 366 case OPS_PTAG_CT_COMPRESSED: 367 case OPS_PTAG_CT_LITERAL_DATA_HEADER: 368 case OPS_PTAG_CT_SE_IP_DATA_BODY: 369 case OPS_PTAG_CT_SE_IP_DATA_HEADER: 370 case OPS_PTAG_CT_SE_DATA_BODY: 371 case OPS_PTAG_CT_SE_DATA_HEADER: 372 373 /* Ignore these packets */ 374 /* They're handled in __ops_parse_packet() */ 375 /* and nothing else needs to be done */ 376 break; 377 378 default: 379 /* return callback_general(contents,cbinfo); */ 380 if (__ops_get_debug_level(__FILE__)) { 381 fprintf(stderr, "Unexpected packet tag=%d (0x%x)\n", 382 contents->tag, 383 contents->tag); 384 } 385 break; 386 } 387 388 return OPS_RELEASE_MEMORY; 389 } 390