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