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