Line data Source code
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 0 : crypto_kernel_init() {
96 : err_status_t status;
97 :
98 : /* check the security state */
99 0 : 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 0 : return crypto_kernel_status();
106 : }
107 :
108 : /* initialize error reporting system */
109 0 : status = err_reporting_init("crypto");
110 0 : if (status)
111 0 : return status;
112 :
113 : /* load debug modules */
114 0 : status = crypto_kernel_load_debug_module(&mod_crypto_kernel);
115 0 : if (status)
116 0 : return status;
117 0 : status = crypto_kernel_load_debug_module(&mod_auth);
118 0 : if (status)
119 0 : return status;
120 0 : status = crypto_kernel_load_debug_module(&mod_cipher);
121 0 : if (status)
122 0 : return status;
123 0 : status = crypto_kernel_load_debug_module(&mod_stat);
124 0 : if (status)
125 0 : return status;
126 0 : status = crypto_kernel_load_debug_module(&mod_alloc);
127 0 : if (status)
128 0 : return status;
129 :
130 : /* initialize random number generator */
131 0 : status = rand_source_init();
132 0 : if (status)
133 0 : return status;
134 :
135 : /* run FIPS-140 statistical tests on rand_source */
136 0 : status = stat_test_rand_source_with_repetition(rand_source_get_octet_string, MAX_RNG_TRIALS);
137 0 : if (status)
138 0 : return status;
139 :
140 : /* initialize pseudorandom number generator */
141 0 : status = ctr_prng_init(rand_source_get_octet_string);
142 0 : if (status)
143 0 : return status;
144 :
145 : /* run FIPS-140 statistical tests on ctr_prng */
146 0 : status = stat_test_rand_source_with_repetition(ctr_prng_get_octet_string, MAX_RNG_TRIALS);
147 0 : if (status)
148 0 : return status;
149 :
150 : /* load cipher types */
151 0 : status = crypto_kernel_load_cipher_type(&null_cipher, NULL_CIPHER);
152 0 : if (status)
153 0 : return status;
154 0 : status = crypto_kernel_load_cipher_type(&aes_icm, AES_ICM);
155 0 : if (status)
156 0 : return status;
157 0 : status = crypto_kernel_load_cipher_type(&aes_cbc, AES_CBC);
158 0 : if (status)
159 0 : return status;
160 :
161 : /* load auth func types */
162 0 : status = crypto_kernel_load_auth_type(&null_auth, NULL_AUTH);
163 0 : if (status)
164 0 : return status;
165 0 : status = crypto_kernel_load_auth_type(&hmac, HMAC_SHA1);
166 0 : if (status)
167 0 : return status;
168 :
169 : /* change state to secure */
170 0 : crypto_kernel.state = crypto_kernel_state_secure;
171 :
172 0 : return err_status_ok;
173 : }
174 :
175 : err_status_t
176 0 : crypto_kernel_status() {
177 : err_status_t status;
178 0 : kernel_cipher_type_t *ctype = crypto_kernel.cipher_type_list;
179 0 : kernel_auth_type_t *atype = crypto_kernel.auth_type_list;
180 0 : kernel_debug_module_t *dm = crypto_kernel.debug_module_list;
181 :
182 : /* run FIPS-140 statistical tests on rand_source */
183 0 : printf("testing rand_source...");
184 0 : status = stat_test_rand_source_with_repetition(rand_source_get_octet_string, MAX_RNG_TRIALS);
185 0 : if (status) {
186 0 : printf("failed\n");
187 0 : crypto_kernel.state = crypto_kernel_state_insecure;
188 0 : return status;
189 : }
190 0 : printf("passed\n");
191 :
192 : /* for each cipher type, describe and test */
193 0 : while(ctype != NULL) {
194 0 : printf("cipher: %s\n", ctype->cipher_type->description);
195 0 : printf(" instance count: %d\n", ctype->cipher_type->ref_count);
196 0 : printf(" self-test: ");
197 0 : status = cipher_type_self_test(ctype->cipher_type);
198 0 : if (status) {
199 0 : printf("failed with error code %d\n", status);
200 0 : exit(status);
201 : }
202 0 : printf("passed\n");
203 0 : ctype = ctype->next;
204 : }
205 :
206 : /* for each auth type, describe and test */
207 0 : while(atype != NULL) {
208 0 : printf("auth func: %s\n", atype->auth_type->description);
209 0 : printf(" instance count: %d\n", atype->auth_type->ref_count);
210 0 : printf(" self-test: ");
211 0 : status = auth_type_self_test(atype->auth_type);
212 0 : if (status) {
213 0 : printf("failed with error code %d\n", status);
214 0 : exit(status);
215 : }
216 0 : printf("passed\n");
217 0 : atype = atype->next;
218 : }
219 :
220 : /* describe each debug module */
221 0 : printf("debug modules loaded:\n");
222 0 : while (dm != NULL) {
223 0 : printf(" %s ", dm->mod->name);
224 0 : if (dm->mod->on)
225 0 : printf("(on)\n");
226 : else
227 0 : printf("(off)\n");
228 0 : dm = dm->next;
229 : }
230 :
231 0 : return err_status_ok;
232 : }
233 :
234 : err_status_t
235 0 : crypto_kernel_list_debug_modules() {
236 0 : kernel_debug_module_t *dm = crypto_kernel.debug_module_list;
237 :
238 : /* describe each debug module */
239 0 : printf("debug modules loaded:\n");
240 0 : while (dm != NULL) {
241 0 : printf(" %s ", dm->mod->name);
242 0 : if (dm->mod->on)
243 0 : printf("(on)\n");
244 : else
245 0 : printf("(off)\n");
246 0 : dm = dm->next;
247 : }
248 :
249 0 : return err_status_ok;
250 : }
251 :
252 : err_status_t
253 0 : 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 0 : while (crypto_kernel.cipher_type_list != NULL) {
262 0 : kernel_cipher_type_t *ctype = crypto_kernel.cipher_type_list;
263 0 : 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 0 : crypto_free(ctype);
268 : }
269 :
270 : /* walk down authetication module list, freeing memory */
271 0 : while (crypto_kernel.auth_type_list != NULL) {
272 0 : kernel_auth_type_t *atype = crypto_kernel.auth_type_list;
273 0 : 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 0 : crypto_free(atype);
278 : }
279 :
280 : /* walk down debug module list, freeing memory */
281 0 : while (crypto_kernel.debug_module_list != NULL) {
282 0 : kernel_debug_module_t *kdm = crypto_kernel.debug_module_list;
283 0 : 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 0 : crypto_free(kdm);
288 : }
289 :
290 0 : /* de-initialize random number generator */ status = rand_source_deinit();
291 0 : if (status)
292 0 : return status;
293 :
294 : /* return to insecure state */
295 0 : crypto_kernel.state = crypto_kernel_state_insecure;
296 :
297 0 : return err_status_ok;
298 : }
299 :
300 : static inline err_status_t
301 0 : 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 0 : if (new_ct == NULL)
308 0 : return err_status_bad_param;
309 :
310 0 : if (new_ct->id != id)
311 0 : return err_status_bad_param;
312 :
313 : /* check cipher type by running self-test */
314 0 : status = cipher_type_self_test(new_ct);
315 0 : if (status) {
316 0 : return status;
317 : }
318 :
319 : /* walk down list, checking if this type is in the list already */
320 0 : ctype = crypto_kernel.cipher_type_list;
321 0 : while (ctype != NULL) {
322 0 : if (id == ctype->id) {
323 0 : if (!replace)
324 0 : return err_status_bad_param;
325 0 : status = cipher_type_test(new_ct, ctype->cipher_type->test_data);
326 0 : if (status)
327 0 : return status;
328 0 : new_ctype = ctype;
329 0 : break;
330 : }
331 0 : else if (new_ct == ctype->cipher_type)
332 0 : return err_status_bad_param;
333 0 : ctype = ctype->next;
334 : }
335 :
336 : /* if not found, put new_ct at the head of the list */
337 0 : if (ctype == NULL) {
338 : /* allocate memory */
339 0 : new_ctype = (kernel_cipher_type_t *) crypto_alloc(sizeof(kernel_cipher_type_t));
340 0 : if (new_ctype == NULL)
341 0 : return err_status_alloc_fail;
342 0 : new_ctype->next = crypto_kernel.cipher_type_list;
343 :
344 : /* set head of list to new cipher type */
345 0 : crypto_kernel.cipher_type_list = new_ctype;
346 : }
347 :
348 : /* set fields */
349 0 : new_ctype->cipher_type = new_ct;
350 0 : new_ctype->id = id;
351 :
352 : /* load debug module, if there is one present */
353 0 : if (new_ct->debug != NULL)
354 0 : crypto_kernel_load_debug_module(new_ct->debug);
355 : /* we could check for errors here */
356 :
357 0 : return err_status_ok;
358 : }
359 :
360 : err_status_t
361 0 : crypto_kernel_load_cipher_type(cipher_type_t *new_ct, cipher_type_id_t id) {
362 0 : return crypto_kernel_do_load_cipher_type(new_ct, id, 0);
363 : }
364 :
365 : err_status_t
366 0 : crypto_kernel_replace_cipher_type(cipher_type_t *new_ct, cipher_type_id_t id) {
367 0 : return crypto_kernel_do_load_cipher_type(new_ct, id, 1);
368 : }
369 :
370 : err_status_t
371 0 : 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 0 : if (new_at == NULL)
378 0 : return err_status_bad_param;
379 :
380 0 : if (new_at->id != id)
381 0 : return err_status_bad_param;
382 :
383 : /* check auth type by running self-test */
384 0 : status = auth_type_self_test(new_at);
385 0 : if (status) {
386 0 : return status;
387 : }
388 :
389 : /* walk down list, checking if this type is in the list already */
390 0 : atype = crypto_kernel.auth_type_list;
391 0 : while (atype != NULL) {
392 0 : if (id == atype->id) {
393 0 : if (!replace)
394 0 : return err_status_bad_param;
395 0 : status = auth_type_test(new_at, atype->auth_type->test_data);
396 0 : if (status)
397 0 : return status;
398 0 : new_atype = atype;
399 0 : break;
400 : }
401 0 : else if (new_at == atype->auth_type)
402 0 : return err_status_bad_param;
403 0 : atype = atype->next;
404 : }
405 :
406 : /* if not found, put new_at at the head of the list */
407 0 : if (atype == NULL) {
408 : /* allocate memory */
409 0 : new_atype = (kernel_auth_type_t *)crypto_alloc(sizeof(kernel_auth_type_t));
410 0 : if (new_atype == NULL)
411 0 : return err_status_alloc_fail;
412 :
413 0 : new_atype->next = crypto_kernel.auth_type_list;
414 : /* set head of list to new auth type */
415 0 : crypto_kernel.auth_type_list = new_atype;
416 : }
417 :
418 : /* set fields */
419 0 : new_atype->auth_type = new_at;
420 0 : new_atype->id = id;
421 :
422 : /* load debug module, if there is one present */
423 0 : if (new_at->debug != NULL)
424 0 : crypto_kernel_load_debug_module(new_at->debug);
425 : /* we could check for errors here */
426 :
427 0 : return err_status_ok;
428 :
429 : }
430 :
431 : err_status_t
432 0 : crypto_kernel_load_auth_type(auth_type_t *new_at, auth_type_id_t id) {
433 0 : return crypto_kernel_do_load_auth_type(new_at, id, 0);
434 : }
435 :
436 : err_status_t
437 0 : crypto_kernel_replace_auth_type(auth_type_t *new_at, auth_type_id_t id) {
438 0 : return crypto_kernel_do_load_auth_type(new_at, id, 1);
439 : }
440 :
441 :
442 : cipher_type_t *
443 0 : 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 0 : ctype = crypto_kernel.cipher_type_list;
448 0 : while (ctype != NULL) {
449 0 : if (id == ctype->id)
450 0 : return ctype->cipher_type;
451 0 : ctype = ctype->next;
452 : }
453 :
454 : /* haven't found the right one, indicate failure by returning NULL */
455 0 : return NULL;
456 : }
457 :
458 :
459 : err_status_t
460 0 : 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 0 : if (crypto_kernel.state != crypto_kernel_state_secure)
470 0 : return err_status_init_fail;
471 :
472 0 : ct = crypto_kernel_get_cipher_type(id);
473 0 : if (!ct)
474 0 : return err_status_fail;
475 :
476 0 : return ((ct)->alloc(cp, key_len));
477 : }
478 :
479 :
480 :
481 : auth_type_t *
482 0 : 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 0 : atype = crypto_kernel.auth_type_list;
487 0 : while (atype != NULL) {
488 0 : if (id == atype->id)
489 0 : return atype->auth_type;
490 0 : atype = atype->next;
491 : }
492 :
493 : /* haven't found the right one, indicate failure by returning NULL */
494 0 : return NULL;
495 : }
496 :
497 : err_status_t
498 0 : 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 0 : if (crypto_kernel.state != crypto_kernel_state_secure)
509 0 : return err_status_init_fail;
510 :
511 0 : at = crypto_kernel_get_auth_type(id);
512 0 : if (!at)
513 0 : return err_status_fail;
514 :
515 0 : return ((at)->alloc(ap, key_len, tag_len));
516 : }
517 :
518 : err_status_t
519 0 : crypto_kernel_load_debug_module(debug_module_t *new_dm) {
520 : kernel_debug_module_t *kdm, *new;
521 :
522 : /* defensive coding */
523 0 : if (new_dm == NULL)
524 0 : return err_status_bad_param;
525 :
526 : /* walk down list, checking if this type is in the list already */
527 0 : kdm = crypto_kernel.debug_module_list;
528 0 : while (kdm != NULL) {
529 0 : if (strncmp(new_dm->name, kdm->mod->name, 64) == 0)
530 0 : return err_status_bad_param;
531 0 : kdm = kdm->next;
532 : }
533 :
534 : /* put new_dm at the head of the list */
535 : /* allocate memory */
536 0 : new = (kernel_debug_module_t *)crypto_alloc(sizeof(kernel_debug_module_t));
537 0 : if (new == NULL)
538 0 : return err_status_alloc_fail;
539 :
540 : /* set fields */
541 0 : new->mod = new_dm;
542 0 : new->next = crypto_kernel.debug_module_list;
543 :
544 : /* set head of list to new cipher type */
545 0 : crypto_kernel.debug_module_list = new;
546 :
547 0 : return err_status_ok;
548 : }
549 :
550 : err_status_t
551 0 : 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 0 : kdm = crypto_kernel.debug_module_list;
556 0 : while (kdm != NULL) {
557 0 : if (strncmp(name, kdm->mod->name, 64) == 0) {
558 0 : kdm->mod->on = on;
559 0 : return err_status_ok;
560 : }
561 0 : kdm = kdm->next;
562 : }
563 :
564 0 : return err_status_fail;
565 : }
566 :
567 : err_status_t
568 0 : crypto_get_random(unsigned char *buffer, unsigned int length) {
569 0 : if (crypto_kernel.state == crypto_kernel_state_secure)
570 0 : return ctr_prng_get_octet_string(buffer, length);
571 : else
572 0 : return err_status_fail;
573 : }
|