1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/netwerk/srtp/src/crypto/cipher/cipher.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,421 @@ 1.4 +/* 1.5 + * cipher.c 1.6 + * 1.7 + * cipher meta-functions 1.8 + * 1.9 + * David A. McGrew 1.10 + * Cisco Systems, Inc. 1.11 + * 1.12 + */ 1.13 + 1.14 +/* 1.15 + * 1.16 + * Copyright (c) 2001-2006, Cisco Systems, Inc. 1.17 + * All rights reserved. 1.18 + * 1.19 + * Redistribution and use in source and binary forms, with or without 1.20 + * modification, are permitted provided that the following conditions 1.21 + * are met: 1.22 + * 1.23 + * Redistributions of source code must retain the above copyright 1.24 + * notice, this list of conditions and the following disclaimer. 1.25 + * 1.26 + * Redistributions in binary form must reproduce the above 1.27 + * copyright notice, this list of conditions and the following 1.28 + * disclaimer in the documentation and/or other materials provided 1.29 + * with the distribution. 1.30 + * 1.31 + * Neither the name of the Cisco Systems, Inc. nor the names of its 1.32 + * contributors may be used to endorse or promote products derived 1.33 + * from this software without specific prior written permission. 1.34 + * 1.35 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1.36 + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1.37 + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 1.38 + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 1.39 + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 1.40 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 1.41 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 1.42 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 1.43 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 1.44 + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 1.45 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 1.46 + * OF THE POSSIBILITY OF SUCH DAMAGE. 1.47 + * 1.48 + */ 1.49 + 1.50 +#include "cipher.h" 1.51 +#include "rand_source.h" /* used in invertibiltiy tests */ 1.52 +#include "alloc.h" /* for crypto_alloc(), crypto_free() */ 1.53 + 1.54 +debug_module_t mod_cipher = { 1.55 + 0, /* debugging is off by default */ 1.56 + "cipher" /* printable module name */ 1.57 +}; 1.58 + 1.59 +err_status_t 1.60 +cipher_output(cipher_t *c, uint8_t *buffer, int num_octets_to_output) { 1.61 + 1.62 + /* zeroize the buffer */ 1.63 + octet_string_set_to_zero(buffer, num_octets_to_output); 1.64 + 1.65 + /* exor keystream into buffer */ 1.66 + return cipher_encrypt(c, buffer, (unsigned int *) &num_octets_to_output); 1.67 +} 1.68 + 1.69 +/* some bookkeeping functions */ 1.70 + 1.71 +int 1.72 +cipher_get_key_length(const cipher_t *c) { 1.73 + return c->key_len; 1.74 +} 1.75 + 1.76 +/* 1.77 + * cipher_type_test(ct, test_data) tests a cipher of type ct against 1.78 + * test cases provided in a list test_data of values of key, salt, iv, 1.79 + * plaintext, and ciphertext that is known to be good 1.80 + */ 1.81 + 1.82 +#define SELF_TEST_BUF_OCTETS 128 1.83 +#define NUM_RAND_TESTS 128 1.84 +#define MAX_KEY_LEN 64 1.85 + 1.86 +err_status_t 1.87 +cipher_type_test(const cipher_type_t *ct, const cipher_test_case_t *test_data) { 1.88 + const cipher_test_case_t *test_case = test_data; 1.89 + cipher_t *c; 1.90 + err_status_t status; 1.91 + uint8_t buffer[SELF_TEST_BUF_OCTETS]; 1.92 + uint8_t buffer2[SELF_TEST_BUF_OCTETS]; 1.93 + unsigned int len; 1.94 + int i, j, case_num = 0; 1.95 + 1.96 + debug_print(mod_cipher, "running self-test for cipher %s", 1.97 + ct->description); 1.98 + 1.99 + /* 1.100 + * check to make sure that we have at least one test case, and 1.101 + * return an error if we don't - we need to be paranoid here 1.102 + */ 1.103 + if (test_case == NULL) 1.104 + return err_status_cant_check; 1.105 + 1.106 + /* 1.107 + * loop over all test cases, perform known-answer tests of both the 1.108 + * encryption and decryption functions 1.109 + */ 1.110 + while (test_case != NULL) { 1.111 + 1.112 + /* allocate cipher */ 1.113 + status = cipher_type_alloc(ct, &c, test_case->key_length_octets); 1.114 + if (status) 1.115 + return status; 1.116 + 1.117 + /* 1.118 + * test the encrypt function 1.119 + */ 1.120 + debug_print(mod_cipher, "testing encryption", NULL); 1.121 + 1.122 + /* initialize cipher */ 1.123 + status = cipher_init(c, test_case->key, direction_encrypt); 1.124 + if (status) { 1.125 + cipher_dealloc(c); 1.126 + return status; 1.127 + } 1.128 + 1.129 + /* copy plaintext into test buffer */ 1.130 + if (test_case->ciphertext_length_octets > SELF_TEST_BUF_OCTETS) { 1.131 + cipher_dealloc(c); 1.132 + return err_status_bad_param; 1.133 + } 1.134 + for (i=0; i < test_case->plaintext_length_octets; i++) 1.135 + buffer[i] = test_case->plaintext[i]; 1.136 + 1.137 + debug_print(mod_cipher, "plaintext: %s", 1.138 + octet_string_hex_string(buffer, 1.139 + test_case->plaintext_length_octets)); 1.140 + 1.141 + /* set the initialization vector */ 1.142 + status = cipher_set_iv(c, test_case->idx); 1.143 + if (status) { 1.144 + cipher_dealloc(c); 1.145 + return status; 1.146 + } 1.147 + 1.148 + /* encrypt */ 1.149 + len = test_case->plaintext_length_octets; 1.150 + status = cipher_encrypt(c, buffer, &len); 1.151 + if (status) { 1.152 + cipher_dealloc(c); 1.153 + return status; 1.154 + } 1.155 + 1.156 + debug_print(mod_cipher, "ciphertext: %s", 1.157 + octet_string_hex_string(buffer, 1.158 + test_case->ciphertext_length_octets)); 1.159 + 1.160 + /* compare the resulting ciphertext with that in the test case */ 1.161 + if (len != (unsigned int)test_case->ciphertext_length_octets) 1.162 + return err_status_algo_fail; 1.163 + status = err_status_ok; 1.164 + for (i=0; i < test_case->ciphertext_length_octets; i++) 1.165 + if (buffer[i] != test_case->ciphertext[i]) { 1.166 + status = err_status_algo_fail; 1.167 + debug_print(mod_cipher, "test case %d failed", case_num); 1.168 + debug_print(mod_cipher, "(failure at byte %d)", i); 1.169 + break; 1.170 + } 1.171 + if (status) { 1.172 + 1.173 + debug_print(mod_cipher, "c computed: %s", 1.174 + octet_string_hex_string(buffer, 1.175 + 2*test_case->plaintext_length_octets)); 1.176 + debug_print(mod_cipher, "c expected: %s", 1.177 + octet_string_hex_string(test_case->ciphertext, 1.178 + 2*test_case->plaintext_length_octets)); 1.179 + 1.180 + cipher_dealloc(c); 1.181 + return err_status_algo_fail; 1.182 + } 1.183 + 1.184 + /* 1.185 + * test the decrypt function 1.186 + */ 1.187 + debug_print(mod_cipher, "testing decryption", NULL); 1.188 + 1.189 + /* re-initialize cipher for decryption */ 1.190 + status = cipher_init(c, test_case->key, direction_decrypt); 1.191 + if (status) { 1.192 + cipher_dealloc(c); 1.193 + return status; 1.194 + } 1.195 + 1.196 + /* copy ciphertext into test buffer */ 1.197 + if (test_case->ciphertext_length_octets > SELF_TEST_BUF_OCTETS) { 1.198 + cipher_dealloc(c); 1.199 + return err_status_bad_param; 1.200 + } 1.201 + for (i=0; i < test_case->ciphertext_length_octets; i++) 1.202 + buffer[i] = test_case->ciphertext[i]; 1.203 + 1.204 + debug_print(mod_cipher, "ciphertext: %s", 1.205 + octet_string_hex_string(buffer, 1.206 + test_case->plaintext_length_octets)); 1.207 + 1.208 + /* set the initialization vector */ 1.209 + status = cipher_set_iv(c, test_case->idx); 1.210 + if (status) { 1.211 + cipher_dealloc(c); 1.212 + return status; 1.213 + } 1.214 + 1.215 + /* decrypt */ 1.216 + len = test_case->ciphertext_length_octets; 1.217 + status = cipher_decrypt(c, buffer, &len); 1.218 + if (status) { 1.219 + cipher_dealloc(c); 1.220 + return status; 1.221 + } 1.222 + 1.223 + debug_print(mod_cipher, "plaintext: %s", 1.224 + octet_string_hex_string(buffer, 1.225 + test_case->plaintext_length_octets)); 1.226 + 1.227 + /* compare the resulting plaintext with that in the test case */ 1.228 + if (len != (unsigned int)test_case->plaintext_length_octets) 1.229 + return err_status_algo_fail; 1.230 + status = err_status_ok; 1.231 + for (i=0; i < test_case->plaintext_length_octets; i++) 1.232 + if (buffer[i] != test_case->plaintext[i]) { 1.233 + status = err_status_algo_fail; 1.234 + debug_print(mod_cipher, "test case %d failed", case_num); 1.235 + debug_print(mod_cipher, "(failure at byte %d)", i); 1.236 + } 1.237 + if (status) { 1.238 + 1.239 + debug_print(mod_cipher, "p computed: %s", 1.240 + octet_string_hex_string(buffer, 1.241 + 2*test_case->plaintext_length_octets)); 1.242 + debug_print(mod_cipher, "p expected: %s", 1.243 + octet_string_hex_string(test_case->plaintext, 1.244 + 2*test_case->plaintext_length_octets)); 1.245 + 1.246 + cipher_dealloc(c); 1.247 + return err_status_algo_fail; 1.248 + } 1.249 + 1.250 + /* deallocate the cipher */ 1.251 + status = cipher_dealloc(c); 1.252 + if (status) 1.253 + return status; 1.254 + 1.255 + /* 1.256 + * the cipher passed the test case, so move on to the next test 1.257 + * case in the list; if NULL, we'l proceed to the next test 1.258 + */ 1.259 + test_case = test_case->next_test_case; 1.260 + ++case_num; 1.261 + } 1.262 + 1.263 + /* now run some random invertibility tests */ 1.264 + 1.265 + /* allocate cipher, using paramaters from the first test case */ 1.266 + test_case = test_data; 1.267 + status = cipher_type_alloc(ct, &c, test_case->key_length_octets); 1.268 + if (status) 1.269 + return status; 1.270 + 1.271 + rand_source_init(); 1.272 + 1.273 + for (j=0; j < NUM_RAND_TESTS; j++) { 1.274 + unsigned length; 1.275 + int plaintext_len; 1.276 + uint8_t key[MAX_KEY_LEN]; 1.277 + uint8_t iv[MAX_KEY_LEN]; 1.278 + 1.279 + /* choose a length at random (leaving room for IV and padding) */ 1.280 + length = rand() % (SELF_TEST_BUF_OCTETS - 64); 1.281 + debug_print(mod_cipher, "random plaintext length %d\n", length); 1.282 + status = rand_source_get_octet_string(buffer, length); 1.283 + if (status) return status; 1.284 + 1.285 + debug_print(mod_cipher, "plaintext: %s", 1.286 + octet_string_hex_string(buffer, length)); 1.287 + 1.288 + /* copy plaintext into second buffer */ 1.289 + for (i=0; (unsigned int)i < length; i++) 1.290 + buffer2[i] = buffer[i]; 1.291 + 1.292 + /* choose a key at random */ 1.293 + if (test_case->key_length_octets > MAX_KEY_LEN) 1.294 + return err_status_cant_check; 1.295 + status = rand_source_get_octet_string(key, test_case->key_length_octets); 1.296 + if (status) return status; 1.297 + 1.298 + /* chose a random initialization vector */ 1.299 + status = rand_source_get_octet_string(iv, MAX_KEY_LEN); 1.300 + if (status) return status; 1.301 + 1.302 + /* initialize cipher */ 1.303 + status = cipher_init(c, key, direction_encrypt); 1.304 + if (status) { 1.305 + cipher_dealloc(c); 1.306 + return status; 1.307 + } 1.308 + 1.309 + /* set initialization vector */ 1.310 + status = cipher_set_iv(c, test_case->idx); 1.311 + if (status) { 1.312 + cipher_dealloc(c); 1.313 + return status; 1.314 + } 1.315 + 1.316 + /* encrypt buffer with cipher */ 1.317 + plaintext_len = length; 1.318 + status = cipher_encrypt(c, buffer, &length); 1.319 + if (status) { 1.320 + cipher_dealloc(c); 1.321 + return status; 1.322 + } 1.323 + debug_print(mod_cipher, "ciphertext: %s", 1.324 + octet_string_hex_string(buffer, length)); 1.325 + 1.326 + /* 1.327 + * re-initialize cipher for decryption, re-set the iv, then 1.328 + * decrypt the ciphertext 1.329 + */ 1.330 + status = cipher_init(c, key, direction_decrypt); 1.331 + if (status) { 1.332 + cipher_dealloc(c); 1.333 + return status; 1.334 + } 1.335 + status = cipher_set_iv(c, test_case->idx); 1.336 + if (status) { 1.337 + cipher_dealloc(c); 1.338 + return status; 1.339 + } 1.340 + status = cipher_decrypt(c, buffer, &length); 1.341 + if (status) { 1.342 + cipher_dealloc(c); 1.343 + return status; 1.344 + } 1.345 + 1.346 + debug_print(mod_cipher, "plaintext[2]: %s", 1.347 + octet_string_hex_string(buffer, length)); 1.348 + 1.349 + /* compare the resulting plaintext with the original one */ 1.350 + if (length != (unsigned)plaintext_len) 1.351 + return err_status_algo_fail; 1.352 + status = err_status_ok; 1.353 + for (i=0; i < plaintext_len; i++) 1.354 + if (buffer[i] != buffer2[i]) { 1.355 + status = err_status_algo_fail; 1.356 + debug_print(mod_cipher, "random test case %d failed", case_num); 1.357 + debug_print(mod_cipher, "(failure at byte %d)", i); 1.358 + } 1.359 + if (status) { 1.360 + cipher_dealloc(c); 1.361 + return err_status_algo_fail; 1.362 + } 1.363 + 1.364 + } 1.365 + 1.366 + status = cipher_dealloc(c); 1.367 + if (status) 1.368 + return status; 1.369 + 1.370 + return err_status_ok; 1.371 +} 1.372 + 1.373 + 1.374 +/* 1.375 + * cipher_type_self_test(ct) performs cipher_type_test on ct's internal 1.376 + * list of test data. 1.377 + */ 1.378 + 1.379 +err_status_t 1.380 +cipher_type_self_test(const cipher_type_t *ct) { 1.381 + return cipher_type_test(ct, ct->test_data); 1.382 +} 1.383 + 1.384 +/* 1.385 + * cipher_bits_per_second(c, l, t) computes (an estimate of) the 1.386 + * number of bits that a cipher implementation can encrypt in a second 1.387 + * 1.388 + * c is a cipher (which MUST be allocated and initialized already), l 1.389 + * is the length in octets of the test data to be encrypted, and t is 1.390 + * the number of trials 1.391 + * 1.392 + * if an error is encountered, the value 0 is returned 1.393 + */ 1.394 + 1.395 +uint64_t 1.396 +cipher_bits_per_second(cipher_t *c, int octets_in_buffer, int num_trials) { 1.397 + int i; 1.398 + v128_t nonce; 1.399 + clock_t timer; 1.400 + unsigned char *enc_buf; 1.401 + unsigned int len = octets_in_buffer; 1.402 + 1.403 + enc_buf = (unsigned char*) crypto_alloc(octets_in_buffer); 1.404 + if (enc_buf == NULL) 1.405 + return 0; /* indicate bad parameters by returning null */ 1.406 + 1.407 + /* time repeated trials */ 1.408 + v128_set_to_zero(&nonce); 1.409 + timer = clock(); 1.410 + for(i=0; i < num_trials; i++, nonce.v32[3] = i) { 1.411 + cipher_set_iv(c, &nonce); 1.412 + cipher_encrypt(c, enc_buf, &len); 1.413 + } 1.414 + timer = clock() - timer; 1.415 + 1.416 + crypto_free(enc_buf); 1.417 + 1.418 + if (timer == 0) { 1.419 + /* Too fast! */ 1.420 + return 0; 1.421 + } 1.422 + 1.423 + return (uint64_t)CLOCKS_PER_SEC * num_trials * 8 * octets_in_buffer / timer; 1.424 +}