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:
David Benjamin
2022-06-05 00:31:29 -04:00
committed by Boringssl LUCI CQ
parent 77dc23983f
commit 44872e1c74
12 changed files with 463 additions and 7 deletions
+1
View File
@@ -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
+1
View File
@@ -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) {
+6
View File
@@ -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)
+241
View File
@@ -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);
}
+104
View File
@@ -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));
}
}
}
+4 -1
View File
@@ -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 */,
+1
View File
@@ -951,3 +951,4 @@ CECPQ2 959
ED448 960
X448 961
sha512_256 962
hkdf 963
+2
View File
@@ -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
+6 -5
View File
@@ -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.
+91
View File
@@ -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
+4
View File
@@ -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
View File
@@ -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)",