Branch data Line data Source code
1 : : /**
2 : : * \file lib/cipher_funcs.c
3 : : *
4 : : * \brief Cipher functions used by fwknop
5 : : */
6 : :
7 : : /* Fwknop is developed primarily by the people listed in the file 'AUTHORS'.
8 : : * Copyright (C) 2009-2015 fwknop developers and contributors. For a full
9 : : * list of contributors, see the file 'CREDITS'.
10 : : *
11 : : * License (GNU General Public License):
12 : : *
13 : : * This library is free software; you can redistribute it and/or
14 : : * modify it under the terms of the GNU General Public License
15 : : * as published by the Free Software Foundation; either version 2
16 : : * of the License, or (at your option) any later version.
17 : : *
18 : : * This program is distributed in the hope that it will be useful,
19 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 : : * GNU General Public License for more details.
22 : : *
23 : : * You should have received a copy of the GNU General Public License
24 : : * along with this program; if not, write to the Free Software
25 : : * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
26 : : * USA
27 : : *
28 : : *****************************************************************************
29 : : */
30 : : #include <stdio.h>
31 : : #include <string.h>
32 : :
33 : : #ifdef WIN32
34 : : #include <sys/timeb.h>
35 : : #include <time.h>
36 : : #include <stdlib.h>
37 : : #else
38 : : #include <sys/time.h>
39 : : #endif
40 : :
41 : : #include "fko_common.h"
42 : : #include "cipher_funcs.h"
43 : : #include "digest.h"
44 : :
45 : : #ifndef WIN32
46 : : #ifndef RAND_FILE
47 : : #define RAND_FILE "/dev/urandom"
48 : : #endif
49 : : #endif
50 : :
51 : : #ifdef HAVE_C_UNIT_TESTS /* LCOV_EXCL_START */
52 : : DECLARE_TEST_SUITE(digest_test, "Cipher functions test suite");
53 : : #endif /* LCOV_EXCL_STOP */
54 : :
55 : : /* Get random data.
56 : : */
57 : : void
58 : 801136 : get_random_data(unsigned char *data, const size_t len)
59 : : {
60 : : uint32_t i;
61 : : #ifdef WIN32
62 : : int rnum;
63 : : struct _timeb tb;
64 : :
65 : : _ftime_s(&tb);
66 : :
67 : : srand((uint32_t)(tb.time*1000)+tb.millitm);
68 : :
69 : : for(i=0; i<len; i++)
70 : : {
71 : : rnum = rand();
72 : : *(data+i) = rnum % 0xff;
73 : : }
74 : : #else
75 : : FILE *rfd;
76 : : struct timeval tv;
77 : 801136 : int do_time = 0;
78 : : size_t amt_read;
79 : :
80 : : /* Attempt to read seed data from /dev/urandom. If that does not
81 : : * work, then fall back to a time-based method (less secure, but
82 : : * probably more portable).
83 : : */
84 [ + + ]: 801136 : if((rfd = fopen(RAND_FILE, "r")) == NULL)
85 : : {
86 : : do_time = 1;
87 : : }
88 : : else
89 : : {
90 : : /* Read seed from /dev/urandom
91 : : */
92 : 801128 : amt_read = fread(data, len, 1, rfd);
93 : 801128 : fclose(rfd);
94 : :
95 [ - + ]: 801128 : if (amt_read != 1)
96 : 0 : do_time = 1;
97 : : }
98 : :
99 [ + + ]: 801136 : if (do_time)
100 : : {
101 : : /* Seed based on time (current usecs).
102 : : */
103 : 8 : gettimeofday(&tv, NULL);
104 : 8 : srand(tv.tv_usec);
105 : :
106 [ + + ]: 72 : for(i=0; i<len; i++)
107 : 64 : *(data+i) = rand() % 0xff;
108 : : }
109 : :
110 : : #endif
111 : :
112 : 801136 : }
113 : :
114 : :
115 : : /*** These are Rijndael-specific functions ***/
116 : :
117 : : /* Rijndael function to generate initial salt and initialization vector
118 : : * (iv). This is is done to be compatible with the data produced via OpenSSL
119 : : */
120 : : static void
121 : 1352085 : rij_salt_and_iv(RIJNDAEL_context *ctx, const char *key,
122 : : const int key_len, const unsigned char *data, const int mode_flag)
123 : : {
124 : 1352085 : char pw_buf[RIJNDAEL_MAX_KEYSIZE] = {0};
125 : 1352085 : unsigned char tmp_buf[MD5_DIGEST_LEN+RIJNDAEL_MAX_KEYSIZE+RIJNDAEL_BLOCKSIZE] = {0};
126 : 1352085 : unsigned char kiv_buf[RIJNDAEL_MAX_KEYSIZE+RIJNDAEL_BLOCKSIZE] = {0}; /* Key and IV buffer */
127 : 1352085 : unsigned char md5_buf[MD5_DIGEST_LEN] = {0}; /* Buffer for computed md5 hash */
128 : :
129 : 1352085 : int final_key_len = 0;
130 : 1352085 : size_t kiv_len = 0;
131 : :
132 [ + + ]: 1352085 : if(mode_flag == FKO_ENC_MODE_CBC_LEGACY_IV)
133 : : {
134 : : /* Pad the pw with '0' chars up to the minimum Rijndael key size.
135 : : *
136 : : * This maintains compatibility with the old perl code if absolutely
137 : : * necessary in some scenarios, but is not recommended to use since it
138 : : * breaks compatibility with how OpenSSL implements AES and introduces
139 : : * other problems. This code will be removed altogether in a future
140 : : * version of fwknop.
141 : : */
142 [ + + ]: 2127 : if(key_len < RIJNDAEL_MIN_KEYSIZE)
143 : : {
144 : 2115 : memcpy(pw_buf, key, key_len);
145 : 2115 : memset(pw_buf+key_len, '0', RIJNDAEL_MIN_KEYSIZE - key_len);
146 : : final_key_len = RIJNDAEL_MIN_KEYSIZE;
147 : : }
148 : : else
149 : : {
150 : 12 : memcpy(pw_buf, key, key_len);
151 : 12 : final_key_len = key_len;
152 : : }
153 : : }
154 : : else
155 : : {
156 : 1349958 : memcpy(pw_buf, key, key_len);
157 : 1349958 : final_key_len = key_len;
158 : : }
159 : :
160 : : /* If we are decrypting, data will contain the salt. Otherwise,
161 : : * for encryption, we generate a random salt.
162 : : */
163 [ + + ]: 1352085 : if(data != NULL)
164 : : {
165 : : /* Pull the salt from the data
166 : : */
167 : 551383 : memcpy(ctx->salt, (data+SALT_LEN), SALT_LEN);
168 : : }
169 : : else
170 : : {
171 : : /* Generate a random 8-byte salt.
172 : : */
173 : 800702 : get_random_data(ctx->salt, SALT_LEN);
174 : : }
175 : :
176 : : /* Now generate the key and initialization vector.
177 : : * (again it is the perl Crypt::CBC way, with a touch of
178 : : * fwknop).
179 : : */
180 : 1352085 : memcpy(tmp_buf+MD5_DIGEST_LEN, pw_buf, final_key_len);
181 : 1352085 : memcpy(tmp_buf+MD5_DIGEST_LEN+final_key_len, ctx->salt, SALT_LEN);
182 : :
183 [ + + ]: 5408340 : while(kiv_len < sizeof(kiv_buf))
184 : : {
185 [ + + ]: 4056255 : if(kiv_len == 0)
186 : 1352085 : md5(md5_buf, tmp_buf+MD5_DIGEST_LEN, final_key_len+SALT_LEN);
187 : : else
188 : 2704170 : md5(md5_buf, tmp_buf, MD5_DIGEST_LEN+final_key_len+SALT_LEN);
189 : :
190 : : memcpy(tmp_buf, md5_buf, MD5_DIGEST_LEN);
191 : :
192 : 4056255 : memcpy(kiv_buf + kiv_len, md5_buf, MD5_DIGEST_LEN);
193 : :
194 : 4056255 : kiv_len += MD5_DIGEST_LEN;
195 : : }
196 : :
197 : 1352085 : memcpy(ctx->key, kiv_buf, RIJNDAEL_MAX_KEYSIZE);
198 : 1352085 : memcpy(ctx->iv, kiv_buf+RIJNDAEL_MAX_KEYSIZE, RIJNDAEL_BLOCKSIZE);
199 : 1352085 : }
200 : :
201 : : /* Initialization entry point.
202 : : */
203 : : static void
204 : 1352085 : rijndael_init(RIJNDAEL_context *ctx, const char *key,
205 : : const int key_len, const unsigned char *data,
206 : : int encryption_mode)
207 : : {
208 : :
209 : : /* The default is Rijndael in CBC mode
210 : : */
211 [ + + ]: 1352085 : if(encryption_mode == FKO_ENC_MODE_CBC
212 : 1352085 : || encryption_mode == FKO_ENC_MODE_CBC_LEGACY_IV)
213 : 1351917 : ctx->mode = MODE_CBC;
214 [ + + ]: 168 : else if(encryption_mode == FKO_ENC_MODE_CTR)
215 : 29 : ctx->mode = MODE_CTR;
216 [ + + ]: 139 : else if(encryption_mode == FKO_ENC_MODE_PCBC)
217 : 25 : ctx->mode = MODE_PCBC;
218 [ + + ]: 114 : else if(encryption_mode == FKO_ENC_MODE_OFB)
219 : 29 : ctx->mode = MODE_OFB;
220 [ + + ]: 85 : else if(encryption_mode == FKO_ENC_MODE_CFB)
221 : 29 : ctx->mode = MODE_CFB;
222 [ + + ]: 56 : else if(encryption_mode == FKO_ENC_MODE_ECB)
223 : 31 : ctx->mode = MODE_ECB;
224 : : else /* shouldn't get this far */
225 : 25 : ctx->mode = encryption_mode;
226 : :
227 : : /* Generate the salt and initialization vector.
228 : : */
229 : 1352085 : rij_salt_and_iv(ctx, key, key_len, data, encryption_mode);
230 : :
231 : : /* Intialize our Rijndael context.
232 : : */
233 : 1352085 : rijndael_setup(ctx, RIJNDAEL_MAX_KEYSIZE, ctx->key);
234 : 1352085 : }
235 : :
236 : : /* Take a chunk of data, encrypt it in the same way OpenSSL would
237 : : * (with a default of AES in CBC mode).
238 : : */
239 : : size_t
240 : 800702 : rij_encrypt(unsigned char *in, size_t in_len,
241 : : const char *key, const int key_len,
242 : : unsigned char *out, int encryption_mode)
243 : : {
244 : : RIJNDAEL_context ctx;
245 : : int i, pad_val;
246 : 800702 : unsigned char *ondx = out;
247 : :
248 : 800702 : rijndael_init(&ctx, key, key_len, NULL, encryption_mode);
249 : :
250 : : /* Prepend the salt to the ciphertext...
251 : : */
252 : : memcpy(ondx, "Salted__", SALT_LEN);
253 : 800702 : ondx+=SALT_LEN;
254 : : memcpy(ondx, ctx.salt, SALT_LEN);
255 : 800702 : ondx+=SALT_LEN;
256 : :
257 : : /* Add padding to the original plaintext to ensure that it is a
258 : : * multiple of the Rijndael block size
259 : : */
260 : 800702 : pad_val = RIJNDAEL_BLOCKSIZE - (in_len % RIJNDAEL_BLOCKSIZE);
261 [ + + ]: 7442863 : for (i = (int)in_len; i < ((int)in_len+pad_val); i++)
262 : 6642161 : in[i] = pad_val;
263 : :
264 : 800702 : block_encrypt(&ctx, in, in_len+pad_val, ondx, ctx.iv);
265 : :
266 : 800702 : ondx += in_len+pad_val;
267 : :
268 : 800702 : zero_buf((char *)ctx.key, RIJNDAEL_MAX_KEYSIZE);
269 : 800702 : zero_buf((char *)ctx.iv, RIJNDAEL_BLOCKSIZE);
270 : 800702 : zero_buf((char *)ctx.salt, SALT_LEN);
271 : :
272 : 800702 : return(ondx - out);
273 : : }
274 : :
275 : : /* Decrypt the given data.
276 : : */
277 : : size_t
278 : 551383 : rij_decrypt(unsigned char *in, size_t in_len,
279 : : const char *key, const int key_len,
280 : : unsigned char *out, int encryption_mode)
281 : : {
282 : : RIJNDAEL_context ctx;
283 : 551383 : int i, pad_val, pad_err = 0;
284 : : unsigned char *pad_s;
285 : 551383 : unsigned char *ondx = out;
286 : :
287 [ + - ][ + - ]: 551383 : if(in == NULL || key == NULL || out == NULL)
288 : : return 0;
289 : :
290 : 551383 : rijndael_init(&ctx, key, key_len, in, encryption_mode);
291 : :
292 : : /* Remove the first block since it contains the salt (it was consumed
293 : : * by the rijndael_init() function above).
294 : : */
295 : 551383 : in_len -= RIJNDAEL_BLOCKSIZE;
296 : 551383 : memmove(in, in+RIJNDAEL_BLOCKSIZE, in_len);
297 : :
298 : 551383 : block_decrypt(&ctx, in, in_len, out, ctx.iv);
299 : :
300 : 551383 : ondx += in_len;
301 : :
302 : : /* Find and remove padding.
303 : : */
304 : 551383 : pad_val = *(ondx-1);
305 : :
306 [ + + ]: 551383 : if(pad_val >= 0 && pad_val <= RIJNDAEL_BLOCKSIZE)
307 : : {
308 : 548898 : pad_s = ondx - pad_val;
309 : :
310 [ + + ]: 5124683 : for(i=0; i < (ondx-pad_s); i++)
311 : : {
312 [ + + ]: 4575785 : if(*(pad_s+i) != pad_val)
313 : 1161 : pad_err++;
314 : : }
315 : :
316 [ + + ]: 548898 : if(pad_err == 0)
317 : 548744 : ondx -= pad_val;
318 : : }
319 : :
320 : 551383 : *ondx = '\0';
321 : :
322 : 551383 : zero_buf((char *)ctx.key, RIJNDAEL_MAX_KEYSIZE);
323 : 551383 : zero_buf((char *)ctx.iv, RIJNDAEL_BLOCKSIZE);
324 : 551383 : zero_buf((char *)ctx.salt, SALT_LEN);
325 : :
326 : 551383 : return(ondx - out);
327 : : }
328 : :
329 : : /* See if we need to add the "Salted__" string to the front of the
330 : : * encrypted data.
331 : : */
332 : : int
333 : 772830 : add_salted_str(fko_ctx_t ctx)
334 : : {
335 : : char *tbuf;
336 : :
337 : : #if AFL_FUZZING
338 : : ctx->added_salted_str = 1;
339 : : return(FKO_SUCCESS);
340 : : #endif
341 : :
342 : : /* We only add the base64 encoded salt to data that is already base64
343 : : * encoded
344 : : */
345 [ + - ]: 772830 : if(is_base64((unsigned char *)ctx->encrypted_msg,
346 : 772830 : ctx->encrypted_msg_len) == 0)
347 : : return(FKO_ERROR_INVALID_DATA_ENCODE_NOTBASE64);
348 : :
349 [ + - ]: 772830 : if(constant_runtime_cmp(ctx->encrypted_msg,
350 : : B64_RIJNDAEL_SALT, B64_RIJNDAEL_SALT_STR_LEN) != 0)
351 : : {
352 : : /* We need to realloc space for the salt.
353 : : */
354 : 1545660 : tbuf = realloc(ctx->encrypted_msg, ctx->encrypted_msg_len
355 : 772830 : + B64_RIJNDAEL_SALT_STR_LEN+1);
356 [ + + ]: 772830 : if(tbuf == NULL)
357 : : return(FKO_ERROR_MEMORY_ALLOCATION);
358 : :
359 : 772800 : memmove(tbuf+B64_RIJNDAEL_SALT_STR_LEN, tbuf, ctx->encrypted_msg_len);
360 : :
361 : 772800 : ctx->encrypted_msg = memcpy(tbuf,
362 : : B64_RIJNDAEL_SALT, B64_RIJNDAEL_SALT_STR_LEN);
363 : :
364 : : /* Adjust the encoded msg len for added SALT value and Make sure we
365 : : * are still a properly NULL-terminated string (Ubuntu was one system
366 : : * for which this was an issue).
367 : : */
368 : 772800 : ctx->encrypted_msg_len += B64_RIJNDAEL_SALT_STR_LEN;
369 : 772800 : tbuf[ctx->encrypted_msg_len] = '\0';
370 : :
371 : 772800 : ctx->added_salted_str = 1;
372 : : }
373 : :
374 : : return(FKO_SUCCESS);
375 : : }
376 : :
377 : : /* See if we need to add the "hQ" string to the front of the
378 : : * encrypted data.
379 : : */
380 : : int
381 : 76 : add_gpg_prefix(fko_ctx_t ctx)
382 : : {
383 : : char *tbuf;
384 : :
385 : : /* We only add the base64 encoded salt to data that is already base64
386 : : * encoded
387 : : */
388 [ + - ]: 76 : if(is_base64((unsigned char *)ctx->encrypted_msg,
389 : 76 : ctx->encrypted_msg_len) == 0)
390 : : return(FKO_ERROR_INVALID_DATA_ENCODE_NOTBASE64);
391 : :
392 [ + - ]: 76 : if(constant_runtime_cmp(ctx->encrypted_msg,
393 : : B64_GPG_PREFIX, B64_GPG_PREFIX_STR_LEN) != 0)
394 : : {
395 : : /* We need to realloc space for the prefix.
396 : : */
397 : 152 : tbuf = realloc(ctx->encrypted_msg, ctx->encrypted_msg_len
398 : 76 : + B64_GPG_PREFIX_STR_LEN+1);
399 [ + - ]: 76 : if(tbuf == NULL)
400 : : return(FKO_ERROR_MEMORY_ALLOCATION);
401 : :
402 : 76 : memmove(tbuf+B64_GPG_PREFIX_STR_LEN, tbuf, ctx->encrypted_msg_len);
403 : :
404 : 76 : ctx->encrypted_msg = memcpy(tbuf,
405 : : B64_GPG_PREFIX, B64_GPG_PREFIX_STR_LEN);
406 : :
407 : : /* Adjust the encoded msg len for added SALT value and Make sure we
408 : : * are still a properly NULL-terminated string (Ubuntu was one system
409 : : * for which this was an issue).
410 : : */
411 : 76 : ctx->encrypted_msg_len += B64_GPG_PREFIX_STR_LEN;
412 : 76 : tbuf[ctx->encrypted_msg_len] = '\0';
413 : :
414 : 76 : ctx->added_gpg_prefix = 1;
415 : : }
416 : :
417 : : return(FKO_SUCCESS);
418 : : }
419 : :
420 : : #ifdef HAVE_C_UNIT_TESTS /* LCOV_EXCL_START */
421 : :
422 : :
423 : :
424 : : DECLARE_UTEST(test_aes_ecb_128, "aes ecb 128 test vectors") //http://www.inconteam.com/software-development/41-encryption/55-aes-test-vectors#aes-cbc-128
425 : : {
426 : : RIJNDAEL_context ctx;
427 : : unsigned char in[1024] = {0};
428 : : unsigned char out[1024] = {0};
429 : : unsigned char expected_out1[1024] = {0};
430 : : unsigned char expected_out2[1024] = {0};
431 : : unsigned char expected_out3[1024] = {0};
432 : : unsigned char expected_out4[1024] = {0};
433 : :
434 : : memcpy(expected_out1, "\x3a\xd7\x7b\xb4\x0d\x7a\x36\x60\xa8\x9e\xca\xf3\x24\x66\xef\x97", 16);
435 : : memcpy(expected_out2, "\xf5\xd3\xd5\x85\x03\xb9\x69\x9d\xe7\x85\x89\x5a\x96\xfd\xba\xaf", 16);
436 : : memcpy(expected_out3, "\x43\xb1\xcd\x7f\x59\x8e\xce\x23\x88\x1b\x00\xe3\xed\x03\x06\x88", 16);
437 : : memcpy(expected_out4, "\x7b\x0c\x78\x5e\x27\xe8\xad\x3f\x82\x23\x20\x71\x04\x72\x5d\xd4", 16);
438 : : memcpy(ctx.key, "\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c", 16);
439 : : rijndael_setup(&ctx, 16, ctx.key);
440 : :
441 : : memcpy(in, "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a", 16);
442 : : rijndael_encrypt(&ctx, in, out);
443 : : CU_ASSERT(memcmp(out, expected_out1, 16) == 0);
444 : :
445 : : memcpy(in, "\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51", 16);
446 : : rijndael_encrypt(&ctx, in, out);
447 : : CU_ASSERT(memcmp(out, expected_out2, 16) == 0);
448 : :
449 : : memcpy(in, "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11\xe5\xfb\xc1\x19\x1a\x0a\x52\xef", 16);
450 : : rijndael_encrypt(&ctx, in, out);
451 : : CU_ASSERT(memcmp(out, expected_out3, 16) == 0);
452 : :
453 : : memcpy(in, "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17\xad\x2b\x41\x7b\xe6\x6c\x37\x10", 16);
454 : : rijndael_encrypt(&ctx, in, out);
455 : : CU_ASSERT(memcmp(out, expected_out4, 16) == 0);
456 : :
457 : : }
458 : : DECLARE_UTEST(test_aes_ecb_192, "aes ecb 192 test vectors") //http://www.inconteam.com/software-development/41-encryption/55-aes-test-vectors#aes-cbc-128
459 : : {
460 : : RIJNDAEL_context ctx;
461 : : unsigned char in[1024] = {0};
462 : : unsigned char out[1024] = {0};
463 : : unsigned char expected_out1[1024] = {0};
464 : : unsigned char expected_out2[1024] = {0};
465 : : unsigned char expected_out3[1024] = {0};
466 : : unsigned char expected_out4[1024] = {0};
467 : :
468 : : memcpy(expected_out1, "\xbd\x33\x4f\x1d\x6e\x45\xf2\x5f\xf7\x12\xa2\x14\x57\x1f\xa5\xcc", 16);
469 : : memcpy(expected_out2, "\x97\x41\x04\x84\x6d\x0a\xd3\xad\x77\x34\xec\xb3\xec\xee\x4e\xef", 16);
470 : : memcpy(expected_out3, "\xef\x7a\xfd\x22\x70\xe2\xe6\x0a\xdc\xe0\xba\x2f\xac\xe6\x44\x4e", 16);
471 : : memcpy(expected_out4, "\x9a\x4b\x41\xba\x73\x8d\x6c\x72\xfb\x16\x69\x16\x03\xc1\x8e\x0e", 16);
472 : : memcpy(ctx.key, "\x8e\x73\xb0\xf7\xda\x0e\x64\x52\xc8\x10\xf3\x2b\x80\x90\x79\xe5\x62\xf8\xea\xd2\x52\x2c\x6b\x7b", 24);
473 : : rijndael_setup(&ctx, 24, ctx.key);
474 : :
475 : : memcpy(in, "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a", 16);
476 : : rijndael_encrypt(&ctx, in, out);
477 : : CU_ASSERT(memcmp(out, expected_out1, 16) == 0);
478 : :
479 : : memcpy(in, "\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51", 16);
480 : : rijndael_encrypt(&ctx, in, out);
481 : : CU_ASSERT(memcmp(out, expected_out2, 16) == 0);
482 : :
483 : : memcpy(in, "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11\xe5\xfb\xc1\x19\x1a\x0a\x52\xef", 16);
484 : : rijndael_encrypt(&ctx, in, out);
485 : : CU_ASSERT(memcmp(out, expected_out3, 16) == 0);
486 : :
487 : : memcpy(in, "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17\xad\x2b\x41\x7b\xe6\x6c\x37\x10", 16);
488 : : rijndael_encrypt(&ctx, in, out);
489 : : CU_ASSERT(memcmp(out, expected_out4, 16) == 0);
490 : :
491 : : }
492 : : DECLARE_UTEST(test_aes_ecb_256, "aes ecb 256 test vectors") //http://www.inconteam.com/software-development/41-encryption/55-aes-test-vectors#aes-cbc-128
493 : : {
494 : : RIJNDAEL_context ctx;
495 : : unsigned char in[1024] = {0};
496 : : unsigned char out[1024] = {0};
497 : : unsigned char expected_out1[1024] = {0};
498 : : unsigned char expected_out2[1024] = {0};
499 : : unsigned char expected_out3[1024] = {0};
500 : : unsigned char expected_out4[1024] = {0};
501 : :
502 : : memcpy(expected_out1, "\xf3\xee\xd1\xbd\xb5\xd2\xa0\x3c\x06\x4b\x5a\x7e\x3d\xb1\x81\xf8", 16);
503 : : memcpy(expected_out2, "\x59\x1c\xcb\x10\xd4\x10\xed\x26\xdc\x5b\xa7\x4a\x31\x36\x28\x70", 16);
504 : : memcpy(expected_out3, "\xb6\xed\x21\xb9\x9c\xa6\xf4\xf9\xf1\x53\xe7\xb1\xbe\xaf\xed\x1d", 16);
505 : : memcpy(expected_out4, "\x23\x30\x4b\x7a\x39\xf9\xf3\xff\x06\x7d\x8d\x8f\x9e\x24\xec\xc7", 16);
506 : : memcpy(ctx.key, "\x60\x3d\xeb\x10\x15\xca\x71\xbe\x2b\x73\xae\xf0\x85\x7d\x77\x81\x1f\x35\x2c\x07\x3b\x61\x08\xd7\x2d\x98\x10\xa3\x09\x14\xdf\xf4", 32);
507 : : rijndael_setup(&ctx, 32, ctx.key);
508 : :
509 : : memcpy(in, "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a", 16);
510 : : rijndael_encrypt(&ctx, in, out);
511 : : CU_ASSERT(memcmp(out, expected_out1, 16) == 0);
512 : :
513 : : memcpy(in, "\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51", 16);
514 : : rijndael_encrypt(&ctx, in, out);
515 : : CU_ASSERT(memcmp(out, expected_out2, 16) == 0);
516 : :
517 : : memcpy(in, "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11\xe5\xfb\xc1\x19\x1a\x0a\x52\xef", 16);
518 : : rijndael_encrypt(&ctx, in, out);
519 : : CU_ASSERT(memcmp(out, expected_out3, 16) == 0);
520 : :
521 : : memcpy(in, "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17\xad\x2b\x41\x7b\xe6\x6c\x37\x10", 16);
522 : : rijndael_encrypt(&ctx, in, out);
523 : : CU_ASSERT(memcmp(out, expected_out4, 16) == 0);
524 : :
525 : : }
526 : :
527 : : DECLARE_UTEST(test_aes_cbc_128, "aes cbc 128 test vectors") //http://www.inconteam.com/software-development/41-encryption/55-aes-test-vectors#aes-cbc-128
528 : : { //would like to test rij_encrypt against known test vectors, but the method of generating the key and iv make this impossible.
529 : : RIJNDAEL_context ctx;
530 : : unsigned char in[1024] = {0};
531 : : unsigned char out[1024] = {0};
532 : : unsigned char expected_out1[1024] = {0};
533 : : unsigned char expected_out2[1024] = {0};
534 : : unsigned char expected_out3[1024] = {0};
535 : : unsigned char expected_out4[1024] = {0};
536 : :
537 : : memcpy(ctx.key, "\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c", 16);
538 : : memcpy(expected_out1, "\x76\x49\xab\xac\x81\x19\xb2\x46\xce\xe9\x8e\x9b\x12\xe9\x19\x7d", 16);
539 : : memcpy(expected_out2, "\x50\x86\xcb\x9b\x50\x72\x19\xee\x95\xdb\x11\x3a\x91\x76\x78\xb2", 16);
540 : : memcpy(expected_out3, "\x73\xbe\xd6\xb8\xe3\xc1\x74\x3b\x71\x16\xe6\x9e\x22\x22\x95\x16", 16);
541 : : memcpy(expected_out4, "\x3f\xf1\xca\xa1\x68\x1f\xac\x09\x12\x0e\xca\x30\x75\x86\xe1\xa7", 16);
542 : : ctx.mode = MODE_CBC;
543 : : rijndael_setup(&ctx, 16, ctx.key);
544 : :
545 : : memcpy(ctx.iv, "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", 16);
546 : : memcpy(in, "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a", 16);
547 : : block_encrypt(&ctx, in, 16, out, ctx.iv);
548 : : CU_ASSERT(memcmp(out, expected_out1, 16) == 0);
549 : :
550 : : memcpy(ctx.iv, "\x76\x49\xAB\xAC\x81\x19\xB2\x46\xCE\xE9\x8E\x9B\x12\xE9\x19\x7D", 16);
551 : : memcpy(in, "\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51", 16);
552 : : block_encrypt(&ctx, in, 16, out, ctx.iv);
553 : : CU_ASSERT(memcmp(out, expected_out2, 16) == 0);
554 : :
555 : : memcpy(ctx.iv, "\x50\x86\xCB\x9B\x50\x72\x19\xEE\x95\xDB\x11\x3A\x91\x76\x78\xB2", 16);
556 : : memcpy(in, "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11\xe5\xfb\xc1\x19\x1a\x0a\x52\xef", 16);
557 : : block_encrypt(&ctx, in, 16, out, ctx.iv);
558 : : CU_ASSERT(memcmp(out, expected_out3, 16) == 0);
559 : :
560 : : memcpy(ctx.iv, "\x73\xBE\xD6\xB8\xE3\xC1\x74\x3B\x71\x16\xE6\x9E\x22\x22\x95\x16", 16);
561 : : memcpy(in, "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17\xad\x2b\x41\x7b\xe6\x6c\x37\x10", 16);
562 : : block_encrypt(&ctx, in, 16, out, ctx.iv);
563 : : CU_ASSERT(memcmp(out, expected_out4, 16) == 0);
564 : :
565 : :
566 : : }
567 : :
568 : : DECLARE_UTEST(test_aes_cbc_192, "aes cbc 192 test vectors") //http://www.inconteam.com/software-development/41-encryption/55-aes-test-vectors#aes-cbc-128
569 : : { //would like to test rij_encrypt against known test vectors, but the method of generating the key and iv make this impossible.
570 : : RIJNDAEL_context ctx;
571 : : unsigned char in[1024] = {0};
572 : : unsigned char out[1024] = {0};
573 : : unsigned char expected_out1[1024] = {0};
574 : : unsigned char expected_out2[1024] = {0};
575 : : unsigned char expected_out3[1024] = {0};
576 : : unsigned char expected_out4[1024] = {0};
577 : :
578 : : memcpy(ctx.key, "\x8e\x73\xb0\xf7\xda\x0e\x64\x52\xc8\x10\xf3\x2b\x80\x90\x79\xe5\x62\xf8\xea\xd2\x52\x2c\x6b\x7b", 24);
579 : : memcpy(expected_out1, "\x4f\x02\x1d\xb2\x43\xbc\x63\x3d\x71\x78\x18\x3a\x9f\xa0\x71\xe8", 16);
580 : : memcpy(expected_out2, "\xb4\xd9\xad\xa9\xad\x7d\xed\xf4\xe5\xe7\x38\x76\x3f\x69\x14\x5a", 16);
581 : : memcpy(expected_out3, "\x57\x1b\x24\x20\x12\xfb\x7a\xe0\x7f\xa9\xba\xac\x3d\xf1\x02\xe0", 16);
582 : : memcpy(expected_out4, "\x08\xb0\xe2\x79\x88\x59\x88\x81\xd9\x20\xa9\xe6\x4f\x56\x15\xcd", 16);
583 : : ctx.mode = MODE_CBC;
584 : : rijndael_setup(&ctx, 24, ctx.key);
585 : :
586 : : memcpy(ctx.iv, "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", 16);
587 : : memcpy(in, "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a", 16);
588 : : block_encrypt(&ctx, in, 16, out, ctx.iv);
589 : : CU_ASSERT(memcmp(out, expected_out1, 16) == 0);
590 : :
591 : : memcpy(ctx.iv, out, 16);
592 : : memcpy(in, "\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51", 16);
593 : : block_encrypt(&ctx, in, 16, out, ctx.iv);
594 : : CU_ASSERT(memcmp(out, expected_out2, 16) == 0);
595 : :
596 : : memcpy(ctx.iv, out, 16);
597 : : memcpy(in, "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11\xe5\xfb\xc1\x19\x1a\x0a\x52\xef", 16);
598 : : block_encrypt(&ctx, in, 16, out, ctx.iv);
599 : : CU_ASSERT(memcmp(out, expected_out3, 16) == 0);
600 : :
601 : : memcpy(ctx.iv, out, 16);
602 : : memcpy(in, "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17\xad\x2b\x41\x7b\xe6\x6c\x37\x10", 16);
603 : : block_encrypt(&ctx, in, 16, out, ctx.iv);
604 : : CU_ASSERT(memcmp(out, expected_out4, 16) == 0);
605 : :
606 : :
607 : : }
608 : :
609 : : DECLARE_UTEST(test_aes_cbc_256, "aes cbc 256 test vectors") //http://www.inconteam.com/software-development/41-encryption/55-aes-test-vectors#aes-cbc-128
610 : : { //would like to test rij_encrypt against known test vectors, but the method of generating the key and iv make this impossible.
611 : : RIJNDAEL_context ctx;
612 : : unsigned char in[1024] = {0};
613 : : unsigned char out[1024] = {0};
614 : : unsigned char expected_out1[1024] = {0};
615 : : unsigned char expected_out2[1024] = {0};
616 : : unsigned char expected_out3[1024] = {0};
617 : : unsigned char expected_out4[1024] = {0};
618 : :
619 : : memcpy(ctx.key, "\x60\x3d\xeb\x10\x15\xca\x71\xbe\x2b\x73\xae\xf0\x85\x7d\x77\x81\x1f\x35\x2c\x07\x3b\x61\x08\xd7\x2d\x98\x10\xa3\x09\x14\xdf\xf4", 32);
620 : : memcpy(expected_out1, "\xf5\x8c\x4c\x04\xd6\xe5\xf1\xba\x77\x9e\xab\xfb\x5f\x7b\xfb\xd6", 16);
621 : : memcpy(expected_out2, "\x9c\xfc\x4e\x96\x7e\xdb\x80\x8d\x67\x9f\x77\x7b\xc6\x70\x2c\x7d", 16);
622 : : memcpy(expected_out3, "\x39\xf2\x33\x69\xa9\xd9\xba\xcf\xa5\x30\xe2\x63\x04\x23\x14\x61", 16);
623 : : memcpy(expected_out4, "\xb2\xeb\x05\xe2\xc3\x9b\xe9\xfc\xda\x6c\x19\x07\x8c\x6a\x9d\x1b", 16);
624 : : ctx.mode = MODE_CBC;
625 : : rijndael_setup(&ctx, 32, ctx.key);
626 : :
627 : : memcpy(ctx.iv, "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", 16);
628 : : memcpy(in, "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a", 16);
629 : : block_encrypt(&ctx, in, 16, out, ctx.iv);
630 : : CU_ASSERT(memcmp(out, expected_out1, 16) == 0);
631 : :
632 : : memcpy(ctx.iv, out, 16);
633 : : memcpy(in, "\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51", 16);
634 : : block_encrypt(&ctx, in, 16, out, ctx.iv);
635 : : CU_ASSERT(memcmp(out, expected_out2, 16) == 0);
636 : :
637 : : memcpy(ctx.iv, out, 16);
638 : : memcpy(in, "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11\xe5\xfb\xc1\x19\x1a\x0a\x52\xef", 16);
639 : : block_encrypt(&ctx, in, 16, out, ctx.iv);
640 : : CU_ASSERT(memcmp(out, expected_out3, 16) == 0);
641 : :
642 : : memcpy(ctx.iv, out, 16);
643 : : memcpy(in, "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17\xad\x2b\x41\x7b\xe6\x6c\x37\x10", 16);
644 : : block_encrypt(&ctx, in, 16, out, ctx.iv);
645 : : CU_ASSERT(memcmp(out, expected_out4, 16) == 0);
646 : :
647 : :
648 : : }
649 : :
650 : : int register_ts_aes_test(void)
651 : : {
652 : : ts_init(&TEST_SUITE(digest_test), TEST_SUITE_DESCR(digest_test), NULL, NULL);
653 : : ts_add_utest(&TEST_SUITE(digest_test), UTEST_FCT(test_aes_ecb_128), UTEST_DESCR(test_aes_ecb_128));
654 : : ts_add_utest(&TEST_SUITE(digest_test), UTEST_FCT(test_aes_ecb_192), UTEST_DESCR(test_aes_ecb_192));
655 : : ts_add_utest(&TEST_SUITE(digest_test), UTEST_FCT(test_aes_ecb_256), UTEST_DESCR(test_aes_ecb_256));
656 : : ts_add_utest(&TEST_SUITE(digest_test), UTEST_FCT(test_aes_cbc_128), UTEST_DESCR(test_aes_cbc_128));
657 : : ts_add_utest(&TEST_SUITE(digest_test), UTEST_FCT(test_aes_cbc_192), UTEST_DESCR(test_aes_cbc_192));
658 : : ts_add_utest(&TEST_SUITE(digest_test), UTEST_FCT(test_aes_cbc_256), UTEST_DESCR(test_aes_cbc_256));
659 : :
660 : : return register_ts(&TEST_SUITE(digest_test));
661 : : }
662 : : #endif /* LCOV_EXCL_STOP */
663 : : /***EOF***/
|