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_128_ICM); 155 if (status) 156 return status; 157 status = crypto_kernel_load_cipher_type(&aes_cbc, AES_128_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 err_status_t 301 crypto_kernel_load_cipher_type(cipher_type_t *new_ct, cipher_type_id_t id) { 302 kernel_cipher_type_t *ctype, *new_ctype; 303 err_status_t status; 304 305 /* defensive coding */ 306 if (new_ct == NULL) 307 return err_status_bad_param; 308 309 /* check cipher type by running self-test */ 310 status = cipher_type_self_test(new_ct); 311 if (status) { 312 return status; 313 } 314 315 /* walk down list, checking if this type is in the list already */ 316 ctype = crypto_kernel.cipher_type_list; 317 while (ctype != NULL) { 318 if ((new_ct == ctype->cipher_type) || (id == ctype->id)) 319 return err_status_bad_param; 320 ctype = ctype->next; 321 } 322 323 /* put new_ct at the head of the list */ 324 /* allocate memory */ 325 new_ctype = (kernel_cipher_type_t *) crypto_alloc(sizeof(kernel_cipher_type_t)); 326 if (new_ctype == NULL) 327 return err_status_alloc_fail; 328 329 /* set fields */ 330 new_ctype->cipher_type = new_ct; 331 new_ctype->id = id; 332 new_ctype->next = crypto_kernel.cipher_type_list; 333 334 /* set head of list to new cipher type */ 335 crypto_kernel.cipher_type_list = new_ctype; 336 337 /* load debug module, if there is one present */ 338 if (new_ct->debug != NULL) 339 crypto_kernel_load_debug_module(new_ct->debug); 340 /* we could check for errors here */ 341 342 return err_status_ok; 343 } 344 345 err_status_t 346 crypto_kernel_load_auth_type(auth_type_t *new_at, auth_type_id_t id) { 347 kernel_auth_type_t *atype, *new_atype; 348 err_status_t status; 349 350 /* defensive coding */ 351 if (new_at == NULL) 352 return err_status_bad_param; 353 354 /* check auth type by running self-test */ 355 status = auth_type_self_test(new_at); 356 if (status) { 357 return status; 358 } 359 360 /* walk down list, checking if this type is in the list already */ 361 atype = crypto_kernel.auth_type_list; 362 while (atype != NULL) { 363 if ((new_at == atype->auth_type) || (id == atype->id)) 364 return err_status_bad_param; 365 atype = atype->next; 366 } 367 368 /* put new_at at the head of the list */ 369 /* allocate memory */ 370 new_atype = (kernel_auth_type_t *)crypto_alloc(sizeof(kernel_auth_type_t)); 371 if (new_atype == NULL) 372 return err_status_alloc_fail; 373 374 /* set fields */ 375 new_atype->auth_type = new_at; 376 new_atype->id = id; 377 new_atype->next = crypto_kernel.auth_type_list; 378 379 /* set head of list to new auth type */ 380 crypto_kernel.auth_type_list = new_atype; 381 382 /* load debug module, if there is one present */ 383 if (new_at->debug != NULL) 384 crypto_kernel_load_debug_module(new_at->debug); 385 /* we could check for errors here */ 386 387 return err_status_ok; 388 389 } 390 391 392 cipher_type_t * 393 crypto_kernel_get_cipher_type(cipher_type_id_t id) { 394 kernel_cipher_type_t *ctype; 395 396 /* walk down list, looking for id */ 397 ctype = crypto_kernel.cipher_type_list; 398 while (ctype != NULL) { 399 if (id == ctype->id) 400 return ctype->cipher_type; 401 ctype = ctype->next; 402 } 403 404 /* haven't found the right one, indicate failure by returning NULL */ 405 return NULL; 406 } 407 408 409 err_status_t 410 crypto_kernel_alloc_cipher(cipher_type_id_t id, 411 cipher_pointer_t *cp, 412 int key_len) { 413 cipher_type_t *ct; 414 415 /* 416 * if the crypto_kernel is not yet initialized, we refuse to allocate 417 * any ciphers - this is a bit extra-paranoid 418 */ 419 if (crypto_kernel.state != crypto_kernel_state_secure) 420 return err_status_init_fail; 421 422 ct = crypto_kernel_get_cipher_type(id); 423 if (!ct) 424 return err_status_fail; 425 426 return ((ct)->alloc(cp, key_len)); 427 } 428 429 430 431 auth_type_t * 432 crypto_kernel_get_auth_type(auth_type_id_t id) { 433 kernel_auth_type_t *atype; 434 435 /* walk down list, looking for id */ 436 atype = crypto_kernel.auth_type_list; 437 while (atype != NULL) { 438 if (id == atype->id) 439 return atype->auth_type; 440 atype = atype->next; 441 } 442 443 /* haven't found the right one, indicate failure by returning NULL */ 444 return NULL; 445 } 446 447 err_status_t 448 crypto_kernel_alloc_auth(auth_type_id_t id, 449 auth_pointer_t *ap, 450 int key_len, 451 int tag_len) { 452 auth_type_t *at; 453 454 /* 455 * if the crypto_kernel is not yet initialized, we refuse to allocate 456 * any auth functions - this is a bit extra-paranoid 457 */ 458 if (crypto_kernel.state != crypto_kernel_state_secure) 459 return err_status_init_fail; 460 461 at = crypto_kernel_get_auth_type(id); 462 if (!at) 463 return err_status_fail; 464 465 return ((at)->alloc(ap, key_len, tag_len)); 466 } 467 468 err_status_t 469 crypto_kernel_load_debug_module(debug_module_t *new_dm) { 470 kernel_debug_module_t *kdm, *new; 471 472 /* defensive coding */ 473 if (new_dm == NULL) 474 return err_status_bad_param; 475 476 /* walk down list, checking if this type is in the list already */ 477 kdm = crypto_kernel.debug_module_list; 478 while (kdm != NULL) { 479 if (strncmp(new_dm->name, kdm->mod->name, 64) == 0) 480 return err_status_bad_param; 481 kdm = kdm->next; 482 } 483 484 /* put new_dm at the head of the list */ 485 /* allocate memory */ 486 new = (kernel_debug_module_t *)crypto_alloc(sizeof(kernel_debug_module_t)); 487 if (new == NULL) 488 return err_status_alloc_fail; 489 490 /* set fields */ 491 new->mod = new_dm; 492 new->next = crypto_kernel.debug_module_list; 493 494 /* set head of list to new cipher type */ 495 crypto_kernel.debug_module_list = new; 496 497 return err_status_ok; 498 } 499 500 err_status_t 501 crypto_kernel_set_debug_module(char *name, int on) { 502 kernel_debug_module_t *kdm; 503 504 /* walk down list, checking if this type is in the list already */ 505 kdm = crypto_kernel.debug_module_list; 506 while (kdm != NULL) { 507 if (strncmp(name, kdm->mod->name, 64) == 0) { 508 kdm->mod->on = on; 509 return err_status_ok; 510 } 511 kdm = kdm->next; 512 } 513 514 return err_status_fail; 515 } 516 517 err_status_t 518 crypto_get_random(unsigned char *buffer, unsigned int length) { 519 if (crypto_kernel.state == crypto_kernel_state_secure) 520 return ctr_prng_get_octet_string(buffer, length); 521 else 522 return err_status_fail; 523 } 524