Home | History | Annotate | Download | only in cipher
      1 /*
      2  * cipher.c
      3  *
      4  * cipher meta-functions
      5  *
      6  * David A. McGrew
      7  * Cisco Systems, Inc.
      8  *
      9  */
     10 
     11 /*
     12  *
     13  * Copyright (c) 2001-2006, Cisco Systems, Inc.
     14  * All rights reserved.
     15  *
     16  * Redistribution and use in source and binary forms, with or without
     17  * modification, are permitted provided that the following conditions
     18  * are met:
     19  *
     20  *   Redistributions of source code must retain the above copyright
     21  *   notice, this list of conditions and the following disclaimer.
     22  *
     23  *   Redistributions in binary form must reproduce the above
     24  *   copyright notice, this list of conditions and the following
     25  *   disclaimer in the documentation and/or other materials provided
     26  *   with the distribution.
     27  *
     28  *   Neither the name of the Cisco Systems, Inc. nor the names of its
     29  *   contributors may be used to endorse or promote products derived
     30  *   from this software without specific prior written permission.
     31  *
     32  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     33  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     34  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
     35  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
     36  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
     37  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     38  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     39  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     40  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     41  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     42  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
     43  * OF THE POSSIBILITY OF SUCH DAMAGE.
     44  *
     45  */
     46 
     47 #include "cipher.h"
     48 #include "rand_source.h"        /* used in invertibiltiy tests        */
     49 #include "alloc.h"              /* for crypto_alloc(), crypto_free()  */
     50 
     51 debug_module_t mod_cipher = {
     52   0,                 /* debugging is off by default */
     53   "cipher"           /* printable module name       */
     54 };
     55 
     56 err_status_t
     57 cipher_output(cipher_t *c, uint8_t *buffer, int num_octets_to_output) {
     58 
     59   /* zeroize the buffer */
     60   octet_string_set_to_zero(buffer, num_octets_to_output);
     61 
     62   /* exor keystream into buffer */
     63   return cipher_encrypt(c, buffer, (unsigned int *) &num_octets_to_output);
     64 }
     65 
     66 /* some bookkeeping functions */
     67 
     68 int
     69 cipher_get_key_length(const cipher_t *c) {
     70   return c->key_len;
     71 }
     72 
     73 /*
     74  * cipher_type_self_test(ct) tests a cipher of type ct against test cases
     75  * provided in an array of values of key, salt, xtd_seq_num_t,
     76  * plaintext, and ciphertext that is known to be good
     77  */
     78 
     79 #define SELF_TEST_BUF_OCTETS 128
     80 #define NUM_RAND_TESTS       128
     81 #define MAX_KEY_LEN          64
     82 
     83 err_status_t
     84 cipher_type_self_test(const cipher_type_t *ct) {
     85   const cipher_test_case_t *test_case = ct->test_data;
     86   cipher_t *c;
     87   err_status_t status;
     88   uint8_t buffer[SELF_TEST_BUF_OCTETS];
     89   uint8_t buffer2[SELF_TEST_BUF_OCTETS];
     90   unsigned int len;
     91   int i, j, case_num = 0;
     92 
     93   debug_print(mod_cipher, "running self-test for cipher %s",
     94 	      ct->description);
     95 
     96   /*
     97    * check to make sure that we have at least one test case, and
     98    * return an error if we don't - we need to be paranoid here
     99    */
    100   if (test_case == NULL)
    101     return err_status_cant_check;
    102 
    103   /*
    104    * loop over all test cases, perform known-answer tests of both the
    105    * encryption and decryption functions
    106    */
    107   while (test_case != NULL) {
    108 
    109     /* allocate cipher */
    110     status = cipher_type_alloc(ct, &c, test_case->key_length_octets);
    111     if (status)
    112       return status;
    113 
    114     /*
    115      * test the encrypt function
    116      */
    117     debug_print(mod_cipher, "testing encryption", NULL);
    118 
    119     /* initialize cipher */
    120     status = cipher_init(c, test_case->key, direction_encrypt);
    121     if (status) {
    122       cipher_dealloc(c);
    123       return status;
    124     }
    125 
    126     /* copy plaintext into test buffer */
    127     if (test_case->ciphertext_length_octets > SELF_TEST_BUF_OCTETS) {
    128       cipher_dealloc(c);
    129       return err_status_bad_param;
    130     }
    131     for (i=0; i < test_case->plaintext_length_octets; i++)
    132       buffer[i] = test_case->plaintext[i];
    133 
    134     debug_print(mod_cipher, "plaintext:    %s",
    135 	     octet_string_hex_string(buffer,
    136 				     test_case->plaintext_length_octets));
    137 
    138     /* set the initialization vector */
    139     status = cipher_set_iv(c, test_case->idx);
    140     if (status) {
    141       cipher_dealloc(c);
    142       return status;
    143     }
    144 
    145     /* encrypt */
    146     len = test_case->plaintext_length_octets;
    147     status = cipher_encrypt(c, buffer, &len);
    148     if (status) {
    149       cipher_dealloc(c);
    150       return status;
    151     }
    152 
    153     debug_print(mod_cipher, "ciphertext:   %s",
    154 	     octet_string_hex_string(buffer,
    155 				     test_case->ciphertext_length_octets));
    156 
    157     /* compare the resulting ciphertext with that in the test case */
    158     if (len != test_case->ciphertext_length_octets)
    159       return err_status_algo_fail;
    160     status = err_status_ok;
    161     for (i=0; i < test_case->ciphertext_length_octets; i++)
    162       if (buffer[i] != test_case->ciphertext[i]) {
    163 	status = err_status_algo_fail;
    164 	debug_print(mod_cipher, "test case %d failed", case_num);
    165 	debug_print(mod_cipher, "(failure at byte %d)", i);
    166 	break;
    167       }
    168     if (status) {
    169 
    170       debug_print(mod_cipher, "c computed: %s",
    171 	     octet_string_hex_string(buffer,
    172 		  2*test_case->plaintext_length_octets));
    173       debug_print(mod_cipher, "c expected: %s",
    174 		  octet_string_hex_string(test_case->ciphertext,
    175 			  2*test_case->plaintext_length_octets));
    176 
    177       cipher_dealloc(c);
    178       return err_status_algo_fail;
    179     }
    180 
    181     /*
    182      * test the decrypt function
    183      */
    184     debug_print(mod_cipher, "testing decryption", NULL);
    185 
    186     /* re-initialize cipher for decryption */
    187     status = cipher_init(c, test_case->key, direction_decrypt);
    188     if (status) {
    189       cipher_dealloc(c);
    190       return status;
    191     }
    192 
    193     /* copy ciphertext into test buffer */
    194     if (test_case->ciphertext_length_octets > SELF_TEST_BUF_OCTETS) {
    195       cipher_dealloc(c);
    196       return err_status_bad_param;
    197     }
    198     for (i=0; i < test_case->ciphertext_length_octets; i++)
    199       buffer[i] = test_case->ciphertext[i];
    200 
    201     debug_print(mod_cipher, "ciphertext:    %s",
    202 		octet_string_hex_string(buffer,
    203 					test_case->plaintext_length_octets));
    204 
    205     /* set the initialization vector */
    206     status = cipher_set_iv(c, test_case->idx);
    207     if (status) {
    208       cipher_dealloc(c);
    209       return status;
    210     }
    211 
    212     /* decrypt */
    213     len = test_case->ciphertext_length_octets;
    214     status = cipher_decrypt(c, buffer, &len);
    215     if (status) {
    216       cipher_dealloc(c);
    217       return status;
    218     }
    219 
    220     debug_print(mod_cipher, "plaintext:   %s",
    221 	     octet_string_hex_string(buffer,
    222 				     test_case->plaintext_length_octets));
    223 
    224     /* compare the resulting plaintext with that in the test case */
    225     if (len != test_case->plaintext_length_octets)
    226       return err_status_algo_fail;
    227     status = err_status_ok;
    228     for (i=0; i < test_case->plaintext_length_octets; i++)
    229       if (buffer[i] != test_case->plaintext[i]) {
    230 	status = err_status_algo_fail;
    231 	debug_print(mod_cipher, "test case %d failed", case_num);
    232 	debug_print(mod_cipher, "(failure at byte %d)", i);
    233       }
    234     if (status) {
    235 
    236       debug_print(mod_cipher, "p computed: %s",
    237 	     octet_string_hex_string(buffer,
    238 		  2*test_case->plaintext_length_octets));
    239       debug_print(mod_cipher, "p expected: %s",
    240 		  octet_string_hex_string(test_case->plaintext,
    241 			  2*test_case->plaintext_length_octets));
    242 
    243       cipher_dealloc(c);
    244       return err_status_algo_fail;
    245     }
    246 
    247     /* deallocate the cipher */
    248     status = cipher_dealloc(c);
    249     if (status)
    250       return status;
    251 
    252     /*
    253      * the cipher passed the test case, so move on to the next test
    254      * case in the list; if NULL, we'l proceed to the next test
    255      */
    256     test_case = test_case->next_test_case;
    257     ++case_num;
    258   }
    259 
    260   /* now run some random invertibility tests */
    261 
    262   /* allocate cipher, using paramaters from the first test case */
    263   test_case = ct->test_data;
    264   status = cipher_type_alloc(ct, &c, test_case->key_length_octets);
    265   if (status)
    266       return status;
    267 
    268   rand_source_init();
    269 
    270   for (j=0; j < NUM_RAND_TESTS; j++) {
    271     unsigned length;
    272     int plaintext_len;
    273     uint8_t key[MAX_KEY_LEN];
    274     uint8_t  iv[MAX_KEY_LEN];
    275 
    276     /* choose a length at random (leaving room for IV and padding) */
    277     length = rand() % (SELF_TEST_BUF_OCTETS - 64);
    278     debug_print(mod_cipher, "random plaintext length %d\n", length);
    279     status = rand_source_get_octet_string(buffer, length);
    280     if (status) return status;
    281 
    282     debug_print(mod_cipher, "plaintext:    %s",
    283 		octet_string_hex_string(buffer, length));
    284 
    285     /* copy plaintext into second buffer */
    286     for (i=0; (unsigned int)i < length; i++)
    287       buffer2[i] = buffer[i];
    288 
    289     /* choose a key at random */
    290     if (test_case->key_length_octets > MAX_KEY_LEN)
    291       return err_status_cant_check;
    292     status = rand_source_get_octet_string(key, test_case->key_length_octets);
    293     if (status) return status;
    294 
    295    /* chose a random initialization vector */
    296     status = rand_source_get_octet_string(iv, MAX_KEY_LEN);
    297     if (status) return status;
    298 
    299     /* initialize cipher */
    300     status = cipher_init(c, key, direction_encrypt);
    301     if (status) {
    302       cipher_dealloc(c);
    303       return status;
    304     }
    305 
    306     /* set initialization vector */
    307     status = cipher_set_iv(c, test_case->idx);
    308     if (status) {
    309       cipher_dealloc(c);
    310       return status;
    311     }
    312 
    313     /* encrypt buffer with cipher */
    314     plaintext_len = length;
    315     status = cipher_encrypt(c, buffer, &length);
    316     if (status) {
    317       cipher_dealloc(c);
    318       return status;
    319     }
    320     debug_print(mod_cipher, "ciphertext:   %s",
    321 		octet_string_hex_string(buffer, length));
    322 
    323     /*
    324      * re-initialize cipher for decryption, re-set the iv, then
    325      * decrypt the ciphertext
    326      */
    327     status = cipher_init(c, key, direction_decrypt);
    328     if (status) {
    329       cipher_dealloc(c);
    330       return status;
    331     }
    332     status = cipher_set_iv(c, test_case->idx);
    333     if (status) {
    334       cipher_dealloc(c);
    335       return status;
    336     }
    337     status = cipher_decrypt(c, buffer, &length);
    338     if (status) {
    339       cipher_dealloc(c);
    340       return status;
    341     }
    342 
    343     debug_print(mod_cipher, "plaintext[2]: %s",
    344 		octet_string_hex_string(buffer, length));
    345 
    346     /* compare the resulting plaintext with the original one */
    347     if (length != plaintext_len)
    348       return err_status_algo_fail;
    349     status = err_status_ok;
    350     for (i=0; i < plaintext_len; i++)
    351       if (buffer[i] != buffer2[i]) {
    352 	status = err_status_algo_fail;
    353 	debug_print(mod_cipher, "random test case %d failed", case_num);
    354 	debug_print(mod_cipher, "(failure at byte %d)", i);
    355       }
    356     if (status) {
    357       cipher_dealloc(c);
    358       return err_status_algo_fail;
    359     }
    360 
    361   }
    362 
    363   return err_status_ok;
    364 }
    365 
    366 
    367 /*
    368  * cipher_bits_per_second(c, l, t) computes (an estimate of) the
    369  * number of bits that a cipher implementation can encrypt in a second
    370  *
    371  * c is a cipher (which MUST be allocated and initialized already), l
    372  * is the length in octets of the test data to be encrypted, and t is
    373  * the number of trials
    374  *
    375  * if an error is encountered, the value 0 is returned
    376  */
    377 
    378 uint64_t
    379 cipher_bits_per_second(cipher_t *c, int octets_in_buffer, int num_trials) {
    380   int i;
    381   v128_t nonce;
    382   clock_t timer;
    383   unsigned char *enc_buf;
    384   unsigned int len = octets_in_buffer;
    385 
    386   enc_buf = (unsigned char*) crypto_alloc(octets_in_buffer);
    387   if (enc_buf == NULL)
    388     return 0;  /* indicate bad parameters by returning null */
    389 
    390   /* time repeated trials */
    391   v128_set_to_zero(&nonce);
    392   timer = clock();
    393   for(i=0; i < num_trials; i++, nonce.v32[3] = i) {
    394     cipher_set_iv(c, &nonce);
    395     cipher_encrypt(c, enc_buf, &len);
    396   }
    397   timer = clock() - timer;
    398 
    399   crypto_free(enc_buf);
    400 
    401   if (timer == 0) {
    402     /* Too fast! */
    403     return 0;
    404   }
    405 
    406   return (uint64_t)CLOCKS_PER_SEC * num_trials * 8 * octets_in_buffer / timer;
    407 }
    408