1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/netwerk/srtp/src/crypto/kernel/crypto_kernel.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,573 @@ 1.4 +/* 1.5 + * crypto_kernel.c 1.6 + * 1.7 + * header for the cryptographic kernel 1.8 + * 1.9 + * David A. McGrew 1.10 + * Cisco Systems, Inc. 1.11 + */ 1.12 +/* 1.13 + * 1.14 + * Copyright(c) 2001-2006 Cisco Systems, Inc. 1.15 + * All rights reserved. 1.16 + * 1.17 + * Redistribution and use in source and binary forms, with or without 1.18 + * modification, are permitted provided that the following conditions 1.19 + * are met: 1.20 + * 1.21 + * Redistributions of source code must retain the above copyright 1.22 + * notice, this list of conditions and the following disclaimer. 1.23 + * 1.24 + * Redistributions in binary form must reproduce the above 1.25 + * copyright notice, this list of conditions and the following 1.26 + * disclaimer in the documentation and/or other materials provided 1.27 + * with the distribution. 1.28 + * 1.29 + * Neither the name of the Cisco Systems, Inc. nor the names of its 1.30 + * contributors may be used to endorse or promote products derived 1.31 + * from this software without specific prior written permission. 1.32 + * 1.33 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1.34 + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1.35 + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 1.36 + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 1.37 + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 1.38 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 1.39 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 1.40 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 1.41 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 1.42 + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 1.43 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 1.44 + * OF THE POSSIBILITY OF SUCH DAMAGE. 1.45 + * 1.46 + */ 1.47 + 1.48 + 1.49 +#include "alloc.h" 1.50 + 1.51 +#include "crypto_kernel.h" 1.52 + 1.53 +/* the debug module for the crypto_kernel */ 1.54 + 1.55 +debug_module_t mod_crypto_kernel = { 1.56 + 0, /* debugging is off by default */ 1.57 + "crypto kernel" /* printable name for module */ 1.58 +}; 1.59 + 1.60 +/* 1.61 + * other debug modules that can be included in the kernel 1.62 + */ 1.63 + 1.64 +extern debug_module_t mod_auth; 1.65 +extern debug_module_t mod_cipher; 1.66 +extern debug_module_t mod_stat; 1.67 +extern debug_module_t mod_alloc; 1.68 + 1.69 +/* 1.70 + * cipher types that can be included in the kernel 1.71 + */ 1.72 + 1.73 +extern cipher_type_t null_cipher; 1.74 +extern cipher_type_t aes_icm; 1.75 +extern cipher_type_t aes_cbc; 1.76 + 1.77 + 1.78 +/* 1.79 + * auth func types that can be included in the kernel 1.80 + */ 1.81 + 1.82 +extern auth_type_t null_auth; 1.83 +extern auth_type_t hmac; 1.84 + 1.85 +/* crypto_kernel is a global variable, the only one of its datatype */ 1.86 + 1.87 +crypto_kernel_t 1.88 +crypto_kernel = { 1.89 + crypto_kernel_state_insecure, /* start off in insecure state */ 1.90 + NULL, /* no cipher types yet */ 1.91 + NULL, /* no auth types yet */ 1.92 + NULL /* no debug modules yet */ 1.93 +}; 1.94 + 1.95 +#define MAX_RNG_TRIALS 25 1.96 + 1.97 +err_status_t 1.98 +crypto_kernel_init() { 1.99 + err_status_t status; 1.100 + 1.101 + /* check the security state */ 1.102 + if (crypto_kernel.state == crypto_kernel_state_secure) { 1.103 + 1.104 + /* 1.105 + * we're already in the secure state, but we've been asked to 1.106 + * re-initialize, so we just re-run the self-tests and then return 1.107 + */ 1.108 + return crypto_kernel_status(); 1.109 + } 1.110 + 1.111 + /* initialize error reporting system */ 1.112 + status = err_reporting_init("crypto"); 1.113 + if (status) 1.114 + return status; 1.115 + 1.116 + /* load debug modules */ 1.117 + status = crypto_kernel_load_debug_module(&mod_crypto_kernel); 1.118 + if (status) 1.119 + return status; 1.120 + status = crypto_kernel_load_debug_module(&mod_auth); 1.121 + if (status) 1.122 + return status; 1.123 + status = crypto_kernel_load_debug_module(&mod_cipher); 1.124 + if (status) 1.125 + return status; 1.126 + status = crypto_kernel_load_debug_module(&mod_stat); 1.127 + if (status) 1.128 + return status; 1.129 + status = crypto_kernel_load_debug_module(&mod_alloc); 1.130 + if (status) 1.131 + return status; 1.132 + 1.133 + /* initialize random number generator */ 1.134 + status = rand_source_init(); 1.135 + if (status) 1.136 + return status; 1.137 + 1.138 + /* run FIPS-140 statistical tests on rand_source */ 1.139 + status = stat_test_rand_source_with_repetition(rand_source_get_octet_string, MAX_RNG_TRIALS); 1.140 + if (status) 1.141 + return status; 1.142 + 1.143 + /* initialize pseudorandom number generator */ 1.144 + status = ctr_prng_init(rand_source_get_octet_string); 1.145 + if (status) 1.146 + return status; 1.147 + 1.148 + /* run FIPS-140 statistical tests on ctr_prng */ 1.149 + status = stat_test_rand_source_with_repetition(ctr_prng_get_octet_string, MAX_RNG_TRIALS); 1.150 + if (status) 1.151 + return status; 1.152 + 1.153 + /* load cipher types */ 1.154 + status = crypto_kernel_load_cipher_type(&null_cipher, NULL_CIPHER); 1.155 + if (status) 1.156 + return status; 1.157 + status = crypto_kernel_load_cipher_type(&aes_icm, AES_ICM); 1.158 + if (status) 1.159 + return status; 1.160 + status = crypto_kernel_load_cipher_type(&aes_cbc, AES_CBC); 1.161 + if (status) 1.162 + return status; 1.163 + 1.164 + /* load auth func types */ 1.165 + status = crypto_kernel_load_auth_type(&null_auth, NULL_AUTH); 1.166 + if (status) 1.167 + return status; 1.168 + status = crypto_kernel_load_auth_type(&hmac, HMAC_SHA1); 1.169 + if (status) 1.170 + return status; 1.171 + 1.172 + /* change state to secure */ 1.173 + crypto_kernel.state = crypto_kernel_state_secure; 1.174 + 1.175 + return err_status_ok; 1.176 +} 1.177 + 1.178 +err_status_t 1.179 +crypto_kernel_status() { 1.180 + err_status_t status; 1.181 + kernel_cipher_type_t *ctype = crypto_kernel.cipher_type_list; 1.182 + kernel_auth_type_t *atype = crypto_kernel.auth_type_list; 1.183 + kernel_debug_module_t *dm = crypto_kernel.debug_module_list; 1.184 + 1.185 + /* run FIPS-140 statistical tests on rand_source */ 1.186 + printf("testing rand_source..."); 1.187 + status = stat_test_rand_source_with_repetition(rand_source_get_octet_string, MAX_RNG_TRIALS); 1.188 + if (status) { 1.189 + printf("failed\n"); 1.190 + crypto_kernel.state = crypto_kernel_state_insecure; 1.191 + return status; 1.192 + } 1.193 + printf("passed\n"); 1.194 + 1.195 + /* for each cipher type, describe and test */ 1.196 + while(ctype != NULL) { 1.197 + printf("cipher: %s\n", ctype->cipher_type->description); 1.198 + printf(" instance count: %d\n", ctype->cipher_type->ref_count); 1.199 + printf(" self-test: "); 1.200 + status = cipher_type_self_test(ctype->cipher_type); 1.201 + if (status) { 1.202 + printf("failed with error code %d\n", status); 1.203 + exit(status); 1.204 + } 1.205 + printf("passed\n"); 1.206 + ctype = ctype->next; 1.207 + } 1.208 + 1.209 + /* for each auth type, describe and test */ 1.210 + while(atype != NULL) { 1.211 + printf("auth func: %s\n", atype->auth_type->description); 1.212 + printf(" instance count: %d\n", atype->auth_type->ref_count); 1.213 + printf(" self-test: "); 1.214 + status = auth_type_self_test(atype->auth_type); 1.215 + if (status) { 1.216 + printf("failed with error code %d\n", status); 1.217 + exit(status); 1.218 + } 1.219 + printf("passed\n"); 1.220 + atype = atype->next; 1.221 + } 1.222 + 1.223 + /* describe each debug module */ 1.224 + printf("debug modules loaded:\n"); 1.225 + while (dm != NULL) { 1.226 + printf(" %s ", dm->mod->name); 1.227 + if (dm->mod->on) 1.228 + printf("(on)\n"); 1.229 + else 1.230 + printf("(off)\n"); 1.231 + dm = dm->next; 1.232 + } 1.233 + 1.234 + return err_status_ok; 1.235 +} 1.236 + 1.237 +err_status_t 1.238 +crypto_kernel_list_debug_modules() { 1.239 + kernel_debug_module_t *dm = crypto_kernel.debug_module_list; 1.240 + 1.241 + /* describe each debug module */ 1.242 + printf("debug modules loaded:\n"); 1.243 + while (dm != NULL) { 1.244 + printf(" %s ", dm->mod->name); 1.245 + if (dm->mod->on) 1.246 + printf("(on)\n"); 1.247 + else 1.248 + printf("(off)\n"); 1.249 + dm = dm->next; 1.250 + } 1.251 + 1.252 + return err_status_ok; 1.253 +} 1.254 + 1.255 +err_status_t 1.256 +crypto_kernel_shutdown() { 1.257 + err_status_t status; 1.258 + 1.259 + /* 1.260 + * free dynamic memory used in crypto_kernel at present 1.261 + */ 1.262 + 1.263 + /* walk down cipher type list, freeing memory */ 1.264 + while (crypto_kernel.cipher_type_list != NULL) { 1.265 + kernel_cipher_type_t *ctype = crypto_kernel.cipher_type_list; 1.266 + crypto_kernel.cipher_type_list = ctype->next; 1.267 + debug_print(mod_crypto_kernel, 1.268 + "freeing memory for cipher %s", 1.269 + ctype->cipher_type->description); 1.270 + crypto_free(ctype); 1.271 + } 1.272 + 1.273 + /* walk down authetication module list, freeing memory */ 1.274 + while (crypto_kernel.auth_type_list != NULL) { 1.275 + kernel_auth_type_t *atype = crypto_kernel.auth_type_list; 1.276 + crypto_kernel.auth_type_list = atype->next; 1.277 + debug_print(mod_crypto_kernel, 1.278 + "freeing memory for authentication %s", 1.279 + atype->auth_type->description); 1.280 + crypto_free(atype); 1.281 + } 1.282 + 1.283 + /* walk down debug module list, freeing memory */ 1.284 + while (crypto_kernel.debug_module_list != NULL) { 1.285 + kernel_debug_module_t *kdm = crypto_kernel.debug_module_list; 1.286 + crypto_kernel.debug_module_list = kdm->next; 1.287 + debug_print(mod_crypto_kernel, 1.288 + "freeing memory for debug module %s", 1.289 + kdm->mod->name); 1.290 + crypto_free(kdm); 1.291 + } 1.292 + 1.293 + /* de-initialize random number generator */ status = rand_source_deinit(); 1.294 + if (status) 1.295 + return status; 1.296 + 1.297 + /* return to insecure state */ 1.298 + crypto_kernel.state = crypto_kernel_state_insecure; 1.299 + 1.300 + return err_status_ok; 1.301 +} 1.302 + 1.303 +static inline err_status_t 1.304 +crypto_kernel_do_load_cipher_type(cipher_type_t *new_ct, cipher_type_id_t id, 1.305 + int replace) { 1.306 + kernel_cipher_type_t *ctype, *new_ctype; 1.307 + err_status_t status; 1.308 + 1.309 + /* defensive coding */ 1.310 + if (new_ct == NULL) 1.311 + return err_status_bad_param; 1.312 + 1.313 + if (new_ct->id != id) 1.314 + return err_status_bad_param; 1.315 + 1.316 + /* check cipher type by running self-test */ 1.317 + status = cipher_type_self_test(new_ct); 1.318 + if (status) { 1.319 + return status; 1.320 + } 1.321 + 1.322 + /* walk down list, checking if this type is in the list already */ 1.323 + ctype = crypto_kernel.cipher_type_list; 1.324 + while (ctype != NULL) { 1.325 + if (id == ctype->id) { 1.326 + if (!replace) 1.327 + return err_status_bad_param; 1.328 + status = cipher_type_test(new_ct, ctype->cipher_type->test_data); 1.329 + if (status) 1.330 + return status; 1.331 + new_ctype = ctype; 1.332 + break; 1.333 + } 1.334 + else if (new_ct == ctype->cipher_type) 1.335 + return err_status_bad_param; 1.336 + ctype = ctype->next; 1.337 + } 1.338 + 1.339 + /* if not found, put new_ct at the head of the list */ 1.340 + if (ctype == NULL) { 1.341 + /* allocate memory */ 1.342 + new_ctype = (kernel_cipher_type_t *) crypto_alloc(sizeof(kernel_cipher_type_t)); 1.343 + if (new_ctype == NULL) 1.344 + return err_status_alloc_fail; 1.345 + new_ctype->next = crypto_kernel.cipher_type_list; 1.346 + 1.347 + /* set head of list to new cipher type */ 1.348 + crypto_kernel.cipher_type_list = new_ctype; 1.349 + } 1.350 + 1.351 + /* set fields */ 1.352 + new_ctype->cipher_type = new_ct; 1.353 + new_ctype->id = id; 1.354 + 1.355 + /* load debug module, if there is one present */ 1.356 + if (new_ct->debug != NULL) 1.357 + crypto_kernel_load_debug_module(new_ct->debug); 1.358 + /* we could check for errors here */ 1.359 + 1.360 + return err_status_ok; 1.361 +} 1.362 + 1.363 +err_status_t 1.364 +crypto_kernel_load_cipher_type(cipher_type_t *new_ct, cipher_type_id_t id) { 1.365 + return crypto_kernel_do_load_cipher_type(new_ct, id, 0); 1.366 +} 1.367 + 1.368 +err_status_t 1.369 +crypto_kernel_replace_cipher_type(cipher_type_t *new_ct, cipher_type_id_t id) { 1.370 + return crypto_kernel_do_load_cipher_type(new_ct, id, 1); 1.371 +} 1.372 + 1.373 +err_status_t 1.374 +crypto_kernel_do_load_auth_type(auth_type_t *new_at, auth_type_id_t id, 1.375 + int replace) { 1.376 + kernel_auth_type_t *atype, *new_atype; 1.377 + err_status_t status; 1.378 + 1.379 + /* defensive coding */ 1.380 + if (new_at == NULL) 1.381 + return err_status_bad_param; 1.382 + 1.383 + if (new_at->id != id) 1.384 + return err_status_bad_param; 1.385 + 1.386 + /* check auth type by running self-test */ 1.387 + status = auth_type_self_test(new_at); 1.388 + if (status) { 1.389 + return status; 1.390 + } 1.391 + 1.392 + /* walk down list, checking if this type is in the list already */ 1.393 + atype = crypto_kernel.auth_type_list; 1.394 + while (atype != NULL) { 1.395 + if (id == atype->id) { 1.396 + if (!replace) 1.397 + return err_status_bad_param; 1.398 + status = auth_type_test(new_at, atype->auth_type->test_data); 1.399 + if (status) 1.400 + return status; 1.401 + new_atype = atype; 1.402 + break; 1.403 + } 1.404 + else if (new_at == atype->auth_type) 1.405 + return err_status_bad_param; 1.406 + atype = atype->next; 1.407 + } 1.408 + 1.409 + /* if not found, put new_at at the head of the list */ 1.410 + if (atype == NULL) { 1.411 + /* allocate memory */ 1.412 + new_atype = (kernel_auth_type_t *)crypto_alloc(sizeof(kernel_auth_type_t)); 1.413 + if (new_atype == NULL) 1.414 + return err_status_alloc_fail; 1.415 + 1.416 + new_atype->next = crypto_kernel.auth_type_list; 1.417 + /* set head of list to new auth type */ 1.418 + crypto_kernel.auth_type_list = new_atype; 1.419 + } 1.420 + 1.421 + /* set fields */ 1.422 + new_atype->auth_type = new_at; 1.423 + new_atype->id = id; 1.424 + 1.425 + /* load debug module, if there is one present */ 1.426 + if (new_at->debug != NULL) 1.427 + crypto_kernel_load_debug_module(new_at->debug); 1.428 + /* we could check for errors here */ 1.429 + 1.430 + return err_status_ok; 1.431 + 1.432 +} 1.433 + 1.434 +err_status_t 1.435 +crypto_kernel_load_auth_type(auth_type_t *new_at, auth_type_id_t id) { 1.436 + return crypto_kernel_do_load_auth_type(new_at, id, 0); 1.437 +} 1.438 + 1.439 +err_status_t 1.440 +crypto_kernel_replace_auth_type(auth_type_t *new_at, auth_type_id_t id) { 1.441 + return crypto_kernel_do_load_auth_type(new_at, id, 1); 1.442 +} 1.443 + 1.444 + 1.445 +cipher_type_t * 1.446 +crypto_kernel_get_cipher_type(cipher_type_id_t id) { 1.447 + kernel_cipher_type_t *ctype; 1.448 + 1.449 + /* walk down list, looking for id */ 1.450 + ctype = crypto_kernel.cipher_type_list; 1.451 + while (ctype != NULL) { 1.452 + if (id == ctype->id) 1.453 + return ctype->cipher_type; 1.454 + ctype = ctype->next; 1.455 + } 1.456 + 1.457 + /* haven't found the right one, indicate failure by returning NULL */ 1.458 + return NULL; 1.459 +} 1.460 + 1.461 + 1.462 +err_status_t 1.463 +crypto_kernel_alloc_cipher(cipher_type_id_t id, 1.464 + cipher_pointer_t *cp, 1.465 + int key_len) { 1.466 + cipher_type_t *ct; 1.467 + 1.468 + /* 1.469 + * if the crypto_kernel is not yet initialized, we refuse to allocate 1.470 + * any ciphers - this is a bit extra-paranoid 1.471 + */ 1.472 + if (crypto_kernel.state != crypto_kernel_state_secure) 1.473 + return err_status_init_fail; 1.474 + 1.475 + ct = crypto_kernel_get_cipher_type(id); 1.476 + if (!ct) 1.477 + return err_status_fail; 1.478 + 1.479 + return ((ct)->alloc(cp, key_len)); 1.480 +} 1.481 + 1.482 + 1.483 + 1.484 +auth_type_t * 1.485 +crypto_kernel_get_auth_type(auth_type_id_t id) { 1.486 + kernel_auth_type_t *atype; 1.487 + 1.488 + /* walk down list, looking for id */ 1.489 + atype = crypto_kernel.auth_type_list; 1.490 + while (atype != NULL) { 1.491 + if (id == atype->id) 1.492 + return atype->auth_type; 1.493 + atype = atype->next; 1.494 + } 1.495 + 1.496 + /* haven't found the right one, indicate failure by returning NULL */ 1.497 + return NULL; 1.498 +} 1.499 + 1.500 +err_status_t 1.501 +crypto_kernel_alloc_auth(auth_type_id_t id, 1.502 + auth_pointer_t *ap, 1.503 + int key_len, 1.504 + int tag_len) { 1.505 + auth_type_t *at; 1.506 + 1.507 + /* 1.508 + * if the crypto_kernel is not yet initialized, we refuse to allocate 1.509 + * any auth functions - this is a bit extra-paranoid 1.510 + */ 1.511 + if (crypto_kernel.state != crypto_kernel_state_secure) 1.512 + return err_status_init_fail; 1.513 + 1.514 + at = crypto_kernel_get_auth_type(id); 1.515 + if (!at) 1.516 + return err_status_fail; 1.517 + 1.518 + return ((at)->alloc(ap, key_len, tag_len)); 1.519 +} 1.520 + 1.521 +err_status_t 1.522 +crypto_kernel_load_debug_module(debug_module_t *new_dm) { 1.523 + kernel_debug_module_t *kdm, *new; 1.524 + 1.525 + /* defensive coding */ 1.526 + if (new_dm == NULL) 1.527 + return err_status_bad_param; 1.528 + 1.529 + /* walk down list, checking if this type is in the list already */ 1.530 + kdm = crypto_kernel.debug_module_list; 1.531 + while (kdm != NULL) { 1.532 + if (strncmp(new_dm->name, kdm->mod->name, 64) == 0) 1.533 + return err_status_bad_param; 1.534 + kdm = kdm->next; 1.535 + } 1.536 + 1.537 + /* put new_dm at the head of the list */ 1.538 + /* allocate memory */ 1.539 + new = (kernel_debug_module_t *)crypto_alloc(sizeof(kernel_debug_module_t)); 1.540 + if (new == NULL) 1.541 + return err_status_alloc_fail; 1.542 + 1.543 + /* set fields */ 1.544 + new->mod = new_dm; 1.545 + new->next = crypto_kernel.debug_module_list; 1.546 + 1.547 + /* set head of list to new cipher type */ 1.548 + crypto_kernel.debug_module_list = new; 1.549 + 1.550 + return err_status_ok; 1.551 +} 1.552 + 1.553 +err_status_t 1.554 +crypto_kernel_set_debug_module(char *name, int on) { 1.555 + kernel_debug_module_t *kdm; 1.556 + 1.557 + /* walk down list, checking if this type is in the list already */ 1.558 + kdm = crypto_kernel.debug_module_list; 1.559 + while (kdm != NULL) { 1.560 + if (strncmp(name, kdm->mod->name, 64) == 0) { 1.561 + kdm->mod->on = on; 1.562 + return err_status_ok; 1.563 + } 1.564 + kdm = kdm->next; 1.565 + } 1.566 + 1.567 + return err_status_fail; 1.568 +} 1.569 + 1.570 +err_status_t 1.571 +crypto_get_random(unsigned char *buffer, unsigned int length) { 1.572 + if (crypto_kernel.state == crypto_kernel_state_secure) 1.573 + return ctr_prng_get_octet_string(buffer, length); 1.574 + else 1.575 + return err_status_fail; 1.576 +}