Quellcode durchsuchen

Add ECDSA and RSA verify Wycheproof drivers.

Along the way, add some utility functions for getting common things
(curves, hashes, etc.) in the names Wycheproof uses.

Change-Id: I09c11ea2970cf2c8a11a8c2a861d85396efda125
Reviewed-on: https://boringssl-review.googlesource.com/27786
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
Reviewed-by: Adam Langley <agl@google.com>
kris/onging/CECPQ3_patch15
David Benjamin vor 6 Jahren
committed by CQ bot account: commit-bot@chromium.org
Ursprung
Commit
40d76f4f7d
15 geänderte Dateien mit 16835 neuen und 47 gelöschten Zeilen
  1. +52
    -0
      crypto/evp/evp_test.cc
  2. +1
    -0
      crypto/test/CMakeLists.txt
  3. +47
    -40
      crypto/test/file_test.cc
  4. +5
    -0
      crypto/test/file_test.h
  5. +91
    -0
      crypto/test/wycheproof_util.cc
  6. +45
    -0
      crypto/test/wycheproof_util.h
  7. +7
    -0
      sources.cmake
  8. +7
    -7
      third_party/wycheproof/convert_wycheproof.go
  9. +2333
    -0
      third_party/wycheproof/ecdsa_secp224r1_sha224_test.txt
  10. +2324
    -0
      third_party/wycheproof/ecdsa_secp224r1_sha256_test.txt
  11. +2404
    -0
      third_party/wycheproof/ecdsa_secp256r1_sha256_test.txt
  12. +2293
    -0
      third_party/wycheproof/ecdsa_secp384r1_sha384_test.txt
  13. +2302
    -0
      third_party/wycheproof/ecdsa_secp384r1_sha512_test.txt
  14. +2318
    -0
      third_party/wycheproof/ecdsa_secp521r1_sha512_test.txt
  15. +2606
    -0
      third_party/wycheproof/rsa_signature_test.txt

+ 52
- 0
crypto/evp/evp_test.cc Datei anzeigen

@@ -79,6 +79,7 @@ OPENSSL_MSVC_PRAGMA(warning(pop))

#include "../test/file_test.h"
#include "../test/test_util.h"
#include "../test/wycheproof_util.h"


// evp_test dispatches between multiple test types. PrivateKey tests take a key
@@ -413,3 +414,54 @@ TEST(EVPTest, TestVectors) {
}
});
}

static void RunWycheproofTest(const char *path) {
SCOPED_TRACE(path);
FileTestGTest(path, [](FileTest *t) {
t->IgnoreInstruction("key.type");
// Extra ECDSA fields.
t->IgnoreInstruction("key.curve");
t->IgnoreInstruction("key.keySize");
t->IgnoreInstruction("key.wx");
t->IgnoreInstruction("key.wy");
// Extra RSA fields.
t->IgnoreInstruction("e");
t->IgnoreInstruction("keyAsn");
t->IgnoreInstruction("keysize");
t->IgnoreInstruction("n");
t->IgnoreAttribute("padding");

std::vector<uint8_t> der;
ASSERT_TRUE(t->GetInstructionBytes(&der, "keyDer"));
CBS cbs;
CBS_init(&cbs, der.data(), der.size());
bssl::UniquePtr<EVP_PKEY> key(EVP_parse_public_key(&cbs));
ASSERT_TRUE(key);

const EVP_MD *md = GetWycheproofDigest(t, "sha", true);
ASSERT_TRUE(md);
std::vector<uint8_t> msg;
ASSERT_TRUE(t->GetBytes(&msg, "msg"));
std::vector<uint8_t> sig;
ASSERT_TRUE(t->GetBytes(&sig, "sig"));

bssl::ScopedEVP_MD_CTX ctx;
ASSERT_TRUE(
EVP_DigestVerifyInit(ctx.get(), nullptr, md, nullptr, key.get()));
WycheproofResult result;
ASSERT_TRUE(GetWycheproofResult(t, &result));
EXPECT_EQ(result == WycheproofResult::kValid ? 1 : 0,
EVP_DigestVerify(ctx.get(), sig.data(), sig.size(), msg.data(),
msg.size()));
});
}

TEST(EVPTest, Wycheproof) {
RunWycheproofTest("third_party/wycheproof/ecdsa_secp224r1_sha224_test.txt");
RunWycheproofTest("third_party/wycheproof/ecdsa_secp224r1_sha256_test.txt");
RunWycheproofTest("third_party/wycheproof/ecdsa_secp256r1_sha256_test.txt");
RunWycheproofTest("third_party/wycheproof/ecdsa_secp384r1_sha384_test.txt");
RunWycheproofTest("third_party/wycheproof/ecdsa_secp384r1_sha512_test.txt");
RunWycheproofTest("third_party/wycheproof/ecdsa_secp521r1_sha512_test.txt");
RunWycheproofTest("third_party/wycheproof/rsa_signature_test.txt");
}

+ 1
- 0
crypto/test/CMakeLists.txt Datei anzeigen

@@ -6,6 +6,7 @@ add_library(
file_test.cc
malloc.cc
test_util.cc
wycheproof_util.cc
)

add_library(


+ 47
- 40
crypto/test/file_test.cc Datei anzeigen

@@ -286,52 +286,19 @@ bool FileTest::GetInstruction(std::string *out_value, const std::string &key) {
return true;
}

const std::string &FileTest::CurrentTestToString() const {
return current_test_;
bool FileTest::GetInstructionBytes(std::vector<uint8_t> *out,
const std::string &key) {
std::string value;
return GetInstruction(&value, key) && ConvertToBytes(out, value);
}

static bool FromHexDigit(uint8_t *out, char c) {
if ('0' <= c && c <= '9') {
*out = c - '0';
return true;
}
if ('a' <= c && c <= 'f') {
*out = c - 'a' + 10;
return true;
}
if ('A' <= c && c <= 'F') {
*out = c - 'A' + 10;
return true;
}
return false;
const std::string &FileTest::CurrentTestToString() const {
return current_test_;
}

bool FileTest::GetBytes(std::vector<uint8_t> *out, const std::string &key) {
std::string value;
if (!GetAttribute(&value, key)) {
return false;
}

if (value.size() >= 2 && value[0] == '"' && value[value.size() - 1] == '"') {
out->assign(value.begin() + 1, value.end() - 1);
return true;
}

if (value.size() % 2 != 0) {
PrintLine("Error decoding value: %s", value.c_str());
return false;
}
out->clear();
out->reserve(value.size() / 2);
for (size_t i = 0; i < value.size(); i += 2) {
uint8_t hi, lo;
if (!FromHexDigit(&hi, value[i]) || !FromHexDigit(&lo, value[i + 1])) {
PrintLine("Error decoding value: %s", value.c_str());
return false;
}
out->push_back((hi << 4) | lo);
}
return true;
return GetAttribute(&value, key) && ConvertToBytes(out, value);
}

static std::string EncodeHex(const uint8_t *in, size_t in_len) {
@@ -381,6 +348,46 @@ void FileTest::OnInstructionUsed(const std::string &key) {
unused_instructions_.erase(key);
}

static bool FromHexDigit(uint8_t *out, char c) {
if ('0' <= c && c <= '9') {
*out = c - '0';
return true;
}
if ('a' <= c && c <= 'f') {
*out = c - 'a' + 10;
return true;
}
if ('A' <= c && c <= 'F') {
*out = c - 'A' + 10;
return true;
}
return false;
}

bool FileTest::ConvertToBytes(std::vector<uint8_t> *out,
const std::string &value) {
if (value.size() >= 2 && value[0] == '"' && value[value.size() - 1] == '"') {
out->assign(value.begin() + 1, value.end() - 1);
return true;
}

if (value.size() % 2 != 0) {
PrintLine("Error decoding value: %s", value.c_str());
return false;
}
out->clear();
out->reserve(value.size() / 2);
for (size_t i = 0; i < value.size(); i += 2) {
uint8_t hi, lo;
if (!FromHexDigit(&hi, value[i]) || !FromHexDigit(&lo, value[i + 1])) {
PrintLine("Error decoding value: %s", value.c_str());
return false;
}
out->push_back((hi << 4) | lo);
}
return true;
}

bool FileTest::IsAtNewInstructionBlock() const {
return is_at_new_instruction_block_;
}


+ 5
- 0
crypto/test/file_test.h Datei anzeigen

@@ -185,6 +185,10 @@ class FileTest {
// otherwise.
bool GetInstruction(std::string *out_value, const std::string &key);

// GetInstructionBytes behaves like GetBytes, but looks up the corresponding
// instruction.
bool GetInstructionBytes(std::vector<uint8_t> *out, const std::string &key);

// CurrentTestToString returns the file content parsed for the current test.
// If the current test was preceded by an instruction block, the return test
// case is preceded by the instruction block and a single blank line. All
@@ -203,6 +207,7 @@ class FileTest {
void ClearInstructions();
void OnKeyUsed(const std::string &key);
void OnInstructionUsed(const std::string &key);
bool ConvertToBytes(std::vector<uint8_t> *out, const std::string &value);

std::unique_ptr<LineReader> reader_;
// line_ is the number of lines read.


+ 91
- 0
crypto/test/wycheproof_util.cc Datei anzeigen

@@ -0,0 +1,91 @@
/* 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. */

#include "./wycheproof_util.h"

#include <openssl/digest.h>
#include <openssl/ec.h>
#include <openssl/nid.h>

#include "./file_test.h"


bool GetWycheproofResult(FileTest *t, WycheproofResult *out) {
std::string result;
if (!t->GetAttribute(&result, "result")) {
return false;
}
if (result == "valid") {
*out = WycheproofResult::kValid;
} else if (result == "invalid") {
*out = WycheproofResult::kInvalid;
} else if (result == "acceptable") {
*out = WycheproofResult::kAcceptable;
} else {
t->PrintLine("Bad result string '%s'", result.c_str());
return false;
}
return true;
}

const EVP_MD *GetWycheproofDigest(FileTest *t, const char *key,
bool instruction) {
std::string name;
bool ok =
instruction ? t->GetInstruction(&name, key) : t->GetAttribute(&name, key);
if (!ok) {
return nullptr;
}
if (name == "SHA-1") {
return EVP_sha1();
}
if (name == "SHA-224") {
return EVP_sha224();
}
if (name == "SHA-256") {
return EVP_sha256();
}
if (name == "SHA-384") {
return EVP_sha384();
}
if (name == "SHA-512") {
return EVP_sha512();
}
t->PrintLine("Unknown digest '%s'", name.c_str());
return nullptr;
}

bssl::UniquePtr<EC_GROUP> GetWycheproofCurve(FileTest *t, const char *key,
bool instruction) {
std::string name;
bool ok =
instruction ? t->GetInstruction(&name, key) : t->GetAttribute(&name, key);
if (!ok) {
return nullptr;
}
int nid;
if (name == "secp224r1") {
nid = NID_secp224r1;
} else if (name == "secp256r1") {
nid = NID_X9_62_prime256v1;
} else if (name == "secp384r1") {
nid = NID_secp384r1;
} else if (name == "secp521r1") {
nid = NID_secp521r1;
} else {
t->PrintLine("Unknown curve '%s'", name.c_str());
return nullptr;
}
return bssl::UniquePtr<EC_GROUP>(EC_GROUP_new_by_curve_name(nid));
}

+ 45
- 0
crypto/test/wycheproof_util.h Datei anzeigen

@@ -0,0 +1,45 @@
/* 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. */

#ifndef OPENSSL_HEADER_CRYPTO_TEST_WYCHEPROOF_UTIL_H
#define OPENSSL_HEADER_CRYPTO_TEST_WYCHEPROOF_UTIL_H

#include <openssl/base.h>


// This header contains convenience functions for Wycheproof tests.

class FileTest;

enum class WycheproofResult {
kValid,
kInvalid,
kAcceptable,
};

// GetWycheproofResult sets |*out| to the parsed "result" key of |t|.
bool GetWycheproofResult(FileTest *t, WycheproofResult *out);

// GetWycheproofDigest returns a digest function using the Wycheproof name, or
// nullptr on error.
const EVP_MD *GetWycheproofDigest(FileTest *t, const char *key,
bool instruction);

// GetWycheproofCurve returns a curve using the Wycheproof name, or nullptr on
// error.
bssl::UniquePtr<EC_GROUP> GetWycheproofCurve(FileTest *t, const char *key,
bool instruction);


#endif // OPENSSL_HEADER_CRYPTO_TEST_WYCHEPROOF_UTIL_H

+ 7
- 0
sources.cmake Datei anzeigen

@@ -59,5 +59,12 @@ set(
crypto/x509/some_names1.pem
crypto/x509/some_names2.pem
crypto/x509/some_names3.pem
third_party/wycheproof/ecdsa_secp224r1_sha224_test.txt
third_party/wycheproof/ecdsa_secp224r1_sha256_test.txt
third_party/wycheproof/ecdsa_secp256r1_sha256_test.txt
third_party/wycheproof/ecdsa_secp384r1_sha384_test.txt
third_party/wycheproof/ecdsa_secp384r1_sha512_test.txt
third_party/wycheproof/ecdsa_secp521r1_sha512_test.txt
third_party/wycheproof/rsa_signature_test.txt
third_party/wycheproof/x25519_test.txt
)

+ 7
- 7
third_party/wycheproof/convert_wycheproof.go Datei anzeigen

@@ -224,6 +224,13 @@ func convertWycheproof(jsonPath, txtPath string) error {

func main() {
jsonPaths := []string{
"ecdsa_secp224r1_sha224_test.json",
"ecdsa_secp224r1_sha256_test.json",
"ecdsa_secp256r1_sha256_test.json",
"ecdsa_secp384r1_sha384_test.json",
"ecdsa_secp384r1_sha512_test.json",
"ecdsa_secp521r1_sha512_test.json",
"rsa_signature_test.json",
"x25519_test.json",

// TODO(davidben): The following tests still need test drivers.
@@ -233,14 +240,7 @@ func main() {
// "chacha20_poly1305_test.json",
// "dsa_test.json",
// "ecdh_test.json",
// "ecdsa_secp224r1_sha224_test.json",
// "ecdsa_secp224r1_sha256_test.json",
// "ecdsa_secp256r1_sha256_test.json",
// "ecdsa_secp384r1_sha384_test.json",
// "ecdsa_secp384r1_sha512_test.json",
// "ecdsa_secp521r1_sha512_test.json",
// "eddsa_test.json",
// "rsa_signature_test.json",
}
for _, jsonPath := range jsonPaths {
if !strings.HasSuffix(jsonPath, ".json") {


+ 2333
- 0
third_party/wycheproof/ecdsa_secp224r1_sha224_test.txt
Datei-Diff unterdrückt, da er zu groß ist
Datei anzeigen


+ 2324
- 0
third_party/wycheproof/ecdsa_secp224r1_sha256_test.txt
Datei-Diff unterdrückt, da er zu groß ist
Datei anzeigen


+ 2404
- 0
third_party/wycheproof/ecdsa_secp256r1_sha256_test.txt
Datei-Diff unterdrückt, da er zu groß ist
Datei anzeigen


+ 2293
- 0
third_party/wycheproof/ecdsa_secp384r1_sha384_test.txt
Datei-Diff unterdrückt, da er zu groß ist
Datei anzeigen


+ 2302
- 0
third_party/wycheproof/ecdsa_secp384r1_sha512_test.txt
Datei-Diff unterdrückt, da er zu groß ist
Datei anzeigen


+ 2318
- 0
third_party/wycheproof/ecdsa_secp521r1_sha512_test.txt
Datei-Diff unterdrückt, da er zu groß ist
Datei anzeigen


+ 2606
- 0
third_party/wycheproof/rsa_signature_test.txt
Datei-Diff unterdrückt, da er zu groß ist
Datei anzeigen


Laden…
Abbrechen
Speichern