From bc2480510960a77bea24edc64fcb089aca103940 Mon Sep 17 00:00:00 2001 From: Daniel McArdle Date: Tue, 25 Aug 2020 17:32:22 -0400 Subject: [PATCH] Implement PSK variants of HPKE setup functions. Change-Id: Ic190ac1efbb079e42bb22b39083ccb96e0a61e57 Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/42664 Reviewed-by: David Benjamin Commit-Queue: David Benjamin --- crypto/err/evp.errordata | 1 + crypto/evp/evp.c | 4 + crypto/hpke/hpke.c | 109 ++++++- crypto/hpke/hpke_test.cc | 148 +++++++-- crypto/hpke/hpke_test_vectors.txt | 432 ++++++++++++++++++++++++++ crypto/hpke/internal.h | 57 +++- crypto/hpke/translate_test_vectors.py | 11 +- include/openssl/evp.h | 1 + 8 files changed, 725 insertions(+), 38 deletions(-) diff --git a/crypto/err/evp.errordata b/crypto/err/evp.errordata index 390dec0634..d0f09d4e1e 100644 --- a/crypto/err/evp.errordata +++ b/crypto/err/evp.errordata @@ -3,6 +3,7 @@ EVP,101,COMMAND_NOT_SUPPORTED EVP,102,DECODE_ERROR EVP,103,DIFFERENT_KEY_TYPES EVP,104,DIFFERENT_PARAMETERS +EVP,136,EMPTY_PSK EVP,105,ENCODE_ERROR EVP,106,EXPECTING_AN_EC_KEY_KEY EVP,107,EXPECTING_AN_RSA_KEY diff --git a/crypto/evp/evp.c b/crypto/evp/evp.c index 60fdf64edb..653d6573fd 100644 --- a/crypto/evp/evp.c +++ b/crypto/evp/evp.c @@ -76,6 +76,10 @@ // TODO(davidben): Fix Node to not touch the error queue itself and remove this. OPENSSL_DECLARE_ERROR_REASON(EVP, NOT_XOF_OR_INVALID_LENGTH) +// The HPKE module uses the EVP error namespace, but it lives in another +// directory. +OPENSSL_DECLARE_ERROR_REASON(EVP, EMPTY_PSK) + EVP_PKEY *EVP_PKEY_new(void) { EVP_PKEY *ret; diff --git a/crypto/hpke/hpke.c b/crypto/hpke/hpke.c index cacc19e05a..2e0a58192e 100644 --- a/crypto/hpke/hpke.c +++ b/crypto/hpke/hpke.c @@ -38,6 +38,7 @@ #define HPKE_SUITE_ID_LEN 10 #define HPKE_MODE_BASE 0 +#define HPKE_MODE_PSK 1 static const char kHpkeRfcId[] = "HPKE-05 "; @@ -115,7 +116,7 @@ static int hpke_extract_and_expand(const EVP_MD *hkdf_md, uint8_t *out_key, X25519_PUBLIC_VALUE_LEN)) { return 0; } - const char kPRKExpandLabel[] = "shared_secret"; + static const char kPRKExpandLabel[] = "shared_secret"; if (!hpke_labeled_expand(hkdf_md, out_key, out_len, prk, prk_len, kX25519SuiteID, sizeof(kX25519SuiteID), kPRKExpandLabel, kem_context, KEM_CONTEXT_LEN)) { @@ -150,9 +151,28 @@ static const EVP_MD *hpke_get_kdf(uint16_t kdf_id) { return NULL; } -static int hpke_key_schedule(EVP_HPKE_CTX *hpke, const uint8_t *shared_secret, +static int hpke_key_schedule(EVP_HPKE_CTX *hpke, uint8_t mode, + const uint8_t *shared_secret, size_t shared_secret_len, const uint8_t *info, - size_t info_len) { + size_t info_len, const uint8_t *psk, + size_t psk_len, const uint8_t *psk_id, + size_t psk_id_len) { + // Verify the PSK inputs. + switch (mode) { + case HPKE_MODE_BASE: + // This is an internal error, unreachable from the caller. + assert(psk_len == 0 && psk_id_len == 0); + break; + case HPKE_MODE_PSK: + if (psk_len == 0 || psk_id_len == 0) { + OPENSSL_PUT_ERROR(EVP, EVP_R_EMPTY_PSK); + return 0; + } + break; + default: + return 0; + } + // Attempt to get an EVP_AEAD*. const EVP_AEAD *aead = hpke_get_aead(hpke->aead_id); if (aead == NULL) { @@ -170,7 +190,7 @@ static int hpke_key_schedule(EVP_HPKE_CTX *hpke, const uint8_t *shared_secret, size_t psk_id_hash_len; if (!hpke_labeled_extract(hpke->hkdf_md, psk_id_hash, &psk_id_hash_len, NULL, 0, suite_id, sizeof(suite_id), kPskIdHashLabel, - NULL, 0)) { + psk_id, psk_id_len)) { return 0; } @@ -189,7 +209,7 @@ static int hpke_key_schedule(EVP_HPKE_CTX *hpke, const uint8_t *shared_secret, size_t context_len; CBB context_cbb; if (!CBB_init_fixed(&context_cbb, context, sizeof(context)) || - !CBB_add_u8(&context_cbb, HPKE_MODE_BASE) || + !CBB_add_u8(&context_cbb, mode) || !CBB_add_bytes(&context_cbb, psk_id_hash, psk_id_hash_len) || !CBB_add_bytes(&context_cbb, info_hash, info_hash_len) || !CBB_finish(&context_cbb, NULL, &context_len)) { @@ -201,8 +221,8 @@ static int hpke_key_schedule(EVP_HPKE_CTX *hpke, const uint8_t *shared_secret, uint8_t psk_hash[EVP_MAX_MD_SIZE]; size_t psk_hash_len; if (!hpke_labeled_extract(hpke->hkdf_md, psk_hash, &psk_hash_len, NULL, 0, - suite_id, sizeof(suite_id), kPskHashLabel, NULL, - 0)) { + suite_id, sizeof(suite_id), kPskHashLabel, psk, + psk_len)) { return 0; } @@ -338,8 +358,9 @@ int EVP_HPKE_CTX_setup_base_s_x25519_for_test( uint8_t shared_secret[SHA256_DIGEST_LENGTH]; if (!hpke_encap(hpke, shared_secret, peer_public_value, ephemeral_private, ephemeral_public) || - !hpke_key_schedule(hpke, shared_secret, sizeof(shared_secret), info, - info_len)) { + !hpke_key_schedule(hpke, HPKE_MODE_BASE, shared_secret, + sizeof(shared_secret), info, info_len, NULL, 0, NULL, + 0)) { return 0; } return 1; @@ -360,8 +381,74 @@ int EVP_HPKE_CTX_setup_base_r_x25519( } uint8_t shared_secret[SHA256_DIGEST_LENGTH]; if (!hpke_decap(hpke, shared_secret, enc, public_key, private_key) || - !hpke_key_schedule(hpke, shared_secret, sizeof(shared_secret), info, - info_len)) { + !hpke_key_schedule(hpke, HPKE_MODE_BASE, shared_secret, + sizeof(shared_secret), info, info_len, NULL, 0, NULL, + 0)) { + return 0; + } + 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, + const uint8_t *psk_id, size_t psk_id_len) { + // 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); +} + +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 *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]) { + hpke->is_sender = 1; + hpke->kdf_id = kdf_id; + hpke->aead_id = aead_id; + hpke->hkdf_md = hpke_get_kdf(kdf_id); + if (hpke->hkdf_md == NULL) { + return 0; + } + uint8_t shared_secret[SHA256_DIGEST_LENGTH]; + if (!hpke_encap(hpke, shared_secret, peer_public_value, ephemeral_private, + ephemeral_public) || + !hpke_key_schedule(hpke, HPKE_MODE_PSK, shared_secret, + sizeof(shared_secret), info, info_len, psk, psk_len, + psk_id, psk_id_len)) { + return 0; + } + return 1; +} + +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, + size_t info_len, const uint8_t *psk, size_t psk_len, const uint8_t *psk_id, + size_t psk_id_len) { + hpke->is_sender = 0; + hpke->kdf_id = kdf_id; + hpke->aead_id = aead_id; + hpke->hkdf_md = hpke_get_kdf(kdf_id); + if (hpke->hkdf_md == NULL) { + return 0; + } + uint8_t shared_secret[SHA256_DIGEST_LENGTH]; + if (!hpke_decap(hpke, shared_secret, enc, public_key, private_key) || + !hpke_key_schedule(hpke, HPKE_MODE_PSK, shared_secret, + sizeof(shared_secret), info, info_len, psk, psk_len, + psk_id, psk_id_len)) { return 0; } return 1; diff --git a/crypto/hpke/hpke_test.cc b/crypto/hpke/hpke_test.cc index 6f942d22f5..49c9b060a0 100644 --- a/crypto/hpke/hpke_test.cc +++ b/crypto/hpke/hpke_test.cc @@ -13,8 +13,8 @@ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include -#include #include +#include #include #include @@ -23,7 +23,9 @@ #include #include #include +#include #include +#include #include "../test/file_test.h" #include "../test/test_util.h" @@ -33,31 +35,66 @@ namespace bssl { namespace { -// HpkeTestVector corresponds to one array member in the published +enum class HPKEMode { + kBase = 0, + kPSK = 1, +}; + +// HPKETestVector corresponds to one array member in the published // test-vectors.json. -class HpkeTestVector { +class HPKETestVector { public: - explicit HpkeTestVector() = default; - ~HpkeTestVector() = default; + explicit HPKETestVector() = default; + ~HPKETestVector() = default; bool ReadFromFileTest(FileTest *t); void Verify() const { - // Set up the sender. ScopedEVP_HPKE_CTX sender_ctx; - ASSERT_GT(secret_key_e_.size(), 0u); - - 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())); - - // 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_, public_key_e_.data(), - public_key_r_.data(), secret_key_r_.data(), info_.data(), - info_.size())); + switch (mode_) { + case HPKEMode::kBase: + ASSERT_GT(secret_key_e_.size(), 0u); + ASSERT_EQ(psk_.size(), 0u); + ASSERT_EQ(psk_id_.size(), 0u); + + // 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())); + + // 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(), + info_.size())); + break; + + case HPKEMode::kPSK: + ASSERT_GT(secret_key_e_.size(), 0u); + ASSERT_GT(psk_.size(), 0u); + ASSERT_GT(psk_id_.size(), 0u); + + // 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())); + + // 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(), + info_.size(), psk_.data(), psk_.size(), psk_id_.data(), + psk_id_.size())); + break; + default: + FAIL() << "Unsupported mode"; + return; + } VerifyEncryptions(sender_ctx.get(), receiver_ctx.get()); VerifyExports(sender_ctx.get()); @@ -112,6 +149,7 @@ class HpkeTestVector { std::vector exportValue; }; + HPKEMode mode_; uint16_t kdf_id_; uint16_t aead_id_; std::vector context_; @@ -122,6 +160,8 @@ class HpkeTestVector { std::vector secret_key_r_; std::vector encryptions_; std::vector exports_; + std::vector psk_; // Empty when mode is not PSK. + std::vector psk_id_; // Empty when mode is not PSK. }; // Match FileTest's naming scheme for duplicated attribute names. @@ -156,7 +196,13 @@ bool FileTestReadInt(FileTest *file_test, T *out, const std::string &key) { } -bool HpkeTestVector::ReadFromFileTest(FileTest *t) { +bool HPKETestVector::ReadFromFileTest(FileTest *t) { + uint8_t mode_tmp; + if (!FileTestReadInt(t, &mode_tmp, "mode")) { + return false; + } + mode_ = static_cast(mode_tmp); + if (!FileTestReadInt(t, &kdf_id_, "kdf_id") || !FileTestReadInt(t, &aead_id_, "aead_id") || !t->GetBytes(&info_, "info") || @@ -167,6 +213,13 @@ bool HpkeTestVector::ReadFromFileTest(FileTest *t) { return false; } + if (mode_ == HPKEMode::kPSK) { + if (!t->GetBytes(&psk_, "psk") || + !t->GetBytes(&psk_id_, "psk_id")) { + return false; + } + } + for (int i = 1; t->HasAttribute(BuildAttrName("aad", i)); i++) { Encryption encryption; if (!t->GetBytes(&encryption.aad, BuildAttrName("aad", i)) || @@ -194,7 +247,7 @@ bool HpkeTestVector::ReadFromFileTest(FileTest *t) { TEST(HPKETest, VerifyTestVectors) { FileTestGTest("crypto/hpke/hpke_test_vectors.txt", [](FileTest *t) { - HpkeTestVector test_vec; + HPKETestVector test_vec; EXPECT_TRUE(test_vec.ReadFromFileTest(t)); test_vec.Verify(); }); @@ -356,6 +409,63 @@ TEST(HPKETest, SenderInvalidOpen) { kMockCiphertextLen, nullptr, 0)); } +// Test that the PSK variants of Setup functions fail when any of the PSK inputs +// are empty. +TEST(HPKETest, EmptyPSK) { + const uint8_t kMockEnc[X25519_PUBLIC_VALUE_LEN] = {0xff}; + const uint8_t kMockPSK[100] = {0xff}; + const bssl::Span kPSKValues[] = { + {kMockPSK, sizeof(kMockPSK)}, + {nullptr, 0}, + }; + + // Generate the receiver's keypair. + 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); + + // Vary the PSK and PSKID inputs for the sender and receiver, trying all four + // permutations of empty and nonempty inputs. + + for (const auto psk : kPSKValues) { + for (const auto psk_id : kPSKValues) { + const bool kExpectSuccess = psk.size() > 0 && psk_id.size() > 0; + + ASSERT_EQ(ERR_get_error(), 0u); + + 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()), + kExpectSuccess); + + if (!kExpectSuccess) { + uint32_t err = ERR_get_error(); + EXPECT_EQ(ERR_LIB_EVP, ERR_GET_LIB(err)); + EXPECT_EQ(EVP_R_EMPTY_PSK, ERR_GET_REASON(err)); + } + ERR_clear_error(); + + ScopedEVP_HPKE_CTX receiver_ctx; + 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()), + kExpectSuccess); + + if (!kExpectSuccess) { + uint32_t err = ERR_get_error(); + EXPECT_EQ(ERR_LIB_EVP, ERR_GET_LIB(err)); + EXPECT_EQ(EVP_R_EMPTY_PSK, ERR_GET_REASON(err)); + } + ERR_clear_error(); + } + } +} + TEST(HPKETest, InternalParseIntSafe) { uint8_t u8 = 0xff; ASSERT_FALSE(ParseIntSafe(&u8, "-1")); diff --git a/crypto/hpke/hpke_test_vectors.txt b/crypto/hpke/hpke_test_vectors.txt index 10669d4f45..9d787e984c 100644 --- a/crypto/hpke/hpke_test_vectors.txt +++ b/crypto/hpke/hpke_test_vectors.txt @@ -1,3 +1,4 @@ +mode = 0 kdf_id = 1 aead_id = 1 info = 4f6465206f6e2061204772656369616e2055726e @@ -66,6 +67,78 @@ exportContext = 436f6e746578742d34 exportLength = 32 exportValue = c4823eeb3efd2d5216b2d3b16e542bf57470dc9b9ea9af6bce85b151a3589d90 +mode = 1 +kdf_id = 1 +aead_id = 1 +info = 4f6465206f6e2061204772656369616e2055726e +skRm = 4b41ef269169090551fcea177ecdf622bca86d82298e21cd93119b804ccc5eab +skEm = e7d2b539792a48a24451303ccd0cfe77176b6cb06823c439edfd217458a1398a +pkRm = a5c85773bed3a831e7096f7df4ff5d1d8bac48fc97bfac366141efab91892a3a +pkEm = 08d39d3e7f9b586341b6004dafba9679d2bd9340066edb247e3e919013efcd0f +psk = 5db3b80a81cb63ca59470c83414ef70a +psk_id = 456e6e796e20447572696e206172616e204d6f726961 +# encryptions[0] +aad = 436f756e742d30 +ciphertext = fb68f911b4e4033d1547f646ea30c9cee987fb4b4a8c30918e5de6e96de32fc63466f2fc05e09aeff552489741 +plaintext = 4265617574792069732074727574682c20747275746820626561757479 +# encryptions[1] +aad = 436f756e742d31 +ciphertext = 85e7472fbb7e2341af35fb2a0795df9a85caa99a8f584056b11d452bc160470672e297f9892ce2c5020e794ae1 +plaintext = 4265617574792069732074727574682c20747275746820626561757479 +# encryptions[2] +aad = 436f756e742d32 +ciphertext = 74229b7491102bcf94cf7633888bc48baa4e5a73cc544bfad4ff61585506facb44b359ade03c0b2b35c6430e4c +plaintext = 4265617574792069732074727574682c20747275746820626561757479 +# encryptions[3] +aad = 436f756e742d33 +ciphertext = 013476197af9440a8be89a0cf7d3802eae519d5f5b39cb600e8b285e16ad90c3d903f6108946616723e9a93b73 +plaintext = 4265617574792069732074727574682c20747275746820626561757479 +# encryptions[4] +aad = 436f756e742d34 +ciphertext = 5aeb09a3798d21dc2ca01f5c255624c9c8c20d75d79d19269eca7b280be0cb7851fae82b646bd5673d10368276 +plaintext = 4265617574792069732074727574682c20747275746820626561757479 +# encryptions[5] +aad = 436f756e742d35 +ciphertext = e9cac48b89f3f8898a85562007854b9f61bdf2d2c3e32e9b6162e9fa2f83924d138194528946d96cf7988685a0 +plaintext = 4265617574792069732074727574682c20747275746820626561757479 +# encryptions[6] +aad = 436f756e742d36 +ciphertext = 2aa76414e0cb28ba7ba0f24d800bc4fec24d51cd1f75e839233ee10610bda97f3daf46fadb53ca01762bbe8a04 +plaintext = 4265617574792069732074727574682c20747275746820626561757479 +# encryptions[7] +aad = 436f756e742d37 +ciphertext = 96148b343eb53df8d528af57214e65de028461ac69f2d9e371cb0aa4d732201d693766a17fd49ec6025bc98705 +plaintext = 4265617574792069732074727574682c20747275746820626561757479 +# encryptions[8] +aad = 436f756e742d38 +ciphertext = 39b7e966e0ada05d8cd8a9beb5765941baad38473f18f705443f882a207ff96bfe1c71ae386e97e2fa91960bbe +plaintext = 4265617574792069732074727574682c20747275746820626561757479 +# encryptions[9] +aad = 436f756e742d39 +ciphertext = 25bd0d0614a38b19a05dff783a1bbd003c25cade55ba0e24e234b803991cae60ba7d105d35e47519a8cf598580 +plaintext = 4265617574792069732074727574682c20747275746820626561757479 +# exports[0] +exportContext = 436f6e746578742d30 +exportLength = 32 +exportValue = bd292b132fae00243851451c3f3a87e9e11c3293c14d61b114b7e12e07245ffd +# exports[1] +exportContext = 436f6e746578742d31 +exportLength = 32 +exportValue = 695de26bc9336caee01cb04826f6e224f4d2108066ab17fc18f0c993dce05f24 +# exports[2] +exportContext = 436f6e746578742d32 +exportLength = 32 +exportValue = c53f26ef1bf4f5fd5469d807c418a0e103d035c76ccdbc6afb5bc42b24968f6c +# exports[3] +exportContext = 436f6e746578742d33 +exportLength = 32 +exportValue = 8cea4a595dfe3de84644ca8ea7ea9401a345f0db29bb4beebc2c471afc602ec4 +# exports[4] +exportContext = 436f6e746578742d34 +exportLength = 32 +exportValue = e6313f12f6c2054c69018f273211c54fcf2439d90173392eaa34b4caac929068 + +mode = 0 kdf_id = 1 aead_id = 2 info = 4f6465206f6e2061204772656369616e2055726e @@ -134,6 +207,78 @@ exportContext = 436f6e746578742d34 exportLength = 32 exportValue = 807d14a692749503f44e54660e8ebe4e93311715b9ba7d540973b2bb3c606825 +mode = 1 +kdf_id = 1 +aead_id = 2 +info = 4f6465206f6e2061204772656369616e2055726e +skRm = cb798ffb68e7b3db33913c365bf45a811fca8382522ac8815b12b26d3377a049 +skEm = bf3981d4d9b43ea83365747e25d8ba71e14d21cca47e35e70b5311e1d48f8a0d +pkRm = 4a9269e9db60008f5c7f3c7d39bb8c4923bc2f244b3ed9085191ef54cd10cf0c +pkEm = 8f65c9f75b4b774d36052dfac0bdd37a03f309b92c9a9ca47e903683be34d04d +psk = 5db3b80a81cb63ca59470c83414ef70a +psk_id = 456e6e796e20447572696e206172616e204d6f726961 +# encryptions[0] +aad = 436f756e742d30 +ciphertext = ad2a3e08e10413e7bdf9e89f2db169338fc68bcf8dc7bb073ca779024996de5922d338cf8407d34109cd2fdccf +plaintext = 4265617574792069732074727574682c20747275746820626561757479 +# encryptions[1] +aad = 436f756e742d31 +ciphertext = d7c94516707aef83e37dc5cbe3e9668260de5954899d54e8ecab3f1cfba8556557f1ff2238f817e0eb75d3cbb7 +plaintext = 4265617574792069732074727574682c20747275746820626561757479 +# encryptions[2] +aad = 436f756e742d32 +ciphertext = 371412a9a86704990e8d7170282134096fc623c74411d5ff95380692a74c438deb0e38f41bfba0562042e987a0 +plaintext = 4265617574792069732074727574682c20747275746820626561757479 +# encryptions[3] +aad = 436f756e742d33 +ciphertext = 4e3486ffca6d42f064c885d169210f6fcce2b3d4981d185d4b1a5c1e82733c14f14fcb8b1f16dd1e7b707907ab +plaintext = 4265617574792069732074727574682c20747275746820626561757479 +# encryptions[4] +aad = 436f756e742d34 +ciphertext = 45f532caeed9f6c35a990812773cfd688f686288dfcb500ae04f8fac4d3704204bb051e704c422edcc3107737b +plaintext = 4265617574792069732074727574682c20747275746820626561757479 +# encryptions[5] +aad = 436f756e742d35 +ciphertext = 1c0aee5fa393a0c4e2dbd70f7ce475542c71fd402b6fb8431855ac8fbafc6801c777996f8243c53a7d96d131c8 +plaintext = 4265617574792069732074727574682c20747275746820626561757479 +# encryptions[6] +aad = 436f756e742d36 +ciphertext = 66cd0eeb97fc59c1863898f9b7f1f67c82c5aede5794c17937f5e0909641af770c4973aec2a21967c0f17a64ba +plaintext = 4265617574792069732074727574682c20747275746820626561757479 +# encryptions[7] +aad = 436f756e742d37 +ciphertext = c96bb3363b31b582476239e1eb0792d2ac632ddaa7a1dc9ac7f9d588b62970016040a278e448256f5bbbf09ed7 +plaintext = 4265617574792069732074727574682c20747275746820626561757479 +# encryptions[8] +aad = 436f756e742d38 +ciphertext = 71b3055db5efe1165e685d25c4a749b6fdf8cb7a59f7e3e76cfbf63c109db9387fc751cc9c36cf886dd0f79411 +plaintext = 4265617574792069732074727574682c20747275746820626561757479 +# encryptions[9] +aad = 436f756e742d39 +ciphertext = 14372e32a6dee0536a11b66343eb436c099d7adf658900fa624a45d6f1a8e84297c56ec6e05b2745605dfcd99e +plaintext = 4265617574792069732074727574682c20747275746820626561757479 +# exports[0] +exportContext = 436f6e746578742d30 +exportLength = 32 +exportValue = c52ecbb65af1c6764ce7d2fd1131d5f050ee2f943a4fe56e9c855b44385b00cf +# exports[1] +exportContext = 436f6e746578742d31 +exportLength = 32 +exportValue = 42c5cf4f81152d05bacc9323e805eab8e429850dd029937c2c42f17ce7fea09b +# exports[2] +exportContext = 436f6e746578742d32 +exportLength = 32 +exportValue = 89d7f97327d51d61a4ac04b2507e51a977c8706bd932941f5acf1f542cfd034b +# exports[3] +exportContext = 436f6e746578742d33 +exportLength = 32 +exportValue = 581e3a66a1ad5309c3295825bc03407c7d9e34673e61aed2c543b47764577783 +# exports[4] +exportContext = 436f6e746578742d34 +exportLength = 32 +exportValue = 599f10537288a9ec87d53c16aaa5881715061e6152a5b51b1e0433a396b38d10 + +mode = 0 kdf_id = 1 aead_id = 3 info = 4f6465206f6e2061204772656369616e2055726e @@ -202,6 +347,78 @@ exportContext = 436f6e746578742d34 exportLength = 32 exportValue = d4f8878dbc471935e86cdee08746e53837bbb4b6013003bebb0bc1cc3e074085 +mode = 1 +kdf_id = 1 +aead_id = 3 +info = 4f6465206f6e2061204772656369616e2055726e +skRm = a6ab4e1bb782d580d837843089d65ebe271a0ee9b5a951777cecf1293c58c150 +skEm = 4bfdb62b95ae2a1f29f20ea49e24aa2673e0d240c6e967f668f55ed5dee996dc +pkRm = c49b46ed73ecb7d3a6a3e44f54b8f00f9ab872b57dd79ded66d7231a14c64144 +pkEm = f4639297e3305b03d34dd5d86522ddc6ba11a608a0003670a30734823cdd3763 +psk = 5db3b80a81cb63ca59470c83414ef70a +psk_id = 456e6e796e20447572696e206172616e204d6f726961 +# encryptions[0] +aad = 436f756e742d30 +ciphertext = f97ca72675b8199e8ffec65b4c200d901110b177b246f241b6f9716fb60b35b32a6d452675534b591e8141468a +plaintext = 4265617574792069732074727574682c20747275746820626561757479 +# encryptions[1] +aad = 436f756e742d31 +ciphertext = 57796e2b9dd0ddf807f1a7cb5884dfc50e61468c4fd69fa03963731e51674ca88fee94eeac3290734e1627ded6 +plaintext = 4265617574792069732074727574682c20747275746820626561757479 +# encryptions[2] +aad = 436f756e742d32 +ciphertext = b514150af1057151687d0036a9b4a3ad50fb186253f839d8433622baa85719ed5d2532017a0ce7b9ca0007f276 +plaintext = 4265617574792069732074727574682c20747275746820626561757479 +# encryptions[3] +aad = 436f756e742d33 +ciphertext = 50a645f0f9bddac7b1029dba61921d2cdc10258e6d67e4918000eab0d617fb04a655caeeab308eb159585ae07a +plaintext = 4265617574792069732074727574682c20747275746820626561757479 +# encryptions[4] +aad = 436f756e742d34 +ciphertext = 6232e4a184dbff7361f9e4d6bfaaf97631225ee317e63cb09e8f74fc93efeedb6385d4f4cb2e30ffb82aea0e1f +plaintext = 4265617574792069732074727574682c20747275746820626561757479 +# encryptions[5] +aad = 436f756e742d35 +ciphertext = ab801465f2080c1b9a06b582a919b51fc289e1b5b14bbad0b09cd92a82d27a1de1b934fd809cde8f19ef988373 +plaintext = 4265617574792069732074727574682c20747275746820626561757479 +# encryptions[6] +aad = 436f756e742d36 +ciphertext = 83248649e62ac67c3b9d5525b886c04960b00b02df2d34c91284e8ed537feba132b03d12b868822af1e583118d +plaintext = 4265617574792069732074727574682c20747275746820626561757479 +# encryptions[7] +aad = 436f756e742d37 +ciphertext = 5ad03248b8e5270a654b090df5eb8955120d5cdc00f5dfb004942125cec1fbcbaef7d9fdef284bddc134018b74 +plaintext = 4265617574792069732074727574682c20747275746820626561757479 +# encryptions[8] +aad = 436f756e742d38 +ciphertext = 56333a4ee1e5512cf2ffa1fd135fa54ba666f4388cf654fda9d7696ccfca1c51facda5a9bf80c9ac789026955a +plaintext = 4265617574792069732074727574682c20747275746820626561757479 +# encryptions[9] +aad = 436f756e742d39 +ciphertext = e352a356575dcee382c8d2489bc45dc3a757979638e952dbac969eb092e9c616d8654e9dec8d1c0777e39478c3 +plaintext = 4265617574792069732074727574682c20747275746820626561757479 +# exports[0] +exportContext = 436f6e746578742d30 +exportLength = 32 +exportValue = 735400cd9b9193daffe840f412074728ade6b1978e9ae27957aacd588dbd7c9e +# exports[1] +exportContext = 436f6e746578742d31 +exportLength = 32 +exportValue = cf4e351e1943d171ff2d88726f18160086ecbec52a8151dba8cf5ba0737a6097 +# exports[2] +exportContext = 436f6e746578742d32 +exportLength = 32 +exportValue = 8e23b44d4f23dd906d1c100580a670d171132c9786212c4ca2876a1541a84fae +# exports[3] +exportContext = 436f6e746578742d33 +exportLength = 32 +exportValue = 56252a940ece53d4013eb619b444ee1d019a08eec427ded2b6dbf24be624a4a0 +# exports[4] +exportContext = 436f6e746578742d34 +exportLength = 32 +exportValue = fc6cdca9ce8ab062401478ffd16ee1c07e2b15d7c781d4227f07c6043d937fad + +mode = 0 kdf_id = 3 aead_id = 1 info = 4f6465206f6e2061204772656369616e2055726e @@ -270,6 +487,78 @@ exportContext = 436f6e746578742d34 exportLength = 32 exportValue = 1538807322f02dbded405d10de3aafc4f6d365d9aefbef081d114dcedbe1cae2 +mode = 1 +kdf_id = 3 +aead_id = 1 +info = 4f6465206f6e2061204772656369616e2055726e +skRm = ac1f54ecf81f53a71c5be7f734346fffe084ba6f5966d2b3173df819145bd722 +skEm = 20c9020273ac6193f27fb69af406cdab8154090c28aa2c7b870b92513d8805f4 +pkRm = 7e8561e6b753c6992df8d89cc1e447bebd4e21fcd4d1dc868f6b2ea663ce7e18 +pkEm = 7c35810fdc4009af7cb98dca0838ad32495c71c3003be650ed1ea0f6cd1ecc3c +psk = 5db3b80a81cb63ca59470c83414ef70a +psk_id = 456e6e796e20447572696e206172616e204d6f726961 +# encryptions[0] +aad = 436f756e742d30 +ciphertext = 13d119d97709546435a5fbc99a39d9ac3f2ef459c9841305582282c435aab714af1df2f52bd07f196bfe9294f5 +plaintext = 4265617574792069732074727574682c20747275746820626561757479 +# encryptions[1] +aad = 436f756e742d31 +ciphertext = e8f9743ee3eeb41cebade4ba2f0d758b679c560a53a720aeb88017bbd778537b02b3eca27bca61fa13898847ec +plaintext = 4265617574792069732074727574682c20747275746820626561757479 +# encryptions[2] +aad = 436f756e742d32 +ciphertext = 7f0218fe141ffccc6229d096516a27cce109e1300f59a3500288cc1bb57c765b91b4a240075493d94abb9e4cf9 +plaintext = 4265617574792069732074727574682c20747275746820626561757479 +# encryptions[3] +aad = 436f756e742d33 +ciphertext = b893adce352a2b1c780f67475062a9eb827ba2fb2e7ec4ae21e27d6663e1a988d81390b50d99b4de2b451afce1 +plaintext = 4265617574792069732074727574682c20747275746820626561757479 +# encryptions[4] +aad = 436f756e742d34 +ciphertext = 8e733ddc1dd2b80ad6decf1b0ce08a28e9f5e644a7439621cd028ac9599c7657dac34173f7d5489e34be099462 +plaintext = 4265617574792069732074727574682c20747275746820626561757479 +# encryptions[5] +aad = 436f756e742d35 +ciphertext = 4551173fc2233def235d52c738dc5095bc7abb6e3c3c7f8e58ae983bf68cb5b6fdfdf334b9bef4e1c5b11c2884 +plaintext = 4265617574792069732074727574682c20747275746820626561757479 +# encryptions[6] +aad = 436f756e742d36 +ciphertext = 3384441833b623b36930d89a3e795fcc31e703d460ec48dc43be345794a2d73af9f4283494f23b904ba609197d +plaintext = 4265617574792069732074727574682c20747275746820626561757479 +# encryptions[7] +aad = 436f756e742d37 +ciphertext = ad5a5977bd3486ec319850a52fb8e7cba74d0e2c2ee261ec9a6b2bfb579f7a55f8bac5ab774c2bc28d86623ff7 +plaintext = 4265617574792069732074727574682c20747275746820626561757479 +# encryptions[8] +aad = 436f756e742d38 +ciphertext = 8d4466e0d99086ee1c0171a111a2c1ea5736ba9324eb20aa0d071dcd8c4581ea1dda96e25dd3f341c84c9c3529 +plaintext = 4265617574792069732074727574682c20747275746820626561757479 +# encryptions[9] +aad = 436f756e742d39 +ciphertext = adf8ca449b303657e9d81bf9566d7562d9b28d9c63758bfa93586f5ba69a2fe2dca1dafd022831de39b6453c28 +plaintext = 4265617574792069732074727574682c20747275746820626561757479 +# exports[0] +exportContext = 436f6e746578742d30 +exportLength = 32 +exportValue = 899f63d5646d1116e63029c0c03a3a8b63b815af58a0e197c440e8075daa220d +# exports[1] +exportContext = 436f6e746578742d31 +exportLength = 32 +exportValue = a2da1ff2773723418e07c63d39455d70be0865d6d0fb29e355eda599a62441da +# exports[2] +exportContext = 436f6e746578742d32 +exportLength = 32 +exportValue = 1c361d5b9b14c6f75660c8c960b908394c0281895fbba9288730822511a24171 +# exports[3] +exportContext = 436f6e746578742d33 +exportLength = 32 +exportValue = b5258b7e39ea3a68177b50a5a492b6cb8083707a1756e5a7d5d4370556c856de +# exports[4] +exportContext = 436f6e746578742d34 +exportLength = 32 +exportValue = 81ddfe54c7894f987e2945333a5ec809068890587759b6407feb1d6f1ca26e6e + +mode = 0 kdf_id = 3 aead_id = 2 info = 4f6465206f6e2061204772656369616e2055726e @@ -338,6 +627,78 @@ exportContext = 436f6e746578742d34 exportLength = 32 exportValue = 5c49cd3ebcb956aeb7e41c9a0f2d4b4c9501f66cc544d8d7fa62ce96d2938857 +mode = 1 +kdf_id = 3 +aead_id = 2 +info = 4f6465206f6e2061204772656369616e2055726e +skRm = 939a0b48510924ccf6449c0eaaa1069bb41ab9cf54d090e6c6eb9aaab6051d69 +skEm = d3668380f7053086047e1f8a66e0e32c45c1086002b6a67dc9a942058a655073 +pkRm = 4af18720a608d13ce17268aa1721876e96ec4173a40788ddfd60c886b4c08605 +pkEm = 2ed53926385da5d41c76e75a636cd795fea5200d0e7ef6affd4b741a1196be37 +psk = 5db3b80a81cb63ca59470c83414ef70a +psk_id = 456e6e796e20447572696e206172616e204d6f726961 +# encryptions[0] +aad = 436f756e742d30 +ciphertext = b5039652103f36bdcf1380b947ed8b6dc3413b98cff2c6451aff5fabee7234ace274918eb665f6d08850a70093 +plaintext = 4265617574792069732074727574682c20747275746820626561757479 +# encryptions[1] +aad = 436f756e742d31 +ciphertext = f1a1beb03a0c2d3f756d992cba6712247e24561e8407aef299285cefc337beaf249b8b92325a6718feffb1cfad +plaintext = 4265617574792069732074727574682c20747275746820626561757479 +# encryptions[2] +aad = 436f756e742d32 +ciphertext = 0f5f58f918a19f55efc146bf3ecd5c72bb0c00893c02ca56cf291904e1e1f8f6d0768f1cfed9d64d3f7f35d912 +plaintext = 4265617574792069732074727574682c20747275746820626561757479 +# encryptions[3] +aad = 436f756e742d33 +ciphertext = 14177f71f6716d128baaff214e360bb9b8dc0ddb34ba7bcb8d0dcb01c548d42d3c43875ec8ff083acba591ca24 +plaintext = 4265617574792069732074727574682c20747275746820626561757479 +# encryptions[4] +aad = 436f756e742d34 +ciphertext = f8ee21f3af210dacb7aea148b444a98e643f161040db1350429c366a667bbc4b0cb6dbf047c2ba9f86a8ecf425 +plaintext = 4265617574792069732074727574682c20747275746820626561757479 +# encryptions[5] +aad = 436f756e742d35 +ciphertext = 9f5ffc686ca660de6101a9dbf412c61de6fc574954f72f7d2c652c0ab61e8597170ec713b5314e41f0601fbf49 +plaintext = 4265617574792069732074727574682c20747275746820626561757479 +# encryptions[6] +aad = 436f756e742d36 +ciphertext = 3f415ff7bc48fbdb69babce3045049ae2bc2a6983ddaf08cc9b3368362f7918bb73a4872c37fed3e3d808a9c1e +plaintext = 4265617574792069732074727574682c20747275746820626561757479 +# encryptions[7] +aad = 436f756e742d37 +ciphertext = bd2199064b596d3ef9a77fa8a5db93f1510bf996e320da92635e435c4b59120702c344825fc012393dcbddc05e +plaintext = 4265617574792069732074727574682c20747275746820626561757479 +# encryptions[8] +aad = 436f756e742d38 +ciphertext = 789faf060328cb1d359a7a30a3ce9d303612ef9c9da56c78fee82334953d425bb1613e757b2d7ab1aafd5be927 +plaintext = 4265617574792069732074727574682c20747275746820626561757479 +# encryptions[9] +aad = 436f756e742d39 +ciphertext = ac41c4a676448ef3f39a471f588d8576bb30817055ce8ac4404b61a4fdbb71adbababd15117cec7371aac83b0e +plaintext = 4265617574792069732074727574682c20747275746820626561757479 +# exports[0] +exportContext = 436f6e746578742d30 +exportLength = 32 +exportValue = e98921e4c437992d7ac035d74dfae232ef41227e2f27e4e4d801b4bd8934a5b6 +# exports[1] +exportContext = 436f6e746578742d31 +exportLength = 32 +exportValue = 1269029586ff64d8bde114359411f61c22211e8725a2b86ea145b8b9151c3915 +# exports[2] +exportContext = 436f6e746578742d32 +exportLength = 32 +exportValue = b8f393d7cea5934e16f4de8ef9a8912104b741ecd464d4c84886f7eef28cc301 +# exports[3] +exportContext = 436f6e746578742d33 +exportLength = 32 +exportValue = eb5c8739d172a30b48235316e13a12fa8abd05d72cc5c330fd3ab3de3371ddc4 +# exports[4] +exportContext = 436f6e746578742d34 +exportLength = 32 +exportValue = 0b15c1a0dccac801a3078a8a01145c940ade7d9993111bf614ac69d073913a6f + +mode = 0 kdf_id = 3 aead_id = 3 info = 4f6465206f6e2061204772656369616e2055726e @@ -405,3 +766,74 @@ exportValue = d440fbf13b9e3956c7d6772166e07305a8f5a396e2bd361b5b9fbae9b0b04909 exportContext = 436f6e746578742d34 exportLength = 32 exportValue = 1474f8e9dac70e76041b4bb365f1fc4e1e2509f43c188b5d15b8d89113c197f7 + +mode = 1 +kdf_id = 3 +aead_id = 3 +info = 4f6465206f6e2061204772656369616e2055726e +skRm = c9221f98c17117ab4216e062481934ad21a12c8ba833a0611ca1910fac031563 +skEm = 9e38eaa97787575e564949bd84845965e910ae90a17bf841f68a4c791385afd3 +pkRm = 4ca2dcf3f5fa2b8b782536f695b3279f03569857a88e90075d5e4a67e4c4a44d +pkEm = 886c15a9d1c3609a3f3f6be3b5d1b60817f6a557e2b7344456dbc8ae49f5e93c +psk = 5db3b80a81cb63ca59470c83414ef70a +psk_id = 456e6e796e20447572696e206172616e204d6f726961 +# encryptions[0] +aad = 436f756e742d30 +ciphertext = 2f3eba789b7706b85fd2fcadf189f640a726160a7a0ef22b6483aaf69210c02d4c22113740235783dbd70ca1b7 +plaintext = 4265617574792069732074727574682c20747275746820626561757479 +# encryptions[1] +aad = 436f756e742d31 +ciphertext = ea76c297d6440fcc6e753980678adf65389171c591cd2ce0cc6de56c4560e6642ca5df5d910b3006b653372657 +plaintext = 4265617574792069732074727574682c20747275746820626561757479 +# encryptions[2] +aad = 436f756e742d32 +ciphertext = 7bed7b81628f1892518ced3b292cdf8e17dd0fa270600177a5c122204bfc381bc01f9bd5de77c4a568055ad19c +plaintext = 4265617574792069732074727574682c20747275746820626561757479 +# encryptions[3] +aad = 436f756e742d33 +ciphertext = 38ad518591bbb6bbbe114e08e76a90b0040ef5571dbeb9a4ca778b72eba6e729c75efaf476e1dc69d2a95ba304 +plaintext = 4265617574792069732074727574682c20747275746820626561757479 +# encryptions[4] +aad = 436f756e742d34 +ciphertext = a38f5cf41d1ad3802ec4043067e4ff1aff3c557d1961cb76f6fbecea500f45ce780c27cc2894057093298d782e +plaintext = 4265617574792069732074727574682c20747275746820626561757479 +# encryptions[5] +aad = 436f756e742d35 +ciphertext = 0844adf506c653ff4cb9eaa595b4a6382055d53bfe4490a323d3ed0369b33a206f6fbed3a2c2409a646edcce70 +plaintext = 4265617574792069732074727574682c20747275746820626561757479 +# encryptions[6] +aad = 436f756e742d36 +ciphertext = 747700aa0de178a38e2ac8ee358e0d79d2b6026a8e86e215312d359933da08bcbb443e9e2280932e2e37ca0c7d +plaintext = 4265617574792069732074727574682c20747275746820626561757479 +# encryptions[7] +aad = 436f756e742d37 +ciphertext = 31b7a490d05bd9e31b6ddc82b2eef9d6500675273e5c215c2f3fd4a28f04b73c752a7b7f89c2220cc5d26d3ef4 +plaintext = 4265617574792069732074727574682c20747275746820626561757479 +# encryptions[8] +aad = 436f756e742d38 +ciphertext = b57d6cb945a21064c1dd0a293ae28d315e7160764e20d48f50ba9be6d3d530cd064a851f7f9fd16f61fd8afef0 +plaintext = 4265617574792069732074727574682c20747275746820626561757479 +# encryptions[9] +aad = 436f756e742d39 +ciphertext = 1bb75c2eb81165d8c95d893c9dc1425d2de1628696c488d6ff0213674a6bdba09a3ad6ef506ca339d64f02e46e +plaintext = 4265617574792069732074727574682c20747275746820626561757479 +# exports[0] +exportContext = 436f6e746578742d30 +exportLength = 32 +exportValue = bf8d87036ace4835ee917a504016601ce7b5add0b8d72aa64ea493ea241786f4 +# exports[1] +exportContext = 436f6e746578742d31 +exportLength = 32 +exportValue = 9583f302506aabded442f4a3c4cb976682fed99c4bcbdf5ad41c2f00d3fbc27a +# exports[2] +exportContext = 436f6e746578742d32 +exportLength = 32 +exportValue = fa169c1e9ca8582381a72b5067da174995500198484520d60d22bf9bb4c34ead +# exports[3] +exportContext = 436f6e746578742d33 +exportLength = 32 +exportValue = 56fbba55aef923240daf63ebd30508e891cdffbe0bfe03306727320d6dfa29e6 +# exports[4] +exportContext = 436f6e746578742d34 +exportLength = 32 +exportValue = eb30f91427038c6e3716310c0ffc431ca9ea2b10c2f264f7aee82f86f817b8e2 diff --git a/crypto/hpke/internal.h b/crypto/hpke/internal.h index 79f65aaeb3..87c049a509 100644 --- a/crypto/hpke/internal.h +++ b/crypto/hpke/internal.h @@ -27,9 +27,10 @@ extern "C" { // Hybrid Public Key Encryption. // // Hybrid Public Key Encryption (HPKE) enables a sender to encrypt messages to a -// receiver with a public key. +// receiver with a public key. Optionally, the sender may authenticate its +// possession of a pre-shared key to the recipient. // -// See https://tools.ietf.org/html/draft-irtf-cfrg-hpke-04. +// See https://tools.ietf.org/html/draft-irtf-cfrg-hpke-05. // EVP_HPKE_AEAD_* are AEAD identifiers. #define EVP_HPKE_AEAD_AES_GCM_128 0x0001 @@ -78,13 +79,11 @@ OPENSSL_EXPORT void EVP_HPKE_CTX_cleanup(EVP_HPKE_CTX *ctx); // must be one of the |EVP_HPKE_HKDF_*| constants. |aead_id| selects the AEAD // for the "open" and "seal" operations and must be one of the |EVP_HPKE_AEAD_*" // constants." -// -// See https://www.ietf.org/id/draft-irtf-cfrg-hpke-04.html#section-5.1.1. // EVP_HPKE_CTX_setup_base_s_x25519 sets up |hpke| as a sender context that can // encrypt for the private key corresponding to |peer_public_value| (the // recipient's public key). It returns one on success, and zero otherwise. Note -// that this function may fail if |peer_public_value| is invalid. +// that this function will fail if |peer_public_value| is invalid. // // This function writes the encapsulated shared secret to |out_enc|. OPENSSL_EXPORT int EVP_HPKE_CTX_setup_base_s_x25519( @@ -106,7 +105,7 @@ OPENSSL_EXPORT int EVP_HPKE_CTX_setup_base_s_x25519_for_test( // 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 -// may fail if |enc| is invalid. +// will fail if |enc| is invalid. 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], @@ -114,6 +113,52 @@ OPENSSL_EXPORT int EVP_HPKE_CTX_setup_base_r_x25519( const uint8_t private_key[X25519_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 +// encrypt for the private key corresponding to |peer_public_value| (the +// recipient's public key) and authenticate its possession of a PSK. It returns +// one on success, and zero otherwise. Note that this function will fail if +// |peer_public_value| is invalid. +// +// 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. +// +// This function writes the encapsulated shared secret to |out_enc|. +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_setup_psk_s_x25519_for_test behaves like +// |EVP_HPKE_CTX_setup_psk_s_x25519|, but takes a pre-generated ephemeral sender +// key. +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 *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]); + +// 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. +// +// 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, + size_t info_len, const uint8_t *psk, size_t psk_len, const uint8_t *psk_id, + size_t psk_id_len); + // Using an HPKE context. diff --git a/crypto/hpke/translate_test_vectors.py b/crypto/hpke/translate_test_vectors.py index 6d73228347..d53787a573 100755 --- a/crypto/hpke/translate_test_vectors.py +++ b/crypto/hpke/translate_test_vectors.py @@ -28,6 +28,7 @@ import sys HPKE_MODE_BASE = 0 +HPKE_MODE_PSK = 1 HPKE_DHKEM_X25519_SHA256 = 0x0020 @@ -46,11 +47,17 @@ def read_test_vectors_and_generate_code(json_file_in_path, test_file_out_path): lines = [] for test in test_vecs: # Filter out test cases that we don't use. - if (test["mode"] != HPKE_MODE_BASE or + if (test["mode"] not in [HPKE_MODE_BASE, HPKE_MODE_PSK] or test["kem_id"] != HPKE_DHKEM_X25519_SHA256): continue - for key in ("kdf_id", "aead_id", "info", "skRm", "skEm", "pkRm", "pkEm"): + keys = ["mode", "kdf_id", "aead_id", "info", "skRm", "skEm", "pkRm", "pkEm"] + + if test["mode"] == HPKE_MODE_PSK: + keys.append("psk") + keys.append("psk_id") + + for key in keys: lines.append("{} = {}".format(key, str(test[key]))) for i, enc in enumerate(test["encryptions"]): diff --git a/include/openssl/evp.h b/include/openssl/evp.h index e647cdf60a..da114d4f6a 100644 --- a/include/openssl/evp.h +++ b/include/openssl/evp.h @@ -1117,5 +1117,6 @@ BSSL_NAMESPACE_END #define EVP_R_INVALID_PARAMETERS 133 #define EVP_R_INVALID_PEER_KEY 134 #define EVP_R_NOT_XOF_OR_INVALID_LENGTH 135 +#define EVP_R_EMPTY_PSK 136 #endif // OPENSSL_HEADER_EVP_H