| File: | libs/srtp/crypto/cipher/cipher.c |
| Location: | line 496, column 5 |
| Description: | Access to field 'type' results in a dereference of a null pointer (loaded from variable 'c') |
| 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,2013 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 "crypto_types.h" | |||||
| 49 | #include "rand_source.h" /* used in invertibiltiy tests */ | |||||
| 50 | #include "alloc.h" /* for crypto_alloc(), crypto_free() */ | |||||
| 51 | ||||||
| 52 | debug_module_t mod_cipher = { | |||||
| 53 | 0, /* debugging is off by default */ | |||||
| 54 | "cipher" /* printable module name */ | |||||
| 55 | }; | |||||
| 56 | ||||||
| 57 | err_status_t | |||||
| 58 | cipher_output(cipher_t *c, uint8_t *buffer, int num_octets_to_output) { | |||||
| 59 | ||||||
| 60 | /* zeroize the buffer */ | |||||
| 61 | octet_string_set_to_zero(buffer, num_octets_to_output); | |||||
| 62 | ||||||
| 63 | /* exor keystream into buffer */ | |||||
| 64 | return cipher_encrypt(c, buffer, (unsigned int *) &num_octets_to_output)(((c)->type)->encrypt(((c)->state), (buffer), ((unsigned int *) &num_octets_to_output))); | |||||
| 65 | } | |||||
| 66 | ||||||
| 67 | /* some bookkeeping functions */ | |||||
| 68 | ||||||
| 69 | int | |||||
| 70 | cipher_get_key_length(const cipher_t *c) { | |||||
| 71 | return c->key_len; | |||||
| 72 | } | |||||
| 73 | ||||||
| 74 | /* | |||||
| 75 | * cipher_type_test(ct, test_data) tests a cipher of type ct against | |||||
| 76 | * test cases provided in a list test_data of values of key, salt, iv, | |||||
| 77 | * plaintext, and ciphertext that is known to be good | |||||
| 78 | */ | |||||
| 79 | ||||||
| 80 | #define SELF_TEST_BUF_OCTETS128 128 | |||||
| 81 | #define NUM_RAND_TESTS128 128 | |||||
| 82 | #define MAX_KEY_LEN64 64 | |||||
| 83 | ||||||
| 84 | err_status_t | |||||
| 85 | cipher_type_test(const cipher_type_t *ct, const cipher_test_case_t *test_data) { | |||||
| 86 | const cipher_test_case_t *test_case = test_data; | |||||
| 87 | cipher_t *c; | |||||
| 88 | err_status_t status; | |||||
| 89 | uint8_t buffer[SELF_TEST_BUF_OCTETS128]; | |||||
| 90 | uint8_t buffer2[SELF_TEST_BUF_OCTETS128]; | |||||
| 91 | int tag_len; | |||||
| 92 | unsigned int len; | |||||
| 93 | int i, j, case_num = 0; | |||||
| 94 | ||||||
| 95 | debug_print(mod_cipher, "running self-test for cipher %s",if (mod_cipher.on) err_report(err_level_debug, ("%s: " "running self-test for cipher %s" "\n"), mod_cipher.name, ct->description) | |||||
| 96 | ct->description)if (mod_cipher.on) err_report(err_level_debug, ("%s: " "running self-test for cipher %s" "\n"), mod_cipher.name, ct->description); | |||||
| 97 | ||||||
| 98 | /* | |||||
| 99 | * check to make sure that we have at least one test case, and | |||||
| 100 | * return an error if we don't - we need to be paranoid here | |||||
| 101 | */ | |||||
| 102 | if (test_case == NULL((void*)0)) | |||||
| 103 | return err_status_cant_check; | |||||
| 104 | ||||||
| 105 | /* | |||||
| 106 | * loop over all test cases, perform known-answer tests of both the | |||||
| 107 | * encryption and decryption functions | |||||
| 108 | */ | |||||
| 109 | while (test_case != NULL((void*)0)) { | |||||
| 110 | /* allocate cipher */ | |||||
| 111 | status = cipher_type_alloc(ct, &c, test_case->key_length_octets, test_case->tag_length_octets)((ct)->alloc((&c), (test_case->key_length_octets), ( test_case->tag_length_octets))); | |||||
| 112 | if (status) | |||||
| 113 | return status; | |||||
| 114 | ||||||
| 115 | /* | |||||
| 116 | * test the encrypt function | |||||
| 117 | */ | |||||
| 118 | debug_print(mod_cipher, "testing encryption", NULL)if (mod_cipher.on) err_report(err_level_debug, ("%s: " "testing encryption" "\n"), mod_cipher.name, ((void*)0)); | |||||
| 119 | ||||||
| 120 | /* initialize cipher */ | |||||
| 121 | status = cipher_init(c, test_case->key)(((c)->type)->init(((c)->state), (test_case->key) , ((c)->key_len))); | |||||
| 122 | if (status) { | |||||
| 123 | cipher_dealloc(c)(((c)->type)->dealloc(c)); | |||||
| 124 | return status; | |||||
| 125 | } | |||||
| 126 | ||||||
| 127 | /* copy plaintext into test buffer */ | |||||
| 128 | if (test_case->ciphertext_length_octets > SELF_TEST_BUF_OCTETS128) { | |||||
| 129 | cipher_dealloc(c)(((c)->type)->dealloc(c)); | |||||
| 130 | return err_status_bad_param; | |||||
| 131 | } | |||||
| 132 | for (i=0; i < test_case->plaintext_length_octets; i++) | |||||
| 133 | buffer[i] = test_case->plaintext[i]; | |||||
| 134 | ||||||
| 135 | debug_print(mod_cipher, "plaintext: %s",if (mod_cipher.on) err_report(err_level_debug, ("%s: " "plaintext: %s" "\n"), mod_cipher.name, octet_string_hex_string(buffer, test_case ->plaintext_length_octets)) | |||||
| 136 | octet_string_hex_string(buffer,if (mod_cipher.on) err_report(err_level_debug, ("%s: " "plaintext: %s" "\n"), mod_cipher.name, octet_string_hex_string(buffer, test_case ->plaintext_length_octets)) | |||||
| 137 | test_case->plaintext_length_octets))if (mod_cipher.on) err_report(err_level_debug, ("%s: " "plaintext: %s" "\n"), mod_cipher.name, octet_string_hex_string(buffer, test_case ->plaintext_length_octets)); | |||||
| 138 | ||||||
| 139 | /* set the initialization vector */ | |||||
| 140 | status = cipher_set_iv(c, test_case->idx, direction_encrypt)((c) ? (((c)->type)->set_iv(((cipher_pointer_t)(c)-> state), (test_case->idx), (direction_encrypt))) : err_status_no_such_op ); | |||||
| 141 | if (status) { | |||||
| 142 | cipher_dealloc(c)(((c)->type)->dealloc(c)); | |||||
| 143 | return status; | |||||
| 144 | } | |||||
| 145 | ||||||
| 146 | if (c->algorithm == AES_128_GCM6 || c->algorithm == AES_256_GCM7) { | |||||
| 147 | debug_print(mod_cipher, "IV: %s",if (mod_cipher.on) err_report(err_level_debug, ("%s: " "IV: %s" "\n"), mod_cipher.name, octet_string_hex_string(test_case-> idx, 12)) | |||||
| 148 | octet_string_hex_string(test_case->idx, 12))if (mod_cipher.on) err_report(err_level_debug, ("%s: " "IV: %s" "\n"), mod_cipher.name, octet_string_hex_string(test_case-> idx, 12)); | |||||
| 149 | ||||||
| 150 | /* | |||||
| 151 | * Set the AAD | |||||
| 152 | */ | |||||
| 153 | status = cipher_set_aad(c, test_case->aad,(((c) && (((c)->type)->set_aad)) ? (((c)->type )->set_aad(((c)->state), (test_case->aad), (test_case ->aad_length_octets))) : err_status_no_such_op) | |||||
| 154 | test_case->aad_length_octets)(((c) && (((c)->type)->set_aad)) ? (((c)->type )->set_aad(((c)->state), (test_case->aad), (test_case ->aad_length_octets))) : err_status_no_such_op); | |||||
| 155 | if (status) { | |||||
| 156 | cipher_dealloc(c)(((c)->type)->dealloc(c)); | |||||
| 157 | return status; | |||||
| 158 | } | |||||
| 159 | debug_print(mod_cipher, "AAD: %s",if (mod_cipher.on) err_report(err_level_debug, ("%s: " "AAD: %s" "\n"), mod_cipher.name, octet_string_hex_string(test_case-> aad, test_case->aad_length_octets)) | |||||
| 160 | octet_string_hex_string(test_case->aad,if (mod_cipher.on) err_report(err_level_debug, ("%s: " "AAD: %s" "\n"), mod_cipher.name, octet_string_hex_string(test_case-> aad, test_case->aad_length_octets)) | |||||
| 161 | test_case->aad_length_octets))if (mod_cipher.on) err_report(err_level_debug, ("%s: " "AAD: %s" "\n"), mod_cipher.name, octet_string_hex_string(test_case-> aad, test_case->aad_length_octets)); | |||||
| 162 | } | |||||
| 163 | ||||||
| 164 | /* encrypt */ | |||||
| 165 | len = test_case->plaintext_length_octets; | |||||
| 166 | status = cipher_encrypt(c, buffer, &len)(((c)->type)->encrypt(((c)->state), (buffer), (& len))); | |||||
| 167 | if (status) { | |||||
| 168 | cipher_dealloc(c)(((c)->type)->dealloc(c)); | |||||
| 169 | return status; | |||||
| 170 | } | |||||
| 171 | ||||||
| 172 | if (c->algorithm == AES_128_GCM6 || c->algorithm == AES_256_GCM7) { | |||||
| 173 | /* | |||||
| 174 | * Get the GCM tag | |||||
| 175 | */ | |||||
| 176 | status = cipher_get_tag(c, buffer + len, &tag_len)(((c)->type)->get_tag(((c)->state), (buffer + len), ( &tag_len))); | |||||
| 177 | if (status) { | |||||
| 178 | cipher_dealloc(c)(((c)->type)->dealloc(c)); | |||||
| 179 | return status; | |||||
| 180 | } | |||||
| 181 | len += tag_len; | |||||
| 182 | } | |||||
| 183 | ||||||
| 184 | debug_print(mod_cipher, "ciphertext: %s",if (mod_cipher.on) err_report(err_level_debug, ("%s: " "ciphertext: %s" "\n"), mod_cipher.name, octet_string_hex_string(buffer, test_case ->ciphertext_length_octets)) | |||||
| 185 | octet_string_hex_string(buffer,if (mod_cipher.on) err_report(err_level_debug, ("%s: " "ciphertext: %s" "\n"), mod_cipher.name, octet_string_hex_string(buffer, test_case ->ciphertext_length_octets)) | |||||
| 186 | test_case->ciphertext_length_octets))if (mod_cipher.on) err_report(err_level_debug, ("%s: " "ciphertext: %s" "\n"), mod_cipher.name, octet_string_hex_string(buffer, test_case ->ciphertext_length_octets)); | |||||
| 187 | ||||||
| 188 | /* compare the resulting ciphertext with that in the test case */ | |||||
| 189 | if (len != (unsigned int)test_case->ciphertext_length_octets) | |||||
| 190 | return err_status_algo_fail; | |||||
| 191 | status = err_status_ok; | |||||
| 192 | for (i=0; i < test_case->ciphertext_length_octets; i++) | |||||
| 193 | if (buffer[i] != test_case->ciphertext[i]) { | |||||
| 194 | status = err_status_algo_fail; | |||||
| 195 | debug_print(mod_cipher, "test case %d failed", case_num)if (mod_cipher.on) err_report(err_level_debug, ("%s: " "test case %d failed" "\n"), mod_cipher.name, case_num); | |||||
| 196 | debug_print(mod_cipher, "(failure at byte %d)", i)if (mod_cipher.on) err_report(err_level_debug, ("%s: " "(failure at byte %d)" "\n"), mod_cipher.name, i); | |||||
| 197 | break; | |||||
| 198 | } | |||||
| 199 | if (status) { | |||||
| 200 | ||||||
| 201 | debug_print(mod_cipher, "c computed: %s",if (mod_cipher.on) err_report(err_level_debug, ("%s: " "c computed: %s" "\n"), mod_cipher.name, octet_string_hex_string(buffer, 2*test_case ->plaintext_length_octets)) | |||||
| 202 | octet_string_hex_string(buffer,if (mod_cipher.on) err_report(err_level_debug, ("%s: " "c computed: %s" "\n"), mod_cipher.name, octet_string_hex_string(buffer, 2*test_case ->plaintext_length_octets)) | |||||
| 203 | 2*test_case->plaintext_length_octets))if (mod_cipher.on) err_report(err_level_debug, ("%s: " "c computed: %s" "\n"), mod_cipher.name, octet_string_hex_string(buffer, 2*test_case ->plaintext_length_octets)); | |||||
| 204 | debug_print(mod_cipher, "c expected: %s",if (mod_cipher.on) err_report(err_level_debug, ("%s: " "c expected: %s" "\n"), mod_cipher.name, octet_string_hex_string(test_case-> ciphertext, 2*test_case->plaintext_length_octets)) | |||||
| 205 | octet_string_hex_string(test_case->ciphertext,if (mod_cipher.on) err_report(err_level_debug, ("%s: " "c expected: %s" "\n"), mod_cipher.name, octet_string_hex_string(test_case-> ciphertext, 2*test_case->plaintext_length_octets)) | |||||
| 206 | 2*test_case->plaintext_length_octets))if (mod_cipher.on) err_report(err_level_debug, ("%s: " "c expected: %s" "\n"), mod_cipher.name, octet_string_hex_string(test_case-> ciphertext, 2*test_case->plaintext_length_octets)); | |||||
| 207 | ||||||
| 208 | cipher_dealloc(c)(((c)->type)->dealloc(c)); | |||||
| 209 | return err_status_algo_fail; | |||||
| 210 | } | |||||
| 211 | ||||||
| 212 | /* | |||||
| 213 | * test the decrypt function | |||||
| 214 | */ | |||||
| 215 | debug_print(mod_cipher, "testing decryption", NULL)if (mod_cipher.on) err_report(err_level_debug, ("%s: " "testing decryption" "\n"), mod_cipher.name, ((void*)0)); | |||||
| 216 | ||||||
| 217 | /* re-initialize cipher for decryption */ | |||||
| 218 | status = cipher_init(c, test_case->key)(((c)->type)->init(((c)->state), (test_case->key) , ((c)->key_len))); | |||||
| 219 | if (status) { | |||||
| 220 | cipher_dealloc(c)(((c)->type)->dealloc(c)); | |||||
| 221 | return status; | |||||
| 222 | } | |||||
| 223 | ||||||
| 224 | /* copy ciphertext into test buffer */ | |||||
| 225 | if (test_case->ciphertext_length_octets > SELF_TEST_BUF_OCTETS128) { | |||||
| 226 | cipher_dealloc(c)(((c)->type)->dealloc(c)); | |||||
| 227 | return err_status_bad_param; | |||||
| 228 | } | |||||
| 229 | for (i=0; i < test_case->ciphertext_length_octets; i++) | |||||
| 230 | buffer[i] = test_case->ciphertext[i]; | |||||
| 231 | ||||||
| 232 | debug_print(mod_cipher, "ciphertext: %s",if (mod_cipher.on) err_report(err_level_debug, ("%s: " "ciphertext: %s" "\n"), mod_cipher.name, octet_string_hex_string(buffer, test_case ->plaintext_length_octets)) | |||||
| 233 | octet_string_hex_string(buffer,if (mod_cipher.on) err_report(err_level_debug, ("%s: " "ciphertext: %s" "\n"), mod_cipher.name, octet_string_hex_string(buffer, test_case ->plaintext_length_octets)) | |||||
| 234 | test_case->plaintext_length_octets))if (mod_cipher.on) err_report(err_level_debug, ("%s: " "ciphertext: %s" "\n"), mod_cipher.name, octet_string_hex_string(buffer, test_case ->plaintext_length_octets)); | |||||
| 235 | ||||||
| 236 | /* set the initialization vector */ | |||||
| 237 | status = cipher_set_iv(c, test_case->idx, direction_decrypt)((c) ? (((c)->type)->set_iv(((cipher_pointer_t)(c)-> state), (test_case->idx), (direction_decrypt))) : err_status_no_such_op ); | |||||
| 238 | if (status) { | |||||
| 239 | cipher_dealloc(c)(((c)->type)->dealloc(c)); | |||||
| 240 | return status; | |||||
| 241 | } | |||||
| 242 | ||||||
| 243 | if (c->algorithm == AES_128_GCM6 || c->algorithm == AES_256_GCM7) { | |||||
| 244 | /* | |||||
| 245 | * Set the AAD | |||||
| 246 | */ | |||||
| 247 | status = cipher_set_aad(c, test_case->aad,(((c) && (((c)->type)->set_aad)) ? (((c)->type )->set_aad(((c)->state), (test_case->aad), (test_case ->aad_length_octets))) : err_status_no_such_op) | |||||
| 248 | test_case->aad_length_octets)(((c) && (((c)->type)->set_aad)) ? (((c)->type )->set_aad(((c)->state), (test_case->aad), (test_case ->aad_length_octets))) : err_status_no_such_op); | |||||
| 249 | if (status) { | |||||
| 250 | cipher_dealloc(c)(((c)->type)->dealloc(c)); | |||||
| 251 | return status; | |||||
| 252 | } | |||||
| 253 | debug_print(mod_cipher, "AAD: %s",if (mod_cipher.on) err_report(err_level_debug, ("%s: " "AAD: %s" "\n"), mod_cipher.name, octet_string_hex_string(test_case-> aad, test_case->aad_length_octets)) | |||||
| 254 | octet_string_hex_string(test_case->aad,if (mod_cipher.on) err_report(err_level_debug, ("%s: " "AAD: %s" "\n"), mod_cipher.name, octet_string_hex_string(test_case-> aad, test_case->aad_length_octets)) | |||||
| 255 | test_case->aad_length_octets))if (mod_cipher.on) err_report(err_level_debug, ("%s: " "AAD: %s" "\n"), mod_cipher.name, octet_string_hex_string(test_case-> aad, test_case->aad_length_octets)); | |||||
| 256 | } | |||||
| 257 | ||||||
| 258 | /* decrypt */ | |||||
| 259 | len = test_case->ciphertext_length_octets; | |||||
| 260 | status = cipher_decrypt(c, buffer, &len)(((c)->type)->decrypt(((c)->state), (buffer), (& len))); | |||||
| 261 | if (status) { | |||||
| 262 | cipher_dealloc(c)(((c)->type)->dealloc(c)); | |||||
| 263 | return status; | |||||
| 264 | } | |||||
| 265 | ||||||
| 266 | debug_print(mod_cipher, "plaintext: %s",if (mod_cipher.on) err_report(err_level_debug, ("%s: " "plaintext: %s" "\n"), mod_cipher.name, octet_string_hex_string(buffer, test_case ->plaintext_length_octets)) | |||||
| 267 | octet_string_hex_string(buffer,if (mod_cipher.on) err_report(err_level_debug, ("%s: " "plaintext: %s" "\n"), mod_cipher.name, octet_string_hex_string(buffer, test_case ->plaintext_length_octets)) | |||||
| 268 | test_case->plaintext_length_octets))if (mod_cipher.on) err_report(err_level_debug, ("%s: " "plaintext: %s" "\n"), mod_cipher.name, octet_string_hex_string(buffer, test_case ->plaintext_length_octets)); | |||||
| 269 | ||||||
| 270 | /* compare the resulting plaintext with that in the test case */ | |||||
| 271 | if (len != (unsigned int)test_case->plaintext_length_octets) | |||||
| 272 | return err_status_algo_fail; | |||||
| 273 | status = err_status_ok; | |||||
| 274 | for (i=0; i < test_case->plaintext_length_octets; i++) | |||||
| 275 | if (buffer[i] != test_case->plaintext[i]) { | |||||
| 276 | status = err_status_algo_fail; | |||||
| 277 | debug_print(mod_cipher, "test case %d failed", case_num)if (mod_cipher.on) err_report(err_level_debug, ("%s: " "test case %d failed" "\n"), mod_cipher.name, case_num); | |||||
| 278 | debug_print(mod_cipher, "(failure at byte %d)", i)if (mod_cipher.on) err_report(err_level_debug, ("%s: " "(failure at byte %d)" "\n"), mod_cipher.name, i); | |||||
| 279 | } | |||||
| 280 | if (status) { | |||||
| 281 | ||||||
| 282 | debug_print(mod_cipher, "p computed: %s",if (mod_cipher.on) err_report(err_level_debug, ("%s: " "p computed: %s" "\n"), mod_cipher.name, octet_string_hex_string(buffer, 2*test_case ->plaintext_length_octets)) | |||||
| 283 | octet_string_hex_string(buffer,if (mod_cipher.on) err_report(err_level_debug, ("%s: " "p computed: %s" "\n"), mod_cipher.name, octet_string_hex_string(buffer, 2*test_case ->plaintext_length_octets)) | |||||
| 284 | 2*test_case->plaintext_length_octets))if (mod_cipher.on) err_report(err_level_debug, ("%s: " "p computed: %s" "\n"), mod_cipher.name, octet_string_hex_string(buffer, 2*test_case ->plaintext_length_octets)); | |||||
| 285 | debug_print(mod_cipher, "p expected: %s",if (mod_cipher.on) err_report(err_level_debug, ("%s: " "p expected: %s" "\n"), mod_cipher.name, octet_string_hex_string(test_case-> plaintext, 2*test_case->plaintext_length_octets)) | |||||
| 286 | octet_string_hex_string(test_case->plaintext,if (mod_cipher.on) err_report(err_level_debug, ("%s: " "p expected: %s" "\n"), mod_cipher.name, octet_string_hex_string(test_case-> plaintext, 2*test_case->plaintext_length_octets)) | |||||
| 287 | 2*test_case->plaintext_length_octets))if (mod_cipher.on) err_report(err_level_debug, ("%s: " "p expected: %s" "\n"), mod_cipher.name, octet_string_hex_string(test_case-> plaintext, 2*test_case->plaintext_length_octets)); | |||||
| 288 | ||||||
| 289 | cipher_dealloc(c)(((c)->type)->dealloc(c)); | |||||
| 290 | return err_status_algo_fail; | |||||
| 291 | } | |||||
| 292 | ||||||
| 293 | /* deallocate the cipher */ | |||||
| 294 | status = cipher_dealloc(c)(((c)->type)->dealloc(c)); | |||||
| 295 | if (status) | |||||
| 296 | return status; | |||||
| 297 | ||||||
| 298 | /* | |||||
| 299 | * the cipher passed the test case, so move on to the next test | |||||
| 300 | * case in the list; if NULL, we'l proceed to the next test | |||||
| 301 | */ | |||||
| 302 | test_case = test_case->next_test_case; | |||||
| 303 | ++case_num; | |||||
| 304 | } | |||||
| 305 | ||||||
| 306 | /* now run some random invertibility tests */ | |||||
| 307 | ||||||
| 308 | /* allocate cipher, using paramaters from the first test case */ | |||||
| 309 | test_case = test_data; | |||||
| 310 | status = cipher_type_alloc(ct, &c, test_case->key_length_octets, test_case->tag_length_octets)((ct)->alloc((&c), (test_case->key_length_octets), ( test_case->tag_length_octets))); | |||||
| 311 | if (status) | |||||
| 312 | return status; | |||||
| 313 | ||||||
| 314 | rand_source_init(); | |||||
| 315 | ||||||
| 316 | for (j=0; j < NUM_RAND_TESTS128; j++) { | |||||
| 317 | unsigned length; | |||||
| 318 | int plaintext_len; | |||||
| 319 | uint8_t key[MAX_KEY_LEN64]; | |||||
| 320 | uint8_t iv[MAX_KEY_LEN64]; | |||||
| 321 | ||||||
| 322 | /* choose a length at random (leaving room for IV and padding) */ | |||||
| 323 | length = rand() % (SELF_TEST_BUF_OCTETS128 - 64); | |||||
| 324 | debug_print(mod_cipher, "random plaintext length %d\n", length)if (mod_cipher.on) err_report(err_level_debug, ("%s: " "random plaintext length %d\n" "\n"), mod_cipher.name, length); | |||||
| 325 | status = rand_source_get_octet_string(buffer, length); | |||||
| 326 | if (status) return status; | |||||
| 327 | ||||||
| 328 | debug_print(mod_cipher, "plaintext: %s",if (mod_cipher.on) err_report(err_level_debug, ("%s: " "plaintext: %s" "\n"), mod_cipher.name, octet_string_hex_string(buffer, length )) | |||||
| 329 | octet_string_hex_string(buffer, length))if (mod_cipher.on) err_report(err_level_debug, ("%s: " "plaintext: %s" "\n"), mod_cipher.name, octet_string_hex_string(buffer, length )); | |||||
| 330 | ||||||
| 331 | /* copy plaintext into second buffer */ | |||||
| 332 | for (i=0; (unsigned int)i < length; i++) | |||||
| 333 | buffer2[i] = buffer[i]; | |||||
| 334 | ||||||
| 335 | /* choose a key at random */ | |||||
| 336 | if (test_case->key_length_octets > MAX_KEY_LEN64) | |||||
| 337 | return err_status_cant_check; | |||||
| 338 | status = rand_source_get_octet_string(key, test_case->key_length_octets); | |||||
| 339 | if (status) return status; | |||||
| 340 | ||||||
| 341 | /* chose a random initialization vector */ | |||||
| 342 | status = rand_source_get_octet_string(iv, MAX_KEY_LEN64); | |||||
| 343 | if (status) return status; | |||||
| 344 | ||||||
| 345 | /* initialize cipher */ | |||||
| 346 | status = cipher_init(c, key)(((c)->type)->init(((c)->state), (key), ((c)->key_len ))); | |||||
| 347 | if (status) { | |||||
| 348 | cipher_dealloc(c)(((c)->type)->dealloc(c)); | |||||
| 349 | return status; | |||||
| 350 | } | |||||
| 351 | ||||||
| 352 | /* set initialization vector */ | |||||
| 353 | status = cipher_set_iv(c, test_case->idx, direction_encrypt)((c) ? (((c)->type)->set_iv(((cipher_pointer_t)(c)-> state), (test_case->idx), (direction_encrypt))) : err_status_no_such_op ); | |||||
| 354 | if (status) { | |||||
| 355 | cipher_dealloc(c)(((c)->type)->dealloc(c)); | |||||
| 356 | return status; | |||||
| 357 | } | |||||
| 358 | ||||||
| 359 | if (c->algorithm == AES_128_GCM6 || c->algorithm == AES_256_GCM7) { | |||||
| 360 | /* | |||||
| 361 | * Set the AAD | |||||
| 362 | */ | |||||
| 363 | status = cipher_set_aad(c, test_case->aad,(((c) && (((c)->type)->set_aad)) ? (((c)->type )->set_aad(((c)->state), (test_case->aad), (test_case ->aad_length_octets))) : err_status_no_such_op) | |||||
| 364 | test_case->aad_length_octets)(((c) && (((c)->type)->set_aad)) ? (((c)->type )->set_aad(((c)->state), (test_case->aad), (test_case ->aad_length_octets))) : err_status_no_such_op); | |||||
| 365 | if (status) { | |||||
| 366 | cipher_dealloc(c)(((c)->type)->dealloc(c)); | |||||
| 367 | return status; | |||||
| 368 | } | |||||
| 369 | debug_print(mod_cipher, "AAD: %s",if (mod_cipher.on) err_report(err_level_debug, ("%s: " "AAD: %s" "\n"), mod_cipher.name, octet_string_hex_string(test_case-> aad, test_case->aad_length_octets)) | |||||
| 370 | octet_string_hex_string(test_case->aad,if (mod_cipher.on) err_report(err_level_debug, ("%s: " "AAD: %s" "\n"), mod_cipher.name, octet_string_hex_string(test_case-> aad, test_case->aad_length_octets)) | |||||
| 371 | test_case->aad_length_octets))if (mod_cipher.on) err_report(err_level_debug, ("%s: " "AAD: %s" "\n"), mod_cipher.name, octet_string_hex_string(test_case-> aad, test_case->aad_length_octets)); | |||||
| 372 | } | |||||
| 373 | ||||||
| 374 | /* encrypt buffer with cipher */ | |||||
| 375 | plaintext_len = length; | |||||
| 376 | status = cipher_encrypt(c, buffer, &length)(((c)->type)->encrypt(((c)->state), (buffer), (& length))); | |||||
| 377 | if (status) { | |||||
| 378 | cipher_dealloc(c)(((c)->type)->dealloc(c)); | |||||
| 379 | return status; | |||||
| 380 | } | |||||
| 381 | if (c->algorithm == AES_128_GCM6 || c->algorithm == AES_256_GCM7) { | |||||
| 382 | /* | |||||
| 383 | * Get the GCM tag | |||||
| 384 | */ | |||||
| 385 | status = cipher_get_tag(c, buffer + length, &tag_len)(((c)->type)->get_tag(((c)->state), (buffer + length ), (&tag_len))); | |||||
| 386 | if (status) { | |||||
| 387 | cipher_dealloc(c)(((c)->type)->dealloc(c)); | |||||
| 388 | return status; | |||||
| 389 | } | |||||
| 390 | length += tag_len; | |||||
| 391 | } | |||||
| 392 | debug_print(mod_cipher, "ciphertext: %s",if (mod_cipher.on) err_report(err_level_debug, ("%s: " "ciphertext: %s" "\n"), mod_cipher.name, octet_string_hex_string(buffer, length )) | |||||
| 393 | octet_string_hex_string(buffer, length))if (mod_cipher.on) err_report(err_level_debug, ("%s: " "ciphertext: %s" "\n"), mod_cipher.name, octet_string_hex_string(buffer, length )); | |||||
| 394 | ||||||
| 395 | /* | |||||
| 396 | * re-initialize cipher for decryption, re-set the iv, then | |||||
| 397 | * decrypt the ciphertext | |||||
| 398 | */ | |||||
| 399 | status = cipher_init(c, key)(((c)->type)->init(((c)->state), (key), ((c)->key_len ))); | |||||
| 400 | if (status) { | |||||
| 401 | cipher_dealloc(c)(((c)->type)->dealloc(c)); | |||||
| 402 | return status; | |||||
| 403 | } | |||||
| 404 | status = cipher_set_iv(c, test_case->idx, direction_decrypt)((c) ? (((c)->type)->set_iv(((cipher_pointer_t)(c)-> state), (test_case->idx), (direction_decrypt))) : err_status_no_such_op ); | |||||
| 405 | if (status) { | |||||
| 406 | cipher_dealloc(c)(((c)->type)->dealloc(c)); | |||||
| 407 | return status; | |||||
| 408 | } | |||||
| 409 | if (c->algorithm == AES_128_GCM6 || c->algorithm == AES_256_GCM7) { | |||||
| 410 | /* | |||||
| 411 | * Set the AAD | |||||
| 412 | */ | |||||
| 413 | status = cipher_set_aad(c, test_case->aad,(((c) && (((c)->type)->set_aad)) ? (((c)->type )->set_aad(((c)->state), (test_case->aad), (test_case ->aad_length_octets))) : err_status_no_such_op) | |||||
| 414 | test_case->aad_length_octets)(((c) && (((c)->type)->set_aad)) ? (((c)->type )->set_aad(((c)->state), (test_case->aad), (test_case ->aad_length_octets))) : err_status_no_such_op); | |||||
| 415 | if (status) { | |||||
| 416 | cipher_dealloc(c)(((c)->type)->dealloc(c)); | |||||
| 417 | return status; | |||||
| 418 | } | |||||
| 419 | debug_print(mod_cipher, "AAD: %s",if (mod_cipher.on) err_report(err_level_debug, ("%s: " "AAD: %s" "\n"), mod_cipher.name, octet_string_hex_string(test_case-> aad, test_case->aad_length_octets)) | |||||
| 420 | octet_string_hex_string(test_case->aad,if (mod_cipher.on) err_report(err_level_debug, ("%s: " "AAD: %s" "\n"), mod_cipher.name, octet_string_hex_string(test_case-> aad, test_case->aad_length_octets)) | |||||
| 421 | test_case->aad_length_octets))if (mod_cipher.on) err_report(err_level_debug, ("%s: " "AAD: %s" "\n"), mod_cipher.name, octet_string_hex_string(test_case-> aad, test_case->aad_length_octets)); | |||||
| 422 | } | |||||
| 423 | status = cipher_decrypt(c, buffer, &length)(((c)->type)->decrypt(((c)->state), (buffer), (& length))); | |||||
| 424 | if (status) { | |||||
| 425 | cipher_dealloc(c)(((c)->type)->dealloc(c)); | |||||
| 426 | return status; | |||||
| 427 | } | |||||
| 428 | ||||||
| 429 | debug_print(mod_cipher, "plaintext[2]: %s",if (mod_cipher.on) err_report(err_level_debug, ("%s: " "plaintext[2]: %s" "\n"), mod_cipher.name, octet_string_hex_string(buffer, length )) | |||||
| 430 | octet_string_hex_string(buffer, length))if (mod_cipher.on) err_report(err_level_debug, ("%s: " "plaintext[2]: %s" "\n"), mod_cipher.name, octet_string_hex_string(buffer, length )); | |||||
| 431 | ||||||
| 432 | /* compare the resulting plaintext with the original one */ | |||||
| 433 | if (length != (unsigned int)plaintext_len) { | |||||
| 434 | return err_status_algo_fail; | |||||
| 435 | } | |||||
| 436 | status = err_status_ok; | |||||
| 437 | for (i=0; i < plaintext_len; i++) | |||||
| 438 | if (buffer[i] != buffer2[i]) { | |||||
| 439 | status = err_status_algo_fail; | |||||
| 440 | debug_print(mod_cipher, "random test case %d failed", case_num)if (mod_cipher.on) err_report(err_level_debug, ("%s: " "random test case %d failed" "\n"), mod_cipher.name, case_num); | |||||
| 441 | debug_print(mod_cipher, "(failure at byte %d)", i)if (mod_cipher.on) err_report(err_level_debug, ("%s: " "(failure at byte %d)" "\n"), mod_cipher.name, i); | |||||
| 442 | } | |||||
| 443 | if (status) { | |||||
| 444 | cipher_dealloc(c)(((c)->type)->dealloc(c)); | |||||
| 445 | return err_status_algo_fail; | |||||
| 446 | } | |||||
| 447 | ||||||
| 448 | } | |||||
| 449 | ||||||
| 450 | status = cipher_dealloc(c)(((c)->type)->dealloc(c)); | |||||
| 451 | if (status) | |||||
| 452 | return status; | |||||
| 453 | ||||||
| 454 | return err_status_ok; | |||||
| 455 | } | |||||
| 456 | ||||||
| 457 | ||||||
| 458 | /* | |||||
| 459 | * cipher_type_self_test(ct) performs cipher_type_test on ct's internal | |||||
| 460 | * list of test data. | |||||
| 461 | */ | |||||
| 462 | ||||||
| 463 | err_status_t | |||||
| 464 | cipher_type_self_test(const cipher_type_t *ct) { | |||||
| 465 | return cipher_type_test(ct, ct->test_data); | |||||
| 466 | } | |||||
| 467 | ||||||
| 468 | /* | |||||
| 469 | * cipher_bits_per_second(c, l, t) computes (an estimate of) the | |||||
| 470 | * number of bits that a cipher implementation can encrypt in a second | |||||
| 471 | * | |||||
| 472 | * c is a cipher (which MUST be allocated and initialized already), l | |||||
| 473 | * is the length in octets of the test data to be encrypted, and t is | |||||
| 474 | * the number of trials | |||||
| 475 | * | |||||
| 476 | * if an error is encountered, the value 0 is returned | |||||
| 477 | */ | |||||
| 478 | ||||||
| 479 | uint64_t | |||||
| 480 | cipher_bits_per_second(cipher_t *c, int octets_in_buffer, int num_trials) { | |||||
| 481 | int i; | |||||
| 482 | v128_t nonce; | |||||
| 483 | clock_t timer; | |||||
| 484 | unsigned char *enc_buf; | |||||
| 485 | unsigned int len = octets_in_buffer; | |||||
| 486 | ||||||
| 487 | enc_buf = (unsigned char*) crypto_alloc(octets_in_buffer); | |||||
| 488 | if (enc_buf == NULL((void*)0)) | |||||
| ||||||
| 489 | return 0; /* indicate bad parameters by returning null */ | |||||
| 490 | ||||||
| 491 | /* time repeated trials */ | |||||
| 492 | v128_set_to_zero(&nonce)( (&nonce)->v32[0] = 0, (&nonce)->v32[1] = 0, ( &nonce)->v32[2] = 0, (&nonce)->v32[3] = 0 ); | |||||
| 493 | timer = clock(); | |||||
| 494 | for(i=0; i < num_trials; i++, nonce.v32[3] = i) { | |||||
| 495 | cipher_set_iv(c, &nonce, direction_encrypt)((c) ? (((c)->type)->set_iv(((cipher_pointer_t)(c)-> state), (&nonce), (direction_encrypt))) : err_status_no_such_op ); | |||||
| 496 | cipher_encrypt(c, enc_buf, &len)(((c)->type)->encrypt(((c)->state), (enc_buf), (& len))); | |||||
| ||||||
| 497 | } | |||||
| 498 | timer = clock() - timer; | |||||
| 499 | ||||||
| 500 | crypto_free(enc_buf); | |||||
| 501 | ||||||
| 502 | if (timer == 0) { | |||||
| 503 | /* Too fast! */ | |||||
| 504 | return 0; | |||||
| 505 | } | |||||
| 506 | ||||||
| 507 | return (uint64_t)CLOCKS_PER_SEC1000000l * num_trials * 8 * octets_in_buffer / timer; | |||||
| 508 | } |