Line data Source code
1 : /* Copyright (c) 2001-2004, Roger Dingledine.
2 : * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
3 : * Copyright (c) 2007-2021, The Tor Project, Inc. */
4 : /* See LICENSE for licensing information */
5 :
6 : #include "orconfig.h"
7 : #define CRYPTO_S2K_PRIVATE
8 : #include "core/or/or.h"
9 : #include "test/test.h"
10 : #include "lib/crypt_ops/crypto_curve25519.h"
11 : #include "lib/crypt_ops/crypto_ed25519.h"
12 : #include "lib/crypt_ops/crypto_s2k.h"
13 : #include "lib/crypt_ops/crypto_pwbox.h"
14 : #include "lib/crypt_ops/crypto_rand.h"
15 :
16 : #if defined(HAVE_LIBSCRYPT_H) && defined(HAVE_LIBSCRYPT_SCRYPT)
17 : #define HAVE_LIBSCRYPT
18 : #include <libscrypt.h>
19 : #endif
20 :
21 : #ifdef ENABLE_OPENSSL
22 : #include <openssl/evp.h>
23 : #endif
24 :
25 : /** Run unit tests for our secret-to-key passphrase hashing functionality. */
26 : static void
27 1 : test_crypto_s2k_rfc2440(void *arg)
28 : {
29 1 : char buf[29];
30 1 : char buf2[29];
31 1 : char *buf3 = NULL;
32 1 : int i;
33 :
34 1 : (void)arg;
35 1 : memset(buf, 0, sizeof(buf));
36 1 : memset(buf2, 0, sizeof(buf2));
37 1 : buf3 = tor_malloc(65536);
38 1 : memset(buf3, 0, 65536);
39 :
40 1 : secret_to_key_rfc2440(buf+9, 20, "", 0, buf);
41 1 : crypto_digest(buf2+9, buf3, 1024);
42 1 : tt_mem_op(buf,OP_EQ, buf2, 29);
43 :
44 1 : memcpy(buf,"vrbacrda",8);
45 1 : memcpy(buf2,"vrbacrda",8);
46 1 : buf[8] = 96;
47 1 : buf2[8] = 96;
48 1 : secret_to_key_rfc2440(buf+9, 20, "12345678", 8, buf);
49 4098 : for (i = 0; i < 65536; i += 16) {
50 4096 : memcpy(buf3+i, "vrbacrda12345678", 16);
51 : }
52 1 : crypto_digest(buf2+9, buf3, 65536);
53 1 : tt_mem_op(buf,OP_EQ, buf2, 29);
54 :
55 1 : done:
56 1 : tor_free(buf3);
57 1 : }
58 :
59 : static void
60 5 : run_s2k_tests(const unsigned flags, const unsigned type,
61 : int speclen, const int keylen, int legacy)
62 : {
63 5 : uint8_t buf[S2K_MAXLEN], buf2[S2K_MAXLEN], buf3[S2K_MAXLEN];
64 5 : int r;
65 5 : size_t sz;
66 5 : const char pw1[] = "You can't come in here unless you say swordfish!";
67 5 : const char pw2[] = "Now, I give you one more guess.";
68 :
69 5 : r = secret_to_key_new(buf, sizeof(buf), &sz,
70 : pw1, strlen(pw1), flags);
71 5 : tt_int_op(r, OP_EQ, S2K_OKAY);
72 5 : tt_int_op(buf[0], OP_EQ, type);
73 :
74 5 : tt_int_op(sz, OP_EQ, keylen + speclen);
75 :
76 5 : if (legacy) {
77 1 : memmove(buf, buf+1, sz-1);
78 1 : --sz;
79 1 : --speclen;
80 : }
81 :
82 5 : tt_int_op(S2K_OKAY, OP_EQ,
83 : secret_to_key_check(buf, sz, pw1, strlen(pw1)));
84 :
85 5 : tt_int_op(S2K_BAD_SECRET, OP_EQ,
86 : secret_to_key_check(buf, sz, pw2, strlen(pw2)));
87 :
88 : /* Move key to buf2, and clear it. */
89 5 : memset(buf3, 0, sizeof(buf3));
90 5 : memcpy(buf2, buf+speclen, keylen);
91 5 : memset(buf+speclen, 0, sz - speclen);
92 :
93 : /* Derivekey should produce the same results. */
94 5 : tt_int_op(S2K_OKAY, OP_EQ,
95 : secret_to_key_derivekey(buf3, keylen, buf, speclen, pw1, strlen(pw1)));
96 :
97 5 : tt_mem_op(buf2, OP_EQ, buf3, keylen);
98 :
99 : /* Derivekey with a longer output should fill the output. */
100 5 : memset(buf2, 0, sizeof(buf2));
101 5 : tt_int_op(S2K_OKAY, OP_EQ,
102 : secret_to_key_derivekey(buf2, sizeof(buf2), buf, speclen,
103 : pw1, strlen(pw1)));
104 :
105 5 : tt_mem_op(buf2, OP_NE, buf3, sizeof(buf2));
106 :
107 5 : memset(buf3, 0, sizeof(buf3));
108 5 : tt_int_op(S2K_OKAY, OP_EQ,
109 : secret_to_key_derivekey(buf3, sizeof(buf3), buf, speclen,
110 : pw1, strlen(pw1)));
111 5 : tt_mem_op(buf2, OP_EQ, buf3, sizeof(buf3));
112 5 : tt_assert(!fast_mem_is_zero((char*)buf2+keylen, sizeof(buf2)-keylen));
113 :
114 5 : done:
115 5 : ;
116 5 : }
117 :
118 : static void
119 5 : test_crypto_s2k_general(void *arg)
120 : {
121 5 : const char *which = arg;
122 :
123 5 : if (!strcmp(which, "scrypt")) {
124 1 : run_s2k_tests(0, 2, 19, 32, 0);
125 4 : } else if (!strcmp(which, "scrypt-low")) {
126 1 : run_s2k_tests(S2K_FLAG_LOW_MEM, 2, 19, 32, 0);
127 3 : } else if (!strcmp(which, "pbkdf2")) {
128 1 : run_s2k_tests(S2K_FLAG_USE_PBKDF2, 1, 18, 20, 0);
129 2 : } else if (!strcmp(which, "rfc2440")) {
130 1 : run_s2k_tests(S2K_FLAG_NO_SCRYPT, 0, 10, 20, 0);
131 1 : } else if (!strcmp(which, "rfc2440-legacy")) {
132 1 : run_s2k_tests(S2K_FLAG_NO_SCRYPT, 0, 10, 20, 1);
133 : } else {
134 0 : tt_fail();
135 : }
136 5 : }
137 :
138 : #if defined(HAVE_LIBSCRYPT) && defined(HAVE_EVP_PBE_SCRYPT)
139 : static void
140 1 : test_libscrypt_eq_openssl(void *arg)
141 : {
142 1 : uint8_t buf1[64];
143 1 : uint8_t buf2[64];
144 :
145 1 : uint64_t N;
146 1 : uint32_t r, p;
147 1 : uint64_t maxmem = 0; // --> SCRYPT_MAX_MEM in OpenSSL.
148 :
149 1 : int libscrypt_retval, openssl_retval;
150 :
151 1 : size_t dk_len = 64;
152 :
153 1 : (void)arg;
154 :
155 1 : memset(buf1,0,64);
156 1 : memset(buf2,0,64);
157 :
158 : /* NOTE: we're using N,r the way OpenSSL and libscrypt define them,
159 : * not the way draft-josefsson-scrypt-kdf-00.txt define them.
160 : */
161 1 : N = 16;
162 1 : r = 1;
163 1 : p = 1;
164 :
165 1 : libscrypt_retval =
166 1 : libscrypt_scrypt((const uint8_t *)"", 0, (const uint8_t *)"", 0,
167 : N, r, p, buf1, dk_len);
168 1 : openssl_retval =
169 1 : EVP_PBE_scrypt((const char *)"", 0, (const unsigned char *)"", 0,
170 : N, r, p, maxmem, buf2, dk_len);
171 :
172 1 : tt_int_op(libscrypt_retval, OP_EQ, 0);
173 1 : tt_int_op(openssl_retval, OP_EQ, 1);
174 :
175 1 : tt_mem_op(buf1, OP_EQ, buf2, 64);
176 :
177 1 : memset(buf1,0,64);
178 1 : memset(buf2,0,64);
179 :
180 1 : N = 1024;
181 1 : r = 8;
182 1 : p = 16;
183 :
184 1 : libscrypt_retval =
185 1 : libscrypt_scrypt((const uint8_t *)"password", strlen("password"),
186 : (const uint8_t *)"NaCl", strlen("NaCl"),
187 : N, r, p, buf1, dk_len);
188 1 : openssl_retval =
189 1 : EVP_PBE_scrypt((const char *)"password", strlen("password"),
190 : (const unsigned char *)"NaCl", strlen("NaCl"),
191 : N, r, p, maxmem, buf2, dk_len);
192 :
193 1 : tt_int_op(libscrypt_retval, OP_EQ, 0);
194 1 : tt_int_op(openssl_retval, OP_EQ, 1);
195 :
196 1 : tt_mem_op(buf1, OP_EQ, buf2, 64);
197 :
198 1 : memset(buf1,0,64);
199 1 : memset(buf2,0,64);
200 :
201 1 : N = 16384;
202 1 : r = 8;
203 1 : p = 1;
204 :
205 1 : libscrypt_retval =
206 1 : libscrypt_scrypt((const uint8_t *)"pleaseletmein",
207 : strlen("pleaseletmein"),
208 : (const uint8_t *)"SodiumChloride",
209 : strlen("SodiumChloride"),
210 : N, r, p, buf1, dk_len);
211 1 : openssl_retval =
212 1 : EVP_PBE_scrypt((const char *)"pleaseletmein",
213 : strlen("pleaseletmein"),
214 : (const unsigned char *)"SodiumChloride",
215 : strlen("SodiumChloride"),
216 : N, r, p, maxmem, buf2, dk_len);
217 :
218 1 : tt_int_op(libscrypt_retval, OP_EQ, 0);
219 1 : tt_int_op(openssl_retval, OP_EQ, 1);
220 :
221 1 : tt_mem_op(buf1, OP_EQ, buf2, 64);
222 :
223 1 : memset(buf1,0,64);
224 1 : memset(buf2,0,64);
225 :
226 1 : N = 1048576;
227 1 : maxmem = 2 * 1024 * 1024 * (uint64_t)1024; // 2 GB
228 :
229 1 : libscrypt_retval =
230 1 : libscrypt_scrypt((const uint8_t *)"pleaseletmein",
231 : strlen("pleaseletmein"),
232 : (const uint8_t *)"SodiumChloride",
233 : strlen("SodiumChloride"),
234 : N, r, p, buf1, dk_len);
235 1 : openssl_retval =
236 1 : EVP_PBE_scrypt((const char *)"pleaseletmein",
237 : strlen("pleaseletmein"),
238 : (const unsigned char *)"SodiumChloride",
239 : strlen("SodiumChloride"),
240 : N, r, p, maxmem, buf2, dk_len);
241 :
242 1 : tt_int_op(libscrypt_retval, OP_EQ, 0);
243 1 : tt_int_op(openssl_retval, OP_EQ, 1);
244 :
245 1 : tt_mem_op(buf1, OP_EQ, buf2, 64);
246 :
247 1 : done:
248 1 : return;
249 : }
250 : #endif /* defined(HAVE_LIBSCRYPT) && defined(HAVE_EVP_PBE_SCRYPT) */
251 :
252 : static void
253 1 : test_crypto_s2k_errors(void *arg)
254 : {
255 1 : uint8_t buf[S2K_MAXLEN], buf2[S2K_MAXLEN];
256 1 : size_t sz;
257 :
258 1 : (void)arg;
259 :
260 : /* Bogus specifiers: simple */
261 1 : tt_int_op(S2K_BAD_LEN, OP_EQ,
262 : secret_to_key_derivekey(buf, sizeof(buf),
263 : (const uint8_t*)"", 0, "ABC", 3));
264 1 : tt_int_op(S2K_BAD_ALGORITHM, OP_EQ,
265 : secret_to_key_derivekey(buf, sizeof(buf),
266 : (const uint8_t*)"\x10", 1, "ABC", 3));
267 1 : tt_int_op(S2K_BAD_LEN, OP_EQ,
268 : secret_to_key_derivekey(buf, sizeof(buf),
269 : (const uint8_t*)"\x01\x02", 2, "ABC", 3));
270 :
271 1 : tt_int_op(S2K_BAD_LEN, OP_EQ,
272 : secret_to_key_check((const uint8_t*)"", 0, "ABC", 3));
273 1 : tt_int_op(S2K_BAD_ALGORITHM, OP_EQ,
274 : secret_to_key_check((const uint8_t*)"\x10", 1, "ABC", 3));
275 1 : tt_int_op(S2K_BAD_LEN, OP_EQ,
276 : secret_to_key_check((const uint8_t*)"\x01\x02", 2, "ABC", 3));
277 :
278 : /* too long gets "BAD_LEN" too */
279 1 : memset(buf, 0, sizeof(buf));
280 1 : buf[0] = 2;
281 1 : tt_int_op(S2K_BAD_LEN, OP_EQ,
282 : secret_to_key_derivekey(buf2, sizeof(buf2),
283 : buf, sizeof(buf), "ABC", 3));
284 :
285 : /* Truncated output */
286 : #ifdef HAVE_LIBSCRYPT
287 1 : tt_int_op(S2K_TRUNCATED, OP_EQ, secret_to_key_new(buf, 50, &sz,
288 : "ABC", 3, 0));
289 1 : tt_int_op(S2K_TRUNCATED, OP_EQ, secret_to_key_new(buf, 50, &sz,
290 : "ABC", 3, S2K_FLAG_LOW_MEM));
291 : #endif /* defined(HAVE_LIBSCRYPT) */
292 1 : tt_int_op(S2K_TRUNCATED, OP_EQ, secret_to_key_new(buf, 37, &sz,
293 : "ABC", 3, S2K_FLAG_USE_PBKDF2));
294 1 : tt_int_op(S2K_TRUNCATED, OP_EQ, secret_to_key_new(buf, 29, &sz,
295 : "ABC", 3, S2K_FLAG_NO_SCRYPT));
296 :
297 : #ifdef HAVE_LIBSCRYPT
298 1 : tt_int_op(S2K_TRUNCATED, OP_EQ, secret_to_key_make_specifier(buf, 18, 0));
299 1 : tt_int_op(S2K_TRUNCATED, OP_EQ, secret_to_key_make_specifier(buf, 18,
300 : S2K_FLAG_LOW_MEM));
301 : #endif
302 1 : tt_int_op(S2K_TRUNCATED, OP_EQ, secret_to_key_make_specifier(buf, 17,
303 : S2K_FLAG_USE_PBKDF2));
304 1 : tt_int_op(S2K_TRUNCATED, OP_EQ, secret_to_key_make_specifier(buf, 9,
305 : S2K_FLAG_NO_SCRYPT));
306 :
307 : /* Now try using type-specific bogus specifiers. */
308 :
309 : /* It's a bad pbkdf2 buffer if it has an iteration count that would overflow
310 : * int32_t. */
311 1 : memset(buf, 0, sizeof(buf));
312 1 : buf[0] = 1; /* pbkdf2 */
313 1 : buf[17] = 100; /* 1<<100 is much bigger than INT32_MAX */
314 1 : tt_int_op(S2K_BAD_PARAMS, OP_EQ,
315 : secret_to_key_derivekey(buf2, sizeof(buf2),
316 : buf, 18, "ABC", 3));
317 :
318 : #ifdef HAVE_LIBSCRYPT
319 : /* It's a bad scrypt buffer if N would overflow uint64 */
320 1 : memset(buf, 0, sizeof(buf));
321 1 : buf[0] = 2; /* scrypt */
322 1 : buf[17] = 100; /* 1<<100 is much bigger than UINT64_MAX */
323 1 : tt_int_op(S2K_BAD_PARAMS, OP_EQ,
324 : secret_to_key_derivekey(buf2, sizeof(buf2),
325 : buf, 19, "ABC", 3));
326 : #endif /* defined(HAVE_LIBSCRYPT) */
327 :
328 1 : done:
329 1 : ;
330 1 : }
331 :
332 : static void
333 1 : test_crypto_scrypt_vectors(void *arg)
334 : {
335 1 : char *mem_op_hex_tmp = NULL;
336 1 : uint8_t spec[64], out[64];
337 :
338 1 : (void)arg;
339 : #ifndef HAVE_LIBSCRYPT
340 : if (1)
341 : tt_skip();
342 : #endif
343 :
344 : /* Test vectors from
345 : https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-00 section 11.
346 :
347 : Note that the names of 'r' and 'N' are switched in that section. Or
348 : possibly in libscrypt.
349 : */
350 :
351 1 : base16_decode((char*)spec, sizeof(spec),
352 : "0400", 4);
353 1 : memset(out, 0x00, sizeof(out));
354 1 : tt_int_op(64, OP_EQ,
355 : secret_to_key_compute_key(out, 64, spec, 2, "", 0, 2));
356 1 : test_memeq_hex(out,
357 : "77d6576238657b203b19ca42c18a0497"
358 : "f16b4844e3074ae8dfdffa3fede21442"
359 : "fcd0069ded0948f8326a753a0fc81f17"
360 : "e8d3e0fb2e0d3628cf35e20c38d18906");
361 :
362 1 : base16_decode((char*)spec, sizeof(spec),
363 : "4e61436c" "0A34", 12);
364 1 : memset(out, 0x00, sizeof(out));
365 1 : tt_int_op(64, OP_EQ,
366 : secret_to_key_compute_key(out, 64, spec, 6, "password", 8, 2));
367 1 : test_memeq_hex(out,
368 : "fdbabe1c9d3472007856e7190d01e9fe"
369 : "7c6ad7cbc8237830e77376634b373162"
370 : "2eaf30d92e22a3886ff109279d9830da"
371 : "c727afb94a83ee6d8360cbdfa2cc0640");
372 :
373 1 : base16_decode((char*)spec, sizeof(spec),
374 : "536f6469756d43686c6f72696465" "0e30", 32);
375 1 : memset(out, 0x00, sizeof(out));
376 1 : tt_int_op(64, OP_EQ,
377 : secret_to_key_compute_key(out, 64, spec, 16,
378 : "pleaseletmein", 13, 2));
379 1 : test_memeq_hex(out,
380 : "7023bdcb3afd7348461c06cd81fd38eb"
381 : "fda8fbba904f8e3ea9b543f6545da1f2"
382 : "d5432955613f0fcf62d49705242a9af9"
383 : "e61e85dc0d651e40dfcf017b45575887");
384 :
385 1 : base16_decode((char*)spec, sizeof(spec),
386 : "536f6469756d43686c6f72696465" "1430", 32);
387 1 : memset(out, 0x00, sizeof(out));
388 1 : tt_int_op(64, OP_EQ,
389 : secret_to_key_compute_key(out, 64, spec, 16,
390 : "pleaseletmein", 13, 2));
391 1 : test_memeq_hex(out,
392 : "2101cb9b6a511aaeaddbbe09cf70f881"
393 : "ec568d574a2ffd4dabe5ee9820adaa47"
394 : "8e56fd8f4ba5d09ffa1c6d927c40f4c3"
395 : "37304049e8a952fbcbf45c6fa77a41a4");
396 :
397 1 : done:
398 1 : tor_free(mem_op_hex_tmp);
399 1 : }
400 :
401 : static void
402 1 : test_crypto_pbkdf2_vectors(void *arg)
403 : {
404 1 : char *mem_op_hex_tmp = NULL;
405 1 : uint8_t spec[64], out[64];
406 1 : (void)arg;
407 :
408 : /* Test vectors from RFC6070, section 2 */
409 1 : base16_decode((char*)spec, sizeof(spec),
410 : "73616c74" "00" , 10);
411 1 : memset(out, 0x00, sizeof(out));
412 1 : tt_int_op(20, OP_EQ,
413 : secret_to_key_compute_key(out, 20, spec, 5, "password", 8, 1));
414 1 : test_memeq_hex(out, "0c60c80f961f0e71f3a9b524af6012062fe037a6");
415 :
416 1 : base16_decode((char*)spec, sizeof(spec),
417 : "73616c74" "01" , 10);
418 1 : memset(out, 0x00, sizeof(out));
419 1 : tt_int_op(20, OP_EQ,
420 : secret_to_key_compute_key(out, 20, spec, 5, "password", 8, 1));
421 1 : test_memeq_hex(out, "ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957");
422 :
423 1 : base16_decode((char*)spec, sizeof(spec),
424 : "73616c74" "0C" , 10);
425 1 : memset(out, 0x00, sizeof(out));
426 1 : tt_int_op(20, OP_EQ,
427 : secret_to_key_compute_key(out, 20, spec, 5, "password", 8, 1));
428 1 : test_memeq_hex(out, "4b007901b765489abead49d926f721d065a429c1");
429 :
430 : /* This is the very slow one here. When enabled, it accounts for roughly
431 : * half the time spent in test-slow. */
432 : /*
433 : base16_decode((char*)spec, sizeof(spec),
434 : "73616c74" "18" , 10);
435 : memset(out, 0x00, sizeof(out));
436 : tt_int_op(20, OP_EQ,
437 : secret_to_key_compute_key(out, 20, spec, 5, "password", 8, 1));
438 : test_memeq_hex(out, "eefe3d61cd4da4e4e9945b3d6ba2158c2634e984");
439 : */
440 :
441 1 : base16_decode((char*)spec, sizeof(spec),
442 : "73616c7453414c5473616c7453414c5473616c745"
443 : "3414c5473616c7453414c5473616c74" "0C" , 74);
444 1 : memset(out, 0x00, sizeof(out));
445 1 : tt_int_op(25, OP_EQ,
446 : secret_to_key_compute_key(out, 25, spec, 37,
447 : "passwordPASSWORDpassword", 24, 1));
448 1 : test_memeq_hex(out, "3d2eec4fe41c849b80c8d83662c0e44a8b291a964cf2f07038");
449 :
450 1 : base16_decode((char*)spec, sizeof(spec),
451 : "7361006c74" "0c" , 12);
452 1 : memset(out, 0x00, sizeof(out));
453 1 : tt_int_op(16, OP_EQ,
454 : secret_to_key_compute_key(out, 16, spec, 6, "pass\0word", 9, 1));
455 1 : test_memeq_hex(out, "56fa6aa75548099dcc37d7f03425e0c3");
456 :
457 1 : done:
458 1 : tor_free(mem_op_hex_tmp);
459 1 : }
460 :
461 : static void
462 1 : test_crypto_pwbox(void *arg)
463 : {
464 1 : uint8_t *boxed=NULL, *decoded=NULL;
465 1 : size_t len, dlen;
466 1 : unsigned i;
467 1 : const char msg[] = "This bunny reminds you that you still have a "
468 : "salamander in your sylladex. She is holding the bunny Dave got you. "
469 : "It’s sort of uncanny how similar they are, aside from the knitted "
470 : "enhancements. Seriously, what are the odds?? So weird.";
471 1 : const char pw[] = "I'm a night owl and a wise bird too";
472 :
473 1 : const unsigned flags[] = { 0,
474 : S2K_FLAG_NO_SCRYPT,
475 : S2K_FLAG_LOW_MEM,
476 : S2K_FLAG_NO_SCRYPT|S2K_FLAG_LOW_MEM,
477 : S2K_FLAG_USE_PBKDF2 };
478 1 : (void)arg;
479 :
480 6 : for (i = 0; i < ARRAY_LENGTH(flags); ++i) {
481 5 : tt_int_op(0, OP_EQ, crypto_pwbox(&boxed, &len,
482 : (const uint8_t*)msg, strlen(msg),
483 : pw, strlen(pw), flags[i]));
484 5 : tt_assert(boxed);
485 5 : tt_assert(len > 128+32);
486 :
487 5 : tt_int_op(0, OP_EQ, crypto_unpwbox(&decoded, &dlen, boxed, len,
488 : pw, strlen(pw)));
489 :
490 5 : tt_assert(decoded);
491 5 : tt_uint_op(dlen, OP_EQ, strlen(msg));
492 5 : tt_mem_op(decoded, OP_EQ, msg, dlen);
493 :
494 5 : tor_free(decoded);
495 :
496 5 : tt_int_op(UNPWBOX_BAD_SECRET, OP_EQ, crypto_unpwbox(&decoded, &dlen,
497 : boxed, len,
498 : pw, strlen(pw)-1));
499 5 : boxed[len-1] ^= 1;
500 5 : tt_int_op(UNPWBOX_BAD_SECRET, OP_EQ, crypto_unpwbox(&decoded, &dlen,
501 : boxed, len,
502 : pw, strlen(pw)));
503 5 : boxed[0] = 255;
504 5 : tt_int_op(UNPWBOX_CORRUPTED, OP_EQ, crypto_unpwbox(&decoded, &dlen,
505 : boxed, len,
506 : pw, strlen(pw)));
507 :
508 5 : tor_free(boxed);
509 : }
510 :
511 1 : done:
512 1 : tor_free(boxed);
513 1 : tor_free(decoded);
514 1 : }
515 :
516 : static void
517 2 : test_crypto_ed25519_fuzz_donna(void *arg)
518 : {
519 2 : const unsigned iters = 1024;
520 2 : uint8_t msg[1024];
521 2 : unsigned i;
522 2 : (void)arg;
523 :
524 2 : tt_uint_op(iters, OP_EQ, sizeof(msg));
525 2 : crypto_rand((char*) msg, sizeof(msg));
526 :
527 : /* Fuzz Ed25519-donna vs ref10, alternating the implementation used to
528 : * generate keys/sign per iteration.
529 : */
530 2052 : for (i = 0; i < iters; ++i) {
531 2048 : const int use_donna = i & 1;
532 2048 : uint8_t blinding[32];
533 2048 : curve25519_keypair_t ckp;
534 2048 : ed25519_keypair_t kp, kp_blind, kp_curve25519;
535 2048 : ed25519_public_key_t pk, pk_blind, pk_curve25519;
536 2048 : ed25519_signature_t sig, sig_blind;
537 2048 : int bit = 0;
538 :
539 2048 : crypto_rand((char*) blinding, sizeof(blinding));
540 :
541 : /* Impl. A:
542 : * 1. Generate a keypair.
543 : * 2. Blinded the keypair.
544 : * 3. Sign a message (unblinded).
545 : * 4. Sign a message (blinded).
546 : * 5. Generate a curve25519 keypair, and convert it to Ed25519.
547 : */
548 2048 : ed25519_set_impl_params(use_donna);
549 2048 : tt_int_op(0, OP_EQ, ed25519_keypair_generate(&kp, i&1));
550 2048 : tt_int_op(0, OP_EQ, ed25519_keypair_blind(&kp_blind, &kp, blinding));
551 2048 : tt_int_op(0, OP_EQ, ed25519_sign(&sig, msg, i, &kp));
552 2048 : tt_int_op(0, OP_EQ, ed25519_sign(&sig_blind, msg, i, &kp_blind));
553 :
554 2048 : tt_int_op(0, OP_EQ, curve25519_keypair_generate(&ckp, i&1));
555 2048 : tt_int_op(0, OP_EQ, ed25519_keypair_from_curve25519_keypair(
556 : &kp_curve25519, &bit, &ckp));
557 :
558 : /* Impl. B:
559 : * 1. Validate the public key by rederiving it.
560 : * 2. Validate the blinded public key by rederiving it.
561 : * 3. Validate the unblinded signature (and test a invalid signature).
562 : * 4. Validate the blinded signature.
563 : * 5. Validate the public key (from Curve25519) by rederiving it.
564 : */
565 2048 : ed25519_set_impl_params(!use_donna);
566 2048 : tt_int_op(0, OP_EQ, ed25519_public_key_generate(&pk, &kp.seckey));
567 2048 : tt_mem_op(pk.pubkey, OP_EQ, kp.pubkey.pubkey, 32);
568 :
569 2048 : tt_int_op(0, OP_EQ, ed25519_public_blind(&pk_blind, &kp.pubkey, blinding));
570 2048 : tt_mem_op(pk_blind.pubkey, OP_EQ, kp_blind.pubkey.pubkey, 32);
571 :
572 2048 : tt_int_op(0, OP_EQ, ed25519_checksig(&sig, msg, i, &pk));
573 2048 : sig.sig[0] ^= 15;
574 2048 : tt_int_op(-1, OP_EQ, ed25519_checksig(&sig, msg, sizeof(msg), &pk));
575 :
576 2048 : tt_int_op(0, OP_EQ, ed25519_checksig(&sig_blind, msg, i, &pk_blind));
577 :
578 2048 : tt_int_op(0, OP_EQ, ed25519_public_key_from_curve25519_public_key(
579 : &pk_curve25519, &ckp.pubkey, bit));
580 2048 : tt_mem_op(pk_curve25519.pubkey, OP_EQ, kp_curve25519.pubkey.pubkey, 32);
581 : }
582 :
583 2 : done:
584 2 : ;
585 2 : }
586 :
587 : #ifndef COCCI
588 : #define CRYPTO_LEGACY(name) \
589 : { #name, test_crypto_ ## name , 0, NULL, NULL }
590 :
591 : #define ED25519_TEST_ONE(name, fl, which) \
592 : { #name "/ed25519_" which, test_crypto_ed25519_ ## name, (fl), \
593 : &ed25519_test_setup, (void*)which }
594 :
595 : #define ED25519_TEST(name, fl) \
596 : ED25519_TEST_ONE(name, (fl), "donna"), \
597 : ED25519_TEST_ONE(name, (fl), "ref10")
598 : #endif /* !defined(COCCI) */
599 :
600 : struct testcase_t slow_crypto_tests[] = {
601 : CRYPTO_LEGACY(s2k_rfc2440),
602 : #ifdef HAVE_LIBSCRYPT
603 : { "s2k_scrypt", test_crypto_s2k_general, 0, &passthrough_setup,
604 : (void*)"scrypt" },
605 : { "s2k_scrypt_low", test_crypto_s2k_general, 0, &passthrough_setup,
606 : (void*)"scrypt-low" },
607 : #ifdef HAVE_EVP_PBE_SCRYPT
608 : { "libscrypt_eq_openssl", test_libscrypt_eq_openssl, 0, NULL, NULL },
609 : #endif
610 : #endif /* defined(HAVE_LIBSCRYPT) */
611 : { "s2k_pbkdf2", test_crypto_s2k_general, 0, &passthrough_setup,
612 : (void*)"pbkdf2" },
613 : { "s2k_rfc2440_general", test_crypto_s2k_general, 0, &passthrough_setup,
614 : (void*)"rfc2440" },
615 : { "s2k_rfc2440_legacy", test_crypto_s2k_general, 0, &passthrough_setup,
616 : (void*)"rfc2440-legacy" },
617 : { "s2k_errors", test_crypto_s2k_errors, 0, NULL, NULL },
618 : { "scrypt_vectors", test_crypto_scrypt_vectors, 0, NULL, NULL },
619 : { "pbkdf2_vectors", test_crypto_pbkdf2_vectors, 0, NULL, NULL },
620 : { "pwbox", test_crypto_pwbox, 0, NULL, NULL },
621 : ED25519_TEST(fuzz_donna, TT_FORK),
622 : END_OF_TESTCASES
623 : };
|