diff options
Diffstat (limited to 'src/crypto/evp/evp_test.cc')
-rw-r--r-- | src/crypto/evp/evp_test.cc | 156 |
1 files changed, 142 insertions, 14 deletions
diff --git a/src/crypto/evp/evp_test.cc b/src/crypto/evp/evp_test.cc index 4d742920..b4be636b 100644 --- a/src/crypto/evp/evp_test.cc +++ b/src/crypto/evp/evp_test.cc @@ -119,6 +119,9 @@ static int GetKeyType(FileTest *t, const std::string &name) { if (name == "Ed25519") { return EVP_PKEY_ED25519; } + if (name == "X25519") { + return EVP_PKEY_X25519; + } ADD_FAILURE() << "Unknown key type: " << name; return EVP_PKEY_NONE; } @@ -179,7 +182,62 @@ static bool ImportKey(FileTest *t, KeyMap *key_map, !t->GetBytes(&output, "Output")) { return false; } - EXPECT_EQ(Bytes(output), Bytes(der, der_len)) << "Re-encoding the key did not match."; + EXPECT_EQ(Bytes(output), Bytes(der, der_len)) + << "Re-encoding the key did not match."; + + if (t->HasAttribute("ExpectNoRawPrivate")) { + size_t len; + EXPECT_FALSE(EVP_PKEY_get_raw_private_key(pkey.get(), nullptr, &len)); + } else if (t->HasAttribute("ExpectRawPrivate")) { + std::vector<uint8_t> expected; + if (!t->GetBytes(&expected, "ExpectRawPrivate")) { + return false; + } + + std::vector<uint8_t> raw; + size_t len; + if (!EVP_PKEY_get_raw_private_key(pkey.get(), nullptr, &len)) { + return false; + } + raw.resize(len); + if (!EVP_PKEY_get_raw_private_key(pkey.get(), raw.data(), &len)) { + return false; + } + raw.resize(len); + EXPECT_EQ(Bytes(raw), Bytes(expected)); + + // Short buffers should be rejected. + raw.resize(len - 1); + len = raw.size(); + EXPECT_FALSE(EVP_PKEY_get_raw_private_key(pkey.get(), raw.data(), &len)); + } + + if (t->HasAttribute("ExpectNoRawPublic")) { + size_t len; + EXPECT_FALSE(EVP_PKEY_get_raw_public_key(pkey.get(), nullptr, &len)); + } else if (t->HasAttribute("ExpectRawPublic")) { + std::vector<uint8_t> expected; + if (!t->GetBytes(&expected, "ExpectRawPublic")) { + return false; + } + + std::vector<uint8_t> raw; + size_t len; + if (!EVP_PKEY_get_raw_public_key(pkey.get(), nullptr, &len)) { + return false; + } + raw.resize(len); + if (!EVP_PKEY_get_raw_public_key(pkey.get(), raw.data(), &len)) { + return false; + } + raw.resize(len); + EXPECT_EQ(Bytes(raw), Bytes(expected)); + + // Short buffers should be rejected. + raw.resize(len - 1); + len = raw.size(); + EXPECT_FALSE(EVP_PKEY_get_raw_public_key(pkey.get(), raw.data(), &len)); + } // Save the key for future tests. const std::string &key_name = t->GetParameter(); @@ -190,7 +248,7 @@ static bool ImportKey(FileTest *t, KeyMap *key_map, // SetupContext configures |ctx| based on attributes in |t|, with the exception // of the signing digest which must be configured externally. -static bool SetupContext(FileTest *t, EVP_PKEY_CTX *ctx) { +static bool SetupContext(FileTest *t, KeyMap *key_map, EVP_PKEY_CTX *ctx) { if (t->HasAttribute("RSAPadding")) { int padding; if (!GetRSAPadding(t, &padding, t->GetAttributeOrDie("RSAPadding")) || @@ -230,6 +288,74 @@ static bool SetupContext(FileTest *t, EVP_PKEY_CTX *ctx) { } buf.release(); } + if (t->HasAttribute("DerivePeer")) { + std::string derive_peer = t->GetAttributeOrDie("DerivePeer"); + if (key_map->count(derive_peer) == 0) { + ADD_FAILURE() << "Could not find key " << derive_peer; + return false; + } + EVP_PKEY *derive_peer_key = (*key_map)[derive_peer].get(); + if (!EVP_PKEY_derive_set_peer(ctx, derive_peer_key)) { + return false; + } + } + return true; +} + +static bool TestDerive(FileTest *t, KeyMap *key_map, EVP_PKEY *key) { + bssl::UniquePtr<EVP_PKEY_CTX> ctx(EVP_PKEY_CTX_new(key, nullptr)); + if (!ctx || + !EVP_PKEY_derive_init(ctx.get()) || + !SetupContext(t, key_map, ctx.get())) { + return false; + } + + bssl::UniquePtr<EVP_PKEY_CTX> copy(EVP_PKEY_CTX_dup(ctx.get())); + if (!copy) { + return false; + } + + for (EVP_PKEY_CTX *pctx : {ctx.get(), copy.get()}) { + size_t len; + std::vector<uint8_t> actual, output; + if (!EVP_PKEY_derive(pctx, nullptr, &len)) { + return false; + } + actual.resize(len); + if (!EVP_PKEY_derive(pctx, actual.data(), &len)) { + return false; + } + actual.resize(len); + + // Defer looking up the attribute so Error works properly. + if (!t->GetBytes(&output, "Output")) { + return false; + } + EXPECT_EQ(Bytes(output), Bytes(actual)); + + // Test when the buffer is too large. + actual.resize(len + 1); + len = actual.size(); + if (!EVP_PKEY_derive(pctx, actual.data(), &len)) { + return false; + } + actual.resize(len); + EXPECT_EQ(Bytes(output), Bytes(actual)); + + // Test when the buffer is too small. + actual.resize(len - 1); + len = actual.size(); + if (t->HasAttribute("SmallBufferTruncates")) { + if (!EVP_PKEY_derive(pctx, actual.data(), &len)) { + return false; + } + actual.resize(len); + EXPECT_EQ(Bytes(output.data(), len), Bytes(actual)); + } else { + EXPECT_FALSE(EVP_PKEY_derive(pctx, actual.data(), &len)); + ERR_clear_error(); + } + } return true; } @@ -243,6 +369,14 @@ static bool TestEVP(FileTest *t, KeyMap *key_map) { return ImportKey(t, key_map, EVP_parse_public_key, EVP_marshal_public_key); } + // Load the key. + const std::string &key_name = t->GetParameter(); + if (key_map->count(key_name) == 0) { + ADD_FAILURE() << "Could not find key " << key_name; + return false; + } + EVP_PKEY *key = (*key_map)[key_name].get(); + int (*key_op_init)(EVP_PKEY_CTX *ctx) = nullptr; int (*key_op)(EVP_PKEY_CTX *ctx, uint8_t *out, size_t *out_len, const uint8_t *in, size_t in_len) = nullptr; @@ -266,19 +400,13 @@ static bool TestEVP(FileTest *t, KeyMap *key_map) { } else if (t->GetType() == "Encrypt") { key_op_init = EVP_PKEY_encrypt_init; key_op = EVP_PKEY_encrypt; + } else if (t->GetType() == "Derive") { + return TestDerive(t, key_map, key); } else { ADD_FAILURE() << "Unknown test " << t->GetType(); return false; } - // Load the key. - const std::string &key_name = t->GetParameter(); - if (key_map->count(key_name) == 0) { - ADD_FAILURE() << "Could not find key " << key_name; - return false; - } - EVP_PKEY *key = (*key_map)[key_name].get(); - const EVP_MD *digest = nullptr; if (t->HasAttribute("Digest")) { digest = GetDigest(t, t->GetAttributeOrDie("Digest")); @@ -300,7 +428,7 @@ static bool TestEVP(FileTest *t, KeyMap *key_map) { bssl::ScopedEVP_MD_CTX ctx, copy; EVP_PKEY_CTX *pctx; if (!md_op_init(ctx.get(), &pctx, digest, nullptr, key) || - !SetupContext(t, pctx) || + !SetupContext(t, key_map, pctx) || !EVP_MD_CTX_copy_ex(copy.get(), ctx.get())) { return false; } @@ -347,7 +475,7 @@ static bool TestEVP(FileTest *t, KeyMap *key_map) { !key_op_init(ctx.get()) || (digest != nullptr && !EVP_PKEY_CTX_set_signature_md(ctx.get(), digest)) || - !SetupContext(t, ctx.get())) { + !SetupContext(t, key_map, ctx.get())) { return false; } @@ -381,7 +509,7 @@ static bool TestEVP(FileTest *t, KeyMap *key_map) { !EVP_PKEY_decrypt_init(decrypt_ctx.get()) || (digest != nullptr && !EVP_PKEY_CTX_set_signature_md(decrypt_ctx.get(), digest)) || - !SetupContext(t, decrypt_ctx.get()) || + !SetupContext(t, key_map, decrypt_ctx.get()) || !EVP_PKEY_decrypt(decrypt_ctx.get(), nullptr, &plaintext_len, actual.data(), actual.size())) { return false; @@ -401,7 +529,7 @@ static bool TestEVP(FileTest *t, KeyMap *key_map) { !EVP_PKEY_verify_init(verify_ctx.get()) || (digest != nullptr && !EVP_PKEY_CTX_set_signature_md(verify_ctx.get(), digest)) || - !SetupContext(t, verify_ctx.get())) { + !SetupContext(t, key_map, verify_ctx.get())) { return false; } if (t->HasAttribute("VerifyPSSSaltLength")) { |