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
51debug_module_t mod_cipher = {
52  0,                 /* debugging is off by default */
53  "cipher"           /* printable module name       */
54};
55
56err_status_t
57cipher_output(cipher_t *c, uint8_t *buffer, int num_octets_to_output) {
58
59  /* zeroize the buffer */
60  octet_string_set_to_zero(buffer, num_octets_to_output);
61
62  /* exor keystream into buffer */
63  return cipher_encrypt(c, buffer, (unsigned int *) &num_octets_to_output);
64}
65
66/* some bookkeeping functions */
67
68int
69cipher_get_key_length(const cipher_t *c) {
70  return c->key_len;
71}
72
73/*
74 * cipher_type_self_test(ct) tests a cipher of type ct against test cases
75 * provided in an array of values of key, salt, xtd_seq_num_t,
76 * plaintext, and ciphertext that is known to be good
77 */
78
79#define SELF_TEST_BUF_OCTETS 128
80#define NUM_RAND_TESTS       128
81#define MAX_KEY_LEN          64
82
83err_status_t
84cipher_type_self_test(const cipher_type_t *ct) {
85  const cipher_test_case_t *test_case = ct->test_data;
86  cipher_t *c;
87  err_status_t status;
88  uint8_t buffer[SELF_TEST_BUF_OCTETS];
89  uint8_t buffer2[SELF_TEST_BUF_OCTETS];
90  unsigned int len;
91  int i, j, case_num = 0;
92
93  debug_print(mod_cipher, "running self-test for cipher %s",
94	      ct->description);
95
96  /*
97   * check to make sure that we have at least one test case, and
98   * return an error if we don't - we need to be paranoid here
99   */
100  if (test_case == NULL)
101    return err_status_cant_check;
102
103  /*
104   * loop over all test cases, perform known-answer tests of both the
105   * encryption and decryption functions
106   */
107  while (test_case != NULL) {
108
109    /* allocate cipher */
110    status = cipher_type_alloc(ct, &c, test_case->key_length_octets);
111    if (status)
112      return status;
113
114    /*
115     * test the encrypt function
116     */
117    debug_print(mod_cipher, "testing encryption", NULL);
118
119    /* initialize cipher */
120    status = cipher_init(c, test_case->key, direction_encrypt);
121    if (status) {
122      cipher_dealloc(c);
123      return status;
124    }
125
126    /* copy plaintext into test buffer */
127    if (test_case->ciphertext_length_octets > SELF_TEST_BUF_OCTETS) {
128      cipher_dealloc(c);
129      return err_status_bad_param;
130    }
131    for (i=0; i < test_case->plaintext_length_octets; i++)
132      buffer[i] = test_case->plaintext[i];
133
134    debug_print(mod_cipher, "plaintext:    %s",
135	     octet_string_hex_string(buffer,
136				     test_case->plaintext_length_octets));
137
138    /* set the initialization vector */
139    status = cipher_set_iv(c, test_case->idx);
140    if (status) {
141      cipher_dealloc(c);
142      return status;
143    }
144
145    /* encrypt */
146    len = test_case->plaintext_length_octets;
147    status = cipher_encrypt(c, buffer, &len);
148    if (status) {
149      cipher_dealloc(c);
150      return status;
151    }
152
153    debug_print(mod_cipher, "ciphertext:   %s",
154	     octet_string_hex_string(buffer,
155				     test_case->ciphertext_length_octets));
156
157    /* compare the resulting ciphertext with that in the test case */
158    if (len != test_case->ciphertext_length_octets)
159      return err_status_algo_fail;
160    status = err_status_ok;
161    for (i=0; i < test_case->ciphertext_length_octets; i++)
162      if (buffer[i] != test_case->ciphertext[i]) {
163	status = err_status_algo_fail;
164	debug_print(mod_cipher, "test case %d failed", case_num);
165	debug_print(mod_cipher, "(failure at byte %d)", i);
166	break;
167      }
168    if (status) {
169
170      debug_print(mod_cipher, "c computed: %s",
171	     octet_string_hex_string(buffer,
172		  2*test_case->plaintext_length_octets));
173      debug_print(mod_cipher, "c expected: %s",
174		  octet_string_hex_string(test_case->ciphertext,
175			  2*test_case->plaintext_length_octets));
176
177      cipher_dealloc(c);
178      return err_status_algo_fail;
179    }
180
181    /*
182     * test the decrypt function
183     */
184    debug_print(mod_cipher, "testing decryption", NULL);
185
186    /* re-initialize cipher for decryption */
187    status = cipher_init(c, test_case->key, direction_decrypt);
188    if (status) {
189      cipher_dealloc(c);
190      return status;
191    }
192
193    /* copy ciphertext into test buffer */
194    if (test_case->ciphertext_length_octets > SELF_TEST_BUF_OCTETS) {
195      cipher_dealloc(c);
196      return err_status_bad_param;
197    }
198    for (i=0; i < test_case->ciphertext_length_octets; i++)
199      buffer[i] = test_case->ciphertext[i];
200
201    debug_print(mod_cipher, "ciphertext:    %s",
202		octet_string_hex_string(buffer,
203					test_case->plaintext_length_octets));
204
205    /* set the initialization vector */
206    status = cipher_set_iv(c, test_case->idx);
207    if (status) {
208      cipher_dealloc(c);
209      return status;
210    }
211
212    /* decrypt */
213    len = test_case->ciphertext_length_octets;
214    status = cipher_decrypt(c, buffer, &len);
215    if (status) {
216      cipher_dealloc(c);
217      return status;
218    }
219
220    debug_print(mod_cipher, "plaintext:   %s",
221	     octet_string_hex_string(buffer,
222				     test_case->plaintext_length_octets));
223
224    /* compare the resulting plaintext with that in the test case */
225    if (len != test_case->plaintext_length_octets)
226      return err_status_algo_fail;
227    status = err_status_ok;
228    for (i=0; i < test_case->plaintext_length_octets; i++)
229      if (buffer[i] != test_case->plaintext[i]) {
230	status = err_status_algo_fail;
231	debug_print(mod_cipher, "test case %d failed", case_num);
232	debug_print(mod_cipher, "(failure at byte %d)", i);
233      }
234    if (status) {
235
236      debug_print(mod_cipher, "p computed: %s",
237	     octet_string_hex_string(buffer,
238		  2*test_case->plaintext_length_octets));
239      debug_print(mod_cipher, "p expected: %s",
240		  octet_string_hex_string(test_case->plaintext,
241			  2*test_case->plaintext_length_octets));
242
243      cipher_dealloc(c);
244      return err_status_algo_fail;
245    }
246
247    /* deallocate the cipher */
248    status = cipher_dealloc(c);
249    if (status)
250      return status;
251
252    /*
253     * the cipher passed the test case, so move on to the next test
254     * case in the list; if NULL, we'l proceed to the next test
255     */
256    test_case = test_case->next_test_case;
257    ++case_num;
258  }
259
260  /* now run some random invertibility tests */
261
262  /* allocate cipher, using paramaters from the first test case */
263  test_case = ct->test_data;
264  status = cipher_type_alloc(ct, &c, test_case->key_length_octets);
265  if (status)
266      return status;
267
268  rand_source_init();
269
270  for (j=0; j < NUM_RAND_TESTS; j++) {
271    unsigned length;
272    int plaintext_len;
273    uint8_t key[MAX_KEY_LEN];
274    uint8_t  iv[MAX_KEY_LEN];
275
276    /* choose a length at random (leaving room for IV and padding) */
277    length = rand() % (SELF_TEST_BUF_OCTETS - 64);
278    debug_print(mod_cipher, "random plaintext length %d\n", length);
279    status = rand_source_get_octet_string(buffer, length);
280    if (status) return status;
281
282    debug_print(mod_cipher, "plaintext:    %s",
283		octet_string_hex_string(buffer, length));
284
285    /* copy plaintext into second buffer */
286    for (i=0; (unsigned int)i < length; i++)
287      buffer2[i] = buffer[i];
288
289    /* choose a key at random */
290    if (test_case->key_length_octets > MAX_KEY_LEN)
291      return err_status_cant_check;
292    status = rand_source_get_octet_string(key, test_case->key_length_octets);
293    if (status) return status;
294
295   /* chose a random initialization vector */
296    status = rand_source_get_octet_string(iv, MAX_KEY_LEN);
297    if (status) return status;
298
299    /* initialize cipher */
300    status = cipher_init(c, key, direction_encrypt);
301    if (status) {
302      cipher_dealloc(c);
303      return status;
304    }
305
306    /* set initialization vector */
307    status = cipher_set_iv(c, test_case->idx);
308    if (status) {
309      cipher_dealloc(c);
310      return status;
311    }
312
313    /* encrypt buffer with cipher */
314    plaintext_len = length;
315    status = cipher_encrypt(c, buffer, &length);
316    if (status) {
317      cipher_dealloc(c);
318      return status;
319    }
320    debug_print(mod_cipher, "ciphertext:   %s",
321		octet_string_hex_string(buffer, length));
322
323    /*
324     * re-initialize cipher for decryption, re-set the iv, then
325     * decrypt the ciphertext
326     */
327    status = cipher_init(c, key, direction_decrypt);
328    if (status) {
329      cipher_dealloc(c);
330      return status;
331    }
332    status = cipher_set_iv(c, test_case->idx);
333    if (status) {
334      cipher_dealloc(c);
335      return status;
336    }
337    status = cipher_decrypt(c, buffer, &length);
338    if (status) {
339      cipher_dealloc(c);
340      return status;
341    }
342
343    debug_print(mod_cipher, "plaintext[2]: %s",
344		octet_string_hex_string(buffer, length));
345
346    /* compare the resulting plaintext with the original one */
347    if (length != plaintext_len)
348      return err_status_algo_fail;
349    status = err_status_ok;
350    for (i=0; i < plaintext_len; i++)
351      if (buffer[i] != buffer2[i]) {
352	status = err_status_algo_fail;
353	debug_print(mod_cipher, "random test case %d failed", case_num);
354	debug_print(mod_cipher, "(failure at byte %d)", i);
355      }
356    if (status) {
357      cipher_dealloc(c);
358      return err_status_algo_fail;
359    }
360
361  }
362
363  return err_status_ok;
364}
365
366
367/*
368 * cipher_bits_per_second(c, l, t) computes (an estimate of) the
369 * number of bits that a cipher implementation can encrypt in a second
370 *
371 * c is a cipher (which MUST be allocated and initialized already), l
372 * is the length in octets of the test data to be encrypted, and t is
373 * the number of trials
374 *
375 * if an error is encountered, the value 0 is returned
376 */
377
378uint64_t
379cipher_bits_per_second(cipher_t *c, int octets_in_buffer, int num_trials) {
380  int i;
381  v128_t nonce;
382  clock_t timer;
383  unsigned char *enc_buf;
384  unsigned int len = octets_in_buffer;
385
386  enc_buf = (unsigned char*) crypto_alloc(octets_in_buffer);
387  if (enc_buf == NULL)
388    return 0;  /* indicate bad parameters by returning null */
389
390  /* time repeated trials */
391  v128_set_to_zero(&nonce);
392  timer = clock();
393  for(i=0; i < num_trials; i++, nonce.v32[3] = i) {
394    cipher_set_iv(c, &nonce);
395    cipher_encrypt(c, enc_buf, &len);
396  }
397  timer = clock() - timer;
398
399  crypto_free(enc_buf);
400
401  if (timer == 0) {
402    /* Too fast! */
403    return 0;
404  }
405
406  return (uint64_t)CLOCKS_PER_SEC * num_trials * 8 * octets_in_buffer / timer;
407}
408