1386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari/*
2386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * cipher_driver.c
3386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari *
4386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * A driver for the generic cipher type
5386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari *
6386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * David A. McGrew
7386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * Cisco Systems, Inc.
8386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari */
9386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
10386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari/*
11386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari *
12386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * Copyright (c) 2001-2006, Cisco Systems, Inc.
13386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * All rights reserved.
14386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari *
15386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * Redistribution and use in source and binary forms, with or without
16386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * modification, are permitted provided that the following conditions
17386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * are met:
18386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari *
19386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari *   Redistributions of source code must retain the above copyright
20386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari *   notice, this list of conditions and the following disclaimer.
21386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari *
22386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari *   Redistributions in binary form must reproduce the above
23386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari *   copyright notice, this list of conditions and the following
24386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari *   disclaimer in the documentation and/or other materials provided
25386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari *   with the distribution.
26386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari *
27386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari *   Neither the name of the Cisco Systems, Inc. nor the names of its
28386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari *   contributors may be used to endorse or promote products derived
29386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari *   from this software without specific prior written permission.
30386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari *
31386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
34386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
35386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
36386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
37386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
38386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
41386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
42386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * OF THE POSSIBILITY OF SUCH DAMAGE.
43386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari *
44386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari */
45386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
46386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#include <stdio.h>           /* for printf() */
47386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#include <stdlib.h>          /* for rand() */
48386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#include <string.h>          /* for memset() */
49386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#include <unistd.h>          /* for getopt() */
50386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#include "cipher.h"
51386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#include "aes_icm.h"
52386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#include "null_cipher.h"
53386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
54386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#define PRINT_DEBUG 0
55386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
56386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarivoid
57386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagaricipher_driver_test_throughput(cipher_t *c);
58386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
59386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarierr_status_t
60386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagaricipher_driver_self_test(cipher_type_t *ct);
61386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
62386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
63386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari/*
64386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * cipher_driver_test_buffering(ct) tests the cipher's output
65386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * buffering for correctness by checking the consistency of succesive
66386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * calls
67386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari */
68386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
69386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarierr_status_t
70386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagaricipher_driver_test_buffering(cipher_t *c);
71386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
72386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
73386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari/*
74386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * functions for testing cipher cache thrash
75386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari */
76386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarierr_status_t
77386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagaricipher_driver_test_array_throughput(cipher_type_t *ct,
78386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari				    int klen, int num_cipher);
79386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
80386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarivoid
81386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagaricipher_array_test_throughput(cipher_t *ca[], int num_cipher);
82386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
83386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagariuint64_t
84386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagaricipher_array_bits_per_second(cipher_t *cipher_array[], int num_cipher,
85386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari			     unsigned octets_in_buffer, int num_trials);
86386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
87386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarierr_status_t
88386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagaricipher_array_delete(cipher_t *cipher_array[], int num_cipher);
89386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
90386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarierr_status_t
91386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagaricipher_array_alloc_init(cipher_t ***cipher_array, int num_ciphers,
92386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari			cipher_type_t *ctype, int klen);
93386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
94386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarivoid
95386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagariusage(char *prog_name) {
96386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  printf("usage: %s [ -t | -v | -a ]\n", prog_name);
97386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  exit(255);
98386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari}
99386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
100386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarivoid
101386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagaricheck_status(err_status_t s) {
102386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (s) {
103386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    printf("error (code %d)\n", s);
104386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    exit(s);
105386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
106386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  return;
107386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari}
108386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
109386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari/*
110386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * null_cipher, aes_icm, and aes_cbc are the cipher meta-objects
111386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * defined in the files in crypto/cipher subdirectory.  these are
112386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * declared external so that we can use these cipher types here
113386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari */
114386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
115386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagariextern cipher_type_t null_cipher;
116386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagariextern cipher_type_t aes_icm;
117386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagariextern cipher_type_t aes_cbc;
118386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
119386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagariint
120386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarimain(int argc, char *argv[]) {
121386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  cipher_t *c = NULL;
122386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  err_status_t status;
123386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  unsigned char test_key[20] = {
124386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
125386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
126386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    0x10, 0x11, 0x12, 0x13
127386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  };
128386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  int q;
129386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  unsigned do_timing_test = 0;
130386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  unsigned do_validation = 0;
131386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  unsigned do_array_timing_test = 0;
132386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
133386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* process input arguments */
134386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  while (1) {
135386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    q = getopt(argc, argv, "tva");
136386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    if (q == -1)
137386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      break;
138386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    switch (q) {
139386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    case 't':
140386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      do_timing_test = 1;
141386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      break;
142386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    case 'v':
143386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      do_validation = 1;
144386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      break;
145386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    case 'a':
146386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      do_array_timing_test = 1;
147386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      break;
148386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    default:
149386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      usage(argv[0]);
150386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    }
151386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
152386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
153386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  printf("cipher test driver\n"
154386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari	 "David A. McGrew\n"
155386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari	 "Cisco Systems, Inc.\n");
156386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
157386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (!do_validation && !do_timing_test && !do_array_timing_test)
158386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    usage(argv[0]);
159386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
160386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   /* arry timing (cache thrash) test */
161386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (do_array_timing_test) {
162386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    int max_num_cipher = 1 << 16;   /* number of ciphers in cipher_array */
163386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    int num_cipher;
164386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
165386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    for (num_cipher=1; num_cipher < max_num_cipher; num_cipher *=8)
166386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      cipher_driver_test_array_throughput(&null_cipher, 0, num_cipher);
167386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
168386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    for (num_cipher=1; num_cipher < max_num_cipher; num_cipher *=8)
169386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      cipher_driver_test_array_throughput(&aes_icm, 30, num_cipher);
170386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
171386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    for (num_cipher=1; num_cipher < max_num_cipher; num_cipher *=8)
172386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      cipher_driver_test_array_throughput(&aes_cbc, 16, num_cipher);
173386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
174386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
175386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
176386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (do_validation) {
177386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    cipher_driver_self_test(&null_cipher);
178386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    cipher_driver_self_test(&aes_icm);
179386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    cipher_driver_self_test(&aes_cbc);
180386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
181386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
182386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* do timing and/or buffer_test on null_cipher */
183386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  status = cipher_type_alloc(&null_cipher, &c, 0);
184386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  check_status(status);
185386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
186386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  status = cipher_init(c, NULL, direction_encrypt);
187386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  check_status(status);
188386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
189386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (do_timing_test)
190386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    cipher_driver_test_throughput(c);
191386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (do_validation) {
192386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    status = cipher_driver_test_buffering(c);
193386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    check_status(status);
194386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
195386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  status = cipher_dealloc(c);
196386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  check_status(status);
197386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
198386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
199386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* run the throughput test on the aes_icm cipher */
200386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    status = cipher_type_alloc(&aes_icm, &c, 30);
201386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    if (status) {
202386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      fprintf(stderr, "error: can't allocate cipher\n");
203386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      exit(status);
204386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    }
205386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
206386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    status = cipher_init(c, test_key, direction_encrypt);
207386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    check_status(status);
208386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
209386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    if (do_timing_test)
210386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      cipher_driver_test_throughput(c);
211386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
212386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    if (do_validation) {
213386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      status = cipher_driver_test_buffering(c);
214386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      check_status(status);
215386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    }
216386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
217386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    status = cipher_dealloc(c);
218386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    check_status(status);
219386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
220386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  return 0;
221386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari}
222386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
223386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarivoid
224386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagaricipher_driver_test_throughput(cipher_t *c) {
225386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  int i;
226386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  int min_enc_len = 32;
227386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  int max_enc_len = 2048;   /* should be a power of two */
228386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  int num_trials = 100000;
229386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
230386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  printf("timing %s throughput:\n", c->type->description);
231386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  fflush(stdout);
232386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  for (i=min_enc_len; i <= max_enc_len; i = i * 2)
233386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    printf("msg len: %d\tgigabits per second: %f\n",
234386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari	   i, cipher_bits_per_second(c, i, num_trials) / 1e9);
235386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
236386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari}
237386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
238386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarierr_status_t
239386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagaricipher_driver_self_test(cipher_type_t *ct) {
240386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  err_status_t status;
241386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
242386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  printf("running cipher self-test for %s...", ct->description);
243386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  status = cipher_type_self_test(ct);
244386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (status) {
245386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    printf("failed with error code %d\n", status);
246386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    exit(status);
247386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
248386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  printf("passed\n");
249386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
250386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  return err_status_ok;
251386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari}
252386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
253386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari/*
254386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * cipher_driver_test_buffering(ct) tests the cipher's output
255386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * buffering for correctness by checking the consistency of succesive
256386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * calls
257386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari */
258386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
259386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarierr_status_t
260386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagaricipher_driver_test_buffering(cipher_t *c) {
261386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  int i, j, num_trials = 1000;
262386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  unsigned len, buflen = 1024;
263386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  uint8_t buffer0[buflen], buffer1[buflen], *current, *end;
264386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  uint8_t idx[16] = {
265386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
266386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x34
267386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  };
268386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  err_status_t status;
269386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
270386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  printf("testing output buffering for cipher %s...",
271386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari	 c->type->description);
272386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
273386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  for (i=0; i < num_trials; i++) {
274386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
275386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   /* set buffers to zero */
276386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    for (j=0; j < buflen; j++)
277386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      buffer0[j] = buffer1[j] = 0;
278386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
279386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    /* initialize cipher  */
280386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    status = cipher_set_iv(c, idx);
281386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    if (status)
282386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      return status;
283386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
284386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    /* generate 'reference' value by encrypting all at once */
285386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    status = cipher_encrypt(c, buffer0, &buflen);
286386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    if (status)
287386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      return status;
288386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
289386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    /* re-initialize cipher */
290386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    status = cipher_set_iv(c, idx);
291386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    if (status)
292386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      return status;
293386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
294386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    /* now loop over short lengths until buffer1 is encrypted */
295386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    current = buffer1;
296386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    end = buffer1 + buflen;
297386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    while (current < end) {
298386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
299386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      /* choose a short length */
300386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      len = rand() & 0x01f;
301386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
302386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      /* make sure that len doesn't cause us to overreach the buffer */
303386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      if (current + len > end)
304386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari	len = end - current;
305386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
306386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      status = cipher_encrypt(c, current, &len);
307386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      if (status)
308386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari	return status;
309386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
310386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      /* advance pointer into buffer1 to reflect encryption */
311386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      current += len;
312386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
313386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      /* if buffer1 is all encrypted, break out of loop */
314386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      if (current == end)
315386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari	break;
316386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    }
317386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
318386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    /* compare buffers */
319386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    for (j=0; j < buflen; j++)
320386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      if (buffer0[j] != buffer1[j]) {
321386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#if PRINT_DEBUG
322386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari	printf("test case %d failed at byte %d\n", i, j);
323386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari	printf("computed: %s\n", octet_string_hex_string(buffer1, buflen));
324386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari	printf("expected: %s\n", octet_string_hex_string(buffer0, buflen));
325386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#endif
326386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari	return err_status_algo_fail;
327386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      }
328386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
329386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
330386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  printf("passed\n");
331386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
332386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  return err_status_ok;
333386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari}
334386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
335386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
336386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari/*
337386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * The function cipher_test_throughput_array() tests the effect of CPU
338386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * cache thrash on cipher throughput.
339386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari *
340386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * cipher_array_alloc_init(ctype, array, num_ciphers) creates an array
341386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * of cipher_t of type ctype
342386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari */
343386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
344386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarierr_status_t
345386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagaricipher_array_alloc_init(cipher_t ***ca, int num_ciphers,
346386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari			cipher_type_t *ctype, int klen) {
347386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  int i, j;
348386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  err_status_t status;
349386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  uint8_t *key;
350386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  cipher_t **cipher_array;
351386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
352386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* allocate array of pointers to ciphers */
353386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  cipher_array = (cipher_t **) malloc(sizeof(cipher_t *) * num_ciphers);
354386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (cipher_array == NULL)
355386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    return err_status_alloc_fail;
356386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
357386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* set ca to location of cipher_array */
358386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  *ca = cipher_array;
359386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
360386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* allocate key */
361386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  key = crypto_alloc(klen);
362386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (key == NULL) {
363386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    free(cipher_array);
364386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    return err_status_alloc_fail;
365386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
366386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
367386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* allocate and initialize an array of ciphers */
368386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  for (i=0; i < num_ciphers; i++) {
369386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
370386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    /* allocate cipher */
371386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    status = cipher_type_alloc(ctype, cipher_array, klen);
372386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    if (status)
373386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      return status;
374386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
375386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    /* generate random key and initialize cipher */
376386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    for (j=0; j < klen; j++)
377386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      key[j] = (uint8_t) rand();
378386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    status = cipher_init(*cipher_array, key, direction_encrypt);
379386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    if (status)
380386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      return status;
381386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
382386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari/*     printf("%dth cipher is at %p\n", i, *cipher_array); */
383386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari/*     printf("%dth cipher description: %s\n", i,  */
384386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari/* 	   (*cipher_array)->type->description); */
385386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
386386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    /* advance cipher array pointer */
387386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    cipher_array++;
388386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
389386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
390386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  return err_status_ok;
391386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari}
392386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
393386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarierr_status_t
394386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagaricipher_array_delete(cipher_t *cipher_array[], int num_cipher) {
395386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  int i;
396386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
397386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  for (i=0; i < num_cipher; i++) {
398386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    cipher_dealloc(cipher_array[i]);
399386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
400386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
401386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  free(cipher_array);
402386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
403386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  return err_status_ok;
404386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari}
405386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
406386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
407386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari/*
408386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * cipher_array_bits_per_second(c, l, t) computes (an estimate of) the
409386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * number of bits that a cipher implementation can encrypt in a second
410386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * when distinct keys are used to encrypt distinct messages
411386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari *
412386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * c is a cipher (which MUST be allocated an initialized already), l
413386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * is the length in octets of the test data to be encrypted, and t is
414386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * the number of trials
415386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari *
416386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * if an error is encountered, the value 0 is returned
417386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari */
418386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
419386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagariuint64_t
420386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagaricipher_array_bits_per_second(cipher_t *cipher_array[], int num_cipher,
421386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari			      unsigned octets_in_buffer, int num_trials) {
422386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  int i;
423386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  v128_t nonce;
424386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  clock_t timer;
425386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  unsigned char *enc_buf;
426386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  int cipher_index = 0;
427386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
428386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
429386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  enc_buf = crypto_alloc(octets_in_buffer);
430386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (enc_buf == NULL)
431386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    return 0;  /* indicate bad parameters by returning null */
432386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
433386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* time repeated trials */
434386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  v128_set_to_zero(&nonce);
435386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  timer = clock();
436386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  for(i=0; i < num_trials; i++, nonce.v32[3] = i) {
437386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
438386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    /* choose a cipher at random from the array*/
439386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    cipher_index = (*((uint32_t *)enc_buf)) % num_cipher;
440386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
441386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    /* encrypt buffer with cipher */
442386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    cipher_set_iv(cipher_array[cipher_index], &nonce);
443386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    cipher_encrypt(cipher_array[cipher_index], enc_buf, &octets_in_buffer);
444386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
445386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  timer = clock() - timer;
446386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
447386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  free(enc_buf);
448386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
449386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (timer == 0) {
450386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    /* Too fast! */
451386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    return 0;
452386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
453386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
454386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  return CLOCKS_PER_SEC * num_trials * 8 * octets_in_buffer / timer;
455386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari}
456386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
457386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarivoid
458386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagaricipher_array_test_throughput(cipher_t *ca[], int num_cipher) {
459386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  int i;
460386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  int min_enc_len = 16;
461386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  int max_enc_len = 2048;   /* should be a power of two */
462386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  int num_trials = 10000;
463386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
464386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  printf("timing %s throughput with array size %d:\n",
465386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari	 (ca[0])->type->description, num_cipher);
466386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  fflush(stdout);
467386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  for (i=min_enc_len; i <= max_enc_len; i = i * 4)
468386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    printf("msg len: %d\tgigabits per second: %f\n", i,
469386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari	   cipher_array_bits_per_second(ca, num_cipher, i, num_trials) / 1e9);
470386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
471386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari}
472386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
473386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarierr_status_t
474386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagaricipher_driver_test_array_throughput(cipher_type_t *ct,
475386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari				    int klen, int num_cipher) {
476386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  cipher_t **ca = NULL;
477386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  err_status_t status;
478386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
479386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  status = cipher_array_alloc_init(&ca, num_cipher, ct, klen);
480386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (status) {
481386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    printf("error: cipher_array_alloc_init() failed with error code %d\n",
482386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari	   status);
483386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    return status;
484386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
485386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
486386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  cipher_array_test_throughput(ca, num_cipher);
487386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
488386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  cipher_array_delete(ca, num_cipher);
489386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
490386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  return err_status_ok;
491386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari}
492