Refactor HPKE API to include explicit length parameters.

Bug: 275
Change-Id: I724e9315b860e230e8fed92de34d89a875ef043c
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/46184
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
grpc-202302
Dan McArdle 4 years ago committed by CQ bot account: commit-bot@chromium.org
parent c9d3265a92
commit d9ee55a89f
  1. 1
      crypto/err/evp.errordata
  2. 118
      crypto/hpke/hpke.c
  3. 220
      crypto/hpke/hpke_test.cc
  4. 78
      crypto/hpke/internal.h
  5. 1
      include/openssl/evp_errors.h

@ -9,6 +9,7 @@ EVP,106,EXPECTING_AN_EC_KEY_KEY
EVP,107,EXPECTING_AN_RSA_KEY
EVP,108,EXPECTING_A_DSA_KEY
EVP,109,ILLEGAL_OR_UNSUPPORTED_PADDING_MODE
EVP,137,INVALID_BUFFER_SIZE
EVP,110,INVALID_DIGEST_LENGTH
EVP,111,INVALID_DIGEST_TYPE
EVP,112,INVALID_KEYBITS

@ -17,6 +17,7 @@
#include <openssl/aead.h>
#include <openssl/bytestring.h>
#include <openssl/curve25519.h>
#include <openssl/digest.h>
#include <openssl/err.h>
#include <openssl/evp_errors.h>
@ -316,27 +317,44 @@ void EVP_HPKE_CTX_cleanup(EVP_HPKE_CTX *ctx) {
EVP_AEAD_CTX_cleanup(&ctx->aead_ctx);
}
int EVP_HPKE_CTX_setup_base_s_x25519(
EVP_HPKE_CTX *hpke, uint8_t out_enc[X25519_PUBLIC_VALUE_LEN],
uint16_t kdf_id, uint16_t aead_id,
const uint8_t peer_public_value[X25519_PUBLIC_VALUE_LEN],
int EVP_HPKE_CTX_setup_base_s_x25519(EVP_HPKE_CTX *hpke, uint8_t *out_enc,
size_t out_enc_len, uint16_t kdf_id,
uint16_t aead_id,
const uint8_t *peer_public_value,
size_t peer_public_value_len,
const uint8_t *info, size_t info_len) {
if (out_enc_len != X25519_PUBLIC_VALUE_LEN) {
OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_BUFFER_SIZE);
return 0;
}
// The GenerateKeyPair() step technically belongs in the KEM's Encap()
// function, but we've moved it up a layer to make it easier for tests to
// inject an ephemeral keypair.
uint8_t ephemeral_private[X25519_PRIVATE_KEY_LEN];
X25519_keypair(out_enc, ephemeral_private);
return EVP_HPKE_CTX_setup_base_s_x25519_for_test(
hpke, kdf_id, aead_id, peer_public_value, info, info_len,
ephemeral_private, out_enc);
hpke, kdf_id, aead_id, peer_public_value, peer_public_value_len, info,
info_len, ephemeral_private, sizeof(ephemeral_private), out_enc,
out_enc_len);
}
int EVP_HPKE_CTX_setup_base_s_x25519_for_test(
EVP_HPKE_CTX *hpke, uint16_t kdf_id, uint16_t aead_id,
const uint8_t peer_public_value[X25519_PUBLIC_VALUE_LEN],
const uint8_t *info, size_t info_len,
const uint8_t ephemeral_private[X25519_PRIVATE_KEY_LEN],
const uint8_t ephemeral_public[X25519_PUBLIC_VALUE_LEN]) {
const uint8_t *peer_public_value, size_t peer_public_value_len,
const uint8_t *info, size_t info_len, const uint8_t *ephemeral_private,
size_t ephemeral_private_len, const uint8_t *ephemeral_public,
size_t ephemeral_public_len) {
if (peer_public_value_len != X25519_PUBLIC_VALUE_LEN) {
OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_PEER_KEY);
return 0;
}
if (ephemeral_private_len != X25519_PRIVATE_KEY_LEN ||
ephemeral_public_len != X25519_PUBLIC_VALUE_LEN) {
OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
return 0;
}
hpke->is_sender = 1;
hpke->kdf_id = kdf_id;
hpke->aead_id = aead_id;
@ -355,12 +373,23 @@ int EVP_HPKE_CTX_setup_base_s_x25519_for_test(
return 1;
}
int EVP_HPKE_CTX_setup_base_r_x25519(
EVP_HPKE_CTX *hpke, uint16_t kdf_id, uint16_t aead_id,
const uint8_t enc[X25519_PUBLIC_VALUE_LEN],
const uint8_t public_key[X25519_PUBLIC_VALUE_LEN],
const uint8_t private_key[X25519_PRIVATE_KEY_LEN], const uint8_t *info,
size_t info_len) {
int EVP_HPKE_CTX_setup_base_r_x25519(EVP_HPKE_CTX *hpke, uint16_t kdf_id,
uint16_t aead_id, const uint8_t *enc,
size_t enc_len, const uint8_t *public_key,
size_t public_key_len,
const uint8_t *private_key,
size_t private_key_len,
const uint8_t *info, size_t info_len) {
if (enc_len != X25519_PUBLIC_VALUE_LEN) {
OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_PEER_KEY);
return 0;
}
if (public_key_len != X25519_PUBLIC_VALUE_LEN ||
private_key_len != X25519_PRIVATE_KEY_LEN) {
OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
return 0;
}
hpke->is_sender = 0;
hpke->kdf_id = kdf_id;
hpke->aead_id = aead_id;
@ -378,29 +407,47 @@ int EVP_HPKE_CTX_setup_base_r_x25519(
return 1;
}
int EVP_HPKE_CTX_setup_psk_s_x25519(
EVP_HPKE_CTX *hpke, uint8_t out_enc[X25519_PUBLIC_VALUE_LEN],
uint16_t kdf_id, uint16_t aead_id,
const uint8_t peer_public_value[X25519_PUBLIC_VALUE_LEN],
const uint8_t *info, size_t info_len, const uint8_t *psk, size_t psk_len,
int EVP_HPKE_CTX_setup_psk_s_x25519(EVP_HPKE_CTX *hpke, uint8_t *out_enc,
size_t out_enc_len, uint16_t kdf_id,
uint16_t aead_id,
const uint8_t *peer_public_value,
size_t peer_public_value_len,
const uint8_t *info, size_t info_len,
const uint8_t *psk, size_t psk_len,
const uint8_t *psk_id, size_t psk_id_len) {
if (out_enc_len != X25519_PUBLIC_VALUE_LEN) {
OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_BUFFER_SIZE);
return 0;
}
// The GenerateKeyPair() step technically belongs in the KEM's Encap()
// function, but we've moved it up a layer to make it easier for tests to
// inject an ephemeral keypair.
uint8_t ephemeral_private[X25519_PRIVATE_KEY_LEN];
X25519_keypair(out_enc, ephemeral_private);
return EVP_HPKE_CTX_setup_psk_s_x25519_for_test(
hpke, kdf_id, aead_id, peer_public_value, info, info_len, psk, psk_len,
psk_id, psk_id_len, ephemeral_private, out_enc);
hpke, kdf_id, aead_id, peer_public_value, peer_public_value_len, info,
info_len, psk, psk_len, psk_id, psk_id_len, ephemeral_private,
sizeof(ephemeral_private), out_enc, out_enc_len);
}
int EVP_HPKE_CTX_setup_psk_s_x25519_for_test(
EVP_HPKE_CTX *hpke, uint16_t kdf_id, uint16_t aead_id,
const uint8_t peer_public_value[X25519_PUBLIC_VALUE_LEN],
const uint8_t *peer_public_value, size_t peer_public_value_len,
const uint8_t *info, size_t info_len, const uint8_t *psk, size_t psk_len,
const uint8_t *psk_id, size_t psk_id_len,
const uint8_t ephemeral_private[X25519_PRIVATE_KEY_LEN],
const uint8_t ephemeral_public[X25519_PUBLIC_VALUE_LEN]) {
const uint8_t *psk_id, size_t psk_id_len, const uint8_t *ephemeral_private,
size_t ephemeral_private_len, const uint8_t *ephemeral_public,
size_t ephemeral_public_len) {
if (peer_public_value_len != X25519_PUBLIC_VALUE_LEN) {
OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_PEER_KEY);
return 0;
}
if (ephemeral_private_len != X25519_PRIVATE_KEY_LEN ||
ephemeral_public_len != X25519_PUBLIC_VALUE_LEN) {
OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
return 0;
}
hpke->is_sender = 1;
hpke->kdf_id = kdf_id;
hpke->aead_id = aead_id;
@ -420,12 +467,21 @@ int EVP_HPKE_CTX_setup_psk_s_x25519_for_test(
}
int EVP_HPKE_CTX_setup_psk_r_x25519(
EVP_HPKE_CTX *hpke, uint16_t kdf_id, uint16_t aead_id,
const uint8_t enc[X25519_PUBLIC_VALUE_LEN],
const uint8_t public_key[X25519_PUBLIC_VALUE_LEN],
const uint8_t private_key[X25519_PRIVATE_KEY_LEN], const uint8_t *info,
EVP_HPKE_CTX *hpke, uint16_t kdf_id, uint16_t aead_id, const uint8_t *enc,
size_t enc_len, const uint8_t *public_key, size_t public_key_len,
const uint8_t *private_key, size_t private_key_len, const uint8_t *info,
size_t info_len, const uint8_t *psk, size_t psk_len, const uint8_t *psk_id,
size_t psk_id_len) {
if (enc_len != X25519_PUBLIC_VALUE_LEN) {
OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_PEER_KEY);
return 0;
}
if (public_key_len != X25519_PUBLIC_VALUE_LEN ||
private_key_len != X25519_PRIVATE_KEY_LEN) {
OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
return 0;
}
hpke->is_sender = 0;
hpke->kdf_id = kdf_id;
hpke->aead_id = aead_id;

@ -62,13 +62,15 @@ class HPKETestVector {
// Set up the sender.
ASSERT_TRUE(EVP_HPKE_CTX_setup_base_s_x25519_for_test(
sender_ctx.get(), kdf_id_, aead_id_, public_key_r_.data(),
info_.data(), info_.size(), secret_key_e_.data(),
public_key_e_.data()));
public_key_r_.size(), info_.data(), info_.size(),
secret_key_e_.data(), secret_key_e_.size(), public_key_e_.data(),
public_key_e_.size()));
// Set up the receiver.
ASSERT_TRUE(EVP_HPKE_CTX_setup_base_r_x25519(
receiver_ctx.get(), kdf_id_, aead_id_, public_key_e_.data(),
public_key_r_.data(), secret_key_r_.data(), info_.data(),
public_key_e_.size(), public_key_r_.data(), public_key_r_.size(),
secret_key_r_.data(), secret_key_r_.size(), info_.data(),
info_.size()));
break;
@ -80,14 +82,15 @@ class HPKETestVector {
// Set up the sender.
ASSERT_TRUE(EVP_HPKE_CTX_setup_psk_s_x25519_for_test(
sender_ctx.get(), kdf_id_, aead_id_, public_key_r_.data(),
info_.data(), info_.size(), psk_.data(), psk_.size(),
psk_id_.data(), psk_id_.size(), secret_key_e_.data(),
public_key_e_.data()));
public_key_r_.size(), info_.data(), info_.size(), psk_.data(),
psk_.size(), psk_id_.data(), psk_id_.size(), secret_key_e_.data(),
secret_key_e_.size(), public_key_e_.data(), public_key_e_.size()));
// Set up the receiver.
ASSERT_TRUE(EVP_HPKE_CTX_setup_psk_r_x25519(
receiver_ctx.get(), kdf_id_, aead_id_, public_key_e_.data(),
public_key_r_.data(), secret_key_r_.data(), info_.data(),
public_key_e_.size(), public_key_r_.data(), public_key_r_.size(),
secret_key_r_.data(), secret_key_r_.size(), info_.data(),
info_.size(), psk_.data(), psk_.size(), psk_id_.data(),
psk_id_.size()));
break;
@ -282,14 +285,15 @@ TEST(HPKETest, RoundTrip) {
ScopedEVP_HPKE_CTX sender_ctx;
uint8_t enc[X25519_PUBLIC_VALUE_LEN];
ASSERT_TRUE(EVP_HPKE_CTX_setup_base_s_x25519(
sender_ctx.get(), enc, kdf_id, aead_id, public_key_r, info.data(),
info.size()));
sender_ctx.get(), enc, sizeof(enc), kdf_id, aead_id, public_key_r,
sizeof(public_key_r), info.data(), info.size()));
// Set up the receiver.
ScopedEVP_HPKE_CTX receiver_ctx;
ASSERT_TRUE(EVP_HPKE_CTX_setup_base_r_x25519(
receiver_ctx.get(), kdf_id, aead_id, enc, public_key_r,
secret_key_r, info.data(), info.size()));
receiver_ctx.get(), kdf_id, aead_id, enc, sizeof(enc),
public_key_r, sizeof(public_key_r), secret_key_r,
sizeof(secret_key_r), info.data(), info.size()));
const char kCleartextPayload[] = "foobar";
@ -347,14 +351,15 @@ TEST(HPKETest, X25519EncapSmallOrderPoint) {
ScopedEVP_HPKE_CTX sender_ctx;
uint8_t enc[X25519_PUBLIC_VALUE_LEN];
ASSERT_FALSE(EVP_HPKE_CTX_setup_base_s_x25519(
sender_ctx.get(), enc, kdf_id, aead_id, kSmallOrderPoint, nullptr,
0));
sender_ctx.get(), enc, sizeof(enc), kdf_id, aead_id, kSmallOrderPoint,
sizeof(kSmallOrderPoint), nullptr, 0));
// Set up the receiver, passing in kSmallOrderPoint as |enc|.
ScopedEVP_HPKE_CTX receiver_ctx;
ASSERT_FALSE(EVP_HPKE_CTX_setup_base_r_x25519(
receiver_ctx.get(), kdf_id, aead_id, kSmallOrderPoint, public_key_r,
secret_key_r, nullptr, 0));
receiver_ctx.get(), kdf_id, aead_id, kSmallOrderPoint,
sizeof(kSmallOrderPoint), public_key_r, sizeof(public_key_r),
secret_key_r, sizeof(secret_key_r), nullptr, 0));
}
}
}
@ -373,7 +378,8 @@ TEST(HPKETest, ReceiverInvalidSeal) {
ScopedEVP_HPKE_CTX receiver_ctx;
ASSERT_TRUE(EVP_HPKE_CTX_setup_base_r_x25519(
receiver_ctx.get(), EVP_HPKE_HKDF_SHA256, EVP_HPKE_AEAD_AES_GCM_128,
kMockEnc, public_key_r, secret_key_r, nullptr, 0));
kMockEnc, sizeof(kMockEnc), public_key_r, sizeof(public_key_r),
secret_key_r, sizeof(secret_key_r), nullptr, 0));
// Call Seal() on the receiver.
size_t ciphertext_len;
@ -398,8 +404,9 @@ TEST(HPKETest, SenderInvalidOpen) {
ScopedEVP_HPKE_CTX sender_ctx;
uint8_t enc[X25519_PUBLIC_VALUE_LEN];
ASSERT_TRUE(EVP_HPKE_CTX_setup_base_s_x25519(
sender_ctx.get(), enc, EVP_HPKE_HKDF_SHA256, EVP_HPKE_AEAD_AES_GCM_128,
public_key_r, nullptr, 0));
sender_ctx.get(), enc, sizeof(enc), EVP_HPKE_HKDF_SHA256,
EVP_HPKE_AEAD_AES_GCM_128, public_key_r, sizeof(public_key_r), nullptr,
0));
// Call Open() on the sender.
uint8_t cleartext[128];
@ -432,10 +439,11 @@ TEST(HPKETest, EmptyPSK) {
ScopedEVP_HPKE_CTX sender_ctx;
uint8_t enc[X25519_PUBLIC_VALUE_LEN];
ASSERT_EQ(EVP_HPKE_CTX_setup_psk_s_x25519(
sender_ctx.get(), enc, EVP_HPKE_HKDF_SHA256,
EVP_HPKE_AEAD_AES_GCM_128, public_key_r, nullptr, 0,
psk.data(), psk.size(), psk_id.data(), psk_id.size()),
ASSERT_EQ(
EVP_HPKE_CTX_setup_psk_s_x25519(
sender_ctx.get(), enc, sizeof(enc), EVP_HPKE_HKDF_SHA256,
EVP_HPKE_AEAD_AES_GCM_128, public_key_r, sizeof(public_key_r),
nullptr, 0, psk.data(), psk.size(), psk_id.data(), psk_id.size()),
kExpectSuccess);
if (!kExpectSuccess) {
@ -446,11 +454,12 @@ TEST(HPKETest, EmptyPSK) {
ERR_clear_error();
ScopedEVP_HPKE_CTX receiver_ctx;
ASSERT_EQ(
EVP_HPKE_CTX_setup_psk_r_x25519(
ASSERT_EQ(EVP_HPKE_CTX_setup_psk_r_x25519(
receiver_ctx.get(), EVP_HPKE_HKDF_SHA256,
EVP_HPKE_AEAD_AES_GCM_128, kMockEnc, public_key_r, secret_key_r,
nullptr, 0, psk.data(), psk.size(), psk_id.data(), psk_id.size()),
EVP_HPKE_AEAD_AES_GCM_128, kMockEnc, sizeof(kMockEnc),
public_key_r, sizeof(public_key_r), secret_key_r,
sizeof(secret_key_r), nullptr, 0, psk.data(), psk.size(),
psk_id.data(), psk_id.size()),
kExpectSuccess);
if (!kExpectSuccess) {
@ -463,6 +472,165 @@ TEST(HPKETest, EmptyPSK) {
}
}
TEST(HPKETest, SetupSenderWrongLengthEnc) {
uint8_t secret_key_r[X25519_PRIVATE_KEY_LEN];
uint8_t public_key_r[X25519_PUBLIC_VALUE_LEN];
X25519_keypair(public_key_r, secret_key_r);
ScopedEVP_HPKE_CTX sender_ctx;
uint8_t bogus_enc[X25519_PUBLIC_VALUE_LEN + 5];
{
ASSERT_FALSE(EVP_HPKE_CTX_setup_base_s_x25519(
sender_ctx.get(), bogus_enc, sizeof(bogus_enc), EVP_HPKE_HKDF_SHA256,
EVP_HPKE_AEAD_AES_GCM_128, public_key_r, sizeof(public_key_r), nullptr,
0));
uint32_t err = ERR_get_error();
EXPECT_EQ(ERR_LIB_EVP, ERR_GET_LIB(err));
EXPECT_EQ(EVP_R_INVALID_BUFFER_SIZE, ERR_GET_REASON(err));
ERR_clear_error();
}
{
const uint8_t psk[] = {1, 2, 3, 4};
const uint8_t psk_id[] = {1, 2, 3, 4};
ASSERT_FALSE(EVP_HPKE_CTX_setup_psk_s_x25519(
sender_ctx.get(), bogus_enc, sizeof(bogus_enc), EVP_HPKE_HKDF_SHA256,
EVP_HPKE_AEAD_AES_GCM_128, public_key_r, sizeof(public_key_r), nullptr,
0, psk, sizeof(psk), psk_id, sizeof(psk_id)));
uint32_t err = ERR_get_error();
EXPECT_EQ(ERR_LIB_EVP, ERR_GET_LIB(err));
EXPECT_EQ(EVP_R_INVALID_BUFFER_SIZE, ERR_GET_REASON(err));
ERR_clear_error();
}
}
TEST(HPKETest, SetupReceiverWrongLengthEnc) {
uint8_t private_key[X25519_PRIVATE_KEY_LEN];
uint8_t public_key[X25519_PUBLIC_VALUE_LEN];
X25519_keypair(public_key, private_key);
const uint8_t bogus_enc[X25519_PUBLIC_VALUE_LEN + 5] = {0xff};
ScopedEVP_HPKE_CTX receiver_ctx;
{
ASSERT_FALSE(EVP_HPKE_CTX_setup_base_r_x25519(
receiver_ctx.get(), EVP_HPKE_HKDF_SHA256, EVP_HPKE_AEAD_AES_GCM_128,
bogus_enc, sizeof(bogus_enc), public_key, sizeof(public_key),
private_key, sizeof(private_key), nullptr, 0));
uint32_t err = ERR_get_error();
EXPECT_EQ(ERR_LIB_EVP, ERR_GET_LIB(err));
EXPECT_EQ(EVP_R_INVALID_PEER_KEY, ERR_GET_REASON(err));
ERR_clear_error();
}
{
const uint8_t psk[] = {1, 2, 3, 4};
const uint8_t psk_id[] = {1, 2, 3, 4};
ASSERT_FALSE(EVP_HPKE_CTX_setup_psk_r_x25519(
receiver_ctx.get(), EVP_HPKE_HKDF_SHA256, EVP_HPKE_AEAD_AES_GCM_128,
bogus_enc, sizeof(bogus_enc), public_key, sizeof(public_key),
private_key, sizeof(private_key), nullptr, 0, psk, sizeof(psk), psk_id,
sizeof(psk_id)));
uint32_t err = ERR_get_error();
EXPECT_EQ(ERR_LIB_EVP, ERR_GET_LIB(err));
EXPECT_EQ(EVP_R_INVALID_PEER_KEY, ERR_GET_REASON(err));
ERR_clear_error();
}
}
TEST(HPKETest, SetupSenderWrongLengthPeerPublicValue) {
const uint8_t bogus_public_key_r[X25519_PRIVATE_KEY_LEN + 5] = {0xff};
ScopedEVP_HPKE_CTX sender_ctx;
uint8_t enc[X25519_PUBLIC_VALUE_LEN];
{
ASSERT_FALSE(EVP_HPKE_CTX_setup_base_s_x25519(
sender_ctx.get(), enc, sizeof(enc), EVP_HPKE_HKDF_SHA256,
EVP_HPKE_AEAD_AES_GCM_128, bogus_public_key_r,
sizeof(bogus_public_key_r), nullptr, 0));
uint32_t err = ERR_get_error();
EXPECT_EQ(ERR_LIB_EVP, ERR_GET_LIB(err));
EXPECT_EQ(EVP_R_INVALID_PEER_KEY, ERR_GET_REASON(err));
ERR_clear_error();
}
{
const uint8_t psk[] = {1, 2, 3, 4};
const uint8_t psk_id[] = {1, 2, 3, 4};
ASSERT_FALSE(EVP_HPKE_CTX_setup_psk_s_x25519(
sender_ctx.get(), enc, sizeof(enc), EVP_HPKE_HKDF_SHA256,
EVP_HPKE_AEAD_AES_GCM_128, bogus_public_key_r,
sizeof(bogus_public_key_r), nullptr, 0, psk, sizeof(psk), psk_id,
sizeof(psk_id)));
uint32_t err = ERR_get_error();
EXPECT_EQ(ERR_LIB_EVP, ERR_GET_LIB(err));
EXPECT_EQ(EVP_R_INVALID_PEER_KEY, ERR_GET_REASON(err));
ERR_clear_error();
}
}
TEST(HPKETest, SetupReceiverWrongLengthKeys) {
uint8_t private_key[X25519_PRIVATE_KEY_LEN];
uint8_t public_key[X25519_PUBLIC_VALUE_LEN];
X25519_keypair(public_key, private_key);
uint8_t unused[X25519_PRIVATE_KEY_LEN];
uint8_t enc[X25519_PUBLIC_VALUE_LEN];
X25519_keypair(enc, unused);
const uint8_t bogus_public_key[X25519_PUBLIC_VALUE_LEN + 5] = {0xff};
const uint8_t bogus_private_key[X25519_PUBLIC_VALUE_LEN + 5] = {0xff};
ScopedEVP_HPKE_CTX receiver_ctx;
{
// Test base mode with |bogus_public_key|.
ASSERT_FALSE(EVP_HPKE_CTX_setup_base_r_x25519(
receiver_ctx.get(), EVP_HPKE_HKDF_SHA256, EVP_HPKE_AEAD_AES_GCM_128,
enc, sizeof(enc), bogus_public_key, sizeof(bogus_public_key),
private_key, sizeof(private_key), nullptr, 0));
uint32_t err = ERR_get_error();
EXPECT_EQ(ERR_LIB_EVP, ERR_GET_LIB(err));
EXPECT_EQ(EVP_R_DECODE_ERROR, ERR_GET_REASON(err));
ERR_clear_error();
}
{
// Test base mode with |bogus_private_key|.
ASSERT_FALSE(EVP_HPKE_CTX_setup_base_r_x25519(
receiver_ctx.get(), EVP_HPKE_HKDF_SHA256, EVP_HPKE_AEAD_AES_GCM_128,
enc, sizeof(enc), public_key, sizeof(public_key), bogus_private_key,
sizeof(bogus_private_key), nullptr, 0));
uint32_t err = ERR_get_error();
EXPECT_EQ(ERR_LIB_EVP, ERR_GET_LIB(err));
EXPECT_EQ(EVP_R_DECODE_ERROR, ERR_GET_REASON(err));
ERR_clear_error();
}
{
// Test PSK mode with |bogus_public_key|.
const uint8_t psk[] = {1, 2, 3, 4};
const uint8_t psk_id[] = {1, 2, 3, 4};
ASSERT_FALSE(EVP_HPKE_CTX_setup_psk_r_x25519(
receiver_ctx.get(), EVP_HPKE_HKDF_SHA256, EVP_HPKE_AEAD_AES_GCM_128,
enc, sizeof(enc), bogus_public_key, sizeof(bogus_public_key),
private_key, sizeof(private_key), nullptr, 0, psk, sizeof(psk), psk_id,
sizeof(psk_id)));
uint32_t err = ERR_get_error();
EXPECT_EQ(ERR_LIB_EVP, ERR_GET_LIB(err));
EXPECT_EQ(EVP_R_DECODE_ERROR, ERR_GET_REASON(err));
ERR_clear_error();
}
{
// Test PSK mode with |bogus_private_key|.
const uint8_t psk[] = {1, 2, 3, 4};
const uint8_t psk_id[] = {1, 2, 3, 4};
ASSERT_FALSE(EVP_HPKE_CTX_setup_psk_r_x25519(
receiver_ctx.get(), EVP_HPKE_HKDF_SHA256, EVP_HPKE_AEAD_AES_GCM_128,
enc, sizeof(enc), public_key, sizeof(public_key), bogus_private_key,
sizeof(bogus_private_key), nullptr, 0, psk, sizeof(psk), psk_id,
sizeof(psk_id)));
uint32_t err = ERR_get_error();
EXPECT_EQ(ERR_LIB_EVP, ERR_GET_LIB(err));
EXPECT_EQ(EVP_R_DECODE_ERROR, ERR_GET_REASON(err));
ERR_clear_error();
}
}
TEST(HPKETest, InternalParseIntSafe) {
uint8_t u8 = 0xff;
ASSERT_FALSE(ParseIntSafe(&u8, "-1"));

@ -86,32 +86,35 @@ OPENSSL_EXPORT void EVP_HPKE_CTX_cleanup(EVP_HPKE_CTX *ctx);
// recipient's public key). It returns one on success, and zero otherwise. Note
// that this function will fail if |peer_public_value| is invalid.
//
// This function writes the encapsulated shared secret to |out_enc|.
// This function writes the encapsulated shared secret, a Diffie-Hellman public
// key, to |out_enc|. It will fail if the buffer's size in |out_enc_len| is not
// exactly |X25519_PUBLIC_VALUE_LEN|.
OPENSSL_EXPORT int EVP_HPKE_CTX_setup_base_s_x25519(
EVP_HPKE_CTX *hpke, uint8_t out_enc[X25519_PUBLIC_VALUE_LEN],
uint16_t kdf_id, uint16_t aead_id,
const uint8_t peer_public_value[X25519_PUBLIC_VALUE_LEN],
const uint8_t *info, size_t info_len);
EVP_HPKE_CTX *hpke, uint8_t *out_enc, size_t out_enc_len, uint16_t kdf_id,
uint16_t aead_id, const uint8_t *peer_public_value,
size_t peer_public_value_len, const uint8_t *info, size_t info_len);
// EVP_HPKE_CTX_setup_base_s_x25519_for_test behaves like
// |EVP_HPKE_CTX_setup_base_s_x25519|, but takes a pre-generated ephemeral
// sender key.
// sender key. The caller ensures that |ephemeral_public| and
// |ephemeral_private| are a valid keypair.
OPENSSL_EXPORT int EVP_HPKE_CTX_setup_base_s_x25519_for_test(
EVP_HPKE_CTX *hpke, uint16_t kdf_id, uint16_t aead_id,
const uint8_t peer_public_value[X25519_PUBLIC_VALUE_LEN],
const uint8_t *info, size_t info_len,
const uint8_t ephemeral_private[X25519_PRIVATE_KEY_LEN],
const uint8_t ephemeral_public[X25519_PUBLIC_VALUE_LEN]);
const uint8_t *peer_public_value, size_t peer_public_value_len,
const uint8_t *info, size_t info_len, const uint8_t *ephemeral_private,
size_t ephemeral_private_len, const uint8_t *ephemeral_public,
size_t ephemeral_public_len);
// EVP_HPKE_CTX_setup_base_r_x25519 sets up |hpke| as a recipient context that
// can decrypt messages. |private_key| is the recipient's private key, and |enc|
// is the encapsulated shared secret from the sender. Note that this function
// will fail if |enc| is invalid.
// can decrypt messages. It returns one on success, and zero otherwise.
//
// The recipient's keypair is composed of |public_key| and |private_key|, and
// |enc| is the encapsulated shared secret from the sender. If |enc| is invalid,
// this function will fail.
OPENSSL_EXPORT int EVP_HPKE_CTX_setup_base_r_x25519(
EVP_HPKE_CTX *hpke, uint16_t kdf_id, uint16_t aead_id,
const uint8_t enc[X25519_PUBLIC_VALUE_LEN],
const uint8_t public_key[X25519_PUBLIC_VALUE_LEN],
const uint8_t private_key[X25519_PRIVATE_KEY_LEN], const uint8_t *info,
EVP_HPKE_CTX *hpke, uint16_t kdf_id, uint16_t aead_id, const uint8_t *enc,
size_t enc_len, const uint8_t *public_key, size_t public_key_len,
const uint8_t *private_key, size_t private_key_len, const uint8_t *info,
size_t info_len);
// EVP_HPKE_CTX_setup_psk_s_x25519 sets up |hpke| as a sender context that can
@ -124,39 +127,44 @@ OPENSSL_EXPORT int EVP_HPKE_CTX_setup_base_r_x25519(
// must be nonempty (|psk_len| and |psk_id_len| must be non-zero), or this
// function will fail.
//
// This function writes the encapsulated shared secret to |out_enc|.
// This function writes the encapsulated shared secret, a Diffie-Hellman public
// key, to |out_enc|. It will fail if the buffer's size in |out_enc_len| is not
// exactly |X25519_PUBLIC_VALUE_LEN|.
OPENSSL_EXPORT int EVP_HPKE_CTX_setup_psk_s_x25519(
EVP_HPKE_CTX *hpke, uint8_t out_enc[X25519_PUBLIC_VALUE_LEN],
uint16_t kdf_id, uint16_t aead_id,
const uint8_t peer_public_value[X25519_PUBLIC_VALUE_LEN],
const uint8_t *info, size_t info_len, const uint8_t *psk, size_t psk_len,
const uint8_t *psk_id, size_t psk_id_len);
EVP_HPKE_CTX *hpke, uint8_t *out_enc, size_t out_enc_len, uint16_t kdf_id,
uint16_t aead_id, const uint8_t *peer_public_value,
size_t peer_public_value_len, const uint8_t *info, size_t info_len,
const uint8_t *psk, size_t psk_len, const uint8_t *psk_id,
size_t psk_id_len);
// EVP_HPKE_CTX_setup_psk_s_x25519_for_test behaves like
// |EVP_HPKE_CTX_setup_psk_s_x25519|, but takes a pre-generated ephemeral sender
// key.
// key. The caller ensures that |ephemeral_public| and |ephemeral_private| are a
// valid keypair.
OPENSSL_EXPORT int EVP_HPKE_CTX_setup_psk_s_x25519_for_test(
EVP_HPKE_CTX *hpke, uint16_t kdf_id, uint16_t aead_id,
const uint8_t peer_public_value[X25519_PUBLIC_VALUE_LEN],
const uint8_t *peer_public_value, size_t peer_public_value_len,
const uint8_t *info, size_t info_len, const uint8_t *psk, size_t psk_len,
const uint8_t *psk_id, size_t psk_id_len,
const uint8_t ephemeral_private[X25519_PRIVATE_KEY_LEN],
const uint8_t ephemeral_public[X25519_PUBLIC_VALUE_LEN]);
const uint8_t *psk_id, size_t psk_id_len, const uint8_t *ephemeral_private,
size_t ephemeral_private_len, const uint8_t *ephemeral_public,
size_t ephemeral_public_len);
// EVP_HPKE_CTX_setup_psk_r_x25519 sets up |hpke| as a recipient context that
// can decrypt messages. Future open (decrypt) operations will fail if the
// sender does not possess the PSK indicated by |psk| and |psk_id|.
// |private_key| is the recipient's private key, and |enc| is the encapsulated
// shared secret from the sender. If |enc| is invalid, this function will fail.
// sender does not possess the PSK indicated by |psk| and |psk_id|. It returns
// one on success, and zero otherwise.
//
// The recipient's keypair is composed of |public_key| and |private_key|, and
// |enc| is the encapsulated shared secret from the sender. If |enc| is invalid,
// this function will fail.
//
// The PSK and its ID must be provided in |psk| and |psk_id|, respectively. Both
// must be nonempty (|psk_len| and |psk_id_len| must be non-zero), or this
// function will fail.
OPENSSL_EXPORT int EVP_HPKE_CTX_setup_psk_r_x25519(
EVP_HPKE_CTX *hpke, uint16_t kdf_id, uint16_t aead_id,
const uint8_t enc[X25519_PUBLIC_VALUE_LEN],
const uint8_t public_key[X25519_PUBLIC_VALUE_LEN],
const uint8_t private_key[X25519_PRIVATE_KEY_LEN], const uint8_t *info,
EVP_HPKE_CTX *hpke, uint16_t kdf_id, uint16_t aead_id, const uint8_t *enc,
size_t enc_len, const uint8_t *public_key, size_t public_key_len,
const uint8_t *private_key, size_t private_key_len, const uint8_t *info,
size_t info_len, const uint8_t *psk, size_t psk_len, const uint8_t *psk_id,
size_t psk_id_len);

@ -94,5 +94,6 @@
#define EVP_R_INVALID_PEER_KEY 134
#define EVP_R_NOT_XOF_OR_INVALID_LENGTH 135
#define EVP_R_EMPTY_PSK 136
#define EVP_R_INVALID_BUFFER_SIZE 137
#endif // OPENSSL_HEADER_EVP_ERRORS_H

Loading…
Cancel
Save