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 57err_status_t 58aes_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 131err_status_t 132aes_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 217err_status_t 218aes_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 328err_status_t 329aes_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 463cryptoalg_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 472cryptoalg_t cryptoalg = &cryptoalg_ctx; 473 474#define NULL_TAG_LEN 12 475 476err_status_t 477null_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 531err_status_t 532null_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 578cryptoalg_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 587cryptoalg_t null_cryptoalg = &null_cryptoalg_ctx; 588 589int 590cryptoalg_get_id(cryptoalg_t c) { 591 if (c == cryptoalg) 592 return 1; 593 return 0; 594} 595 596cryptoalg_t 597cryptoalg_find_by_id(int id) { 598 switch(id) { 599 case 1: 600 return cryptoalg; 601 default: 602 break; 603 } 604 return 0; 605} 606