netwerk/srtp/src/crypto/kernel/crypto_kernel.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     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  */
    46 #include "alloc.h"
    48 #include "crypto_kernel.h"
    50 /* the debug module for the crypto_kernel */
    52 debug_module_t mod_crypto_kernel = {
    53   0,                  /* debugging is off by default */
    54   "crypto kernel"     /* printable name for module   */
    55 };
    57 /*
    58  * other debug modules that can be included in the kernel
    59  */
    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;
    66 /* 
    67  * cipher types that can be included in the kernel
    68  */ 
    70 extern cipher_type_t null_cipher;
    71 extern cipher_type_t aes_icm;
    72 extern cipher_type_t aes_cbc;
    75 /*
    76  * auth func types that can be included in the kernel
    77  */
    79 extern auth_type_t null_auth;
    80 extern auth_type_t hmac;
    82 /* crypto_kernel is a global variable, the only one of its datatype */
    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 };
    92 #define MAX_RNG_TRIALS 25
    94 err_status_t
    95 crypto_kernel_init() {
    96   err_status_t status;  
    98   /* check the security state */
    99   if (crypto_kernel.state == crypto_kernel_state_secure) {
   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   }
   108   /* initialize error reporting system */
   109   status = err_reporting_init("crypto");
   110   if (status)
   111     return status;
   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;
   130   /* initialize random number generator */
   131   status = rand_source_init();
   132   if (status)
   133     return status;
   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;
   140   /* initialize pseudorandom number generator */
   141   status = ctr_prng_init(rand_source_get_octet_string);
   142   if (status)
   143     return status;
   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;
   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;
   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;
   169   /* change state to secure */
   170   crypto_kernel.state = crypto_kernel_state_secure;
   172   return err_status_ok;
   173 }
   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;
   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");
   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   }
   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   }
   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   }
   231   return err_status_ok;
   232 }
   234 err_status_t
   235 crypto_kernel_list_debug_modules() {
   236   kernel_debug_module_t *dm = crypto_kernel.debug_module_list;
   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   }
   249   return err_status_ok;
   250 }
   252 err_status_t
   253 crypto_kernel_shutdown() {
   254   err_status_t status;
   256   /*
   257    * free dynamic memory used in crypto_kernel at present
   258    */
   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   }
   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   }
   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   }
   290   /* de-initialize random number generator */  status = rand_source_deinit();
   291   if (status)
   292     return status;
   294   /* return to insecure state */
   295   crypto_kernel.state = crypto_kernel_state_insecure;
   297   return err_status_ok;
   298 }
   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;
   306   /* defensive coding */
   307   if (new_ct == NULL)
   308     return err_status_bad_param;
   310   if (new_ct->id != id)
   311     return err_status_bad_param;
   313   /* check cipher type by running self-test */
   314   status = cipher_type_self_test(new_ct);
   315   if (status) {
   316     return status;
   317   }
   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   }
   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;
   344     /* set head of list to new cipher type */
   345     crypto_kernel.cipher_type_list = new_ctype;    
   346   }
   348   /* set fields */
   349   new_ctype->cipher_type = new_ct;
   350   new_ctype->id = id;
   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 */
   357   return err_status_ok;
   358 }
   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 }
   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 }
   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;
   376   /* defensive coding */
   377   if (new_at == NULL)
   378     return err_status_bad_param;
   380   if (new_at->id != id)
   381     return err_status_bad_param;
   383   /* check auth type by running self-test */
   384   status = auth_type_self_test(new_at);
   385   if (status) {
   386     return status;
   387   }
   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   }
   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;
   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   }
   418   /* set fields */
   419   new_atype->auth_type = new_at;
   420   new_atype->id = id;
   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 */
   427   return err_status_ok;
   429 }
   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 }
   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 }
   442 cipher_type_t *
   443 crypto_kernel_get_cipher_type(cipher_type_id_t id) {
   444   kernel_cipher_type_t *ctype;
   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   } 
   454   /* haven't found the right one, indicate failure by returning NULL */
   455   return NULL;
   456 }
   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;
   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;
   472   ct = crypto_kernel_get_cipher_type(id);
   473   if (!ct)
   474     return err_status_fail;
   476   return ((ct)->alloc(cp, key_len));
   477 }
   481 auth_type_t *
   482 crypto_kernel_get_auth_type(auth_type_id_t id) {
   483   kernel_auth_type_t *atype;
   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   } 
   493   /* haven't found the right one, indicate failure by returning NULL */
   494   return NULL;
   495 }
   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;
   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;
   511   at = crypto_kernel_get_auth_type(id);
   512   if (!at)
   513     return err_status_fail;
   515   return ((at)->alloc(ap, key_len, tag_len));
   516 }
   518 err_status_t
   519 crypto_kernel_load_debug_module(debug_module_t *new_dm) {
   520   kernel_debug_module_t *kdm, *new;
   522   /* defensive coding */
   523   if (new_dm == NULL)
   524     return err_status_bad_param;
   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   }
   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;
   540   /* set fields */
   541   new->mod = new_dm;
   542   new->next = crypto_kernel.debug_module_list;
   544   /* set head of list to new cipher type */
   545   crypto_kernel.debug_module_list = new;    
   547   return err_status_ok;
   548 }
   550 err_status_t
   551 crypto_kernel_set_debug_module(char *name, int on) {
   552   kernel_debug_module_t *kdm;
   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   }
   564   return err_status_fail;
   565 }
   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 }

mercurial