diff options
Diffstat (limited to 'src/test/test_crypto.c')
-rw-r--r-- | src/test/test_crypto.c | 224 |
1 files changed, 150 insertions, 74 deletions
diff --git a/src/test/test_crypto.c b/src/test/test_crypto.c index 64a46f7914..4d9651db9c 100644 --- a/src/test/test_crypto.c +++ b/src/test/test_crypto.c @@ -1,6 +1,6 @@ /* 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-2017, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #include "orconfig.h" @@ -15,9 +15,6 @@ #include "crypto_ed25519.h" #include "ed25519_vectors.inc" -#include <openssl/evp.h> -#include <openssl/rand.h> - /** Run unit tests for Diffie-Hellman functionality. */ static void test_crypto_dh(void *arg) @@ -331,38 +328,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 +1100,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, ==, 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) @@ -1429,28 +1442,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 @@ -1479,7 +1470,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); } @@ -1506,20 +1497,6 @@ test_crypto_formats(void *arg) 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)); - } - /* Encoding SHA256 */ crypto_rand(data2, DIGEST256_LEN); memset(data2, 100, 1024); @@ -2193,6 +2170,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)); @@ -2564,6 +2544,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) { @@ -2855,6 +2868,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) { @@ -2893,7 +2967,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" }, @@ -2918,6 +2991,7 @@ struct testcase_t crypto_tests[] = { { "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" }, @@ -2940,7 +3014,9 @@ 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 }, |