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_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