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 | } |