1 /* 2 * crypto_kernel.c 3 * 4 * header for the cryptographic kernel 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 46 #include "alloc.h" 47 48 #include "crypto_kernel.h" 49 50 /* the debug module for the crypto_kernel */ 51 52 debug_module_t mod_crypto_kernel = { 53 0, /* debugging is off by default */ 54 "crypto kernel" /* printable name for module */ 55 }; 56 57 /* 58 * other debug modules that can be included in the kernel 59 */ 60 61 extern debug_module_t mod_auth; 62 extern debug_module_t mod_cipher; 63 extern debug_module_t mod_stat; 64 extern debug_module_t mod_alloc; 65 66 /* 67 * cipher types that can be included in the kernel 68 */ 69 70 extern cipher_type_t null_cipher; 71 extern cipher_type_t aes_icm; 72 extern cipher_type_t aes_cbc; 73 74 75 /* 76 * auth func types that can be included in the kernel 77 */ 78 79 extern auth_type_t null_auth; 80 extern auth_type_t hmac; 81 82 /* crypto_kernel is a global variable, the only one of its datatype */ 83 84 crypto_kernel_t 85 crypto_kernel = { 86 crypto_kernel_state_insecure, /* start off in insecure state */ 87 NULL, /* no cipher types yet */ 88 NULL, /* no auth types yet */ 89 NULL /* no debug modules yet */ 90 }; 91 92 #define MAX_RNG_TRIALS 25 93 94 err_status_t 95 crypto_kernel_init() { 96 err_status_t status; 97 98 /* check the security state */ 99 if (crypto_kernel.state == crypto_kernel_state_secure) { 100 101 /* 102 * we're already in the secure state, but we've been asked to 103 * re-initialize, so we just re-run the self-tests and then return 104 */ 105 return crypto_kernel_status(); 106 } 107 108 /* initialize error reporting system */ 109 status = err_reporting_init("crypto"); 110 if (status) 111 return status; 112 113 /* load debug modules */ 114 status = crypto_kernel_load_debug_module(&mod_crypto_kernel); 115 if (status) 116 return status; 117 status = crypto_kernel_load_debug_module(&mod_auth); 118 if (status) 119 return status; 120 status = crypto_kernel_load_debug_module(&mod_cipher); 121 if (status) 122 return status; 123 status = crypto_kernel_load_debug_module(&mod_stat); 124 if (status) 125 return status; 126 status = crypto_kernel_load_debug_module(&mod_alloc); 127 if (status) 128 return status; 129 130 /* initialize random number generator */ 131 status = rand_source_init(); 132 if (status) 133 return status; 134 135 /* run FIPS-140 statistical tests on rand_source */ 136 status = stat_test_rand_source_with_repetition(rand_source_get_octet_string, MAX_RNG_TRIALS); 137 if (status) 138 return status; 139 140 /* initialize pseudorandom number generator */ 141 status = ctr_prng_init(rand_source_get_octet_string); 142 if (status) 143 return status; 144 145 /* run FIPS-140 statistical tests on ctr_prng */ 146 status = stat_test_rand_source_with_repetition(ctr_prng_get_octet_string, MAX_RNG_TRIALS); 147 if (status) 148 return status; 149 150 /* load cipher types */ 151 status = crypto_kernel_load_cipher_type(&null_cipher, NULL_CIPHER); 152 if (status) 153 return status; 154 status = crypto_kernel_load_cipher_type(&aes_icm, AES_ICM); 155 if (status) 156 return status; 157 status = crypto_kernel_load_cipher_type(&aes_cbc, AES_CBC); 158 if (status) 159 return status; 160 161 /* load auth func types */ 162 status = crypto_kernel_load_auth_type(&null_auth, NULL_AUTH); 163 if (status) 164 return status; 165 status = crypto_kernel_load_auth_type(&hmac, HMAC_SHA1); 166 if (status) 167 return status; 168 169 /* change state to secure */ 170 crypto_kernel.state = crypto_kernel_state_secure; 171 172 return err_status_ok; 173 } 174 175 err_status_t 176 crypto_kernel_status() { 177 err_status_t status; 178 kernel_cipher_type_t *ctype = crypto_kernel.cipher_type_list; 179 kernel_auth_type_t *atype = crypto_kernel.auth_type_list; 180 kernel_debug_module_t *dm = crypto_kernel.debug_module_list; 181 182 /* run FIPS-140 statistical tests on rand_source */ 183 printf("testing rand_source..."); 184 status = stat_test_rand_source_with_repetition(rand_source_get_octet_string, MAX_RNG_TRIALS); 185 if (status) { 186 printf("failed\n"); 187 crypto_kernel.state = crypto_kernel_state_insecure; 188 return status; 189 } 190 printf("passed\n"); 191 192 /* for each cipher type, describe and test */ 193 while(ctype != NULL) { 194 printf("cipher: %s\n", ctype->cipher_type->description); 195 printf(" instance count: %d\n", ctype->cipher_type->ref_count); 196 printf(" self-test: "); 197 status = cipher_type_self_test(ctype->cipher_type); 198 if (status) { 199 printf("failed with error code %d\n", status); 200 exit(status); 201 } 202 printf("passed\n"); 203 ctype = ctype->next; 204 } 205 206 /* for each auth type, describe and test */ 207 while(atype != NULL) { 208 printf("auth func: %s\n", atype->auth_type->description); 209 printf(" instance count: %d\n", atype->auth_type->ref_count); 210 printf(" self-test: "); 211 status = auth_type_self_test(atype->auth_type); 212 if (status) { 213 printf("failed with error code %d\n", status); 214 exit(status); 215 } 216 printf("passed\n"); 217 atype = atype->next; 218 } 219 220 /* describe each debug module */ 221 printf("debug modules loaded:\n"); 222 while (dm != NULL) { 223 printf(" %s ", dm->mod->name); 224 if (dm->mod->on) 225 printf("(on)\n"); 226 else 227 printf("(off)\n"); 228 dm = dm->next; 229 } 230 231 return err_status_ok; 232 } 233 234 err_status_t 235 crypto_kernel_list_debug_modules() { 236 kernel_debug_module_t *dm = crypto_kernel.debug_module_list; 237 238 /* describe each debug module */ 239 printf("debug modules loaded:\n"); 240 while (dm != NULL) { 241 printf(" %s ", dm->mod->name); 242 if (dm->mod->on) 243 printf("(on)\n"); 244 else 245 printf("(off)\n"); 246 dm = dm->next; 247 } 248 249 return err_status_ok; 250 } 251 252 err_status_t 253 crypto_kernel_shutdown() { 254 err_status_t status; 255 256 /* 257 * free dynamic memory used in crypto_kernel at present 258 */ 259 260 /* walk down cipher type list, freeing memory */ 261 while (crypto_kernel.cipher_type_list != NULL) { 262 kernel_cipher_type_t *ctype = crypto_kernel.cipher_type_list; 263 crypto_kernel.cipher_type_list = ctype->next; 264 debug_print(mod_crypto_kernel, 265 "freeing memory for cipher %s", 266 ctype->cipher_type->description); 267 crypto_free(ctype); 268 } 269 270 /* walk down authetication module list, freeing memory */ 271 while (crypto_kernel.auth_type_list != NULL) { 272 kernel_auth_type_t *atype = crypto_kernel.auth_type_list; 273 crypto_kernel.auth_type_list = atype->next; 274 debug_print(mod_crypto_kernel, 275 "freeing memory for authentication %s", 276 atype->auth_type->description); 277 crypto_free(atype); 278 } 279 280 /* walk down debug module list, freeing memory */ 281 while (crypto_kernel.debug_module_list != NULL) { 282 kernel_debug_module_t *kdm = crypto_kernel.debug_module_list; 283 crypto_kernel.debug_module_list = kdm->next; 284 debug_print(mod_crypto_kernel, 285 "freeing memory for debug module %s", 286 kdm->mod->name); 287 crypto_free(kdm); 288 } 289 290 /* de-initialize random number generator */ status = rand_source_deinit(); 291 if (status) 292 return status; 293 294 /* return to insecure state */ 295 crypto_kernel.state = crypto_kernel_state_insecure; 296 297 return err_status_ok; 298 } 299 300 static INLINE err_status_t 301 crypto_kernel_do_load_cipher_type(cipher_type_t *new_ct, cipher_type_id_t id, 302 int replace) { 303 kernel_cipher_type_t *ctype, *new_ctype; 304 err_status_t status; 305 306 /* defensive coding */ 307 if (new_ct == NULL) 308 return err_status_bad_param; 309 310 if (new_ct->id != id) 311 return err_status_bad_param; 312 313 /* check cipher type by running self-test */ 314 status = cipher_type_self_test(new_ct); 315 if (status) { 316 return status; 317 } 318 319 /* walk down list, checking if this type is in the list already */ 320 ctype = crypto_kernel.cipher_type_list; 321 while (ctype != NULL) { 322 if (id == ctype->id) { 323 if (!replace) 324 return err_status_bad_param; 325 status = cipher_type_test(new_ct, ctype->cipher_type->test_data); 326 if (status) 327 return status; 328 new_ctype = ctype; 329 break; 330 } 331 else if (new_ct == ctype->cipher_type) 332 return err_status_bad_param; 333 ctype = ctype->next; 334 } 335 336 /* if not found, put new_ct at the head of the list */ 337 if (ctype == NULL) { 338 /* allocate memory */ 339 new_ctype = (kernel_cipher_type_t *) crypto_alloc(sizeof(kernel_cipher_type_t)); 340 if (new_ctype == NULL) 341 return err_status_alloc_fail; 342 new_ctype->next = crypto_kernel.cipher_type_list; 343 344 /* set head of list to new cipher type */ 345 crypto_kernel.cipher_type_list = new_ctype; 346 } 347 348 /* set fields */ 349 new_ctype->cipher_type = new_ct; 350 new_ctype->id = id; 351 352 /* load debug module, if there is one present */ 353 if (new_ct->debug != NULL) 354 crypto_kernel_load_debug_module(new_ct->debug); 355 /* we could check for errors here */ 356 357 return err_status_ok; 358 } 359 360 err_status_t 361 crypto_kernel_load_cipher_type(cipher_type_t *new_ct, cipher_type_id_t id) { 362 return crypto_kernel_do_load_cipher_type(new_ct, id, 0); 363 } 364 365 err_status_t 366 crypto_kernel_replace_cipher_type(cipher_type_t *new_ct, cipher_type_id_t id) { 367 return crypto_kernel_do_load_cipher_type(new_ct, id, 1); 368 } 369 370 err_status_t 371 crypto_kernel_do_load_auth_type(auth_type_t *new_at, auth_type_id_t id, 372 int replace) { 373 kernel_auth_type_t *atype, *new_atype; 374 err_status_t status; 375 376 /* defensive coding */ 377 if (new_at == NULL) 378 return err_status_bad_param; 379 380 if (new_at->id != id) 381 return err_status_bad_param; 382 383 /* check auth type by running self-test */ 384 status = auth_type_self_test(new_at); 385 if (status) { 386 return status; 387 } 388 389 /* walk down list, checking if this type is in the list already */ 390 atype = crypto_kernel.auth_type_list; 391 while (atype != NULL) { 392 if (id == atype->id) { 393 if (!replace) 394 return err_status_bad_param; 395 status = auth_type_test(new_at, atype->auth_type->test_data); 396 if (status) 397 return status; 398 new_atype = atype; 399 break; 400 } 401 else if (new_at == atype->auth_type) 402 return err_status_bad_param; 403 atype = atype->next; 404 } 405 406 /* if not found, put new_at at the head of the list */ 407 if (atype == NULL) { 408 /* allocate memory */ 409 new_atype = (kernel_auth_type_t *)crypto_alloc(sizeof(kernel_auth_type_t)); 410 if (new_atype == NULL) 411 return err_status_alloc_fail; 412 413 new_atype->next = crypto_kernel.auth_type_list; 414 /* set head of list to new auth type */ 415 crypto_kernel.auth_type_list = new_atype; 416 } 417 418 /* set fields */ 419 new_atype->auth_type = new_at; 420 new_atype->id = id; 421 422 /* load debug module, if there is one present */ 423 if (new_at->debug != NULL) 424 crypto_kernel_load_debug_module(new_at->debug); 425 /* we could check for errors here */ 426 427 return err_status_ok; 428 429 } 430 431 err_status_t 432 crypto_kernel_load_auth_type(auth_type_t *new_at, auth_type_id_t id) { 433 return crypto_kernel_do_load_auth_type(new_at, id, 0); 434 } 435 436 err_status_t 437 crypto_kernel_replace_auth_type(auth_type_t *new_at, auth_type_id_t id) { 438 return crypto_kernel_do_load_auth_type(new_at, id, 1); 439 } 440 441 442 cipher_type_t * 443 crypto_kernel_get_cipher_type(cipher_type_id_t id) { 444 kernel_cipher_type_t *ctype; 445 446 /* walk down list, looking for id */ 447 ctype = crypto_kernel.cipher_type_list; 448 while (ctype != NULL) { 449 if (id == ctype->id) 450 return ctype->cipher_type; 451 ctype = ctype->next; 452 } 453 454 /* haven't found the right one, indicate failure by returning NULL */ 455 return NULL; 456 } 457 458 459 err_status_t 460 crypto_kernel_alloc_cipher(cipher_type_id_t id, 461 cipher_pointer_t *cp, 462 int key_len) { 463 cipher_type_t *ct; 464 465 /* 466 * if the crypto_kernel is not yet initialized, we refuse to allocate 467 * any ciphers - this is a bit extra-paranoid 468 */ 469 if (crypto_kernel.state != crypto_kernel_state_secure) 470 return err_status_init_fail; 471 472 ct = crypto_kernel_get_cipher_type(id); 473 if (!ct) 474 return err_status_fail; 475 476 return ((ct)->alloc(cp, key_len)); 477 } 478 479 480 481 auth_type_t * 482 crypto_kernel_get_auth_type(auth_type_id_t id) { 483 kernel_auth_type_t *atype; 484 485 /* walk down list, looking for id */ 486 atype = crypto_kernel.auth_type_list; 487 while (atype != NULL) { 488 if (id == atype->id) 489 return atype->auth_type; 490 atype = atype->next; 491 } 492 493 /* haven't found the right one, indicate failure by returning NULL */ 494 return NULL; 495 } 496 497 err_status_t 498 crypto_kernel_alloc_auth(auth_type_id_t id, 499 auth_pointer_t *ap, 500 int key_len, 501 int tag_len) { 502 auth_type_t *at; 503 504 /* 505 * if the crypto_kernel is not yet initialized, we refuse to allocate 506 * any auth functions - this is a bit extra-paranoid 507 */ 508 if (crypto_kernel.state != crypto_kernel_state_secure) 509 return err_status_init_fail; 510 511 at = crypto_kernel_get_auth_type(id); 512 if (!at) 513 return err_status_fail; 514 515 return ((at)->alloc(ap, key_len, tag_len)); 516 } 517 518 err_status_t 519 crypto_kernel_load_debug_module(debug_module_t *new_dm) { 520 kernel_debug_module_t *kdm, *new; 521 522 /* defensive coding */ 523 if (new_dm == NULL) 524 return err_status_bad_param; 525 526 /* walk down list, checking if this type is in the list already */ 527 kdm = crypto_kernel.debug_module_list; 528 while (kdm != NULL) { 529 if (strncmp(new_dm->name, kdm->mod->name, 64) == 0) 530 return err_status_bad_param; 531 kdm = kdm->next; 532 } 533 534 /* put new_dm at the head of the list */ 535 /* allocate memory */ 536 new = (kernel_debug_module_t *)crypto_alloc(sizeof(kernel_debug_module_t)); 537 if (new == NULL) 538 return err_status_alloc_fail; 539 540 /* set fields */ 541 new->mod = new_dm; 542 new->next = crypto_kernel.debug_module_list; 543 544 /* set head of list to new cipher type */ 545 crypto_kernel.debug_module_list = new; 546 547 return err_status_ok; 548 } 549 550 err_status_t 551 crypto_kernel_set_debug_module(char *name, int on) { 552 kernel_debug_module_t *kdm; 553 554 /* walk down list, checking if this type is in the list already */ 555 kdm = crypto_kernel.debug_module_list; 556 while (kdm != NULL) { 557 if (strncmp(name, kdm->mod->name, 64) == 0) { 558 kdm->mod->on = on; 559 return err_status_ok; 560 } 561 kdm = kdm->next; 562 } 563 564 return err_status_fail; 565 } 566 567 err_status_t 568 crypto_get_random(unsigned char *buffer, unsigned int length) { 569 if (crypto_kernel.state == crypto_kernel_state_secure) 570 return ctr_prng_get_octet_string(buffer, length); 571 else 572 return err_status_fail; 573 } 574