Drop CAVP code.

All FIPS testing is done with ACVP now. We can delete all the CAVP
stuff.

Change-Id: I459873474e40b0371f9cf760090a130ef9a90a8c
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/51330
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: Adam Langley <agl@google.com>
This commit is contained in:
Adam Langley
2022-02-15 20:02:16 +00:00
committed by Boringssl LUCI CQ
parent d04c32a3d8
commit ea9fb94c35
27 changed files with 19 additions and 3298 deletions
+1 -1
View File
@@ -593,7 +593,7 @@ add_subdirectory(crypto)
add_subdirectory(ssl)
add_subdirectory(ssl/test)
add_subdirectory(tool)
add_subdirectory(util/fipstools/cavp)
add_subdirectory(util/fipstools)
add_subdirectory(util/fipstools/acvp/modulewrapper)
add_subdirectory(decrepit)
+2 -5
View File
@@ -13,12 +13,9 @@ BoringCrypto has undergone the following validations:
1. 2019-08-08: certificate [#3678](https://csrc.nist.gov/Projects/Cryptographic-Module-Validation-Program/Certificate/3678), [security policy](/crypto/fipsmodule/policydocs/BoringCrypto-Security-Policy-20190808.docx) (in docx format).
1. 2019-10-20: certificate [#3753](https://csrc.nist.gov/Projects/Cryptographic-Module-Validation-Program/Certificate/3753), [security policy](/crypto/fipsmodule/policydocs/BoringCrypto-Android-Security-Policy-20191020.docx) (in docx format).
## Running CAVP tests
## Running ACVP tests
CAVP results are calculated by `util/fipstools/cavp`, but that binary is almost always run by `util/fipstools/run_cavp.go`. The latter knows the set of tests to be processed and the flags needed to configure `cavp` for each one. It must be run from the top of a CAVP directory and needs the following options:
1. `-oracle-bin`: points to the location of `util/fipstools/cavp`
2. `-no-fax`: this is needed to suppress checking of the FAX files, which are only included in sample sets.
See `util/fipstools/acvp/ACVP.md` for details of how ACVP testing is done.
## Breaking known-answer and continuous tests
+12
View File
@@ -0,0 +1,12 @@
include_directories(../../include)
if(FIPS)
add_executable(
test_fips
test_fips.c
)
add_dependencies(test_fips global_target)
target_link_libraries(test_fips crypto)
endif()
-42
View File
@@ -1,42 +0,0 @@
include_directories(../../../include)
if(FIPS)
add_executable(
cavp
cavp_main.cc
cavp_aes_gcm_test.cc
cavp_aes_test.cc
cavp_ctr_drbg_test.cc
cavp_ecdsa2_keypair_test.cc
cavp_ecdsa2_pkv_test.cc
cavp_ecdsa2_siggen_test.cc
cavp_ecdsa2_sigver_test.cc
cavp_hmac_test.cc
cavp_kas_test.cc
cavp_keywrap_test.cc
cavp_rsa2_keygen_test.cc
cavp_rsa2_siggen_test.cc
cavp_rsa2_sigver_test.cc
cavp_sha_monte_test.cc
cavp_sha_test.cc
cavp_tdes_test.cc
cavp_tlskdf_test.cc
cavp_test_util.cc
)
add_dependencies(cavp global_target)
add_executable(
test_fips
test_fips.c
)
add_dependencies(test_fips global_target)
target_link_libraries(cavp test_support_lib crypto)
target_link_libraries(test_fips test_support_lib crypto)
endif()
-166
View File
@@ -1,166 +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. */
// cavp_aes_gcm_test processes a NIST CAVP AES GCM test vector request file and
// emits the corresponding response.
#include <stdlib.h>
#include <openssl/aead.h>
#include <openssl/cipher.h>
#include <openssl/crypto.h>
#include <openssl/err.h>
#include "../crypto/test/file_test.h"
#include "../crypto/test/test_util.h"
#include "cavp_test_util.h"
namespace {
struct TestCtx {
const EVP_AEAD *aead;
};
}
static const EVP_AEAD *GetAEAD(const std::string &name, const bool enc) {
if (name == "aes-128-gcm") {
return EVP_aead_aes_128_gcm();
} else if (name == "aes-192-gcm") {
return EVP_aead_aes_192_gcm();
} else if (name == "aes-256-gcm") {
return EVP_aead_aes_256_gcm();
}
return nullptr;
}
static bool TestAEADEncrypt(FileTest *t, void *arg) {
TestCtx *ctx = reinterpret_cast<TestCtx *>(arg);
std::string key_len_str, iv_len_str, pt_len_str, aad_len_str, tag_len_str;
if (!t->GetInstruction(&key_len_str, "Keylen") ||
!t->GetInstruction(&iv_len_str, "IVlen") ||
!t->GetInstruction(&pt_len_str, "PTlen") ||
!t->GetInstruction(&aad_len_str, "AADlen") ||
!t->GetInstruction(&tag_len_str, "Taglen")) {
return false;
}
std::string count;
std::vector<uint8_t> key, iv, pt, aad, tag, ct;
if (!t->GetAttribute(&count, "Count") ||
!t->GetBytes(&key, "Key") ||
!t->GetBytes(&iv, "IV") ||
!t->GetBytes(&pt, "PT") ||
!t->GetBytes(&aad, "AAD") ||
key.size() * 8 != strtoul(key_len_str.c_str(), nullptr, 0) ||
iv.size() * 8 != strtoul(iv_len_str.c_str(), nullptr, 0) ||
pt.size() * 8 != strtoul(pt_len_str.c_str(), nullptr, 0) ||
aad.size() * 8 != strtoul(aad_len_str.c_str(), nullptr, 0) ||
iv.size() != 12) {
return false;
}
const size_t tag_len = strtoul(tag_len_str.c_str(), nullptr, 0) / 8;
if (!AEADEncrypt(ctx->aead, &ct, &tag, tag_len, key, pt, aad, iv)) {
return false;
}
printf("%s", t->CurrentTestToString().c_str());
printf("CT = %s\r\n", EncodeHex(ct).c_str());
printf("Tag = %s\r\n\r\n", EncodeHex(tag).c_str());
return true;
}
static bool TestAEADDecrypt(FileTest *t, void *arg) {
TestCtx *ctx = reinterpret_cast<TestCtx *>(arg);
std::string key_len, iv_len, pt_len_str, aad_len_str, tag_len;
if (!t->GetInstruction(&key_len, "Keylen") ||
!t->GetInstruction(&iv_len, "IVlen") ||
!t->GetInstruction(&pt_len_str, "PTlen") ||
!t->GetInstruction(&aad_len_str, "AADlen") ||
!t->GetInstruction(&tag_len, "Taglen")) {
t->PrintLine("Invalid instruction block.");
return false;
}
size_t aad_len = strtoul(aad_len_str.c_str(), nullptr, 0) / 8;
size_t pt_len = strtoul(pt_len_str.c_str(), nullptr, 0) / 8;
std::string count;
std::vector<uint8_t> key, iv, ct, aad, tag, pt;
if (!t->GetAttribute(&count, "Count") ||
!t->GetBytes(&key, "Key") ||
!t->GetBytes(&aad, "AAD") ||
!t->GetBytes(&tag, "Tag") ||
!t->GetBytes(&iv, "IV") ||
!t->GetBytes(&ct, "CT") ||
key.size() * 8 != strtoul(key_len.c_str(), nullptr, 0) ||
iv.size() * 8 != strtoul(iv_len.c_str(), nullptr, 0) ||
ct.size() != pt_len ||
aad.size() != aad_len ||
tag.size() * 8 != strtoul(tag_len.c_str(), nullptr, 0)) {
t->PrintLine("Invalid test case");
return false;
}
printf("%s", t->CurrentTestToString().c_str());
bool aead_result =
AEADDecrypt(ctx->aead, &pt, pt_len, key, aad, ct, tag, iv);
if (aead_result) {
printf("PT = %s\r\n\r\n", EncodeHex(pt).c_str());
} else {
printf("FAIL\r\n\r\n");
}
return true;
}
static int usage(char *arg) {
fprintf(stderr, "usage: %s (enc|dec) <cipher> <test file>\n", arg);
return 1;
}
int cavp_aes_gcm_test_main(int argc, char **argv) {
if (argc != 4) {
return usage(argv[0]);
}
const std::string mode(argv[1]);
bool (*test_fn)(FileTest * t, void *arg);
if (mode == "enc") {
test_fn = &TestAEADEncrypt;
} else if (mode == "dec") {
test_fn = &TestAEADDecrypt;
} else {
return usage(argv[0]);
}
const EVP_AEAD *aead = GetAEAD(argv[2], mode == "enc");
if (aead == nullptr) {
fprintf(stderr, "invalid aead: %s\n", argv[2]);
return 1;
}
TestCtx ctx = {aead};
FileTest::Options opts;
opts.path = argv[3];
opts.callback = test_fn;
opts.arg = &ctx;
opts.silent = true;
opts.comment_callback = EchoComment;
return FileTestMain(opts);
}
-225
View File
@@ -1,225 +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. */
// cavp_aes_test processes a NIST CAVP AES test vector request file and emits
// the corresponding response.
#include <stdlib.h>
#include <openssl/cipher.h>
#include <openssl/crypto.h>
#include <openssl/err.h>
#include "../crypto/test/file_test.h"
#include "../crypto/test/test_util.h"
#include "cavp_test_util.h"
namespace {
struct TestCtx {
const EVP_CIPHER *cipher;
bool has_iv;
enum Mode {
kKAT, // Known Answer Test
kMCT, // Monte Carlo Test
};
Mode mode;
};
}
static bool MonteCarlo(const TestCtx *ctx, FileTest *t,
const EVP_CIPHER *cipher, std::vector<uint8_t> *out,
bool encrypt, std::vector<uint8_t> key,
std::vector<uint8_t> iv, std::vector<uint8_t> in) {
const std::string in_label = encrypt ? "PLAINTEXT" : "CIPHERTEXT",
result_label = encrypt ? "CIPHERTEXT" : "PLAINTEXT";
std::vector<uint8_t> prev_result, result, prev_in;
for (int i = 0; i < 100; i++) {
printf("COUNT = %d\r\nKEY = %s\r\n", i, EncodeHex(key).c_str());
if (ctx->has_iv) {
printf("IV = %s\r\n", EncodeHex(iv).c_str());
}
printf("%s = %s\r\n", in_label.c_str(), EncodeHex(in).c_str());
if (!ctx->has_iv) { // ECB mode
for (int j = 0; j < 1000; j++) {
prev_result = result;
if (!CipherOperation(cipher, &result, encrypt, key, iv, in)) {
return false;
}
in = result;
}
} else {
for (int j = 0; j < 1000; j++) {
prev_result = result;
if (j > 0) {
if (encrypt) {
iv = result;
} else {
iv = prev_in;
}
}
if (!CipherOperation(cipher, &result, encrypt, key, iv, in)) {
return false;
}
prev_in = in;
if (j == 0) {
in = iv;
} else {
in = prev_result;
}
}
}
printf("%s = %s\r\n\r\n", result_label.c_str(), EncodeHex(result).c_str());
const size_t key_len = key.size() * 8;
if (key_len == 128) {
for (size_t k = 0; k < key.size(); k++) {
key[k] ^= result[k];
}
} else if (key_len == 192) {
for (size_t k = 0; k < key.size(); k++) {
// Key[i+1] = Key[i] xor (last 64-bits of CT[j-1] || CT[j])
if (k < 8) {
key[k] ^= prev_result[prev_result.size() - 8 + k];
} else {
key[k] ^= result[k - 8];
}
}
} else { // key_len == 256
for (size_t k = 0; k < key.size(); k++) {
// Key[i+1] = Key[i] xor (CT[j-1] || CT[j])
if (k < 16) {
key[k] ^= prev_result[k];
} else {
key[k] ^= result[k - 16];
}
}
}
if (ctx->has_iv) {
iv = result;
in = prev_result;
} else {
in = result;
}
}
return true;
}
static bool TestCipher(FileTest *t, void *arg) {
TestCtx *ctx = reinterpret_cast<TestCtx *>(arg);
if (t->HasInstruction("ENCRYPT") == t->HasInstruction("DECRYPT")) {
t->PrintLine("Want either ENCRYPT or DECRYPT");
return false;
}
enum {
kEncrypt,
kDecrypt,
} operation = t->HasInstruction("ENCRYPT") ? kEncrypt : kDecrypt;
std::string count;
std::vector<uint8_t> key, iv, in, result;
if (!t->GetAttribute(&count, "COUNT") ||
!t->GetBytes(&key, "KEY") ||
(ctx->has_iv && !t->GetBytes(&iv, "IV"))) {
return false;
}
const EVP_CIPHER *cipher = ctx->cipher;
if (operation == kEncrypt) {
if (!t->GetBytes(&in, "PLAINTEXT")) {
return false;
}
} else { // operation == kDecrypt
if (!t->GetBytes(&in, "CIPHERTEXT")) {
return false;
}
}
if (ctx->mode == TestCtx::kKAT) {
if (!CipherOperation(cipher, &result, operation == kEncrypt, key, iv, in)) {
return false;
}
const std::string label =
operation == kEncrypt ? "CIPHERTEXT" : "PLAINTEXT";
printf("%s%s = %s\r\n\r\n", t->CurrentTestToString().c_str(), label.c_str(),
EncodeHex(result).c_str());
} else { // ctx->mode == kMCT
const std::string op_label =
operation == kEncrypt ? "[ENCRYPT]" : "[DECRYPT]";
printf("%s\r\n\r\n", op_label.c_str());
if (!MonteCarlo(ctx, t, cipher, &result, operation == kEncrypt, key, iv,
in)) {
return false;
}
if (operation == kEncrypt) {
// MCT tests contain a stray blank line after the ENCRYPT section.
printf("\r\n");
}
}
return true;
}
static int usage(char *arg) {
fprintf(stderr, "usage: %s (kat|mct) <cipher> <test file>\n", arg);
return 1;
}
int cavp_aes_test_main(int argc, char **argv) {
if (argc != 4) {
return usage(argv[0]);
}
const std::string tm(argv[1]);
enum TestCtx::Mode test_mode;
if (tm == "kat") {
test_mode = TestCtx::kKAT;
} else if (tm == "mct") {
test_mode = TestCtx::kMCT;
} else {
fprintf(stderr, "invalid test_mode: %s\n", tm.c_str());
return usage(argv[0]);
}
const std::string cipher_name(argv[2]);
const EVP_CIPHER *cipher = GetCipher(argv[2]);
if (cipher == nullptr) {
fprintf(stderr, "invalid cipher: %s\n", argv[2]);
return 1;
}
const bool has_iv =
(cipher_name != "aes-128-ecb" &&
cipher_name != "aes-192-ecb" &&
cipher_name != "aes-256-ecb");
TestCtx ctx = {cipher, has_iv, test_mode};
FileTest::Options opts;
opts.path = argv[3];
opts.callback = TestCipher;
opts.arg = &ctx;
opts.silent = true;
opts.comment_callback = EchoComment;
return FileTestMain(opts);
}
-106
View File
@@ -1,106 +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. */
// cavp_ctr_drbg_test processes a NIST CAVP DRBG800-90A test vector request
// file and emits the corresponding response.
#include <openssl/crypto.h>
#include <stdlib.h>
#include "cavp_test_util.h"
#include "../crypto/fipsmodule/rand/internal.h"
#include "../crypto/test/file_test.h"
#include "../crypto/test/test_util.h"
static bool TestCTRDRBG(FileTest *t, void *arg) {
std::string test_type, prediction_resistance, entropy_input_len, nonce_len,
personalization_str_len, additional_input_len, returned_bits_len;
if (!t->GetInstruction(&test_type, "AES-256 no df") ||
!t->GetInstruction(&prediction_resistance, "PredictionResistance") ||
!t->GetInstruction(&entropy_input_len, "EntropyInputLen") ||
!t->GetInstruction(&nonce_len, "NonceLen") ||
!t->GetInstruction(&personalization_str_len,
"PersonalizationStringLen") ||
!t->GetInstruction(&additional_input_len, "AdditionalInputLen") ||
!t->GetInstruction(&returned_bits_len, "ReturnedBitsLen") ||
!test_type.empty() ||
prediction_resistance != "False" ||
strtoul(entropy_input_len.c_str(), nullptr, 0) !=
CTR_DRBG_ENTROPY_LEN * 8 ||
nonce_len != "0") {
return false;
}
std::string count;
std::vector<uint8_t> entropy, nonce, personalization_str, ai1, ai2;
if (!t->GetAttribute(&count, "COUNT") ||
!t->GetBytes(&entropy, "EntropyInput") ||
!t->GetBytes(&nonce, "Nonce") ||
!t->GetBytes(&personalization_str, "PersonalizationString") ||
!t->GetBytes(&ai1, "AdditionalInput") ||
!t->GetBytes(&ai2, "AdditionalInput/2") ||
entropy.size() * 8 != strtoul(entropy_input_len.c_str(), nullptr, 0) ||
nonce.size() != 0 ||
personalization_str.size() * 8 !=
strtoul(personalization_str_len.c_str(), nullptr, 0) ||
ai1.size() != ai2.size() ||
ai1.size() * 8 != strtoul(additional_input_len.c_str(), nullptr, 0)) {
return false;
}
CTR_DRBG_STATE drbg;
CTR_DRBG_init(&drbg, entropy.data(),
personalization_str.size() > 0 ? personalization_str.data()
: nullptr,
personalization_str.size());
uint64_t out_len = strtoul(returned_bits_len.c_str(), nullptr, 0);
if (out_len == 0 || (out_len & 7) != 0) {
return false;
}
out_len /= 8;
std::vector<uint8_t> out;
out.resize(out_len);
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());
printf("%s", t->CurrentTestToString().c_str());
printf("ReturnedBits = %s\r\n\r\n", EncodeHex(out).c_str());
return true;
}
static int usage(char *arg) {
fprintf(stderr, "usage: %s <test file>\n", arg);
return 1;
}
int cavp_ctr_drbg_test_main(int argc, char **argv) {
if (argc != 2) {
return usage(argv[0]);
}
FileTest::Options opts;
opts.path = argv[1];
opts.callback = TestCTRDRBG;
opts.silent = true;
opts.comment_callback = EchoComment;
return FileTestMain(opts);
}
@@ -1,92 +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. */
// cavp_ecdsa2_keypair_test processes a NIST CAVP ECDSA2 KeyPair test vector
// request file and emits the corresponding response.
#include <stdlib.h>
#include <vector>
#include <openssl/bn.h>
#include <openssl/crypto.h>
#include <openssl/ec_key.h>
#include <openssl/err.h>
#include <openssl/nid.h>
#include "../crypto/test/file_test.h"
#include "../crypto/test/test_util.h"
#include "cavp_test_util.h"
static bool TestECDSA2KeyPair(FileTest *t, void *arg) {
std::string n_str;
const char *group_str;
int nid = GetECGroupNIDFromInstruction(t, &group_str);
if (nid == NID_undef ||
!t->GetAttribute(&n_str, "N")) {
return false;
}
// Don't use CurrentTestToString to avoid printing the N.
printf(
"[%s]\r\n\r\n[B.4.2 Key Pair Generation by Testing Candidates]\r\n\r\n",
group_str);
unsigned long n = strtoul(n_str.c_str(), nullptr, 10);
for (unsigned long i = 0; i < n; i++) {
bssl::UniquePtr<BIGNUM> qx(BN_new()), qy(BN_new());
bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(nid));
if (!key ||
!EC_KEY_generate_key_fips(key.get()) ||
!EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(key.get()),
EC_KEY_get0_public_key(key.get()),
qx.get(), qy.get(), nullptr)) {
return false;
}
size_t degree_len =
(EC_GROUP_get_degree(EC_KEY_get0_group(key.get())) + 7) / 8;
size_t order_len =
BN_num_bytes(EC_GROUP_get0_order(EC_KEY_get0_group(key.get())));
std::vector<uint8_t> qx_bytes(degree_len), qy_bytes(degree_len);
std::vector<uint8_t> d_bytes(order_len);
if (!BN_bn2bin_padded(qx_bytes.data(), qx_bytes.size(), qx.get()) ||
!BN_bn2bin_padded(qy_bytes.data(), qy_bytes.size(), qy.get()) ||
!BN_bn2bin_padded(d_bytes.data(), d_bytes.size(),
EC_KEY_get0_private_key(key.get()))) {
return false;
}
printf("d = %s\r\nQx = %s\r\nQy = %s\r\n\r\n", EncodeHex(d_bytes).c_str(),
EncodeHex(qx_bytes).c_str(), EncodeHex(qy_bytes).c_str());
}
return true;
}
int cavp_ecdsa2_keypair_test_main(int argc, char **argv) {
if (argc != 2) {
fprintf(stderr, "usage: %s <test file>\n",
argv[0]);
return 1;
}
FileTest::Options opts;
opts.path = argv[1];
opts.callback = TestECDSA2KeyPair;
opts.silent = true;
opts.comment_callback = EchoComment;
return FileTestMain(opts);
}
@@ -1,66 +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. */
// cavp_ecdsa2_pkv_test processes a NIST CAVP ECDSA2 PKV test vector request file
// and emits the corresponding response.
#include <vector>
#include <openssl/bn.h>
#include <openssl/crypto.h>
#include <openssl/ec_key.h>
#include <openssl/err.h>
#include <openssl/nid.h>
#include "../crypto/test/file_test.h"
#include "cavp_test_util.h"
static bool TestECDSA2PKV(FileTest *t, void *arg) {
int nid = GetECGroupNIDFromInstruction(t);
if (nid == NID_undef) {
return false;
}
bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(nid));
bssl::UniquePtr<BIGNUM> qx = GetBIGNUM(t, "Qx");
bssl::UniquePtr<BIGNUM> qy = GetBIGNUM(t, "Qy");
if (!key || !qx || !qy) {
return false;
}
if (EC_KEY_set_public_key_affine_coordinates(key.get(), qx.get(), qy.get())) {
printf("%sResult = P\r\n\r\n", t->CurrentTestToString().c_str());
} else {
char buf[256];
ERR_error_string_n(ERR_get_error(), buf, sizeof(buf));
printf("%sResult = F (%s)\r\n\r\n", t->CurrentTestToString().c_str(), buf);
}
ERR_clear_error();
return true;
}
int cavp_ecdsa2_pkv_test_main(int argc, char **argv) {
if (argc != 2) {
fprintf(stderr, "usage: %s <test file>\n",
argv[0]);
return 1;
}
FileTest::Options opts;
opts.path = argv[1];
opts.callback = TestECDSA2PKV;
opts.silent = true;
opts.comment_callback = EchoComment;
return FileTestMain(opts);
}
@@ -1,123 +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. */
// cavp_ecdsa2_siggen_test processes NIST CAVP ECDSA2 SigGen and
// SigGenComponent test vector request files and emits the corresponding
// response.
#include <vector>
#include <openssl/bn.h>
#include <openssl/crypto.h>
#include <openssl/digest.h>
#include <openssl/ec_key.h>
#include <openssl/ecdsa.h>
#include <openssl/err.h>
#include <openssl/nid.h>
#include "../crypto/internal.h"
#include "../crypto/test/file_test.h"
#include "../crypto/test/test_util.h"
#include "cavp_test_util.h"
static bool TestECDSA2SigGenImpl(FileTest *t, bool is_component) {
int nid = GetECGroupNIDFromInstruction(t);
const EVP_MD *md = GetDigestFromInstruction(t);
if (nid == NID_undef || md == nullptr) {
return false;
}
bssl::UniquePtr<BIGNUM> qx(BN_new()), qy(BN_new());
bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(nid));
std::vector<uint8_t> msg;
if (!qx || !qy || !key ||
!EC_KEY_generate_key_fips(key.get()) ||
!EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(key.get()),
EC_KEY_get0_public_key(key.get()),
qx.get(), qy.get(), nullptr) ||
!t->GetBytes(&msg, "Msg")) {
return false;
}
uint8_t digest[EVP_MAX_MD_SIZE];
unsigned digest_len;
if (is_component) {
if (msg.size() != EVP_MD_size(md)) {
t->PrintLine("Bad input length.");
return false;
}
digest_len = EVP_MD_size(md);
OPENSSL_memcpy(digest, msg.data(), msg.size());
} else if (!EVP_Digest(msg.data(), msg.size(), digest, &digest_len, md,
nullptr)) {
return false;
}
bssl::UniquePtr<ECDSA_SIG> sig(ECDSA_do_sign(digest, digest_len, key.get()));
if (!sig) {
return false;
}
size_t degree_len =
(EC_GROUP_get_degree(EC_KEY_get0_group(key.get())) + 7) / 8;
size_t order_len =
BN_num_bytes(EC_GROUP_get0_order(EC_KEY_get0_group(key.get())));
std::vector<uint8_t> qx_bytes(degree_len), qy_bytes(degree_len);
std::vector<uint8_t> r_bytes(order_len), s_bytes(order_len);
if (!BN_bn2bin_padded(qx_bytes.data(), qx_bytes.size(), qx.get()) ||
!BN_bn2bin_padded(qy_bytes.data(), qy_bytes.size(), qy.get()) ||
!BN_bn2bin_padded(r_bytes.data(), r_bytes.size(), sig->r) ||
!BN_bn2bin_padded(s_bytes.data(), s_bytes.size(), sig->s)) {
return false;
}
printf("%sQx = %s\r\nQy = %s\r\nR = %s\r\nS = %s\r\n\r\n",
t->CurrentTestToString().c_str(), EncodeHex(qx_bytes).c_str(),
EncodeHex(qy_bytes).c_str(), EncodeHex(r_bytes).c_str(),
EncodeHex(s_bytes).c_str());
return true;
}
static bool TestECDSA2SigGen(FileTest *t, void *arg) {
return TestECDSA2SigGenImpl(t, false);
}
static bool TestECDSA2SigGenComponent(FileTest *t, void *arg) {
return TestECDSA2SigGenImpl(t, true);
}
int cavp_ecdsa2_siggen_test_main(int argc, char **argv) {
if (argc != 3) {
fprintf(stderr, "usage: %s (SigGen|SigGenComponent) <test file>\n",
argv[0]);
return 1;
}
static bool (*test_func)(FileTest *, void *);
if (strcmp(argv[1], "SigGen") == 0) {
test_func = TestECDSA2SigGen;
} else if (strcmp(argv[1], "SigGenComponent") == 0) {
test_func = TestECDSA2SigGenComponent;
} else {
fprintf(stderr, "Unknown test type: %s\n", argv[1]);
return 1;
}
FileTest::Options opts;
opts.path = argv[2];
opts.callback = test_func;
opts.silent = true;
opts.comment_callback = EchoComment;
return FileTestMain(opts);
}
@@ -1,84 +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. */
// cavp_ecdsa2_sigver_test processes a NIST CAVP ECDSA2 SigVer test vector
// request file and emits the corresponding response.
#include <vector>
#include <openssl/bn.h>
#include <openssl/crypto.h>
#include <openssl/digest.h>
#include <openssl/ec_key.h>
#include <openssl/ecdsa.h>
#include <openssl/err.h>
#include <openssl/nid.h>
#include "../crypto/test/file_test.h"
#include "cavp_test_util.h"
static bool TestECDSA2SigVer(FileTest *t, void *arg) {
int nid = GetECGroupNIDFromInstruction(t);
const EVP_MD *md = GetDigestFromInstruction(t);
if (nid == NID_undef || md == nullptr) {
return false;
}
bssl::UniquePtr<ECDSA_SIG> sig(ECDSA_SIG_new());
bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(nid));
bssl::UniquePtr<BIGNUM> qx = GetBIGNUM(t, "Qx");
bssl::UniquePtr<BIGNUM> qy = GetBIGNUM(t, "Qy");
bssl::UniquePtr<BIGNUM> r = GetBIGNUM(t, "R");
bssl::UniquePtr<BIGNUM> s = GetBIGNUM(t, "S");
std::vector<uint8_t> msg;
uint8_t digest[EVP_MAX_MD_SIZE];
unsigned digest_len;
if (!sig || !key || !qx || !qy || !r || !s ||
!EC_KEY_set_public_key_affine_coordinates(key.get(), qx.get(),
qy.get()) ||
!t->GetBytes(&msg, "Msg") ||
!EVP_Digest(msg.data(), msg.size(), digest, &digest_len, md, nullptr)) {
return false;
}
BN_free(sig->r);
sig->r = r.release();
BN_free(sig->s);
sig->s = s.release();
if (ECDSA_do_verify(digest, digest_len, sig.get(), key.get())) {
printf("%sResult = P\r\n\r\n", t->CurrentTestToString().c_str());
} else {
char buf[256];
ERR_error_string_n(ERR_get_error(), buf, sizeof(buf));
printf("%sResult = F (%s)\r\n\r\n", t->CurrentTestToString().c_str(), buf);
}
ERR_clear_error();
return true;
}
int cavp_ecdsa2_sigver_test_main(int argc, char **argv) {
if (argc != 2) {
fprintf(stderr, "usage: %s <test file>\n",
argv[0]);
return 1;
}
FileTest::Options opts;
opts.path = argv[1];
opts.callback = TestECDSA2SigVer;
opts.silent = true;
opts.comment_callback = EchoComment;
return FileTestMain(opts);
}
-106
View File
@@ -1,106 +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. */
// cavp_hmac_test processes a NIST CAVP HMAC test vector request file and emits
// the corresponding response.
#include <stdlib.h>
#include <openssl/crypto.h>
#include <openssl/hmac.h>
#include <openssl/span.h>
#include "../crypto/test/file_test.h"
#include "../crypto/test/test_util.h"
#include "cavp_test_util.h"
static bool TestHMAC(FileTest *t, void *arg) {
std::string md_len_str;
if (!t->GetInstruction(&md_len_str, "L")) {
return false;
}
const size_t md_len = strtoul(md_len_str.c_str(), nullptr, 0);
const EVP_MD *md;
switch (md_len) {
case 20:
md = EVP_sha1();
break;
case 28:
md = EVP_sha224();
break;
case 32:
md = EVP_sha256();
break;
case 48:
md = EVP_sha384();
break;
case 64:
md = EVP_sha512();
break;
default:
return false;
}
std::string count_str, k_len_str, t_len_str;
std::vector<uint8_t> key, msg;
if (!t->GetAttribute(&count_str, "Count") ||
!t->GetAttribute(&k_len_str, "Klen") ||
!t->GetAttribute(&t_len_str, "Tlen") ||
!t->GetBytes(&key, "Key") ||
!t->GetBytes(&msg, "Msg")) {
return false;
}
size_t k_len = strtoul(k_len_str.c_str(), nullptr, 0);
size_t t_len = strtoul(t_len_str.c_str(), nullptr, 0);
if (key.size() < k_len) {
return false;
}
unsigned out_len;
uint8_t out[EVP_MAX_MD_SIZE];
if (HMAC(md, key.data(), k_len, msg.data(), msg.size(), out, &out_len) ==
NULL) {
return false;
}
if (out_len < t_len) {
return false;
}
printf("%s", t->CurrentTestToString().c_str());
printf("Mac = %s\r\n\r\n",
EncodeHex(bssl::MakeConstSpan(out, t_len)).c_str());
return true;
}
static int usage(char *arg) {
fprintf(stderr, "usage: %s <test file>\n", arg);
return 1;
}
int cavp_hmac_test_main(int argc, char **argv) {
if (argc != 2) {
return usage(argv[0]);
}
FileTest::Options opts;
opts.path = argv[1];
opts.callback = TestHMAC;
opts.silent = true;
opts.comment_callback = EchoComment;
return FileTestMain(opts);
}
-156
View File
@@ -1,156 +0,0 @@
/* Copyright (c) 2018, 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. */
// cavp_kas_test processes NIST CAVP ECC KAS test vector request files and
// emits the corresponding response.
#include <vector>
#include <openssl/bn.h>
#include <openssl/crypto.h>
#include <openssl/digest.h>
#include <openssl/ecdh.h>
#include <openssl/ecdsa.h>
#include <openssl/ec_key.h>
#include <openssl/err.h>
#include <openssl/nid.h>
#include <openssl/sha.h>
#include <openssl/span.h>
#include "../crypto/internal.h"
#include "../crypto/test/file_test.h"
#include "../crypto/test/test_util.h"
#include "cavp_test_util.h"
static bool TestKAS(FileTest *t, void *arg) {
const bool validate = *reinterpret_cast<bool *>(arg);
int nid = NID_undef;
size_t digest_len = 0;
if (t->HasInstruction("EB - SHA224")) {
nid = NID_secp224r1;
digest_len = SHA224_DIGEST_LENGTH;
} else if (t->HasInstruction("EC - SHA256")) {
nid = NID_X9_62_prime256v1;
digest_len = SHA256_DIGEST_LENGTH;
} else if (t->HasInstruction("ED - SHA384")) {
nid = NID_secp384r1;
digest_len = SHA384_DIGEST_LENGTH;
} else if (t->HasInstruction("EE - SHA512")) {
nid = NID_secp521r1;
digest_len = SHA512_DIGEST_LENGTH;
} else {
return false;
}
if (!t->HasAttribute("COUNT")) {
return false;
}
bssl::UniquePtr<BIGNUM> their_x(GetBIGNUM(t, "QeCAVSx"));
bssl::UniquePtr<BIGNUM> their_y(GetBIGNUM(t, "QeCAVSy"));
bssl::UniquePtr<EC_KEY> ec_key(EC_KEY_new_by_curve_name(nid));
bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
if (!their_x || !their_y || !ec_key || !ctx) {
return false;
}
const EC_GROUP *const group = EC_KEY_get0_group(ec_key.get());
bssl::UniquePtr<EC_POINT> their_point(EC_POINT_new(group));
if (!their_point ||
!EC_POINT_set_affine_coordinates_GFp(
group, their_point.get(), their_x.get(), their_y.get(), ctx.get())) {
return false;
}
if (validate) {
bssl::UniquePtr<BIGNUM> our_k(GetBIGNUM(t, "deIUT"));
if (!our_k ||
!EC_KEY_set_private_key(ec_key.get(), our_k.get()) ||
// These attributes are ignored.
!t->HasAttribute("QeIUTx") ||
!t->HasAttribute("QeIUTy")) {
return false;
}
} else if (!EC_KEY_generate_key(ec_key.get())) {
return false;
}
uint8_t digest[EVP_MAX_MD_SIZE];
if (!ECDH_compute_key_fips(digest, digest_len, their_point.get(),
ec_key.get())) {
return false;
}
if (validate) {
std::vector<uint8_t> expected_shared_bytes;
if (!t->GetBytes(&expected_shared_bytes, "CAVSHashZZ")) {
return false;
}
const bool ok =
digest_len == expected_shared_bytes.size() &&
OPENSSL_memcmp(digest, expected_shared_bytes.data(), digest_len) == 0;
printf("%sIUTHashZZ = %s\r\nResult = %c\r\n\r\n\r\n",
t->CurrentTestToString().c_str(),
EncodeHex(bssl::MakeConstSpan(digest, digest_len)).c_str(),
ok ? 'P' : 'F');
} else {
const EC_POINT *pub = EC_KEY_get0_public_key(ec_key.get());
bssl::UniquePtr<BIGNUM> x(BN_new());
bssl::UniquePtr<BIGNUM> y(BN_new());
if (!x || !y ||
!EC_POINT_get_affine_coordinates_GFp(group, pub, x.get(), y.get(),
ctx.get())) {
return false;
}
bssl::UniquePtr<char> x_hex(BN_bn2hex(x.get()));
bssl::UniquePtr<char> y_hex(BN_bn2hex(y.get()));
printf("%sQeIUTx = %s\r\nQeIUTy = %s\r\nHashZZ = %s\r\n",
t->CurrentTestToString().c_str(), x_hex.get(), y_hex.get(),
EncodeHex(bssl::MakeConstSpan(digest, digest_len)).c_str());
}
return true;
}
int cavp_kas_test_main(int argc, char **argv) {
if (argc != 3) {
fprintf(stderr, "usage: %s (validity|function) <test file>\n",
argv[0]);
return 1;
}
bool validity;
if (strcmp(argv[1], "validity") == 0) {
validity = true;
} else if (strcmp(argv[1], "function") == 0) {
validity = false;
} else {
fprintf(stderr, "Unknown test type: %s\n", argv[1]);
return 1;
}
FileTest::Options opts;
opts.path = argv[2];
opts.arg = &validity;
opts.callback = TestKAS;
opts.silent = true;
opts.comment_callback = EchoComment;
opts.is_kas_test = true;
return FileTestMain(opts);
}
-166
View File
@@ -1,166 +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. */
// cavp_keywrap_test processes a NIST CAVP AES test vector request file and
// emits the corresponding response.
#include <stdlib.h>
#include <openssl/aes.h>
#include <openssl/crypto.h>
#include "../crypto/test/file_test.h"
#include "../crypto/test/test_util.h"
#include "cavp_test_util.h"
namespace {
struct TestCtx {
bool encrypt;
bool padding;
};
} // namespace
static bool AESKeyWrap(std::vector<uint8_t> *out, bool encrypt,
const std::vector<uint8_t> &key,
const std::vector<uint8_t> &in) {
size_t key_bits = key.size() * 8;
if (key_bits != 128 && key_bits != 192 && key_bits != 256) {
return false;
}
AES_KEY aes_key;
if (encrypt) {
out->resize(in.size() + 8);
if (AES_set_encrypt_key(key.data(), key_bits, &aes_key) ||
AES_wrap_key(&aes_key, nullptr, out->data(), in.data(), in.size()) ==
-1) {
return false;
}
} else {
out->resize(in.size() - 8);
if (AES_set_decrypt_key(key.data(), key_bits, &aes_key) ||
AES_unwrap_key(&aes_key, nullptr, out->data(), in.data(), in.size()) ==
-1) {
return false;
}
}
return true;
}
static bool AESKeyWrapWithPadding(std::vector<uint8_t> *out, bool encrypt,
const std::vector<uint8_t> &key,
const std::vector<uint8_t> &in) {
const size_t key_bits = key.size() * 8;
if (key_bits != 128 && key_bits != 192 && key_bits != 256) {
return false;
}
AES_KEY aes_key;
size_t out_len;
if (encrypt) {
out->resize(in.size() + 15);
if (AES_set_encrypt_key(key.data(), key_bits, &aes_key) ||
!AES_wrap_key_padded(&aes_key, out->data(), &out_len, out->size(),
in.data(), in.size())) {
return false;
}
} else {
out->resize(in.size());
if (AES_set_decrypt_key(key.data(), key_bits, &aes_key) ||
!AES_unwrap_key_padded(&aes_key, out->data(), &out_len, out->size(),
in.data(), in.size())) {
return false;
}
}
out->resize(out_len);
return true;
}
static bool TestCipher(FileTest *t, void *arg) {
TestCtx *ctx = reinterpret_cast<TestCtx *>(arg);
std::string count, unused, in_label = ctx->encrypt ? "P" : "C",
result_label = ctx->encrypt ? "C" : "P";
std::vector<uint8_t> key, in, result;
// clang-format off
if (!t->GetInstruction(&unused, "PLAINTEXT LENGTH") ||
!t->GetAttribute(&count, "COUNT") ||
!t->GetBytes(&key, "K") ||
!t->GetBytes(&in, in_label)) {
return false;
}
// clang-format on
auto wrap_function = AESKeyWrap;
if (ctx->padding) {
wrap_function = AESKeyWrapWithPadding;
}
printf("%s", t->CurrentTestToString().c_str());
if (!wrap_function(&result, ctx->encrypt, key, in)) {
if (ctx->encrypt) {
return false;
} else {
printf("FAIL\r\n\r\n");
}
} else {
printf("%s = %s\r\n\r\n", result_label.c_str(), EncodeHex(result).c_str());
}
return true;
}
static int usage(char *arg) {
fprintf(
stderr,
"usage: %s (enc|dec|enc-pad|dec-pad) (128|192|256) <test file>\n",
arg);
return 1;
}
int cavp_keywrap_test_main(int argc, char **argv) {
if (argc != 4) {
return usage(argv[0]);
}
const std::string op(argv[1]);
bool encrypt = false;
bool padding = false;
if (op == "enc") {
encrypt = true;
} else if (op == "dec") {
} else if (op == "enc-pad") {
encrypt = true;
padding = true;
} else if (op == "dec-pad") {
padding = true;
} else {
return usage(argv[0]);
}
TestCtx ctx = {encrypt, padding};
FileTest::Options opts;
opts.path = argv[3];
opts.callback = TestCipher;
opts.arg = &ctx;
opts.silent = true;
opts.comment_callback = EchoComment;
return FileTestMain(opts);
}
-73
View File
@@ -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. */
// cavp_main is a wrapper that invokes the main entry function of one of the
// CAVP validation suite binaries.
#include <stdlib.h>
#include <cstdio>
#include <string>
#include <openssl/crypto.h>
#include "cavp_test_util.h"
static int usage(char *arg) {
fprintf(stderr, "usage: %s <validation suite> <args ...>\n", arg);
return 1;
}
struct TestSuite {
std::string name;
int (*main_func)(int argc, char **argv);
};
static TestSuite all_test_suites[] = {
{"aes", &cavp_aes_test_main},
{"aes_gcm", &cavp_aes_gcm_test_main},
{"ctr_drbg", &cavp_ctr_drbg_test_main},
{"ecdsa2_keypair", &cavp_ecdsa2_keypair_test_main},
{"ecdsa2_pkv", &cavp_ecdsa2_pkv_test_main},
{"ecdsa2_siggen", &cavp_ecdsa2_siggen_test_main},
{"ecdsa2_sigver", &cavp_ecdsa2_sigver_test_main},
{"hmac", &cavp_hmac_test_main},
{"kas", &cavp_kas_test_main},
{"keywrap", &cavp_keywrap_test_main},
{"rsa2_keygen", &cavp_rsa2_keygen_test_main},
{"rsa2_siggen", &cavp_rsa2_siggen_test_main},
{"rsa2_sigver", &cavp_rsa2_sigver_test_main},
{"tlskdf", &cavp_tlskdf_test_main},
{"sha", &cavp_sha_test_main},
{"sha_monte", &cavp_sha_monte_test_main},
{"tdes", &cavp_tdes_test_main}
};
int main(int argc, char **argv) {
CRYPTO_library_init();
if (argc < 3) {
return usage(argv[0]);
}
const std::string suite(argv[1]);
for (const TestSuite &s : all_test_suites) {
if (s.name == suite) {
return s.main_func(argc - 1, &argv[1]);
}
}
fprintf(stderr, "invalid test suite: %s\n\n", argv[1]);
return usage(argv[0]);
}
@@ -1,93 +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. */
// cavp_rsa2_keygen_test processes NIST CAVP RSA2 KeyGen test vector request
// files and emits the corresponding response.
#include <vector>
#include <openssl/bn.h>
#include <openssl/crypto.h>
#include <openssl/rsa.h>
#include "../crypto/internal.h"
#include "../crypto/test/file_test.h"
#include "../crypto/test/test_util.h"
#include "cavp_test_util.h"
static bool TestRSA2KeyGen(FileTest *t, void *arg) {
std::string mod_str, table, count_str;
if (!t->GetInstruction(&mod_str, "mod") ||
!t->GetInstruction(&table, "Table for M-R Test") ||
table != "C.2" ||
!t->GetAttribute(&count_str, "N")) {
return false;
}
printf("[mod = %s]\r\n", mod_str.c_str());
printf("[Table for M-R Test = %s]\r\n\r\n", table.c_str());
size_t bits = strtoul(mod_str.c_str(), nullptr, 0);
size_t count = strtoul(count_str.c_str(), nullptr, 0);
for (size_t i = 0; i < count; i++) {
bssl::UniquePtr<RSA> key(RSA_new());
if (key == nullptr ||
bits == 0 ||
!RSA_generate_key_fips(key.get(), bits, nullptr)) {
return 0;
}
const BIGNUM *n, *e, *d, *p, *q;
RSA_get0_key(key.get(), &n, &e, &d);
RSA_get0_factors(key.get(), &p, &q);
std::vector<uint8_t> n_bytes(BN_num_bytes(n)), e_bytes(BN_num_bytes(e)),
d_bytes((bits + 7) / 8), p_bytes(BN_num_bytes(p)),
q_bytes(BN_num_bytes(q));
if (n == NULL ||
BN_bn2bin(n, n_bytes.data()) != n_bytes.size() ||
e == NULL ||
BN_bn2bin(e, e_bytes.data()) != e_bytes.size() ||
d == NULL ||
!BN_bn2bin_padded(d_bytes.data(), d_bytes.size(), d) ||
p == NULL ||
BN_bn2bin(p, p_bytes.data()) != p_bytes.size() ||
q == NULL ||
BN_bn2bin(q, q_bytes.data()) != q_bytes.size()) {
return false;
}
printf("e = %s\r\np = %s\r\nq = %s\r\nn = %s\r\nd = %s\r\n\r\n",
EncodeHex(e_bytes).c_str(), EncodeHex(p_bytes).c_str(),
EncodeHex(q_bytes).c_str(), EncodeHex(n_bytes).c_str(),
EncodeHex(d_bytes).c_str());
}
return true;
}
int cavp_rsa2_keygen_test_main(int argc, char **argv) {
if (argc != 2) {
fprintf(stderr, "usage: %s <test file>\n",
argv[0]);
return 1;
}
FileTest::Options opts;
opts.path = argv[1];
opts.callback = TestRSA2KeyGen;
opts.silent = true;
opts.comment_callback = EchoComment;
return FileTestMain(opts);
}
@@ -1,128 +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. */
// cavp_rsa2_siggen_test processes NIST CAVP RSA2 SigGen test vector request
// files and emits the corresponding response.
#include <vector>
#include <openssl/bn.h>
#include <openssl/crypto.h>
#include <openssl/digest.h>
#include <openssl/rsa.h>
#include "../crypto/internal.h"
#include "../crypto/test/file_test.h"
#include "../crypto/test/test_util.h"
#include "cavp_test_util.h"
namespace {
struct TestCtx {
bssl::UniquePtr<RSA> key;
bool is_pss;
};
}
static bool TestRSA2SigGen(FileTest *t, void *arg) {
TestCtx *ctx = reinterpret_cast<TestCtx *>(arg);
std::string mod_str, hash;
std::vector<uint8_t> msg;
if (!t->GetInstruction(&mod_str, "mod") ||
!t->GetAttribute(&hash, "SHAAlg") ||
!t->GetBytes(&msg, "Msg")) {
return false;
}
std::string test = t->CurrentTestToString();
if (t->IsAtNewInstructionBlock()) {
int mod_bits = strtoul(mod_str.c_str(), nullptr, 0);
ctx->key = bssl::UniquePtr<RSA>(RSA_new());
if (ctx->key == nullptr ||
mod_bits == 0 ||
!RSA_generate_key_fips(ctx->key.get(), mod_bits, nullptr)) {
return false;
}
const BIGNUM *n, *e;
RSA_get0_key(ctx->key.get(), &n, &e, nullptr);
std::vector<uint8_t> n_bytes(BN_num_bytes(n));
std::vector<uint8_t> e_bytes(BN_num_bytes(e));
if (!BN_bn2bin_padded(n_bytes.data(), n_bytes.size(), n) ||
!BN_bn2bin_padded(e_bytes.data(), e_bytes.size(), e)) {
return false;
}
printf("[mod = %s]\r\n\r\nn = %s\r\n\r\ne = %s", mod_str.c_str(),
EncodeHex(n_bytes).c_str(), EncodeHex(e_bytes).c_str());
test = test.substr(test.find("]") + 3);
}
const EVP_MD *md = EVP_get_digestbyname(hash.c_str());
uint8_t digest_buf[EVP_MAX_MD_SIZE];
std::vector<uint8_t> sig(RSA_size(ctx->key.get()));
unsigned digest_len;
size_t sig_len;
if (md == NULL ||
!EVP_Digest(msg.data(), msg.size(), digest_buf, &digest_len, md, NULL)) {
return false;
}
if (ctx->is_pss) {
if (!RSA_sign_pss_mgf1(ctx->key.get(), &sig_len, sig.data(), sig.size(),
digest_buf, digest_len, md, md, -1)) {
return false;
}
} else {
unsigned sig_len_u;
if (!RSA_sign(EVP_MD_type(md), digest_buf, digest_len, sig.data(),
&sig_len_u, ctx->key.get())) {
return false;
}
sig_len = sig_len_u;
}
sig.resize(sig_len);
printf("%sS = %s\r\n\r\n", test.c_str(), EncodeHex(sig).c_str());
return true;
}
int cavp_rsa2_siggen_test_main(int argc, char **argv) {
if (argc != 3) {
fprintf(stderr, "usage: %s (pkcs15|pss) <test file>\n",
argv[0]);
return 1;
}
TestCtx ctx;
if (strcmp(argv[1], "pkcs15") == 0) {
ctx = {nullptr, false};
} else if (strcmp(argv[1], "pss") == 0) {
ctx = {nullptr, true};
} else {
fprintf(stderr, "Unknown test type: %s\n", argv[1]);
return 1;
}
FileTest::Options opts;
opts.path = argv[2];
opts.callback = TestRSA2SigGen;
opts.arg = &ctx;
opts.silent = true;
opts.comment_callback = EchoComment;
return FileTestMain(opts);
}
@@ -1,125 +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. */
// cavp_rsa2_sigver_test processes NIST CAVP RSA2 SigVer test vector request
// files and emits the corresponding response.
#include <vector>
#include <openssl/bn.h>
#include <openssl/crypto.h>
#include <openssl/digest.h>
#include <openssl/err.h>
#include <openssl/rsa.h>
#include "../crypto/internal.h"
#include "../crypto/test/file_test.h"
#include "cavp_test_util.h"
namespace {
struct TestCtx {
std::vector<uint8_t> N;
bool is_pss;
};
}
static bool TestRSA2SigVer(FileTest *t, void *arg) {
TestCtx *ctx = reinterpret_cast<TestCtx *>(arg);
std::string mod_str;
if (!t->GetInstruction(&mod_str, "mod")) {
return false;
}
printf("%s", t->CurrentTestToString().c_str());
if (t->HasAttribute("n")) {
printf("\r\n");
return t->GetBytes(&ctx->N, "n");
}
std::string hash;
std::vector<uint8_t> e_bytes, msg, sig;
if (!t->GetAttribute(&hash, "SHAAlg") ||
!t->GetBytes(&e_bytes, "e") ||
!t->GetBytes(&msg, "Msg") ||
!t->GetBytes(&sig, "S")) {
return false;
}
bssl::UniquePtr<RSA> key(RSA_new());
key->n = BN_new();
key->e = BN_new();
if (key == nullptr ||
!BN_bin2bn(ctx->N.data(), ctx->N.size(), key->n) ||
!BN_bin2bn(e_bytes.data(), e_bytes.size(), key->e)) {
return false;
}
const EVP_MD *md = EVP_get_digestbyname(hash.c_str());
uint8_t digest_buf[EVP_MAX_MD_SIZE];
unsigned digest_len;
if (md == NULL ||
!EVP_Digest(msg.data(), msg.size(), digest_buf, &digest_len, md, NULL)) {
return false;
}
int ok;
if (ctx->is_pss) {
ok = RSA_verify_pss_mgf1(key.get(), digest_buf, digest_len, md, md, -1,
sig.data(), sig.size());
} else {
ok = RSA_verify(EVP_MD_type(md), digest_buf, digest_len, sig.data(),
sig.size(), key.get());
}
if (ok) {
printf("Result = P\r\n\r\n");
} else {
char buf[256];
ERR_error_string_n(ERR_get_error(), buf, sizeof(buf));
printf("Result = F (%s)\r\n\r\n", buf);
}
ERR_clear_error();
return true;
}
int cavp_rsa2_sigver_test_main(int argc, char **argv) {
if (argc != 3) {
fprintf(stderr, "usage: %s (pkcs15|pss) <test file>\n",
argv[0]);
return 1;
}
TestCtx ctx;
if (strcmp(argv[1], "pkcs15") == 0) {
ctx = {std::vector<uint8_t>(), false};
} else if (strcmp(argv[1], "pss") == 0) {
ctx = {std::vector<uint8_t>(), true};
} else {
fprintf(stderr, "Unknown test type: %s\n", argv[1]);
return 1;
}
FileTest::Options opts;
opts.path = argv[2];
opts.callback = TestRSA2SigVer;
opts.arg = &ctx;
opts.silent = true;
opts.comment_callback = EchoComment;
return FileTestMain(opts);
}
-103
View File
@@ -1,103 +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. */
// cavp_sha_monte_test processes a NIST CAVP SHA-Monte test vector request file
// and emits the corresponding response.
#include <stdlib.h>
#include <openssl/crypto.h>
#include <openssl/digest.h>
#include "../crypto/test/file_test.h"
#include "../crypto/test/test_util.h"
#include "cavp_test_util.h"
namespace {
struct TestCtx {
std::string hash;
};
}
static bool TestSHAMonte(FileTest *t, void *arg) {
TestCtx *ctx = reinterpret_cast<TestCtx *>(arg);
const EVP_MD *md = EVP_get_digestbyname(ctx->hash.c_str());
if (md == nullptr) {
return false;
}
const size_t md_len = EVP_MD_size(md);
std::string out_len;
if (!t->GetInstruction(&out_len, "L") ||
md_len != strtoul(out_len.c_str(), nullptr, 0)) {
return false;
}
std::vector<uint8_t> seed;
if (!t->GetBytes(&seed, "Seed") ||
seed.size() != md_len) {
return false;
}
std::vector<uint8_t> out = seed;
printf("%s\r\n", t->CurrentTestToString().c_str());
for (int count = 0; count < 100; count++) {
std::vector<uint8_t> msg;
msg.insert(msg.end(), out.begin(), out.end());
msg.insert(msg.end(), out.begin(), out.end());
msg.insert(msg.end(), out.begin(), out.end());
for (int i = 0; i < 1000; i++) {
unsigned digest_len;
if (!EVP_Digest(msg.data(), msg.size(), out.data(), &digest_len, md,
nullptr) ||
digest_len != out.size()) {
return false;
}
msg.erase(msg.begin(), msg.begin() + out.size());
msg.insert(msg.end(), out.begin(), out.end());
}
printf("COUNT = %d\r\n", count);
printf("MD = %s\r\n\r\n", EncodeHex(out).c_str());
}
return true;
}
static int usage(char *arg) {
fprintf(stderr, "usage: %s <hash> <test file>\n", arg);
return 1;
}
int cavp_sha_monte_test_main(int argc, char **argv) {
if (argc != 3) {
return usage(argv[0]);
}
TestCtx ctx = {std::string(argv[1])};
FileTest::Options opts;
opts.path = argv[2];
opts.callback = TestSHAMonte;
opts.arg = &ctx;
opts.silent = true;
opts.comment_callback = EchoComment;
return FileTestMain(opts);
}
-97
View File
@@ -1,97 +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. */
// cavp_sha_test processes a NIST CAVP SHA test vector request file and emits
// the corresponding response.
#include <stdlib.h>
#include <openssl/crypto.h>
#include <openssl/digest.h>
#include "../crypto/test/file_test.h"
#include "../crypto/test/test_util.h"
#include "cavp_test_util.h"
namespace {
struct TestCtx {
std::string hash;
};
}
static bool TestSHA(FileTest *t, void *arg) {
TestCtx *ctx = reinterpret_cast<TestCtx *>(arg);
const EVP_MD *md = EVP_get_digestbyname(ctx->hash.c_str());
if (md == nullptr) {
return false;
}
const size_t md_len = EVP_MD_size(md);
std::string out_len;
if (!t->GetInstruction(&out_len, "L") ||
md_len != strtoul(out_len.c_str(), nullptr, 0)) {
return false;
}
std::string msg_len_str;
std::vector<uint8_t> msg;
if (!t->GetAttribute(&msg_len_str, "Len") ||
!t->GetBytes(&msg, "Msg")) {
return false;
}
size_t msg_len = strtoul(msg_len_str.c_str(), nullptr, 0);
if (msg_len % 8 != 0 ||
msg_len / 8 > msg.size()) {
return false;
}
msg_len /= 8;
std::vector<uint8_t> out;
out.resize(md_len);
unsigned digest_len;
if (!EVP_Digest(msg.data(), msg_len, out.data(), &digest_len, md, nullptr) ||
digest_len != out.size()) {
return false;
}
printf("%s", t->CurrentTestToString().c_str());
printf("MD = %s\r\n\r\n", EncodeHex(out).c_str());
return true;
}
static int usage(char *arg) {
fprintf(stderr, "usage: %s <hash> <test file>\n", arg);
return 1;
}
int cavp_sha_test_main(int argc, char **argv) {
if (argc != 3) {
return usage(argv[0]);
}
TestCtx ctx = {std::string(argv[1])};
FileTest::Options opts;
opts.path = argv[2];
opts.callback = TestSHA;
opts.arg = &ctx;
opts.silent = true;
opts.comment_callback = EchoComment;
return FileTestMain(opts);
}
-336
View File
@@ -1,336 +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. */
// cavp_tdes_test processes a NIST TMOVS test vector request file and emits the
// corresponding response.
#include <stdlib.h>
#include <openssl/cipher.h>
#include <openssl/crypto.h>
#include <openssl/err.h>
#include "../crypto/test/file_test.h"
#include "../crypto/test/test_util.h"
#include "cavp_test_util.h"
namespace {
struct TestCtx {
const EVP_CIPHER *cipher;
enum Mode {
kKAT, // Known Answer Test
kMCT, // Monte Carlo Test
};
bool has_iv;
Mode mode;
};
}
static bool TestKAT(FileTest *t, void *arg) {
TestCtx *ctx = reinterpret_cast<TestCtx *>(arg);
if (t->HasInstruction("ENCRYPT") == t->HasInstruction("DECRYPT")) {
t->PrintLine("Want either ENCRYPT or DECRYPT");
return false;
}
enum {
kEncrypt,
kDecrypt,
} operation = t->HasInstruction("ENCRYPT") ? kEncrypt : kDecrypt;
if (t->HasAttribute("NumKeys")) {
// Another file format quirk: NumKeys is a single attribute line immediately
// following an instruction and should probably have been an instruction
// instead. If it is present, the file has separate attributes "KEY{1,2,3}".
// If it is not, the keys are concatenated in a single attribute "KEYs".
std::string num_keys;
t->GetAttribute(&num_keys, "NumKeys");
t->InjectInstruction("NumKeys", num_keys);
std::string header = operation == kEncrypt ? "[ENCRYPT]" : "[DECRYPT]";
printf("%s\r\n\r\n", header.c_str());
return true;
}
enum {
kNotPresent,
kTwo,
kThree,
} num_keys = kNotPresent;
if (t->HasInstruction("NumKeys")) {
std::string num_keys_str;
t->GetInstruction(&num_keys_str, "NumKeys");
const int n = strtoul(num_keys_str.c_str(), nullptr, 0);
if (n == 2) {
num_keys = kTwo;
} else if (n == 3) {
num_keys = kThree;
} else {
t->PrintLine("invalid NumKeys value");
return false;
}
}
std::string count;
std::vector<uint8_t> keys, key1, key2, key3, iv, in, result;
const std::string in_label =
operation == kEncrypt ? "PLAINTEXT" : "CIPHERTEXT";
// clang-format off
if (!t->GetAttribute(&count, "COUNT") ||
(num_keys == 0 && !t->GetBytes(&keys, "KEYs")) ||
(num_keys > 0 &&
(!t->GetBytes(&key1, "KEY1") ||
!t->GetBytes(&key2, "KEY2") ||
!t->GetBytes(&key3, "KEY3"))) ||
(ctx->has_iv && !t->GetBytes(&iv, "IV")) ||
!t->GetBytes(&in, in_label)) {
return false;
}
// clang-format on
std::vector<uint8_t> key;
if (num_keys != kNotPresent) {
key.insert(key.end(), key1.begin(), key1.end());
key.insert(key.end(), key2.begin(), key2.end());
if (num_keys == kThree) {
key.insert(key.end(), key3.begin(), key3.end());
}
} else {
key.insert(key.end(), keys.begin(), keys.end());
key.insert(key.end(), keys.begin(), keys.end());
key.insert(key.end(), keys.begin(), keys.end());
}
if (!CipherOperation(ctx->cipher, &result, operation == kEncrypt, key, iv,
in)) {
return false;
}
// TDES fax files output format differs from file to file, and the input
// format is inconsistent with the output, so we construct the output manually
// rather than printing CurrentTestToString().
if (t->IsAtNewInstructionBlock() && num_keys == kNotPresent) {
// If NumKeys is present, header is printed when parsing NumKeys.
std::string header = operation == kEncrypt ? "[ENCRYPT]" : "[DECRYPT]";
printf("%s\r\n", header.c_str());
}
const std::string result_label =
operation == kEncrypt ? "CIPHERTEXT" : "PLAINTEXT";
printf("COUNT = %s\r\n", count.c_str());
if (num_keys == kNotPresent) {
printf("KEYs = %s\r\n", EncodeHex(keys).c_str());
} else {
printf("KEY1 = %s\r\nKEY2 = %s\r\nKEY3 = %s\r\n", EncodeHex(key1).c_str(),
EncodeHex(key2).c_str(), EncodeHex(key3).c_str());
}
if (ctx->has_iv) {
printf("IV = %s\r\n", EncodeHex(iv).c_str());
}
printf("%s = %s\r\n", in_label.c_str(), EncodeHex(in).c_str());
printf("%s = %s\r\n\r\n", result_label.c_str(), EncodeHex(result).c_str());
return true;
}
// XORKeyWithOddParityLSB sets |*key| to |key| XOR |value| and then writes
// the LSB of each byte to establish odd parity for that byte. This parity-based
// embedded of a DES key into 64 bits is an old tradition and something that
// NIST's tests require.
static void XORKeyWithOddParityLSB(std::vector<uint8_t> *key,
const std::vector<uint8_t> &value) {
for (size_t i = 0; i < key->size(); i++) {
uint8_t v = (*key)[i] ^ value[i];
// Use LSB to establish odd parity.
v |= 0x01;
for (uint8_t j = 1; j < 8; j++) {
v ^= ((v >> j) & 0x01);
}
(*key)[i] = v;
}
}
static bool TestMCT(FileTest *t, void *arg) {
TestCtx *ctx = reinterpret_cast<TestCtx *>(arg);
if (t->HasInstruction("ENCRYPT") == t->HasInstruction("DECRYPT")) {
t->PrintLine("Want either ENCRYPT or DECRYPT");
return false;
}
enum {
kEncrypt,
kDecrypt,
} operation = t->HasInstruction("ENCRYPT") ? kEncrypt : kDecrypt;
if (t->HasAttribute("NumKeys")) {
// Another file format quirk: NumKeys is a single attribute line immediately
// following an instruction and should probably have been an instruction
// instead.
std::string num_keys;
t->GetAttribute(&num_keys, "NumKeys");
t->InjectInstruction("NumKeys", num_keys);
return true;
}
enum {
kTwo,
kThree,
} num_keys;
std::string num_keys_str;
if (!t->GetInstruction(&num_keys_str, "NumKeys")) {
return false;
} else {
const int n = strtoul(num_keys_str.c_str(), nullptr, 0);
if (n == 2) {
num_keys = kTwo;
} else if (n == 3) {
num_keys = kThree;
} else {
t->PrintLine("invalid NumKeys value");
return false;
}
}
std::string count;
std::vector<uint8_t> key1, key2, key3, iv, in, result;
const std::string in_label =
operation == kEncrypt ? "PLAINTEXT" : "CIPHERTEXT";
// clang-format off
if (!t->GetBytes(&key1, "KEY1") ||
!t->GetBytes(&key2, "KEY2") ||
!t->GetBytes(&key3, "KEY3") ||
(ctx->has_iv && !t->GetBytes(&iv, "IV")) ||
!t->GetBytes(&in, in_label)) {
return false;
}
// clang-format on
for (int i = 0; i < 400; i++) {
std::vector<uint8_t> current_iv = iv, current_in = in, prev_result,
prev_prev_result;
std::vector<uint8_t> key(key1);
key.insert(key.end(), key2.begin(), key2.end());
key.insert(key.end(), key3.begin(), key3.end());
for (int j = 0; j < 10000; j++) {
prev_prev_result = prev_result;
prev_result = result;
const EVP_CIPHER *cipher = ctx->cipher;
if (!CipherOperation(cipher, &result, operation == kEncrypt, key,
current_iv, current_in)) {
t->PrintLine("CipherOperation failed");
return false;
}
if (ctx->has_iv) {
if (operation == kEncrypt) {
if (j == 0) {
current_in = current_iv;
} else {
current_in = prev_result;
}
current_iv = result;
} else { // operation == kDecrypt
current_iv = current_in;
current_in = result;
}
} else {
current_in = result;
}
}
// Output result for COUNT = i.
const std::string result_label =
operation == kEncrypt ? "CIPHERTEXT" : "PLAINTEXT";
if (i == 0) {
const std::string op_label =
operation == kEncrypt ? "ENCRYPT" : "DECRYPT";
printf("[%s]\n\n", op_label.c_str());
}
printf("COUNT = %d\r\nKEY1 = %s\r\nKEY2 = %s\r\nKEY3 = %s\r\n", i,
EncodeHex(key1).c_str(), EncodeHex(key2).c_str(),
EncodeHex(key3).c_str());
if (ctx->has_iv) {
printf("IV = %s\r\n", EncodeHex(iv).c_str());
}
printf("%s = %s\r\n", in_label.c_str(), EncodeHex(in).c_str());
printf("%s = %s\r\n\r\n", result_label.c_str(), EncodeHex(result).c_str());
XORKeyWithOddParityLSB(&key1, result);
XORKeyWithOddParityLSB(&key2, prev_result);
if (num_keys == kThree) {
XORKeyWithOddParityLSB(&key3, prev_prev_result);
} else {
XORKeyWithOddParityLSB(&key3, result);
}
if (ctx->has_iv) {
if (operation == kEncrypt) {
in = prev_result;
iv = result;
} else {
iv = current_iv;
in = current_in;
}
} else {
in = result;
}
}
return true;
}
static int usage(char *arg) {
fprintf(stderr, "usage: %s (kat|mct) <cipher> <test file>\n", arg);
return 1;
}
int cavp_tdes_test_main(int argc, char **argv) {
if (argc != 4) {
return usage(argv[0]);
}
const std::string tm(argv[1]);
enum TestCtx::Mode test_mode;
if (tm == "kat") {
test_mode = TestCtx::kKAT;
} else if (tm == "mct") {
test_mode = TestCtx::kMCT;
} else {
fprintf(stderr, "invalid test_mode: %s\n", tm.c_str());
return usage(argv[0]);
}
const std::string cipher_name(argv[2]);
const EVP_CIPHER *cipher = GetCipher(argv[2]);
if (cipher == nullptr) {
fprintf(stderr, "invalid cipher: %s\n", argv[2]);
return 1;
}
bool has_iv = cipher_name != "des-ede" && cipher_name != "des-ede3";
TestCtx ctx = {cipher, has_iv, test_mode};
FileTestFunc test_fn = test_mode == TestCtx::kKAT ? &TestKAT : &TestMCT;
FileTest::Options opts;
opts.path = argv[3];
opts.callback = test_fn;
opts.arg = &ctx;
opts.silent = true;
opts.comment_callback = EchoComment;
return FileTestMain(opts);
}
-220
View File
@@ -1,220 +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 "cavp_test_util.h"
#include <openssl/bn.h>
#include <openssl/digest.h>
#include <openssl/ec.h>
#include <openssl/nid.h>
const EVP_CIPHER *GetCipher(const std::string &name) {
if (name == "des-cbc") {
return EVP_des_cbc();
} else if (name == "des-ecb") {
return EVP_des_ecb();
} else if (name == "des-ede") {
return EVP_des_ede();
} else if (name == "des-ede3") {
return EVP_des_ede3();
} else if (name == "des-ede-cbc") {
return EVP_des_ede_cbc();
} else if (name == "des-ede3-cbc") {
return EVP_des_ede3_cbc();
} else if (name == "rc4") {
return EVP_rc4();
} else if (name == "aes-128-ecb") {
return EVP_aes_128_ecb();
} else if (name == "aes-256-ecb") {
return EVP_aes_256_ecb();
} else if (name == "aes-128-cbc") {
return EVP_aes_128_cbc();
} else if (name == "aes-128-gcm") {
return EVP_aes_128_gcm();
} else if (name == "aes-128-ofb") {
return EVP_aes_128_ofb();
} else if (name == "aes-192-cbc") {
return EVP_aes_192_cbc();
} else if (name == "aes-192-ctr") {
return EVP_aes_192_ctr();
} else if (name == "aes-192-ecb") {
return EVP_aes_192_ecb();
} else if (name == "aes-256-cbc") {
return EVP_aes_256_cbc();
} else if (name == "aes-128-ctr") {
return EVP_aes_128_ctr();
} else if (name == "aes-256-ctr") {
return EVP_aes_256_ctr();
} else if (name == "aes-256-gcm") {
return EVP_aes_256_gcm();
} else if (name == "aes-256-ofb") {
return EVP_aes_256_ofb();
}
return nullptr;
}
bool CipherOperation(const EVP_CIPHER *cipher, std::vector<uint8_t> *out,
bool encrypt, const std::vector<uint8_t> &key,
const std::vector<uint8_t> &iv,
const std::vector<uint8_t> &in) {
bssl::ScopedEVP_CIPHER_CTX ctx;
if (!EVP_CipherInit_ex(ctx.get(), cipher, nullptr, nullptr, nullptr,
encrypt ? 1 : 0)) {
return false;
}
if (!iv.empty() && iv.size() != EVP_CIPHER_CTX_iv_length(ctx.get())) {
return false;
}
int result_len1 = 0, result_len2;
*out = std::vector<uint8_t>(in.size());
if (!EVP_CIPHER_CTX_set_key_length(ctx.get(), key.size()) ||
!EVP_CipherInit_ex(ctx.get(), nullptr, nullptr, key.data(), iv.data(),
-1) ||
!EVP_CIPHER_CTX_set_padding(ctx.get(), 0) ||
!EVP_CipherUpdate(ctx.get(), out->data(), &result_len1, in.data(),
in.size()) ||
!EVP_CipherFinal_ex(ctx.get(), out->data() + result_len1, &result_len2)) {
return false;
}
out->resize(result_len1 + result_len2);
return true;
}
bool AEADEncrypt(const EVP_AEAD *aead, std::vector<uint8_t> *ct,
std::vector<uint8_t> *tag, size_t tag_len,
const std::vector<uint8_t> &key,
const std::vector<uint8_t> &pt,
const std::vector<uint8_t> &aad,
const std::vector<uint8_t> &iv) {
bssl::ScopedEVP_AEAD_CTX ctx;
if (!EVP_AEAD_CTX_init(ctx.get(), aead, key.data(), key.size(), tag_len,
nullptr)) {
return false;
}
std::vector<uint8_t> out;
out.resize(pt.size() + EVP_AEAD_max_overhead(aead));
size_t out_len;
if (!EVP_AEAD_CTX_seal(ctx.get(), out.data(), &out_len, out.size(), iv.data(),
iv.size(), pt.data(), pt.size(), aad.data(),
aad.size())) {
return false;
}
out.resize(out_len);
ct->assign(out.begin(), out.end() - tag_len);
tag->assign(out.end() - tag_len, out.end());
return true;
}
bool AEADDecrypt(const EVP_AEAD *aead, std::vector<uint8_t> *pt, size_t pt_len,
const std::vector<uint8_t> &key,
const std::vector<uint8_t> &aad,
const std::vector<uint8_t> &ct,
const std::vector<uint8_t> &tag,
const std::vector<uint8_t> &iv) {
bssl::ScopedEVP_AEAD_CTX ctx;
if (!EVP_AEAD_CTX_init_with_direction(ctx.get(), aead, key.data(), key.size(),
tag.size(), evp_aead_open)) {
return false;
}
std::vector<uint8_t> in = ct;
in.reserve(ct.size() + tag.size());
in.insert(in.end(), tag.begin(), tag.end());
pt->resize(pt_len);
size_t out_pt_len;
if (!EVP_AEAD_CTX_open(ctx.get(), pt->data(), &out_pt_len, pt->size(),
iv.data(), iv.size(), in.data(), in.size(), aad.data(),
aad.size()) ||
out_pt_len != pt_len) {
return false;
}
return true;
}
static int HexToBIGNUM(bssl::UniquePtr<BIGNUM> *out, const char *in) {
BIGNUM *raw = NULL;
int ret = BN_hex2bn(&raw, in);
out->reset(raw);
return ret;
}
bssl::UniquePtr<BIGNUM> GetBIGNUM(FileTest *t, const char *attribute) {
std::string hex;
if (!t->GetAttribute(&hex, attribute)) {
return nullptr;
}
bssl::UniquePtr<BIGNUM> ret;
if (HexToBIGNUM(&ret, hex.c_str()) != static_cast<int>(hex.size())) {
t->PrintLine("Could not decode '%s'.", hex.c_str());
return nullptr;
}
return ret;
}
int GetECGroupNIDFromInstruction(FileTest *t, const char **out_str) {
const char *dummy;
if (out_str == nullptr) {
out_str = &dummy;
}
if (t->HasInstruction("P-224")) {
*out_str = "P-224";
return NID_secp224r1;
}
if (t->HasInstruction("P-256")) {
*out_str = "P-256";
return NID_X9_62_prime256v1;
}
if (t->HasInstruction("P-384")) {
*out_str = "P-384";
return NID_secp384r1;
}
if (t->HasInstruction("P-521")) {
*out_str = "P-521";
return NID_secp521r1;
}
t->PrintLine("No supported group specified.");
return NID_undef;
}
const EVP_MD *GetDigestFromInstruction(FileTest *t) {
if (t->HasInstruction("SHA-1")) {
return EVP_sha1();
}
if (t->HasInstruction("SHA-224")) {
return EVP_sha224();
}
if (t->HasInstruction("SHA-256")) {
return EVP_sha256();
}
if (t->HasInstruction("SHA-384")) {
return EVP_sha384();
}
if (t->HasInstruction("SHA-512")) {
return EVP_sha512();
}
t->PrintLine("No supported digest function specified.");
return nullptr;
}
void EchoComment(const std::string& comment) {
fwrite(comment.c_str(), comment.size(), 1, stdout);
}
-76
View File
@@ -1,76 +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. */
#ifndef OPENSSL_HEADER_CRYPTO_FIPSMODULE_CAVP_TEST_UTIL_H
#define OPENSSL_HEADER_CRYPTO_FIPSMODULE_CAVP_TEST_UTIL_H
#include <stdlib.h>
#include <string>
#include <vector>
#include <openssl/aead.h>
#include <openssl/cipher.h>
#include "../crypto/test/file_test.h"
const EVP_CIPHER *GetCipher(const std::string &name);
bool CipherOperation(const EVP_CIPHER *cipher, std::vector<uint8_t> *out,
bool encrypt, const std::vector<uint8_t> &key,
const std::vector<uint8_t> &iv,
const std::vector<uint8_t> &in);
bool AEADEncrypt(const EVP_AEAD *aead, std::vector<uint8_t> *ct,
std::vector<uint8_t> *tag, size_t tag_len,
const std::vector<uint8_t> &key,
const std::vector<uint8_t> &pt,
const std::vector<uint8_t> &aad,
const std::vector<uint8_t> &iv);
bool AEADDecrypt(const EVP_AEAD *aead, std::vector<uint8_t> *pt, size_t pt_len,
const std::vector<uint8_t> &key,
const std::vector<uint8_t> &aad,
const std::vector<uint8_t> &ct,
const std::vector<uint8_t> &tag,
const std::vector<uint8_t> &iv);
bssl::UniquePtr<BIGNUM> GetBIGNUM(FileTest *t, const char *attribute);
int GetECGroupNIDFromInstruction(FileTest *t, const char **out_str = nullptr);
const EVP_MD *GetDigestFromInstruction(FileTest *t);
void EchoComment(const std::string& comment);
int cavp_aes_gcm_test_main(int argc, char **argv);
int cavp_aes_test_main(int argc, char **argv);
int cavp_ctr_drbg_test_main(int argc, char **argv);
int cavp_ecdsa2_keypair_test_main(int argc, char **argv);
int cavp_ecdsa2_pkv_test_main(int argc, char **argv);
int cavp_ecdsa2_siggen_test_main(int argc, char **argv);
int cavp_ecdsa2_sigver_test_main(int argc, char **argv);
int cavp_hmac_test_main(int argc, char **argv);
int cavp_kas_test_main(int argc, char **argv);
int cavp_keywrap_test_main(int argc, char **argv);
int cavp_rsa2_keygen_test_main(int argc, char **argv);
int cavp_rsa2_siggen_test_main(int argc, char **argv);
int cavp_rsa2_sigver_test_main(int argc, char **argv);
int cavp_sha_monte_test_main(int argc, char **argv);
int cavp_sha_test_main(int argc, char **argv);
int cavp_tdes_test_main(int argc, char **argv);
int cavp_tlskdf_test_main(int argc, char **argv);
#endif // OPENSSL_HEADER_CRYPTO_FIPSMODULE_CAVP_TEST_UTIL_H
-113
View File
@@ -1,113 +0,0 @@
/* Copyright (c) 2018, 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. */
// cavp_tlskdf_test processes NIST TLS KDF test vectors and emits the
// corresponding response.
// See https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/components/askdfvs.pdf, section 6.4.
#include <vector>
#include <errno.h>
#include <openssl/digest.h>
#include "cavp_test_util.h"
#include "../crypto/fipsmodule/tls/internal.h"
#include "../crypto/test/file_test.h"
#include "../crypto/test/test_util.h"
static bool TestTLSKDF(FileTest *t, void *arg) {
const EVP_MD *md = nullptr;
if (t->HasInstruction("TLS 1.0/1.1")) {
md = EVP_md5_sha1();
} else if (t->HasInstruction("TLS 1.2")) {
if (t->HasInstruction("SHA-256")) {
md = EVP_sha256();
} else if (t->HasInstruction("SHA-384")) {
md = EVP_sha384();
} else if (t->HasInstruction("SHA-512")) {
md = EVP_sha512();
}
}
if (md == nullptr) {
return false;
}
std::string key_block_len_str;
std::vector<uint8_t> premaster, server_random, client_random,
key_block_server_random, key_block_client_random;
if (!t->GetBytes(&premaster, "pre_master_secret") ||
!t->GetBytes(&server_random, "serverHello_random") ||
!t->GetBytes(&client_random, "clientHello_random") ||
// The NIST tests specify different client and server randoms for the
// expansion step from the master-secret step. This is impossible in TLS.
!t->GetBytes(&key_block_server_random, "server_random") ||
!t->GetBytes(&key_block_client_random, "client_random") ||
!t->GetInstruction(&key_block_len_str, "key block length") ||
// These are ignored.
!t->HasAttribute("COUNT") ||
!t->HasInstruction("pre-master secret length")) {
return false;
}
uint8_t master_secret[48];
static const char kMasterSecretLabel[] = "master secret";
if (!CRYPTO_tls1_prf(md, master_secret, sizeof(master_secret),
premaster.data(), premaster.size(), kMasterSecretLabel,
sizeof(kMasterSecretLabel) - 1, client_random.data(),
client_random.size(), server_random.data(),
server_random.size())) {
return false;
}
errno = 0;
const long int key_block_bits =
strtol(key_block_len_str.c_str(), nullptr, 10);
if (errno != 0 || key_block_bits <= 0 || (key_block_bits & 7) != 0) {
return false;
}
const size_t key_block_len = key_block_bits / 8;
std::vector<uint8_t> key_block(key_block_len);
static const char kLabel[] = "key expansion";
if (!CRYPTO_tls1_prf(
md, key_block.data(), key_block.size(), master_secret,
sizeof(master_secret), kLabel, sizeof(kLabel) - 1,
key_block_server_random.data(), key_block_server_random.size(),
key_block_client_random.data(), key_block_client_random.size())) {
return false;
}
printf("%smaster_secret = %s\r\nkey_block = %s\r\n\r\n",
t->CurrentTestToString().c_str(), EncodeHex(master_secret).c_str(),
EncodeHex(key_block).c_str());
return true;
}
int cavp_tlskdf_test_main(int argc, char **argv) {
if (argc != 2) {
fprintf(stderr, "usage: %s <test file>\n", argv[0]);
return 1;
}
FileTest::Options opts;
opts.path = argv[1];
opts.callback = TestTLSKDF;
opts.silent = true;
opts.comment_callback = EchoComment;
return FileTestMain(opts);
}
-592
View File
@@ -1,592 +0,0 @@
// run_cavp.go processes CAVP input files and generates suitable response
// files, optionally comparing the results against the provided FAX files.
package main
import (
"bufio"
"errors"
"flag"
"fmt"
"os"
"os/exec"
"path"
"path/filepath"
"runtime"
"strings"
"sync"
"time"
)
var (
oraclePath = flag.String("oracle-bin", "", "Path to the oracle binary")
suiteDir = flag.String("suite-dir", "", "Base directory containing the CAVP test suite")
noFAX = flag.Bool("no-fax", false, "Skip comparing against FAX files")
android = flag.Bool("android", false, "Run tests via ADB")
)
const (
androidTmpPath = "/data/local/tmp/"
androidCAVPPath = androidTmpPath + "cavp"
androidLibCryptoPath = androidTmpPath + "libcrypto.so"
)
// test describes a single request file.
type test struct {
// inFile is the base of the filename without an extension, i.e.
// “ECBMCT128”.
inFile string
// args are the arguments (not including the input filename) to the
// oracle binary.
args []string
// noFAX, if true, indicates that the output cannot be compared against
// the FAX file. (E.g. because the primitive is non-deterministic.)
noFAX bool
}
// nextLineState can be used by FAX next-line function to store state.
type nextLineState struct {
// State used by the KAS test.
nextIsIUTHash bool
}
// testSuite describes a series of tests that are handled by a single oracle
// binary.
type testSuite struct {
// directory is the name of the directory in the CAVP input, i.e. “AES”.
directory string
// suite names the test suite to pass as the first command-line argument.
suite string
// nextLineFunc, if not nil, is the function used to read the next line
// from the FAX file. This can be used to skip lines and/or mutate them
// as needed. The second argument can be used by the scanner to store
// state, if needed. If isWildcard is true on return then line is not
// meaningful and any line from the response file should be accepted.
nextLineFunc func(*bufio.Scanner, *nextLineState) (line string, isWildcard, ok bool)
tests []test
}
func (t *testSuite) getDirectory() string {
return filepath.Join(*suiteDir, t.directory)
}
var aesGCMTests = testSuite{
"AES_GCM",
"aes_gcm",
nil,
[]test{
{"gcmDecrypt128", []string{"dec", "aes-128-gcm"}, false},
{"gcmDecrypt192", []string{"dec", "aes-192-gcm"}, false},
{"gcmDecrypt256", []string{"dec", "aes-256-gcm"}, false},
{"gcmEncryptExtIV128", []string{"enc", "aes-128-gcm"}, false},
{"gcmEncryptExtIV192", []string{"enc", "aes-192-gcm"}, false},
{"gcmEncryptExtIV256", []string{"enc", "aes-256-gcm"}, false},
},
}
var aesTests = testSuite{
"AES",
"aes",
nil,
[]test{
{"CBCGFSbox128", []string{"kat", "aes-128-cbc"}, false},
{"CBCGFSbox192", []string{"kat", "aes-192-cbc"}, false},
{"CBCGFSbox256", []string{"kat", "aes-256-cbc"}, false},
{"CBCKeySbox128", []string{"kat", "aes-128-cbc"}, false},
{"CBCKeySbox192", []string{"kat", "aes-192-cbc"}, false},
{"CBCKeySbox256", []string{"kat", "aes-256-cbc"}, false},
{"CBCMMT128", []string{"kat", "aes-128-cbc"}, false},
{"CBCMMT192", []string{"kat", "aes-192-cbc"}, false},
{"CBCMMT256", []string{"kat", "aes-256-cbc"}, false},
{"CBCVarKey128", []string{"kat", "aes-128-cbc"}, false},
{"CBCVarKey192", []string{"kat", "aes-192-cbc"}, false},
{"CBCVarKey256", []string{"kat", "aes-256-cbc"}, false},
{"CBCVarTxt128", []string{"kat", "aes-128-cbc"}, false},
{"CBCVarTxt192", []string{"kat", "aes-192-cbc"}, false},
{"CBCVarTxt256", []string{"kat", "aes-256-cbc"}, false},
{"ECBGFSbox128", []string{"kat", "aes-128-ecb"}, false},
{"ECBGFSbox192", []string{"kat", "aes-192-ecb"}, false},
{"ECBGFSbox256", []string{"kat", "aes-256-ecb"}, false},
{"ECBKeySbox128", []string{"kat", "aes-128-ecb"}, false},
{"ECBKeySbox192", []string{"kat", "aes-192-ecb"}, false},
{"ECBKeySbox256", []string{"kat", "aes-256-ecb"}, false},
{"ECBMMT128", []string{"kat", "aes-128-ecb"}, false},
{"ECBMMT192", []string{"kat", "aes-192-ecb"}, false},
{"ECBMMT256", []string{"kat", "aes-256-ecb"}, false},
{"ECBVarKey128", []string{"kat", "aes-128-ecb"}, false},
{"ECBVarKey192", []string{"kat", "aes-192-ecb"}, false},
{"ECBVarKey256", []string{"kat", "aes-256-ecb"}, false},
{"ECBVarTxt128", []string{"kat", "aes-128-ecb"}, false},
{"ECBVarTxt192", []string{"kat", "aes-192-ecb"}, false},
{"ECBVarTxt256", []string{"kat", "aes-256-ecb"}, false},
// AES Monte-Carlo tests
{"ECBMCT128", []string{"mct", "aes-128-ecb"}, false},
{"ECBMCT192", []string{"mct", "aes-192-ecb"}, false},
{"ECBMCT256", []string{"mct", "aes-256-ecb"}, false},
{"CBCMCT128", []string{"mct", "aes-128-cbc"}, false},
{"CBCMCT192", []string{"mct", "aes-192-cbc"}, false},
{"CBCMCT256", []string{"mct", "aes-256-cbc"}, false},
},
}
var ecdsa2KeyPairTests = testSuite{
"ECDSA2",
"ecdsa2_keypair",
nil,
[]test{{"KeyPair", nil, true}},
}
var ecdsa2PKVTests = testSuite{
"ECDSA2",
"ecdsa2_pkv",
nil,
[]test{{"PKV", nil, false}},
}
var ecdsa2SigGenTests = testSuite{
"ECDSA2",
"ecdsa2_siggen",
nil,
[]test{
{"SigGen", []string{"SigGen"}, true},
{"SigGenComponent", []string{"SigGenComponent"}, true},
},
}
var ecdsa2SigVerTests = testSuite{
"ECDSA2",
"ecdsa2_sigver",
nil,
[]test{{"SigVer", nil, false}},
}
var rsa2KeyGenTests = testSuite{
"RSA2",
"rsa2_keygen",
nil,
[]test{
{"KeyGen_RandomProbablyPrime3_3", nil, true},
},
}
var rsa2SigGenTests = testSuite{
"RSA2",
"rsa2_siggen",
nil,
[]test{
{"SigGen15_186-3", []string{"pkcs15"}, true},
{"SigGenPSS_186-3", []string{"pss"}, true},
},
}
var rsa2SigVerTests = testSuite{
"RSA2",
"rsa2_sigver",
func(s *bufio.Scanner, state *nextLineState) (string, bool, bool) {
for {
if !s.Scan() {
return "", false, false
}
line := s.Text()
if strings.HasPrefix(line, "p = ") || strings.HasPrefix(line, "d = ") || strings.HasPrefix(line, "SaltVal = ") || strings.HasPrefix(line, "EM with ") {
continue
}
if strings.HasPrefix(line, "q = ") {
// Skip the "q = " line and an additional blank line.
if !s.Scan() ||
len(strings.TrimSpace(s.Text())) > 0 {
return "", false, false
}
continue
}
return line, false, true
}
},
[]test{
{"SigVer15_186-3", []string{"pkcs15"}, false},
{"SigVerPSS_186-3", []string{"pss"}, false},
},
}
var hmacTests = testSuite{
"HMAC",
"hmac",
nil,
[]test{{"HMAC", nil, false}},
}
var shaTests = testSuite{
"SHA",
"sha",
nil,
[]test{
{"SHA1LongMsg", []string{"SHA1"}, false},
{"SHA1ShortMsg", []string{"SHA1"}, false},
{"SHA224LongMsg", []string{"SHA224"}, false},
{"SHA224ShortMsg", []string{"SHA224"}, false},
{"SHA256LongMsg", []string{"SHA256"}, false},
{"SHA256ShortMsg", []string{"SHA256"}, false},
{"SHA384LongMsg", []string{"SHA384"}, false},
{"SHA384ShortMsg", []string{"SHA384"}, false},
{"SHA512LongMsg", []string{"SHA512"}, false},
{"SHA512ShortMsg", []string{"SHA512"}, false},
},
}
var shaMonteTests = testSuite{
"SHA",
"sha_monte",
nil,
[]test{
{"SHA1Monte", []string{"SHA1"}, false},
{"SHA224Monte", []string{"SHA224"}, false},
{"SHA256Monte", []string{"SHA256"}, false},
{"SHA384Monte", []string{"SHA384"}, false},
{"SHA512Monte", []string{"SHA512"}, false},
},
}
var ctrDRBGTests = testSuite{
"DRBG800-90A",
"ctr_drbg",
nil,
[]test{{"CTR_DRBG", nil, false}},
}
var tdesTests = testSuite{
"TDES",
"tdes",
nil,
[]test{
{"TCBCMMT2", []string{"kat", "des-ede-cbc"}, false},
{"TCBCMMT3", []string{"kat", "des-ede3-cbc"}, false},
{"TCBCMonte2", []string{"mct", "des-ede3-cbc"}, false},
{"TCBCMonte3", []string{"mct", "des-ede3-cbc"}, false},
{"TCBCinvperm", []string{"kat", "des-ede3-cbc"}, false},
{"TCBCpermop", []string{"kat", "des-ede3-cbc"}, false},
{"TCBCsubtab", []string{"kat", "des-ede3-cbc"}, false},
{"TCBCvarkey", []string{"kat", "des-ede3-cbc"}, false},
{"TCBCvartext", []string{"kat", "des-ede3-cbc"}, false},
{"TECBMMT2", []string{"kat", "des-ede"}, false},
{"TECBMMT3", []string{"kat", "des-ede3"}, false},
{"TECBMonte2", []string{"mct", "des-ede3"}, false},
{"TECBMonte3", []string{"mct", "des-ede3"}, false},
{"TECBinvperm", []string{"kat", "des-ede3"}, false},
{"TECBpermop", []string{"kat", "des-ede3"}, false},
{"TECBsubtab", []string{"kat", "des-ede3"}, false},
{"TECBvarkey", []string{"kat", "des-ede3"}, false},
{"TECBvartext", []string{"kat", "des-ede3"}, false},
},
}
var keyWrapTests = testSuite{
"KeyWrap38F",
"keywrap",
nil,
[]test{
{"KW_AD_128", []string{"dec", "128"}, false},
{"KW_AD_192", []string{"dec", "192"}, false},
{"KW_AD_256", []string{"dec", "256"}, false},
{"KW_AE_128", []string{"enc", "128"}, false},
{"KW_AE_192", []string{"enc", "192"}, false},
{"KW_AE_256", []string{"enc", "256"}, false},
{"KWP_AD_128", []string{"dec-pad", "128"}, false},
{"KWP_AD_192", []string{"dec-pad", "192"}, false},
{"KWP_AD_256", []string{"dec-pad", "256"}, false},
{"KWP_AE_128", []string{"enc-pad", "128"}, false},
{"KWP_AE_192", []string{"enc-pad", "192"}, false},
{"KWP_AE_256", []string{"enc-pad", "256"}, false},
},
}
var kasTests = testSuite{
"KAS",
"kas",
func(s *bufio.Scanner, state *nextLineState) (line string, isWildcard, ok bool) {
for {
// If the response file will include the IUT hash next,
// return a wildcard signal because this cannot be
// matched against the FAX file.
if state.nextIsIUTHash {
state.nextIsIUTHash = false
return "", true, true
}
if !s.Scan() {
return "", false, false
}
line := s.Text()
if strings.HasPrefix(line, "deCAVS = ") || strings.HasPrefix(line, "Z = ") {
continue
}
if strings.HasPrefix(line, "CAVSHashZZ = ") {
state.nextIsIUTHash = true
}
return line, false, true
}
},
[]test{
{"KASFunctionTest_ECCEphemeralUnified_NOKC_ZZOnly_init", []string{"function"}, true},
{"KASFunctionTest_ECCEphemeralUnified_NOKC_ZZOnly_resp", []string{"function"}, true},
{"KASValidityTest_ECCEphemeralUnified_NOKC_ZZOnly_init", []string{"validity"}, false},
{"KASValidityTest_ECCEphemeralUnified_NOKC_ZZOnly_resp", []string{"validity"}, false},
},
}
var tlsKDFTests = testSuite{
"KDF135",
"tlskdf",
nil,
[]test{
{"tls", nil, false},
},
}
var testSuites = []*testSuite{
&aesGCMTests,
&aesTests,
&ctrDRBGTests,
&ecdsa2KeyPairTests,
&ecdsa2PKVTests,
&ecdsa2SigGenTests,
&ecdsa2SigVerTests,
&hmacTests,
&keyWrapTests,
&rsa2KeyGenTests,
&rsa2SigGenTests,
&rsa2SigVerTests,
&shaTests,
&shaMonteTests,
&tdesTests,
&kasTests,
&tlsKDFTests,
}
// testInstance represents a specific test in a testSuite.
type testInstance struct {
suite *testSuite
testIndex int
}
func worker(wg *sync.WaitGroup, work <-chan testInstance) {
defer wg.Done()
for ti := range work {
test := ti.suite.tests[ti.testIndex]
if err := doTest(ti.suite, test); err != nil {
fmt.Fprintf(os.Stderr, "%s\n", err)
os.Exit(2)
}
if !*noFAX && !test.noFAX {
if err := compareFAX(ti.suite, test); err != nil {
fmt.Fprintf(os.Stderr, "%s\n", err)
os.Exit(3)
}
}
}
}
func checkAndroidPrereqs() error {
// The cavp binary, and a matching libcrypto.so, are required to be placed
// in /data/local/tmp before running this script.
if err := exec.Command("adb", "shell", "ls", androidCAVPPath).Run(); err != nil {
return errors.New("failed to list cavp binary; ensure that adb works and cavp binary is in place: " + err.Error())
}
if err := exec.Command("adb", "shell", "ls", androidLibCryptoPath).Run(); err != nil {
return errors.New("failed to list libcrypto.so; ensure that library is in place: " + err.Error())
}
return nil
}
func main() {
flag.Parse()
if *android {
if err := checkAndroidPrereqs(); err != nil {
fmt.Fprintf(os.Stderr, "%s\n", err)
os.Exit(1)
}
} else if len(*oraclePath) == 0 {
fmt.Fprintf(os.Stderr, "Must give -oracle-bin\n")
os.Exit(1)
}
work := make(chan testInstance)
var wg sync.WaitGroup
numWorkers := runtime.NumCPU()
if *android {
numWorkers = 1
}
for i := 0; i < numWorkers; i++ {
wg.Add(1)
go worker(&wg, work)
}
for _, suite := range testSuites {
for i := range suite.tests {
work <- testInstance{suite, i}
}
}
close(work)
wg.Wait()
}
func doTest(suite *testSuite, test test) error {
bin := *oraclePath
var args []string
if *android {
bin = "adb"
args = []string{"shell", "LD_LIBRARY_PATH=" + androidTmpPath, androidCAVPPath}
}
args = append(args, suite.suite)
args = append(args, test.args...)
reqPath := filepath.Join(suite.getDirectory(), "req", test.inFile+".req")
var reqPathOnDevice string
if *android {
reqPathOnDevice = path.Join(androidTmpPath, test.inFile+".req")
if err := exec.Command("adb", "push", reqPath, reqPathOnDevice).Run(); err != nil {
return errors.New("failed to push request file: " + err.Error())
}
args = append(args, reqPathOnDevice)
} else {
args = append(args, reqPath)
}
respDir := filepath.Join(suite.getDirectory(), "resp")
if err := os.Mkdir(respDir, 0755); err != nil && !os.IsExist(err) {
return fmt.Errorf("cannot create resp directory: %s", err)
}
outPath := filepath.Join(respDir, test.inFile+".rsp")
outFile, err := os.OpenFile(outPath, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644)
if err != nil {
return fmt.Errorf("cannot open output file for %q %q: %s", suite.getDirectory(), test.inFile, err)
}
defer outFile.Close()
cmd := exec.Command(bin, args...)
cmd.Stdout = outFile
cmd.Stderr = os.Stderr
cmdLine := strings.Join(append([]string{bin}, args...), " ")
startTime := time.Now()
if err := cmd.Run(); err != nil {
return fmt.Errorf("cannot run command for %q %q (%s): %s", suite.getDirectory(), test.inFile, cmdLine, err)
}
fmt.Printf("%s (%ds)\n", cmdLine, int(time.Since(startTime).Seconds()))
if *android {
exec.Command("adb", "shell", "rm", reqPathOnDevice).Run()
}
return nil
}
func canonicalizeLine(in string) string {
if strings.HasPrefix(in, "Result = P (") {
return "Result = P"
}
if strings.HasPrefix(in, "Result = F (") {
return "Result = F"
}
return in
}
func compareFAX(suite *testSuite, test test) error {
nextLineFunc := suite.nextLineFunc
if nextLineFunc == nil {
nextLineFunc = func(s *bufio.Scanner, state *nextLineState) (string, bool, bool) {
if !s.Scan() {
return "", false, false
}
return s.Text(), false, true
}
}
respPath := filepath.Join(suite.getDirectory(), "resp", test.inFile+".rsp")
respFile, err := os.Open(respPath)
if err != nil {
return fmt.Errorf("cannot read output of %q %q: %s", suite.getDirectory(), test.inFile, err)
}
defer respFile.Close()
faxPath := filepath.Join(suite.getDirectory(), "fax", test.inFile+".fax")
faxFile, err := os.Open(faxPath)
if err != nil {
return fmt.Errorf("cannot open fax file for %q %q: %s", suite.getDirectory(), test.inFile, err)
}
defer faxFile.Close()
respScanner := bufio.NewScanner(respFile)
faxScanner := bufio.NewScanner(faxFile)
var nextLineState nextLineState
lineNo := 0
inHeader := true
for respScanner.Scan() {
lineNo++
respLine := respScanner.Text()
var faxLine string
var isWildcard, ok bool
if inHeader && (len(respLine) == 0 || respLine[0] == '#') {
continue
}
for {
haveFaxLine := false
if inHeader {
for {
if faxLine, isWildcard, ok = nextLineFunc(faxScanner, &nextLineState); !ok {
break
}
if len(faxLine) != 0 && faxLine[0] != '#' {
haveFaxLine = true
break
}
}
inHeader = false
} else {
faxLine, isWildcard, haveFaxLine = nextLineFunc(faxScanner, &nextLineState)
}
if !haveFaxLine {
// Ignore blank lines at the end of the generated file.
if len(respLine) == 0 {
break
}
return fmt.Errorf("resp file is longer than fax for %q %q", suite.getDirectory(), test.inFile)
}
if strings.HasPrefix(faxLine, " (Reason: ") {
continue
}
break
}
if isWildcard || canonicalizeLine(faxLine) == canonicalizeLine(respLine) {
continue
}
return fmt.Errorf("resp and fax differ at line %d for %q %q: %q vs %q", lineNo, suite.getDirectory(), test.inFile, respLine, faxLine)
}
if _, _, ok := nextLineFunc(faxScanner, &nextLineState); ok {
return fmt.Errorf("fax file is longer than resp for %q %q", suite.getDirectory(), test.inFile)
}
return nil
}
+1 -1
View File
@@ -18,7 +18,7 @@
set -x
set -e
TEST_FIPS_BIN="build/util/fipstools/cavp/test_fips"
TEST_FIPS_BIN="build/util/fipstools/test_fips"
if [ ! -f $TEST_FIPS_BIN ]; then
echo "$TEST_FIPS_BIN is missing. Run this script from the top level of a"
@@ -30,9 +30,9 @@
#include <openssl/rsa.h>
#include <openssl/sha.h>
#include "../crypto/fipsmodule/rand/internal.h"
#include "../crypto/fipsmodule/tls/internal.h"
#include "../crypto/internal.h"
#include "../../crypto/fipsmodule/rand/internal.h"
#include "../../crypto/fipsmodule/tls/internal.h"
#include "../../crypto/internal.h"
static void hexdump(const void *a, size_t len) {