• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
crypto_kernel_init()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
crypto_kernel_status()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
crypto_kernel_list_debug_modules()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
crypto_kernel_shutdown()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
crypto_kernel_load_cipher_type(cipher_type_t * new_ct,cipher_type_id_t id)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
crypto_kernel_load_auth_type(auth_type_t * new_at,auth_type_id_t id)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 *
crypto_kernel_get_cipher_type(cipher_type_id_t id)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
crypto_kernel_alloc_cipher(cipher_type_id_t id,cipher_pointer_t * cp,int key_len)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 *
crypto_kernel_get_auth_type(auth_type_id_t id)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
crypto_kernel_alloc_auth(auth_type_id_t id,auth_pointer_t * ap,int key_len,int tag_len)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
crypto_kernel_load_debug_module(debug_module_t * new_dm)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
crypto_kernel_set_debug_module(char * name,int on)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
crypto_get_random(unsigned char * buffer,unsigned int length)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