Cullen Jennings | 235513a | 2005-09-21 22:51:36 +0000 | [diff] [blame] | 1 | /* |
| 2 | * cipher_driver.c |
| 3 | * |
| 4 | * A driver for the generic cipher type |
| 5 | * |
| 6 | * David A. McGrew |
| 7 | * Cisco Systems, Inc. |
| 8 | */ |
| 9 | |
| 10 | /* |
| 11 | * |
jfigus | 7882dd9 | 2013-08-02 16:08:23 -0400 | [diff] [blame] | 12 | * Copyright (c) 2001-2006,2013 Cisco Systems, Inc. |
Cullen Jennings | 235513a | 2005-09-21 22:51:36 +0000 | [diff] [blame] | 13 | * All rights reserved. |
| 14 | * |
| 15 | * Redistribution and use in source and binary forms, with or without |
| 16 | * modification, are permitted provided that the following conditions |
| 17 | * are met: |
| 18 | * |
| 19 | * Redistributions of source code must retain the above copyright |
| 20 | * notice, this list of conditions and the following disclaimer. |
| 21 | * |
| 22 | * Redistributions in binary form must reproduce the above |
| 23 | * copyright notice, this list of conditions and the following |
| 24 | * disclaimer in the documentation and/or other materials provided |
| 25 | * with the distribution. |
| 26 | * |
| 27 | * Neither the name of the Cisco Systems, Inc. nor the names of its |
| 28 | * contributors may be used to endorse or promote products derived |
| 29 | * from this software without specific prior written permission. |
| 30 | * |
| 31 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 32 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 33 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
| 34 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
| 35 | * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, |
| 36 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| 37 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
| 38 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| 39 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
| 40 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| 41 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED |
| 42 | * OF THE POSSIBILITY OF SUCH DAMAGE. |
| 43 | * |
| 44 | */ |
| 45 | |
Teerapap Changwichukarn | 6cffe24 | 2014-09-24 11:24:07 +0800 | [diff] [blame] | 46 | #ifdef HAVE_CONFIG_H |
| 47 | #include <config.h> |
| 48 | #endif |
| 49 | |
Cullen Jennings | 235513a | 2005-09-21 22:51:36 +0000 | [diff] [blame] | 50 | #include <stdio.h> /* for printf() */ |
Marcus Sundberg | d774edb | 2005-10-02 20:36:02 +0000 | [diff] [blame] | 51 | #include <stdlib.h> /* for rand() */ |
Cullen Jennings | 235513a | 2005-09-21 22:51:36 +0000 | [diff] [blame] | 52 | #include <string.h> /* for memset() */ |
| 53 | #include <unistd.h> /* for getopt() */ |
| 54 | #include "cipher.h" |
jfigus | a14b5a0 | 2013-03-29 12:24:12 -0400 | [diff] [blame] | 55 | #ifdef OPENSSL |
| 56 | #include "aes_icm_ossl.h" |
jfigus | 7882dd9 | 2013-08-02 16:08:23 -0400 | [diff] [blame] | 57 | #include "aes_gcm_ossl.h" |
jfigus | a14b5a0 | 2013-03-29 12:24:12 -0400 | [diff] [blame] | 58 | #else |
Cullen Jennings | 235513a | 2005-09-21 22:51:36 +0000 | [diff] [blame] | 59 | #include "aes_icm.h" |
jfigus | a14b5a0 | 2013-03-29 12:24:12 -0400 | [diff] [blame] | 60 | #endif |
Cullen Jennings | 235513a | 2005-09-21 22:51:36 +0000 | [diff] [blame] | 61 | #include "null_cipher.h" |
| 62 | |
| 63 | #define PRINT_DEBUG 0 |
| 64 | |
| 65 | void |
| 66 | cipher_driver_test_throughput(cipher_t *c); |
| 67 | |
jfigus | 857009c | 2014-11-05 11:17:43 -0500 | [diff] [blame] | 68 | srtp_err_status_t |
Cullen Jennings | 235513a | 2005-09-21 22:51:36 +0000 | [diff] [blame] | 69 | cipher_driver_self_test(cipher_type_t *ct); |
| 70 | |
| 71 | |
| 72 | /* |
| 73 | * cipher_driver_test_buffering(ct) tests the cipher's output |
| 74 | * buffering for correctness by checking the consistency of succesive |
| 75 | * calls |
| 76 | */ |
| 77 | |
jfigus | 857009c | 2014-11-05 11:17:43 -0500 | [diff] [blame] | 78 | srtp_err_status_t |
Cullen Jennings | 235513a | 2005-09-21 22:51:36 +0000 | [diff] [blame] | 79 | cipher_driver_test_buffering(cipher_t *c); |
| 80 | |
| 81 | |
| 82 | /* |
| 83 | * functions for testing cipher cache thrash |
| 84 | */ |
jfigus | 857009c | 2014-11-05 11:17:43 -0500 | [diff] [blame] | 85 | srtp_err_status_t |
Cullen Jennings | 235513a | 2005-09-21 22:51:36 +0000 | [diff] [blame] | 86 | cipher_driver_test_array_throughput(cipher_type_t *ct, |
| 87 | int klen, int num_cipher); |
| 88 | |
| 89 | void |
| 90 | cipher_array_test_throughput(cipher_t *ca[], int num_cipher); |
| 91 | |
Marcus Sundberg | e544f61 | 2005-10-03 16:29:05 +0000 | [diff] [blame] | 92 | uint64_t |
Cullen Jennings | 235513a | 2005-09-21 22:51:36 +0000 | [diff] [blame] | 93 | cipher_array_bits_per_second(cipher_t *cipher_array[], int num_cipher, |
David McGrew | fec49dd | 2005-09-23 19:34:11 +0000 | [diff] [blame] | 94 | unsigned octets_in_buffer, int num_trials); |
Cullen Jennings | 235513a | 2005-09-21 22:51:36 +0000 | [diff] [blame] | 95 | |
jfigus | 857009c | 2014-11-05 11:17:43 -0500 | [diff] [blame] | 96 | srtp_err_status_t |
Cullen Jennings | 235513a | 2005-09-21 22:51:36 +0000 | [diff] [blame] | 97 | cipher_array_delete(cipher_t *cipher_array[], int num_cipher); |
| 98 | |
jfigus | 857009c | 2014-11-05 11:17:43 -0500 | [diff] [blame] | 99 | srtp_err_status_t |
Cullen Jennings | 235513a | 2005-09-21 22:51:36 +0000 | [diff] [blame] | 100 | cipher_array_alloc_init(cipher_t ***cipher_array, int num_ciphers, |
| 101 | cipher_type_t *ctype, int klen); |
| 102 | |
| 103 | void |
| 104 | usage(char *prog_name) { |
| 105 | printf("usage: %s [ -t | -v | -a ]\n", prog_name); |
| 106 | exit(255); |
| 107 | } |
| 108 | |
| 109 | void |
jfigus | 857009c | 2014-11-05 11:17:43 -0500 | [diff] [blame] | 110 | check_status(srtp_err_status_t s) { |
Cullen Jennings | 235513a | 2005-09-21 22:51:36 +0000 | [diff] [blame] | 111 | if (s) { |
| 112 | printf("error (code %d)\n", s); |
| 113 | exit(s); |
| 114 | } |
| 115 | return; |
| 116 | } |
| 117 | |
| 118 | /* |
| 119 | * null_cipher, aes_icm, and aes_cbc are the cipher meta-objects |
| 120 | * defined in the files in crypto/cipher subdirectory. these are |
| 121 | * declared external so that we can use these cipher types here |
| 122 | */ |
| 123 | |
| 124 | extern cipher_type_t null_cipher; |
jfigus | 5a2b2d0 | 2014-11-19 14:34:20 -0500 | [diff] [blame^] | 125 | extern cipher_type_t srtp_aes_icm; |
jfigus | 0d3a268 | 2013-04-02 15:42:37 -0400 | [diff] [blame] | 126 | #ifndef OPENSSL |
jfigus | 5a2b2d0 | 2014-11-19 14:34:20 -0500 | [diff] [blame^] | 127 | extern cipher_type_t srtp_aes_cbc; |
jfigus | 7882dd9 | 2013-08-02 16:08:23 -0400 | [diff] [blame] | 128 | #else |
jfigus | 5a2b2d0 | 2014-11-19 14:34:20 -0500 | [diff] [blame^] | 129 | extern cipher_type_t srtp_aes_icm_192; |
| 130 | extern cipher_type_t srtp_aes_icm_256; |
| 131 | extern cipher_type_t srtp_aes_gcm_128_openssl; |
| 132 | extern cipher_type_t srtp_aes_gcm_256_openssl; |
jfigus | 0d3a268 | 2013-04-02 15:42:37 -0400 | [diff] [blame] | 133 | #endif |
Cullen Jennings | 235513a | 2005-09-21 22:51:36 +0000 | [diff] [blame] | 134 | |
| 135 | int |
| 136 | main(int argc, char *argv[]) { |
| 137 | cipher_t *c = NULL; |
jfigus | 857009c | 2014-11-05 11:17:43 -0500 | [diff] [blame] | 138 | srtp_err_status_t status; |
Jonathan Lennox | 5df951a | 2010-05-20 20:55:54 +0000 | [diff] [blame] | 139 | unsigned char test_key[48] = { |
Cullen Jennings | 235513a | 2005-09-21 22:51:36 +0000 | [diff] [blame] | 140 | 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, |
| 141 | 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, |
Jonathan Lennox | 5df951a | 2010-05-20 20:55:54 +0000 | [diff] [blame] | 142 | 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, |
| 143 | 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, |
| 144 | 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, |
| 145 | 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, |
Cullen Jennings | 235513a | 2005-09-21 22:51:36 +0000 | [diff] [blame] | 146 | }; |
| 147 | int q; |
| 148 | unsigned do_timing_test = 0; |
| 149 | unsigned do_validation = 0; |
| 150 | unsigned do_array_timing_test = 0; |
| 151 | |
| 152 | /* process input arguments */ |
| 153 | while (1) { |
| 154 | q = getopt(argc, argv, "tva"); |
| 155 | if (q == -1) |
| 156 | break; |
| 157 | switch (q) { |
| 158 | case 't': |
| 159 | do_timing_test = 1; |
| 160 | break; |
| 161 | case 'v': |
| 162 | do_validation = 1; |
| 163 | break; |
| 164 | case 'a': |
| 165 | do_array_timing_test = 1; |
| 166 | break; |
| 167 | default: |
| 168 | usage(argv[0]); |
| 169 | } |
| 170 | } |
| 171 | |
| 172 | printf("cipher test driver\n" |
| 173 | "David A. McGrew\n" |
| 174 | "Cisco Systems, Inc.\n"); |
| 175 | |
| 176 | if (!do_validation && !do_timing_test && !do_array_timing_test) |
| 177 | usage(argv[0]); |
| 178 | |
| 179 | /* arry timing (cache thrash) test */ |
| 180 | if (do_array_timing_test) { |
| 181 | int max_num_cipher = 1 << 16; /* number of ciphers in cipher_array */ |
| 182 | int num_cipher; |
| 183 | |
| 184 | for (num_cipher=1; num_cipher < max_num_cipher; num_cipher *=8) |
| 185 | cipher_driver_test_array_throughput(&null_cipher, 0, num_cipher); |
| 186 | |
| 187 | for (num_cipher=1; num_cipher < max_num_cipher; num_cipher *=8) |
jfigus | 5a2b2d0 | 2014-11-19 14:34:20 -0500 | [diff] [blame^] | 188 | cipher_driver_test_array_throughput(&srtp_aes_icm, 30, num_cipher); |
Cullen Jennings | 235513a | 2005-09-21 22:51:36 +0000 | [diff] [blame] | 189 | |
jfigus | b5a2177 | 2013-11-08 10:05:59 -0500 | [diff] [blame] | 190 | #ifndef OPENSSL |
Cullen Jennings | 235513a | 2005-09-21 22:51:36 +0000 | [diff] [blame] | 191 | for (num_cipher=1; num_cipher < max_num_cipher; num_cipher *=8) |
jfigus | 5a2b2d0 | 2014-11-19 14:34:20 -0500 | [diff] [blame^] | 192 | cipher_driver_test_array_throughput(&srtp_aes_icm, 46, num_cipher); |
Jonathan Lennox | 5df951a | 2010-05-20 20:55:54 +0000 | [diff] [blame] | 193 | |
| 194 | for (num_cipher=1; num_cipher < max_num_cipher; num_cipher *=8) |
jfigus | 5a2b2d0 | 2014-11-19 14:34:20 -0500 | [diff] [blame^] | 195 | cipher_driver_test_array_throughput(&srtp_aes_cbc, 16, num_cipher); |
Cullen Jennings | 235513a | 2005-09-21 22:51:36 +0000 | [diff] [blame] | 196 | |
Jonathan Lennox | 5df951a | 2010-05-20 20:55:54 +0000 | [diff] [blame] | 197 | for (num_cipher=1; num_cipher < max_num_cipher; num_cipher *=8) |
jfigus | 5a2b2d0 | 2014-11-19 14:34:20 -0500 | [diff] [blame^] | 198 | cipher_driver_test_array_throughput(&srtp_aes_cbc, 32, num_cipher); |
jfigus | 7882dd9 | 2013-08-02 16:08:23 -0400 | [diff] [blame] | 199 | #else |
jfigus | b5a2177 | 2013-11-08 10:05:59 -0500 | [diff] [blame] | 200 | for (num_cipher=1; num_cipher < max_num_cipher; num_cipher *=8) |
jfigus | 5a2b2d0 | 2014-11-19 14:34:20 -0500 | [diff] [blame^] | 201 | cipher_driver_test_array_throughput(&srtp_aes_icm_192, 38, num_cipher); |
jfigus | b5a2177 | 2013-11-08 10:05:59 -0500 | [diff] [blame] | 202 | |
| 203 | for (num_cipher=1; num_cipher < max_num_cipher; num_cipher *=8) |
jfigus | 5a2b2d0 | 2014-11-19 14:34:20 -0500 | [diff] [blame^] | 204 | cipher_driver_test_array_throughput(&srtp_aes_icm_256, 46, num_cipher); |
jfigus | b5a2177 | 2013-11-08 10:05:59 -0500 | [diff] [blame] | 205 | |
jfigus | 7882dd9 | 2013-08-02 16:08:23 -0400 | [diff] [blame] | 206 | for (num_cipher=1; num_cipher < max_num_cipher; num_cipher *=8) { |
jfigus | 5a2b2d0 | 2014-11-19 14:34:20 -0500 | [diff] [blame^] | 207 | cipher_driver_test_array_throughput(&srtp_aes_gcm_128_openssl, SRTP_AES_128_GCM_KEYSIZE_WSALT, num_cipher); |
jfigus | 7882dd9 | 2013-08-02 16:08:23 -0400 | [diff] [blame] | 208 | } |
| 209 | |
| 210 | for (num_cipher=1; num_cipher < max_num_cipher; num_cipher *=8) { |
jfigus | 5a2b2d0 | 2014-11-19 14:34:20 -0500 | [diff] [blame^] | 211 | cipher_driver_test_array_throughput(&srtp_aes_gcm_256_openssl, SRTP_AES_256_GCM_KEYSIZE_WSALT, num_cipher); |
jfigus | 7882dd9 | 2013-08-02 16:08:23 -0400 | [diff] [blame] | 212 | } |
jfigus | 0d3a268 | 2013-04-02 15:42:37 -0400 | [diff] [blame] | 213 | #endif |
Cullen Jennings | 235513a | 2005-09-21 22:51:36 +0000 | [diff] [blame] | 214 | } |
| 215 | |
| 216 | if (do_validation) { |
| 217 | cipher_driver_self_test(&null_cipher); |
jfigus | 5a2b2d0 | 2014-11-19 14:34:20 -0500 | [diff] [blame^] | 218 | cipher_driver_self_test(&srtp_aes_icm); |
jfigus | 0d3a268 | 2013-04-02 15:42:37 -0400 | [diff] [blame] | 219 | #ifndef OPENSSL |
jfigus | 5a2b2d0 | 2014-11-19 14:34:20 -0500 | [diff] [blame^] | 220 | cipher_driver_self_test(&srtp_aes_cbc); |
jfigus | 7882dd9 | 2013-08-02 16:08:23 -0400 | [diff] [blame] | 221 | #else |
jfigus | 5a2b2d0 | 2014-11-19 14:34:20 -0500 | [diff] [blame^] | 222 | cipher_driver_self_test(&srtp_aes_icm_192); |
| 223 | cipher_driver_self_test(&srtp_aes_icm_256); |
| 224 | cipher_driver_self_test(&srtp_aes_gcm_128_openssl); |
| 225 | cipher_driver_self_test(&srtp_aes_gcm_256_openssl); |
jfigus | 0d3a268 | 2013-04-02 15:42:37 -0400 | [diff] [blame] | 226 | #endif |
Cullen Jennings | 235513a | 2005-09-21 22:51:36 +0000 | [diff] [blame] | 227 | } |
| 228 | |
| 229 | /* do timing and/or buffer_test on null_cipher */ |
jfigus | c13c100 | 2014-05-08 13:34:53 -0400 | [diff] [blame] | 230 | status = cipher_type_alloc(&null_cipher, &c, 0, 0); |
Cullen Jennings | 235513a | 2005-09-21 22:51:36 +0000 | [diff] [blame] | 231 | check_status(status); |
| 232 | |
jfigus | 7882dd9 | 2013-08-02 16:08:23 -0400 | [diff] [blame] | 233 | status = cipher_init(c, NULL); |
Cullen Jennings | 235513a | 2005-09-21 22:51:36 +0000 | [diff] [blame] | 234 | check_status(status); |
| 235 | |
| 236 | if (do_timing_test) |
| 237 | cipher_driver_test_throughput(c); |
| 238 | if (do_validation) { |
| 239 | status = cipher_driver_test_buffering(c); |
| 240 | check_status(status); |
| 241 | } |
| 242 | status = cipher_dealloc(c); |
| 243 | check_status(status); |
| 244 | |
| 245 | |
Jonathan Lennox | 5df951a | 2010-05-20 20:55:54 +0000 | [diff] [blame] | 246 | /* run the throughput test on the aes_icm cipher (128-bit key) */ |
jfigus | 5a2b2d0 | 2014-11-19 14:34:20 -0500 | [diff] [blame^] | 247 | status = cipher_type_alloc(&srtp_aes_icm, &c, 30, 0); |
Cullen Jennings | 235513a | 2005-09-21 22:51:36 +0000 | [diff] [blame] | 248 | if (status) { |
| 249 | fprintf(stderr, "error: can't allocate cipher\n"); |
| 250 | exit(status); |
| 251 | } |
| 252 | |
jfigus | 7882dd9 | 2013-08-02 16:08:23 -0400 | [diff] [blame] | 253 | status = cipher_init(c, test_key); |
Cullen Jennings | 235513a | 2005-09-21 22:51:36 +0000 | [diff] [blame] | 254 | check_status(status); |
| 255 | |
| 256 | if (do_timing_test) |
| 257 | cipher_driver_test_throughput(c); |
| 258 | |
| 259 | if (do_validation) { |
| 260 | status = cipher_driver_test_buffering(c); |
| 261 | check_status(status); |
| 262 | } |
| 263 | |
| 264 | status = cipher_dealloc(c); |
| 265 | check_status(status); |
Jonathan Lennox | 5df951a | 2010-05-20 20:55:54 +0000 | [diff] [blame] | 266 | |
| 267 | /* repeat the tests with 256-bit keys */ |
jfigus | b5a2177 | 2013-11-08 10:05:59 -0500 | [diff] [blame] | 268 | #ifndef OPENSSL |
jfigus | 5a2b2d0 | 2014-11-19 14:34:20 -0500 | [diff] [blame^] | 269 | status = cipher_type_alloc(&srtp_aes_icm, &c, 46, 0); |
jfigus | b5a2177 | 2013-11-08 10:05:59 -0500 | [diff] [blame] | 270 | #else |
jfigus | 5a2b2d0 | 2014-11-19 14:34:20 -0500 | [diff] [blame^] | 271 | status = cipher_type_alloc(&srtp_aes_icm_256, &c, 46, 0); |
jfigus | b5a2177 | 2013-11-08 10:05:59 -0500 | [diff] [blame] | 272 | #endif |
Jonathan Lennox | 5df951a | 2010-05-20 20:55:54 +0000 | [diff] [blame] | 273 | if (status) { |
| 274 | fprintf(stderr, "error: can't allocate cipher\n"); |
| 275 | exit(status); |
| 276 | } |
| 277 | |
jfigus | 7882dd9 | 2013-08-02 16:08:23 -0400 | [diff] [blame] | 278 | status = cipher_init(c, test_key); |
Jonathan Lennox | 5df951a | 2010-05-20 20:55:54 +0000 | [diff] [blame] | 279 | check_status(status); |
| 280 | |
| 281 | if (do_timing_test) |
| 282 | cipher_driver_test_throughput(c); |
| 283 | |
| 284 | if (do_validation) { |
| 285 | status = cipher_driver_test_buffering(c); |
| 286 | check_status(status); |
| 287 | } |
| 288 | |
| 289 | status = cipher_dealloc(c); |
| 290 | check_status(status); |
jfigus | 7882dd9 | 2013-08-02 16:08:23 -0400 | [diff] [blame] | 291 | |
| 292 | #ifdef OPENSSL |
| 293 | /* run the throughput test on the aes_gcm_128_openssl cipher */ |
jfigus | 5a2b2d0 | 2014-11-19 14:34:20 -0500 | [diff] [blame^] | 294 | status = cipher_type_alloc(&srtp_aes_gcm_128_openssl, &c, SRTP_AES_128_GCM_KEYSIZE_WSALT, 8); |
jfigus | 7882dd9 | 2013-08-02 16:08:23 -0400 | [diff] [blame] | 295 | if (status) { |
| 296 | fprintf(stderr, "error: can't allocate GCM 128 cipher\n"); |
| 297 | exit(status); |
| 298 | } |
| 299 | status = cipher_init(c, test_key); |
| 300 | check_status(status); |
| 301 | if (do_timing_test) { |
| 302 | cipher_driver_test_throughput(c); |
| 303 | } |
| 304 | |
| 305 | if (do_validation) { |
| 306 | status = cipher_driver_test_buffering(c); |
| 307 | check_status(status); |
| 308 | } |
| 309 | status = cipher_dealloc(c); |
| 310 | check_status(status); |
| 311 | |
| 312 | /* run the throughput test on the aes_gcm_256_openssl cipher */ |
jfigus | 5a2b2d0 | 2014-11-19 14:34:20 -0500 | [diff] [blame^] | 313 | status = cipher_type_alloc(&srtp_aes_gcm_256_openssl, &c, SRTP_AES_256_GCM_KEYSIZE_WSALT, 16); |
jfigus | 7882dd9 | 2013-08-02 16:08:23 -0400 | [diff] [blame] | 314 | if (status) { |
| 315 | fprintf(stderr, "error: can't allocate GCM 256 cipher\n"); |
| 316 | exit(status); |
| 317 | } |
| 318 | status = cipher_init(c, test_key); |
| 319 | check_status(status); |
| 320 | if (do_timing_test) { |
| 321 | cipher_driver_test_throughput(c); |
| 322 | } |
| 323 | |
| 324 | if (do_validation) { |
| 325 | status = cipher_driver_test_buffering(c); |
| 326 | check_status(status); |
| 327 | } |
| 328 | status = cipher_dealloc(c); |
| 329 | check_status(status); |
| 330 | #endif |
| 331 | |
| 332 | return 0; |
Cullen Jennings | 235513a | 2005-09-21 22:51:36 +0000 | [diff] [blame] | 333 | } |
| 334 | |
| 335 | void |
| 336 | cipher_driver_test_throughput(cipher_t *c) { |
| 337 | int i; |
| 338 | int min_enc_len = 32; |
| 339 | int max_enc_len = 2048; /* should be a power of two */ |
Jonathan Lennox | 1731e29 | 2010-05-20 00:44:24 +0000 | [diff] [blame] | 340 | int num_trials = 1000000; |
Cullen Jennings | 235513a | 2005-09-21 22:51:36 +0000 | [diff] [blame] | 341 | |
Jonathan Lennox | 5df951a | 2010-05-20 20:55:54 +0000 | [diff] [blame] | 342 | printf("timing %s throughput, key length %d:\n", c->type->description, c->key_len); |
Cullen Jennings | 235513a | 2005-09-21 22:51:36 +0000 | [diff] [blame] | 343 | fflush(stdout); |
| 344 | for (i=min_enc_len; i <= max_enc_len; i = i * 2) |
| 345 | printf("msg len: %d\tgigabits per second: %f\n", |
| 346 | i, cipher_bits_per_second(c, i, num_trials) / 1e9); |
| 347 | |
| 348 | } |
| 349 | |
jfigus | 857009c | 2014-11-05 11:17:43 -0500 | [diff] [blame] | 350 | srtp_err_status_t |
Cullen Jennings | 235513a | 2005-09-21 22:51:36 +0000 | [diff] [blame] | 351 | cipher_driver_self_test(cipher_type_t *ct) { |
jfigus | 857009c | 2014-11-05 11:17:43 -0500 | [diff] [blame] | 352 | srtp_err_status_t status; |
Cullen Jennings | 235513a | 2005-09-21 22:51:36 +0000 | [diff] [blame] | 353 | |
| 354 | printf("running cipher self-test for %s...", ct->description); |
| 355 | status = cipher_type_self_test(ct); |
| 356 | if (status) { |
| 357 | printf("failed with error code %d\n", status); |
| 358 | exit(status); |
| 359 | } |
| 360 | printf("passed\n"); |
| 361 | |
jfigus | 857009c | 2014-11-05 11:17:43 -0500 | [diff] [blame] | 362 | return srtp_err_status_ok; |
Cullen Jennings | 235513a | 2005-09-21 22:51:36 +0000 | [diff] [blame] | 363 | } |
| 364 | |
| 365 | /* |
| 366 | * cipher_driver_test_buffering(ct) tests the cipher's output |
| 367 | * buffering for correctness by checking the consistency of succesive |
| 368 | * calls |
| 369 | */ |
| 370 | |
jfigus | 857009c | 2014-11-05 11:17:43 -0500 | [diff] [blame] | 371 | srtp_err_status_t |
Cullen Jennings | 235513a | 2005-09-21 22:51:36 +0000 | [diff] [blame] | 372 | cipher_driver_test_buffering(cipher_t *c) { |
David McGrew | fec49dd | 2005-09-23 19:34:11 +0000 | [diff] [blame] | 373 | int i, j, num_trials = 1000; |
| 374 | unsigned len, buflen = 1024; |
Marcus Sundberg | 410faaa | 2005-09-29 12:36:43 +0000 | [diff] [blame] | 375 | uint8_t buffer0[buflen], buffer1[buflen], *current, *end; |
| 376 | uint8_t idx[16] = { |
Cullen Jennings | 235513a | 2005-09-21 22:51:36 +0000 | [diff] [blame] | 377 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 378 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x34 |
| 379 | }; |
jfigus | 857009c | 2014-11-05 11:17:43 -0500 | [diff] [blame] | 380 | srtp_err_status_t status; |
Cullen Jennings | 235513a | 2005-09-21 22:51:36 +0000 | [diff] [blame] | 381 | |
| 382 | printf("testing output buffering for cipher %s...", |
| 383 | c->type->description); |
| 384 | |
| 385 | for (i=0; i < num_trials; i++) { |
| 386 | |
| 387 | /* set buffers to zero */ |
| 388 | for (j=0; j < buflen; j++) |
| 389 | buffer0[j] = buffer1[j] = 0; |
| 390 | |
| 391 | /* initialize cipher */ |
jfigus | 7882dd9 | 2013-08-02 16:08:23 -0400 | [diff] [blame] | 392 | status = cipher_set_iv(c, idx, direction_encrypt); |
Cullen Jennings | 235513a | 2005-09-21 22:51:36 +0000 | [diff] [blame] | 393 | if (status) |
| 394 | return status; |
| 395 | |
| 396 | /* generate 'reference' value by encrypting all at once */ |
| 397 | status = cipher_encrypt(c, buffer0, &buflen); |
| 398 | if (status) |
| 399 | return status; |
| 400 | |
| 401 | /* re-initialize cipher */ |
jfigus | 7882dd9 | 2013-08-02 16:08:23 -0400 | [diff] [blame] | 402 | status = cipher_set_iv(c, idx, direction_encrypt); |
Cullen Jennings | 235513a | 2005-09-21 22:51:36 +0000 | [diff] [blame] | 403 | if (status) |
| 404 | return status; |
| 405 | |
| 406 | /* now loop over short lengths until buffer1 is encrypted */ |
| 407 | current = buffer1; |
| 408 | end = buffer1 + buflen; |
| 409 | while (current < end) { |
| 410 | |
| 411 | /* choose a short length */ |
Marcus Sundberg | d774edb | 2005-10-02 20:36:02 +0000 | [diff] [blame] | 412 | len = rand() & 0x01f; |
Cullen Jennings | 235513a | 2005-09-21 22:51:36 +0000 | [diff] [blame] | 413 | |
| 414 | /* make sure that len doesn't cause us to overreach the buffer */ |
| 415 | if (current + len > end) |
| 416 | len = end - current; |
| 417 | |
| 418 | status = cipher_encrypt(c, current, &len); |
| 419 | if (status) |
| 420 | return status; |
| 421 | |
| 422 | /* advance pointer into buffer1 to reflect encryption */ |
| 423 | current += len; |
| 424 | |
| 425 | /* if buffer1 is all encrypted, break out of loop */ |
| 426 | if (current == end) |
| 427 | break; |
| 428 | } |
| 429 | |
| 430 | /* compare buffers */ |
| 431 | for (j=0; j < buflen; j++) |
| 432 | if (buffer0[j] != buffer1[j]) { |
| 433 | #if PRINT_DEBUG |
| 434 | printf("test case %d failed at byte %d\n", i, j); |
| 435 | printf("computed: %s\n", octet_string_hex_string(buffer1, buflen)); |
| 436 | printf("expected: %s\n", octet_string_hex_string(buffer0, buflen)); |
| 437 | #endif |
jfigus | 857009c | 2014-11-05 11:17:43 -0500 | [diff] [blame] | 438 | return srtp_err_status_algo_fail; |
Cullen Jennings | 235513a | 2005-09-21 22:51:36 +0000 | [diff] [blame] | 439 | } |
| 440 | } |
| 441 | |
| 442 | printf("passed\n"); |
| 443 | |
jfigus | 857009c | 2014-11-05 11:17:43 -0500 | [diff] [blame] | 444 | return srtp_err_status_ok; |
Cullen Jennings | 235513a | 2005-09-21 22:51:36 +0000 | [diff] [blame] | 445 | } |
| 446 | |
| 447 | |
| 448 | /* |
| 449 | * The function cipher_test_throughput_array() tests the effect of CPU |
| 450 | * cache thrash on cipher throughput. |
| 451 | * |
| 452 | * cipher_array_alloc_init(ctype, array, num_ciphers) creates an array |
| 453 | * of cipher_t of type ctype |
| 454 | */ |
| 455 | |
jfigus | 857009c | 2014-11-05 11:17:43 -0500 | [diff] [blame] | 456 | srtp_err_status_t |
Cullen Jennings | 235513a | 2005-09-21 22:51:36 +0000 | [diff] [blame] | 457 | cipher_array_alloc_init(cipher_t ***ca, int num_ciphers, |
| 458 | cipher_type_t *ctype, int klen) { |
| 459 | int i, j; |
jfigus | 857009c | 2014-11-05 11:17:43 -0500 | [diff] [blame] | 460 | srtp_err_status_t status; |
Marcus Sundberg | 410faaa | 2005-09-29 12:36:43 +0000 | [diff] [blame] | 461 | uint8_t *key; |
Cullen Jennings | 235513a | 2005-09-21 22:51:36 +0000 | [diff] [blame] | 462 | cipher_t **cipher_array; |
Jonathan Lennox | 7852d8f | 2010-05-18 21:36:39 +0000 | [diff] [blame] | 463 | /* pad klen allocation, to handle aes_icm reading 16 bytes for the |
| 464 | 14-byte salt */ |
| 465 | int klen_pad = ((klen + 15) >> 4) << 4; |
Cullen Jennings | 235513a | 2005-09-21 22:51:36 +0000 | [diff] [blame] | 466 | |
| 467 | /* allocate array of pointers to ciphers */ |
| 468 | cipher_array = (cipher_t **) malloc(sizeof(cipher_t *) * num_ciphers); |
| 469 | if (cipher_array == NULL) |
jfigus | 857009c | 2014-11-05 11:17:43 -0500 | [diff] [blame] | 470 | return srtp_err_status_alloc_fail; |
Cullen Jennings | 235513a | 2005-09-21 22:51:36 +0000 | [diff] [blame] | 471 | |
| 472 | /* set ca to location of cipher_array */ |
| 473 | *ca = cipher_array; |
| 474 | |
| 475 | /* allocate key */ |
Jonathan Lennox | 7852d8f | 2010-05-18 21:36:39 +0000 | [diff] [blame] | 476 | key = crypto_alloc(klen_pad); |
Cullen Jennings | 235513a | 2005-09-21 22:51:36 +0000 | [diff] [blame] | 477 | if (key == NULL) { |
| 478 | free(cipher_array); |
jfigus | 857009c | 2014-11-05 11:17:43 -0500 | [diff] [blame] | 479 | return srtp_err_status_alloc_fail; |
Cullen Jennings | 235513a | 2005-09-21 22:51:36 +0000 | [diff] [blame] | 480 | } |
| 481 | |
| 482 | /* allocate and initialize an array of ciphers */ |
| 483 | for (i=0; i < num_ciphers; i++) { |
| 484 | |
| 485 | /* allocate cipher */ |
jfigus | c13c100 | 2014-05-08 13:34:53 -0400 | [diff] [blame] | 486 | status = cipher_type_alloc(ctype, cipher_array, klen, 16); |
Cullen Jennings | 235513a | 2005-09-21 22:51:36 +0000 | [diff] [blame] | 487 | if (status) |
| 488 | return status; |
| 489 | |
| 490 | /* generate random key and initialize cipher */ |
| 491 | for (j=0; j < klen; j++) |
Marcus Sundberg | d774edb | 2005-10-02 20:36:02 +0000 | [diff] [blame] | 492 | key[j] = (uint8_t) rand(); |
Jonathan Lennox | 7852d8f | 2010-05-18 21:36:39 +0000 | [diff] [blame] | 493 | for (; j < klen_pad; j++) |
| 494 | key[j] = 0; |
jfigus | 7882dd9 | 2013-08-02 16:08:23 -0400 | [diff] [blame] | 495 | status = cipher_init(*cipher_array, key); |
Cullen Jennings | 235513a | 2005-09-21 22:51:36 +0000 | [diff] [blame] | 496 | if (status) |
| 497 | return status; |
| 498 | |
| 499 | /* printf("%dth cipher is at %p\n", i, *cipher_array); */ |
| 500 | /* printf("%dth cipher description: %s\n", i, */ |
| 501 | /* (*cipher_array)->type->description); */ |
| 502 | |
| 503 | /* advance cipher array pointer */ |
| 504 | cipher_array++; |
| 505 | } |
| 506 | |
Jonathan Lennox | 7852d8f | 2010-05-18 21:36:39 +0000 | [diff] [blame] | 507 | crypto_free(key); |
| 508 | |
jfigus | 857009c | 2014-11-05 11:17:43 -0500 | [diff] [blame] | 509 | return srtp_err_status_ok; |
Cullen Jennings | 235513a | 2005-09-21 22:51:36 +0000 | [diff] [blame] | 510 | } |
| 511 | |
jfigus | 857009c | 2014-11-05 11:17:43 -0500 | [diff] [blame] | 512 | srtp_err_status_t |
Cullen Jennings | 235513a | 2005-09-21 22:51:36 +0000 | [diff] [blame] | 513 | cipher_array_delete(cipher_t *cipher_array[], int num_cipher) { |
| 514 | int i; |
| 515 | |
| 516 | for (i=0; i < num_cipher; i++) { |
| 517 | cipher_dealloc(cipher_array[i]); |
| 518 | } |
| 519 | |
| 520 | free(cipher_array); |
| 521 | |
jfigus | 857009c | 2014-11-05 11:17:43 -0500 | [diff] [blame] | 522 | return srtp_err_status_ok; |
Cullen Jennings | 235513a | 2005-09-21 22:51:36 +0000 | [diff] [blame] | 523 | } |
| 524 | |
| 525 | |
| 526 | /* |
| 527 | * cipher_array_bits_per_second(c, l, t) computes (an estimate of) the |
| 528 | * number of bits that a cipher implementation can encrypt in a second |
| 529 | * when distinct keys are used to encrypt distinct messages |
| 530 | * |
| 531 | * c is a cipher (which MUST be allocated an initialized already), l |
| 532 | * is the length in octets of the test data to be encrypted, and t is |
| 533 | * the number of trials |
| 534 | * |
Marcus Sundberg | e544f61 | 2005-10-03 16:29:05 +0000 | [diff] [blame] | 535 | * if an error is encountered, the value 0 is returned |
Cullen Jennings | 235513a | 2005-09-21 22:51:36 +0000 | [diff] [blame] | 536 | */ |
| 537 | |
Marcus Sundberg | e544f61 | 2005-10-03 16:29:05 +0000 | [diff] [blame] | 538 | uint64_t |
Cullen Jennings | 235513a | 2005-09-21 22:51:36 +0000 | [diff] [blame] | 539 | cipher_array_bits_per_second(cipher_t *cipher_array[], int num_cipher, |
Marcus Sundberg | e544f61 | 2005-10-03 16:29:05 +0000 | [diff] [blame] | 540 | unsigned octets_in_buffer, int num_trials) { |
Cullen Jennings | 235513a | 2005-09-21 22:51:36 +0000 | [diff] [blame] | 541 | int i; |
| 542 | v128_t nonce; |
| 543 | clock_t timer; |
| 544 | unsigned char *enc_buf; |
Jonathan Lennox | 7852d8f | 2010-05-18 21:36:39 +0000 | [diff] [blame] | 545 | int cipher_index = rand() % num_cipher; |
Cullen Jennings | 235513a | 2005-09-21 22:51:36 +0000 | [diff] [blame] | 546 | |
Jonathan Lennox | 7852d8f | 2010-05-18 21:36:39 +0000 | [diff] [blame] | 547 | /* Over-alloc, for NIST CBC padding */ |
| 548 | enc_buf = crypto_alloc(octets_in_buffer+17); |
Cullen Jennings | 235513a | 2005-09-21 22:51:36 +0000 | [diff] [blame] | 549 | if (enc_buf == NULL) |
Marcus Sundberg | e544f61 | 2005-10-03 16:29:05 +0000 | [diff] [blame] | 550 | return 0; /* indicate bad parameters by returning null */ |
Jonathan Lennox | 7852d8f | 2010-05-18 21:36:39 +0000 | [diff] [blame] | 551 | memset(enc_buf, 0, octets_in_buffer); |
Cullen Jennings | 235513a | 2005-09-21 22:51:36 +0000 | [diff] [blame] | 552 | |
| 553 | /* time repeated trials */ |
| 554 | v128_set_to_zero(&nonce); |
| 555 | timer = clock(); |
| 556 | for(i=0; i < num_trials; i++, nonce.v32[3] = i) { |
Jonathan Lennox | 7852d8f | 2010-05-18 21:36:39 +0000 | [diff] [blame] | 557 | /* length parameter to cipher_encrypt is in/out -- out is total, padded |
| 558 | * length -- so reset it each time. */ |
| 559 | unsigned octets_to_encrypt = octets_in_buffer; |
Cullen Jennings | 235513a | 2005-09-21 22:51:36 +0000 | [diff] [blame] | 560 | |
| 561 | /* encrypt buffer with cipher */ |
jfigus | 7882dd9 | 2013-08-02 16:08:23 -0400 | [diff] [blame] | 562 | cipher_set_iv(cipher_array[cipher_index], &nonce, direction_encrypt); |
Jonathan Lennox | 7852d8f | 2010-05-18 21:36:39 +0000 | [diff] [blame] | 563 | cipher_encrypt(cipher_array[cipher_index], enc_buf, &octets_to_encrypt); |
| 564 | |
| 565 | /* choose a cipher at random from the array*/ |
| 566 | cipher_index = (*((uint32_t *)enc_buf)) % num_cipher; |
Cullen Jennings | 235513a | 2005-09-21 22:51:36 +0000 | [diff] [blame] | 567 | } |
| 568 | timer = clock() - timer; |
| 569 | |
| 570 | free(enc_buf); |
Marcus Sundberg | e544f61 | 2005-10-03 16:29:05 +0000 | [diff] [blame] | 571 | |
| 572 | if (timer == 0) { |
| 573 | /* Too fast! */ |
| 574 | return 0; |
| 575 | } |
| 576 | |
Jonathan Lennox | 7852d8f | 2010-05-18 21:36:39 +0000 | [diff] [blame] | 577 | return (uint64_t)CLOCKS_PER_SEC * num_trials * 8 * octets_in_buffer / timer; |
Cullen Jennings | 235513a | 2005-09-21 22:51:36 +0000 | [diff] [blame] | 578 | } |
| 579 | |
| 580 | void |
| 581 | cipher_array_test_throughput(cipher_t *ca[], int num_cipher) { |
| 582 | int i; |
| 583 | int min_enc_len = 16; |
| 584 | int max_enc_len = 2048; /* should be a power of two */ |
Jonathan Lennox | 1731e29 | 2010-05-20 00:44:24 +0000 | [diff] [blame] | 585 | int num_trials = 1000000; |
Cullen Jennings | 235513a | 2005-09-21 22:51:36 +0000 | [diff] [blame] | 586 | |
Jonathan Lennox | 5df951a | 2010-05-20 20:55:54 +0000 | [diff] [blame] | 587 | printf("timing %s throughput with key length %d, array size %d:\n", |
| 588 | (ca[0])->type->description, (ca[0])->key_len, num_cipher); |
Cullen Jennings | 235513a | 2005-09-21 22:51:36 +0000 | [diff] [blame] | 589 | fflush(stdout); |
| 590 | for (i=min_enc_len; i <= max_enc_len; i = i * 4) |
| 591 | printf("msg len: %d\tgigabits per second: %f\n", i, |
| 592 | cipher_array_bits_per_second(ca, num_cipher, i, num_trials) / 1e9); |
| 593 | |
| 594 | } |
| 595 | |
jfigus | 857009c | 2014-11-05 11:17:43 -0500 | [diff] [blame] | 596 | srtp_err_status_t |
Cullen Jennings | 235513a | 2005-09-21 22:51:36 +0000 | [diff] [blame] | 597 | cipher_driver_test_array_throughput(cipher_type_t *ct, |
| 598 | int klen, int num_cipher) { |
| 599 | cipher_t **ca = NULL; |
jfigus | 857009c | 2014-11-05 11:17:43 -0500 | [diff] [blame] | 600 | srtp_err_status_t status; |
Cullen Jennings | 235513a | 2005-09-21 22:51:36 +0000 | [diff] [blame] | 601 | |
| 602 | status = cipher_array_alloc_init(&ca, num_cipher, ct, klen); |
| 603 | if (status) { |
| 604 | printf("error: cipher_array_alloc_init() failed with error code %d\n", |
| 605 | status); |
| 606 | return status; |
| 607 | } |
| 608 | |
| 609 | cipher_array_test_throughput(ca, num_cipher); |
| 610 | |
| 611 | cipher_array_delete(ca, num_cipher); |
| 612 | |
jfigus | 857009c | 2014-11-05 11:17:43 -0500 | [diff] [blame] | 613 | return srtp_err_status_ok; |
Cullen Jennings | 235513a | 2005-09-21 22:51:36 +0000 | [diff] [blame] | 614 | } |