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 51 debug_module_t mod_cipher = { 52 0, /* debugging is off by default */ 53 "cipher" /* printable module name */ 54 }; 55 56 err_status_t 57 cipher_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 68 int 69 cipher_get_key_length(const cipher_t *c) { 70 return c->key_len; 71 } 72 73 /* 74 * cipher_type_test(ct, test_data) tests a cipher of type ct against 75 * test cases provided in a list test_data of values of key, salt, iv, 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 83 err_status_t 84 cipher_type_test(const cipher_type_t *ct, const cipher_test_case_t *test_data) { 85 const cipher_test_case_t *test_case = 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 = 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 status = cipher_dealloc(c); 364 if (status) 365 return status; 366 367 return err_status_ok; 368 } 369 370 371 /* 372 * cipher_type_self_test(ct) performs cipher_type_test on ct's internal 373 * list of test data. 374 */ 375 376 err_status_t 377 cipher_type_self_test(const cipher_type_t *ct) { 378 return cipher_type_test(ct, ct->test_data); 379 } 380 381 /* 382 * cipher_bits_per_second(c, l, t) computes (an estimate of) the 383 * number of bits that a cipher implementation can encrypt in a second 384 * 385 * c is a cipher (which MUST be allocated and initialized already), l 386 * is the length in octets of the test data to be encrypted, and t is 387 * the number of trials 388 * 389 * if an error is encountered, the value 0 is returned 390 */ 391 392 uint64_t 393 cipher_bits_per_second(cipher_t *c, int octets_in_buffer, int num_trials) { 394 int i; 395 v128_t nonce; 396 clock_t timer; 397 unsigned char *enc_buf; 398 unsigned int len = octets_in_buffer; 399 400 enc_buf = (unsigned char*) crypto_alloc(octets_in_buffer); 401 if (enc_buf == NULL) 402 return 0; /* indicate bad parameters by returning null */ 403 404 /* time repeated trials */ 405 v128_set_to_zero(&nonce); 406 timer = clock(); 407 for(i=0; i < num_trials; i++, nonce.v32[3] = i) { 408 cipher_set_iv(c, &nonce); 409 cipher_encrypt(c, enc_buf, &len); 410 } 411 timer = clock() - timer; 412 413 crypto_free(enc_buf); 414 415 if (timer == 0) { 416 /* Too fast! */ 417 return 0; 418 } 419 420 return (uint64_t)CLOCKS_PER_SEC * num_trials * 8 * octets_in_buffer / timer; 421 } 422