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 #include "packet-show.h" 25 26 #include <string.h> 27 28 #ifdef HAVE_ASSERT_H 29 #include <assert.h> 30 #endif 31 32 #ifdef HAVE_OPENSSL_CAST_H 33 #include <openssl/cast.h> 34 #endif 35 36 #ifdef HAVE_OPENSSL_IDEA_H 37 #include <openssl/idea.h> 38 #endif 39 40 #ifdef HAVE_OPENSSL_AES_H 41 #include <openssl/aes.h> 42 #endif 43 44 #ifdef HAVE_OPENSSL_DES_H 45 #include <openssl/des.h> 46 #endif 47 48 #include "parse_local.h" 49 #include "netpgpdefs.h" 50 51 52 static void 53 std_set_iv(__ops_crypt_t * crypt, const unsigned char *iv) 54 { 55 (void) memcpy(crypt->iv, iv, crypt->blocksize); 56 crypt->num = 0; 57 } 58 59 static void 60 std_set_key(__ops_crypt_t * crypt, const unsigned char *key) 61 { 62 (void) memcpy(crypt->key, key, crypt->keysize); 63 } 64 65 static void 66 std_resync(__ops_crypt_t * decrypt) 67 { 68 if ((size_t) decrypt->num == decrypt->blocksize) 69 return; 70 71 memmove(decrypt->civ + decrypt->blocksize - decrypt->num, decrypt->civ, 72 decrypt->num); 73 (void) memcpy(decrypt->civ, decrypt->siv + decrypt->num, 74 decrypt->blocksize - decrypt->num); 75 decrypt->num = 0; 76 } 77 78 static void 79 std_finish(__ops_crypt_t * crypt) 80 { 81 if (crypt->encrypt_key) { 82 free(crypt->encrypt_key); 83 crypt->encrypt_key = NULL; 84 } 85 if (crypt->decrypt_key) { 86 free(crypt->decrypt_key); 87 crypt->decrypt_key = NULL; 88 } 89 } 90 91 static void 92 cast5_init(__ops_crypt_t * crypt) 93 { 94 if (crypt->encrypt_key) 95 free(crypt->encrypt_key); 96 crypt->encrypt_key = calloc(1, sizeof(CAST_KEY)); 97 CAST_set_key(crypt->encrypt_key, crypt->keysize, crypt->key); 98 crypt->decrypt_key = calloc(1, sizeof(CAST_KEY)); 99 CAST_set_key(crypt->decrypt_key, crypt->keysize, crypt->key); 100 } 101 102 static void 103 cast5_block_encrypt(__ops_crypt_t * crypt, void *out, const void *in) 104 { 105 CAST_ecb_encrypt(in, out, crypt->encrypt_key, CAST_ENCRYPT); 106 } 107 108 static void 109 cast5_block_decrypt(__ops_crypt_t * crypt, void *out, const void *in) 110 { 111 CAST_ecb_encrypt(in, out, crypt->encrypt_key, CAST_DECRYPT); 112 } 113 114 static void 115 cast5_cfb_encrypt(__ops_crypt_t * crypt, void *out, const void *in, size_t count) 116 { 117 CAST_cfb64_encrypt(in, out, count, 118 crypt->encrypt_key, crypt->iv, &crypt->num, 119 CAST_ENCRYPT); 120 } 121 122 static void 123 cast5_cfb_decrypt(__ops_crypt_t * crypt, void *out, const void *in, size_t count) 124 { 125 CAST_cfb64_encrypt(in, out, count, 126 crypt->encrypt_key, crypt->iv, &crypt->num, 127 CAST_DECRYPT); 128 } 129 130 #define TRAILER "","","","",0,NULL,NULL 131 132 static __ops_crypt_t cast5 = 133 { 134 OPS_SA_CAST5, 135 CAST_BLOCK, 136 CAST_KEY_LENGTH, 137 std_set_iv, 138 std_set_key, 139 cast5_init, 140 std_resync, 141 cast5_block_encrypt, 142 cast5_block_decrypt, 143 cast5_cfb_encrypt, 144 cast5_cfb_decrypt, 145 std_finish, 146 TRAILER 147 }; 148 149 #ifndef OPENSSL_NO_IDEA 150 static void 151 idea_init(__ops_crypt_t * crypt) 152 { 153 assert(crypt->keysize == IDEA_KEY_LENGTH); 154 155 if (crypt->encrypt_key) 156 free(crypt->encrypt_key); 157 crypt->encrypt_key = calloc(1, sizeof(IDEA_KEY_SCHEDULE)); 158 159 /* note that we don't invert the key when decrypting for CFB mode */ 160 idea_set_encrypt_key(crypt->key, crypt->encrypt_key); 161 162 if (crypt->decrypt_key) 163 free(crypt->decrypt_key); 164 crypt->decrypt_key = calloc(1, sizeof(IDEA_KEY_SCHEDULE)); 165 166 idea_set_decrypt_key(crypt->encrypt_key, crypt->decrypt_key); 167 } 168 169 static void 170 idea_block_encrypt(__ops_crypt_t * crypt, void *out, const void *in) 171 { 172 idea_ecb_encrypt(in, out, crypt->encrypt_key); 173 } 174 175 static void 176 idea_block_decrypt(__ops_crypt_t * crypt, void *out, const void *in) 177 { 178 idea_ecb_encrypt(in, out, crypt->decrypt_key); 179 } 180 181 static void 182 idea_cfb_encrypt(__ops_crypt_t * crypt, void *out, const void *in, size_t count) 183 { 184 idea_cfb64_encrypt(in, out, count, 185 crypt->encrypt_key, crypt->iv, &crypt->num, 186 CAST_ENCRYPT); 187 } 188 189 static void 190 idea_cfb_decrypt(__ops_crypt_t * crypt, void *out, const void *in, size_t count) 191 { 192 idea_cfb64_encrypt(in, out, count, 193 crypt->decrypt_key, crypt->iv, &crypt->num, 194 CAST_DECRYPT); 195 } 196 197 static const __ops_crypt_t idea = 198 { 199 OPS_SA_IDEA, 200 IDEA_BLOCK, 201 IDEA_KEY_LENGTH, 202 std_set_iv, 203 std_set_key, 204 idea_init, 205 std_resync, 206 idea_block_encrypt, 207 idea_block_decrypt, 208 idea_cfb_encrypt, 209 idea_cfb_decrypt, 210 std_finish, 211 TRAILER 212 }; 213 #endif /* OPENSSL_NO_IDEA */ 214 215 /* AES with 128-bit key (AES) */ 216 217 #define KEYBITS_AES128 128 218 219 static void 220 aes128_init(__ops_crypt_t * crypt) 221 { 222 if (crypt->encrypt_key) 223 free(crypt->encrypt_key); 224 crypt->encrypt_key = calloc(1, sizeof(AES_KEY)); 225 if (AES_set_encrypt_key(crypt->key, KEYBITS_AES128, crypt->encrypt_key)) 226 fprintf(stderr, "aes128_init: Error setting encrypt_key\n"); 227 228 if (crypt->decrypt_key) 229 free(crypt->decrypt_key); 230 crypt->decrypt_key = calloc(1, sizeof(AES_KEY)); 231 if (AES_set_decrypt_key(crypt->key, KEYBITS_AES128, crypt->decrypt_key)) 232 fprintf(stderr, "aes128_init: Error setting decrypt_key\n"); 233 } 234 235 static void 236 aes_block_encrypt(__ops_crypt_t * crypt, void *out, const void *in) 237 { 238 AES_encrypt(in, out, crypt->encrypt_key); 239 } 240 241 static void 242 aes_block_decrypt(__ops_crypt_t * crypt, void *out, const void *in) 243 { 244 AES_decrypt(in, out, crypt->decrypt_key); 245 } 246 247 static void 248 aes_cfb_encrypt(__ops_crypt_t * crypt, void *out, const void *in, size_t count) 249 { 250 AES_cfb128_encrypt(in, out, count, 251 crypt->encrypt_key, crypt->iv, &crypt->num, 252 AES_ENCRYPT); 253 } 254 255 static void 256 aes_cfb_decrypt(__ops_crypt_t * crypt, void *out, const void *in, size_t count) 257 { 258 AES_cfb128_encrypt(in, out, count, 259 crypt->encrypt_key, crypt->iv, &crypt->num, 260 AES_DECRYPT); 261 } 262 263 static const __ops_crypt_t aes128 = 264 { 265 OPS_SA_AES_128, 266 AES_BLOCK_SIZE, 267 KEYBITS_AES128 / 8, 268 std_set_iv, 269 std_set_key, 270 aes128_init, 271 std_resync, 272 aes_block_encrypt, 273 aes_block_decrypt, 274 aes_cfb_encrypt, 275 aes_cfb_decrypt, 276 std_finish, 277 TRAILER 278 }; 279 280 /* AES with 256-bit key */ 281 282 #define KEYBITS_AES256 256 283 284 static void 285 aes256_init(__ops_crypt_t * crypt) 286 { 287 if (crypt->encrypt_key) 288 free(crypt->encrypt_key); 289 crypt->encrypt_key = calloc(1, sizeof(AES_KEY)); 290 if (AES_set_encrypt_key(crypt->key, KEYBITS_AES256, crypt->encrypt_key)) 291 fprintf(stderr, "aes256_init: Error setting encrypt_key\n"); 292 293 if (crypt->decrypt_key) 294 free(crypt->decrypt_key); 295 crypt->decrypt_key = calloc(1, sizeof(AES_KEY)); 296 if (AES_set_decrypt_key(crypt->key, KEYBITS_AES256, crypt->decrypt_key)) 297 fprintf(stderr, "aes256_init: Error setting decrypt_key\n"); 298 } 299 300 static const __ops_crypt_t aes256 = 301 { 302 OPS_SA_AES_256, 303 AES_BLOCK_SIZE, 304 KEYBITS_AES256 / 8, 305 std_set_iv, 306 std_set_key, 307 aes256_init, 308 std_resync, 309 aes_block_encrypt, 310 aes_block_decrypt, 311 aes_cfb_encrypt, 312 aes_cfb_decrypt, 313 std_finish, 314 TRAILER 315 }; 316 317 /* Triple DES */ 318 319 static void 320 tripledes_init(__ops_crypt_t * crypt) 321 { 322 DES_key_schedule *keys; 323 int n; 324 325 if (crypt->encrypt_key) 326 free(crypt->encrypt_key); 327 keys = crypt->encrypt_key = calloc(1, 3 * sizeof(DES_key_schedule)); 328 329 for (n = 0; n < 3; ++n) 330 DES_set_key((DES_cblock *) (crypt->key + n * 8), &keys[n]); 331 } 332 333 static void 334 tripledes_block_encrypt(__ops_crypt_t * crypt, void *out, 335 const void *in) 336 { 337 DES_key_schedule *keys = crypt->encrypt_key; 338 339 DES_ecb3_encrypt(__UNCONST(in), out, &keys[0], &keys[1], &keys[2], DES_ENCRYPT); 340 } 341 342 static void 343 tripledes_block_decrypt(__ops_crypt_t * crypt, void *out, 344 const void *in) 345 { 346 DES_key_schedule *keys = crypt->encrypt_key; 347 348 DES_ecb3_encrypt(__UNCONST(in), out, &keys[0], &keys[1], &keys[2], DES_DECRYPT); 349 } 350 351 static void 352 tripledes_cfb_encrypt(__ops_crypt_t * crypt, void *out, const void *in, size_t count) 353 { 354 DES_key_schedule *keys = crypt->encrypt_key; 355 356 DES_ede3_cfb64_encrypt(in, out, count, 357 &keys[0], &keys[1], &keys[2], (DES_cblock *) crypt->iv, 358 &crypt->num, DES_ENCRYPT); 359 } 360 361 static void 362 tripledes_cfb_decrypt(__ops_crypt_t * crypt, void *out, const void *in, size_t count) 363 { 364 DES_key_schedule *keys = crypt->encrypt_key; 365 366 DES_ede3_cfb64_encrypt(in, out, count, 367 &keys[0], &keys[1], &keys[2], (DES_cblock *) crypt->iv, 368 &crypt->num, DES_DECRYPT); 369 } 370 371 static const __ops_crypt_t tripledes = 372 { 373 OPS_SA_TRIPLEDES, 374 8, 375 24, 376 std_set_iv, 377 std_set_key, 378 tripledes_init, 379 std_resync, 380 tripledes_block_encrypt, 381 tripledes_block_decrypt, 382 tripledes_cfb_encrypt, 383 tripledes_cfb_decrypt, 384 std_finish, 385 TRAILER 386 }; 387 388 static const __ops_crypt_t * 389 get_proto(__ops_symmetric_algorithm_t alg) 390 { 391 switch (alg) { 392 case OPS_SA_CAST5: 393 return &cast5; 394 395 #ifndef OPENSSL_NO_IDEA 396 case OPS_SA_IDEA: 397 return &idea; 398 #endif /* OPENSSL_NO_IDEA */ 399 400 case OPS_SA_AES_128: 401 return &aes128; 402 403 case OPS_SA_AES_256: 404 return &aes256; 405 406 case OPS_SA_TRIPLEDES: 407 return &tripledes; 408 409 default: 410 fprintf(stderr, "Unknown algorithm: %d (%s)\n", alg, __ops_show_symmetric_algorithm(alg)); 411 /* assert(0); */ 412 } 413 414 return NULL; 415 } 416 417 int 418 __ops_crypt_any(__ops_crypt_t * crypt, __ops_symmetric_algorithm_t alg) 419 { 420 const __ops_crypt_t *ptr = get_proto(alg); 421 if (ptr) { 422 *crypt = *ptr; 423 return 1; 424 } else { 425 (void) memset(crypt, 0x0, sizeof(*crypt)); 426 return 0; 427 } 428 } 429 430 unsigned 431 __ops_block_size(__ops_symmetric_algorithm_t alg) 432 { 433 const __ops_crypt_t *p = get_proto(alg); 434 435 if (!p) 436 return 0; 437 438 return p->blocksize; 439 } 440 441 unsigned 442 __ops_key_size(__ops_symmetric_algorithm_t alg) 443 { 444 const __ops_crypt_t *p = get_proto(alg); 445 446 if (!p) 447 return 0; 448 449 return p->keysize; 450 } 451 452 void 453 __ops_encrypt_init(__ops_crypt_t * encrypt) 454 { 455 /* \todo should there be a separate __ops_encrypt_init? */ 456 __ops_decrypt_init(encrypt); 457 } 458 459 void 460 __ops_decrypt_init(__ops_crypt_t * decrypt) 461 { 462 decrypt->base_init(decrypt); 463 decrypt->block_encrypt(decrypt, decrypt->siv, decrypt->iv); 464 (void) memcpy(decrypt->civ, decrypt->siv, decrypt->blocksize); 465 decrypt->num = 0; 466 } 467 468 size_t 469 __ops_decrypt_se(__ops_crypt_t * decrypt, void *outvoid, const void *invoid, size_t count) 470 { 471 unsigned char *out = outvoid; 472 const unsigned char *in = invoid; 473 int saved = count; 474 475 /* 476 * in order to support v3's weird resyncing we have to implement CFB 477 * mode ourselves 478 */ 479 while (count-- > 0) { 480 unsigned char t; 481 482 if ((size_t) decrypt->num == decrypt->blocksize) { 483 (void) memcpy(decrypt->siv, decrypt->civ, decrypt->blocksize); 484 decrypt->block_decrypt(decrypt, decrypt->civ, decrypt->civ); 485 decrypt->num = 0; 486 } 487 t = decrypt->civ[decrypt->num]; 488 *out++ = t ^ (decrypt->civ[decrypt->num++] = *in++); 489 } 490 491 return saved; 492 } 493 494 size_t 495 __ops_encrypt_se(__ops_crypt_t * encrypt, void *outvoid, const void *invoid, 496 size_t count) 497 { 498 unsigned char *out = outvoid; 499 const unsigned char *in = invoid; 500 int saved = count; 501 502 /* 503 * in order to support v3's weird resyncing we have to implement CFB 504 * mode ourselves 505 */ 506 while (count-- > 0) { 507 if ((size_t) encrypt->num == encrypt->blocksize) { 508 (void) memcpy(encrypt->siv, encrypt->civ, encrypt->blocksize); 509 encrypt->block_encrypt(encrypt, encrypt->civ, encrypt->civ); 510 encrypt->num = 0; 511 } 512 encrypt->civ[encrypt->num] = *out++ = encrypt->civ[encrypt->num] ^ *in++; 513 ++encrypt->num; 514 } 515 516 return saved; 517 } 518 519 /** 520 \ingroup HighLevel_Supported 521 \brief Is this Symmetric Algorithm supported? 522 \param alg Symmetric Algorithm to check 523 \return true if supported; else false 524 */ 525 bool 526 __ops_is_sa_supported(__ops_symmetric_algorithm_t alg) 527 { 528 switch (alg) { 529 case OPS_SA_AES_128: 530 case OPS_SA_AES_256: 531 case OPS_SA_CAST5: 532 case OPS_SA_TRIPLEDES: 533 #ifndef OPENSSL_NO_IDEA 534 case OPS_SA_IDEA: 535 #endif 536 return true; 537 break; 538 539 default: 540 fprintf(stderr, "\nWarning: %s not supported\n", 541 __ops_show_symmetric_algorithm(alg)); 542 return false; 543 } 544 } 545 546 size_t 547 __ops_encrypt_se_ip(__ops_crypt_t * crypt, void *out, const void *in, 548 size_t count) 549 { 550 if (!__ops_is_sa_supported(crypt->algorithm)) 551 return -1; 552 553 crypt->cfb_encrypt(crypt, out, in, count); 554 555 /* \todo test this number was encrypted */ 556 return count; 557 } 558 559 size_t 560 __ops_decrypt_se_ip(__ops_crypt_t * crypt, void *out, const void *in, 561 size_t count) 562 { 563 if (!__ops_is_sa_supported(crypt->algorithm)) 564 return -1; 565 566 crypt->cfb_decrypt(crypt, out, in, count); 567 568 /* \todo check this number was in fact decrypted */ 569 return count; 570 } 571