LCOV - code coverage report
Current view: top level - netwerk/srtp/src/crypto/kernel - crypto_kernel.c (source / functions) Hit Total Coverage
Test: output.info Lines: 0 244 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 17 0.0 %
Legend: Lines: hit not hit

          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             : }

Generated by: LCOV version 1.13