mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2025-02-26 15:42:34 +01:00
We used to link both libraries at once, but now that I'm working on TLS, there's nothing left to keep OpenSSL around for when NSS is enabled. Note that this patch causes a couple of places that still assumed OpenSSL to be disabled when NSS is enabled - tor-gencert - pbkdf2
621 lines
20 KiB
C
621 lines
20 KiB
C
/* Copyright (c) 2001-2004, Roger Dingledine.
|
||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||
* Copyright (c) 2007-2018, The Tor Project, Inc. */
|
||
/* See LICENSE for licensing information */
|
||
|
||
#include "orconfig.h"
|
||
#define CRYPTO_S2K_PRIVATE
|
||
#include "core/or/or.h"
|
||
#include "test/test.h"
|
||
#include "lib/crypt_ops/crypto_curve25519.h"
|
||
#include "lib/crypt_ops/crypto_ed25519.h"
|
||
#include "lib/crypt_ops/crypto_s2k.h"
|
||
#include "lib/crypt_ops/crypto_pwbox.h"
|
||
#include "lib/crypt_ops/crypto_rand.h"
|
||
|
||
#if defined(HAVE_LIBSCRYPT_H) && defined(HAVE_LIBSCRYPT_SCRYPT)
|
||
#define HAVE_LIBSCRYPT
|
||
#include <libscrypt.h>
|
||
#endif
|
||
|
||
#ifdef ENABLE_OPENSSL
|
||
#include <openssl/evp.h>
|
||
#endif
|
||
|
||
/** Run unit tests for our secret-to-key passphrase hashing functionality. */
|
||
static void
|
||
test_crypto_s2k_rfc2440(void *arg)
|
||
{
|
||
char buf[29];
|
||
char buf2[29];
|
||
char *buf3 = NULL;
|
||
int i;
|
||
|
||
(void)arg;
|
||
memset(buf, 0, sizeof(buf));
|
||
memset(buf2, 0, sizeof(buf2));
|
||
buf3 = tor_malloc(65536);
|
||
memset(buf3, 0, 65536);
|
||
|
||
secret_to_key_rfc2440(buf+9, 20, "", 0, buf);
|
||
crypto_digest(buf2+9, buf3, 1024);
|
||
tt_mem_op(buf,OP_EQ, buf2, 29);
|
||
|
||
memcpy(buf,"vrbacrda",8);
|
||
memcpy(buf2,"vrbacrda",8);
|
||
buf[8] = 96;
|
||
buf2[8] = 96;
|
||
secret_to_key_rfc2440(buf+9, 20, "12345678", 8, buf);
|
||
for (i = 0; i < 65536; i += 16) {
|
||
memcpy(buf3+i, "vrbacrda12345678", 16);
|
||
}
|
||
crypto_digest(buf2+9, buf3, 65536);
|
||
tt_mem_op(buf,OP_EQ, buf2, 29);
|
||
|
||
done:
|
||
tor_free(buf3);
|
||
}
|
||
|
||
static void
|
||
run_s2k_tests(const unsigned flags, const unsigned type,
|
||
int speclen, const int keylen, int legacy)
|
||
{
|
||
uint8_t buf[S2K_MAXLEN], buf2[S2K_MAXLEN], buf3[S2K_MAXLEN];
|
||
int r;
|
||
size_t sz;
|
||
const char pw1[] = "You can't come in here unless you say swordfish!";
|
||
const char pw2[] = "Now, I give you one more guess.";
|
||
|
||
r = secret_to_key_new(buf, sizeof(buf), &sz,
|
||
pw1, strlen(pw1), flags);
|
||
tt_int_op(r, OP_EQ, S2K_OKAY);
|
||
tt_int_op(buf[0], OP_EQ, type);
|
||
|
||
tt_int_op(sz, OP_EQ, keylen + speclen);
|
||
|
||
if (legacy) {
|
||
memmove(buf, buf+1, sz-1);
|
||
--sz;
|
||
--speclen;
|
||
}
|
||
|
||
tt_int_op(S2K_OKAY, OP_EQ,
|
||
secret_to_key_check(buf, sz, pw1, strlen(pw1)));
|
||
|
||
tt_int_op(S2K_BAD_SECRET, OP_EQ,
|
||
secret_to_key_check(buf, sz, pw2, strlen(pw2)));
|
||
|
||
/* Move key to buf2, and clear it. */
|
||
memset(buf3, 0, sizeof(buf3));
|
||
memcpy(buf2, buf+speclen, keylen);
|
||
memset(buf+speclen, 0, sz - speclen);
|
||
|
||
/* Derivekey should produce the same results. */
|
||
tt_int_op(S2K_OKAY, OP_EQ,
|
||
secret_to_key_derivekey(buf3, keylen, buf, speclen, pw1, strlen(pw1)));
|
||
|
||
tt_mem_op(buf2, OP_EQ, buf3, keylen);
|
||
|
||
/* Derivekey with a longer output should fill the output. */
|
||
memset(buf2, 0, sizeof(buf2));
|
||
tt_int_op(S2K_OKAY, OP_EQ,
|
||
secret_to_key_derivekey(buf2, sizeof(buf2), buf, speclen,
|
||
pw1, strlen(pw1)));
|
||
|
||
tt_mem_op(buf2, OP_NE, buf3, sizeof(buf2));
|
||
|
||
memset(buf3, 0, sizeof(buf3));
|
||
tt_int_op(S2K_OKAY, OP_EQ,
|
||
secret_to_key_derivekey(buf3, sizeof(buf3), buf, speclen,
|
||
pw1, strlen(pw1)));
|
||
tt_mem_op(buf2, OP_EQ, buf3, sizeof(buf3));
|
||
tt_assert(!tor_mem_is_zero((char*)buf2+keylen, sizeof(buf2)-keylen));
|
||
|
||
done:
|
||
;
|
||
}
|
||
|
||
static void
|
||
test_crypto_s2k_general(void *arg)
|
||
{
|
||
const char *which = arg;
|
||
|
||
if (!strcmp(which, "scrypt")) {
|
||
run_s2k_tests(0, 2, 19, 32, 0);
|
||
} else if (!strcmp(which, "scrypt-low")) {
|
||
run_s2k_tests(S2K_FLAG_LOW_MEM, 2, 19, 32, 0);
|
||
} else if (!strcmp(which, "pbkdf2")) {
|
||
run_s2k_tests(S2K_FLAG_USE_PBKDF2, 1, 18, 20, 0);
|
||
} else if (!strcmp(which, "rfc2440")) {
|
||
run_s2k_tests(S2K_FLAG_NO_SCRYPT, 0, 10, 20, 0);
|
||
} else if (!strcmp(which, "rfc2440-legacy")) {
|
||
run_s2k_tests(S2K_FLAG_NO_SCRYPT, 0, 10, 20, 1);
|
||
} else {
|
||
tt_fail();
|
||
}
|
||
}
|
||
|
||
#if defined(HAVE_LIBSCRYPT) && defined(HAVE_EVP_PBE_SCRYPT)
|
||
static void
|
||
test_libscrypt_eq_openssl(void *arg)
|
||
{
|
||
uint8_t buf1[64];
|
||
uint8_t buf2[64];
|
||
|
||
uint64_t N;
|
||
uint32_t r, p;
|
||
uint64_t maxmem = 0; // --> SCRYPT_MAX_MEM in OpenSSL.
|
||
|
||
int libscrypt_retval, openssl_retval;
|
||
|
||
size_t dk_len = 64;
|
||
|
||
(void)arg;
|
||
|
||
memset(buf1,0,64);
|
||
memset(buf2,0,64);
|
||
|
||
/* NOTE: we're using N,r the way OpenSSL and libscrypt define them,
|
||
* not the way draft-josefsson-scrypt-kdf-00.txt define them.
|
||
*/
|
||
N = 16;
|
||
r = 1;
|
||
p = 1;
|
||
|
||
libscrypt_retval =
|
||
libscrypt_scrypt((const uint8_t *)"", 0, (const uint8_t *)"", 0,
|
||
N, r, p, buf1, dk_len);
|
||
openssl_retval =
|
||
EVP_PBE_scrypt((const char *)"", 0, (const unsigned char *)"", 0,
|
||
N, r, p, maxmem, buf2, dk_len);
|
||
|
||
tt_int_op(libscrypt_retval, OP_EQ, 0);
|
||
tt_int_op(openssl_retval, OP_EQ, 1);
|
||
|
||
tt_mem_op(buf1, OP_EQ, buf2, 64);
|
||
|
||
memset(buf1,0,64);
|
||
memset(buf2,0,64);
|
||
|
||
N = 1024;
|
||
r = 8;
|
||
p = 16;
|
||
|
||
libscrypt_retval =
|
||
libscrypt_scrypt((const uint8_t *)"password", strlen("password"),
|
||
(const uint8_t *)"NaCl", strlen("NaCl"),
|
||
N, r, p, buf1, dk_len);
|
||
openssl_retval =
|
||
EVP_PBE_scrypt((const char *)"password", strlen("password"),
|
||
(const unsigned char *)"NaCl", strlen("NaCl"),
|
||
N, r, p, maxmem, buf2, dk_len);
|
||
|
||
tt_int_op(libscrypt_retval, OP_EQ, 0);
|
||
tt_int_op(openssl_retval, OP_EQ, 1);
|
||
|
||
tt_mem_op(buf1, OP_EQ, buf2, 64);
|
||
|
||
memset(buf1,0,64);
|
||
memset(buf2,0,64);
|
||
|
||
N = 16384;
|
||
r = 8;
|
||
p = 1;
|
||
|
||
libscrypt_retval =
|
||
libscrypt_scrypt((const uint8_t *)"pleaseletmein",
|
||
strlen("pleaseletmein"),
|
||
(const uint8_t *)"SodiumChloride",
|
||
strlen("SodiumChloride"),
|
||
N, r, p, buf1, dk_len);
|
||
openssl_retval =
|
||
EVP_PBE_scrypt((const char *)"pleaseletmein",
|
||
strlen("pleaseletmein"),
|
||
(const unsigned char *)"SodiumChloride",
|
||
strlen("SodiumChloride"),
|
||
N, r, p, maxmem, buf2, dk_len);
|
||
|
||
tt_int_op(libscrypt_retval, OP_EQ, 0);
|
||
tt_int_op(openssl_retval, OP_EQ, 1);
|
||
|
||
tt_mem_op(buf1, OP_EQ, buf2, 64);
|
||
|
||
memset(buf1,0,64);
|
||
memset(buf2,0,64);
|
||
|
||
N = 1048576;
|
||
maxmem = 2 * 1024 * 1024 * (uint64_t)1024; // 2 GB
|
||
|
||
libscrypt_retval =
|
||
libscrypt_scrypt((const uint8_t *)"pleaseletmein",
|
||
strlen("pleaseletmein"),
|
||
(const uint8_t *)"SodiumChloride",
|
||
strlen("SodiumChloride"),
|
||
N, r, p, buf1, dk_len);
|
||
openssl_retval =
|
||
EVP_PBE_scrypt((const char *)"pleaseletmein",
|
||
strlen("pleaseletmein"),
|
||
(const unsigned char *)"SodiumChloride",
|
||
strlen("SodiumChloride"),
|
||
N, r, p, maxmem, buf2, dk_len);
|
||
|
||
tt_int_op(libscrypt_retval, OP_EQ, 0);
|
||
tt_int_op(openssl_retval, OP_EQ, 1);
|
||
|
||
tt_mem_op(buf1, OP_EQ, buf2, 64);
|
||
|
||
done:
|
||
return;
|
||
}
|
||
#endif /* defined(HAVE_LIBSCRYPT) && defined(HAVE_EVP_PBE_SCRYPT) */
|
||
|
||
static void
|
||
test_crypto_s2k_errors(void *arg)
|
||
{
|
||
uint8_t buf[S2K_MAXLEN], buf2[S2K_MAXLEN];
|
||
size_t sz;
|
||
|
||
(void)arg;
|
||
|
||
/* Bogus specifiers: simple */
|
||
tt_int_op(S2K_BAD_LEN, OP_EQ,
|
||
secret_to_key_derivekey(buf, sizeof(buf),
|
||
(const uint8_t*)"", 0, "ABC", 3));
|
||
tt_int_op(S2K_BAD_ALGORITHM, OP_EQ,
|
||
secret_to_key_derivekey(buf, sizeof(buf),
|
||
(const uint8_t*)"\x10", 1, "ABC", 3));
|
||
tt_int_op(S2K_BAD_LEN, OP_EQ,
|
||
secret_to_key_derivekey(buf, sizeof(buf),
|
||
(const uint8_t*)"\x01\x02", 2, "ABC", 3));
|
||
|
||
tt_int_op(S2K_BAD_LEN, OP_EQ,
|
||
secret_to_key_check((const uint8_t*)"", 0, "ABC", 3));
|
||
tt_int_op(S2K_BAD_ALGORITHM, OP_EQ,
|
||
secret_to_key_check((const uint8_t*)"\x10", 1, "ABC", 3));
|
||
tt_int_op(S2K_BAD_LEN, OP_EQ,
|
||
secret_to_key_check((const uint8_t*)"\x01\x02", 2, "ABC", 3));
|
||
|
||
/* too long gets "BAD_LEN" too */
|
||
memset(buf, 0, sizeof(buf));
|
||
buf[0] = 2;
|
||
tt_int_op(S2K_BAD_LEN, OP_EQ,
|
||
secret_to_key_derivekey(buf2, sizeof(buf2),
|
||
buf, sizeof(buf), "ABC", 3));
|
||
|
||
/* Truncated output */
|
||
#ifdef HAVE_LIBSCRYPT
|
||
tt_int_op(S2K_TRUNCATED, OP_EQ, secret_to_key_new(buf, 50, &sz,
|
||
"ABC", 3, 0));
|
||
tt_int_op(S2K_TRUNCATED, OP_EQ, secret_to_key_new(buf, 50, &sz,
|
||
"ABC", 3, S2K_FLAG_LOW_MEM));
|
||
#endif /* defined(HAVE_LIBSCRYPT) */
|
||
tt_int_op(S2K_TRUNCATED, OP_EQ, secret_to_key_new(buf, 37, &sz,
|
||
"ABC", 3, S2K_FLAG_USE_PBKDF2));
|
||
tt_int_op(S2K_TRUNCATED, OP_EQ, secret_to_key_new(buf, 29, &sz,
|
||
"ABC", 3, S2K_FLAG_NO_SCRYPT));
|
||
|
||
#ifdef HAVE_LIBSCRYPT
|
||
tt_int_op(S2K_TRUNCATED, OP_EQ, secret_to_key_make_specifier(buf, 18, 0));
|
||
tt_int_op(S2K_TRUNCATED, OP_EQ, secret_to_key_make_specifier(buf, 18,
|
||
S2K_FLAG_LOW_MEM));
|
||
#endif
|
||
tt_int_op(S2K_TRUNCATED, OP_EQ, secret_to_key_make_specifier(buf, 17,
|
||
S2K_FLAG_USE_PBKDF2));
|
||
tt_int_op(S2K_TRUNCATED, OP_EQ, secret_to_key_make_specifier(buf, 9,
|
||
S2K_FLAG_NO_SCRYPT));
|
||
|
||
/* Now try using type-specific bogus specifiers. */
|
||
|
||
/* It's a bad pbkdf2 buffer if it has an iteration count that would overflow
|
||
* int32_t. */
|
||
memset(buf, 0, sizeof(buf));
|
||
buf[0] = 1; /* pbkdf2 */
|
||
buf[17] = 100; /* 1<<100 is much bigger than INT32_MAX */
|
||
tt_int_op(S2K_BAD_PARAMS, OP_EQ,
|
||
secret_to_key_derivekey(buf2, sizeof(buf2),
|
||
buf, 18, "ABC", 3));
|
||
|
||
#ifdef HAVE_LIBSCRYPT
|
||
/* It's a bad scrypt buffer if N would overflow uint64 */
|
||
memset(buf, 0, sizeof(buf));
|
||
buf[0] = 2; /* scrypt */
|
||
buf[17] = 100; /* 1<<100 is much bigger than UINT64_MAX */
|
||
tt_int_op(S2K_BAD_PARAMS, OP_EQ,
|
||
secret_to_key_derivekey(buf2, sizeof(buf2),
|
||
buf, 19, "ABC", 3));
|
||
#endif /* defined(HAVE_LIBSCRYPT) */
|
||
|
||
done:
|
||
;
|
||
}
|
||
|
||
static void
|
||
test_crypto_scrypt_vectors(void *arg)
|
||
{
|
||
char *mem_op_hex_tmp = NULL;
|
||
uint8_t spec[64], out[64];
|
||
|
||
(void)arg;
|
||
#ifndef HAVE_LIBSCRYPT
|
||
if (1)
|
||
tt_skip();
|
||
#endif
|
||
|
||
/* Test vectors from
|
||
http://tools.ietf.org/html/draft-josefsson-scrypt-kdf-00 section 11.
|
||
|
||
Note that the names of 'r' and 'N' are switched in that section. Or
|
||
possibly in libscrypt.
|
||
*/
|
||
|
||
base16_decode((char*)spec, sizeof(spec),
|
||
"0400", 4);
|
||
memset(out, 0x00, sizeof(out));
|
||
tt_int_op(64, OP_EQ,
|
||
secret_to_key_compute_key(out, 64, spec, 2, "", 0, 2));
|
||
test_memeq_hex(out,
|
||
"77d6576238657b203b19ca42c18a0497"
|
||
"f16b4844e3074ae8dfdffa3fede21442"
|
||
"fcd0069ded0948f8326a753a0fc81f17"
|
||
"e8d3e0fb2e0d3628cf35e20c38d18906");
|
||
|
||
base16_decode((char*)spec, sizeof(spec),
|
||
"4e61436c" "0A34", 12);
|
||
memset(out, 0x00, sizeof(out));
|
||
tt_int_op(64, OP_EQ,
|
||
secret_to_key_compute_key(out, 64, spec, 6, "password", 8, 2));
|
||
test_memeq_hex(out,
|
||
"fdbabe1c9d3472007856e7190d01e9fe"
|
||
"7c6ad7cbc8237830e77376634b373162"
|
||
"2eaf30d92e22a3886ff109279d9830da"
|
||
"c727afb94a83ee6d8360cbdfa2cc0640");
|
||
|
||
base16_decode((char*)spec, sizeof(spec),
|
||
"536f6469756d43686c6f72696465" "0e30", 32);
|
||
memset(out, 0x00, sizeof(out));
|
||
tt_int_op(64, OP_EQ,
|
||
secret_to_key_compute_key(out, 64, spec, 16,
|
||
"pleaseletmein", 13, 2));
|
||
test_memeq_hex(out,
|
||
"7023bdcb3afd7348461c06cd81fd38eb"
|
||
"fda8fbba904f8e3ea9b543f6545da1f2"
|
||
"d5432955613f0fcf62d49705242a9af9"
|
||
"e61e85dc0d651e40dfcf017b45575887");
|
||
|
||
base16_decode((char*)spec, sizeof(spec),
|
||
"536f6469756d43686c6f72696465" "1430", 32);
|
||
memset(out, 0x00, sizeof(out));
|
||
tt_int_op(64, OP_EQ,
|
||
secret_to_key_compute_key(out, 64, spec, 16,
|
||
"pleaseletmein", 13, 2));
|
||
test_memeq_hex(out,
|
||
"2101cb9b6a511aaeaddbbe09cf70f881"
|
||
"ec568d574a2ffd4dabe5ee9820adaa47"
|
||
"8e56fd8f4ba5d09ffa1c6d927c40f4c3"
|
||
"37304049e8a952fbcbf45c6fa77a41a4");
|
||
|
||
done:
|
||
tor_free(mem_op_hex_tmp);
|
||
}
|
||
|
||
static void
|
||
test_crypto_pbkdf2_vectors(void *arg)
|
||
{
|
||
char *mem_op_hex_tmp = NULL;
|
||
uint8_t spec[64], out[64];
|
||
(void)arg;
|
||
|
||
/* Test vectors from RFC6070, section 2 */
|
||
base16_decode((char*)spec, sizeof(spec),
|
||
"73616c74" "00" , 10);
|
||
memset(out, 0x00, sizeof(out));
|
||
tt_int_op(20, OP_EQ,
|
||
secret_to_key_compute_key(out, 20, spec, 5, "password", 8, 1));
|
||
test_memeq_hex(out, "0c60c80f961f0e71f3a9b524af6012062fe037a6");
|
||
|
||
base16_decode((char*)spec, sizeof(spec),
|
||
"73616c74" "01" , 10);
|
||
memset(out, 0x00, sizeof(out));
|
||
tt_int_op(20, OP_EQ,
|
||
secret_to_key_compute_key(out, 20, spec, 5, "password", 8, 1));
|
||
test_memeq_hex(out, "ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957");
|
||
|
||
base16_decode((char*)spec, sizeof(spec),
|
||
"73616c74" "0C" , 10);
|
||
memset(out, 0x00, sizeof(out));
|
||
tt_int_op(20, OP_EQ,
|
||
secret_to_key_compute_key(out, 20, spec, 5, "password", 8, 1));
|
||
test_memeq_hex(out, "4b007901b765489abead49d926f721d065a429c1");
|
||
|
||
/* This is the very slow one here. When enabled, it accounts for roughly
|
||
* half the time spent in test-slow. */
|
||
/*
|
||
base16_decode((char*)spec, sizeof(spec),
|
||
"73616c74" "18" , 10);
|
||
memset(out, 0x00, sizeof(out));
|
||
tt_int_op(20, OP_EQ,
|
||
secret_to_key_compute_key(out, 20, spec, 5, "password", 8, 1));
|
||
test_memeq_hex(out, "eefe3d61cd4da4e4e9945b3d6ba2158c2634e984");
|
||
*/
|
||
|
||
base16_decode((char*)spec, sizeof(spec),
|
||
"73616c7453414c5473616c7453414c5473616c745"
|
||
"3414c5473616c7453414c5473616c74" "0C" , 74);
|
||
memset(out, 0x00, sizeof(out));
|
||
tt_int_op(25, OP_EQ,
|
||
secret_to_key_compute_key(out, 25, spec, 37,
|
||
"passwordPASSWORDpassword", 24, 1));
|
||
test_memeq_hex(out, "3d2eec4fe41c849b80c8d83662c0e44a8b291a964cf2f07038");
|
||
|
||
base16_decode((char*)spec, sizeof(spec),
|
||
"7361006c74" "0c" , 12);
|
||
memset(out, 0x00, sizeof(out));
|
||
tt_int_op(16, OP_EQ,
|
||
secret_to_key_compute_key(out, 16, spec, 6, "pass\0word", 9, 1));
|
||
test_memeq_hex(out, "56fa6aa75548099dcc37d7f03425e0c3");
|
||
|
||
done:
|
||
tor_free(mem_op_hex_tmp);
|
||
}
|
||
|
||
static void
|
||
test_crypto_pwbox(void *arg)
|
||
{
|
||
uint8_t *boxed=NULL, *decoded=NULL;
|
||
size_t len, dlen;
|
||
unsigned i;
|
||
const char msg[] = "This bunny reminds you that you still have a "
|
||
"salamander in your sylladex. She is holding the bunny Dave got you. "
|
||
"It’s sort of uncanny how similar they are, aside from the knitted "
|
||
"enhancements. Seriously, what are the odds?? So weird.";
|
||
const char pw[] = "I'm a night owl and a wise bird too";
|
||
|
||
const unsigned flags[] = { 0,
|
||
S2K_FLAG_NO_SCRYPT,
|
||
S2K_FLAG_LOW_MEM,
|
||
S2K_FLAG_NO_SCRYPT|S2K_FLAG_LOW_MEM,
|
||
S2K_FLAG_USE_PBKDF2 };
|
||
(void)arg;
|
||
|
||
for (i = 0; i < ARRAY_LENGTH(flags); ++i) {
|
||
tt_int_op(0, OP_EQ, crypto_pwbox(&boxed, &len,
|
||
(const uint8_t*)msg, strlen(msg),
|
||
pw, strlen(pw), flags[i]));
|
||
tt_assert(boxed);
|
||
tt_assert(len > 128+32);
|
||
|
||
tt_int_op(0, OP_EQ, crypto_unpwbox(&decoded, &dlen, boxed, len,
|
||
pw, strlen(pw)));
|
||
|
||
tt_assert(decoded);
|
||
tt_uint_op(dlen, OP_EQ, strlen(msg));
|
||
tt_mem_op(decoded, OP_EQ, msg, dlen);
|
||
|
||
tor_free(decoded);
|
||
|
||
tt_int_op(UNPWBOX_BAD_SECRET, OP_EQ, crypto_unpwbox(&decoded, &dlen,
|
||
boxed, len,
|
||
pw, strlen(pw)-1));
|
||
boxed[len-1] ^= 1;
|
||
tt_int_op(UNPWBOX_BAD_SECRET, OP_EQ, crypto_unpwbox(&decoded, &dlen,
|
||
boxed, len,
|
||
pw, strlen(pw)));
|
||
boxed[0] = 255;
|
||
tt_int_op(UNPWBOX_CORRUPTED, OP_EQ, crypto_unpwbox(&decoded, &dlen,
|
||
boxed, len,
|
||
pw, strlen(pw)));
|
||
|
||
tor_free(boxed);
|
||
}
|
||
|
||
done:
|
||
tor_free(boxed);
|
||
tor_free(decoded);
|
||
}
|
||
|
||
static void
|
||
test_crypto_ed25519_fuzz_donna(void *arg)
|
||
{
|
||
const unsigned iters = 1024;
|
||
uint8_t msg[1024];
|
||
unsigned i;
|
||
(void)arg;
|
||
|
||
tt_uint_op(iters, OP_EQ, sizeof(msg));
|
||
crypto_rand((char*) msg, sizeof(msg));
|
||
|
||
/* Fuzz Ed25519-donna vs ref10, alternating the implementation used to
|
||
* generate keys/sign per iteration.
|
||
*/
|
||
for (i = 0; i < iters; ++i) {
|
||
const int use_donna = i & 1;
|
||
uint8_t blinding[32];
|
||
curve25519_keypair_t ckp;
|
||
ed25519_keypair_t kp, kp_blind, kp_curve25519;
|
||
ed25519_public_key_t pk, pk_blind, pk_curve25519;
|
||
ed25519_signature_t sig, sig_blind;
|
||
int bit = 0;
|
||
|
||
crypto_rand((char*) blinding, sizeof(blinding));
|
||
|
||
/* Impl. A:
|
||
* 1. Generate a keypair.
|
||
* 2. Blinded the keypair.
|
||
* 3. Sign a message (unblinded).
|
||
* 4. Sign a message (blinded).
|
||
* 5. Generate a curve25519 keypair, and convert it to Ed25519.
|
||
*/
|
||
ed25519_set_impl_params(use_donna);
|
||
tt_int_op(0, OP_EQ, ed25519_keypair_generate(&kp, i&1));
|
||
tt_int_op(0, OP_EQ, ed25519_keypair_blind(&kp_blind, &kp, blinding));
|
||
tt_int_op(0, OP_EQ, ed25519_sign(&sig, msg, i, &kp));
|
||
tt_int_op(0, OP_EQ, ed25519_sign(&sig_blind, msg, i, &kp_blind));
|
||
|
||
tt_int_op(0, OP_EQ, curve25519_keypair_generate(&ckp, i&1));
|
||
tt_int_op(0, OP_EQ, ed25519_keypair_from_curve25519_keypair(
|
||
&kp_curve25519, &bit, &ckp));
|
||
|
||
/* Impl. B:
|
||
* 1. Validate the public key by rederiving it.
|
||
* 2. Validate the blinded public key by rederiving it.
|
||
* 3. Validate the unblinded signature (and test a invalid signature).
|
||
* 4. Validate the blinded signature.
|
||
* 5. Validate the public key (from Curve25519) by rederiving it.
|
||
*/
|
||
ed25519_set_impl_params(!use_donna);
|
||
tt_int_op(0, OP_EQ, ed25519_public_key_generate(&pk, &kp.seckey));
|
||
tt_mem_op(pk.pubkey, OP_EQ, kp.pubkey.pubkey, 32);
|
||
|
||
tt_int_op(0, OP_EQ, ed25519_public_blind(&pk_blind, &kp.pubkey, blinding));
|
||
tt_mem_op(pk_blind.pubkey, OP_EQ, kp_blind.pubkey.pubkey, 32);
|
||
|
||
tt_int_op(0, OP_EQ, ed25519_checksig(&sig, msg, i, &pk));
|
||
sig.sig[0] ^= 15;
|
||
tt_int_op(-1, OP_EQ, ed25519_checksig(&sig, msg, sizeof(msg), &pk));
|
||
|
||
tt_int_op(0, OP_EQ, ed25519_checksig(&sig_blind, msg, i, &pk_blind));
|
||
|
||
tt_int_op(0, OP_EQ, ed25519_public_key_from_curve25519_public_key(
|
||
&pk_curve25519, &ckp.pubkey, bit));
|
||
tt_mem_op(pk_curve25519.pubkey, OP_EQ, kp_curve25519.pubkey.pubkey, 32);
|
||
}
|
||
|
||
done:
|
||
;
|
||
}
|
||
|
||
#define CRYPTO_LEGACY(name) \
|
||
{ #name, test_crypto_ ## name , 0, NULL, NULL }
|
||
|
||
#define ED25519_TEST_ONE(name, fl, which) \
|
||
{ #name "/ed25519_" which, test_crypto_ed25519_ ## name, (fl), \
|
||
&ed25519_test_setup, (void*)which }
|
||
|
||
#define ED25519_TEST(name, fl) \
|
||
ED25519_TEST_ONE(name, (fl), "donna"), \
|
||
ED25519_TEST_ONE(name, (fl), "ref10")
|
||
|
||
struct testcase_t slow_crypto_tests[] = {
|
||
CRYPTO_LEGACY(s2k_rfc2440),
|
||
#ifdef HAVE_LIBSCRYPT
|
||
{ "s2k_scrypt", test_crypto_s2k_general, 0, &passthrough_setup,
|
||
(void*)"scrypt" },
|
||
{ "s2k_scrypt_low", test_crypto_s2k_general, 0, &passthrough_setup,
|
||
(void*)"scrypt-low" },
|
||
#ifdef HAVE_EVP_PBE_SCRYPT
|
||
{ "libscrypt_eq_openssl", test_libscrypt_eq_openssl, 0, NULL, NULL },
|
||
#endif
|
||
#endif /* defined(HAVE_LIBSCRYPT) */
|
||
{ "s2k_pbkdf2", test_crypto_s2k_general, 0, &passthrough_setup,
|
||
(void*)"pbkdf2" },
|
||
{ "s2k_rfc2440_general", test_crypto_s2k_general, 0, &passthrough_setup,
|
||
(void*)"rfc2440" },
|
||
{ "s2k_rfc2440_legacy", test_crypto_s2k_general, 0, &passthrough_setup,
|
||
(void*)"rfc2440-legacy" },
|
||
{ "s2k_errors", test_crypto_s2k_errors, 0, NULL, NULL },
|
||
{ "scrypt_vectors", test_crypto_scrypt_vectors, 0, NULL, NULL },
|
||
{ "pbkdf2_vectors", test_crypto_pbkdf2_vectors, 0, NULL, NULL },
|
||
{ "pwbox", test_crypto_pwbox, 0, NULL, NULL },
|
||
ED25519_TEST(fuzz_donna, TT_FORK),
|
||
END_OF_TESTCASES
|
||
};
|