Prop210: Refactor connection_get_* to produce lists and counts
[tor.git] / src / test / test_crypto_slow.c
blob853a08d8860b2806280b3be97b3d00adcaa70a27
1 /* Copyright (c) 2001-2004, Roger Dingledine.
2 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
3 * Copyright (c) 2007-2015, The Tor Project, Inc. */
4 /* See LICENSE for licensing information */
6 #include "orconfig.h"
7 #define CRYPTO_S2K_PRIVATE
8 #include "or.h"
9 #include "test.h"
10 #include "crypto_s2k.h"
11 #include "crypto_pwbox.h"
13 #if defined(HAVE_LIBSCRYPT_H)
14 #include <libscrypt.h>
15 #endif
17 #include <openssl/evp.h>
19 /** Run unit tests for our secret-to-key passphrase hashing functionality. */
20 static void
21 test_crypto_s2k_rfc2440(void *arg)
23 char buf[29];
24 char buf2[29];
25 char *buf3 = NULL;
26 int i;
28 (void)arg;
29 memset(buf, 0, sizeof(buf));
30 memset(buf2, 0, sizeof(buf2));
31 buf3 = tor_malloc(65536);
32 memset(buf3, 0, 65536);
34 secret_to_key_rfc2440(buf+9, 20, "", 0, buf);
35 crypto_digest(buf2+9, buf3, 1024);
36 tt_mem_op(buf,OP_EQ, buf2, 29);
38 memcpy(buf,"vrbacrda",8);
39 memcpy(buf2,"vrbacrda",8);
40 buf[8] = 96;
41 buf2[8] = 96;
42 secret_to_key_rfc2440(buf+9, 20, "12345678", 8, buf);
43 for (i = 0; i < 65536; i += 16) {
44 memcpy(buf3+i, "vrbacrda12345678", 16);
46 crypto_digest(buf2+9, buf3, 65536);
47 tt_mem_op(buf,OP_EQ, buf2, 29);
49 done:
50 tor_free(buf3);
53 static void
54 run_s2k_tests(const unsigned flags, const unsigned type,
55 int speclen, const int keylen, int legacy)
57 uint8_t buf[S2K_MAXLEN], buf2[S2K_MAXLEN], buf3[S2K_MAXLEN];
58 int r;
59 size_t sz;
60 const char pw1[] = "You can't come in here unless you say swordfish!";
61 const char pw2[] = "Now, I give you one more guess.";
63 r = secret_to_key_new(buf, sizeof(buf), &sz,
64 pw1, strlen(pw1), flags);
65 tt_int_op(r, OP_EQ, S2K_OKAY);
66 tt_int_op(buf[0], OP_EQ, type);
68 tt_int_op(sz, OP_EQ, keylen + speclen);
70 if (legacy) {
71 memmove(buf, buf+1, sz-1);
72 --sz;
73 --speclen;
76 tt_int_op(S2K_OKAY, OP_EQ,
77 secret_to_key_check(buf, sz, pw1, strlen(pw1)));
79 tt_int_op(S2K_BAD_SECRET, OP_EQ,
80 secret_to_key_check(buf, sz, pw2, strlen(pw2)));
82 /* Move key to buf2, and clear it. */
83 memset(buf3, 0, sizeof(buf3));
84 memcpy(buf2, buf+speclen, keylen);
85 memset(buf+speclen, 0, sz - speclen);
87 /* Derivekey should produce the same results. */
88 tt_int_op(S2K_OKAY, OP_EQ,
89 secret_to_key_derivekey(buf3, keylen, buf, speclen, pw1, strlen(pw1)));
91 tt_mem_op(buf2, OP_EQ, buf3, keylen);
93 /* Derivekey with a longer output should fill the output. */
94 memset(buf2, 0, sizeof(buf2));
95 tt_int_op(S2K_OKAY, OP_EQ,
96 secret_to_key_derivekey(buf2, sizeof(buf2), buf, speclen,
97 pw1, strlen(pw1)));
99 tt_mem_op(buf2, OP_NE, buf3, sizeof(buf2));
101 memset(buf3, 0, sizeof(buf3));
102 tt_int_op(S2K_OKAY, OP_EQ,
103 secret_to_key_derivekey(buf3, sizeof(buf3), buf, speclen,
104 pw1, strlen(pw1)));
105 tt_mem_op(buf2, OP_EQ, buf3, sizeof(buf3));
106 tt_assert(!tor_mem_is_zero((char*)buf2+keylen, sizeof(buf2)-keylen));
108 done:
112 static void
113 test_crypto_s2k_general(void *arg)
115 const char *which = arg;
117 if (!strcmp(which, "scrypt")) {
118 run_s2k_tests(0, 2, 19, 32, 0);
119 } else if (!strcmp(which, "scrypt-low")) {
120 run_s2k_tests(S2K_FLAG_LOW_MEM, 2, 19, 32, 0);
121 } else if (!strcmp(which, "pbkdf2")) {
122 run_s2k_tests(S2K_FLAG_USE_PBKDF2, 1, 18, 20, 0);
123 } else if (!strcmp(which, "rfc2440")) {
124 run_s2k_tests(S2K_FLAG_NO_SCRYPT, 0, 10, 20, 0);
125 } else if (!strcmp(which, "rfc2440-legacy")) {
126 run_s2k_tests(S2K_FLAG_NO_SCRYPT, 0, 10, 20, 1);
127 } else {
128 tt_fail();
132 #if defined(HAVE_LIBSCRYPT_H) && defined(HAVE_EVP_PBE_SCRYPT)
133 static void
134 test_libscrypt_eq_openssl(void *arg)
136 uint8_t buf1[64];
137 uint8_t buf2[64];
139 uint64_t N, r, p;
140 uint64_t maxmem = 0; // --> SCRYPT_MAX_MEM in OpenSSL.
142 int libscrypt_retval, openssl_retval;
144 size_t dk_len = 64;
146 (void)arg;
148 memset(buf1,0,64);
149 memset(buf2,0,64);
151 /* NOTE: we're using N,r the way OpenSSL and libscrypt define them,
152 * not the way draft-josefsson-scrypt-kdf-00.txt define them.
154 N = 16;
155 r = 1;
156 p = 1;
158 libscrypt_retval =
159 libscrypt_scrypt((const uint8_t *)"", 0, (const uint8_t *)"", 0,
160 N, r, p, buf1, dk_len);
161 openssl_retval =
162 EVP_PBE_scrypt((const char *)"", 0, (const unsigned char *)"", 0,
163 N, r, p, maxmem, buf2, dk_len);
165 tt_int_op(libscrypt_retval, ==, 0);
166 tt_int_op(openssl_retval, ==, 1);
168 tt_mem_op(buf1, ==, buf2, 64);
170 memset(buf1,0,64);
171 memset(buf2,0,64);
173 N = 1024;
174 r = 8;
175 p = 16;
177 libscrypt_retval =
178 libscrypt_scrypt((const uint8_t *)"password", strlen("password"),
179 (const uint8_t *)"NaCl", strlen("NaCl"),
180 N, r, p, buf1, dk_len);
181 openssl_retval =
182 EVP_PBE_scrypt((const char *)"password", strlen("password"),
183 (const unsigned char *)"NaCl", strlen("NaCl"),
184 N, r, p, maxmem, buf2, dk_len);
186 tt_int_op(libscrypt_retval, ==, 0);
187 tt_int_op(openssl_retval, ==, 1);
189 tt_mem_op(buf1, ==, buf2, 64);
191 memset(buf1,0,64);
192 memset(buf2,0,64);
194 N = 16384;
195 r = 8;
196 p = 1;
198 libscrypt_retval =
199 libscrypt_scrypt((const uint8_t *)"pleaseletmein",
200 strlen("pleaseletmein"),
201 (const uint8_t *)"SodiumChloride",
202 strlen("SodiumChloride"),
203 N, r, p, buf1, dk_len);
204 openssl_retval =
205 EVP_PBE_scrypt((const char *)"pleaseletmein",
206 strlen("pleaseletmein"),
207 (const unsigned char *)"SodiumChloride",
208 strlen("SodiumChloride"),
209 N, r, p, maxmem, buf2, dk_len);
211 tt_int_op(libscrypt_retval, ==, 0);
212 tt_int_op(openssl_retval, ==, 1);
214 tt_mem_op(buf1, ==, buf2, 64);
216 memset(buf1,0,64);
217 memset(buf2,0,64);
219 N = 1048576;
220 maxmem = 2 * 1024 * 1024 * (uint64_t)1024; // 2 GB
222 libscrypt_retval =
223 libscrypt_scrypt((const uint8_t *)"pleaseletmein",
224 strlen("pleaseletmein"),
225 (const uint8_t *)"SodiumChloride",
226 strlen("SodiumChloride"),
227 N, r, p, buf1, dk_len);
228 openssl_retval =
229 EVP_PBE_scrypt((const char *)"pleaseletmein",
230 strlen("pleaseletmein"),
231 (const unsigned char *)"SodiumChloride",
232 strlen("SodiumChloride"),
233 N, r, p, maxmem, buf2, dk_len);
235 tt_int_op(libscrypt_retval, ==, 0);
236 tt_int_op(openssl_retval, ==, 1);
238 tt_mem_op(buf1, ==, buf2, 64);
240 done:
241 return;
243 #endif
245 static void
246 test_crypto_s2k_errors(void *arg)
248 uint8_t buf[S2K_MAXLEN], buf2[S2K_MAXLEN];
249 size_t sz;
251 (void)arg;
253 /* Bogus specifiers: simple */
254 tt_int_op(S2K_BAD_LEN, OP_EQ,
255 secret_to_key_derivekey(buf, sizeof(buf),
256 (const uint8_t*)"", 0, "ABC", 3));
257 tt_int_op(S2K_BAD_ALGORITHM, OP_EQ,
258 secret_to_key_derivekey(buf, sizeof(buf),
259 (const uint8_t*)"\x10", 1, "ABC", 3));
260 tt_int_op(S2K_BAD_LEN, OP_EQ,
261 secret_to_key_derivekey(buf, sizeof(buf),
262 (const uint8_t*)"\x01\x02", 2, "ABC", 3));
264 tt_int_op(S2K_BAD_LEN, OP_EQ,
265 secret_to_key_check((const uint8_t*)"", 0, "ABC", 3));
266 tt_int_op(S2K_BAD_ALGORITHM, OP_EQ,
267 secret_to_key_check((const uint8_t*)"\x10", 1, "ABC", 3));
268 tt_int_op(S2K_BAD_LEN, OP_EQ,
269 secret_to_key_check((const uint8_t*)"\x01\x02", 2, "ABC", 3));
271 /* too long gets "BAD_LEN" too */
272 memset(buf, 0, sizeof(buf));
273 buf[0] = 2;
274 tt_int_op(S2K_BAD_LEN, OP_EQ,
275 secret_to_key_derivekey(buf2, sizeof(buf2),
276 buf, sizeof(buf), "ABC", 3));
278 /* Truncated output */
279 #ifdef HAVE_LIBSCRYPT_H
280 tt_int_op(S2K_TRUNCATED, OP_EQ, secret_to_key_new(buf, 50, &sz,
281 "ABC", 3, 0));
282 tt_int_op(S2K_TRUNCATED, OP_EQ, secret_to_key_new(buf, 50, &sz,
283 "ABC", 3, S2K_FLAG_LOW_MEM));
284 #endif
285 tt_int_op(S2K_TRUNCATED, OP_EQ, secret_to_key_new(buf, 37, &sz,
286 "ABC", 3, S2K_FLAG_USE_PBKDF2));
287 tt_int_op(S2K_TRUNCATED, OP_EQ, secret_to_key_new(buf, 29, &sz,
288 "ABC", 3, S2K_FLAG_NO_SCRYPT));
290 #ifdef HAVE_LIBSCRYPT_H
291 tt_int_op(S2K_TRUNCATED, OP_EQ, secret_to_key_make_specifier(buf, 18, 0));
292 tt_int_op(S2K_TRUNCATED, OP_EQ, secret_to_key_make_specifier(buf, 18,
293 S2K_FLAG_LOW_MEM));
294 #endif
295 tt_int_op(S2K_TRUNCATED, OP_EQ, secret_to_key_make_specifier(buf, 17,
296 S2K_FLAG_USE_PBKDF2));
297 tt_int_op(S2K_TRUNCATED, OP_EQ, secret_to_key_make_specifier(buf, 9,
298 S2K_FLAG_NO_SCRYPT));
300 /* Now try using type-specific bogus specifiers. */
302 /* It's a bad pbkdf2 buffer if it has an iteration count that would overflow
303 * int32_t. */
304 memset(buf, 0, sizeof(buf));
305 buf[0] = 1; /* pbkdf2 */
306 buf[17] = 100; /* 1<<100 is much bigger than INT32_MAX */
307 tt_int_op(S2K_BAD_PARAMS, OP_EQ,
308 secret_to_key_derivekey(buf2, sizeof(buf2),
309 buf, 18, "ABC", 3));
311 #ifdef HAVE_LIBSCRYPT_H
312 /* It's a bad scrypt buffer if N would overflow uint64 */
313 memset(buf, 0, sizeof(buf));
314 buf[0] = 2; /* scrypt */
315 buf[17] = 100; /* 1<<100 is much bigger than UINT64_MAX */
316 tt_int_op(S2K_BAD_PARAMS, OP_EQ,
317 secret_to_key_derivekey(buf2, sizeof(buf2),
318 buf, 19, "ABC", 3));
319 #endif
321 done:
325 static void
326 test_crypto_scrypt_vectors(void *arg)
328 char *mem_op_hex_tmp = NULL;
329 uint8_t spec[64], out[64];
331 (void)arg;
332 #ifndef HAVE_LIBSCRYPT_H
333 if (1)
334 tt_skip();
335 #endif
337 /* Test vectors from
338 http://tools.ietf.org/html/draft-josefsson-scrypt-kdf-00 section 11.
340 Note that the names of 'r' and 'N' are switched in that section. Or
341 possibly in libscrypt.
344 base16_decode((char*)spec, sizeof(spec),
345 "0400", 4);
346 memset(out, 0x00, sizeof(out));
347 tt_int_op(64, OP_EQ,
348 secret_to_key_compute_key(out, 64, spec, 2, "", 0, 2));
349 test_memeq_hex(out,
350 "77d6576238657b203b19ca42c18a0497"
351 "f16b4844e3074ae8dfdffa3fede21442"
352 "fcd0069ded0948f8326a753a0fc81f17"
353 "e8d3e0fb2e0d3628cf35e20c38d18906");
355 base16_decode((char*)spec, sizeof(spec),
356 "4e61436c" "0A34", 12);
357 memset(out, 0x00, sizeof(out));
358 tt_int_op(64, OP_EQ,
359 secret_to_key_compute_key(out, 64, spec, 6, "password", 8, 2));
360 test_memeq_hex(out,
361 "fdbabe1c9d3472007856e7190d01e9fe"
362 "7c6ad7cbc8237830e77376634b373162"
363 "2eaf30d92e22a3886ff109279d9830da"
364 "c727afb94a83ee6d8360cbdfa2cc0640");
366 base16_decode((char*)spec, sizeof(spec),
367 "536f6469756d43686c6f72696465" "0e30", 32);
368 memset(out, 0x00, sizeof(out));
369 tt_int_op(64, OP_EQ,
370 secret_to_key_compute_key(out, 64, spec, 16,
371 "pleaseletmein", 13, 2));
372 test_memeq_hex(out,
373 "7023bdcb3afd7348461c06cd81fd38eb"
374 "fda8fbba904f8e3ea9b543f6545da1f2"
375 "d5432955613f0fcf62d49705242a9af9"
376 "e61e85dc0d651e40dfcf017b45575887");
378 base16_decode((char*)spec, sizeof(spec),
379 "536f6469756d43686c6f72696465" "1430", 32);
380 memset(out, 0x00, sizeof(out));
381 tt_int_op(64, OP_EQ,
382 secret_to_key_compute_key(out, 64, spec, 16,
383 "pleaseletmein", 13, 2));
384 test_memeq_hex(out,
385 "2101cb9b6a511aaeaddbbe09cf70f881"
386 "ec568d574a2ffd4dabe5ee9820adaa47"
387 "8e56fd8f4ba5d09ffa1c6d927c40f4c3"
388 "37304049e8a952fbcbf45c6fa77a41a4");
390 done:
391 tor_free(mem_op_hex_tmp);
394 static void
395 test_crypto_pbkdf2_vectors(void *arg)
397 char *mem_op_hex_tmp = NULL;
398 uint8_t spec[64], out[64];
399 (void)arg;
401 /* Test vectors from RFC6070, section 2 */
402 base16_decode((char*)spec, sizeof(spec),
403 "73616c74" "00" , 10);
404 memset(out, 0x00, sizeof(out));
405 tt_int_op(20, OP_EQ,
406 secret_to_key_compute_key(out, 20, spec, 5, "password", 8, 1));
407 test_memeq_hex(out, "0c60c80f961f0e71f3a9b524af6012062fe037a6");
409 base16_decode((char*)spec, sizeof(spec),
410 "73616c74" "01" , 10);
411 memset(out, 0x00, sizeof(out));
412 tt_int_op(20, OP_EQ,
413 secret_to_key_compute_key(out, 20, spec, 5, "password", 8, 1));
414 test_memeq_hex(out, "ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957");
416 base16_decode((char*)spec, sizeof(spec),
417 "73616c74" "0C" , 10);
418 memset(out, 0x00, sizeof(out));
419 tt_int_op(20, OP_EQ,
420 secret_to_key_compute_key(out, 20, spec, 5, "password", 8, 1));
421 test_memeq_hex(out, "4b007901b765489abead49d926f721d065a429c1");
423 base16_decode((char*)spec, sizeof(spec),
424 "73616c74" "18" , 10);
425 memset(out, 0x00, sizeof(out));
426 tt_int_op(20, OP_EQ,
427 secret_to_key_compute_key(out, 20, spec, 5, "password", 8, 1));
428 test_memeq_hex(out, "eefe3d61cd4da4e4e9945b3d6ba2158c2634e984");
430 base16_decode((char*)spec, sizeof(spec),
431 "73616c7453414c5473616c7453414c5473616c745"
432 "3414c5473616c7453414c5473616c74" "0C" , 74);
433 memset(out, 0x00, sizeof(out));
434 tt_int_op(25, OP_EQ,
435 secret_to_key_compute_key(out, 25, spec, 37,
436 "passwordPASSWORDpassword", 24, 1));
437 test_memeq_hex(out, "3d2eec4fe41c849b80c8d83662c0e44a8b291a964cf2f07038");
439 base16_decode((char*)spec, sizeof(spec),
440 "7361006c74" "0c" , 12);
441 memset(out, 0x00, sizeof(out));
442 tt_int_op(16, OP_EQ,
443 secret_to_key_compute_key(out, 16, spec, 6, "pass\0word", 9, 1));
444 test_memeq_hex(out, "56fa6aa75548099dcc37d7f03425e0c3");
446 done:
447 tor_free(mem_op_hex_tmp);
450 static void
451 test_crypto_pwbox(void *arg)
453 uint8_t *boxed=NULL, *decoded=NULL;
454 size_t len, dlen;
455 unsigned i;
456 const char msg[] = "This bunny reminds you that you still have a "
457 "salamander in your sylladex. She is holding the bunny Dave got you. "
458 "It’s sort of uncanny how similar they are, aside from the knitted "
459 "enhancements. Seriously, what are the odds?? So weird.";
460 const char pw[] = "I'm a night owl and a wise bird too";
462 const unsigned flags[] = { 0,
463 S2K_FLAG_NO_SCRYPT,
464 S2K_FLAG_LOW_MEM,
465 S2K_FLAG_NO_SCRYPT|S2K_FLAG_LOW_MEM,
466 S2K_FLAG_USE_PBKDF2 };
467 (void)arg;
469 for (i = 0; i < ARRAY_LENGTH(flags); ++i) {
470 tt_int_op(0, OP_EQ, crypto_pwbox(&boxed, &len,
471 (const uint8_t*)msg, strlen(msg),
472 pw, strlen(pw), flags[i]));
473 tt_assert(boxed);
474 tt_assert(len > 128+32);
476 tt_int_op(0, OP_EQ, crypto_unpwbox(&decoded, &dlen, boxed, len,
477 pw, strlen(pw)));
479 tt_assert(decoded);
480 tt_uint_op(dlen, OP_EQ, strlen(msg));
481 tt_mem_op(decoded, OP_EQ, msg, dlen);
483 tor_free(decoded);
485 tt_int_op(UNPWBOX_BAD_SECRET, OP_EQ, crypto_unpwbox(&decoded, &dlen,
486 boxed, len,
487 pw, strlen(pw)-1));
488 boxed[len-1] ^= 1;
489 tt_int_op(UNPWBOX_BAD_SECRET, OP_EQ, crypto_unpwbox(&decoded, &dlen,
490 boxed, len,
491 pw, strlen(pw)));
492 boxed[0] = 255;
493 tt_int_op(UNPWBOX_CORRUPTED, OP_EQ, crypto_unpwbox(&decoded, &dlen,
494 boxed, len,
495 pw, strlen(pw)));
497 tor_free(boxed);
500 done:
501 tor_free(boxed);
502 tor_free(decoded);
505 #define CRYPTO_LEGACY(name) \
506 { #name, test_crypto_ ## name , 0, NULL, NULL }
508 struct testcase_t slow_crypto_tests[] = {
509 CRYPTO_LEGACY(s2k_rfc2440),
510 #ifdef HAVE_LIBSCRYPT_H
511 { "s2k_scrypt", test_crypto_s2k_general, 0, &passthrough_setup,
512 (void*)"scrypt" },
513 { "s2k_scrypt_low", test_crypto_s2k_general, 0, &passthrough_setup,
514 (void*)"scrypt-low" },
515 #ifdef HAVE_EVP_PBE_SCRYPT
516 { "libscrypt_eq_openssl", test_libscrypt_eq_openssl, 0, NULL, NULL },
517 #endif
518 #endif
519 { "s2k_pbkdf2", test_crypto_s2k_general, 0, &passthrough_setup,
520 (void*)"pbkdf2" },
521 { "s2k_rfc2440_general", test_crypto_s2k_general, 0, &passthrough_setup,
522 (void*)"rfc2440" },
523 { "s2k_rfc2440_legacy", test_crypto_s2k_general, 0, &passthrough_setup,
524 (void*)"rfc2440-legacy" },
525 { "s2k_errors", test_crypto_s2k_errors, 0, NULL, NULL },
526 { "scrypt_vectors", test_crypto_scrypt_vectors, 0, NULL, NULL },
527 { "pbkdf2_vectors", test_crypto_pbkdf2_vectors, 0, NULL, NULL },
528 { "pwbox", test_crypto_pwbox, 0, NULL, NULL },
529 END_OF_TESTCASES