1386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari/* 2386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * cipher.c 3386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * 4386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * cipher meta-functions 5386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * 6386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * David A. McGrew 7386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * Cisco Systems, Inc. 8386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * 9386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari */ 10386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 11386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari/* 12386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * 13386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * Copyright (c) 2001-2006, Cisco Systems, Inc. 14386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * All rights reserved. 15386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * 16386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * Redistribution and use in source and binary forms, with or without 17386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * modification, are permitted provided that the following conditions 18386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * are met: 19386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * 20386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * Redistributions of source code must retain the above copyright 21386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * notice, this list of conditions and the following disclaimer. 22386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * 23386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * Redistributions in binary form must reproduce the above 24386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * copyright notice, this list of conditions and the following 25386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * disclaimer in the documentation and/or other materials provided 26386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * with the distribution. 27386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * 28386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * Neither the name of the Cisco Systems, Inc. nor the names of its 29386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * contributors may be used to endorse or promote products derived 30386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * from this software without specific prior written permission. 31386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * 32386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 33386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 34386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 35386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 36386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 37386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 38386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 39386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 40386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 41386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 42386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 43386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * OF THE POSSIBILITY OF SUCH DAMAGE. 44386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * 45386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari */ 46386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 47386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#include "cipher.h" 48386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#include "rand_source.h" /* used in invertibiltiy tests */ 49386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#include "alloc.h" /* for crypto_alloc(), crypto_free() */ 50386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 51386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagaridebug_module_t mod_cipher = { 52386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 0, /* debugging is off by default */ 53386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari "cipher" /* printable module name */ 54386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari}; 55386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 56386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarierr_status_t 57386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagaricipher_output(cipher_t *c, uint8_t *buffer, int num_octets_to_output) { 58386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 59386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* zeroize the buffer */ 60386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari octet_string_set_to_zero(buffer, num_octets_to_output); 61386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 62386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* exor keystream into buffer */ 63386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari return cipher_encrypt(c, buffer, (unsigned int *) &num_octets_to_output); 64386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari} 65386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 66386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari/* some bookkeeping functions */ 67386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 68386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagariint 69386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagaricipher_get_key_length(const cipher_t *c) { 70386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari return c->key_len; 71386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari} 72386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 73386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari/* 74386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * cipher_type_self_test(ct) tests a cipher of type ct against test cases 75386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * provided in an array of values of key, salt, xtd_seq_num_t, 76386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * plaintext, and ciphertext that is known to be good 77386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari */ 78386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 79386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#define SELF_TEST_BUF_OCTETS 128 80386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#define NUM_RAND_TESTS 128 81386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#define MAX_KEY_LEN 64 82386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 83386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarierr_status_t 84386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagaricipher_type_self_test(const cipher_type_t *ct) { 85386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari const cipher_test_case_t *test_case = ct->test_data; 86386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari cipher_t *c; 87386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari err_status_t status; 88386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari uint8_t buffer[SELF_TEST_BUF_OCTETS]; 89386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari uint8_t buffer2[SELF_TEST_BUF_OCTETS]; 90386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari unsigned int len; 91386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari int i, j, case_num = 0; 92386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 93386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari debug_print(mod_cipher, "running self-test for cipher %s", 94386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari ct->description); 95386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 96386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* 97386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * check to make sure that we have at least one test case, and 98386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * return an error if we don't - we need to be paranoid here 99386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari */ 100386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari if (test_case == NULL) 101386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari return err_status_cant_check; 102386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 103386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* 104386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * loop over all test cases, perform known-answer tests of both the 105386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * encryption and decryption functions 106386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari */ 107386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari while (test_case != NULL) { 108386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 109386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* allocate cipher */ 110386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari status = cipher_type_alloc(ct, &c, test_case->key_length_octets); 111386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari if (status) 112386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari return status; 113386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 114386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* 115386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * test the encrypt function 116386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari */ 117386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari debug_print(mod_cipher, "testing encryption", NULL); 118386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 119386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* initialize cipher */ 120386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari status = cipher_init(c, test_case->key, direction_encrypt); 121386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari if (status) { 122386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari cipher_dealloc(c); 123386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari return status; 124386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari } 125386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 126386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* copy plaintext into test buffer */ 127386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari if (test_case->ciphertext_length_octets > SELF_TEST_BUF_OCTETS) { 128386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari cipher_dealloc(c); 129386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari return err_status_bad_param; 130386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari } 131386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari for (i=0; i < test_case->plaintext_length_octets; i++) 132386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari buffer[i] = test_case->plaintext[i]; 133386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 134386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari debug_print(mod_cipher, "plaintext: %s", 135386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari octet_string_hex_string(buffer, 136386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari test_case->plaintext_length_octets)); 137386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 138386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* set the initialization vector */ 139386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari status = cipher_set_iv(c, test_case->idx); 140386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari if (status) { 141386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari cipher_dealloc(c); 142386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari return status; 143386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari } 144386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 145386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* encrypt */ 146386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari len = test_case->plaintext_length_octets; 147386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari status = cipher_encrypt(c, buffer, &len); 148386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari if (status) { 149386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari cipher_dealloc(c); 150386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari return status; 151386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari } 152386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 153386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari debug_print(mod_cipher, "ciphertext: %s", 154386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari octet_string_hex_string(buffer, 155386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari test_case->ciphertext_length_octets)); 156386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 157386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* compare the resulting ciphertext with that in the test case */ 158386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari if (len != test_case->ciphertext_length_octets) 159386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari return err_status_algo_fail; 160386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari status = err_status_ok; 161386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari for (i=0; i < test_case->ciphertext_length_octets; i++) 162386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari if (buffer[i] != test_case->ciphertext[i]) { 163386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari status = err_status_algo_fail; 164386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari debug_print(mod_cipher, "test case %d failed", case_num); 165386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari debug_print(mod_cipher, "(failure at byte %d)", i); 166386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari break; 167386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari } 168386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari if (status) { 169386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 170386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari debug_print(mod_cipher, "c computed: %s", 171386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari octet_string_hex_string(buffer, 172386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 2*test_case->plaintext_length_octets)); 173386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari debug_print(mod_cipher, "c expected: %s", 174386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari octet_string_hex_string(test_case->ciphertext, 175386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 2*test_case->plaintext_length_octets)); 176386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 177386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari cipher_dealloc(c); 178386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari return err_status_algo_fail; 179386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari } 180386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 181386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* 182386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * test the decrypt function 183386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari */ 184386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari debug_print(mod_cipher, "testing decryption", NULL); 185386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 186386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* re-initialize cipher for decryption */ 187386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari status = cipher_init(c, test_case->key, direction_decrypt); 188386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari if (status) { 189386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari cipher_dealloc(c); 190386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari return status; 191386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari } 192386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 193386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* copy ciphertext into test buffer */ 194386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari if (test_case->ciphertext_length_octets > SELF_TEST_BUF_OCTETS) { 195386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari cipher_dealloc(c); 196386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari return err_status_bad_param; 197386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari } 198386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari for (i=0; i < test_case->ciphertext_length_octets; i++) 199386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari buffer[i] = test_case->ciphertext[i]; 200386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 201386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari debug_print(mod_cipher, "ciphertext: %s", 202386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari octet_string_hex_string(buffer, 203386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari test_case->plaintext_length_octets)); 204386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 205386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* set the initialization vector */ 206386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari status = cipher_set_iv(c, test_case->idx); 207386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari if (status) { 208386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari cipher_dealloc(c); 209386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari return status; 210386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari } 211386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 212386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* decrypt */ 213386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari len = test_case->ciphertext_length_octets; 214386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari status = cipher_decrypt(c, buffer, &len); 215386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari if (status) { 216386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari cipher_dealloc(c); 217386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari return status; 218386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari } 219386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 220386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari debug_print(mod_cipher, "plaintext: %s", 221386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari octet_string_hex_string(buffer, 222386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari test_case->plaintext_length_octets)); 223386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 224386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* compare the resulting plaintext with that in the test case */ 225386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari if (len != test_case->plaintext_length_octets) 226386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari return err_status_algo_fail; 227386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari status = err_status_ok; 228386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari for (i=0; i < test_case->plaintext_length_octets; i++) 229386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari if (buffer[i] != test_case->plaintext[i]) { 230386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari status = err_status_algo_fail; 231386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari debug_print(mod_cipher, "test case %d failed", case_num); 232386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari debug_print(mod_cipher, "(failure at byte %d)", i); 233386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari } 234386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari if (status) { 235386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 236386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari debug_print(mod_cipher, "p computed: %s", 237386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari octet_string_hex_string(buffer, 238386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 2*test_case->plaintext_length_octets)); 239386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari debug_print(mod_cipher, "p expected: %s", 240386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari octet_string_hex_string(test_case->plaintext, 241386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 2*test_case->plaintext_length_octets)); 242386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 243386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari cipher_dealloc(c); 244386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari return err_status_algo_fail; 245386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari } 246386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 247386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* deallocate the cipher */ 248386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari status = cipher_dealloc(c); 249386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari if (status) 250386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari return status; 251386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 252386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* 253386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * the cipher passed the test case, so move on to the next test 254386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * case in the list; if NULL, we'l proceed to the next test 255386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari */ 256386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari test_case = test_case->next_test_case; 257386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari ++case_num; 258386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari } 259386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 260386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* now run some random invertibility tests */ 261386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 262386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* allocate cipher, using paramaters from the first test case */ 263386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari test_case = ct->test_data; 264386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari status = cipher_type_alloc(ct, &c, test_case->key_length_octets); 265386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari if (status) 266386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari return status; 267386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 268386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari rand_source_init(); 269386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 270386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari for (j=0; j < NUM_RAND_TESTS; j++) { 271386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari unsigned length; 272386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari int plaintext_len; 273386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari uint8_t key[MAX_KEY_LEN]; 274386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari uint8_t iv[MAX_KEY_LEN]; 275386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 276386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* choose a length at random (leaving room for IV and padding) */ 277386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari length = rand() % (SELF_TEST_BUF_OCTETS - 64); 278386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari debug_print(mod_cipher, "random plaintext length %d\n", length); 279386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari status = rand_source_get_octet_string(buffer, length); 280386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari if (status) return status; 281386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 282386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari debug_print(mod_cipher, "plaintext: %s", 283386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari octet_string_hex_string(buffer, length)); 284386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 285386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* copy plaintext into second buffer */ 286386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari for (i=0; (unsigned int)i < length; i++) 287386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari buffer2[i] = buffer[i]; 288386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 289386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* choose a key at random */ 290386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari if (test_case->key_length_octets > MAX_KEY_LEN) 291386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari return err_status_cant_check; 292386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari status = rand_source_get_octet_string(key, test_case->key_length_octets); 293386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari if (status) return status; 294386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 295386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* chose a random initialization vector */ 296386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari status = rand_source_get_octet_string(iv, MAX_KEY_LEN); 297386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari if (status) return status; 298386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 299386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* initialize cipher */ 300386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari status = cipher_init(c, key, direction_encrypt); 301386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari if (status) { 302386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari cipher_dealloc(c); 303386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari return status; 304386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari } 305386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 306386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* set initialization vector */ 307386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari status = cipher_set_iv(c, test_case->idx); 308386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari if (status) { 309386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari cipher_dealloc(c); 310386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari return status; 311386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari } 312386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 313386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* encrypt buffer with cipher */ 314386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari plaintext_len = length; 315386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari status = cipher_encrypt(c, buffer, &length); 316386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari if (status) { 317386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari cipher_dealloc(c); 318386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari return status; 319386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari } 320386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari debug_print(mod_cipher, "ciphertext: %s", 321386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari octet_string_hex_string(buffer, length)); 322386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 323386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* 324386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * re-initialize cipher for decryption, re-set the iv, then 325386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * decrypt the ciphertext 326386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari */ 327386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari status = cipher_init(c, key, direction_decrypt); 328386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari if (status) { 329386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari cipher_dealloc(c); 330386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari return status; 331386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari } 332386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari status = cipher_set_iv(c, test_case->idx); 333386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari if (status) { 334386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari cipher_dealloc(c); 335386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari return status; 336386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari } 337386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari status = cipher_decrypt(c, buffer, &length); 338386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari if (status) { 339386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari cipher_dealloc(c); 340386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari return status; 341386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari } 342386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 343386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari debug_print(mod_cipher, "plaintext[2]: %s", 344386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari octet_string_hex_string(buffer, length)); 345386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 346386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* compare the resulting plaintext with the original one */ 347386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari if (length != plaintext_len) 348386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari return err_status_algo_fail; 349386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari status = err_status_ok; 350386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari for (i=0; i < plaintext_len; i++) 351386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari if (buffer[i] != buffer2[i]) { 352386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari status = err_status_algo_fail; 353386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari debug_print(mod_cipher, "random test case %d failed", case_num); 354386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari debug_print(mod_cipher, "(failure at byte %d)", i); 355386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari } 356386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari if (status) { 357386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari cipher_dealloc(c); 358386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari return err_status_algo_fail; 359386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari } 360386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 361386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari } 362386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 363386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari return err_status_ok; 364386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari} 365386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 366386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 367386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari/* 368386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * cipher_bits_per_second(c, l, t) computes (an estimate of) the 369386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * number of bits that a cipher implementation can encrypt in a second 370386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * 371386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * c is a cipher (which MUST be allocated and initialized already), l 372386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * is the length in octets of the test data to be encrypted, and t is 373386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * the number of trials 374386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * 375386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * if an error is encountered, the value 0 is returned 376386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari */ 377386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 378386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagariuint64_t 379386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagaricipher_bits_per_second(cipher_t *c, int octets_in_buffer, int num_trials) { 380386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari int i; 381386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari v128_t nonce; 382386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari clock_t timer; 383386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari unsigned char *enc_buf; 384386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari unsigned int len = octets_in_buffer; 385386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 386386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari enc_buf = (unsigned char*) crypto_alloc(octets_in_buffer); 387386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari if (enc_buf == NULL) 388386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari return 0; /* indicate bad parameters by returning null */ 389386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 390386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* time repeated trials */ 391386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari v128_set_to_zero(&nonce); 392386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari timer = clock(); 393386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari for(i=0; i < num_trials; i++, nonce.v32[3] = i) { 394386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari cipher_set_iv(c, &nonce); 395386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari cipher_encrypt(c, enc_buf, &len); 396386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari } 397386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari timer = clock() - timer; 398386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 399386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari crypto_free(enc_buf); 400386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 401386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari if (timer == 0) { 402386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* Too fast! */ 403386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari return 0; 404386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari } 405386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 406386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari return (uint64_t)CLOCKS_PER_SEC * num_trials * 8 * octets_in_buffer / timer; 407386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari} 408