openssl: add kdf_kb_hmac_derive()
Add function to perform key-based (KB) key derivation function (KDF) using hash-based message authentication code (HMAC). Also alphabetize openssl-util.c header list, and include string-util.h.
This commit is contained in:
@@ -1,9 +1,10 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include "fd-util.h"
|
||||
#include "openssl-util.h"
|
||||
#include "alloc-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "hexdecoct.h"
|
||||
#include "openssl-util.h"
|
||||
#include "string-util.h"
|
||||
|
||||
#if HAVE_OPENSSL
|
||||
/* For each error in the the Openssl thread error queue, log the provided message and the Openssl error
|
||||
@@ -236,6 +237,92 @@ int openssl_hmac_many(
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Perform Key-Based HMAC KDF. The mode must be "COUNTER" or "FEEDBACK". The parameter naming is from the
|
||||
* Openssl api, and maps to SP800-108 naming as "...key, salt, info, and seed correspond to KI, Label,
|
||||
* Context, and IV (respectively)...". The derive_size parameter specifies how many bytes are derived.
|
||||
*
|
||||
* For more details see: https://www.openssl.org/docs/manmaster/man7/EVP_KDF-KB.html */
|
||||
int kdf_kb_hmac_derive(
|
||||
const char *mode,
|
||||
const char *digest,
|
||||
const void *key,
|
||||
size_t key_size,
|
||||
const void *salt,
|
||||
size_t salt_size,
|
||||
const void *info,
|
||||
size_t info_size,
|
||||
const void *seed,
|
||||
size_t seed_size,
|
||||
size_t derive_size,
|
||||
void **ret) {
|
||||
|
||||
#if OPENSSL_VERSION_MAJOR >= 3
|
||||
assert(mode);
|
||||
assert(strcaseeq(mode, "COUNTER") || strcaseeq(mode, "FEEDBACK"));
|
||||
assert(digest);
|
||||
assert(key || key_size == 0);
|
||||
assert(salt || salt_size == 0);
|
||||
assert(info || info_size == 0);
|
||||
assert(seed || seed_size == 0);
|
||||
assert(derive_size > 0);
|
||||
assert(ret);
|
||||
|
||||
_cleanup_(EVP_KDF_freep) EVP_KDF *kdf = EVP_KDF_fetch(NULL, "KBKDF", NULL);
|
||||
if (!kdf)
|
||||
return log_openssl_errors("Failed to create new EVP_KDF");
|
||||
|
||||
_cleanup_(EVP_KDF_CTX_freep) EVP_KDF_CTX *ctx = EVP_KDF_CTX_new(kdf);
|
||||
if (!ctx)
|
||||
return log_openssl_errors("Failed to create new EVP_KDF_CTX");
|
||||
|
||||
_cleanup_(OSSL_PARAM_BLD_freep) OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new();
|
||||
if (!bld)
|
||||
return log_openssl_errors("Failed to create new OSSL_PARAM_BLD");
|
||||
|
||||
if (!OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_KDF_PARAM_MAC, (char*) "HMAC", 0))
|
||||
return log_openssl_errors("Failed to add KDF-KB OSSL_KDF_PARAM_MAC");
|
||||
|
||||
if (!OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_KDF_PARAM_MODE, (char*) mode, 0))
|
||||
return log_openssl_errors("Failed to add KDF-KB OSSL_KDF_PARAM_MODE");
|
||||
|
||||
if (!OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_KDF_PARAM_DIGEST, (char*) digest, 0))
|
||||
return log_openssl_errors("Failed to add KDF-KB OSSL_KDF_PARAM_DIGEST");
|
||||
|
||||
if (key)
|
||||
if (!OSSL_PARAM_BLD_push_octet_string(bld, OSSL_KDF_PARAM_KEY, (char*) key, key_size))
|
||||
return log_openssl_errors("Failed to add KDF-KB OSSL_KDF_PARAM_KEY");
|
||||
|
||||
if (salt)
|
||||
if (!OSSL_PARAM_BLD_push_octet_string(bld, OSSL_KDF_PARAM_SALT, (char*) salt, salt_size))
|
||||
return log_openssl_errors("Failed to add KDF-KB OSSL_KDF_PARAM_SALT");
|
||||
|
||||
if (info)
|
||||
if (!OSSL_PARAM_BLD_push_octet_string(bld, OSSL_KDF_PARAM_INFO, (char*) info, info_size))
|
||||
return log_openssl_errors("Failed to add KDF-KB OSSL_KDF_PARAM_INFO");
|
||||
|
||||
if (seed)
|
||||
if (!OSSL_PARAM_BLD_push_octet_string(bld, OSSL_KDF_PARAM_SEED, (char*) seed, seed_size))
|
||||
return log_openssl_errors("Failed to add KDF-KB OSSL_KDF_PARAM_SEED");
|
||||
|
||||
_cleanup_(OSSL_PARAM_freep) OSSL_PARAM *params = OSSL_PARAM_BLD_to_param(bld);
|
||||
if (!params)
|
||||
return log_openssl_errors("Failed to build KDF-KB OSSL_PARAM");
|
||||
|
||||
_cleanup_free_ void *buf = malloc(derive_size);
|
||||
if (!buf)
|
||||
return log_oom_debug();
|
||||
|
||||
if (EVP_KDF_derive(ctx, buf, derive_size, params) <= 0)
|
||||
return log_openssl_errors("Openssl KDF-KB derive failed");
|
||||
|
||||
*ret = TAKE_PTR(buf);
|
||||
|
||||
return 0;
|
||||
#else
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "KDF-KB requires openssl >= 3.");
|
||||
#endif
|
||||
}
|
||||
|
||||
int rsa_encrypt_bytes(
|
||||
EVP_PKEY *pkey,
|
||||
const void *decrypted_key,
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
# endif
|
||||
# if OPENSSL_VERSION_MAJOR >= 3
|
||||
# include <openssl/core_names.h>
|
||||
# include <openssl/kdf.h>
|
||||
# include <openssl/param_build.h>
|
||||
# endif
|
||||
|
||||
@@ -40,6 +41,8 @@ DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(SSL*, SSL_free, NULL);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(BIO*, BIO_free, NULL);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EVP_MD_CTX*, EVP_MD_CTX_free, NULL);
|
||||
#if OPENSSL_VERSION_MAJOR >= 3
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EVP_KDF*, EVP_KDF_free, NULL);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EVP_KDF_CTX*, EVP_KDF_CTX_free, NULL);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EVP_MAC*, EVP_MAC_free, NULL);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EVP_MAC_CTX*, EVP_MAC_CTX_free, NULL);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EVP_MD*, EVP_MD_free, NULL);
|
||||
@@ -74,6 +77,8 @@ static inline int openssl_hmac(const char *digest_alg, const void *key, size_t k
|
||||
return openssl_hmac_many(digest_alg, key, key_size, &IOVEC_MAKE((void*) buf, len), 1, ret_digest, ret_digest_size);
|
||||
}
|
||||
|
||||
int kdf_kb_hmac_derive(const char *mode, const char *digest, const void *key, size_t key_size, const void *salt, size_t salt_size, const void *info, size_t info_size, const void *seed, size_t seed_size, size_t derive_size, void **ret);
|
||||
|
||||
int rsa_encrypt_bytes(EVP_PKEY *pkey, const void *decrypted_key, size_t decrypted_key_size, void **ret_encrypt_key, size_t *ret_encrypt_key_size);
|
||||
|
||||
int rsa_oaep_encrypt_bytes(const EVP_PKEY *pkey, const char *digest_alg, const char *label, const void *decrypted_key, size_t decrypted_key_size, void **ret_encrypt_key, size_t *ret_encrypt_key_size);
|
||||
|
||||
@@ -296,4 +296,20 @@ TEST(hmac_many) {
|
||||
DEFINE_HMAC_SHA256_TEST(key3, "5BE1F4D9C2AFAA2BB3F58FCE967BC7D3084BB8F512659875BDA634991145B0F0", i1, i1, i1, i4, i4, i4, i4, i3, i3, i2);
|
||||
}
|
||||
|
||||
TEST(kdf_kb_hmac_derive) {
|
||||
#if OPENSSL_VERSION_MAJOR >= 3
|
||||
_cleanup_free_ void *derived_key = NULL;
|
||||
|
||||
DEFINE_HEX_PTR(key, "d7ac57124f28371eacaec475b74869d26b4cd64586412a607ce0a9e0c63d468c");
|
||||
const char *salt = "salty chocolate";
|
||||
DEFINE_HEX_PTR(info, "6721a2012d9554f5a64593ed3eaa8fe15e6a21e1c8c8736ea4d234eb55b9e31a");
|
||||
DEFINE_HEX_PTR(expected_derived_key, "A9DA9CEEB9578DBE7DD2862F82898B086E85FF2D10C4E8EC5BD99D0D7F003A2DE1574EB4BD789C03EF5235259BCB3A009DA303EA4DB4CA6BF507DB7C5A063279");
|
||||
|
||||
assert_se(kdf_kb_hmac_derive("COUNTER", "SHA256", key, key_len, salt, strlen(salt), info, info_len, /* seed= */ NULL, /* seed_size= */ 0, 64, &derived_key) >= 0);
|
||||
assert_se(memcmp_nn(derived_key, 64, expected_derived_key, expected_derived_key_len) == 0);
|
||||
#else
|
||||
log_tests_skipped("KDF-KB requires Openssl >= 3");
|
||||
#endif
|
||||
}
|
||||
|
||||
DEFINE_TEST_MAIN(LOG_DEBUG);
|
||||
|
||||
Reference in New Issue
Block a user