mirror of
https://github.com/AntelopeIO/boringssl.git
synced 2026-07-21 14:43:53 +00:00
Add EVP_PKEY_HKDF for OpenSSL compatibility.
OpenSSL 1.1.1 added HKDF support, but by sticking it into EVP_PKEY_derive, the API meant for Diffie-Hellman-like primitives. Implement it for OpenSSL compatibility. This does unfortunately mean anything using EVP now pulls in HKDF. HKDF isn't much code, but we should make EVP more static-linker-friendly. (Filed https://crbug.com/boringssl/497) Change-Id: I90b9b0d918129829eb36ba9d50ff4d8580346ff0 Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/52829 Reviewed-by: Adam Langley <agl@google.com> Commit-Queue: David Benjamin <davidben@google.com>
This commit is contained in:
committed by
Boringssl LUCI CQ
parent
77dc23983f
commit
44872e1c74
@@ -296,6 +296,7 @@ add_library(
|
||||
evp/p_ec_asn1.c
|
||||
evp/p_ed25519.c
|
||||
evp/p_ed25519_asn1.c
|
||||
evp/p_hkdf.c
|
||||
evp/p_rsa.c
|
||||
evp/p_rsa_asn1.c
|
||||
evp/p_x25519.c
|
||||
|
||||
@@ -71,6 +71,7 @@ static const EVP_PKEY_METHOD *const evp_methods[] = {
|
||||
&ec_pkey_meth,
|
||||
&ed25519_pkey_meth,
|
||||
&x25519_pkey_meth,
|
||||
&hkdf_pkey_meth,
|
||||
};
|
||||
|
||||
static const EVP_PKEY_METHOD *evp_pkey_meth_find(int type) {
|
||||
|
||||
@@ -178,6 +178,11 @@ OPENSSL_EXPORT int EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype,
|
||||
#define EVP_PKEY_CTRL_RSA_OAEP_LABEL (EVP_PKEY_ALG_CTRL + 11)
|
||||
#define EVP_PKEY_CTRL_GET_RSA_OAEP_LABEL (EVP_PKEY_ALG_CTRL + 12)
|
||||
#define EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID (EVP_PKEY_ALG_CTRL + 13)
|
||||
#define EVP_PKEY_CTRL_HKDF_MODE (EVP_PKEY_ALG_CTRL + 14)
|
||||
#define EVP_PKEY_CTRL_HKDF_MD (EVP_PKEY_ALG_CTRL + 15)
|
||||
#define EVP_PKEY_CTRL_HKDF_KEY (EVP_PKEY_ALG_CTRL + 16)
|
||||
#define EVP_PKEY_CTRL_HKDF_SALT (EVP_PKEY_ALG_CTRL + 17)
|
||||
#define EVP_PKEY_CTRL_HKDF_INFO (EVP_PKEY_ALG_CTRL + 18)
|
||||
|
||||
struct evp_pkey_ctx_st {
|
||||
// Method associated with this operation
|
||||
@@ -260,6 +265,7 @@ extern const EVP_PKEY_METHOD rsa_pkey_meth;
|
||||
extern const EVP_PKEY_METHOD ec_pkey_meth;
|
||||
extern const EVP_PKEY_METHOD ed25519_pkey_meth;
|
||||
extern const EVP_PKEY_METHOD x25519_pkey_meth;
|
||||
extern const EVP_PKEY_METHOD hkdf_pkey_meth;
|
||||
|
||||
|
||||
#if defined(__cplusplus)
|
||||
|
||||
@@ -0,0 +1,241 @@
|
||||
/* Copyright (c) 2022, 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 <openssl/evp.h>
|
||||
|
||||
#include <openssl/bytestring.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/hkdf.h>
|
||||
#include <openssl/kdf.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
#include "../internal.h"
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
typedef struct {
|
||||
int mode;
|
||||
const EVP_MD *md;
|
||||
uint8_t *key;
|
||||
size_t key_len;
|
||||
uint8_t *salt;
|
||||
size_t salt_len;
|
||||
CBB info;
|
||||
} HKDF_PKEY_CTX;
|
||||
|
||||
static int pkey_hkdf_init(EVP_PKEY_CTX *ctx) {
|
||||
HKDF_PKEY_CTX *hctx = OPENSSL_malloc(sizeof(HKDF_PKEY_CTX));
|
||||
if (hctx == NULL) {
|
||||
OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
OPENSSL_memset(hctx, 0, sizeof(HKDF_PKEY_CTX));
|
||||
if (!CBB_init(&hctx->info, 0)) {
|
||||
OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE);
|
||||
OPENSSL_free(hctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ctx->data = hctx;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int pkey_hkdf_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) {
|
||||
if (!pkey_hkdf_init(dst)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
HKDF_PKEY_CTX *hctx_dst = dst->data;
|
||||
const HKDF_PKEY_CTX *hctx_src = src->data;
|
||||
hctx_dst->mode = hctx_src->mode;
|
||||
hctx_dst->md = hctx_src->md;
|
||||
|
||||
if (hctx_src->key_len != 0) {
|
||||
hctx_dst->key = OPENSSL_memdup(hctx_src->key, hctx_src->key_len);
|
||||
if (hctx_src->key == NULL) {
|
||||
OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
hctx_dst->key_len = hctx_src->key_len;
|
||||
}
|
||||
|
||||
if (hctx_src->salt_len != 0) {
|
||||
hctx_dst->salt = OPENSSL_memdup(hctx_src->salt, hctx_src->salt_len);
|
||||
if (hctx_src->salt == NULL) {
|
||||
OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
hctx_dst->salt_len = hctx_src->salt_len;
|
||||
}
|
||||
|
||||
if (!CBB_add_bytes(&hctx_dst->info, CBB_data(&hctx_src->info),
|
||||
CBB_len(&hctx_src->info))) {
|
||||
OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void pkey_hkdf_cleanup(EVP_PKEY_CTX *ctx) {
|
||||
HKDF_PKEY_CTX *hctx = ctx->data;
|
||||
if (hctx != NULL) {
|
||||
OPENSSL_free(hctx->key);
|
||||
OPENSSL_free(hctx->salt);
|
||||
CBB_cleanup(&hctx->info);
|
||||
OPENSSL_free(hctx);
|
||||
ctx->data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int pkey_hkdf_derive(EVP_PKEY_CTX *ctx, uint8_t *out, size_t *out_len) {
|
||||
HKDF_PKEY_CTX *hctx = ctx->data;
|
||||
if (hctx->md == NULL) {
|
||||
OPENSSL_PUT_ERROR(EVP, EVP_R_MISSING_PARAMETERS);
|
||||
return 0;
|
||||
}
|
||||
if (hctx->key_len == 0) {
|
||||
OPENSSL_PUT_ERROR(EVP, EVP_R_NO_KEY_SET);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (out == NULL) {
|
||||
if (hctx->mode == EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY) {
|
||||
*out_len = EVP_MD_size(hctx->md);
|
||||
}
|
||||
// HKDF-Expand is variable-length and returns |*out_len| bytes. "Output" the
|
||||
// input length by leaving it alone.
|
||||
return 1;
|
||||
}
|
||||
|
||||
switch (hctx->mode) {
|
||||
case EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND:
|
||||
return HKDF(out, *out_len, hctx->md, hctx->key, hctx->key_len, hctx->salt,
|
||||
hctx->salt_len, CBB_data(&hctx->info), CBB_len(&hctx->info));
|
||||
|
||||
case EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY:
|
||||
if (*out_len < EVP_MD_size(hctx->md)) {
|
||||
OPENSSL_PUT_ERROR(EVP, EVP_R_BUFFER_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
return HKDF_extract(out, out_len, hctx->md, hctx->key, hctx->key_len,
|
||||
hctx->salt, hctx->salt_len);
|
||||
|
||||
case EVP_PKEY_HKDEF_MODE_EXPAND_ONLY:
|
||||
return HKDF_expand(out, *out_len, hctx->md, hctx->key, hctx->key_len,
|
||||
CBB_data(&hctx->info), CBB_len(&hctx->info));
|
||||
}
|
||||
OPENSSL_PUT_ERROR(EVP, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pkey_hkdf_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) {
|
||||
HKDF_PKEY_CTX *hctx = ctx->data;
|
||||
switch (type) {
|
||||
case EVP_PKEY_CTRL_HKDF_MODE:
|
||||
if (p1 != EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND &&
|
||||
p1 != EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY &&
|
||||
p1 != EVP_PKEY_HKDEF_MODE_EXPAND_ONLY) {
|
||||
OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_OPERATION);
|
||||
return 0;
|
||||
}
|
||||
hctx->mode = p1;
|
||||
return 1;
|
||||
case EVP_PKEY_CTRL_HKDF_MD:
|
||||
hctx->md = p2;
|
||||
return 1;
|
||||
case EVP_PKEY_CTRL_HKDF_KEY: {
|
||||
const CBS *key = p2;
|
||||
if (!CBS_stow(key, &hctx->key, &hctx->key_len)) {
|
||||
OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
case EVP_PKEY_CTRL_HKDF_SALT: {
|
||||
const CBS *salt = p2;
|
||||
if (!CBS_stow(salt, &hctx->salt, &hctx->salt_len)) {
|
||||
OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
case EVP_PKEY_CTRL_HKDF_INFO: {
|
||||
const CBS *info = p2;
|
||||
// |EVP_PKEY_CTX_add1_hkdf_info| appends to the info string, rather than
|
||||
// replacing it.
|
||||
if (!CBB_add_bytes(&hctx->info, CBS_data(info), CBS_len(info))) {
|
||||
OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
default:
|
||||
OPENSSL_PUT_ERROR(EVP, EVP_R_COMMAND_NOT_SUPPORTED);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
const EVP_PKEY_METHOD hkdf_pkey_meth = {
|
||||
EVP_PKEY_HKDF,
|
||||
pkey_hkdf_init,
|
||||
pkey_hkdf_copy,
|
||||
pkey_hkdf_cleanup,
|
||||
/*keygen=*/NULL,
|
||||
/*sign=*/NULL,
|
||||
/*sign_message=*/NULL,
|
||||
/*verify=*/NULL,
|
||||
/*verify_message=*/NULL,
|
||||
/*verify_recover=*/NULL,
|
||||
/*encrypt=*/NULL,
|
||||
/*decrypt=*/NULL,
|
||||
pkey_hkdf_derive,
|
||||
/*paramgen=*/NULL,
|
||||
pkey_hkdf_ctrl,
|
||||
};
|
||||
|
||||
int EVP_PKEY_CTX_hkdf_mode(EVP_PKEY_CTX *ctx, int mode) {
|
||||
return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_HKDF, EVP_PKEY_OP_DERIVE,
|
||||
EVP_PKEY_CTRL_HKDF_MODE, mode, NULL);
|
||||
}
|
||||
|
||||
int EVP_PKEY_CTX_set_hkdf_md(EVP_PKEY_CTX *ctx, const EVP_MD *md) {
|
||||
return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_HKDF, EVP_PKEY_OP_DERIVE,
|
||||
EVP_PKEY_CTRL_HKDF_MD, 0, (void *)md);
|
||||
}
|
||||
|
||||
int EVP_PKEY_CTX_set1_hkdf_key(EVP_PKEY_CTX *ctx, const uint8_t *key,
|
||||
size_t key_len) {
|
||||
CBS cbs;
|
||||
CBS_init(&cbs, key, key_len);
|
||||
return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_HKDF, EVP_PKEY_OP_DERIVE,
|
||||
EVP_PKEY_CTRL_HKDF_KEY, 0, &cbs);
|
||||
}
|
||||
|
||||
int EVP_PKEY_CTX_set1_hkdf_salt(EVP_PKEY_CTX *ctx, const uint8_t *salt,
|
||||
size_t salt_len) {
|
||||
CBS cbs;
|
||||
CBS_init(&cbs, salt, salt_len);
|
||||
return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_HKDF, EVP_PKEY_OP_DERIVE,
|
||||
EVP_PKEY_CTRL_HKDF_SALT, 0, &cbs);
|
||||
}
|
||||
|
||||
int EVP_PKEY_CTX_add1_hkdf_info(EVP_PKEY_CTX *ctx, const uint8_t *info,
|
||||
size_t info_len) {
|
||||
CBS cbs;
|
||||
CBS_init(&cbs, info, info_len);
|
||||
return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_HKDF, EVP_PKEY_OP_DERIVE,
|
||||
EVP_PKEY_CTRL_HKDF_INFO, 0, &cbs);
|
||||
}
|
||||
@@ -14,7 +14,9 @@
|
||||
|
||||
#include <openssl/digest.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/hkdf.h>
|
||||
#include <openssl/kdf.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
@@ -266,6 +268,108 @@ TEST(HKDFTest, TestVectors) {
|
||||
test->ikm_len, test->salt, test->salt_len, test->info,
|
||||
test->info_len));
|
||||
EXPECT_EQ(Bytes(test->out, test->out_len), Bytes(buf, test->out_len));
|
||||
|
||||
// Repeat the test with the OpenSSL compatibility |EVP_PKEY_derive| API.
|
||||
bssl::UniquePtr<EVP_PKEY_CTX> ctx(
|
||||
EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, nullptr));
|
||||
ASSERT_TRUE(ctx);
|
||||
ASSERT_TRUE(EVP_PKEY_derive_init(ctx.get()));
|
||||
ASSERT_TRUE(
|
||||
EVP_PKEY_CTX_hkdf_mode(ctx.get(), EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY));
|
||||
ASSERT_TRUE(EVP_PKEY_CTX_set_hkdf_md(ctx.get(), test->md_func()));
|
||||
ASSERT_TRUE(
|
||||
EVP_PKEY_CTX_set1_hkdf_key(ctx.get(), test->ikm, test->ikm_len));
|
||||
ASSERT_TRUE(
|
||||
EVP_PKEY_CTX_set1_hkdf_salt(ctx.get(), test->salt, test->salt_len));
|
||||
for (bool copy_ctx : {false, true}) {
|
||||
SCOPED_TRACE(copy_ctx);
|
||||
bssl::UniquePtr<EVP_PKEY_CTX> copy;
|
||||
EVP_PKEY_CTX *use_ctx = ctx.get();
|
||||
if (copy_ctx) {
|
||||
copy.reset(EVP_PKEY_CTX_dup(ctx.get()));
|
||||
ASSERT_TRUE(copy);
|
||||
use_ctx = copy.get();
|
||||
}
|
||||
|
||||
// A null output should report the length.
|
||||
prk_len = 0;
|
||||
ASSERT_TRUE(EVP_PKEY_derive(use_ctx, nullptr, &prk_len));
|
||||
EXPECT_EQ(prk_len, test->prk_len);
|
||||
|
||||
// Too small of a buffer should cleanly fail.
|
||||
prk_len = test->prk_len - 1;
|
||||
EXPECT_FALSE(EVP_PKEY_derive(use_ctx, prk, &prk_len));
|
||||
ERR_clear_error();
|
||||
|
||||
// Test the correct buffer size.
|
||||
OPENSSL_memset(prk, 0, sizeof(prk));
|
||||
prk_len = test->prk_len;
|
||||
ASSERT_TRUE(EVP_PKEY_derive(use_ctx, prk, &prk_len));
|
||||
EXPECT_EQ(Bytes(test->prk, test->prk_len), Bytes(prk, prk_len));
|
||||
|
||||
// Test a larger buffer than necessary.
|
||||
OPENSSL_memset(prk, 0, sizeof(prk));
|
||||
prk_len = test->prk_len + 1;
|
||||
ASSERT_TRUE(EVP_PKEY_derive(use_ctx, prk, &prk_len));
|
||||
EXPECT_EQ(Bytes(test->prk, test->prk_len), Bytes(prk, prk_len));
|
||||
}
|
||||
|
||||
ctx.reset(EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, nullptr));
|
||||
ASSERT_TRUE(ctx);
|
||||
ASSERT_TRUE(EVP_PKEY_derive_init(ctx.get()));
|
||||
ASSERT_TRUE(
|
||||
EVP_PKEY_CTX_hkdf_mode(ctx.get(), EVP_PKEY_HKDEF_MODE_EXPAND_ONLY));
|
||||
ASSERT_TRUE(EVP_PKEY_CTX_set_hkdf_md(ctx.get(), test->md_func()));
|
||||
ASSERT_TRUE(
|
||||
EVP_PKEY_CTX_set1_hkdf_key(ctx.get(), test->prk, test->prk_len));
|
||||
// |info| can be passed in multiple parts.
|
||||
size_t half = test->info_len / 2;
|
||||
ASSERT_TRUE(EVP_PKEY_CTX_add1_hkdf_info(ctx.get(), test->info, half));
|
||||
ASSERT_TRUE(EVP_PKEY_CTX_add1_hkdf_info(ctx.get(), test->info + half,
|
||||
test->info_len - half));
|
||||
for (bool copy_ctx : {false, true}) {
|
||||
SCOPED_TRACE(copy_ctx);
|
||||
bssl::UniquePtr<EVP_PKEY_CTX> copy;
|
||||
EVP_PKEY_CTX *use_ctx = ctx.get();
|
||||
if (copy_ctx) {
|
||||
copy.reset(EVP_PKEY_CTX_dup(ctx.get()));
|
||||
ASSERT_TRUE(copy);
|
||||
use_ctx = copy.get();
|
||||
}
|
||||
OPENSSL_memset(buf, 0, sizeof(buf));
|
||||
size_t len = test->out_len;
|
||||
ASSERT_TRUE(EVP_PKEY_derive(use_ctx, buf, &len));
|
||||
EXPECT_EQ(Bytes(test->out, test->out_len), Bytes(buf, len));
|
||||
}
|
||||
|
||||
ctx.reset(EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, nullptr));
|
||||
ASSERT_TRUE(ctx);
|
||||
ASSERT_TRUE(EVP_PKEY_derive_init(ctx.get()));
|
||||
ASSERT_TRUE(EVP_PKEY_CTX_hkdf_mode(ctx.get(),
|
||||
EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND));
|
||||
ASSERT_TRUE(EVP_PKEY_CTX_set_hkdf_md(ctx.get(), test->md_func()));
|
||||
ASSERT_TRUE(
|
||||
EVP_PKEY_CTX_set1_hkdf_key(ctx.get(), test->ikm, test->ikm_len));
|
||||
ASSERT_TRUE(
|
||||
EVP_PKEY_CTX_set1_hkdf_salt(ctx.get(), test->salt, test->salt_len));
|
||||
// |info| can be passed in multiple parts.
|
||||
ASSERT_TRUE(EVP_PKEY_CTX_add1_hkdf_info(ctx.get(), test->info, half));
|
||||
ASSERT_TRUE(EVP_PKEY_CTX_add1_hkdf_info(ctx.get(), test->info + half,
|
||||
test->info_len - half));
|
||||
for (bool copy_ctx : {false, true}) {
|
||||
SCOPED_TRACE(copy_ctx);
|
||||
bssl::UniquePtr<EVP_PKEY_CTX> copy;
|
||||
EVP_PKEY_CTX *use_ctx = ctx.get();
|
||||
if (copy_ctx) {
|
||||
copy.reset(EVP_PKEY_CTX_dup(ctx.get()));
|
||||
ASSERT_TRUE(copy);
|
||||
use_ctx = copy.get();
|
||||
}
|
||||
OPENSSL_memset(buf, 0, sizeof(buf));
|
||||
size_t len = test->out_len;
|
||||
ASSERT_TRUE(EVP_PKEY_derive(use_ctx, buf, &len));
|
||||
EXPECT_EQ(Bytes(test->out, test->out_len), Bytes(buf, len));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
/* This file is generated by crypto/obj/objects.go. */
|
||||
|
||||
|
||||
#define NUM_NID 963
|
||||
#define NUM_NID 964
|
||||
|
||||
static const uint8_t kObjectData[] = {
|
||||
/* NID_rsadsi */
|
||||
@@ -8781,6 +8781,7 @@ static const ASN1_OBJECT kObjects[NUM_NID] = {
|
||||
{"ED448", "ED448", NID_ED448, 3, &kObjectData[6181], 0},
|
||||
{"X448", "X448", NID_X448, 3, &kObjectData[6184], 0},
|
||||
{"SHA512-256", "sha512-256", NID_sha512_256, 9, &kObjectData[6187], 0},
|
||||
{"HKDF", "hkdf", NID_hkdf, 0, NULL, 0},
|
||||
};
|
||||
|
||||
static const uint16_t kNIDsInShortNameOrder[] = {
|
||||
@@ -8878,6 +8879,7 @@ static const uint16_t kNIDsInShortNameOrder[] = {
|
||||
949 /* ED25519 */,
|
||||
960 /* ED448 */,
|
||||
99 /* GN */,
|
||||
963 /* HKDF */,
|
||||
855 /* HMAC */,
|
||||
780 /* HMAC-MD5 */,
|
||||
781 /* HMAC-SHA1 */,
|
||||
@@ -10096,6 +10098,7 @@ static const uint16_t kNIDsInLongNameOrder[] = {
|
||||
601 /* generic cryptogram */,
|
||||
99 /* givenName */,
|
||||
814 /* gost89-cnt */,
|
||||
963 /* hkdf */,
|
||||
855 /* hmac */,
|
||||
780 /* hmac-md5 */,
|
||||
781 /* hmac-sha1 */,
|
||||
|
||||
@@ -951,3 +951,4 @@ CECPQ2 959
|
||||
ED448 960
|
||||
X448 961
|
||||
sha512_256 962
|
||||
hkdf 963
|
||||
|
||||
@@ -1356,3 +1356,5 @@ secg-scheme 14 3 : dhSinglePass-cofactorDH-sha512kdf-scheme
|
||||
# TLS 1.3 cipher suites do not specify key exchange or authentication.
|
||||
: KxANY : kx-any
|
||||
: AuthANY : auth-any
|
||||
|
||||
: HKDF : hkdf
|
||||
|
||||
@@ -178,6 +178,7 @@ OPENSSL_EXPORT EC_KEY *EVP_PKEY_get1_EC_KEY(const EVP_PKEY *pkey);
|
||||
#define EVP_PKEY_EC NID_X9_62_id_ecPublicKey
|
||||
#define EVP_PKEY_ED25519 NID_ED25519
|
||||
#define EVP_PKEY_X25519 NID_X25519
|
||||
#define EVP_PKEY_HKDF NID_hkdf
|
||||
|
||||
// EVP_PKEY_assign sets the underlying key of |pkey| to |key|, which must be of
|
||||
// the given type. It returns one if successful or zero if the |type| argument
|
||||
@@ -665,11 +666,11 @@ OPENSSL_EXPORT int EVP_PKEY_derive_init(EVP_PKEY_CTX *ctx);
|
||||
// success and zero on error.
|
||||
OPENSSL_EXPORT int EVP_PKEY_derive_set_peer(EVP_PKEY_CTX *ctx, EVP_PKEY *peer);
|
||||
|
||||
// EVP_PKEY_derive derives a shared key between the two keys configured in
|
||||
// |ctx|. If |key| is non-NULL then, on entry, |out_key_len| must contain the
|
||||
// amount of space at |key|. If sufficient then the shared key will be written
|
||||
// to |key| and |*out_key_len| will be set to the length. If |key| is NULL then
|
||||
// |out_key_len| will be set to the maximum length.
|
||||
// EVP_PKEY_derive derives a shared key from |ctx|. If |key| is non-NULL then,
|
||||
// on entry, |out_key_len| must contain the amount of space at |key|. If
|
||||
// sufficient then the shared key will be written to |key| and |*out_key_len|
|
||||
// will be set to the length. If |key| is NULL then |out_key_len| will be set to
|
||||
// the maximum length.
|
||||
//
|
||||
// WARNING: Setting |out| to NULL only gives the maximum size of the key. The
|
||||
// actual key may be smaller.
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
/* Copyright (c) 2022, 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_KDF_H
|
||||
#define OPENSSL_HEADER_KDF_H
|
||||
|
||||
#include <openssl/base.h>
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
// KDF support for EVP.
|
||||
|
||||
|
||||
// HKDF-specific functions.
|
||||
//
|
||||
// The following functions are provided for OpenSSL compatibility. Prefer the
|
||||
// HKDF functions in <openssl/hkdf.h>. In each, |ctx| must be created with
|
||||
// |EVP_PKEY_CTX_new_id| with |EVP_PKEY_HKDF| and then initialized with
|
||||
// |EVP_PKEY_derive_init|.
|
||||
|
||||
// EVP_PKEY_HKDEF_MODE_* define "modes" for use with |EVP_PKEY_CTX_hkdf_mode|.
|
||||
// The mispelling of "HKDF" as "HKDEF" is intentional for OpenSSL compatibility.
|
||||
#define EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND 0
|
||||
#define EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY 1
|
||||
#define EVP_PKEY_HKDEF_MODE_EXPAND_ONLY 2
|
||||
|
||||
// EVP_PKEY_CTX_hkdf_mode configures which HKDF operation to run. It returns one
|
||||
// on success and zero on error. |mode| must be one of |EVP_PKEY_HKDEF_MODE_*|.
|
||||
// By default, the mode is |EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND|.
|
||||
//
|
||||
// If |mode| is |EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND| or
|
||||
// |EVP_PKEY_HKDEF_MODE_EXPAND_ONLY|, the output is variable-length.
|
||||
// |EVP_PKEY_derive| uses the size of the output buffer as the output length for
|
||||
// HKDF-Expand.
|
||||
//
|
||||
// WARNING: Although this API calls it a "mode", HKDF-Extract and HKDF-Expand
|
||||
// are distinct operations with distinct inputs and distinct kinds of keys.
|
||||
// Callers should not pass input secrets for one operation into the other.
|
||||
OPENSSL_EXPORT int EVP_PKEY_CTX_hkdf_mode(EVP_PKEY_CTX *ctx, int mode);
|
||||
|
||||
// EVP_PKEY_CTX_set_hkdf_md sets |md| as the digest to use with HKDF. It returns
|
||||
// one on success and zero on error.
|
||||
OPENSSL_EXPORT int EVP_PKEY_CTX_set_hkdf_md(EVP_PKEY_CTX *ctx,
|
||||
const EVP_MD *md);
|
||||
|
||||
// EVP_PKEY_CTX_set1_hkdf_key configures HKDF to use |key_len| bytes from |key|
|
||||
// as the "key", described below. It returns one on success and zero on error.
|
||||
//
|
||||
// Which input is the key depends on the "mode" (see |EVP_PKEY_CTX_hkdf_mode|).
|
||||
// If |EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND| or
|
||||
// |EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY|, this function specifies the input keying
|
||||
// material (IKM) for HKDF-Extract. If |EVP_PKEY_HKDEF_MODE_EXPAND_ONLY|, it
|
||||
// instead specifies the pseudorandom key (PRK) for HKDF-Expand.
|
||||
OPENSSL_EXPORT int EVP_PKEY_CTX_set1_hkdf_key(EVP_PKEY_CTX *ctx,
|
||||
const uint8_t *key,
|
||||
size_t key_len);
|
||||
|
||||
// EVP_PKEY_CTX_set1_hkdf_salt configures HKDF to use |salt_len| bytes from
|
||||
// |salt| as the salt parameter to HKDF-Extract. It returns one on success and
|
||||
// zero on error. If performing HKDF-Expand only, this parameter is ignored.
|
||||
OPENSSL_EXPORT int EVP_PKEY_CTX_set1_hkdf_salt(EVP_PKEY_CTX *ctx,
|
||||
const uint8_t *salt,
|
||||
size_t salt_len);
|
||||
|
||||
// EVP_PKEY_CTX_add1_hkdf_info appends |info_len| bytes from |info| to the info
|
||||
// parameter used with HKDF-Expand. It returns one on success and zero on error.
|
||||
// If performing HKDF-Extract only, this parameter is ignored.
|
||||
OPENSSL_EXPORT int EVP_PKEY_CTX_add1_hkdf_info(EVP_PKEY_CTX *ctx,
|
||||
const uint8_t *info,
|
||||
size_t info_len);
|
||||
|
||||
|
||||
#if defined(__cplusplus)
|
||||
} // extern C
|
||||
#endif
|
||||
|
||||
#endif // OPENSSL_HEADER_KDF_H
|
||||
@@ -4251,6 +4251,10 @@ extern "C" {
|
||||
#define NID_sha512_256 962
|
||||
#define OBJ_sha512_256 2L, 16L, 840L, 1L, 101L, 3L, 4L, 2L, 6L
|
||||
|
||||
#define SN_hkdf "HKDF"
|
||||
#define LN_hkdf "hkdf"
|
||||
#define NID_hkdf 963
|
||||
|
||||
|
||||
#if defined(__cplusplus)
|
||||
} /* extern C */
|
||||
|
||||
+2
-1
@@ -48,7 +48,8 @@
|
||||
"include/openssl/cipher.h",
|
||||
"include/openssl/aead.h",
|
||||
"include/openssl/evp.h",
|
||||
"include/openssl/hpke.h"
|
||||
"include/openssl/hpke.h",
|
||||
"include/openssl/kdf.h"
|
||||
]
|
||||
},{
|
||||
"Name": "Legacy ASN.1 and X.509 implementation (documentation in progress)",
|
||||
|
||||
Reference in New Issue
Block a user