Convert a number of tests to GTest.
BUG=129 Change-Id: Ifcdacb2f5f59fd03b757f88778ceb1e672208fd9 Reviewed-on: https://boringssl-review.googlesource.com/16744 Reviewed-by: Adam Langley <agl@google.com> Commit-Queue: Adam Langley <agl@google.com> CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
This commit is contained in:
parent
b22e15c33c
commit
6757fbf8e3
@ -108,7 +108,6 @@ add_subdirectory(rsa_extra)
|
||||
add_subdirectory(ec_extra)
|
||||
add_subdirectory(ecdh)
|
||||
add_subdirectory(ecdsa_extra)
|
||||
add_subdirectory(hmac_extra)
|
||||
|
||||
# Level 3
|
||||
add_subdirectory(cmac)
|
||||
@ -232,13 +231,15 @@ add_executable(
|
||||
bio/bio_test.cc
|
||||
bytestring/bytestring_test.cc
|
||||
chacha/chacha_test.cc
|
||||
cipher_extra/aead_extra_test.cc
|
||||
cipher_extra/aead_test.cc
|
||||
cipher_extra/cipher_test.cc
|
||||
cmac/cmac_test.cc
|
||||
compiler_test.cc
|
||||
constant_time_test.cc
|
||||
curve25519/ed25519_test.cc
|
||||
curve25519/spake25519_test.cc
|
||||
curve25519/x25519_test.cc
|
||||
ecdh/ecdh_test.cc
|
||||
dh/dh_test.cc
|
||||
digest_extra/digest_test.cc
|
||||
dsa/dsa_test.cc
|
||||
@ -247,9 +248,12 @@ add_executable(
|
||||
evp/pbkdf_test.cc
|
||||
fipsmodule/aes/aes_test.cc
|
||||
fipsmodule/ec/ec_test.cc
|
||||
fipsmodule/modes/gcm_test.cc
|
||||
fipsmodule/rand/ctrdrbg_test.cc
|
||||
hkdf/hkdf_test.cc
|
||||
hmac_extra/hmac_test.cc
|
||||
lhash/lhash_test.cc
|
||||
poly1305/poly1305_test.cc
|
||||
pool/pool_test.cc
|
||||
refcount_test.cc
|
||||
rsa_extra/rsa_test.cc
|
||||
|
@ -31,23 +31,5 @@ add_library(
|
||||
${CIPHER_ARCH_SOURCES}
|
||||
)
|
||||
|
||||
add_executable(
|
||||
cipher_test
|
||||
|
||||
cipher_test.cc
|
||||
$<TARGET_OBJECTS:test_support>
|
||||
)
|
||||
|
||||
add_executable(
|
||||
aead_test
|
||||
|
||||
aead_test.cc
|
||||
$<TARGET_OBJECTS:test_support>
|
||||
)
|
||||
|
||||
perlasm(aes128gcmsiv-x86_64.${ASM_EXT} asm/aes128gcmsiv-x86_64.pl)
|
||||
perlasm(chacha20_poly1305_x86_64.${ASM_EXT} asm/chacha20_poly1305_x86_64.pl)
|
||||
|
||||
target_link_libraries(cipher_test crypto)
|
||||
target_link_libraries(aead_test crypto)
|
||||
add_dependencies(all_tests cipher_test aead_test)
|
||||
|
@ -1,68 +0,0 @@
|
||||
/* Copyright (c) 2017, Google Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <openssl/aead.h>
|
||||
#include <openssl/cipher.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
|
||||
// Test that EVP_aead_aes_128_gcm and EVP_aead_aes_256_gcm reject empty nonces.
|
||||
// AES-GCM is not defined for those.
|
||||
//
|
||||
// TODO(davidben): Fold this into aead_test.cc, once it is converted to GTest.
|
||||
TEST(AEADTest, AESGCMEmptyNonce) {
|
||||
static const uint8_t kZeros[32] = {0};
|
||||
|
||||
// Test AES-128-GCM.
|
||||
uint8_t buf[16];
|
||||
size_t len;
|
||||
bssl::ScopedEVP_AEAD_CTX ctx;
|
||||
ASSERT_TRUE(EVP_AEAD_CTX_init(ctx.get(), EVP_aead_aes_128_gcm(), kZeros, 16,
|
||||
EVP_AEAD_DEFAULT_TAG_LENGTH, nullptr));
|
||||
|
||||
EXPECT_FALSE(EVP_AEAD_CTX_seal(ctx.get(), buf, &len, sizeof(buf),
|
||||
nullptr /* nonce */, 0, nullptr /* in */, 0,
|
||||
nullptr /* ad */, 0));
|
||||
uint32_t err = ERR_get_error();
|
||||
EXPECT_EQ(ERR_LIB_CIPHER, ERR_GET_LIB(err));
|
||||
EXPECT_EQ(CIPHER_R_INVALID_NONCE_SIZE, ERR_GET_REASON(err));
|
||||
|
||||
EXPECT_FALSE(EVP_AEAD_CTX_open(ctx.get(), buf, &len, sizeof(buf),
|
||||
nullptr /* nonce */, 0, kZeros /* in */,
|
||||
sizeof(kZeros), nullptr /* ad */, 0));
|
||||
err = ERR_get_error();
|
||||
EXPECT_EQ(ERR_LIB_CIPHER, ERR_GET_LIB(err));
|
||||
EXPECT_EQ(CIPHER_R_INVALID_NONCE_SIZE, ERR_GET_REASON(err));
|
||||
|
||||
// Test AES-256-GCM.
|
||||
ctx.Reset();
|
||||
ASSERT_TRUE(EVP_AEAD_CTX_init(ctx.get(), EVP_aead_aes_256_gcm(), kZeros, 32,
|
||||
EVP_AEAD_DEFAULT_TAG_LENGTH, nullptr));
|
||||
|
||||
EXPECT_FALSE(EVP_AEAD_CTX_seal(ctx.get(), buf, &len, sizeof(buf),
|
||||
nullptr /* nonce */, 0, nullptr /* in */, 0,
|
||||
nullptr /* ad */, 0));
|
||||
err = ERR_get_error();
|
||||
EXPECT_EQ(ERR_LIB_CIPHER, ERR_GET_LIB(err));
|
||||
EXPECT_EQ(CIPHER_R_INVALID_NONCE_SIZE, ERR_GET_REASON(err));
|
||||
|
||||
EXPECT_FALSE(EVP_AEAD_CTX_open(ctx.get(), buf, &len, sizeof(buf),
|
||||
nullptr /* nonce */, 0, kZeros /* in */,
|
||||
sizeof(kZeros), nullptr /* ad */, 0));
|
||||
err = ERR_get_error();
|
||||
EXPECT_EQ(ERR_LIB_CIPHER, ERR_GET_LIB(err));
|
||||
EXPECT_EQ(CIPHER_R_INVALID_NONCE_SIZE, ERR_GET_REASON(err));
|
||||
}
|
@ -12,31 +12,95 @@
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <openssl/aead.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/cipher.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include "../internal.h"
|
||||
#include "../test/file_test.h"
|
||||
#include "../test/test_util.h"
|
||||
|
||||
|
||||
#if defined(OPENSSL_SMALL)
|
||||
const EVP_AEAD* EVP_aead_aes_128_gcm_siv(void) {
|
||||
return nullptr;
|
||||
}
|
||||
const EVP_AEAD* EVP_aead_aes_256_gcm_siv(void) {
|
||||
return nullptr;
|
||||
}
|
||||
struct KnownAEAD {
|
||||
const char name[40];
|
||||
const EVP_AEAD *(*func)(void);
|
||||
const char *test_vectors;
|
||||
// limited_implementation indicates that tests that assume a generic AEAD
|
||||
// interface should not be performed. For example, the key-wrap AEADs only
|
||||
// handle inputs that are a multiple of eight bytes in length and the
|
||||
// SSLv3/TLS AEADs have the concept of “direction”.
|
||||
bool limited_implementation;
|
||||
// truncated_tags is true if the AEAD supports truncating tags to arbitrary
|
||||
// lengths.
|
||||
bool truncated_tags;
|
||||
};
|
||||
|
||||
static const struct KnownAEAD kAEADs[] = {
|
||||
{"AES_128_GCM", EVP_aead_aes_128_gcm, "aes_128_gcm_tests.txt", false, true},
|
||||
{"AES_128_GCM_NIST", EVP_aead_aes_128_gcm, "nist_cavp/aes_128_gcm.txt",
|
||||
false, true},
|
||||
{"AES_256_GCM", EVP_aead_aes_256_gcm, "aes_256_gcm_tests.txt", false, true},
|
||||
{"AES_256_GCM_NIST", EVP_aead_aes_256_gcm, "nist_cavp/aes_256_gcm.txt",
|
||||
false, true},
|
||||
#if !defined(OPENSSL_SMALL)
|
||||
{"AES_128_GCM_SIV", EVP_aead_aes_128_gcm_siv, "aes_128_gcm_siv_tests.txt",
|
||||
false, false},
|
||||
{"AES_256_GCM_SIV", EVP_aead_aes_256_gcm_siv, "aes_256_gcm_siv_tests.txt",
|
||||
false, false},
|
||||
#endif
|
||||
{"ChaCha20Poly1305", EVP_aead_chacha20_poly1305,
|
||||
"chacha20_poly1305_tests.txt", false, true},
|
||||
{"AES_128_CBC_SHA1_TLS", EVP_aead_aes_128_cbc_sha1_tls,
|
||||
"aes_128_cbc_sha1_tls_tests.txt", true, false},
|
||||
{"AES_128_CBC_SHA1_TLSImplicitIV",
|
||||
EVP_aead_aes_128_cbc_sha1_tls_implicit_iv,
|
||||
"aes_128_cbc_sha1_tls_implicit_iv_tests.txt", true, false},
|
||||
{"AES_128_CBC_SHA256_TLS", EVP_aead_aes_128_cbc_sha256_tls,
|
||||
"aes_128_cbc_sha256_tls_tests.txt", true, false},
|
||||
{"AES_256_CBC_SHA1_TLS", EVP_aead_aes_256_cbc_sha1_tls,
|
||||
"aes_256_cbc_sha1_tls_tests.txt", true, false},
|
||||
{"AES_256_CBC_SHA1_TLSImplicitIV",
|
||||
EVP_aead_aes_256_cbc_sha1_tls_implicit_iv,
|
||||
"aes_256_cbc_sha1_tls_implicit_iv_tests.txt", true, false},
|
||||
{"AES_256_CBC_SHA256_TLS", EVP_aead_aes_256_cbc_sha256_tls,
|
||||
"aes_256_cbc_sha256_tls_tests.txt", true, false},
|
||||
{"AES_256_CBC_SHA384_TLS", EVP_aead_aes_256_cbc_sha384_tls,
|
||||
"aes_256_cbc_sha384_tls_tests.txt", true, false},
|
||||
{"DES_EDE3_CBC_SHA1_TLS", EVP_aead_des_ede3_cbc_sha1_tls,
|
||||
"des_ede3_cbc_sha1_tls_tests.txt", true, false},
|
||||
{"DES_EDE3_CBC_SHA1_TLSImplicitIV",
|
||||
EVP_aead_des_ede3_cbc_sha1_tls_implicit_iv,
|
||||
"des_ede3_cbc_sha1_tls_implicit_iv_tests.txt", true, false},
|
||||
{"AES_128_CBC_SHA1_SSL3", EVP_aead_aes_128_cbc_sha1_ssl3,
|
||||
"aes_128_cbc_sha1_ssl3_tests.txt", true, false},
|
||||
{"AES_256_CBC_SHA1_SSL3", EVP_aead_aes_256_cbc_sha1_ssl3,
|
||||
"aes_256_cbc_sha1_ssl3_tests.txt", true, false},
|
||||
{"DES_EDE3_CBC_SHA1_SSL3", EVP_aead_des_ede3_cbc_sha1_ssl3,
|
||||
"des_ede3_cbc_sha1_ssl3_tests.txt", true, false},
|
||||
{"AES_128_CTR_HMAC_SHA256", EVP_aead_aes_128_ctr_hmac_sha256,
|
||||
"aes_128_ctr_hmac_sha256.txt", false, true},
|
||||
{"AES_256_CTR_HMAC_SHA256", EVP_aead_aes_256_ctr_hmac_sha256,
|
||||
"aes_256_ctr_hmac_sha256.txt", false, true},
|
||||
};
|
||||
|
||||
// This program tests an AEAD against a series of test vectors from a file,
|
||||
// using the FileTest format. As an example, here's a valid test case:
|
||||
class PerAEADTest : public testing::TestWithParam<KnownAEAD> {
|
||||
public:
|
||||
const EVP_AEAD *aead() { return GetParam().func(); }
|
||||
};
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(, PerAEADTest, testing::ValuesIn(kAEADs),
|
||||
[](const testing::TestParamInfo<KnownAEAD> ¶ms)
|
||||
-> std::string { return params.param.name; });
|
||||
|
||||
// Tests an AEAD against a series of test vectors from a file, using the
|
||||
// FileTest format. As an example, here's a valid test case:
|
||||
//
|
||||
// KEY: 5a19f3173586b4c42f8412f4d5a786531b3231753e9e00998aec12fda8df10e4
|
||||
// NONCE: 978105dfce667bf4
|
||||
@ -44,177 +108,134 @@ const EVP_AEAD* EVP_aead_aes_256_gcm_siv(void) {
|
||||
// AD: b654574932
|
||||
// CT: 5294265a60
|
||||
// TAG: 1d45758621762e061368e68868e2f929
|
||||
TEST_P(PerAEADTest, TestVector) {
|
||||
std::string test_vectors = "crypto/cipher_extra/test/";
|
||||
test_vectors += GetParam().test_vectors;
|
||||
FileTestGTest(test_vectors.c_str(), [&](FileTest *t) {
|
||||
std::vector<uint8_t> key, nonce, in, ad, ct, tag;
|
||||
ASSERT_TRUE(t->GetBytes(&key, "KEY"));
|
||||
ASSERT_TRUE(t->GetBytes(&nonce, "NONCE"));
|
||||
ASSERT_TRUE(t->GetBytes(&in, "IN"));
|
||||
ASSERT_TRUE(t->GetBytes(&ad, "AD"));
|
||||
ASSERT_TRUE(t->GetBytes(&ct, "CT"));
|
||||
ASSERT_TRUE(t->GetBytes(&tag, "TAG"));
|
||||
|
||||
static bool TestAEAD(FileTest *t, void *arg) {
|
||||
const EVP_AEAD *aead = reinterpret_cast<const EVP_AEAD*>(arg);
|
||||
bssl::ScopedEVP_AEAD_CTX ctx;
|
||||
ASSERT_TRUE(EVP_AEAD_CTX_init_with_direction(
|
||||
ctx.get(), aead(), key.data(), key.size(), tag.size(), evp_aead_seal));
|
||||
|
||||
std::vector<uint8_t> key, nonce, in, ad, ct, tag;
|
||||
if (!t->GetBytes(&key, "KEY") ||
|
||||
!t->GetBytes(&nonce, "NONCE") ||
|
||||
!t->GetBytes(&in, "IN") ||
|
||||
!t->GetBytes(&ad, "AD") ||
|
||||
!t->GetBytes(&ct, "CT") ||
|
||||
!t->GetBytes(&tag, "TAG")) {
|
||||
return false;
|
||||
}
|
||||
std::vector<uint8_t> out(in.size() + EVP_AEAD_max_overhead(aead()));
|
||||
if (!t->HasAttribute("NO_SEAL")) {
|
||||
size_t out_len;
|
||||
ASSERT_TRUE(EVP_AEAD_CTX_seal(ctx.get(), out.data(), &out_len, out.size(),
|
||||
nonce.data(), nonce.size(), in.data(),
|
||||
in.size(), ad.data(), ad.size()));
|
||||
out.resize(out_len);
|
||||
|
||||
bssl::ScopedEVP_AEAD_CTX ctx;
|
||||
if (!EVP_AEAD_CTX_init_with_direction(ctx.get(), aead, key.data(), key.size(),
|
||||
tag.size(), evp_aead_seal)) {
|
||||
t->PrintLine("Failed to init AEAD.");
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> out(in.size() + EVP_AEAD_max_overhead(aead));
|
||||
if (!t->HasAttribute("NO_SEAL")) {
|
||||
size_t out_len;
|
||||
if (!EVP_AEAD_CTX_seal(ctx.get(), out.data(), &out_len, out.size(),
|
||||
nonce.data(), nonce.size(), in.data(), in.size(),
|
||||
ad.data(), ad.size())) {
|
||||
t->PrintLine("Failed to run AEAD.");
|
||||
return false;
|
||||
ASSERT_EQ(out.size(), ct.size() + tag.size());
|
||||
EXPECT_EQ(Bytes(ct), Bytes(out.data(), ct.size()));
|
||||
EXPECT_EQ(Bytes(tag), Bytes(out.data() + ct.size(), tag.size()));
|
||||
} else {
|
||||
out.resize(ct.size() + tag.size());
|
||||
OPENSSL_memcpy(out.data(), ct.data(), ct.size());
|
||||
OPENSSL_memcpy(out.data() + ct.size(), tag.data(), tag.size());
|
||||
}
|
||||
out.resize(out_len);
|
||||
|
||||
if (out.size() != ct.size() + tag.size()) {
|
||||
t->PrintLine("Bad output length: %u vs %u.", (unsigned)out_len,
|
||||
(unsigned)(ct.size() + tag.size()));
|
||||
return false;
|
||||
}
|
||||
if (!t->ExpectBytesEqual(ct.data(), ct.size(), out.data(), ct.size()) ||
|
||||
!t->ExpectBytesEqual(tag.data(), tag.size(), out.data() + ct.size(),
|
||||
tag.size())) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
out.resize(ct.size() + tag.size());
|
||||
OPENSSL_memcpy(out.data(), ct.data(), ct.size());
|
||||
OPENSSL_memcpy(out.data() + ct.size(), tag.data(), tag.size());
|
||||
}
|
||||
// The "stateful" AEADs for implementing pre-AEAD cipher suites need to be
|
||||
// reset after each operation.
|
||||
ctx.Reset();
|
||||
ASSERT_TRUE(EVP_AEAD_CTX_init_with_direction(
|
||||
ctx.get(), aead(), key.data(), key.size(), tag.size(), evp_aead_open));
|
||||
|
||||
// The "stateful" AEADs for implementing pre-AEAD cipher suites need to be
|
||||
// reset after each operation.
|
||||
ctx.Reset();
|
||||
if (!EVP_AEAD_CTX_init_with_direction(ctx.get(), aead, key.data(), key.size(),
|
||||
tag.size(), evp_aead_open)) {
|
||||
t->PrintLine("Failed to init AEAD.");
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> out2(out.size());
|
||||
size_t out2_len;
|
||||
int ret = EVP_AEAD_CTX_open(ctx.get(), out2.data(), &out2_len, out2.size(),
|
||||
nonce.data(), nonce.size(), out.data(),
|
||||
out.size(), ad.data(), ad.size());
|
||||
if (t->HasAttribute("FAILS")) {
|
||||
if (ret) {
|
||||
t->PrintLine("Decrypted bad data.");
|
||||
return false;
|
||||
std::vector<uint8_t> out2(out.size());
|
||||
size_t out2_len;
|
||||
int ret = EVP_AEAD_CTX_open(ctx.get(), out2.data(), &out2_len, out2.size(),
|
||||
nonce.data(), nonce.size(), out.data(),
|
||||
out.size(), ad.data(), ad.size());
|
||||
if (t->HasAttribute("FAILS")) {
|
||||
ASSERT_FALSE(ret) << "Decrypted bad data.";
|
||||
ERR_clear_error();
|
||||
return;
|
||||
}
|
||||
|
||||
ASSERT_TRUE(ret) << "Failed to decrypt.";
|
||||
out2.resize(out2_len);
|
||||
EXPECT_EQ(Bytes(in), Bytes(out2));
|
||||
|
||||
// The "stateful" AEADs for implementing pre-AEAD cipher suites need to be
|
||||
// reset after each operation.
|
||||
ctx.Reset();
|
||||
ASSERT_TRUE(EVP_AEAD_CTX_init_with_direction(
|
||||
ctx.get(), aead(), key.data(), key.size(), tag.size(), evp_aead_open));
|
||||
|
||||
// Garbage at the end isn't ignored.
|
||||
out.push_back(0);
|
||||
out2.resize(out.size());
|
||||
EXPECT_FALSE(EVP_AEAD_CTX_open(
|
||||
ctx.get(), out2.data(), &out2_len, out2.size(), nonce.data(),
|
||||
nonce.size(), out.data(), out.size(), ad.data(), ad.size()))
|
||||
<< "Decrypted bad data with trailing garbage.";
|
||||
ERR_clear_error();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
t->PrintLine("Failed to decrypt.");
|
||||
return false;
|
||||
}
|
||||
out2.resize(out2_len);
|
||||
if (!t->ExpectBytesEqual(in.data(), in.size(), out2.data(), out2.size())) {
|
||||
return false;
|
||||
}
|
||||
// The "stateful" AEADs for implementing pre-AEAD cipher suites need to be
|
||||
// reset after each operation.
|
||||
ctx.Reset();
|
||||
ASSERT_TRUE(EVP_AEAD_CTX_init_with_direction(
|
||||
ctx.get(), aead(), key.data(), key.size(), tag.size(), evp_aead_open));
|
||||
|
||||
// The "stateful" AEADs for implementing pre-AEAD cipher suites need to be
|
||||
// reset after each operation.
|
||||
ctx.Reset();
|
||||
if (!EVP_AEAD_CTX_init_with_direction(ctx.get(), aead, key.data(), key.size(),
|
||||
tag.size(), evp_aead_open)) {
|
||||
t->PrintLine("Failed to init AEAD.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Garbage at the end isn't ignored.
|
||||
out.push_back(0);
|
||||
out2.resize(out.size());
|
||||
if (EVP_AEAD_CTX_open(ctx.get(), out2.data(), &out2_len, out2.size(),
|
||||
nonce.data(), nonce.size(), out.data(), out.size(),
|
||||
ad.data(), ad.size())) {
|
||||
t->PrintLine("Decrypted bad data with trailing garbage.");
|
||||
return false;
|
||||
}
|
||||
ERR_clear_error();
|
||||
|
||||
// The "stateful" AEADs for implementing pre-AEAD cipher suites need to be
|
||||
// reset after each operation.
|
||||
ctx.Reset();
|
||||
if (!EVP_AEAD_CTX_init_with_direction(ctx.get(), aead, key.data(), key.size(),
|
||||
tag.size(), evp_aead_open)) {
|
||||
t->PrintLine("Failed to init AEAD.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Verify integrity is checked.
|
||||
out[0] ^= 0x80;
|
||||
out.resize(out.size() - 1);
|
||||
out2.resize(out.size());
|
||||
if (EVP_AEAD_CTX_open(ctx.get(), out2.data(), &out2_len, out2.size(),
|
||||
nonce.data(), nonce.size(), out.data(), out.size(),
|
||||
ad.data(), ad.size())) {
|
||||
t->PrintLine("Decrypted bad data with corrupted byte.");
|
||||
return false;
|
||||
}
|
||||
ERR_clear_error();
|
||||
|
||||
return true;
|
||||
// Verify integrity is checked.
|
||||
out[0] ^= 0x80;
|
||||
out.resize(out.size() - 1);
|
||||
out2.resize(out.size());
|
||||
EXPECT_FALSE(EVP_AEAD_CTX_open(
|
||||
ctx.get(), out2.data(), &out2_len, out2.size(), nonce.data(),
|
||||
nonce.size(), out.data(), out.size(), ad.data(), ad.size()))
|
||||
<< "Decrypted bad data with corrupted byte.";
|
||||
ERR_clear_error();
|
||||
});
|
||||
}
|
||||
|
||||
static int TestCleanupAfterInitFailure(const EVP_AEAD *aead) {
|
||||
TEST_P(PerAEADTest, CleanupAfterInitFailure) {
|
||||
uint8_t key[EVP_AEAD_MAX_KEY_LENGTH];
|
||||
OPENSSL_memset(key, 0, sizeof(key));
|
||||
const size_t key_len = EVP_AEAD_key_length(aead);
|
||||
assert(sizeof(key) >= key_len);
|
||||
const size_t key_len = EVP_AEAD_key_length(aead());
|
||||
ASSERT_GE(sizeof(key), key_len);
|
||||
|
||||
EVP_AEAD_CTX ctx;
|
||||
if (EVP_AEAD_CTX_init(&ctx, aead, key, key_len,
|
||||
9999 /* a silly tag length to trigger an error */,
|
||||
NULL /* ENGINE */) != 0) {
|
||||
fprintf(stderr, "A silly tag length didn't trigger an error!\n");
|
||||
return 0;
|
||||
}
|
||||
ASSERT_FALSE(EVP_AEAD_CTX_init(
|
||||
&ctx, aead(), key, key_len,
|
||||
9999 /* a silly tag length to trigger an error */, NULL /* ENGINE */));
|
||||
ERR_clear_error();
|
||||
|
||||
/* Running a second, failed _init should not cause a memory leak. */
|
||||
if (EVP_AEAD_CTX_init(&ctx, aead, key, key_len,
|
||||
9999 /* a silly tag length to trigger an error */,
|
||||
NULL /* ENGINE */) != 0) {
|
||||
fprintf(stderr, "A silly tag length didn't trigger an error!\n");
|
||||
return 0;
|
||||
}
|
||||
ASSERT_FALSE(EVP_AEAD_CTX_init(
|
||||
&ctx, aead(), key, key_len,
|
||||
9999 /* a silly tag length to trigger an error */, NULL /* ENGINE */));
|
||||
ERR_clear_error();
|
||||
|
||||
/* Calling _cleanup on an |EVP_AEAD_CTX| after a failed _init should be a
|
||||
* no-op. */
|
||||
EVP_AEAD_CTX_cleanup(&ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int TestTruncatedTags(const EVP_AEAD *aead) {
|
||||
TEST_P(PerAEADTest, TruncatedTags) {
|
||||
if (!GetParam().truncated_tags) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t key[EVP_AEAD_MAX_KEY_LENGTH];
|
||||
OPENSSL_memset(key, 0, sizeof(key));
|
||||
const size_t key_len = EVP_AEAD_key_length(aead);
|
||||
assert(sizeof(key) >= key_len);
|
||||
const size_t key_len = EVP_AEAD_key_length(aead());
|
||||
ASSERT_GE(sizeof(key), key_len);
|
||||
|
||||
uint8_t nonce[EVP_AEAD_MAX_NONCE_LENGTH];
|
||||
OPENSSL_memset(nonce, 0, sizeof(nonce));
|
||||
const size_t nonce_len = EVP_AEAD_nonce_length(aead);
|
||||
assert(sizeof(nonce) >= nonce_len);
|
||||
const size_t nonce_len = EVP_AEAD_nonce_length(aead());
|
||||
ASSERT_GE(sizeof(nonce), nonce_len);
|
||||
|
||||
bssl::ScopedEVP_AEAD_CTX ctx;
|
||||
if (!EVP_AEAD_CTX_init(ctx.get(), aead, key, key_len, 1 /* one byte tag */,
|
||||
NULL /* ENGINE */)) {
|
||||
fprintf(stderr, "Couldn't initialise AEAD with truncated tag.\n");
|
||||
return 1;
|
||||
}
|
||||
ASSERT_TRUE(EVP_AEAD_CTX_init(ctx.get(), aead(), key, key_len,
|
||||
1 /* one byte tag */, NULL /* ENGINE */));
|
||||
|
||||
const uint8_t plaintext[1] = {'A'};
|
||||
|
||||
@ -223,68 +244,53 @@ static int TestTruncatedTags(const EVP_AEAD *aead) {
|
||||
constexpr uint8_t kSentinel = 42;
|
||||
OPENSSL_memset(ciphertext, kSentinel, sizeof(ciphertext));
|
||||
|
||||
if (!EVP_AEAD_CTX_seal(ctx.get(), ciphertext, &ciphertext_len,
|
||||
sizeof(ciphertext), nonce, nonce_len, plaintext,
|
||||
sizeof(plaintext), nullptr /* ad */, 0)) {
|
||||
fprintf(stderr, "Sealing with truncated tag didn't work.\n");
|
||||
return 0;
|
||||
}
|
||||
ASSERT_TRUE(EVP_AEAD_CTX_seal(ctx.get(), ciphertext, &ciphertext_len,
|
||||
sizeof(ciphertext), nonce, nonce_len, plaintext,
|
||||
sizeof(plaintext), nullptr /* ad */, 0));
|
||||
|
||||
for (size_t i = ciphertext_len; i < sizeof(ciphertext); i++) {
|
||||
// Sealing must not write past where it said it did.
|
||||
if (ciphertext[i] != kSentinel) {
|
||||
fprintf(stderr, "Sealing wrote off the end of the buffer.\n");
|
||||
return 0;
|
||||
}
|
||||
EXPECT_EQ(kSentinel, ciphertext[i])
|
||||
<< "Sealing wrote off the end of the buffer.";
|
||||
}
|
||||
|
||||
const size_t overhead_used = ciphertext_len - sizeof(plaintext);
|
||||
const size_t expected_overhead =
|
||||
1 + EVP_AEAD_max_overhead(aead) - EVP_AEAD_max_tag_len(aead);
|
||||
if (overhead_used != expected_overhead) {
|
||||
fprintf(stderr, "AEAD is probably ignoring request to truncate tags.\n");
|
||||
return 0;
|
||||
}
|
||||
1 + EVP_AEAD_max_overhead(aead()) - EVP_AEAD_max_tag_len(aead());
|
||||
EXPECT_EQ(overhead_used, expected_overhead)
|
||||
<< "AEAD is probably ignoring request to truncate tags.";
|
||||
|
||||
uint8_t plaintext2[sizeof(plaintext) + 16];
|
||||
OPENSSL_memset(plaintext2, kSentinel, sizeof(plaintext2));
|
||||
|
||||
size_t plaintext2_len;
|
||||
if (!EVP_AEAD_CTX_open(ctx.get(), plaintext2, &plaintext2_len,
|
||||
sizeof(plaintext2), nonce, nonce_len, ciphertext,
|
||||
ciphertext_len, nullptr /* ad */, 0)) {
|
||||
fprintf(stderr, "Opening with truncated tag didn't work.\n");
|
||||
return 0;
|
||||
}
|
||||
ASSERT_TRUE(EVP_AEAD_CTX_open(
|
||||
ctx.get(), plaintext2, &plaintext2_len, sizeof(plaintext2), nonce,
|
||||
nonce_len, ciphertext, ciphertext_len, nullptr /* ad */, 0))
|
||||
<< "Opening with truncated tag didn't work.";
|
||||
|
||||
for (size_t i = plaintext2_len; i < sizeof(plaintext2); i++) {
|
||||
// Likewise, opening should also stay within bounds.
|
||||
if (plaintext2[i] != kSentinel) {
|
||||
fprintf(stderr, "Opening wrote off the end of the buffer.\n");
|
||||
return 0;
|
||||
}
|
||||
EXPECT_EQ(kSentinel, plaintext2[i])
|
||||
<< "Opening wrote off the end of the buffer.";
|
||||
}
|
||||
|
||||
if (plaintext2_len != sizeof(plaintext) ||
|
||||
OPENSSL_memcmp(plaintext2, plaintext, sizeof(plaintext)) != 0) {
|
||||
fprintf(stderr, "Opening with truncated tag gave wrong result.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
EXPECT_EQ(Bytes(plaintext), Bytes(plaintext2, plaintext2_len));
|
||||
}
|
||||
|
||||
static bool TestWithAliasedBuffers(const EVP_AEAD *aead) {
|
||||
const size_t key_len = EVP_AEAD_key_length(aead);
|
||||
const size_t nonce_len = EVP_AEAD_nonce_length(aead);
|
||||
const size_t max_overhead = EVP_AEAD_max_overhead(aead);
|
||||
TEST_P(PerAEADTest, AliasedBuffers) {
|
||||
if (GetParam().limited_implementation) {
|
||||
return;
|
||||
}
|
||||
|
||||
const size_t key_len = EVP_AEAD_key_length(aead());
|
||||
const size_t nonce_len = EVP_AEAD_nonce_length(aead());
|
||||
const size_t max_overhead = EVP_AEAD_max_overhead(aead());
|
||||
|
||||
std::vector<uint8_t> key(key_len, 'a');
|
||||
bssl::ScopedEVP_AEAD_CTX ctx;
|
||||
if (!EVP_AEAD_CTX_init(ctx.get(), aead, key.data(), key_len,
|
||||
EVP_AEAD_DEFAULT_TAG_LENGTH, nullptr)) {
|
||||
return false;
|
||||
}
|
||||
ASSERT_TRUE(EVP_AEAD_CTX_init(ctx.get(), aead(), key.data(), key_len,
|
||||
EVP_AEAD_DEFAULT_TAG_LENGTH, nullptr));
|
||||
|
||||
static const uint8_t kPlaintext[260] =
|
||||
"testing123456testing123456testing123456testing123456testing123456testing"
|
||||
@ -299,13 +305,11 @@ static bool TestWithAliasedBuffers(const EVP_AEAD *aead) {
|
||||
std::vector<uint8_t> nonce(nonce_len, 'b');
|
||||
std::vector<uint8_t> valid_encryption(sizeof(kPlaintext) + max_overhead);
|
||||
size_t valid_encryption_len;
|
||||
if (!EVP_AEAD_CTX_seal(
|
||||
ctx.get(), valid_encryption.data(), &valid_encryption_len,
|
||||
sizeof(kPlaintext) + max_overhead, nonce.data(), nonce_len,
|
||||
kPlaintext, sizeof(kPlaintext), nullptr, 0)) {
|
||||
fprintf(stderr, "EVP_AEAD_CTX_seal failed with disjoint buffers.\n");
|
||||
return false;
|
||||
}
|
||||
ASSERT_TRUE(EVP_AEAD_CTX_seal(
|
||||
ctx.get(), valid_encryption.data(), &valid_encryption_len,
|
||||
sizeof(kPlaintext) + max_overhead, nonce.data(), nonce_len, kPlaintext,
|
||||
sizeof(kPlaintext), nullptr, 0))
|
||||
<< "EVP_AEAD_CTX_seal failed with disjoint buffers.";
|
||||
|
||||
// Test with out != in which we expect to fail.
|
||||
std::vector<uint8_t> buffer(2 + valid_encryption_len);
|
||||
@ -315,138 +319,81 @@ static bool TestWithAliasedBuffers(const EVP_AEAD *aead) {
|
||||
|
||||
OPENSSL_memcpy(in, kPlaintext, sizeof(kPlaintext));
|
||||
size_t out_len;
|
||||
if (EVP_AEAD_CTX_seal(ctx.get(), out1, &out_len,
|
||||
sizeof(kPlaintext) + max_overhead, nonce.data(),
|
||||
nonce_len, in, sizeof(kPlaintext), nullptr, 0) ||
|
||||
EVP_AEAD_CTX_seal(ctx.get(), out2, &out_len,
|
||||
sizeof(kPlaintext) + max_overhead, nonce.data(),
|
||||
nonce_len, in, sizeof(kPlaintext), nullptr, 0)) {
|
||||
fprintf(stderr, "EVP_AEAD_CTX_seal unexpectedly succeeded.\n");
|
||||
return false;
|
||||
}
|
||||
EXPECT_FALSE(EVP_AEAD_CTX_seal(
|
||||
ctx.get(), out1 /* in - 1 */, &out_len, sizeof(kPlaintext) + max_overhead,
|
||||
nonce.data(), nonce_len, in, sizeof(kPlaintext), nullptr, 0));
|
||||
EXPECT_FALSE(EVP_AEAD_CTX_seal(
|
||||
ctx.get(), out2 /* in + 1 */, &out_len, sizeof(kPlaintext) + max_overhead,
|
||||
nonce.data(), nonce_len, in, sizeof(kPlaintext), nullptr, 0));
|
||||
ERR_clear_error();
|
||||
|
||||
OPENSSL_memcpy(in, valid_encryption.data(), valid_encryption_len);
|
||||
if (EVP_AEAD_CTX_open(ctx.get(), out1, &out_len, valid_encryption_len,
|
||||
nonce.data(), nonce_len, in, valid_encryption_len,
|
||||
nullptr, 0) ||
|
||||
EVP_AEAD_CTX_open(ctx.get(), out2, &out_len, valid_encryption_len,
|
||||
nonce.data(), nonce_len, in, valid_encryption_len,
|
||||
nullptr, 0)) {
|
||||
fprintf(stderr, "EVP_AEAD_CTX_open unexpectedly succeeded.\n");
|
||||
return false;
|
||||
}
|
||||
EXPECT_FALSE(EVP_AEAD_CTX_open(ctx.get(), out1 /* in - 1 */, &out_len,
|
||||
valid_encryption_len, nonce.data(), nonce_len,
|
||||
in, valid_encryption_len, nullptr, 0));
|
||||
EXPECT_FALSE(EVP_AEAD_CTX_open(ctx.get(), out2 /* in + 1 */, &out_len,
|
||||
valid_encryption_len, nonce.data(), nonce_len,
|
||||
in, valid_encryption_len, nullptr, 0));
|
||||
ERR_clear_error();
|
||||
|
||||
// Test with out == in, which we expect to work.
|
||||
OPENSSL_memcpy(in, kPlaintext, sizeof(kPlaintext));
|
||||
|
||||
if (!EVP_AEAD_CTX_seal(ctx.get(), in, &out_len,
|
||||
sizeof(kPlaintext) + max_overhead, nonce.data(),
|
||||
nonce_len, in, sizeof(kPlaintext), nullptr, 0)) {
|
||||
fprintf(stderr, "EVP_AEAD_CTX_seal failed in-place.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (out_len != valid_encryption_len ||
|
||||
OPENSSL_memcmp(in, valid_encryption.data(), out_len) != 0) {
|
||||
fprintf(stderr, "EVP_AEAD_CTX_seal produced bad output in-place.\n");
|
||||
return false;
|
||||
}
|
||||
ASSERT_TRUE(EVP_AEAD_CTX_seal(ctx.get(), in, &out_len,
|
||||
sizeof(kPlaintext) + max_overhead, nonce.data(),
|
||||
nonce_len, in, sizeof(kPlaintext), nullptr, 0));
|
||||
EXPECT_EQ(Bytes(valid_encryption.data(), valid_encryption_len),
|
||||
Bytes(in, out_len));
|
||||
|
||||
OPENSSL_memcpy(in, valid_encryption.data(), valid_encryption_len);
|
||||
if (!EVP_AEAD_CTX_open(ctx.get(), in, &out_len, valid_encryption_len,
|
||||
nonce.data(), nonce_len, in, valid_encryption_len,
|
||||
nullptr, 0)) {
|
||||
fprintf(stderr, "EVP_AEAD_CTX_open failed in-place.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (out_len != sizeof(kPlaintext) ||
|
||||
OPENSSL_memcmp(in, kPlaintext, out_len) != 0) {
|
||||
fprintf(stderr, "EVP_AEAD_CTX_open produced bad output in-place.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
ASSERT_TRUE(EVP_AEAD_CTX_open(ctx.get(), in, &out_len, valid_encryption_len,
|
||||
nonce.data(), nonce_len, in,
|
||||
valid_encryption_len, nullptr, 0));
|
||||
EXPECT_EQ(Bytes(kPlaintext), Bytes(in, out_len));
|
||||
}
|
||||
|
||||
struct KnownAEAD {
|
||||
const char name[40];
|
||||
const EVP_AEAD *(*func)(void);
|
||||
// limited_implementation indicates that tests that assume a generic AEAD
|
||||
// interface should not be performed. For example, the key-wrap AEADs only
|
||||
// handle inputs that are a multiple of eight bytes in length and the
|
||||
// SSLv3/TLS AEADs have the concept of “direction”.
|
||||
bool limited_implementation;
|
||||
// truncated_tags is true if the AEAD supports truncating tags to arbitrary
|
||||
// lengths.
|
||||
bool truncated_tags;
|
||||
};
|
||||
// Test that EVP_aead_aes_128_gcm and EVP_aead_aes_256_gcm reject empty nonces.
|
||||
// AES-GCM is not defined for those.
|
||||
TEST(AEADTest, AESGCMEmptyNonce) {
|
||||
static const uint8_t kZeros[32] = {0};
|
||||
|
||||
static const struct KnownAEAD kAEADs[] = {
|
||||
{ "aes-128-gcm", EVP_aead_aes_128_gcm, false, true },
|
||||
{ "aes-256-gcm", EVP_aead_aes_256_gcm, false, true },
|
||||
{ "aes-128-gcm-siv", EVP_aead_aes_128_gcm_siv, false, false },
|
||||
{ "aes-256-gcm-siv", EVP_aead_aes_256_gcm_siv, false, false },
|
||||
{ "chacha20-poly1305", EVP_aead_chacha20_poly1305, false, true },
|
||||
{ "aes-128-cbc-sha1-tls", EVP_aead_aes_128_cbc_sha1_tls, true, false },
|
||||
{ "aes-128-cbc-sha1-tls-implicit-iv", EVP_aead_aes_128_cbc_sha1_tls_implicit_iv, true, false },
|
||||
{ "aes-128-cbc-sha256-tls", EVP_aead_aes_128_cbc_sha256_tls, true, false },
|
||||
{ "aes-256-cbc-sha1-tls", EVP_aead_aes_256_cbc_sha1_tls, true, false },
|
||||
{ "aes-256-cbc-sha1-tls-implicit-iv", EVP_aead_aes_256_cbc_sha1_tls_implicit_iv, true, false },
|
||||
{ "aes-256-cbc-sha256-tls", EVP_aead_aes_256_cbc_sha256_tls, true, false },
|
||||
{ "aes-256-cbc-sha384-tls", EVP_aead_aes_256_cbc_sha384_tls, true, false },
|
||||
{ "des-ede3-cbc-sha1-tls", EVP_aead_des_ede3_cbc_sha1_tls, true, false },
|
||||
{ "des-ede3-cbc-sha1-tls-implicit-iv", EVP_aead_des_ede3_cbc_sha1_tls_implicit_iv, true, false },
|
||||
{ "aes-128-cbc-sha1-ssl3", EVP_aead_aes_128_cbc_sha1_ssl3, true, false },
|
||||
{ "aes-256-cbc-sha1-ssl3", EVP_aead_aes_256_cbc_sha1_ssl3, true, false },
|
||||
{ "des-ede3-cbc-sha1-ssl3", EVP_aead_des_ede3_cbc_sha1_ssl3, true, false },
|
||||
{ "aes-128-ctr-hmac-sha256", EVP_aead_aes_128_ctr_hmac_sha256, false, true },
|
||||
{ "aes-256-ctr-hmac-sha256", EVP_aead_aes_256_ctr_hmac_sha256, false, true },
|
||||
{ "", NULL, false, false },
|
||||
};
|
||||
// Test AES-128-GCM.
|
||||
uint8_t buf[16];
|
||||
size_t len;
|
||||
bssl::ScopedEVP_AEAD_CTX ctx;
|
||||
ASSERT_TRUE(EVP_AEAD_CTX_init(ctx.get(), EVP_aead_aes_128_gcm(), kZeros, 16,
|
||||
EVP_AEAD_DEFAULT_TAG_LENGTH, nullptr));
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
CRYPTO_library_init();
|
||||
EXPECT_FALSE(EVP_AEAD_CTX_seal(ctx.get(), buf, &len, sizeof(buf),
|
||||
nullptr /* nonce */, 0, nullptr /* in */, 0,
|
||||
nullptr /* ad */, 0));
|
||||
uint32_t err = ERR_get_error();
|
||||
EXPECT_EQ(ERR_LIB_CIPHER, ERR_GET_LIB(err));
|
||||
EXPECT_EQ(CIPHER_R_INVALID_NONCE_SIZE, ERR_GET_REASON(err));
|
||||
|
||||
if (argc != 3) {
|
||||
fprintf(stderr, "%s <aead> <test file.txt>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
EXPECT_FALSE(EVP_AEAD_CTX_open(ctx.get(), buf, &len, sizeof(buf),
|
||||
nullptr /* nonce */, 0, kZeros /* in */,
|
||||
sizeof(kZeros), nullptr /* ad */, 0));
|
||||
err = ERR_get_error();
|
||||
EXPECT_EQ(ERR_LIB_CIPHER, ERR_GET_LIB(err));
|
||||
EXPECT_EQ(CIPHER_R_INVALID_NONCE_SIZE, ERR_GET_REASON(err));
|
||||
|
||||
const struct KnownAEAD *known_aead;
|
||||
for (unsigned i = 0;; i++) {
|
||||
known_aead = &kAEADs[i];
|
||||
if (known_aead->func == NULL) {
|
||||
fprintf(stderr, "Unknown AEAD: %s\n", argv[1]);
|
||||
return 2;
|
||||
}
|
||||
if (strcmp(known_aead->name, argv[1]) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Test AES-256-GCM.
|
||||
ctx.Reset();
|
||||
ASSERT_TRUE(EVP_AEAD_CTX_init(ctx.get(), EVP_aead_aes_256_gcm(), kZeros, 32,
|
||||
EVP_AEAD_DEFAULT_TAG_LENGTH, nullptr));
|
||||
|
||||
const EVP_AEAD *const aead = known_aead->func();
|
||||
if (aead == NULL) {
|
||||
// AEAD is not compiled in this configuration.
|
||||
printf("PASS\n");
|
||||
return 0;
|
||||
}
|
||||
EXPECT_FALSE(EVP_AEAD_CTX_seal(ctx.get(), buf, &len, sizeof(buf),
|
||||
nullptr /* nonce */, 0, nullptr /* in */, 0,
|
||||
nullptr /* ad */, 0));
|
||||
err = ERR_get_error();
|
||||
EXPECT_EQ(ERR_LIB_CIPHER, ERR_GET_LIB(err));
|
||||
EXPECT_EQ(CIPHER_R_INVALID_NONCE_SIZE, ERR_GET_REASON(err));
|
||||
|
||||
if (!TestCleanupAfterInitFailure(aead)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (known_aead->truncated_tags && !TestTruncatedTags(aead)) {
|
||||
fprintf(stderr, "Truncated tags test failed for %s.\n", known_aead->name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!known_aead->limited_implementation && !TestWithAliasedBuffers(aead)) {
|
||||
fprintf(stderr, "Aliased buffers test failed for %s.\n", known_aead->name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return FileTestMain(TestAEAD, const_cast<EVP_AEAD*>(aead), argv[2]);
|
||||
EXPECT_FALSE(EVP_AEAD_CTX_open(ctx.get(), buf, &len, sizeof(buf),
|
||||
nullptr /* nonce */, 0, kZeros /* in */,
|
||||
sizeof(kZeros), nullptr /* ad */, 0));
|
||||
err = ERR_get_error();
|
||||
EXPECT_EQ(ERR_LIB_CIPHER, ERR_GET_LIB(err));
|
||||
EXPECT_EQ(CIPHER_R_INVALID_NONCE_SIZE, ERR_GET_REASON(err));
|
||||
}
|
||||
|
@ -57,11 +57,13 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <openssl/cipher.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include "../test/file_test.h"
|
||||
#include "../test/test_util.h"
|
||||
|
||||
|
||||
static const EVP_CIPHER *GetCipher(const std::string &name) {
|
||||
@ -109,11 +111,8 @@ static const EVP_CIPHER *GetCipher(const std::string &name) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static bool TestOperation(FileTest *t,
|
||||
const EVP_CIPHER *cipher,
|
||||
bool encrypt,
|
||||
size_t chunk_size,
|
||||
const std::vector<uint8_t> &key,
|
||||
static void TestOperation(FileTest *t, const EVP_CIPHER *cipher, bool encrypt,
|
||||
size_t chunk_size, const std::vector<uint8_t> &key,
|
||||
const std::vector<uint8_t> &iv,
|
||||
const std::vector<uint8_t> &plaintext,
|
||||
const std::vector<uint8_t> &ciphertext,
|
||||
@ -131,48 +130,36 @@ static bool TestOperation(FileTest *t,
|
||||
bool is_aead = EVP_CIPHER_mode(cipher) == EVP_CIPH_GCM_MODE;
|
||||
|
||||
bssl::ScopedEVP_CIPHER_CTX ctx;
|
||||
if (!EVP_CipherInit_ex(ctx.get(), cipher, nullptr, nullptr, nullptr,
|
||||
encrypt ? 1 : 0)) {
|
||||
return false;
|
||||
}
|
||||
ASSERT_TRUE(EVP_CipherInit_ex(ctx.get(), cipher, nullptr, nullptr, nullptr,
|
||||
encrypt ? 1 : 0));
|
||||
if (t->HasAttribute("IV")) {
|
||||
if (is_aead) {
|
||||
if (!EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_SET_IVLEN,
|
||||
iv.size(), 0)) {
|
||||
return false;
|
||||
}
|
||||
} else if (iv.size() != EVP_CIPHER_CTX_iv_length(ctx.get())) {
|
||||
t->PrintLine("Bad IV length.");
|
||||
return false;
|
||||
ASSERT_TRUE(
|
||||
EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_SET_IVLEN, iv.size(), 0));
|
||||
} else {
|
||||
ASSERT_EQ(iv.size(), EVP_CIPHER_CTX_iv_length(ctx.get()));
|
||||
}
|
||||
}
|
||||
if (is_aead && !encrypt &&
|
||||
!EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_SET_TAG, tag.size(),
|
||||
const_cast<uint8_t*>(tag.data()))) {
|
||||
return false;
|
||||
if (is_aead && !encrypt) {
|
||||
ASSERT_TRUE(EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_SET_TAG, tag.size(),
|
||||
const_cast<uint8_t *>(tag.data())));
|
||||
}
|
||||
// The ciphers are run with no padding. For each of the ciphers we test, the
|
||||
// output size matches the input size.
|
||||
std::vector<uint8_t> result(in->size());
|
||||
if (in->size() != out->size()) {
|
||||
t->PrintLine("Input/output size mismatch (%u vs %u).", (unsigned)in->size(),
|
||||
(unsigned)out->size());
|
||||
return false;
|
||||
}
|
||||
ASSERT_EQ(in->size(), out->size());
|
||||
int unused, result_len1 = 0, result_len2;
|
||||
ASSERT_TRUE(EVP_CIPHER_CTX_set_key_length(ctx.get(), key.size()));
|
||||
ASSERT_TRUE(EVP_CipherInit_ex(ctx.get(), nullptr, nullptr, key.data(),
|
||||
iv.data(), -1));
|
||||
// Note: the deprecated |EVP_CIPHER|-based AES-GCM API is sensitive to whether
|
||||
// parameters are NULL, so it is important to skip the |in| and |aad|
|
||||
// |EVP_CipherUpdate| calls when empty.
|
||||
int unused, result_len1 = 0, result_len2;
|
||||
if (!EVP_CIPHER_CTX_set_key_length(ctx.get(), key.size()) ||
|
||||
!EVP_CipherInit_ex(ctx.get(), nullptr, nullptr, key.data(), iv.data(),
|
||||
-1) ||
|
||||
(!aad.empty() &&
|
||||
!EVP_CipherUpdate(ctx.get(), nullptr, &unused, aad.data(),
|
||||
aad.size())) ||
|
||||
!EVP_CIPHER_CTX_set_padding(ctx.get(), 0)) {
|
||||
t->PrintLine("Operation failed.");
|
||||
return false;
|
||||
if (!aad.empty()) {
|
||||
ASSERT_TRUE(
|
||||
EVP_CipherUpdate(ctx.get(), nullptr, &unused, aad.data(), aad.size()));
|
||||
}
|
||||
ASSERT_TRUE(EVP_CIPHER_CTX_set_padding(ctx.get(), 0));
|
||||
if (chunk_size != 0) {
|
||||
for (size_t i = 0; i < in->size();) {
|
||||
size_t todo = chunk_size;
|
||||
@ -181,72 +168,44 @@ static bool TestOperation(FileTest *t,
|
||||
}
|
||||
|
||||
int len;
|
||||
if (!EVP_CipherUpdate(ctx.get(), result.data() + result_len1, &len,
|
||||
in->data() + i, todo)) {
|
||||
t->PrintLine("Operation failed.");
|
||||
return false;
|
||||
}
|
||||
ASSERT_TRUE(EVP_CipherUpdate(ctx.get(), result.data() + result_len1, &len,
|
||||
in->data() + i, todo));
|
||||
result_len1 += len;
|
||||
i += todo;
|
||||
}
|
||||
} else if (!in->empty() &&
|
||||
!EVP_CipherUpdate(ctx.get(), result.data(), &result_len1,
|
||||
in->data(), in->size())) {
|
||||
t->PrintLine("Operation failed.");
|
||||
return false;
|
||||
}
|
||||
if (!EVP_CipherFinal_ex(ctx.get(), result.data() + result_len1,
|
||||
&result_len2)) {
|
||||
t->PrintLine("Operation failed.");
|
||||
return false;
|
||||
} else if (!in->empty()) {
|
||||
ASSERT_TRUE(EVP_CipherUpdate(ctx.get(), result.data(), &result_len1,
|
||||
in->data(), in->size()));
|
||||
}
|
||||
ASSERT_TRUE(
|
||||
EVP_CipherFinal_ex(ctx.get(), result.data() + result_len1, &result_len2));
|
||||
result.resize(result_len1 + result_len2);
|
||||
if (!t->ExpectBytesEqual(out->data(), out->size(), result.data(),
|
||||
result.size())) {
|
||||
return false;
|
||||
}
|
||||
EXPECT_EQ(Bytes(*out), Bytes(result));
|
||||
if (encrypt && is_aead) {
|
||||
uint8_t rtag[16];
|
||||
if (tag.size() > sizeof(rtag)) {
|
||||
t->PrintLine("Bad tag length.");
|
||||
return false;
|
||||
}
|
||||
if (!EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_GET_TAG, tag.size(),
|
||||
rtag) ||
|
||||
!t->ExpectBytesEqual(tag.data(), tag.size(), rtag,
|
||||
tag.size())) {
|
||||
return false;
|
||||
}
|
||||
ASSERT_LE(tag.size(), sizeof(rtag));
|
||||
ASSERT_TRUE(
|
||||
EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_GET_TAG, tag.size(), rtag));
|
||||
EXPECT_EQ(Bytes(tag), Bytes(rtag, tag.size()));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool TestCipher(FileTest *t, void *arg) {
|
||||
static void TestCipher(FileTest *t) {
|
||||
std::string cipher_str;
|
||||
if (!t->GetAttribute(&cipher_str, "Cipher")) {
|
||||
return false;
|
||||
}
|
||||
ASSERT_TRUE(t->GetAttribute(&cipher_str, "Cipher"));
|
||||
const EVP_CIPHER *cipher = GetCipher(cipher_str);
|
||||
if (cipher == nullptr) {
|
||||
t->PrintLine("Unknown cipher: '%s'.", cipher_str.c_str());
|
||||
return false;
|
||||
}
|
||||
ASSERT_TRUE(cipher);
|
||||
|
||||
std::vector<uint8_t> key, iv, plaintext, ciphertext, aad, tag;
|
||||
if (!t->GetBytes(&key, "Key") ||
|
||||
!t->GetBytes(&plaintext, "Plaintext") ||
|
||||
!t->GetBytes(&ciphertext, "Ciphertext")) {
|
||||
return false;
|
||||
}
|
||||
if (EVP_CIPHER_iv_length(cipher) > 0 &&
|
||||
!t->GetBytes(&iv, "IV")) {
|
||||
return false;
|
||||
ASSERT_TRUE(t->GetBytes(&key, "Key"));
|
||||
ASSERT_TRUE(t->GetBytes(&plaintext, "Plaintext"));
|
||||
ASSERT_TRUE(t->GetBytes(&ciphertext, "Ciphertext"));
|
||||
if (EVP_CIPHER_iv_length(cipher) > 0) {
|
||||
ASSERT_TRUE(t->GetBytes(&iv, "IV"));
|
||||
}
|
||||
if (EVP_CIPHER_mode(cipher) == EVP_CIPH_GCM_MODE) {
|
||||
if (!t->GetBytes(&aad, "AAD") ||
|
||||
!t->GetBytes(&tag, "Tag")) {
|
||||
return false;
|
||||
}
|
||||
ASSERT_TRUE(t->GetBytes(&aad, "AAD"));
|
||||
ASSERT_TRUE(t->GetBytes(&tag, "Tag"));
|
||||
}
|
||||
|
||||
enum {
|
||||
@ -261,8 +220,7 @@ static bool TestCipher(FileTest *t, void *arg) {
|
||||
} else if (str == "DECRYPT") {
|
||||
operation = kDecrypt;
|
||||
} else {
|
||||
t->PrintLine("Unknown operation: '%s'.", str.c_str());
|
||||
return false;
|
||||
FAIL() << "Unknown operation: " << str;
|
||||
}
|
||||
}
|
||||
|
||||
@ -270,30 +228,60 @@ static bool TestCipher(FileTest *t, void *arg) {
|
||||
17, 31, 32, 33, 63, 64, 65, 512};
|
||||
|
||||
for (size_t chunk_size : chunk_sizes) {
|
||||
SCOPED_TRACE(chunk_size);
|
||||
// By default, both directions are run, unless overridden by the operation.
|
||||
if (operation != kDecrypt &&
|
||||
!TestOperation(t, cipher, true /* encrypt */, chunk_size, key, iv,
|
||||
plaintext, ciphertext, aad, tag)) {
|
||||
return false;
|
||||
if (operation != kDecrypt) {
|
||||
SCOPED_TRACE("encrypt");
|
||||
TestOperation(t, cipher, true /* encrypt */, chunk_size, key, iv,
|
||||
plaintext, ciphertext, aad, tag);
|
||||
}
|
||||
|
||||
if (operation != kEncrypt &&
|
||||
!TestOperation(t, cipher, false /* decrypt */, chunk_size, key, iv,
|
||||
plaintext, ciphertext, aad, tag)) {
|
||||
return false;
|
||||
if (operation != kEncrypt) {
|
||||
SCOPED_TRACE("decrypt");
|
||||
TestOperation(t, cipher, false /* decrypt */, chunk_size, key, iv,
|
||||
plaintext, ciphertext, aad, tag);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
CRYPTO_library_init();
|
||||
|
||||
if (argc != 2) {
|
||||
fprintf(stderr, "%s <test file>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return FileTestMain(TestCipher, nullptr, argv[1]);
|
||||
TEST(CipherTest, TestVectors) {
|
||||
FileTestGTest("crypto/cipher_extra/test/cipher_tests.txt", TestCipher);
|
||||
}
|
||||
|
||||
TEST(CipherTest, CAVP_AES_128_CBC) {
|
||||
FileTestGTest("crypto/cipher_extra/test/nist_cavp/aes_128_cbc.txt",
|
||||
TestCipher);
|
||||
}
|
||||
|
||||
TEST(CipherTest, CAVP_AES_128_CTR) {
|
||||
FileTestGTest("crypto/cipher_extra/test/nist_cavp/aes_128_ctr.txt",
|
||||
TestCipher);
|
||||
}
|
||||
|
||||
TEST(CipherTest, CAVP_AES_192_CBC) {
|
||||
FileTestGTest("crypto/cipher_extra/test/nist_cavp/aes_192_cbc.txt",
|
||||
TestCipher);
|
||||
}
|
||||
|
||||
TEST(CipherTest, CAVP_AES_192_CTR) {
|
||||
FileTestGTest("crypto/cipher_extra/test/nist_cavp/aes_192_ctr.txt",
|
||||
TestCipher);
|
||||
}
|
||||
|
||||
TEST(CipherTest, CAVP_AES_256_CBC) {
|
||||
FileTestGTest("crypto/cipher_extra/test/nist_cavp/aes_256_cbc.txt",
|
||||
TestCipher);
|
||||
}
|
||||
|
||||
TEST(CipherTest, CAVP_AES_256_CTR) {
|
||||
FileTestGTest("crypto/cipher_extra/test/nist_cavp/aes_256_ctr.txt",
|
||||
TestCipher);
|
||||
}
|
||||
|
||||
TEST(CipherTest, CAVP_TDES_CBC) {
|
||||
FileTestGTest("crypto/cipher_extra/test/nist_cavp/tdes_cbc.txt", TestCipher);
|
||||
}
|
||||
|
||||
TEST(CipherTest, CAVP_TDES_ECB) {
|
||||
FileTestGTest("crypto/cipher_extra/test/nist_cavp/tdes_ecb.txt", TestCipher);
|
||||
}
|
||||
|
@ -7,14 +7,3 @@ add_library(
|
||||
|
||||
ecdh.c
|
||||
)
|
||||
|
||||
add_executable(
|
||||
ecdh_test
|
||||
|
||||
ecdh_test.cc
|
||||
|
||||
$<TARGET_OBJECTS:test_support>
|
||||
)
|
||||
|
||||
target_link_libraries(ecdh_test crypto)
|
||||
add_dependencies(all_tests ecdh_test)
|
||||
|
@ -16,6 +16,8 @@
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/ec.h>
|
||||
@ -24,6 +26,7 @@
|
||||
#include <openssl/nid.h>
|
||||
|
||||
#include "../test/file_test.h"
|
||||
#include "../test/test_util.h"
|
||||
|
||||
|
||||
static bssl::UniquePtr<EC_GROUP> GetCurve(FileTest *t, const char *key) {
|
||||
@ -59,67 +62,53 @@ static bssl::UniquePtr<BIGNUM> GetBIGNUM(FileTest *t, const char *key) {
|
||||
return bssl::UniquePtr<BIGNUM>(BN_bin2bn(bytes.data(), bytes.size(), nullptr));
|
||||
}
|
||||
|
||||
static bool TestECDH(FileTest *t, void *arg) {
|
||||
bssl::UniquePtr<EC_GROUP> group = GetCurve(t, "Curve");
|
||||
bssl::UniquePtr<BIGNUM> priv_key = GetBIGNUM(t, "Private");
|
||||
bssl::UniquePtr<BIGNUM> x = GetBIGNUM(t, "X");
|
||||
bssl::UniquePtr<BIGNUM> y = GetBIGNUM(t, "Y");
|
||||
bssl::UniquePtr<BIGNUM> peer_x = GetBIGNUM(t, "PeerX");
|
||||
bssl::UniquePtr<BIGNUM> peer_y = GetBIGNUM(t, "PeerY");
|
||||
std::vector<uint8_t> z;
|
||||
if (!group || !priv_key || !x || !y || !peer_x || !peer_y ||
|
||||
!t->GetBytes(&z, "Z")) {
|
||||
return false;
|
||||
}
|
||||
TEST(ECDHTest, TestVectors) {
|
||||
FileTestGTest("crypto/ecdh/ecdh_tests.txt", [](FileTest *t) {
|
||||
bssl::UniquePtr<EC_GROUP> group = GetCurve(t, "Curve");
|
||||
ASSERT_TRUE(group);
|
||||
bssl::UniquePtr<BIGNUM> priv_key = GetBIGNUM(t, "Private");
|
||||
ASSERT_TRUE(priv_key);
|
||||
bssl::UniquePtr<BIGNUM> x = GetBIGNUM(t, "X");
|
||||
ASSERT_TRUE(x);
|
||||
bssl::UniquePtr<BIGNUM> y = GetBIGNUM(t, "Y");
|
||||
ASSERT_TRUE(y);
|
||||
bssl::UniquePtr<BIGNUM> peer_x = GetBIGNUM(t, "PeerX");
|
||||
ASSERT_TRUE(peer_x);
|
||||
bssl::UniquePtr<BIGNUM> peer_y = GetBIGNUM(t, "PeerY");
|
||||
ASSERT_TRUE(peer_y);
|
||||
std::vector<uint8_t> z;
|
||||
ASSERT_TRUE(t->GetBytes(&z, "Z"));
|
||||
|
||||
bssl::UniquePtr<EC_KEY> key(EC_KEY_new());
|
||||
bssl::UniquePtr<EC_POINT> pub_key(EC_POINT_new(group.get()));
|
||||
bssl::UniquePtr<EC_POINT> peer_pub_key(EC_POINT_new(group.get()));
|
||||
if (!key || !pub_key || !peer_pub_key ||
|
||||
!EC_KEY_set_group(key.get(), group.get()) ||
|
||||
!EC_KEY_set_private_key(key.get(), priv_key.get()) ||
|
||||
!EC_POINT_set_affine_coordinates_GFp(group.get(), pub_key.get(), x.get(),
|
||||
y.get(), nullptr) ||
|
||||
!EC_POINT_set_affine_coordinates_GFp(group.get(), peer_pub_key.get(),
|
||||
peer_x.get(), peer_y.get(),
|
||||
nullptr) ||
|
||||
!EC_KEY_set_public_key(key.get(), pub_key.get()) ||
|
||||
!EC_KEY_check_key(key.get())) {
|
||||
return false;
|
||||
}
|
||||
bssl::UniquePtr<EC_KEY> key(EC_KEY_new());
|
||||
ASSERT_TRUE(key);
|
||||
bssl::UniquePtr<EC_POINT> pub_key(EC_POINT_new(group.get()));
|
||||
ASSERT_TRUE(pub_key);
|
||||
bssl::UniquePtr<EC_POINT> peer_pub_key(EC_POINT_new(group.get()));
|
||||
ASSERT_TRUE(peer_pub_key);
|
||||
ASSERT_TRUE(EC_KEY_set_group(key.get(), group.get()));
|
||||
ASSERT_TRUE(EC_KEY_set_private_key(key.get(), priv_key.get()));
|
||||
ASSERT_TRUE(EC_POINT_set_affine_coordinates_GFp(group.get(), pub_key.get(),
|
||||
x.get(), y.get(), nullptr));
|
||||
ASSERT_TRUE(EC_POINT_set_affine_coordinates_GFp(
|
||||
group.get(), peer_pub_key.get(), peer_x.get(), peer_y.get(), nullptr));
|
||||
ASSERT_TRUE(EC_KEY_set_public_key(key.get(), pub_key.get()));
|
||||
ASSERT_TRUE(EC_KEY_check_key(key.get()));
|
||||
|
||||
std::vector<uint8_t> actual_z;
|
||||
// Make |actual_z| larger than expected to ensure |ECDH_compute_key| returns
|
||||
// the right amount of data.
|
||||
actual_z.resize(z.size() + 1);
|
||||
int ret = ECDH_compute_key(actual_z.data(), actual_z.size(),
|
||||
peer_pub_key.get(), key.get(), nullptr);
|
||||
if (ret < 0 ||
|
||||
!t->ExpectBytesEqual(z.data(), z.size(), actual_z.data(),
|
||||
static_cast<size_t>(ret))) {
|
||||
return false;
|
||||
}
|
||||
std::vector<uint8_t> actual_z;
|
||||
// Make |actual_z| larger than expected to ensure |ECDH_compute_key| returns
|
||||
// the right amount of data.
|
||||
actual_z.resize(z.size() + 1);
|
||||
int ret = ECDH_compute_key(actual_z.data(), actual_z.size(),
|
||||
peer_pub_key.get(), key.get(), nullptr);
|
||||
ASSERT_GE(ret, 0);
|
||||
EXPECT_EQ(Bytes(z), Bytes(actual_z.data(), static_cast<size_t>(ret)));
|
||||
|
||||
// Test |ECDH_compute_key| truncates.
|
||||
actual_z.resize(z.size() - 1);
|
||||
ret = ECDH_compute_key(actual_z.data(), actual_z.size(), peer_pub_key.get(),
|
||||
key.get(), nullptr);
|
||||
if (ret < 0 ||
|
||||
!t->ExpectBytesEqual(z.data(), z.size() - 1, actual_z.data(),
|
||||
static_cast<size_t>(ret))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
CRYPTO_library_init();
|
||||
|
||||
if (argc != 2) {
|
||||
fprintf(stderr, "%s <test file.txt>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return FileTestMain(TestECDH, nullptr, argv[1]);
|
||||
// Test |ECDH_compute_key| truncates.
|
||||
actual_z.resize(z.size() - 1);
|
||||
ret = ECDH_compute_key(actual_z.data(), actual_z.size(), peer_pub_key.get(),
|
||||
key.get(), nullptr);
|
||||
ASSERT_GE(ret, 0);
|
||||
EXPECT_EQ(Bytes(z.data(), z.size() - 1),
|
||||
Bytes(actual_z.data(), static_cast<size_t>(ret)));
|
||||
});
|
||||
}
|
||||
|
@ -205,28 +205,6 @@ add_executable(
|
||||
target_link_libraries(bn_test crypto)
|
||||
add_dependencies(all_tests bn_test)
|
||||
|
||||
add_executable(
|
||||
gcm_test
|
||||
|
||||
modes/gcm_test.cc
|
||||
|
||||
$<TARGET_OBJECTS:test_support>
|
||||
)
|
||||
|
||||
target_link_libraries(gcm_test crypto)
|
||||
add_dependencies(all_tests gcm_test)
|
||||
|
||||
add_executable(
|
||||
ctrdrbg_vector_test
|
||||
|
||||
rand/ctrdrbg_vector_test.cc
|
||||
|
||||
$<TARGET_OBJECTS:test_support>
|
||||
)
|
||||
|
||||
target_link_libraries(ctrdrbg_vector_test crypto)
|
||||
add_dependencies(all_tests ctrdrbg_vector_test)
|
||||
|
||||
add_executable(
|
||||
example_mul
|
||||
|
||||
|
@ -56,370 +56,65 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <openssl/aes.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
#include "internal.h"
|
||||
#include "../../test/file_test.h"
|
||||
#include "../../test/test_util.h"
|
||||
|
||||
|
||||
struct test_case {
|
||||
const char *key;
|
||||
const char *plaintext;
|
||||
const char *additional_data;
|
||||
const char *nonce;
|
||||
const char *ciphertext;
|
||||
const char *tag;
|
||||
};
|
||||
TEST(GCMTest, TestVectors) {
|
||||
FileTestGTest("crypto/fipsmodule/modes/gcm_tests.txt", [](FileTest *t) {
|
||||
std::vector<uint8_t> key, plaintext, additional_data, nonce, ciphertext,
|
||||
tag;
|
||||
ASSERT_TRUE(t->GetBytes(&key, "Key"));
|
||||
ASSERT_TRUE(t->GetBytes(&plaintext, "Plaintext"));
|
||||
ASSERT_TRUE(t->GetBytes(&additional_data, "AdditionalData"));
|
||||
ASSERT_TRUE(t->GetBytes(&nonce, "Nonce"));
|
||||
ASSERT_TRUE(t->GetBytes(&ciphertext, "Ciphertext"));
|
||||
ASSERT_TRUE(t->GetBytes(&tag, "Tag"));
|
||||
|
||||
static const struct test_case test_cases[] = {
|
||||
{
|
||||
"00000000000000000000000000000000",
|
||||
NULL,
|
||||
NULL,
|
||||
"000000000000000000000000",
|
||||
NULL,
|
||||
"58e2fccefa7e3061367f1d57a4e7455a",
|
||||
},
|
||||
{
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
NULL,
|
||||
"000000000000000000000000",
|
||||
"0388dace60b6a392f328c2b971b2fe78",
|
||||
"ab6e47d42cec13bdf53a67b21257bddf",
|
||||
},
|
||||
{
|
||||
"feffe9928665731c6d6a8f9467308308",
|
||||
"d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255",
|
||||
NULL,
|
||||
"cafebabefacedbaddecaf888",
|
||||
"42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091473f5985",
|
||||
"4d5c2af327cd64a62cf35abd2ba6fab4",
|
||||
},
|
||||
{
|
||||
"feffe9928665731c6d6a8f9467308308",
|
||||
"d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
|
||||
"feedfacedeadbeeffeedfacedeadbeefabaddad2",
|
||||
"cafebabefacedbaddecaf888",
|
||||
"42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091",
|
||||
"5bc94fbc3221a5db94fae95ae7121a47",
|
||||
},
|
||||
{
|
||||
"feffe9928665731c6d6a8f9467308308",
|
||||
"d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
|
||||
"feedfacedeadbeeffeedfacedeadbeefabaddad2",
|
||||
"cafebabefacedbad",
|
||||
"61353b4c2806934a777ff51fa22a4755699b2a714fcdc6f83766e5f97b6c742373806900e49f24b22b097544d4896b424989b5e1ebac0f07c23f4598",
|
||||
"3612d2e79e3b0785561be14aaca2fccb",
|
||||
},
|
||||
{
|
||||
"feffe9928665731c6d6a8f9467308308",
|
||||
"d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
|
||||
"feedfacedeadbeeffeedfacedeadbeefabaddad2",
|
||||
"9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b",
|
||||
"8ce24998625615b603a033aca13fb894be9112a5c3a211a8ba262a3cca7e2ca701e4a9a4fba43c90ccdcb281d48c7c6fd62875d2aca417034c34aee5",
|
||||
"619cc5aefffe0bfa462af43c1699d050",
|
||||
},
|
||||
{
|
||||
"000000000000000000000000000000000000000000000000",
|
||||
NULL,
|
||||
NULL,
|
||||
"000000000000000000000000",
|
||||
NULL,
|
||||
"cd33b28ac773f74ba00ed1f312572435",
|
||||
},
|
||||
{
|
||||
"000000000000000000000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
NULL,
|
||||
"000000000000000000000000",
|
||||
"98e7247c07f0fe411c267e4384b0f600",
|
||||
"2ff58d80033927ab8ef4d4587514f0fb",
|
||||
},
|
||||
{
|
||||
"feffe9928665731c6d6a8f9467308308feffe9928665731c",
|
||||
"d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255",
|
||||
NULL,
|
||||
"cafebabefacedbaddecaf888",
|
||||
"3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710acade256",
|
||||
"9924a7c8587336bfb118024db8674a14",
|
||||
},
|
||||
{
|
||||
"feffe9928665731c6d6a8f9467308308feffe9928665731c",
|
||||
"d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
|
||||
"feedfacedeadbeeffeedfacedeadbeefabaddad2",
|
||||
"cafebabefacedbaddecaf888",
|
||||
"3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710",
|
||||
"2519498e80f1478f37ba55bd6d27618c",
|
||||
},
|
||||
{
|
||||
"feffe9928665731c6d6a8f9467308308feffe9928665731c",
|
||||
"d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
|
||||
"feedfacedeadbeeffeedfacedeadbeefabaddad2",
|
||||
"cafebabefacedbad",
|
||||
"0f10f599ae14a154ed24b36e25324db8c566632ef2bbb34f8347280fc4507057fddc29df9a471f75c66541d4d4dad1c9e93a19a58e8b473fa0f062f7",
|
||||
"65dcc57fcf623a24094fcca40d3533f8",
|
||||
},
|
||||
{
|
||||
"feffe9928665731c6d6a8f9467308308feffe9928665731c",
|
||||
"d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
|
||||
"feedfacedeadbeeffeedfacedeadbeefabaddad2",
|
||||
"cafebabefacedbad",
|
||||
"0f10f599ae14a154ed24b36e25324db8c566632ef2bbb34f8347280fc4507057fddc29df9a471f75c66541d4d4dad1c9e93a19a58e8b473fa0f062f7",
|
||||
"65dcc57fcf623a24094fcca40d3533f8",
|
||||
},
|
||||
{
|
||||
"feffe9928665731c6d6a8f9467308308feffe9928665731c",
|
||||
"d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
|
||||
"feedfacedeadbeeffeedfacedeadbeefabaddad2",
|
||||
"9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b",
|
||||
"d27e88681ce3243c4830165a8fdcf9ff1de9a1d8e6b447ef6ef7b79828666e4581e79012af34ddd9e2f037589b292db3e67c036745fa22e7e9b7373b",
|
||||
"dcf566ff291c25bbb8568fc3d376a6d9",
|
||||
},
|
||||
{
|
||||
"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
NULL,
|
||||
NULL,
|
||||
"000000000000000000000000",
|
||||
NULL,
|
||||
"530f8afbc74536b9a963b4f1c4cb738b",
|
||||
},
|
||||
{
|
||||
"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
NULL,
|
||||
"000000000000000000000000",
|
||||
"cea7403d4d606b6e074ec5d3baf39d18",
|
||||
"d0d1c8a799996bf0265b98b5d48ab919",
|
||||
},
|
||||
{
|
||||
"feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308",
|
||||
"d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255",
|
||||
NULL,
|
||||
"cafebabefacedbaddecaf888",
|
||||
"522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015ad",
|
||||
"b094dac5d93471bdec1a502270e3cc6c",
|
||||
},
|
||||
{
|
||||
"feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308",
|
||||
"d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
|
||||
"feedfacedeadbeeffeedfacedeadbeefabaddad2",
|
||||
"cafebabefacedbaddecaf888",
|
||||
"522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662",
|
||||
"76fc6ece0f4e1768cddf8853bb2d551b",
|
||||
},
|
||||
{
|
||||
"feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308",
|
||||
"d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
|
||||
"feedfacedeadbeeffeedfacedeadbeefabaddad2",
|
||||
"cafebabefacedbad",
|
||||
"c3762df1ca787d32ae47c13bf19844cbaf1ae14d0b976afac52ff7d79bba9de0feb582d33934a4f0954cc2363bc73f7862ac430e64abe499f47c9b1f",
|
||||
"3a337dbf46a792c45e454913fe2ea8f2",
|
||||
},
|
||||
{
|
||||
"feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308",
|
||||
"d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
|
||||
"feedfacedeadbeeffeedfacedeadbeefabaddad2",
|
||||
"9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b",
|
||||
"5a8def2f0c9e53f1f75d7853659e2a20eeb2b22aafde6419a058ab4f6f746bf40fc0c3b780f244452da3ebf1c5d82cdea2418997200ef82e44ae7e3f",
|
||||
"a44a8266ee1c8eb0c8b5d4cf5ae9f19a",
|
||||
},
|
||||
{
|
||||
"00000000000000000000000000000000",
|
||||
NULL,
|
||||
"d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015ad",
|
||||
"000000000000000000000000",
|
||||
NULL,
|
||||
"5fea793a2d6f974d37e68e0cb8ff9492",
|
||||
},
|
||||
{
|
||||
"00000000000000000000000000000000",
|
||||
"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
NULL,
|
||||
/* This nonce results in 0xfff in counter LSB. */
|
||||
"ffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"56b3373ca9ef6e4a2b64fe1e9a17b61425f10d47a75a5fce13efc6bc784af24f4141bdd48cf7c770887afd573cca5418a9aeffcd7c5ceddfc6a78397b9a85b499da558257267caab2ad0b23ca476a53cb17fb41c4b8b475cb4f3f7165094c229c9e8c4dc0a2a5ff1903e501511221376a1cdb8364c5061a20cae74bc4acd76ceb0abc9fd3217ef9f8c90be402ddf6d8697f4f880dff15bfb7a6b28241ec8fe183c2d59e3f9dfff653c7126f0acb9e64211f42bae12af462b1070bef1ab5e3606872ca10dee15b3249b1a1b958f23134c4bccb7d03200bce420a2f8eb66dcf3644d1423c1b5699003c13ecef4bf38a3b60eedc34033bac1902783dc6d89e2e774188a439c7ebcc0672dbda4ddcfb2794613b0be41315ef778708a70ee7d75165c",
|
||||
"8b307f6b33286d0ab026a9ed3fe1e85f",
|
||||
},
|
||||
};
|
||||
ASSERT_EQ(plaintext.size(), ciphertext.size());
|
||||
ASSERT_TRUE(key.size() == 16 || key.size() == 24 || key.size() == 32);
|
||||
ASSERT_EQ(16u, tag.size());
|
||||
|
||||
static int from_hex(uint8_t *out, char in) {
|
||||
if (in >= '0' && in <= '9') {
|
||||
*out = in - '0';
|
||||
return 1;
|
||||
}
|
||||
if (in >= 'a' && in <= 'f') {
|
||||
*out = in - 'a' + 10;
|
||||
return 1;
|
||||
}
|
||||
if (in >= 'A' && in <= 'F') {
|
||||
*out = in - 'A' + 10;
|
||||
return 1;
|
||||
}
|
||||
std::vector<uint8_t> out(plaintext.size());
|
||||
AES_KEY aes_key;
|
||||
ASSERT_EQ(0, AES_set_encrypt_key(key.data(), key.size() * 8, &aes_key));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int decode_hex(uint8_t **out, size_t *out_len, const char *in,
|
||||
unsigned test_num, const char *description) {
|
||||
if (in == NULL) {
|
||||
*out = NULL;
|
||||
*out_len = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t len = strlen(in);
|
||||
if (len & 1) {
|
||||
fprintf(stderr, "%u: Odd-length %s input.\n", test_num, description);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t *buf = reinterpret_cast<uint8_t *>(OPENSSL_malloc(len / 2));
|
||||
if (buf == NULL) {
|
||||
fprintf(stderr, "%u: malloc failure.\n", test_num);
|
||||
goto err;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < len; i += 2) {
|
||||
uint8_t v, v2;
|
||||
if (!from_hex(&v, in[i]) ||
|
||||
!from_hex(&v2, in[i+1])) {
|
||||
fprintf(stderr, "%u: invalid hex digit in %s around offset %zu.\n",
|
||||
test_num, description, i);
|
||||
goto err;
|
||||
GCM128_CONTEXT ctx;
|
||||
CRYPTO_gcm128_init(&ctx, &aes_key, (block128_f)AES_encrypt, 0);
|
||||
CRYPTO_gcm128_setiv(&ctx, &aes_key, nonce.data(), nonce.size());
|
||||
if (!additional_data.empty()) {
|
||||
CRYPTO_gcm128_aad(&ctx, additional_data.data(), additional_data.size());
|
||||
}
|
||||
buf[i/2] = (v << 4) | v2;
|
||||
}
|
||||
|
||||
*out = buf;
|
||||
*out_len = len/2;
|
||||
return 1;
|
||||
|
||||
err:
|
||||
OPENSSL_free(buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int run_test_case(unsigned test_num, const struct test_case *test) {
|
||||
size_t key_len, plaintext_len, additional_data_len, nonce_len, ciphertext_len,
|
||||
tag_len;
|
||||
uint8_t *key = NULL, *plaintext = NULL, *additional_data = NULL,
|
||||
*nonce = NULL, *ciphertext = NULL, *tag = NULL, *out = NULL;
|
||||
int ret = 0;
|
||||
AES_KEY aes_key;
|
||||
GCM128_CONTEXT ctx;
|
||||
|
||||
if (!decode_hex(&key, &key_len, test->key, test_num, "key") ||
|
||||
!decode_hex(&plaintext, &plaintext_len, test->plaintext, test_num,
|
||||
"plaintext") ||
|
||||
!decode_hex(&additional_data, &additional_data_len, test->additional_data,
|
||||
test_num, "additional_data") ||
|
||||
!decode_hex(&nonce, &nonce_len, test->nonce, test_num, "nonce") ||
|
||||
!decode_hex(&ciphertext, &ciphertext_len, test->ciphertext, test_num,
|
||||
"ciphertext") ||
|
||||
!decode_hex(&tag, &tag_len, test->tag, test_num, "tag")) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (plaintext_len != ciphertext_len) {
|
||||
fprintf(stderr, "%u: plaintext and ciphertext have differing lengths.\n",
|
||||
test_num);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (key_len != 16 && key_len != 24 && key_len != 32) {
|
||||
fprintf(stderr, "%u: bad key length.\n", test_num);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (tag_len != 16) {
|
||||
fprintf(stderr, "%u: bad tag length.\n", test_num);
|
||||
goto out;
|
||||
}
|
||||
|
||||
out = reinterpret_cast<uint8_t *>(OPENSSL_malloc(plaintext_len));
|
||||
if (plaintext_len != 0 && out == NULL) {
|
||||
goto out;
|
||||
}
|
||||
if (AES_set_encrypt_key(key, key_len*8, &aes_key)) {
|
||||
fprintf(stderr, "%u: AES_set_encrypt_key failed.\n", test_num);
|
||||
goto out;
|
||||
}
|
||||
|
||||
CRYPTO_gcm128_init(&ctx, &aes_key, (block128_f) AES_encrypt, 0);
|
||||
CRYPTO_gcm128_setiv(&ctx, &aes_key, nonce, nonce_len);
|
||||
OPENSSL_memset(out, 0, plaintext_len);
|
||||
if (additional_data) {
|
||||
CRYPTO_gcm128_aad(&ctx, additional_data, additional_data_len);
|
||||
}
|
||||
if (plaintext) {
|
||||
CRYPTO_gcm128_encrypt(&ctx, &aes_key, plaintext, out, plaintext_len);
|
||||
}
|
||||
if (!CRYPTO_gcm128_finish(&ctx, tag, tag_len) ||
|
||||
(ciphertext && OPENSSL_memcmp(out, ciphertext, plaintext_len) != 0)) {
|
||||
fprintf(stderr, "%u: encrypt failed.\n", test_num);
|
||||
hexdump(stderr, "got :", out, plaintext_len);
|
||||
hexdump(stderr, "want:", ciphertext, plaintext_len);
|
||||
goto out;
|
||||
}
|
||||
|
||||
CRYPTO_gcm128_setiv(&ctx, &aes_key, nonce, nonce_len);
|
||||
OPENSSL_memset(out, 0, plaintext_len);
|
||||
if (additional_data) {
|
||||
CRYPTO_gcm128_aad(&ctx, additional_data, additional_data_len);
|
||||
}
|
||||
if (ciphertext) {
|
||||
CRYPTO_gcm128_decrypt(&ctx, &aes_key, ciphertext, out, plaintext_len);
|
||||
}
|
||||
if (!CRYPTO_gcm128_finish(&ctx, tag, tag_len)) {
|
||||
fprintf(stderr, "%u: decrypt failed.\n", test_num);
|
||||
goto out;
|
||||
}
|
||||
if (plaintext && OPENSSL_memcmp(out, plaintext, plaintext_len)) {
|
||||
fprintf(stderr, "%u: plaintext doesn't match.\n", test_num);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
|
||||
out:
|
||||
OPENSSL_free(key);
|
||||
OPENSSL_free(plaintext);
|
||||
OPENSSL_free(additional_data);
|
||||
OPENSSL_free(nonce);
|
||||
OPENSSL_free(ciphertext);
|
||||
OPENSSL_free(tag);
|
||||
OPENSSL_free(out);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool TestByteSwap() {
|
||||
return CRYPTO_bswap4(0x01020304) == 0x04030201 &&
|
||||
CRYPTO_bswap8(UINT64_C(0x0102030405060708)) ==
|
||||
UINT64_C(0x0807060504030201);
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
int ret = 0;
|
||||
unsigned i;
|
||||
|
||||
CRYPTO_library_init();
|
||||
|
||||
if (!TestByteSwap()) {
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
for (i = 0; i < sizeof(test_cases) / sizeof(struct test_case); i++) {
|
||||
if (!run_test_case(i, &test_cases[i])) {
|
||||
ret = 1;
|
||||
if (!plaintext.empty()) {
|
||||
CRYPTO_gcm128_encrypt(&ctx, &aes_key, plaintext.data(), out.data(),
|
||||
plaintext.size());
|
||||
}
|
||||
}
|
||||
ASSERT_TRUE(CRYPTO_gcm128_finish(&ctx, tag.data(), tag.size()));
|
||||
EXPECT_EQ(Bytes(ciphertext), Bytes(out));
|
||||
|
||||
if (ret == 0) {
|
||||
printf("PASS\n");
|
||||
}
|
||||
|
||||
return ret;
|
||||
CRYPTO_gcm128_setiv(&ctx, &aes_key, nonce.data(), nonce.size());
|
||||
OPENSSL_memset(out.data(), 0, out.size());
|
||||
if (!additional_data.empty()) {
|
||||
CRYPTO_gcm128_aad(&ctx, additional_data.data(), additional_data.size());
|
||||
}
|
||||
if (!ciphertext.empty()) {
|
||||
CRYPTO_gcm128_decrypt(&ctx, &aes_key, ciphertext.data(), out.data(),
|
||||
ciphertext.size());
|
||||
}
|
||||
ASSERT_TRUE(CRYPTO_gcm128_finish(&ctx, tag.data(), tag.size()));
|
||||
EXPECT_EQ(Bytes(plaintext), Bytes(out));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(GCMTest, ByteSwap) {
|
||||
EXPECT_EQ(0x04030201u, CRYPTO_bswap4(0x01020304u));
|
||||
EXPECT_EQ(UINT64_C(0x0807060504030201),
|
||||
CRYPTO_bswap8(UINT64_C(0x0102030405060708)));
|
||||
}
|
||||
|
147
crypto/fipsmodule/modes/gcm_tests.txt
Normal file
147
crypto/fipsmodule/modes/gcm_tests.txt
Normal file
@ -0,0 +1,147 @@
|
||||
Key = 00000000000000000000000000000000
|
||||
Plaintext =
|
||||
AdditionalData =
|
||||
Nonce = 000000000000000000000000
|
||||
Ciphertext =
|
||||
Tag = 58e2fccefa7e3061367f1d57a4e7455a
|
||||
|
||||
Key = 00000000000000000000000000000000
|
||||
Plaintext = 00000000000000000000000000000000
|
||||
AdditionalData =
|
||||
Nonce = 000000000000000000000000
|
||||
Ciphertext = 0388dace60b6a392f328c2b971b2fe78
|
||||
Tag = ab6e47d42cec13bdf53a67b21257bddf
|
||||
|
||||
Key = feffe9928665731c6d6a8f9467308308
|
||||
Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255
|
||||
AdditionalData =
|
||||
Nonce = cafebabefacedbaddecaf888
|
||||
Ciphertext = 42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091473f5985
|
||||
Tag = 4d5c2af327cd64a62cf35abd2ba6fab4
|
||||
|
||||
Key = feffe9928665731c6d6a8f9467308308
|
||||
Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
|
||||
AdditionalData = feedfacedeadbeeffeedfacedeadbeefabaddad2
|
||||
Nonce = cafebabefacedbaddecaf888
|
||||
Ciphertext = 42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091
|
||||
Tag = 5bc94fbc3221a5db94fae95ae7121a47
|
||||
|
||||
Key = feffe9928665731c6d6a8f9467308308
|
||||
Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
|
||||
AdditionalData = feedfacedeadbeeffeedfacedeadbeefabaddad2
|
||||
Nonce = cafebabefacedbad
|
||||
Ciphertext = 61353b4c2806934a777ff51fa22a4755699b2a714fcdc6f83766e5f97b6c742373806900e49f24b22b097544d4896b424989b5e1ebac0f07c23f4598
|
||||
Tag = 3612d2e79e3b0785561be14aaca2fccb
|
||||
|
||||
Key = feffe9928665731c6d6a8f9467308308
|
||||
Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
|
||||
AdditionalData = feedfacedeadbeeffeedfacedeadbeefabaddad2
|
||||
Nonce = 9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b
|
||||
Ciphertext = 8ce24998625615b603a033aca13fb894be9112a5c3a211a8ba262a3cca7e2ca701e4a9a4fba43c90ccdcb281d48c7c6fd62875d2aca417034c34aee5
|
||||
Tag = 619cc5aefffe0bfa462af43c1699d050
|
||||
|
||||
Key = 000000000000000000000000000000000000000000000000
|
||||
Plaintext =
|
||||
AdditionalData =
|
||||
Nonce = 000000000000000000000000
|
||||
Ciphertext =
|
||||
Tag = cd33b28ac773f74ba00ed1f312572435
|
||||
|
||||
Key = 000000000000000000000000000000000000000000000000
|
||||
Plaintext = 00000000000000000000000000000000
|
||||
AdditionalData =
|
||||
Nonce = 000000000000000000000000
|
||||
Ciphertext = 98e7247c07f0fe411c267e4384b0f600
|
||||
Tag = 2ff58d80033927ab8ef4d4587514f0fb
|
||||
|
||||
Key = feffe9928665731c6d6a8f9467308308feffe9928665731c
|
||||
Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255
|
||||
AdditionalData =
|
||||
Nonce = cafebabefacedbaddecaf888
|
||||
Ciphertext = 3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710acade256
|
||||
Tag = 9924a7c8587336bfb118024db8674a14
|
||||
|
||||
Key = feffe9928665731c6d6a8f9467308308feffe9928665731c
|
||||
Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
|
||||
AdditionalData = feedfacedeadbeeffeedfacedeadbeefabaddad2
|
||||
Nonce = cafebabefacedbaddecaf888
|
||||
Ciphertext = 3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710
|
||||
Tag = 2519498e80f1478f37ba55bd6d27618c
|
||||
|
||||
Key = feffe9928665731c6d6a8f9467308308feffe9928665731c
|
||||
Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
|
||||
AdditionalData = feedfacedeadbeeffeedfacedeadbeefabaddad2
|
||||
Nonce = cafebabefacedbad
|
||||
Ciphertext = 0f10f599ae14a154ed24b36e25324db8c566632ef2bbb34f8347280fc4507057fddc29df9a471f75c66541d4d4dad1c9e93a19a58e8b473fa0f062f7
|
||||
Tag = 65dcc57fcf623a24094fcca40d3533f8
|
||||
|
||||
Key = feffe9928665731c6d6a8f9467308308feffe9928665731c
|
||||
Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
|
||||
AdditionalData = feedfacedeadbeeffeedfacedeadbeefabaddad2
|
||||
Nonce = cafebabefacedbad
|
||||
Ciphertext = 0f10f599ae14a154ed24b36e25324db8c566632ef2bbb34f8347280fc4507057fddc29df9a471f75c66541d4d4dad1c9e93a19a58e8b473fa0f062f7
|
||||
Tag = 65dcc57fcf623a24094fcca40d3533f8
|
||||
|
||||
Key = feffe9928665731c6d6a8f9467308308feffe9928665731c
|
||||
Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
|
||||
AdditionalData = feedfacedeadbeeffeedfacedeadbeefabaddad2
|
||||
Nonce = 9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b
|
||||
Ciphertext = d27e88681ce3243c4830165a8fdcf9ff1de9a1d8e6b447ef6ef7b79828666e4581e79012af34ddd9e2f037589b292db3e67c036745fa22e7e9b7373b
|
||||
Tag = dcf566ff291c25bbb8568fc3d376a6d9
|
||||
|
||||
Key = 0000000000000000000000000000000000000000000000000000000000000000
|
||||
Plaintext =
|
||||
AdditionalData =
|
||||
Nonce = 000000000000000000000000
|
||||
Ciphertext =
|
||||
Tag = 530f8afbc74536b9a963b4f1c4cb738b
|
||||
|
||||
Key = 0000000000000000000000000000000000000000000000000000000000000000
|
||||
Plaintext = 00000000000000000000000000000000
|
||||
AdditionalData =
|
||||
Nonce = 000000000000000000000000
|
||||
Ciphertext = cea7403d4d606b6e074ec5d3baf39d18
|
||||
Tag = d0d1c8a799996bf0265b98b5d48ab919
|
||||
|
||||
Key = feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308
|
||||
Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255
|
||||
AdditionalData =
|
||||
Nonce = cafebabefacedbaddecaf888
|
||||
Ciphertext = 522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015ad
|
||||
Tag = b094dac5d93471bdec1a502270e3cc6c
|
||||
|
||||
Key = feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308
|
||||
Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
|
||||
AdditionalData = feedfacedeadbeeffeedfacedeadbeefabaddad2
|
||||
Nonce = cafebabefacedbaddecaf888
|
||||
Ciphertext = 522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662
|
||||
Tag = 76fc6ece0f4e1768cddf8853bb2d551b
|
||||
|
||||
Key = feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308
|
||||
Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
|
||||
AdditionalData = feedfacedeadbeeffeedfacedeadbeefabaddad2
|
||||
Nonce = cafebabefacedbad
|
||||
Ciphertext = c3762df1ca787d32ae47c13bf19844cbaf1ae14d0b976afac52ff7d79bba9de0feb582d33934a4f0954cc2363bc73f7862ac430e64abe499f47c9b1f
|
||||
Tag = 3a337dbf46a792c45e454913fe2ea8f2
|
||||
|
||||
Key = feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308
|
||||
Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
|
||||
AdditionalData = feedfacedeadbeeffeedfacedeadbeefabaddad2
|
||||
Nonce = 9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b
|
||||
Ciphertext = 5a8def2f0c9e53f1f75d7853659e2a20eeb2b22aafde6419a058ab4f6f746bf40fc0c3b780f244452da3ebf1c5d82cdea2418997200ef82e44ae7e3f
|
||||
Tag = a44a8266ee1c8eb0c8b5d4cf5ae9f19a
|
||||
|
||||
Key = 00000000000000000000000000000000
|
||||
Plaintext =
|
||||
AdditionalData = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015ad
|
||||
Nonce = 000000000000000000000000
|
||||
Ciphertext =
|
||||
Tag = 5fea793a2d6f974d37e68e0cb8ff9492
|
||||
|
||||
Key = 00000000000000000000000000000000
|
||||
Plaintext = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
AdditionalData =
|
||||
# This nonce results in 0xfff in counter LSB.
|
||||
Nonce = ffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
Ciphertext = 56b3373ca9ef6e4a2b64fe1e9a17b61425f10d47a75a5fce13efc6bc784af24f4141bdd48cf7c770887afd573cca5418a9aeffcd7c5ceddfc6a78397b9a85b499da558257267caab2ad0b23ca476a53cb17fb41c4b8b475cb4f3f7165094c229c9e8c4dc0a2a5ff1903e501511221376a1cdb8364c5061a20cae74bc4acd76ceb0abc9fd3217ef9f8c90be402ddf6d8697f4f880dff15bfb7a6b28241ec8fe183c2d59e3f9dfff653c7126f0acb9e64211f42bae12af462b1070bef1ab5e3606872ca10dee15b3249b1a1b958f23134c4bccb7d03200bce420a2f8eb66dcf3644d1423c1b5699003c13ecef4bf38a3b60eedc34033bac1902783dc6d89e2e774188a439c7ebcc0672dbda4ddcfb2794613b0be41315ef778708a70ee7d75165c
|
||||
Tag = 8b307f6b33286d0ab026a9ed3fe1e85f
|
@ -18,6 +18,7 @@
|
||||
#include <openssl/sha.h>
|
||||
|
||||
#include "internal.h"
|
||||
#include "../../test/file_test.h"
|
||||
#include "../../test/test_util.h"
|
||||
|
||||
|
||||
@ -81,3 +82,38 @@ TEST(CTRDRBGTest, Large) {
|
||||
|
||||
CTR_DRBG_clear(&drbg);
|
||||
}
|
||||
|
||||
TEST(CTRDRBGTest, TestVectors) {
|
||||
FileTestGTest("crypto/fipsmodule/rand/ctrdrbg_vectors.txt", [](FileTest *t) {
|
||||
std::vector<uint8_t> seed, personalisation, reseed, ai_reseed, ai1, ai2,
|
||||
expected;
|
||||
ASSERT_TRUE(t->GetBytes(&seed, "EntropyInput"));
|
||||
ASSERT_TRUE(t->GetBytes(&personalisation, "PersonalizationString"));
|
||||
ASSERT_TRUE(t->GetBytes(&reseed, "EntropyInputReseed"));
|
||||
ASSERT_TRUE(t->GetBytes(&ai_reseed, "AdditionalInputReseed"));
|
||||
ASSERT_TRUE(t->GetBytes(&ai1, "AdditionalInput1"));
|
||||
ASSERT_TRUE(t->GetBytes(&ai2, "AdditionalInput2"));
|
||||
ASSERT_TRUE(t->GetBytes(&expected, "ReturnedBits"));
|
||||
|
||||
ASSERT_EQ(static_cast<size_t>(CTR_DRBG_ENTROPY_LEN), seed.size());
|
||||
ASSERT_EQ(static_cast<size_t>(CTR_DRBG_ENTROPY_LEN), reseed.size());
|
||||
|
||||
CTR_DRBG_STATE drbg;
|
||||
CTR_DRBG_init(&drbg, seed.data(),
|
||||
personalisation.size() > 0 ? personalisation.data() : nullptr,
|
||||
personalisation.size());
|
||||
CTR_DRBG_reseed(&drbg, reseed.data(),
|
||||
ai_reseed.size() > 0 ? ai_reseed.data() : nullptr,
|
||||
ai_reseed.size());
|
||||
|
||||
std::vector<uint8_t> out;
|
||||
out.resize(expected.size());
|
||||
|
||||
CTR_DRBG_generate(&drbg, out.data(), out.size(),
|
||||
ai1.size() > 0 ? ai1.data() : nullptr, ai1.size());
|
||||
CTR_DRBG_generate(&drbg, out.data(), out.size(),
|
||||
ai2.size() > 0 ? ai2.data() : nullptr, ai2.size());
|
||||
|
||||
EXPECT_EQ(Bytes(expected), Bytes(out));
|
||||
});
|
||||
}
|
||||
|
@ -1,73 +0,0 @@
|
||||
/* Copyright (c) 2017, Google Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
||||
|
||||
#include <openssl/rand.h>
|
||||
|
||||
#include <openssl/crypto.h>
|
||||
|
||||
#include "internal.h"
|
||||
#include "../../test/test_util.h"
|
||||
#include "../../test/file_test.h"
|
||||
|
||||
|
||||
static bool TestCTRDRBG(FileTest *t, void *arg) {
|
||||
std::vector<uint8_t> seed, personalisation, reseed, ai_reseed, ai1, ai2,
|
||||
expected;
|
||||
if (!t->GetBytes(&seed, "EntropyInput") ||
|
||||
!t->GetBytes(&personalisation, "PersonalizationString") ||
|
||||
!t->GetBytes(&reseed, "EntropyInputReseed") ||
|
||||
!t->GetBytes(&ai_reseed, "AdditionalInputReseed") ||
|
||||
!t->GetBytes(&ai1, "AdditionalInput1") ||
|
||||
!t->GetBytes(&ai2, "AdditionalInput2") ||
|
||||
!t->GetBytes(&expected, "ReturnedBits")) {
|
||||
t->PrintLine("missing value");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (seed.size() != CTR_DRBG_ENTROPY_LEN ||
|
||||
reseed.size() != CTR_DRBG_ENTROPY_LEN) {
|
||||
t->PrintLine("bad seed length");
|
||||
return false;
|
||||
}
|
||||
|
||||
CTR_DRBG_STATE drbg;
|
||||
CTR_DRBG_init(&drbg, seed.data(),
|
||||
personalisation.size() > 0 ? personalisation.data() : nullptr,
|
||||
personalisation.size());
|
||||
CTR_DRBG_reseed(&drbg, reseed.data(),
|
||||
ai_reseed.size() > 0 ? ai_reseed.data() : nullptr,
|
||||
ai_reseed.size());
|
||||
|
||||
std::vector<uint8_t> out;
|
||||
out.resize(expected.size());
|
||||
|
||||
CTR_DRBG_generate(&drbg, out.data(), out.size(),
|
||||
ai1.size() > 0 ? ai1.data() : nullptr, ai1.size());
|
||||
CTR_DRBG_generate(&drbg, out.data(), out.size(),
|
||||
ai2.size() > 0 ? ai2.data() : nullptr, ai2.size());
|
||||
|
||||
return t->ExpectBytesEqual(expected.data(), expected.size(), out.data(),
|
||||
out.size());
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
CRYPTO_library_init();
|
||||
|
||||
if (argc != 2) {
|
||||
fprintf(stderr, "%s <test file>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return FileTestMain(TestCTRDRBG, nullptr, argv[1]);
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
include_directories(../../include)
|
||||
|
||||
add_executable(
|
||||
hmac_test
|
||||
|
||||
hmac_test.cc
|
||||
|
||||
$<TARGET_OBJECTS:test_support>
|
||||
)
|
||||
|
||||
target_link_libraries(hmac_test crypto)
|
||||
add_dependencies(all_tests hmac_test)
|
@ -54,18 +54,17 @@
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <openssl/crypto.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <openssl/digest.h>
|
||||
#include <openssl/hmac.h>
|
||||
|
||||
#include "../test/file_test.h"
|
||||
#include "../test/test_util.h"
|
||||
|
||||
|
||||
static const EVP_MD *GetDigest(const std::string &name) {
|
||||
@ -85,85 +84,47 @@ static const EVP_MD *GetDigest(const std::string &name) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static bool TestHMAC(FileTest *t, void *arg) {
|
||||
std::string digest_str;
|
||||
if (!t->GetAttribute(&digest_str, "HMAC")) {
|
||||
return false;
|
||||
}
|
||||
const EVP_MD *digest = GetDigest(digest_str);
|
||||
if (digest == nullptr) {
|
||||
t->PrintLine("Unknown digest '%s'", digest_str.c_str());
|
||||
return false;
|
||||
}
|
||||
TEST(HMACTest, TestVectors) {
|
||||
FileTestGTest("crypto/hmac_extra/hmac_tests.txt", [](FileTest *t) {
|
||||
std::string digest_str;
|
||||
ASSERT_TRUE(t->GetAttribute(&digest_str, "HMAC"));
|
||||
const EVP_MD *digest = GetDigest(digest_str);
|
||||
ASSERT_TRUE(digest) << "Unknown digest: " << digest_str;
|
||||
|
||||
std::vector<uint8_t> key, input, output;
|
||||
if (!t->GetBytes(&key, "Key") ||
|
||||
!t->GetBytes(&input, "Input") ||
|
||||
!t->GetBytes(&output, "Output")) {
|
||||
return false;
|
||||
}
|
||||
std::vector<uint8_t> key, input, output;
|
||||
ASSERT_TRUE(t->GetBytes(&key, "Key"));
|
||||
ASSERT_TRUE(t->GetBytes(&input, "Input"));
|
||||
ASSERT_TRUE(t->GetBytes(&output, "Output"));
|
||||
ASSERT_EQ(EVP_MD_size(digest), output.size());
|
||||
|
||||
// Test using the one-shot API.
|
||||
unsigned expected_mac_len = EVP_MD_size(digest);
|
||||
std::unique_ptr<uint8_t[]> mac(new uint8_t[expected_mac_len]);
|
||||
unsigned mac_len;
|
||||
if (nullptr == HMAC(digest, key.data(), key.size(), input.data(),
|
||||
input.size(), mac.get(), &mac_len) ||
|
||||
mac_len != expected_mac_len ||
|
||||
!t->ExpectBytesEqual(output.data(), output.size(), mac.get(), mac_len)) {
|
||||
t->PrintLine("One-shot API failed.");
|
||||
return false;
|
||||
}
|
||||
// Test using the one-shot API.
|
||||
unsigned expected_mac_len = EVP_MD_size(digest);
|
||||
std::unique_ptr<uint8_t[]> mac(new uint8_t[expected_mac_len]);
|
||||
unsigned mac_len;
|
||||
ASSERT_TRUE(HMAC(digest, key.data(), key.size(), input.data(), input.size(),
|
||||
mac.get(), &mac_len));
|
||||
EXPECT_EQ(Bytes(output), Bytes(mac.get(), mac_len));
|
||||
|
||||
// Test using HMAC_CTX.
|
||||
bssl::ScopedHMAC_CTX ctx;
|
||||
if (!HMAC_Init_ex(ctx.get(), key.data(), key.size(), digest, nullptr) ||
|
||||
!HMAC_Update(ctx.get(), input.data(), input.size()) ||
|
||||
!HMAC_Final(ctx.get(), mac.get(), &mac_len) ||
|
||||
mac_len != expected_mac_len ||
|
||||
!t->ExpectBytesEqual(output.data(), output.size(), mac.get(), mac_len)) {
|
||||
t->PrintLine("HMAC_CTX failed.");
|
||||
return false;
|
||||
}
|
||||
// Test using HMAC_CTX.
|
||||
bssl::ScopedHMAC_CTX ctx;
|
||||
ASSERT_TRUE(
|
||||
HMAC_Init_ex(ctx.get(), key.data(), key.size(), digest, nullptr));
|
||||
ASSERT_TRUE(HMAC_Update(ctx.get(), input.data(), input.size()));
|
||||
ASSERT_TRUE(HMAC_Final(ctx.get(), mac.get(), &mac_len));
|
||||
EXPECT_EQ(Bytes(output), Bytes(mac.get(), mac_len));
|
||||
|
||||
// Test that an HMAC_CTX may be reset with the same key.
|
||||
if (!HMAC_Init_ex(ctx.get(), nullptr, 0, digest, nullptr) ||
|
||||
!HMAC_Update(ctx.get(), input.data(), input.size()) ||
|
||||
!HMAC_Final(ctx.get(), mac.get(), &mac_len) ||
|
||||
mac_len != expected_mac_len ||
|
||||
!t->ExpectBytesEqual(output.data(), output.size(), mac.get(), mac_len)) {
|
||||
t->PrintLine("HMAC_CTX with reset failed.");
|
||||
return false;
|
||||
}
|
||||
// Test that an HMAC_CTX may be reset with the same key.
|
||||
ASSERT_TRUE(HMAC_Init_ex(ctx.get(), nullptr, 0, digest, nullptr));
|
||||
ASSERT_TRUE(HMAC_Update(ctx.get(), input.data(), input.size()));
|
||||
ASSERT_TRUE(HMAC_Final(ctx.get(), mac.get(), &mac_len));
|
||||
EXPECT_EQ(Bytes(output), Bytes(mac.get(), mac_len));
|
||||
|
||||
// Test feeding the input in byte by byte.
|
||||
if (!HMAC_Init_ex(ctx.get(), nullptr, 0, nullptr, nullptr)) {
|
||||
t->PrintLine("HMAC_CTX streaming failed.");
|
||||
return false;
|
||||
}
|
||||
for (size_t i = 0; i < input.size(); i++) {
|
||||
if (!HMAC_Update(ctx.get(), &input[i], 1)) {
|
||||
t->PrintLine("HMAC_CTX streaming failed.");
|
||||
return false;
|
||||
// Test feeding the input in byte by byte.
|
||||
ASSERT_TRUE(HMAC_Init_ex(ctx.get(), nullptr, 0, nullptr, nullptr));
|
||||
for (size_t i = 0; i < input.size(); i++) {
|
||||
ASSERT_TRUE(HMAC_Update(ctx.get(), &input[i], 1));
|
||||
}
|
||||
}
|
||||
if (!HMAC_Final(ctx.get(), mac.get(), &mac_len) ||
|
||||
mac_len != expected_mac_len ||
|
||||
!t->ExpectBytesEqual(output.data(), output.size(), mac.get(), mac_len)) {
|
||||
t->PrintLine("HMAC_CTX streaming failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
CRYPTO_library_init();
|
||||
|
||||
if (argc != 2) {
|
||||
fprintf(stderr, "%s <test file.txt>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return FileTestMain(TestHMAC, nullptr, argv[1]);
|
||||
ASSERT_TRUE(HMAC_Final(ctx.get(), mac.get(), &mac_len));
|
||||
EXPECT_EQ(Bytes(output), Bytes(mac.get(), mac_len));
|
||||
});
|
||||
}
|
||||
|
@ -19,13 +19,3 @@ add_library(
|
||||
|
||||
${POLY1305_ARCH_SOURCES}
|
||||
)
|
||||
|
||||
add_executable(
|
||||
poly1305_test
|
||||
|
||||
poly1305_test.cc
|
||||
$<TARGET_OBJECTS:test_support>
|
||||
)
|
||||
|
||||
target_link_libraries(poly1305_test crypto)
|
||||
add_dependencies(all_tests poly1305_test)
|
||||
|
@ -17,15 +17,16 @@
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <openssl/crypto.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <openssl/poly1305.h>
|
||||
|
||||
#include "../internal.h"
|
||||
#include "../test/file_test.h"
|
||||
#include "../test/test_util.h"
|
||||
|
||||
|
||||
static bool TestSIMD(FileTest *t, unsigned excess,
|
||||
const std::vector<uint8_t> &key,
|
||||
static void TestSIMD(unsigned excess, const std::vector<uint8_t> &key,
|
||||
const std::vector<uint8_t> &in,
|
||||
const std::vector<uint8_t> &mac) {
|
||||
poly1305_state state;
|
||||
@ -64,68 +65,40 @@ static bool TestSIMD(FileTest *t, unsigned excess,
|
||||
// |CRYPTO_poly1305_finish| requires a 16-byte-aligned output.
|
||||
alignas(16) uint8_t out[16];
|
||||
CRYPTO_poly1305_finish(&state, out);
|
||||
if (!t->ExpectBytesEqual(mac.data(), mac.size(), out, 16)) {
|
||||
t->PrintLine("SIMD pattern %u failed.", excess);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
EXPECT_EQ(Bytes(out), Bytes(mac)) << "SIMD pattern " << excess << " failed.";
|
||||
}
|
||||
|
||||
static bool TestPoly1305(FileTest *t, void *arg) {
|
||||
std::vector<uint8_t> key, in, mac;
|
||||
if (!t->GetBytes(&key, "Key") ||
|
||||
!t->GetBytes(&in, "Input") ||
|
||||
!t->GetBytes(&mac, "MAC")) {
|
||||
return false;
|
||||
}
|
||||
if (key.size() != 32 || mac.size() != 16) {
|
||||
t->PrintLine("Invalid test");
|
||||
return false;
|
||||
}
|
||||
TEST(Poly1305Test, TestVectors) {
|
||||
FileTestGTest("crypto/poly1305/poly1305_tests.txt", [](FileTest *t) {
|
||||
std::vector<uint8_t> key, in, mac;
|
||||
ASSERT_TRUE(t->GetBytes(&key, "Key"));
|
||||
ASSERT_TRUE(t->GetBytes(&in, "Input"));
|
||||
ASSERT_TRUE(t->GetBytes(&mac, "MAC"));
|
||||
ASSERT_EQ(32u, key.size());
|
||||
ASSERT_EQ(16u, mac.size());
|
||||
|
||||
// Test single-shot operation.
|
||||
poly1305_state state;
|
||||
CRYPTO_poly1305_init(&state, key.data());
|
||||
CRYPTO_poly1305_update(&state, in.data(), in.size());
|
||||
// |CRYPTO_poly1305_finish| requires a 16-byte-aligned output.
|
||||
alignas(16) uint8_t out[16];
|
||||
CRYPTO_poly1305_finish(&state, out);
|
||||
if (!t->ExpectBytesEqual(out, 16, mac.data(), mac.size())) {
|
||||
t->PrintLine("Single-shot Poly1305 failed.");
|
||||
return false;
|
||||
}
|
||||
// Test single-shot operation.
|
||||
poly1305_state state;
|
||||
CRYPTO_poly1305_init(&state, key.data());
|
||||
CRYPTO_poly1305_update(&state, in.data(), in.size());
|
||||
// |CRYPTO_poly1305_finish| requires a 16-byte-aligned output.
|
||||
alignas(16) uint8_t out[16];
|
||||
CRYPTO_poly1305_finish(&state, out);
|
||||
EXPECT_EQ(Bytes(out), Bytes(mac)) << "Single-shot Poly1305 failed.";
|
||||
|
||||
// Test streaming byte-by-byte.
|
||||
CRYPTO_poly1305_init(&state, key.data());
|
||||
for (size_t i = 0; i < in.size(); i++) {
|
||||
CRYPTO_poly1305_update(&state, &in[i], 1);
|
||||
}
|
||||
CRYPTO_poly1305_finish(&state, out);
|
||||
if (!t->ExpectBytesEqual(mac.data(), mac.size(), out, 16)) {
|
||||
t->PrintLine("Streaming Poly1305 failed.");
|
||||
return false;
|
||||
}
|
||||
// Test streaming byte-by-byte.
|
||||
CRYPTO_poly1305_init(&state, key.data());
|
||||
for (size_t i = 0; i < in.size(); i++) {
|
||||
CRYPTO_poly1305_update(&state, &in[i], 1);
|
||||
}
|
||||
CRYPTO_poly1305_finish(&state, out);
|
||||
EXPECT_EQ(Bytes(out), Bytes(mac)) << "Streaming Poly1305 failed.";
|
||||
|
||||
// Test SIMD stress patterns. OpenSSL's AVX2 assembly needs a multiple of
|
||||
// four blocks, so test up to three blocks of excess.
|
||||
if (!TestSIMD(t, 0, key, in, mac) ||
|
||||
!TestSIMD(t, 16, key, in, mac) ||
|
||||
!TestSIMD(t, 32, key, in, mac) ||
|
||||
!TestSIMD(t, 48, key, in, mac)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
CRYPTO_library_init();
|
||||
|
||||
if (argc != 2) {
|
||||
fprintf(stderr, "%s <test file>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return FileTestMain(TestPoly1305, nullptr, argv[1]);
|
||||
// Test SIMD stress patterns. OpenSSL's AVX2 assembly needs a multiple of
|
||||
// four blocks, so test up to three blocks of excess.
|
||||
TestSIMD(0, key, in, mac);
|
||||
TestSIMD(16, key, in, mac);
|
||||
TestSIMD(32, key, in, mac);
|
||||
TestSIMD(48, key, in, mac);
|
||||
});
|
||||
}
|
||||
|
@ -23,6 +23,8 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <openssl/err.h>
|
||||
|
||||
|
||||
std::string GetTestData(const char *path);
|
||||
|
||||
@ -81,5 +83,8 @@ void FileTestGTest(const char *path, std::function<void(FileTest *)> run_test) {
|
||||
|
||||
SCOPED_TRACE(testing::Message() << path << ", line " << t.start_line());
|
||||
run_test(&t);
|
||||
|
||||
// Clean up the error queue for the next test.
|
||||
ERR_clear_error();
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,41 @@
|
||||
set(
|
||||
CRYPTO_TEST_DATA
|
||||
|
||||
crypto/cipher_extra/test/aes_128_cbc_sha1_ssl3_tests.txt
|
||||
crypto/cipher_extra/test/aes_128_cbc_sha1_tls_implicit_iv_tests.txt
|
||||
crypto/cipher_extra/test/aes_128_cbc_sha1_tls_tests.txt
|
||||
crypto/cipher_extra/test/aes_128_cbc_sha256_tls_tests.txt
|
||||
crypto/cipher_extra/test/aes_128_ctr_hmac_sha256.txt
|
||||
crypto/cipher_extra/test/aes_128_gcm_siv_tests.txt
|
||||
crypto/cipher_extra/test/aes_128_gcm_tests.txt
|
||||
crypto/cipher_extra/test/aes_256_cbc_sha1_ssl3_tests.txt
|
||||
crypto/cipher_extra/test/aes_256_cbc_sha1_tls_implicit_iv_tests.txt
|
||||
crypto/cipher_extra/test/aes_256_cbc_sha1_tls_tests.txt
|
||||
crypto/cipher_extra/test/aes_256_cbc_sha256_tls_tests.txt
|
||||
crypto/cipher_extra/test/aes_256_cbc_sha384_tls_tests.txt
|
||||
crypto/cipher_extra/test/aes_256_ctr_hmac_sha256.txt
|
||||
crypto/cipher_extra/test/aes_256_gcm_siv_tests.txt
|
||||
crypto/cipher_extra/test/aes_256_gcm_tests.txt
|
||||
crypto/cipher_extra/test/chacha20_poly1305_tests.txt
|
||||
crypto/cipher_extra/test/cipher_tests.txt
|
||||
crypto/cipher_extra/test/des_ede3_cbc_sha1_ssl3_tests.txt
|
||||
crypto/cipher_extra/test/des_ede3_cbc_sha1_tls_implicit_iv_tests.txt
|
||||
crypto/cipher_extra/test/des_ede3_cbc_sha1_tls_tests.txt
|
||||
crypto/cipher_extra/test/nist_cavp/aes_128_cbc.txt
|
||||
crypto/cipher_extra/test/nist_cavp/aes_128_ctr.txt
|
||||
crypto/cipher_extra/test/nist_cavp/aes_128_gcm.txt
|
||||
crypto/cipher_extra/test/nist_cavp/aes_192_cbc.txt
|
||||
crypto/cipher_extra/test/nist_cavp/aes_192_ctr.txt
|
||||
crypto/cipher_extra/test/nist_cavp/aes_256_cbc.txt
|
||||
crypto/cipher_extra/test/nist_cavp/aes_256_ctr.txt
|
||||
crypto/cipher_extra/test/nist_cavp/aes_256_gcm.txt
|
||||
crypto/cipher_extra/test/nist_cavp/tdes_cbc.txt
|
||||
crypto/cipher_extra/test/nist_cavp/tdes_ecb.txt
|
||||
crypto/curve25519/ed25519_tests.txt
|
||||
crypto/ecdh/ecdh_tests.txt
|
||||
crypto/fipsmodule/aes/aes_tests.txt
|
||||
crypto/fipsmodule/modes/gcm_tests.txt
|
||||
crypto/fipsmodule/rand/ctrdrbg_vectors.txt
|
||||
crypto/hmac_extra/hmac_tests.txt
|
||||
crypto/poly1305/poly1305_tests.txt
|
||||
)
|
||||
|
@ -1,51 +1,16 @@
|
||||
[
|
||||
["crypto/cipher_extra/aead_test", "aes-128-cbc-sha1-ssl3", "crypto/cipher_extra/test/aes_128_cbc_sha1_ssl3_tests.txt"],
|
||||
["crypto/cipher_extra/aead_test", "aes-128-cbc-sha1-tls", "crypto/cipher_extra/test/aes_128_cbc_sha1_tls_tests.txt"],
|
||||
["crypto/cipher_extra/aead_test", "aes-128-cbc-sha1-tls-implicit-iv", "crypto/cipher_extra/test/aes_128_cbc_sha1_tls_implicit_iv_tests.txt"],
|
||||
["crypto/cipher_extra/aead_test", "aes-128-cbc-sha256-tls", "crypto/cipher_extra/test/aes_128_cbc_sha256_tls_tests.txt"],
|
||||
["crypto/cipher_extra/aead_test", "aes-128-ctr-hmac-sha256", "crypto/cipher_extra/test/aes_128_ctr_hmac_sha256.txt"],
|
||||
["crypto/cipher_extra/aead_test", "aes-128-gcm", "crypto/cipher_extra/test/aes_128_gcm_tests.txt"],
|
||||
["crypto/cipher_extra/aead_test", "aes-128-gcm", "crypto/cipher_extra/test/nist_cavp/aes_128_gcm.txt"],
|
||||
["crypto/cipher_extra/aead_test", "aes-128-gcm-siv", "crypto/cipher_extra/test/aes_128_gcm_siv_tests.txt"],
|
||||
["crypto/cipher_extra/aead_test", "aes-256-cbc-sha1-ssl3", "crypto/cipher_extra/test/aes_256_cbc_sha1_ssl3_tests.txt"],
|
||||
["crypto/cipher_extra/aead_test", "aes-256-cbc-sha1-tls", "crypto/cipher_extra/test/aes_256_cbc_sha1_tls_tests.txt"],
|
||||
["crypto/cipher_extra/aead_test", "aes-256-cbc-sha1-tls-implicit-iv", "crypto/cipher_extra/test/aes_256_cbc_sha1_tls_implicit_iv_tests.txt"],
|
||||
["crypto/cipher_extra/aead_test", "aes-256-cbc-sha256-tls", "crypto/cipher_extra/test/aes_256_cbc_sha256_tls_tests.txt"],
|
||||
["crypto/cipher_extra/aead_test", "aes-256-cbc-sha384-tls", "crypto/cipher_extra/test/aes_256_cbc_sha384_tls_tests.txt"],
|
||||
["crypto/cipher_extra/aead_test", "aes-256-ctr-hmac-sha256", "crypto/cipher_extra/test/aes_256_ctr_hmac_sha256.txt"],
|
||||
["crypto/cipher_extra/aead_test", "aes-256-gcm", "crypto/cipher_extra/test/aes_256_gcm_tests.txt"],
|
||||
["crypto/cipher_extra/aead_test", "aes-256-gcm", "crypto/cipher_extra/test/nist_cavp/aes_256_gcm.txt"],
|
||||
["crypto/cipher_extra/aead_test", "aes-256-gcm-siv", "crypto/cipher_extra/test/aes_256_gcm_siv_tests.txt"],
|
||||
["crypto/cipher_extra/aead_test", "chacha20-poly1305", "crypto/cipher_extra/test/chacha20_poly1305_tests.txt"],
|
||||
["crypto/cipher_extra/aead_test", "des-ede3-cbc-sha1-ssl3", "crypto/cipher_extra/test/des_ede3_cbc_sha1_ssl3_tests.txt"],
|
||||
["crypto/cipher_extra/aead_test", "des-ede3-cbc-sha1-tls", "crypto/cipher_extra/test/des_ede3_cbc_sha1_tls_tests.txt"],
|
||||
["crypto/cipher_extra/aead_test", "des-ede3-cbc-sha1-tls-implicit-iv", "crypto/cipher_extra/test/des_ede3_cbc_sha1_tls_implicit_iv_tests.txt"],
|
||||
["crypto/cipher_extra/cipher_test", "crypto/cipher_extra/test/cipher_tests.txt"],
|
||||
["crypto/cipher_extra/cipher_test", "crypto/cipher_extra/test/nist_cavp/aes_128_cbc.txt"],
|
||||
["crypto/cipher_extra/cipher_test", "crypto/cipher_extra/test/nist_cavp/aes_128_ctr.txt"],
|
||||
["crypto/cipher_extra/cipher_test", "crypto/cipher_extra/test/nist_cavp/aes_192_cbc.txt"],
|
||||
["crypto/cipher_extra/cipher_test", "crypto/cipher_extra/test/nist_cavp/aes_192_ctr.txt"],
|
||||
["crypto/cipher_extra/cipher_test", "crypto/cipher_extra/test/nist_cavp/aes_256_cbc.txt"],
|
||||
["crypto/cipher_extra/cipher_test", "crypto/cipher_extra/test/nist_cavp/aes_256_ctr.txt"],
|
||||
["crypto/cipher_extra/cipher_test", "crypto/cipher_extra/test/nist_cavp/tdes_cbc.txt"],
|
||||
["crypto/cipher_extra/cipher_test", "crypto/cipher_extra/test/nist_cavp/tdes_ecb.txt"],
|
||||
["crypto/crypto_test"],
|
||||
["crypto/ecdh/ecdh_test", "crypto/ecdh/ecdh_tests.txt"],
|
||||
["crypto/evp/evp_test", "crypto/evp/evp_tests.txt"],
|
||||
["crypto/fipsmodule/bn_test", "crypto/fipsmodule/bn/bn_tests.txt"],
|
||||
["crypto/fipsmodule/ctrdrbg_vector_test", "crypto/fipsmodule/rand/ctrdrbg_vectors.txt"],
|
||||
["crypto/fipsmodule/ecdsa_sign_test", "crypto/fipsmodule/ecdsa/ecdsa_sign_tests.txt"],
|
||||
["crypto/fipsmodule/ecdsa_test"],
|
||||
["crypto/fipsmodule/ecdsa_verify_test", "crypto/fipsmodule/ecdsa/ecdsa_verify_tests.txt"],
|
||||
["crypto/fipsmodule/example_mul"],
|
||||
["crypto/fipsmodule/gcm_test"],
|
||||
["crypto/fipsmodule/p256-x86_64_test", "crypto/fipsmodule/ec/p256-x86_64_tests.txt"],
|
||||
["crypto/hmac_extra/hmac_test", "crypto/hmac_extra/hmac_tests.txt"],
|
||||
["crypto/obj/obj_test"],
|
||||
["crypto/pkcs7/pkcs7_test"],
|
||||
["crypto/pkcs8/pkcs12_test"],
|
||||
["crypto/pkcs8/pkcs8_test"],
|
||||
["crypto/poly1305/poly1305_test", "crypto/poly1305/poly1305_tests.txt"],
|
||||
["crypto/thread_test"],
|
||||
["crypto/x509v3/tab_test"],
|
||||
["crypto/x509v3/v3name_test"],
|
||||
|
Loading…
Reference in New Issue
Block a user