1 /* 2 * xfm.c 3 * 4 * Crypto transform implementation 5 * 6 * David A. McGrew 7 * Cisco Systems, Inc. 8 */ 9 /* 10 * 11 * Copyright (c) 2001-2006, Cisco Systems, Inc. 12 * All rights reserved. 13 * 14 * Redistribution and use in source and binary forms, with or without 15 * modification, are permitted provided that the following conditions 16 * are met: 17 * 18 * Redistributions of source code must retain the above copyright 19 * notice, this list of conditions and the following disclaimer. 20 * 21 * Redistributions in binary form must reproduce the above 22 * copyright notice, this list of conditions and the following 23 * disclaimer in the documentation and/or other materials provided 24 * with the distribution. 25 * 26 * Neither the name of the Cisco Systems, Inc. nor the names of its 27 * contributors may be used to endorse or promote products derived 28 * from this software without specific prior written permission. 29 * 30 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 31 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 32 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 33 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 34 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 35 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 36 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 37 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 40 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 41 * OF THE POSSIBILITY OF SUCH DAMAGE. 42 * 43 */ 44 45 #include "cryptoalg.h" 46 #include "aes_cbc.h" 47 #include "hmac.h" 48 #include "crypto_kernel.h" /* for crypto_get_random() */ 49 50 #define KEY_LEN 16 51 #define ENC_KEY_LEN 16 52 #define MAC_KEY_LEN 16 53 #define IV_LEN 16 54 #define TAG_LEN 12 55 #define MAX_EXPAND 27 56 57 err_status_t 58 aes_128_cbc_hmac_sha1_96_func(void *key, 59 void *clear, 60 unsigned clear_len, 61 void *iv, 62 void *opaque, 63 unsigned *opaque_len, 64 void *auth_tag) { 65 aes_cbc_ctx_t aes_ctx; 66 hmac_ctx_t hmac_ctx; 67 unsigned char enc_key[ENC_KEY_LEN]; 68 unsigned char mac_key[MAC_KEY_LEN]; 69 err_status_t status; 70 71 /* check if we're doing authentication only */ 72 if ((iv == NULL) && (opaque == NULL) && (opaque_len == NULL)) { 73 74 /* perform authentication only */ 75 76 } else if ((iv == NULL) || (opaque == NULL) || (opaque_len == NULL)) { 77 78 /* 79 * bad parameter - we expect either all three pointers to be NULL, 80 * or none of those pointers to be NULL 81 */ 82 return err_status_fail; 83 84 } else { 85 86 /* derive encryption and authentication keys from the input key */ 87 status = hmac_init(&hmac_ctx, key, KEY_LEN); 88 if (status) return status; 89 status = hmac_compute(&hmac_ctx, "ENC", 3, ENC_KEY_LEN, enc_key); 90 if (status) return status; 91 92 status = hmac_init(&hmac_ctx, key, KEY_LEN); 93 if (status) return status; 94 status = hmac_compute(&hmac_ctx, "MAC", 3, MAC_KEY_LEN, mac_key); 95 if (status) return status; 96 97 98 /* perform encryption and authentication */ 99 100 /* set aes key */ 101 status = aes_cbc_context_init(&aes_ctx, key, ENC_KEY_LEN, direction_encrypt); 102 if (status) return status; 103 104 /* set iv */ 105 status = crypto_get_random(iv, IV_LEN); 106 if (status) return status; 107 status = aes_cbc_set_iv(&aes_ctx, iv); 108 109 /* encrypt the opaque data */ 110 status = aes_cbc_nist_encrypt(&aes_ctx, opaque, opaque_len); 111 if (status) return status; 112 113 /* authenticate clear and opaque data */ 114 status = hmac_init(&hmac_ctx, mac_key, MAC_KEY_LEN); 115 if (status) return status; 116 117 status = hmac_start(&hmac_ctx); 118 if (status) return status; 119 120 status = hmac_update(&hmac_ctx, clear, clear_len); 121 if (status) return status; 122 123 status = hmac_compute(&hmac_ctx, opaque, *opaque_len, TAG_LEN, auth_tag); 124 if (status) return status; 125 126 } 127 128 return err_status_ok; 129 } 130 131 err_status_t 132 aes_128_cbc_hmac_sha1_96_inv(void *key, 133 void *clear, 134 unsigned clear_len, 135 void *iv, 136 void *opaque, 137 unsigned *opaque_len, 138 void *auth_tag) { 139 aes_cbc_ctx_t aes_ctx; 140 hmac_ctx_t hmac_ctx; 141 unsigned char enc_key[ENC_KEY_LEN]; 142 unsigned char mac_key[MAC_KEY_LEN]; 143 unsigned char tmp_tag[TAG_LEN]; 144 unsigned char *tag = auth_tag; 145 err_status_t status; 146 int i; 147 148 /* check if we're doing authentication only */ 149 if ((iv == NULL) && (opaque == NULL) && (opaque_len == NULL)) { 150 151 /* perform authentication only */ 152 153 } else if ((iv == NULL) || (opaque == NULL) || (opaque_len == NULL)) { 154 155 /* 156 * bad parameter - we expect either all three pointers to be NULL, 157 * or none of those pointers to be NULL 158 */ 159 return err_status_fail; 160 161 } else { 162 163 /* derive encryption and authentication keys from the input key */ 164 status = hmac_init(&hmac_ctx, key, KEY_LEN); 165 if (status) return status; 166 status = hmac_compute(&hmac_ctx, "ENC", 3, ENC_KEY_LEN, enc_key); 167 if (status) return status; 168 169 status = hmac_init(&hmac_ctx, key, KEY_LEN); 170 if (status) return status; 171 status = hmac_compute(&hmac_ctx, "MAC", 3, MAC_KEY_LEN, mac_key); 172 if (status) return status; 173 174 /* perform encryption and authentication */ 175 176 /* set aes key */ 177 status = aes_cbc_context_init(&aes_ctx, key, ENC_KEY_LEN, direction_decrypt); 178 if (status) return status; 179 180 /* set iv */ 181 status = rand_source_get_octet_string(iv, IV_LEN); 182 if (status) return status; 183 status = aes_cbc_set_iv(&aes_ctx, iv); 184 185 /* encrypt the opaque data */ 186 status = aes_cbc_nist_decrypt(&aes_ctx, opaque, opaque_len); 187 if (status) return status; 188 189 /* authenticate clear and opaque data */ 190 status = hmac_init(&hmac_ctx, mac_key, MAC_KEY_LEN); 191 if (status) return status; 192 193 status = hmac_start(&hmac_ctx); 194 if (status) return status; 195 196 status = hmac_update(&hmac_ctx, clear, clear_len); 197 if (status) return status; 198 199 status = hmac_compute(&hmac_ctx, opaque, *opaque_len, TAG_LEN, tmp_tag); 200 if (status) return status; 201 202 /* compare the computed tag with the one provided as input */ 203 for (i=0; i < TAG_LEN; i++) 204 if (tmp_tag[i] != tag[i]) 205 return err_status_auth_fail; 206 207 } 208 209 return err_status_ok; 210 } 211 212 213 #define ENC 1 214 215 #define DEBUG 0 216 217 err_status_t 218 aes_128_cbc_hmac_sha1_96_enc(void *key, 219 const void *clear, 220 unsigned clear_len, 221 void *iv, 222 void *opaque, 223 unsigned *opaque_len) { 224 aes_cbc_ctx_t aes_ctx; 225 hmac_ctx_t hmac_ctx; 226 unsigned char enc_key[ENC_KEY_LEN]; 227 unsigned char mac_key[MAC_KEY_LEN]; 228 unsigned char *auth_tag; 229 err_status_t status; 230 231 /* check if we're doing authentication only */ 232 if ((iv == NULL) && (opaque == NULL) && (opaque_len == NULL)) { 233 234 /* perform authentication only */ 235 236 } else if ((iv == NULL) || (opaque == NULL) || (opaque_len == NULL)) { 237 238 /* 239 * bad parameter - we expect either all three pointers to be NULL, 240 * or none of those pointers to be NULL 241 */ 242 return err_status_fail; 243 244 } else { 245 246 #if DEBUG 247 printf("ENC using key %s\n", octet_string_hex_string(key, KEY_LEN)); 248 #endif 249 250 /* derive encryption and authentication keys from the input key */ 251 status = hmac_init(&hmac_ctx, key, KEY_LEN); 252 if (status) return status; 253 status = hmac_compute(&hmac_ctx, "ENC", 3, ENC_KEY_LEN, enc_key); 254 if (status) return status; 255 256 status = hmac_init(&hmac_ctx, key, KEY_LEN); 257 if (status) return status; 258 status = hmac_compute(&hmac_ctx, "MAC", 3, MAC_KEY_LEN, mac_key); 259 if (status) return status; 260 261 262 /* perform encryption and authentication */ 263 264 /* set aes key */ 265 status = aes_cbc_context_init(&aes_ctx, key, ENC_KEY_LEN, direction_encrypt); 266 if (status) return status; 267 268 /* set iv */ 269 status = rand_source_get_octet_string(iv, IV_LEN); 270 if (status) return status; 271 status = aes_cbc_set_iv(&aes_ctx, iv); 272 if (status) return status; 273 274 #if DEBUG 275 printf("plaintext len: %d\n", *opaque_len); 276 printf("iv: %s\n", octet_string_hex_string(iv, IV_LEN)); 277 printf("plaintext: %s\n", octet_string_hex_string(opaque, *opaque_len)); 278 #endif 279 280 #if ENC 281 /* encrypt the opaque data */ 282 status = aes_cbc_nist_encrypt(&aes_ctx, opaque, opaque_len); 283 if (status) return status; 284 #endif 285 286 #if DEBUG 287 printf("ciphertext len: %d\n", *opaque_len); 288 printf("ciphertext: %s\n", octet_string_hex_string(opaque, *opaque_len)); 289 #endif 290 291 /* 292 * authenticate clear and opaque data, then write the 293 * authentication tag to the location immediately following the 294 * ciphertext 295 */ 296 status = hmac_init(&hmac_ctx, mac_key, MAC_KEY_LEN); 297 if (status) return status; 298 299 status = hmac_start(&hmac_ctx); 300 if (status) return status; 301 302 status = hmac_update(&hmac_ctx, clear, clear_len); 303 if (status) return status; 304 #if DEBUG 305 printf("hmac input: %s\n", 306 octet_string_hex_string(clear, clear_len)); 307 #endif 308 auth_tag = (unsigned char *)opaque; 309 auth_tag += *opaque_len; 310 status = hmac_compute(&hmac_ctx, opaque, *opaque_len, TAG_LEN, auth_tag); 311 if (status) return status; 312 #if DEBUG 313 printf("hmac input: %s\n", 314 octet_string_hex_string(opaque, *opaque_len)); 315 #endif 316 /* bump up the opaque_len to reflect the authentication tag */ 317 *opaque_len += TAG_LEN; 318 319 #if DEBUG 320 printf("prot data len: %d\n", *opaque_len); 321 printf("prot data: %s\n", octet_string_hex_string(opaque, *opaque_len)); 322 #endif 323 } 324 325 return err_status_ok; 326 } 327 328 err_status_t 329 aes_128_cbc_hmac_sha1_96_dec(void *key, 330 const void *clear, 331 unsigned clear_len, 332 void *iv, 333 void *opaque, 334 unsigned *opaque_len) { 335 aes_cbc_ctx_t aes_ctx; 336 hmac_ctx_t hmac_ctx; 337 unsigned char enc_key[ENC_KEY_LEN]; 338 unsigned char mac_key[MAC_KEY_LEN]; 339 unsigned char tmp_tag[TAG_LEN]; 340 unsigned char *auth_tag; 341 unsigned ciphertext_len; 342 err_status_t status; 343 int i; 344 345 /* check if we're doing authentication only */ 346 if ((iv == NULL) && (opaque == NULL) && (opaque_len == NULL)) { 347 348 /* perform authentication only */ 349 350 } else if ((iv == NULL) || (opaque == NULL) || (opaque_len == NULL)) { 351 352 /* 353 * bad parameter - we expect either all three pointers to be NULL, 354 * or none of those pointers to be NULL 355 */ 356 return err_status_fail; 357 358 } else { 359 #if DEBUG 360 printf("DEC using key %s\n", octet_string_hex_string(key, KEY_LEN)); 361 #endif 362 363 /* derive encryption and authentication keys from the input key */ 364 status = hmac_init(&hmac_ctx, key, KEY_LEN); 365 if (status) return status; 366 status = hmac_compute(&hmac_ctx, "ENC", 3, ENC_KEY_LEN, enc_key); 367 if (status) return status; 368 369 status = hmac_init(&hmac_ctx, key, KEY_LEN); 370 if (status) return status; 371 status = hmac_compute(&hmac_ctx, "MAC", 3, MAC_KEY_LEN, mac_key); 372 if (status) return status; 373 374 #if DEBUG 375 printf("prot data len: %d\n", *opaque_len); 376 printf("prot data: %s\n", octet_string_hex_string(opaque, *opaque_len)); 377 #endif 378 379 /* 380 * set the protected data length to that of the ciphertext, by 381 * subtracting out the length of the authentication tag 382 */ 383 ciphertext_len = *opaque_len - TAG_LEN; 384 385 #if DEBUG 386 printf("ciphertext len: %d\n", ciphertext_len); 387 #endif 388 /* verify the authentication tag */ 389 390 /* 391 * compute the authentication tag for the clear and opaque data, 392 * and write it to a temporary location 393 */ 394 status = hmac_init(&hmac_ctx, mac_key, MAC_KEY_LEN); 395 if (status) return status; 396 397 status = hmac_start(&hmac_ctx); 398 if (status) return status; 399 400 status = hmac_update(&hmac_ctx, clear, clear_len); 401 if (status) return status; 402 403 #if DEBUG 404 printf("hmac input: %s\n", 405 octet_string_hex_string(clear, clear_len)); 406 #endif 407 408 status = hmac_compute(&hmac_ctx, opaque, ciphertext_len, TAG_LEN, tmp_tag); 409 if (status) return status; 410 411 #if DEBUG 412 printf("hmac input: %s\n", 413 octet_string_hex_string(opaque, ciphertext_len)); 414 #endif 415 416 /* 417 * compare the computed tag with the one provided as input (which 418 * immediately follows the ciphertext) 419 */ 420 auth_tag = (unsigned char *)opaque; 421 auth_tag += ciphertext_len; 422 #if DEBUG 423 printf("auth_tag: %s\n", octet_string_hex_string(auth_tag, TAG_LEN)); 424 printf("tmp_tag: %s\n", octet_string_hex_string(tmp_tag, TAG_LEN)); 425 #endif 426 for (i=0; i < TAG_LEN; i++) { 427 if (tmp_tag[i] != auth_tag[i]) 428 return err_status_auth_fail; 429 } 430 431 /* bump down the opaque_len to reflect the authentication tag */ 432 *opaque_len -= TAG_LEN; 433 434 /* decrypt the confidential data */ 435 status = aes_cbc_context_init(&aes_ctx, key, ENC_KEY_LEN, direction_decrypt); 436 if (status) return status; 437 status = aes_cbc_set_iv(&aes_ctx, iv); 438 if (status) return status; 439 440 #if DEBUG 441 printf("ciphertext: %s\n", octet_string_hex_string(opaque, *opaque_len)); 442 printf("iv: %s\n", octet_string_hex_string(iv, IV_LEN)); 443 #endif 444 445 #if ENC 446 status = aes_cbc_nist_decrypt(&aes_ctx, opaque, &ciphertext_len); 447 if (status) return status; 448 #endif 449 450 #if DEBUG 451 printf("plaintext len: %d\n", ciphertext_len); 452 printf("plaintext: %s\n", 453 octet_string_hex_string(opaque, ciphertext_len)); 454 #endif 455 456 /* indicate the length of the plaintext */ 457 *opaque_len = ciphertext_len; 458 } 459 460 return err_status_ok; 461 } 462 463 cryptoalg_ctx_t cryptoalg_ctx = { 464 aes_128_cbc_hmac_sha1_96_enc, 465 aes_128_cbc_hmac_sha1_96_dec, 466 KEY_LEN, 467 IV_LEN, 468 TAG_LEN, 469 MAX_EXPAND, 470 }; 471 472 cryptoalg_t cryptoalg = &cryptoalg_ctx; 473 474 #define NULL_TAG_LEN 12 475 476 err_status_t 477 null_enc(void *key, 478 const void *clear, 479 unsigned clear_len, 480 void *iv, 481 void *opaque, 482 unsigned *opaque_len) { 483 int i; 484 unsigned char *auth_tag; 485 unsigned char *init_vec = iv; 486 487 /* check if we're doing authentication only */ 488 if ((iv == NULL) && (opaque == NULL) && (opaque_len == NULL)) { 489 490 /* perform authentication only */ 491 492 } else if ((iv == NULL) || (opaque == NULL) || (opaque_len == NULL)) { 493 494 /* 495 * bad parameter - we expect either all three pointers to be NULL, 496 * or none of those pointers to be NULL 497 */ 498 return err_status_fail; 499 500 } else { 501 502 #if DEBUG 503 printf("NULL ENC using key %s\n", octet_string_hex_string(key, KEY_LEN)); 504 printf("NULL_TAG_LEN: %d\n", NULL_TAG_LEN); 505 printf("plaintext len: %d\n", *opaque_len); 506 #endif 507 for (i=0; i < IV_LEN; i++) 508 init_vec[i] = i + (i * 16); 509 #if DEBUG 510 printf("iv: %s\n", 511 octet_string_hex_string(iv, IV_LEN)); 512 printf("plaintext: %s\n", 513 octet_string_hex_string(opaque, *opaque_len)); 514 #endif 515 auth_tag = opaque; 516 auth_tag += *opaque_len; 517 for (i=0; i < NULL_TAG_LEN; i++) 518 auth_tag[i] = i + (i * 16); 519 *opaque_len += NULL_TAG_LEN; 520 #if DEBUG 521 printf("protected data len: %d\n", *opaque_len); 522 printf("protected data: %s\n", 523 octet_string_hex_string(opaque, *opaque_len)); 524 #endif 525 526 } 527 528 return err_status_ok; 529 } 530 531 err_status_t 532 null_dec(void *key, 533 const void *clear, 534 unsigned clear_len, 535 void *iv, 536 void *opaque, 537 unsigned *opaque_len) { 538 unsigned char *auth_tag; 539 540 /* check if we're doing authentication only */ 541 if ((iv == NULL) && (opaque == NULL) && (opaque_len == NULL)) { 542 543 /* perform authentication only */ 544 545 } else if ((iv == NULL) || (opaque == NULL) || (opaque_len == NULL)) { 546 547 /* 548 * bad parameter - we expect either all three pointers to be NULL, 549 * or none of those pointers to be NULL 550 */ 551 return err_status_fail; 552 553 } else { 554 555 #if DEBUG 556 printf("NULL DEC using key %s\n", octet_string_hex_string(key, KEY_LEN)); 557 558 printf("protected data len: %d\n", *opaque_len); 559 printf("protected data: %s\n", 560 octet_string_hex_string(opaque, *opaque_len)); 561 #endif 562 auth_tag = opaque; 563 auth_tag += (*opaque_len - NULL_TAG_LEN); 564 #if DEBUG 565 printf("iv: %s\n", octet_string_hex_string(iv, IV_LEN)); 566 #endif 567 *opaque_len -= NULL_TAG_LEN; 568 #if DEBUG 569 printf("plaintext len: %d\n", *opaque_len); 570 printf("plaintext: %s\n", 571 octet_string_hex_string(opaque, *opaque_len)); 572 #endif 573 } 574 575 return err_status_ok; 576 } 577 578 cryptoalg_ctx_t null_cryptoalg_ctx = { 579 null_enc, 580 null_dec, 581 KEY_LEN, 582 IV_LEN, 583 NULL_TAG_LEN, 584 MAX_EXPAND, 585 }; 586 587 cryptoalg_t null_cryptoalg = &null_cryptoalg_ctx; 588 589 int 590 cryptoalg_get_id(cryptoalg_t c) { 591 if (c == cryptoalg) 592 return 1; 593 return 0; 594 } 595 596 cryptoalg_t 597 cryptoalg_find_by_id(int id) { 598 switch(id) { 599 case 1: 600 return cryptoalg; 601 default: 602 break; 603 } 604 return 0; 605 } 606