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

          Line data    Source code
       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           0 : cipher_output(cipher_t *c, uint8_t *buffer, int num_octets_to_output) {
      58             :   
      59             :   /* zeroize the buffer */
      60           0 :   octet_string_set_to_zero(buffer, num_octets_to_output);
      61             :   
      62             :   /* exor keystream into buffer */
      63           0 :   return cipher_encrypt(c, buffer, (unsigned int *) &num_octets_to_output);
      64             : }
      65             : 
      66             : /* some bookkeeping functions */
      67             : 
      68             : int
      69           0 : cipher_get_key_length(const cipher_t *c) {
      70           0 :   return c->key_len;
      71             : }
      72             : 
      73             : /* 
      74             :  * cipher_type_test(ct, test_data) tests a cipher of type ct against
      75             :  * test cases provided in a list test_data of values of key, salt, iv,
      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           0 : cipher_type_test(const cipher_type_t *ct, const cipher_test_case_t *test_data) {
      85           0 :   const cipher_test_case_t *test_case = 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           0 :   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           0 :   if (test_case == NULL)
     101           0 :     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           0 :   while (test_case != NULL) {
     108             : 
     109             :     /* allocate cipher */
     110           0 :     status = cipher_type_alloc(ct, &c, test_case->key_length_octets);
     111           0 :     if (status)
     112           0 :       return status;
     113             :     
     114             :     /*
     115             :      * test the encrypt function 
     116             :      */
     117             :     debug_print(mod_cipher, "testing encryption", NULL);    
     118             :     
     119             :     /* initialize cipher */
     120           0 :     status = cipher_init(c, test_case->key, direction_encrypt);
     121           0 :     if (status) {
     122           0 :       cipher_dealloc(c);
     123           0 :       return status;
     124             :     }
     125             :     
     126             :     /* copy plaintext into test buffer */
     127           0 :     if (test_case->ciphertext_length_octets > SELF_TEST_BUF_OCTETS) {
     128           0 :       cipher_dealloc(c);    
     129           0 :       return err_status_bad_param;
     130             :     }
     131           0 :     for (i=0; i < test_case->plaintext_length_octets; i++)
     132           0 :       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           0 :     status = cipher_set_iv(c, test_case->idx);
     140           0 :     if (status) {
     141           0 :       cipher_dealloc(c);
     142           0 :       return status;
     143             :     } 
     144             :     
     145             :     /* encrypt */
     146           0 :     len = test_case->plaintext_length_octets;
     147           0 :     status = cipher_encrypt(c, buffer, &len);
     148           0 :     if (status) {
     149           0 :       cipher_dealloc(c);
     150           0 :       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           0 :     if (len != (unsigned int)test_case->ciphertext_length_octets)
     159           0 :       return err_status_algo_fail;
     160           0 :     status = err_status_ok;
     161           0 :     for (i=0; i < test_case->ciphertext_length_octets; i++)
     162           0 :       if (buffer[i] != test_case->ciphertext[i]) {
     163           0 :         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           0 :         break;
     167             :       }
     168           0 :     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           0 :       cipher_dealloc(c);
     178           0 :       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           0 :     status = cipher_init(c, test_case->key, direction_decrypt);
     188           0 :     if (status) {
     189           0 :       cipher_dealloc(c);
     190           0 :       return status;
     191             :     }
     192             : 
     193             :     /* copy ciphertext into test buffer */
     194           0 :     if (test_case->ciphertext_length_octets > SELF_TEST_BUF_OCTETS) {
     195           0 :       cipher_dealloc(c);    
     196           0 :       return err_status_bad_param;
     197             :     }
     198           0 :     for (i=0; i < test_case->ciphertext_length_octets; i++)
     199           0 :       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           0 :     status = cipher_set_iv(c, test_case->idx);
     207           0 :     if (status) {
     208           0 :       cipher_dealloc(c);
     209           0 :       return status;
     210             :     } 
     211             :     
     212             :     /* decrypt */
     213           0 :     len = test_case->ciphertext_length_octets;
     214           0 :     status = cipher_decrypt(c, buffer, &len);
     215           0 :     if (status) {
     216           0 :       cipher_dealloc(c);
     217           0 :       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           0 :     if (len != (unsigned int)test_case->plaintext_length_octets)
     226           0 :       return err_status_algo_fail;
     227           0 :     status = err_status_ok;
     228           0 :     for (i=0; i < test_case->plaintext_length_octets; i++)
     229           0 :       if (buffer[i] != test_case->plaintext[i]) {
     230           0 :         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           0 :     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           0 :       cipher_dealloc(c);
     244           0 :       return err_status_algo_fail;
     245             :     }
     246             : 
     247             :     /* deallocate the cipher */
     248           0 :     status = cipher_dealloc(c);
     249           0 :     if (status)
     250           0 :       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           0 :     test_case = test_case->next_test_case;
     257           0 :     ++case_num;
     258             :   }
     259             :   
     260             :   /* now run some random invertibility tests */
     261             : 
     262             :   /* allocate cipher, using paramaters from the first test case */
     263           0 :   test_case = test_data;
     264           0 :   status = cipher_type_alloc(ct, &c, test_case->key_length_octets);
     265           0 :   if (status)
     266           0 :       return status;
     267             :   
     268           0 :   rand_source_init();
     269             :   
     270           0 :   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           0 :     length = rand() % (SELF_TEST_BUF_OCTETS - 64);
     278             :     debug_print(mod_cipher, "random plaintext length %d\n", length);
     279           0 :     status = rand_source_get_octet_string(buffer, length);
     280           0 :     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           0 :     for (i=0; (unsigned int)i < length; i++)
     287           0 :       buffer2[i] = buffer[i];
     288             :     
     289             :     /* choose a key at random */
     290           0 :     if (test_case->key_length_octets > MAX_KEY_LEN)
     291           0 :       return err_status_cant_check;
     292           0 :     status = rand_source_get_octet_string(key, test_case->key_length_octets);
     293           0 :     if (status) return status;
     294             : 
     295             :    /* chose a random initialization vector */
     296           0 :     status = rand_source_get_octet_string(iv, MAX_KEY_LEN);
     297           0 :     if (status) return status;
     298             :         
     299             :     /* initialize cipher */
     300           0 :     status = cipher_init(c, key, direction_encrypt);
     301           0 :     if (status) {
     302           0 :       cipher_dealloc(c);
     303           0 :       return status;
     304             :     }
     305             : 
     306             :     /* set initialization vector */
     307           0 :     status = cipher_set_iv(c, test_case->idx);
     308           0 :     if (status) {
     309           0 :       cipher_dealloc(c);
     310           0 :       return status;
     311             :     } 
     312             : 
     313             :     /* encrypt buffer with cipher */
     314           0 :     plaintext_len = length;
     315           0 :     status = cipher_encrypt(c, buffer, &length);
     316           0 :     if (status) {
     317           0 :       cipher_dealloc(c);
     318           0 :       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           0 :     status = cipher_init(c, key, direction_decrypt);
     328           0 :     if (status) {
     329           0 :       cipher_dealloc(c);
     330           0 :       return status;
     331             :     }
     332           0 :     status = cipher_set_iv(c, test_case->idx);
     333           0 :     if (status) {
     334           0 :       cipher_dealloc(c);
     335           0 :       return status;
     336             :     } 
     337           0 :     status = cipher_decrypt(c, buffer, &length);
     338           0 :     if (status) {
     339           0 :       cipher_dealloc(c);
     340           0 :       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           0 :     if (length != (unsigned)plaintext_len)
     348           0 :       return err_status_algo_fail;
     349           0 :     status = err_status_ok;
     350           0 :     for (i=0; i < plaintext_len; i++)
     351           0 :       if (buffer[i] != buffer2[i]) {
     352           0 :         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           0 :     if (status) {
     357           0 :       cipher_dealloc(c);
     358           0 :       return err_status_algo_fail;
     359             :     }
     360             :         
     361             :   }
     362             : 
     363           0 :   status = cipher_dealloc(c);
     364           0 :   if (status)
     365           0 :     return status;
     366             : 
     367           0 :   return err_status_ok;
     368             : }
     369             : 
     370             : 
     371             : /* 
     372             :  * cipher_type_self_test(ct) performs cipher_type_test on ct's internal
     373             :  * list of test data.
     374             :  */
     375             : 
     376             : err_status_t
     377           0 : cipher_type_self_test(const cipher_type_t *ct) {
     378           0 :   return cipher_type_test(ct, ct->test_data);
     379             : }
     380             : 
     381             : /*
     382             :  * cipher_bits_per_second(c, l, t) computes (an estimate of) the
     383             :  * number of bits that a cipher implementation can encrypt in a second
     384             :  * 
     385             :  * c is a cipher (which MUST be allocated and initialized already), l
     386             :  * is the length in octets of the test data to be encrypted, and t is
     387             :  * the number of trials
     388             :  *
     389             :  * if an error is encountered, the value 0 is returned
     390             :  */
     391             : 
     392             : uint64_t
     393           0 : cipher_bits_per_second(cipher_t *c, int octets_in_buffer, int num_trials) {
     394             :   int i;
     395             :   v128_t nonce;
     396             :   clock_t timer;
     397             :   unsigned char *enc_buf;
     398           0 :   unsigned int len = octets_in_buffer;
     399             : 
     400           0 :   enc_buf = (unsigned char*) crypto_alloc(octets_in_buffer);
     401           0 :   if (enc_buf == NULL)
     402           0 :     return 0;  /* indicate bad parameters by returning null */
     403             :   
     404             :   /* time repeated trials */
     405           0 :   v128_set_to_zero(&nonce);
     406           0 :   timer = clock();
     407           0 :   for(i=0; i < num_trials; i++, nonce.v32[3] = i) {
     408           0 :     cipher_set_iv(c, &nonce);
     409           0 :     cipher_encrypt(c, enc_buf, &len);
     410             :   }
     411           0 :   timer = clock() - timer;
     412             : 
     413           0 :   crypto_free(enc_buf);
     414             : 
     415           0 :   if (timer == 0) {
     416             :     /* Too fast! */
     417           0 :     return 0;
     418             :   }
     419             :   
     420           0 :   return (uint64_t)CLOCKS_PER_SEC * num_trials * 8 * octets_in_buffer / timer;
     421             : }

Generated by: LCOV version 1.13