Home | History | Annotate | Download | only in kernel
      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