summaryrefslogtreecommitdiff
path: root/src/test/test_crypto.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/test_crypto.c')
-rw-r--r--src/test/test_crypto.c538
1 files changed, 375 insertions, 163 deletions
diff --git a/src/test/test_crypto.c b/src/test/test_crypto.c
index 8fd9ca7671..fa79f4cc47 100644
--- a/src/test/test_crypto.c
+++ b/src/test/test_crypto.c
@@ -1,22 +1,38 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2016, The Tor Project, Inc. */
+ * Copyright (c) 2007-2019, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
#define CRYPTO_CURVE25519_PRIVATE
-#define CRYPTO_PRIVATE
-#include "or.h"
-#include "test.h"
-#include "aes.h"
-#include "util.h"
+#define CRYPTO_RAND_PRIVATE
+#include "core/or/or.h"
+#include "test/test.h"
+#include "lib/crypt_ops/aes.h"
#include "siphash.h"
-#include "crypto_curve25519.h"
-#include "crypto_ed25519.h"
+#include "lib/crypt_ops/crypto_curve25519.h"
+#include "lib/crypt_ops/crypto_dh.h"
+#include "lib/crypt_ops/crypto_ed25519.h"
+#include "lib/crypt_ops/crypto_format.h"
+#include "lib/crypt_ops/crypto_hkdf.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "lib/crypt_ops/crypto_init.h"
#include "ed25519_vectors.inc"
+#include "test/log_test_helpers.h"
-#include <openssl/evp.h>
-#include <openssl/rand.h>
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#if defined(ENABLE_OPENSSL)
+#include "lib/crypt_ops/compat_openssl.h"
+DISABLE_GCC_WARNING(redundant-decls)
+#include <openssl/dh.h>
+ENABLE_GCC_WARNING(redundant-decls)
+#endif
/** Run unit tests for Diffie-Hellman functionality. */
static void
@@ -25,38 +41,45 @@ test_crypto_dh(void *arg)
crypto_dh_t *dh1 = crypto_dh_new(DH_TYPE_CIRCUIT);
crypto_dh_t *dh1_dup = NULL;
crypto_dh_t *dh2 = crypto_dh_new(DH_TYPE_CIRCUIT);
- char p1[DH_BYTES];
- char p2[DH_BYTES];
- char s1[DH_BYTES];
- char s2[DH_BYTES];
+ char p1[DH1024_KEY_LEN];
+ char p2[DH1024_KEY_LEN];
+ char s1[DH1024_KEY_LEN];
+ char s2[DH1024_KEY_LEN];
ssize_t s1len, s2len;
+#ifdef ENABLE_OPENSSL
+ crypto_dh_t *dh3 = NULL;
+ DH *dh4 = NULL;
+ BIGNUM *pubkey_tmp = NULL;
+#endif
(void)arg;
- tt_int_op(crypto_dh_get_bytes(dh1),OP_EQ, DH_BYTES);
- tt_int_op(crypto_dh_get_bytes(dh2),OP_EQ, DH_BYTES);
+ tt_int_op(crypto_dh_get_bytes(dh1),OP_EQ, DH1024_KEY_LEN);
+ tt_int_op(crypto_dh_get_bytes(dh2),OP_EQ, DH1024_KEY_LEN);
- memset(p1, 0, DH_BYTES);
- memset(p2, 0, DH_BYTES);
- tt_mem_op(p1,OP_EQ, p2, DH_BYTES);
+ memset(p1, 0, DH1024_KEY_LEN);
+ memset(p2, 0, DH1024_KEY_LEN);
+ tt_mem_op(p1,OP_EQ, p2, DH1024_KEY_LEN);
tt_int_op(-1, OP_EQ, crypto_dh_get_public(dh1, p1, 6)); /* too short */
- tt_assert(! crypto_dh_get_public(dh1, p1, DH_BYTES));
- tt_mem_op(p1,OP_NE, p2, DH_BYTES);
- tt_assert(! crypto_dh_get_public(dh2, p2, DH_BYTES));
- tt_mem_op(p1,OP_NE, p2, DH_BYTES);
+ tt_assert(! crypto_dh_get_public(dh1, p1, DH1024_KEY_LEN));
+ tt_mem_op(p1,OP_NE, p2, DH1024_KEY_LEN);
+ tt_assert(! crypto_dh_get_public(dh2, p2, DH1024_KEY_LEN));
+ tt_mem_op(p1,OP_NE, p2, DH1024_KEY_LEN);
- memset(s1, 0, DH_BYTES);
- memset(s2, 0xFF, DH_BYTES);
- s1len = crypto_dh_compute_secret(LOG_WARN, dh1, p2, DH_BYTES, s1, 50);
- s2len = crypto_dh_compute_secret(LOG_WARN, dh2, p1, DH_BYTES, s2, 50);
+ memset(s1, 0, DH1024_KEY_LEN);
+ memset(s2, 0xFF, DH1024_KEY_LEN);
+ s1len = crypto_dh_compute_secret(LOG_WARN, dh1, p2, DH1024_KEY_LEN, s1, 50);
+ s2len = crypto_dh_compute_secret(LOG_WARN, dh2, p1, DH1024_KEY_LEN, s2, 50);
tt_assert(s1len > 0);
tt_int_op(s1len,OP_EQ, s2len);
tt_mem_op(s1,OP_EQ, s2, s1len);
/* test dh_dup; make sure it works the same. */
dh1_dup = crypto_dh_dup(dh1);
- s1len = crypto_dh_compute_secret(LOG_WARN, dh1_dup, p2, DH_BYTES, s1, 50);
+ s1len = crypto_dh_compute_secret(LOG_WARN, dh1_dup, p2, DH1024_KEY_LEN,
+ s1, 50);
+ tt_i64_op(s1len, OP_GE, 0);
tt_mem_op(s1,OP_EQ, s2, s1len);
{
@@ -69,18 +92,24 @@ test_crypto_dh(void *arg)
s1len = crypto_dh_compute_secret(LOG_WARN, dh1, "\x00", 1, s1, 50);
tt_int_op(-1, OP_EQ, s1len);
- memset(p1, 0, DH_BYTES); /* 0 with padding. */
- s1len = crypto_dh_compute_secret(LOG_WARN, dh1, p1, DH_BYTES, s1, 50);
+ memset(p1, 0, DH1024_KEY_LEN); /* 0 with padding. */
+ s1len = crypto_dh_compute_secret(LOG_WARN, dh1, p1, DH1024_KEY_LEN,
+ s1, 50);
tt_int_op(-1, OP_EQ, s1len);
- p1[DH_BYTES-1] = 1; /* 1 with padding*/
- s1len = crypto_dh_compute_secret(LOG_WARN, dh1, p1, DH_BYTES, s1, 50);
+ p1[DH1024_KEY_LEN-1] = 1; /* 1 with padding*/
+ s1len = crypto_dh_compute_secret(LOG_WARN, dh1, p1, DH1024_KEY_LEN,
+ s1, 50);
tt_int_op(-1, OP_EQ, s1len);
/* 2 is okay, though weird. */
s1len = crypto_dh_compute_secret(LOG_WARN, dh1, "\x02", 1, s1, 50);
tt_int_op(50, OP_EQ, s1len);
+ /* 2 a second time is still okay, though weird. */
+ s1len = crypto_dh_compute_secret(LOG_WARN, dh1, "\x02", 1, s1, 50);
+ tt_int_op(50, OP_EQ, s1len);
+
const char P[] =
"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E08"
"8A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B"
@@ -91,15 +120,18 @@ test_crypto_dh(void *arg)
/* p-1, p, and so on are not okay. */
base16_decode(p1, sizeof(p1), P, strlen(P));
- s1len = crypto_dh_compute_secret(LOG_WARN, dh1, p1, DH_BYTES, s1, 50);
+ s1len = crypto_dh_compute_secret(LOG_WARN, dh1, p1, DH1024_KEY_LEN,
+ s1, 50);
tt_int_op(-1, OP_EQ, s1len);
- p1[DH_BYTES-1] = 0xFE; /* p-1 */
- s1len = crypto_dh_compute_secret(LOG_WARN, dh1, p1, DH_BYTES, s1, 50);
+ p1[DH1024_KEY_LEN-1] = 0xFE; /* p-1 */
+ s1len = crypto_dh_compute_secret(LOG_WARN, dh1, p1, DH1024_KEY_LEN,
+ s1, 50);
tt_int_op(-1, OP_EQ, s1len);
- p1[DH_BYTES-1] = 0xFD; /* p-2 works fine */
- s1len = crypto_dh_compute_secret(LOG_WARN, dh1, p1, DH_BYTES, s1, 50);
+ p1[DH1024_KEY_LEN-1] = 0xFD; /* p-2 works fine */
+ s1len = crypto_dh_compute_secret(LOG_WARN, dh1, p1, DH1024_KEY_LEN,
+ s1, 50);
tt_int_op(50, OP_EQ, s1len);
const char P_plus_one[] =
@@ -111,51 +143,103 @@ test_crypto_dh(void *arg)
base16_decode(p1, sizeof(p1), P_plus_one, strlen(P_plus_one));
- s1len = crypto_dh_compute_secret(LOG_WARN, dh1, p1, DH_BYTES, s1, 50);
+ s1len = crypto_dh_compute_secret(LOG_WARN, dh1, p1, DH1024_KEY_LEN,
+ s1, 50);
tt_int_op(-1, OP_EQ, s1len);
- p1[DH_BYTES-1] = 0x01; /* p+2 */
- s1len = crypto_dh_compute_secret(LOG_WARN, dh1, p1, DH_BYTES, s1, 50);
+ p1[DH1024_KEY_LEN-1] = 0x01; /* p+2 */
+ s1len = crypto_dh_compute_secret(LOG_WARN, dh1, p1, DH1024_KEY_LEN,
+ s1, 50);
tt_int_op(-1, OP_EQ, s1len);
- p1[DH_BYTES-1] = 0xff; /* p+256 */
- s1len = crypto_dh_compute_secret(LOG_WARN, dh1, p1, DH_BYTES, s1, 50);
+ p1[DH1024_KEY_LEN-1] = 0xff; /* p+256 */
+ s1len = crypto_dh_compute_secret(LOG_WARN, dh1, p1, DH1024_KEY_LEN,
+ s1, 50);
tt_int_op(-1, OP_EQ, s1len);
- memset(p1, 0xff, DH_BYTES), /* 2^1024-1 */
- s1len = crypto_dh_compute_secret(LOG_WARN, dh1, p1, DH_BYTES, s1, 50);
+ memset(p1, 0xff, DH1024_KEY_LEN), /* 2^1024-1 */
+ s1len = crypto_dh_compute_secret(LOG_WARN, dh1, p1, DH1024_KEY_LEN,
+ s1, 50);
tt_int_op(-1, OP_EQ, s1len);
}
{
/* provoke an error in the openssl DH_compute_key function; make sure we
* survive. */
- tt_assert(! crypto_dh_get_public(dh1, p1, DH_BYTES));
+ tt_assert(! crypto_dh_get_public(dh1, p1, DH1024_KEY_LEN));
crypto_dh_free(dh2);
dh2= crypto_dh_new(DH_TYPE_CIRCUIT); /* no private key set */
s1len = crypto_dh_compute_secret(LOG_WARN, dh2,
- p1, DH_BYTES,
+ p1, DH1024_KEY_LEN,
s1, 50);
tt_int_op(s1len, OP_EQ, -1);
}
+#if defined(ENABLE_OPENSSL)
+ {
+ /* Make sure that our crypto library can handshake with openssl. */
+ dh3 = crypto_dh_new(DH_TYPE_TLS);
+ tt_assert(!crypto_dh_get_public(dh3, p1, DH1024_KEY_LEN));
+
+ dh4 = crypto_dh_new_openssl_tls();
+ tt_assert(DH_generate_key(dh4));
+ const BIGNUM *pk=NULL;
+#ifdef OPENSSL_1_1_API
+ const BIGNUM *sk=NULL;
+ DH_get0_key(dh4, &pk, &sk);
+#else
+ pk = dh4->pub_key;
+#endif
+ tt_assert(pk);
+ tt_int_op(BN_num_bytes(pk), OP_LE, DH1024_KEY_LEN);
+ tt_int_op(BN_num_bytes(pk), OP_GT, 0);
+ memset(p2, 0, sizeof(p2));
+ /* right-pad. */
+ BN_bn2bin(pk, (unsigned char *)(p2+DH1024_KEY_LEN-BN_num_bytes(pk)));
+
+ s1len = crypto_dh_handshake(LOG_WARN, dh3, p2, DH1024_KEY_LEN,
+ (unsigned char *)s1, sizeof(s1));
+ pubkey_tmp = BN_bin2bn((unsigned char *)p1, DH1024_KEY_LEN, NULL);
+ s2len = DH_compute_key((unsigned char *)s2, pubkey_tmp, dh4);
+
+ tt_int_op(s1len, OP_EQ, s2len);
+ tt_int_op(s1len, OP_GT, 0);
+ tt_mem_op(s1, OP_EQ, s2, s1len);
+ }
+#endif
+
done:
crypto_dh_free(dh1);
crypto_dh_free(dh2);
crypto_dh_free(dh1_dup);
+#ifdef ENABLE_OPENSSL
+ crypto_dh_free(dh3);
+ if (dh4)
+ DH_free(dh4);
+ if (pubkey_tmp)
+ BN_free(pubkey_tmp);
+#endif
}
static void
test_crypto_openssl_version(void *arg)
{
(void)arg;
+#ifdef ENABLE_NSS
+ tt_skip();
+#else
const char *version = crypto_openssl_get_version_str();
const char *h_version = crypto_openssl_get_header_version_str();
tt_assert(version);
tt_assert(h_version);
- tt_assert(!strcmpstart(version, h_version)); /* "-fips" suffix, etc */
- tt_assert(!strstr(version, "OpenSSL"));
+ if (strcmpstart(version, h_version)) { /* "-fips" suffix, etc */
+ TT_DIE(("OpenSSL library version %s did not begin with header version %s.",
+ version, h_version));
+ }
+ if (strstr(version, "OpenSSL")) {
+ TT_DIE(("assertion failed: !strstr(\"%s\", \"OpenSSL\")", version));
+ }
int a=-1,b=-1,c=-1;
if (!strcmpstart(version, "LibreSSL") || !strcmpstart(version, "BoringSSL"))
return;
@@ -164,6 +248,7 @@ test_crypto_openssl_version(void *arg)
tt_int_op(a, OP_GE, 0);
tt_int_op(b, OP_GE, 0);
tt_int_op(c, OP_GE, 0);
+#endif
done:
;
@@ -192,10 +277,10 @@ test_crypto_rng(void *arg)
j = crypto_rand_int(100);
if (j < 0 || j >= 100)
allok = 0;
- big = crypto_rand_uint64(U64_LITERAL(1)<<40);
- if (big >= (U64_LITERAL(1)<<40))
+ big = crypto_rand_uint64(UINT64_C(1)<<40);
+ if (big >= (UINT64_C(1)<<40))
allok = 0;
- big = crypto_rand_uint64(U64_LITERAL(5));
+ big = crypto_rand_uint64(UINT64_C(5));
if (big >= 5)
allok = 0;
d = crypto_rand_double();
@@ -331,38 +416,6 @@ test_crypto_rng_strongest(void *arg)
#undef N
}
-/* Test for rectifying openssl RAND engine. */
-static void
-test_crypto_rng_engine(void *arg)
-{
- (void)arg;
- RAND_METHOD dummy_method;
- memset(&dummy_method, 0, sizeof(dummy_method));
-
- /* We should be a no-op if we're already on RAND_OpenSSL */
- tt_int_op(0, ==, crypto_force_rand_ssleay());
- tt_assert(RAND_get_rand_method() == RAND_OpenSSL());
-
- /* We should correct the method if it's a dummy. */
- RAND_set_rand_method(&dummy_method);
-#ifdef LIBRESSL_VERSION_NUMBER
- /* On libressl, you can't override the RNG. */
- tt_assert(RAND_get_rand_method() == RAND_OpenSSL());
- tt_int_op(0, ==, crypto_force_rand_ssleay());
-#else
- tt_assert(RAND_get_rand_method() == &dummy_method);
- tt_int_op(1, ==, crypto_force_rand_ssleay());
-#endif
- tt_assert(RAND_get_rand_method() == RAND_OpenSSL());
-
- /* Make sure we aren't calling dummy_method */
- crypto_rand((void *) &dummy_method, sizeof(dummy_method));
- crypto_rand((void *) &dummy_method, sizeof(dummy_method));
-
- done:
- ;
-}
-
/** Run unit tests for our AES128 functionality */
static void
test_crypto_aes128(void *arg)
@@ -1135,6 +1188,54 @@ test_crypto_sha3_xof(void *arg)
tor_free(mem_op_hex_tmp);
}
+/* Test our MAC-SHA3 function. There are not actually any MAC-SHA3 test
+ * vectors out there for our H(len(k) || k || m) construction. Hence what we
+ * are gonna do is test our crypto_mac_sha3_256() function against manually
+ * doing H(len(k) || k||m). If in the future the Keccak group decides to
+ * standarize an MAC construction and make test vectors, we should
+ * incorporate them here. */
+static void
+test_crypto_mac_sha3(void *arg)
+{
+ const char msg[] = "i am in a library somewhere using my computer";
+ const char key[] = "i'm from the past talking to the future.";
+
+ uint8_t hmac_test[DIGEST256_LEN];
+ char hmac_manual[DIGEST256_LEN];
+
+ (void) arg;
+
+ /* First let's use our nice HMAC-SHA3 function */
+ crypto_mac_sha3_256(hmac_test, sizeof(hmac_test),
+ (uint8_t *) key, strlen(key),
+ (uint8_t *) msg, strlen(msg));
+
+ /* Now let's try a manual H(len(k) || k || m) construction */
+ {
+ char *key_msg_concat = NULL, *all = NULL;
+ int result;
+ const uint64_t key_len_netorder = tor_htonll(strlen(key));
+ size_t all_len;
+
+ tor_asprintf(&key_msg_concat, "%s%s", key, msg);
+ all_len = sizeof(key_len_netorder) + strlen(key_msg_concat);
+ all = tor_malloc_zero(all_len);
+ memcpy(all, &key_len_netorder, sizeof(key_len_netorder));
+ memcpy(all + sizeof(key_len_netorder), key_msg_concat,
+ strlen(key_msg_concat));
+
+ result = crypto_digest256(hmac_manual, all, all_len, DIGEST_SHA3_256);
+ tor_free(key_msg_concat);
+ tor_free(all);
+ tt_int_op(result, OP_EQ, 0);
+ }
+
+ /* Now compare the two results */
+ tt_mem_op(hmac_test, OP_EQ, hmac_manual, DIGEST256_LEN);
+
+ done: ;
+}
+
/** Run unit tests for our public key crypto functions */
static void
test_crypto_pk(void *arg)
@@ -1195,12 +1296,12 @@ test_crypto_pk(void *arg)
tt_assert(! crypto_pk_write_private_key_to_filename(pk1,
get_fname("pkey1")));
/* failing case for read: can't read. */
- tt_assert(crypto_pk_read_private_key_from_filename(pk2,
- get_fname("xyzzy")) < 0);
+ tt_int_op(crypto_pk_read_private_key_from_filename(pk2, get_fname("xyzzy")),
+ OP_LT, 0);
write_str_to_file(get_fname("xyzzy"), "foobar", 6);
/* Failing case for read: no key. */
- tt_assert(crypto_pk_read_private_key_from_filename(pk2,
- get_fname("xyzzy")) < 0);
+ tt_int_op(crypto_pk_read_private_key_from_filename(pk2, get_fname("xyzzy")),
+ OP_LT, 0);
tt_assert(! crypto_pk_read_private_key_from_filename(pk2,
get_fname("pkey1")));
tt_int_op(15,OP_EQ,
@@ -1232,17 +1333,17 @@ test_crypto_pk(void *arg)
i = crypto_pk_asn1_encode(pk1, data1, 1024);
tt_int_op(i, OP_GT, 0);
pk2 = crypto_pk_asn1_decode(data1, i);
- tt_assert(crypto_pk_cmp_keys(pk1,pk2) == 0);
+ tt_int_op(crypto_pk_cmp_keys(pk1, pk2), OP_EQ, 0);
/* Try with hybrid encryption wrappers. */
crypto_rand(data1, 1024);
for (i = 85; i < 140; ++i) {
memset(data2,0,1024);
memset(data3,0,1024);
- len = crypto_pk_public_hybrid_encrypt(pk1,data2,sizeof(data2),
+ len = crypto_pk_obsolete_public_hybrid_encrypt(pk1,data2,sizeof(data2),
data1,i,PK_PKCS1_OAEP_PADDING,0);
tt_int_op(len, OP_GE, 0);
- len = crypto_pk_private_hybrid_decrypt(pk1,data3,sizeof(data3),
+ len = crypto_pk_obsolete_private_hybrid_decrypt(pk1,data3,sizeof(data3),
data2,len,PK_PKCS1_OAEP_PADDING,1);
tt_int_op(len,OP_EQ, i);
tt_mem_op(data1,OP_EQ, data3,i);
@@ -1251,9 +1352,9 @@ test_crypto_pk(void *arg)
/* Try copy_full */
crypto_pk_free(pk2);
pk2 = crypto_pk_copy_full(pk1);
- tt_assert(pk2 != NULL);
+ tt_ptr_op(pk2, OP_NE, NULL);
tt_ptr_op(pk1, OP_NE, pk2);
- tt_assert(crypto_pk_cmp_keys(pk1,pk2) == 0);
+ tt_int_op(crypto_pk_cmp_keys(pk1, pk2), OP_EQ, 0);
done:
if (pk1)
@@ -1325,23 +1426,23 @@ test_crypto_pk_base64(void *arg)
/* Test Base64 encoding a key. */
pk1 = pk_generate(0);
tt_assert(pk1);
- tt_int_op(0, OP_EQ, crypto_pk_base64_encode(pk1, &encoded));
+ tt_int_op(0, OP_EQ, crypto_pk_base64_encode_private(pk1, &encoded));
tt_assert(encoded);
/* Test decoding a valid key. */
- pk2 = crypto_pk_base64_decode(encoded, strlen(encoded));
+ pk2 = crypto_pk_base64_decode_private(encoded, strlen(encoded));
tt_assert(pk2);
- tt_assert(crypto_pk_cmp_keys(pk1,pk2) == 0);
+ tt_int_op(crypto_pk_cmp_keys(pk1, pk2), OP_EQ, 0);
crypto_pk_free(pk2);
/* Test decoding a invalid key (not Base64). */
static const char *invalid_b64 = "The key is in another castle!";
- pk2 = crypto_pk_base64_decode(invalid_b64, strlen(invalid_b64));
- tt_assert(!pk2);
+ pk2 = crypto_pk_base64_decode_private(invalid_b64, strlen(invalid_b64));
+ tt_ptr_op(pk2, OP_EQ, NULL);
/* Test decoding a truncated Base64 blob. */
- pk2 = crypto_pk_base64_decode(encoded, strlen(encoded)/2);
- tt_assert(!pk2);
+ pk2 = crypto_pk_base64_decode_private(encoded, strlen(encoded)/2);
+ tt_ptr_op(pk2, OP_EQ, NULL);
done:
crypto_pk_free(pk1);
@@ -1389,6 +1490,58 @@ test_crypto_pk_pem_encrypted(void *arg)
done:
crypto_pk_free(pk);
}
+
+static void
+test_crypto_pk_invalid_private_key(void *arg)
+{
+ (void)arg;
+ /* Here is a simple invalid private key: it was produced by making
+ * a regular private key, and then adding 2 to the modulus. */
+ const char pem[] =
+ "-----BEGIN RSA PRIVATE KEY-----\n"
+ "MIIEpQIBAAKCAQEAskRyZrs+YAukvBmZlgo6/rCxyKF2xyUk073ap+2CgRUnSfGG\n"
+ "mflHlzqVq7tpH50DafpS+fFAbaEaNV/ac20QG0rUZi38HTB4qURWOu6n0Bws6E4l\n"
+ "UX/AkvDlWnuYH0pHHi2c3DGNFjwoJpjKuUTk+cRffVR8X3Kjr62SUDUaBNW0Kecz\n"
+ "3SYLbmgmZI16dFZ+g9sNM3znXZbhvb33WwPqpZSSPs37cPgF7eS6mAw/gUMx6zfE\n"
+ "HRmUnOQSzUdS05rvc/hsiCLhiIZ8hgfkD07XnTT1Ds8DwE55k7BUWY2wvwWCNLsH\n"
+ "qtqAxTr615XdkMxVkYgImpqPybarpfNYhFqkOwIDAQABAoIBACPC3VxEdbfYvhxJ\n"
+ "2mih9sG++nswAN7kUaX0cRe86rAwaShJPmJHApiQ1ROVTfpciiHJaLnhLraPWe2Z\n"
+ "I/6Bw3hmI4O399p3Lc1u+wlpdNqnvE6B1rSptx0DHE9xecvVH70rE0uM2Su7t6Y+\n"
+ "gnR2IKUGQs2mlCilm7aTUEWs0WJkkl4CG1dyxItuOSdNBjOEzXimJyiB10jEBFsp\n"
+ "SZeCF2FZ7AJbck5CVC42+oTsiDbZrHTHOn7v26rFGdONeHD1wOI1v7JwHFpCB923\n"
+ "aEHBzsPbMeq7DWG1rjzCYpcXHhTDBDBWSia4SEhyr2Nl7m7qxWWWwR+x4dqAj3rD\n"
+ "HeTmos0CgYEA6uf1CLpjPpOs5IaW1DQI8dJA/xFEAC/6GVgq4nFOGHZrm8G3L5o+\n"
+ "qvtQNMpDs2naWuZpqROFqv24o01DykHygR72GlPIY6uvmmf5tvJLoGnbFUay33L4\n"
+ "7b9dkNhuEIBNPzVDie0pgS77WgaPbYkVv5fnDwgPuVnkqfakEt7Pz2MCgYEAwkZ5\n"
+ "R1wLuTQEA2Poo6Gf4L8Bg6yNYI46LHDqDIs818iYLjtcnEEvbPfaoKNpOn7s7s4O\n"
+ "Pc+4HnT1aIQs0IKVLRTp+5a/9wfOkPZnobWOUHZk9UzBL3Hc1uy/qhp93iE3tSzx\n"
+ "v0O1pvR+hr3guTCZx8wZnDvaMgG3hlyPnVlHdrMCgYEAzQQxGbMC1ySv6quEjCP2\n"
+ "AogMbhE1lixJTUFj/EoDbNo9xKznIkauly/Lqqc1OysRhfA/G2+MY9YZBX1zwtyX\n"
+ "uBW7mPKynDrFgi9pBECnvJNmwET57Ic9ttIj6Tzbos83nAjyrzgr1zGX8dRz7ZeN\n"
+ "QbBj2vygLJbGOYinXkjUeh0CgYEAhN5aF9n2EqZmkEMGWtMxWy6HRJ0A3Cap1rcq\n"
+ "+4VHCXWhzwy+XAeg/e/N0MuyLlWcif7XcqLcE8h+BwtO8xQ8HmcNWApUJAls12wO\n"
+ "mGRpftJaXgIupdpD5aJpu1b++qrRRNIGTH9sf1D8L/8w8LcylZkbcuTkaAsQj45C\n"
+ "kqT64U0CgYEAq47IKS6xc3CDc17BqExR6t+1yRe+4ml+z1zcVbfUKony4pGvl1yo\n"
+ "rk0IYDN5Vd8h5xtXrkPdX9h+ywmohnelDKsayEuE+opyqEpSU4/96Bb22RZUoucb\n"
+ "LWkV5gZx5hFnDFtEd4vadMIiY4jVv/3JqiZDKwMVBJKlHRXJEEmIEBk=\n"
+ "-----END RSA PRIVATE KEY-----\n";
+
+ crypto_pk_t *pk = NULL;
+
+ pk = crypto_pk_new();
+ setup_capture_of_logs(LOG_WARN);
+ tt_int_op(-1, OP_EQ,
+ crypto_pk_read_private_key_from_string(pk, pem, strlen(pem)));
+#ifdef ENABLE_NSS
+ expect_single_log_msg_containing("received bad data");
+#else
+ expect_single_log_msg_containing("while checking RSA key");
+#endif
+ done:
+ teardown_capture_of_logs();
+ crypto_pk_free(pk);
+}
+
#ifdef HAVE_TRUNCATE
#define do_truncate truncate
#else
@@ -1410,7 +1563,7 @@ do_truncate(const char *fname, size_t len)
tor_free(bytes);
return r;
}
-#endif
+#endif /* defined(HAVE_TRUNCATE) */
/** Sanity check for crypto pk digests */
static void
@@ -1424,7 +1577,8 @@ test_crypto_digests(void *arg)
(void)arg;
k = crypto_pk_new();
tt_assert(k);
- r = crypto_pk_read_private_key_from_string(k, AUTHORITY_SIGNKEY_3, -1);
+ r = crypto_pk_read_private_key_from_string(k, AUTHORITY_SIGNKEY_3,
+ strlen(AUTHORITY_SIGNKEY_3));
tt_assert(!r);
r = crypto_pk_get_digest(k, digest);
@@ -1433,6 +1587,7 @@ test_crypto_digests(void *arg)
AUTHORITY_SIGNKEY_A_DIGEST, HEX_DIGEST_LEN);
r = crypto_pk_get_common_digests(k, &pkey_digests);
+ tt_int_op(r, OP_EQ, 0);
tt_mem_op(hex_str(pkey_digests.d[DIGEST_SHA1], DIGEST_LEN),OP_EQ,
AUTHORITY_SIGNKEY_A_DIGEST, HEX_DIGEST_LEN);
@@ -1469,28 +1624,6 @@ test_crypto_digest_names(void *arg)
;
}
-#ifndef OPENSSL_1_1_API
-#define EVP_ENCODE_CTX_new() tor_malloc_zero(sizeof(EVP_ENCODE_CTX))
-#define EVP_ENCODE_CTX_free(ctx) tor_free(ctx)
-#endif
-
-/** Encode src into dest with OpenSSL's EVP Encode interface, returning the
- * length of the encoded data in bytes.
- */
-static int
-base64_encode_evp(char *dest, char *src, size_t srclen)
-{
- const unsigned char *s = (unsigned char*)src;
- EVP_ENCODE_CTX *ctx = EVP_ENCODE_CTX_new();
- int len, ret;
-
- EVP_EncodeInit(ctx);
- EVP_EncodeUpdate(ctx, (unsigned char *)dest, &len, s, (int)srclen);
- EVP_EncodeFinal(ctx, (unsigned char *)(dest + len), &ret);
- EVP_ENCODE_CTX_free(ctx);
- return ret+ len;
-}
-
/** Run unit tests for misc crypto formatting functionality (base64, base32,
* fingerprints, etc) */
static void
@@ -1519,7 +1652,7 @@ test_crypto_formats(void *arg)
tt_int_op(i, OP_GE, 0);
tt_int_op(i, OP_EQ, strlen(data2));
tt_assert(! strchr(data2, '='));
- j = base64_decode_nopad((uint8_t*)data3, 1024, data2, i);
+ j = base64_decode(data3, 1024, data2, i);
tt_int_op(j, OP_EQ, idx);
tt_mem_op(data3,OP_EQ, data1, idx);
}
@@ -1544,21 +1677,7 @@ test_crypto_formats(void *arg)
tt_mem_op(data1,OP_EQ, data3, DIGEST_LEN);
tt_int_op(99,OP_EQ, data3[DIGEST_LEN+1]);
- tt_assert(digest_from_base64(data3, "###") < 0);
-
- for (i = 0; i < 256; i++) {
- /* Test the multiline format Base64 encoder with 0 .. 256 bytes of
- * output against OpenSSL.
- */
- const size_t enclen = base64_encode_size(i, BASE64_ENCODE_MULTILINE);
- data1[i] = i;
- j = base64_encode(data2, 1024, data1, i, BASE64_ENCODE_MULTILINE);
- tt_int_op(j, OP_EQ, enclen);
- j = base64_encode_evp(data3, data1, i);
- tt_int_op(j, OP_EQ, enclen);
- tt_mem_op(data2, OP_EQ, data3, enclen);
- tt_int_op(j, OP_EQ, strlen(data2));
- }
+ tt_int_op(digest_from_base64(data3, "###"), OP_LT, 0);
/* Encoding SHA256 */
crypto_rand(data2, DIGEST256_LEN);
@@ -1838,15 +1957,6 @@ test_crypto_hkdf_sha256(void *arg)
key_material, 100)
/* Test vectors generated with ntor_ref.py */
- memset(key_material, 0, sizeof(key_material));
- EXPAND("");
- tt_int_op(r, OP_EQ, 0);
- test_memeq_hex(key_material,
- "d3490ed48b12a48f9547861583573fe3f19aafe3f81dc7fc75"
- "eeed96d741b3290f941576c1f9f0b2d463d1ec7ab2c6bf71cd"
- "d7f826c6298c00dbfe6711635d7005f0269493edf6046cc7e7"
- "dcf6abe0d20c77cf363e8ffe358927817a3d3e73712cee28d8");
-
EXPAND("Tor");
tt_int_op(r, OP_EQ, 0);
test_memeq_hex(key_material,
@@ -1969,7 +2079,7 @@ test_crypto_curve25519_impl(void *arg)
"e0544770bc7de853b38f9100489e3e79";
const char e1e2k_expected[] = "cd6e8269104eb5aaee886bd2071fba88"
"bd13861475516bc2cd2b6e005e805064";
-#else
+#else /* !(defined(SLOW_CURVE25519_TEST)) */
const int loop_max=200;
const char e1_expected[] = "bc7112cde03f97ef7008cad1bdc56be3"
"c6a1037d74cceb3712e9206871dcf654";
@@ -1977,7 +2087,7 @@ test_crypto_curve25519_impl(void *arg)
"8e3ee1a63c7d14274ea5d4c67f065467";
const char e1e2k_expected[] = "7ddb98bd89025d2347776b33901b3e7e"
"c0ee98cb2257a4545c0cfb2ca3e1812b";
-#endif
+#endif /* defined(SLOW_CURVE25519_TEST) */
unsigned char e1k[32];
unsigned char e2k[32];
@@ -2233,6 +2343,9 @@ test_crypto_ed25519_simple(void *arg)
tt_int_op(0, OP_EQ, ed25519_public_key_generate(&pub1, &sec1));
tt_int_op(0, OP_EQ, ed25519_public_key_generate(&pub2, &sec1));
+ tt_int_op(ed25519_validate_pubkey(&pub1), OP_EQ, 0);
+ tt_int_op(ed25519_validate_pubkey(&pub2), OP_EQ, 0);
+
tt_mem_op(pub1.pubkey, OP_EQ, pub2.pubkey, sizeof(pub1.pubkey));
tt_assert(ed25519_pubkey_eq(&pub1, &pub2));
tt_assert(ed25519_pubkey_eq(&pub1, &pub1));
@@ -2604,6 +2717,39 @@ test_crypto_ed25519_blinding(void *arg)
;
}
+/** Test that our blinding functions will fail if we pass them bad pubkeys */
+static void
+test_crypto_ed25519_blinding_fail(void *arg)
+{
+ int retval;
+ uint8_t param[32] = {2};
+ ed25519_public_key_t pub;
+ ed25519_public_key_t pub_blinded;
+
+ (void)arg;
+
+ /* This point is not on the curve: the blind routines should fail */
+ const char badkey[] =
+ "e19c65de75c68cf3b7643ea732ba9eb1a3d20d6d57ba223c2ece1df66feb5af0";
+ retval = base16_decode((char*)pub.pubkey, sizeof(pub.pubkey),
+ badkey, strlen(badkey));
+ tt_int_op(retval, OP_EQ, sizeof(pub.pubkey));
+ retval = ed25519_public_blind(&pub_blinded, &pub, param);
+ tt_int_op(retval, OP_EQ, -1);
+
+ /* This point is legit: blind routines should be happy */
+ const char goodkey[] =
+ "4ba2e44760dff4c559ef3c38768c1c14a8a54740c782c8d70803e9d6e3ad8794";
+ retval = base16_decode((char*)pub.pubkey, sizeof(pub.pubkey),
+ goodkey, strlen(goodkey));
+ tt_int_op(retval, OP_EQ, sizeof(pub.pubkey));
+ retval = ed25519_public_blind(&pub_blinded, &pub, param);
+ tt_int_op(retval, OP_EQ, 0);
+
+ done:
+ ;
+}
+
static void
test_crypto_ed25519_testvectors(void *arg)
{
@@ -2621,6 +2767,8 @@ test_crypto_ed25519_testvectors(void *arg)
ed25519_signature_t sig;
int sign;
+ memset(&curvekp, 0xd0, sizeof(curvekp));
+
#define DECODE(p,s) base16_decode((char*)(p),sizeof(p),(s),strlen(s))
#define EQ(a,h) test_memeq_hex((const char*)(a), (h))
@@ -2702,8 +2850,8 @@ test_crypto_ed25519_storage(void *arg)
tor_free(tag);
/* whitebox test: truncated keys. */
- tt_int_op(0, ==, do_truncate(fname_1, 40));
- tt_int_op(0, ==, do_truncate(fname_2, 40));
+ tt_int_op(0, OP_EQ, do_truncate(fname_1, 40));
+ tt_int_op(0, OP_EQ, do_truncate(fname_2, 40));
tt_int_op(-1, OP_EQ, ed25519_pubkey_read_from_file(&pub, &tag, fname_2));
tt_ptr_op(tag, OP_EQ, NULL);
tor_free(tag);
@@ -2793,8 +2941,8 @@ test_crypto_siphash(void *arg)
{ 0x72, 0x45, 0x06, 0xeb, 0x4c, 0x32, 0x8a, 0x95, }
};
- const struct sipkey K = { U64_LITERAL(0x0706050403020100),
- U64_LITERAL(0x0f0e0d0c0b0a0908) };
+ const struct sipkey K = { UINT64_C(0x0706050403020100),
+ UINT64_C(0x0f0e0d0c0b0a0908) };
uint8_t input[64];
int i, j;
@@ -2849,12 +2997,12 @@ crypto_rand_check_failure_mode_identical(void)
{
/* just in case the buffer size isn't a multiple of sizeof(int64_t) */
#define FAILURE_MODE_BUFFER_SIZE_I64 \
- (FAILURE_MODE_BUFFER_SIZE/SIZEOF_INT64_T)
+ (FAILURE_MODE_BUFFER_SIZE/8)
#define FAILURE_MODE_BUFFER_SIZE_I64_BYTES \
- (FAILURE_MODE_BUFFER_SIZE_I64*SIZEOF_INT64_T)
+ (FAILURE_MODE_BUFFER_SIZE_I64*8)
#if FAILURE_MODE_BUFFER_SIZE_I64 < 2
-#error FAILURE_MODE_BUFFER_SIZE needs to be at least 2*SIZEOF_INT64_T
+#error FAILURE_MODE_BUFFER_SIZE needs to be at least 2*8
#endif
int64_t buf[FAILURE_MODE_BUFFER_SIZE_I64];
@@ -2895,6 +3043,67 @@ crypto_rand_check_failure_mode_predict(void)
#undef FAILURE_MODE_BUFFER_SIZE
+/** Test that our ed25519 validation function rejects evil public keys and
+ * accepts good ones. */
+static void
+test_crypto_ed25519_validation(void *arg)
+{
+ (void) arg;
+
+ int retval;
+ ed25519_public_key_t pub1;
+
+ /* See https://lists.torproject.org/pipermail/tor-dev/2017-April/012230.html
+ for a list of points with torsion components in ed25519. */
+
+ { /* Point with torsion component (order 8l) */
+ const char badkey[] =
+ "300ef2e64e588e1df55b48e4da0416ffb64cc85d5b00af6463d5cc6c2b1c185e";
+ retval = base16_decode((char*)pub1.pubkey, sizeof(pub1.pubkey),
+ badkey, strlen(badkey));
+ tt_int_op(retval, OP_EQ, sizeof(pub1.pubkey));
+ tt_int_op(ed25519_validate_pubkey(&pub1), OP_EQ, -1);
+ }
+
+ { /* Point with torsion component (order 4l) */
+ const char badkey[] =
+ "f43e3a046db8749164c6e69b193f1e942c7452e7d888736f40b98093d814d5e7";
+ retval = base16_decode((char*)pub1.pubkey, sizeof(pub1.pubkey),
+ badkey, strlen(badkey));
+ tt_int_op(retval, OP_EQ, sizeof(pub1.pubkey));
+ tt_int_op(ed25519_validate_pubkey(&pub1), OP_EQ, -1);
+ }
+
+ { /* Point with torsion component (order 2l) */
+ const char badkey[] =
+ "c9fff3af0471c28e33e98c2043e44f779d0427b1e37c521a6bddc011ed1869af";
+ retval = base16_decode((char*)pub1.pubkey, sizeof(pub1.pubkey),
+ badkey, strlen(badkey));
+ tt_int_op(retval, OP_EQ, sizeof(pub1.pubkey));
+ tt_int_op(ed25519_validate_pubkey(&pub1), OP_EQ, -1);
+ }
+
+ { /* This point is not even on the curve */
+ const char badkey[] =
+ "e19c65de75c68cf3b7643ea732ba9eb1a3d20d6d57ba223c2ece1df66feb5af0";
+ retval = base16_decode((char*)pub1.pubkey, sizeof(pub1.pubkey),
+ badkey, strlen(badkey));
+ tt_int_op(retval, OP_EQ, sizeof(pub1.pubkey));
+ tt_int_op(ed25519_validate_pubkey(&pub1), OP_EQ, -1);
+ }
+
+ { /* This one is a good key */
+ const char goodkey[] =
+ "4ba2e44760dff4c559ef3c38768c1c14a8a54740c782c8d70803e9d6e3ad8794";
+ retval = base16_decode((char*)pub1.pubkey, sizeof(pub1.pubkey),
+ goodkey, strlen(goodkey));
+ tt_int_op(retval, OP_EQ, sizeof(pub1.pubkey));
+ tt_int_op(ed25519_validate_pubkey(&pub1), OP_EQ, 0);
+ }
+
+ done: ;
+}
+
static void
test_crypto_failure_modes(void *arg)
{
@@ -2902,17 +3111,17 @@ test_crypto_failure_modes(void *arg)
(void)arg;
rv = crypto_early_init();
- tt_assert(rv == 0);
+ tt_int_op(rv, OP_EQ, 0);
/* Check random works */
rv = crypto_rand_check_failure_mode_zero();
- tt_assert(rv == 0);
+ tt_int_op(rv, OP_EQ, 0);
rv = crypto_rand_check_failure_mode_identical();
- tt_assert(rv == 0);
+ tt_int_op(rv, OP_EQ, 0);
rv = crypto_rand_check_failure_mode_predict();
- tt_assert(rv == 0);
+ tt_int_op(rv, OP_EQ, 0);
done:
;
@@ -2933,7 +3142,6 @@ struct testcase_t crypto_tests[] = {
CRYPTO_LEGACY(formats),
CRYPTO_LEGACY(rng),
{ "rng_range", test_crypto_rng_range, 0, NULL, NULL },
- { "rng_engine", test_crypto_rng_engine, TT_FORK, NULL, NULL },
{ "rng_strongest", test_crypto_rng_strongest, TT_FORK, NULL, NULL },
{ "rng_strongest_nosyscall", test_crypto_rng_strongest, TT_FORK,
&passthrough_setup, (void*)"nosyscall" },
@@ -2955,10 +3163,13 @@ struct testcase_t crypto_tests[] = {
{ "pk_fingerprints", test_crypto_pk_fingerprints, TT_FORK, NULL, NULL },
{ "pk_base64", test_crypto_pk_base64, TT_FORK, NULL, NULL },
{ "pk_pem_encrypted", test_crypto_pk_pem_encrypted, TT_FORK, NULL, NULL },
+ { "pk_invalid_private_key", test_crypto_pk_invalid_private_key, 0,
+ NULL, NULL },
CRYPTO_LEGACY(digests),
{ "digest_names", test_crypto_digest_names, 0, NULL, NULL },
{ "sha3", test_crypto_sha3, TT_FORK, NULL, NULL},
{ "sha3_xof", test_crypto_sha3_xof, TT_FORK, NULL, NULL},
+ { "mac_sha3", test_crypto_mac_sha3, TT_FORK, NULL, NULL},
CRYPTO_LEGACY(dh),
{ "aes_iv_AES", test_crypto_aes_iv, TT_FORK, &passthrough_setup,
(void*)"aes" },
@@ -2981,10 +3192,11 @@ struct testcase_t crypto_tests[] = {
ED25519_TEST(encode, 0),
ED25519_TEST(convert, 0),
ED25519_TEST(blinding, 0),
+ ED25519_TEST(blinding_fail, 0),
ED25519_TEST(testvectors, 0),
+ ED25519_TEST(validation, 0),
{ "ed25519_storage", test_crypto_ed25519_storage, 0, NULL, NULL },
{ "siphash", test_crypto_siphash, 0, NULL, NULL },
{ "failure_modes", test_crypto_failure_modes, TT_FORK, NULL, NULL },
END_OF_TESTCASES
};
-