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