From 36878956e5338dc9e462f2dbe2874ef207e07485 Mon Sep 17 00:00:00 2001 From: Sean McGrail Date: Fri, 24 May 2024 20:40:21 +0000 Subject: [PATCH] One-step key derivation implementation --- crypto/CMakeLists.txt | 1 + crypto/fipsmodule/bcm.c | 2 +- crypto/fipsmodule/kdf/kdf_test.cc | 58 +++++ crypto/fipsmodule/kdf/sskdf.c | 315 +++++++++++++++++++++++++++ crypto/fipsmodule/kdf/test/sskdf.txt | 183 ++++++++++++++++ include/openssl/kdf.h | 20 ++ sources.cmake | 1 + 7 files changed, 579 insertions(+), 1 deletion(-) create mode 100644 crypto/fipsmodule/kdf/kdf_test.cc create mode 100644 crypto/fipsmodule/kdf/sskdf.c create mode 100644 crypto/fipsmodule/kdf/test/sskdf.txt diff --git a/crypto/CMakeLists.txt b/crypto/CMakeLists.txt index ce7524f2c40..3aaf8f3c039 100644 --- a/crypto/CMakeLists.txt +++ b/crypto/CMakeLists.txt @@ -731,6 +731,7 @@ if(BUILD_TESTING) fipsmodule/ec/ec_test.cc fipsmodule/ec/p256-nistz_test.cc fipsmodule/ecdsa/ecdsa_test.cc + fipsmodule/kdf/kdf_test.cc fipsmodule/md5/md5_test.cc fipsmodule/modes/gcm_test.cc fipsmodule/modes/xts_test.cc diff --git a/crypto/fipsmodule/bcm.c b/crypto/fipsmodule/bcm.c index 3915104447b..c009326dfd9 100644 --- a/crypto/fipsmodule/bcm.c +++ b/crypto/fipsmodule/bcm.c @@ -114,6 +114,7 @@ #include "evp/p_rsa.c" #include "hkdf/hkdf.c" #include "hmac/hmac.c" +#include "kdf/sskdf.c" #include "md4/md4.c" #include "md5/md5.c" #include "modes/cbc.c" @@ -145,7 +146,6 @@ #include "sshkdf/sshkdf.c" #include "tls/kdf.c" - #if defined(BORINGSSL_FIPS) #if !defined(OPENSSL_ASAN) diff --git a/crypto/fipsmodule/kdf/kdf_test.cc b/crypto/fipsmodule/kdf/kdf_test.cc new file mode 100644 index 00000000000..122e23bd156 --- /dev/null +++ b/crypto/fipsmodule/kdf/kdf_test.cc @@ -0,0 +1,58 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 OR ISC + +#include +#include +#include +#include "../../test/file_test.h" +#include "../../test/test_util.h" + +#include + +TEST(SSKDFTest, TestVectors) { + FileTestGTest("crypto/fipsmodule/kdf/test/sskdf.txt", [](FileTest *t) { + const EVP_MD *md; + std::string hash; + ASSERT_TRUE(t->GetAttribute(&hash, "HASH")); + if (hash == "SHA1") { + md = EVP_sha1(); + } else if (hash == "SHA-256") { + md = EVP_sha256(); + } else if (hash == "SHA-384") { + md = EVP_sha384(); + } else if (hash == "SHA-512") { + md = EVP_sha512(); + } else { + FAIL() << "Unknown HASH=" + hash; + } + + std::vector secret, info, expect; + + ASSERT_TRUE(t->GetBytes(&secret, "SECRET")); + ASSERT_TRUE(t->GetBytes(&info, "INFO")); + ASSERT_TRUE(t->GetBytes(&expect, "EXPECT")); + + std::vector out(expect.size()); + + std::string variant; + ASSERT_TRUE(t->GetAttribute(&variant, "VARIANT")); + if (variant == "DIGEST") { + ASSERT_TRUE(SSKDF_DIGEST(out.data(), out.size(), md, secret.data(), + secret.size(), info.data(), info.size())); + } else if (variant == "HMAC") { + if (t->HasAttribute("SALT")) { + std::vector salt; + ASSERT_TRUE(t->GetBytes(&salt, "SALT")); + ASSERT_TRUE(SSKDF_HMAC(out.data(), out.size(), md, secret.data(), + secret.size(), info.data(), info.size(), + salt.data(), salt.size())); + } else { + ASSERT_TRUE(SSKDF_HMAC(out.data(), out.size(), md, secret.data(), + secret.size(), info.data(), info.size(), NULL, + 0)); + } + } + ASSERT_EQ(Bytes(expect.data(), expect.size()), + Bytes(out.data(), out.size())); + }); +} diff --git a/crypto/fipsmodule/kdf/sskdf.c b/crypto/fipsmodule/kdf/sskdf.c new file mode 100644 index 00000000000..80bf4b6c8f0 --- /dev/null +++ b/crypto/fipsmodule/kdf/sskdf.c @@ -0,0 +1,315 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 OR ISC + +#include +#include +#include +#include +#include + +typedef struct { + void *data; +} SSKDF_VARIANT_CTX; + +typedef struct { + const EVP_MD *digest; + EVP_MD_CTX *ctx; +} SSKDF_VARIANT_DIGEST_CTX; + +typedef struct { + HMAC_CTX *ctx; +} SSKDF_VARIANT_HMAC_CTX; + +typedef struct { + size_t (*size)(SSKDF_VARIANT_CTX *ctx); + int (*compute)(SSKDF_VARIANT_CTX *ctx, uint8_t *out, size_t out_len, + const uint8_t counter[4], const uint8_t *secret, + size_t secret_len, const uint8_t *info, size_t info_len); +} SSKDF_VARIANT; + +static int SSKDF_VARIANT_DIGEST_CTX_init(SSKDF_VARIANT_CTX *ctx, + const EVP_MD *digest) { + SSKDF_VARIANT_DIGEST_CTX *variant_ctx = NULL; + EVP_MD_CTX *md_ctx = NULL; + + int ret = 0; + + if (!ctx || !digest) { + goto err; + } + + variant_ctx = OPENSSL_malloc(sizeof(SSKDF_VARIANT_DIGEST_CTX)); + if (!variant_ctx) { + goto err; + } + + md_ctx = EVP_MD_CTX_new(); + if (!md_ctx) { + goto err; + } + + ret = 1; + variant_ctx->digest = digest; + variant_ctx->ctx = md_ctx; + ctx->data = variant_ctx; + + return ret; + +err: + EVP_MD_CTX_free(md_ctx); + OPENSSL_free(variant_ctx); + + return ret; +} + + + +static void SSKDF_VARIANT_DIGEST_CTX_cleanup(SSKDF_VARIANT_CTX *ctx) { + if (!ctx) { + return; + } + SSKDF_VARIANT_DIGEST_CTX *variant_ctx = (SSKDF_VARIANT_DIGEST_CTX *)ctx->data; + if (!ctx->data) { + return; + } + EVP_MD_CTX_free(variant_ctx->ctx); + OPENSSL_free(variant_ctx); + ctx->data = NULL; +} + +static int SSKDF_VARIANT_HMAC_CTX_init(SSKDF_VARIANT_CTX *ctx, + const EVP_MD *digest, + const uint8_t *salt, size_t salt_len) { + SSKDF_VARIANT_HMAC_CTX *variant_ctx = NULL; + HMAC_CTX *hmac_ctx = NULL; + + int ret = 0; + + if (!ctx || !digest) { + goto err; + } + + variant_ctx = OPENSSL_malloc(sizeof(SSKDF_VARIANT_HMAC_CTX)); + if (!variant_ctx) { + goto err; + } + + hmac_ctx = HMAC_CTX_new(); + if (!hmac_ctx) { + goto err; + } + + if (!HMAC_Init_ex(hmac_ctx, salt, salt_len, digest, NULL)) { + goto err; + } + + ret = 1; + variant_ctx->ctx = hmac_ctx; + ctx->data = variant_ctx; + + return ret; + +err: + HMAC_CTX_free(hmac_ctx); + OPENSSL_free(variant_ctx); + + return ret; +} + + + +static void SSKDF_VARIANT_HMAC_CTX_cleanup(SSKDF_VARIANT_CTX *ctx) { + if (!ctx) { + return; + } + SSKDF_VARIANT_HMAC_CTX *hmac_ctx = (SSKDF_VARIANT_HMAC_CTX *)ctx->data; + if (!hmac_ctx) { + return; + } + HMAC_CTX_free(hmac_ctx->ctx); + OPENSSL_free(hmac_ctx); + ctx->data = NULL; +} + +static size_t sskdf_variant_digest_size(SSKDF_VARIANT_CTX *ctx) { + if (!ctx || !ctx->data) { + return 0; + } + SSKDF_VARIANT_DIGEST_CTX *variant_ctx = (SSKDF_VARIANT_DIGEST_CTX *)ctx->data; + return EVP_MD_size(variant_ctx->digest); +} + +static int sskdf_variant_digest_compute(SSKDF_VARIANT_CTX *ctx, uint8_t *out, + size_t out_len, + const uint8_t counter[4], + const uint8_t *secret, + size_t secret_len, const uint8_t *info, + size_t info_len) { + if (!ctx || !ctx->data || !out || !counter || !secret || !info) { + return 0; + } + + SSKDF_VARIANT_DIGEST_CTX *variant_ctx = (SSKDF_VARIANT_DIGEST_CTX *)ctx->data; + + if (!EVP_MD_CTX_reset(variant_ctx->ctx) || + !EVP_DigestInit_ex(variant_ctx->ctx, variant_ctx->digest, NULL) || + !EVP_DigestUpdate(variant_ctx->ctx, &counter[0], 4) || + !EVP_DigestUpdate(variant_ctx->ctx, secret, secret_len) || + !EVP_DigestUpdate(variant_ctx->ctx, info, info_len) || + !EVP_DigestFinal(variant_ctx->ctx, out, NULL)) { + // TODO: put error on queue + return 0; + } + + return 1; +} + +static size_t sskdf_variant_hmac_size(SSKDF_VARIANT_CTX *ctx) { + if (!ctx || !ctx->data) { + // TODO: put error on queue + return 0; + } + SSKDF_VARIANT_HMAC_CTX *variant_ctx = (SSKDF_VARIANT_HMAC_CTX *)ctx->data; + if (!variant_ctx) { + // TODO: put error on queue + return 0; + } + return HMAC_size(variant_ctx->ctx); +} + +static int sskdf_variant_hmac_compute(SSKDF_VARIANT_CTX *ctx, uint8_t *out, + size_t out_len, const uint8_t counter[4], + const uint8_t *secret, size_t secret_len, + const uint8_t *info, size_t info_len) { + if (!ctx || !ctx->data || !out || !counter || !secret || !info) { + return 0; + } + + SSKDF_VARIANT_HMAC_CTX *variant_ctx = (SSKDF_VARIANT_HMAC_CTX *)ctx->data; + + + if (!HMAC_Init_ex(variant_ctx->ctx, NULL, 0, NULL, NULL) || + !HMAC_Update(variant_ctx->ctx, &counter[0], 4) || + !HMAC_Update(variant_ctx->ctx, secret, secret_len) || + !HMAC_Update(variant_ctx->ctx, info, info_len) || + !HMAC_Final(variant_ctx->ctx, out, NULL)) { + return 0; + } + + return 1; +} + +static const SSKDF_VARIANT SSKDF_VARIANT_DIGEST = { + .size = sskdf_variant_digest_size, + .compute = sskdf_variant_digest_compute, +}; + +static const SSKDF_VARIANT SSKDF_VARIANT_HMAC = { + .size = sskdf_variant_hmac_size, + .compute = sskdf_variant_hmac_compute, +}; + +static int SSKDF(const SSKDF_VARIANT *variant, SSKDF_VARIANT_CTX *ctx, + uint8_t *out_key, size_t out_len, const uint8_t *secret, + size_t secret_len, const uint8_t *info, size_t info_len) { + int ret = 0; + + if (!ctx) { + abort(); + } + + size_t h_len = variant->size(ctx); + if (!h_len) { + return 0; + } + assert(h_len <= EVP_MAX_MD_SIZE); + + uint64_t n = (out_len + h_len - 1) / h_len; + + size_t done = 0; + + if (out_len + h_len < out_len || n > UINT32_MAX) { + goto err; + } + + // UINT32_MAX is sufficient to cap the approved algorithms to not exceed the + // max_H_inputBits hash(x) or HMAC-hash(salt, x). + // See Section 4.2 Table 1 and 2 + // https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Cr2.pdf + if (4 + secret_len + info_len > UINT32_MAX) { + // TODO: put error on queue + goto err; + } + + // TODO: Abstract buffer size, if we ever need to support KMAC this could be + // variable. Currently sufficient for HMAC and digest variants + uint8_t previous[EVP_MAX_MD_SIZE]; + + for (uint32_t i = 0; i < n; i++) { + uint8_t counter[4]; // counter == 4 bytes + size_t todo; + + CRYPTO_store_u32_be(&counter[0], i + 1); + + if (!variant->compute(ctx, &previous[0], h_len, counter, secret, secret_len, + info, info_len)) { + goto err; + } + + todo = h_len; + if (todo > out_len - done) { + todo = out_len - done; + } + OPENSSL_memcpy(out_key + done, previous, todo); + done += todo; + } + + ret = 1; + +err: + return ret; +} + +int SSKDF_DIGEST(uint8_t *out_key, size_t out_len, const EVP_MD *digest, + const uint8_t *secret, size_t secret_len, const uint8_t *info, + size_t info_len) { + SSKDF_VARIANT_CTX ctx; + int ret = 0; + + if (!SSKDF_VARIANT_DIGEST_CTX_init(&ctx, digest)) { + return 0; + } + + if (!SSKDF(&SSKDF_VARIANT_DIGEST, &ctx, out_key, out_len, secret, secret_len, + info, info_len)) { + goto end; + } + + ret = 1; + +end: + SSKDF_VARIANT_DIGEST_CTX_cleanup(&ctx); + return ret; +} + +int SSKDF_HMAC(uint8_t *out_key, size_t out_len, const EVP_MD *digest, + const uint8_t *secret, size_t secret_len, const uint8_t *info, + size_t info_len, const uint8_t *salt, size_t salt_len) { + SSKDF_VARIANT_CTX ctx; + int ret = 0; + + if (!SSKDF_VARIANT_HMAC_CTX_init(&ctx, digest, salt, salt_len)) { + return 0; + } + + if (!SSKDF(&SSKDF_VARIANT_HMAC, &ctx, out_key, out_len, secret, secret_len, + info, info_len)) { + goto end; + } + + ret = 1; + +end: + SSKDF_VARIANT_HMAC_CTX_cleanup(&ctx); + return ret; +} diff --git a/crypto/fipsmodule/kdf/test/sskdf.txt b/crypto/fipsmodule/kdf/test/sskdf.txt new file mode 100644 index 00000000000..94428ee9b8c --- /dev/null +++ b/crypto/fipsmodule/kdf/test/sskdf.txt @@ -0,0 +1,183 @@ +HASH=SHA1 +VARIANT=DIGEST +SECRET=81f3d2ad1f70fd67a374547d59506a04d545f4e869f00fa0 +INFO=434156536964e63969525e54d806789d7121a1b2c3d4e581597a0e979d5c99a79b1789b41ae57fef5b916f85a1e449 +EXPECT=6ff62398511a8a243513 + +HASH=SHA1 +VARIANT=DIGEST +SECRET=1b36653c8d00d4742982e7347e3591b04a6507ffff2d60cf +INFO=4341565369647ebfbe28a821381fd4acacbda1b2c3d4e59f086148af5b212020587c5bca84b1cc856ee790473f6f43 +EXPECT=190109cefea280e8413d + +HASH=SHA1 +VARIANT=DIGEST +SECRET=805ed191d06b9e65bb866babe3d81dfdaf50170a57b6fd72 +INFO=43415653696432a993134a35b0bb99b23c50a1b2c3d4e53948d820d0da600eb36a3d0b4074508306d74879cccec51b +EXPECT=5bade971de631bc7d912 + +HASH=SHA1 +VARIANT=DIGEST +SECRET=d3cd77a44a1e951b23b698b04c3f342780b00917c9c2c2fb +INFO=434156536964600097e08aedd076438dcb2fa1b2c3d4e52880245fa69c4ea8b9dc5e4d8f4984c98855c1303aca04c1 +EXPECT=f53465669cf0a327c2e3 + +HASH=SHA-256 +VARIANT=DIGEST +SECRET=a4801c1ca39cc74b7df5c127593e3482f4c4e4e945753076 +INFO=4341565369649a34a5c3879740e3907add7ba1b2c3d4e5658aaff1cc4bd0aa8e7a215ad1f61873ce67cd7b83225010 +EXPECT=13229b870d7e49795f34 + +HASH=SHA-256 +VARIANT=DIGEST +SECRET=008392d899edd742510212be86e6ba5eede4f354b034b2f4df0e6f5a0003f3b334aebbd3 +INFO=434156536964808e2f1e4b8a68301e33483b423d0a9b6d15a1b2c3d4e5f3c9e8598a950b971c402d0d65a290845fde +EXPECT=2041f42703fd9ff370373fef399009cd + +HASH=SHA-256 +VARIANT=DIGEST +SECRET=0189e7c2133207b3f37741fd596d532bfd37a62b2f6577678f42e0643300a3f20c1f4bed +INFO=434156536964cc2ac48877251aef42fd21686b0aa425a838a1b2c3d4e5da4e1b22f244bdf689861da265954b433e14 +EXPECT=247b5fb8977bf202b9c6fc81e07c7deb + +HASH=SHA-256 +VARIANT=DIGEST +SECRET=07ce5c270ad7d39b0d4c594eb66620fbfc424ee8464c6c12cff08307d34f74082b7a9f54 +INFO=434156536964bd813bb05390d7bbd94ff0b3687c157ca53da1b2c3d4e5a42c7a0c533d316edcd318fbac3a9f754f5e +EXPECT=fab546ee7a66c58e0a0501ce63e0731f + +HASH=SHA-384 +VARIANT=DIGEST +SECRET=016995ef4b250d677dc674577427a0603b5d2185ee66e88c2f450c47727cfafa5707c5b74f9d6a2403f571094eaa7ee54bb251de +INFO=434156536964ac9a3236f3d2a4cda1ada36079b3275556220286c036169ebda8a1b2c3d4e575408962a5a3c8afeb92 +EXPECT=86a4a396d8819edfab9784f668b997fe9a1da99f6f08c5b1 + +HASH=SHA-384 +VARIANT=DIGEST +SECRET=00c12d6863ff167766e1ee061eb53109f281d5ffb0593939fb37281354110cffa0f73f2f3761524f86d047e57f8e3fa04f7ba9ea +INFO=43415653696495b4b25586d6a8a0653ea547ce23d757ee125ff89f889e9cd4c0a1b2c3d4e50ebd18fdde3f0429c876 +EXPECT=3ca777a800ff751ecfc610b08ce3506aab4541cba38b1cb8 + +HASH=SHA-384 +VARIANT=DIGEST +SECRET=012060eb88ab29fa77688ab0ea23fcd21af79456598b82f5212e7e0b835fecca08c6a6fd5d49a264cc6d66f93bf8a436c1fadd60 +INFO=43415653696433a0c05720cd9ae757b38a71e9abd634e90fbd842bf15b1d4c0da1b2c3d4e54e7d6c1bc80533e7452d +EXPECT=241e45e9cbe075abe0a0aed94834d97f704d4a62da1889ec + +HASH=SHA-384 +VARIANT=DIGEST +SECRET=01b11eb41c758b28cb326d78e33ffcacd5ace2ab395281f791fd4f7a80649fd47d4d091bb9cc1c725a4c32715165291b5f522a1a +INFO=4341565369647cdaff4407f99eae33795b0aaf968c20b0071dfe9fe0e3f80eb7a1b2c3d4e5457a0daef12445a665f0 +EXPECT=c0f969c63e99d1798f0a52907b6e42c952611940618733c1 + +HASH=SHA-512 +VARIANT=DIGEST +SECRET=017812834e28c2930b612b15de106b241948a823291480cfe2c7515530aff60cd8eee86f6100769a889bbfda985d6fb60e12104c +INFO=4341565369644e1d7bb30359f9dfcf4a622e809a87bf0c78ac5775eb8b54ef66a1b2c3d4e54f288cc26c3a5c84d344 +EXPECT=61b86d9bf5783c89e9a30b4e30d2c0096544c74d1677820f + +HASH=SHA-512 +VARIANT=DIGEST +SECRET=0184c49404209f6c0af846444fb5705da3875c8a84b6f43004e9e6fae6d2faaaef26d0853fe191624b74de855955807077cd1e6a +INFO=43415653696426abad2b9558fc7450a4e2a9416330626c17ad5a7667ba7e64cca1b2c3d4e5b49c2962094b5387f0d1 +EXPECT=76ee4f052b5862138b91de6b57b9f9ab74f8263ef72948eb + +HASH=SHA-512 +VARIANT=DIGEST +SECRET=016774c65fb07b9d3d737d027ae5409999b1a3965c8f9d4b470c50be201e75f9ee6cc6cfe3863d0e683971b92512cfb64b816e24 +INFO=434156536964fa87a7dda67d13f0aded76ef7a62bf5b9ffa25e024691a7e1f40a1b2c3d4e5902e4f6e3f344a95c3f8 +EXPECT=51cad9a349609ad538704ab813d82401a23f2c1c7d429912 + +HASH=SHA-512 +VARIANT=DIGEST +SECRET=0058d0c565a00f423efb4ccc321acddf7b2e24ba9e259c5ac43845e97b1117a8b89a30b02f9421e31c60ebeac22c6b42b95d4a56 +INFO=434156536964f5c1165e63acf905b51ac0bcaf116b51737b49a3f6cb1063b1e3a1b2c3d4e5e150d4c3b125bf032b47 +EXPECT=7abf9a0654a90c18b0d423bb20c3c4d6374c8dfd06446848 + +HASH=SHA-512 +VARIANT=DIGEST +SECRET=005f8c03ac2d9313e2cc5b30dcc9133cbf8c53671af5e80032bb36b9279cc41c8742f859b3c64097ef1ba62a1c4b6d02d9ec1a6e +INFO=4341565369641253e69cd9f2692f10c4d09c1be8d1967445c4e4596ffa61c2cea1b2c3d4e5f776d55088934bc8d5d2 +EXPECT=00059c8673b4d3e269147e91591385d5636e793cc36690ae + +HASH=SHA1 +VARIANT=DIGEST +SECRET=81f3d2ad1f70fd67a374547d59506a04d545f4e869f00fa0 +INFO=434156536964e63969525e54d806789d7121a1b2c3d4e581597a0e979d5c99a79b1789b41ae57fef5b916f85a1e449 +EXPECT=6ff62398511a8a243513781f02d9e50d412c247c84a01dac17f8d8d74bb5ddc5c5d156eb0173e597cab4a276aed4f42d74b5a105666cddd26efc1fa130e1b062f2431c974eca6bc81c8fdc0a78088271cbd3aae0972d37016a293b59fb5656ff169da3ac23cc39723fa887342346fb5859b63ebb86eb19ccff6e314253b9a771 + +HASH=SHA-256 +VARIANT=DIGEST +SECRET=81f3d2ad1f70fd67a374547d59506a04d545f4e869f00fa0 +INFO=434156536964e63969525e54d806789d7121a1b2c3d4e581597a0e979d5c99a79b1789b41ae57fef5b916f85a1e449 +EXPECT=94a283be5d007b1729f8a7ed1a9bf0361435131c4477e750959bd64426c1fa16df07f848e1ba90d8d3196424de928cdb8a5eda08ef03a5ca907b07faa0d4ac096a9dc7c5fa1f931336f864fdd9038b2dda14ca933c722657c90dd1c82c3a99af48fdb599a975498f023424c5a6cfe010dd800e42c55de57a5d75a6cd54e299b9 + +HASH=SHA-384 +VARIANT=DIGEST +SECRET=81f3d2ad1f70fd67a374547d59506a04d545f4e869f00fa0 +INFO=434156536964e63969525e54d806789d7121a1b2c3d4e581597a0e979d5c99a79b1789b41ae57fef5b916f85a1e449 +EXPECT=98989fa5f8de3098dfa089a454c24586f75f5bdc1e860d6088f42d9cc129bb462ae243b7922a6c276891bee5ca79b0744b7ef4cb419db1e4ab80d67c873cb62912cb6cef80f17198e02ff590af59faf17e3128b80879606fa346f14930597005d2be607b08b4361a403a28f18f5bc485a8c53921fbe8adcb35e64d4dc9227a5e + +HASH=SHA-512 +VARIANT=DIGEST +SECRET=81f3d2ad1f70fd67a374547d59506a04d545f4e869f00fa0 +INFO=434156536964e63969525e54d806789d7121a1b2c3d4e581597a0e979d5c99a79b1789b41ae57fef5b916f85a1e449 +EXPECT=8501c55696448de9e6b452cd56b022cba6826e8d4fd3d1f75346ef4698169b2642ffedad53e948ab42b923f54083244879b735e5e478139cb500fa7972d79f6c4cfdbc243f34b37bede60315c7e92500fee77cdd1c6eff97ff6a181d39dfe01350ad1702eb37441256bca3d0ddeb6043daebafc821afa2bae9a5457515ddee56 + +# Tests that follow were sourced from https://github.com/patrickfav/singlestep-kdf + +HASH=SHA-256 +VARIANT=DIGEST +SECRET=4d7920736563726574 +INFO=00000000000000000000000000000000 +EXPECT=5f225b4801843ed861b95f5b0a3afd78473498f0b5cb6d7769e67458e057da8c0311 + +HASH=SHA-256 +VARIANT=DIGEST +SECRET=616e6f74686572206f6e65 +INFO=9014bf55dc1e03babb5ca1c1323a1e5b +EXPECT=4f0a3cf7d52987ccd470d4a8f9d41da9bc6dcf4945c1e522c04fd0c070c397ddb7f4 + +HASH=SHA-256 +VARIANT=DIGEST +SECRET=65306334326336353234373139 +INFO=dbebe4f7dde938229f26651e011f7bbd +EXPECT=d9151c3f36f6980951d84cca75ade71b + +HASH=SHA-256 +VARIANT=DIGEST +SECRET=cf80cf80cf80cf80cf80cf80cf80cf80 +INFO=676c65eb966200b04a2bb870d7ed20ce +EXPECT=c5bb681f1a04713ee7be14e0190676773b0ff63561892fac030b18cca38955369cfc32cdd956ef6e2e4301deb61d049a4d82e57a434168bc5ae084e0df15c0a0d8232d7a791088446b66e612753d36649e70a234a360b611baa07e4a6a7c660db2a1b56acba42d6d3d83b3ce51c787c544bb14b1c94b780fab5c0f966efd80f4a71cd4f267f816a3bb1ec8ceddcd810d1665742c8f68767cd9d7f87ad97792edc6896b6518 + +HASH=SHA-256 +VARIANT=HMAC +SECRET=4d7920736563726574 +INFO=00000000000000000000000000000000 +EXPECT=eba887dca269a550a3882f06f3b1c30058751bc4ec5375e5435e525aeca9782e6311 + +HASH=SHA-256 +VARIANT=HMAC +SECRET=616e6f74686572206f6e65 +INFO=9014bf55dc1e03babb5ca1c1323a1e5b +SALT=ebf4c1e001f26879afc76c7a45ac9541 +EXPECT=8a6484427e5231642a83e7a01fd410040dda5bf3b3d34ec626a8603ac1a5e2e38f02 + +HASH=SHA-256 +VARIANT=HMAC +SECRET=65306334326336353234373139 +INFO=dbebe4f7dde938229f26651e011f7bbd +EXPECT=cceb4536d8431c4d91a5c6f061955aac + +HASH=SHA-256 +VARIANT=HMAC +SECRET=cf80cf80cf80cf80cf80cf80cf80cf80 +INFO=676c65eb966200b04a2bb870d7ed20ce +SALT=1aab1829c8b7ed941b3dc8359dd1f402 +EXPECT=2933b1a656efd556c421533e4fab685c4a9c32f15099a357a73a59c6acebb01b9685631d6208992413c2397c58e8020e588cc16f1f1b470a411ab65d6a0503e3728be789e54e313d49bd1edd606757db6c605ed1e346dd6841afd895379ba09dde046a19dce0a8d49b3ed5671d448e141da5f6bcf3aa5313affd8a14784c424b6d5087aa038ab13db398abbd50dfd39d1134dbe88e308373861d7acf1d79b740f717193d5b + +HASH=SHA-512 +VARIANT=DIGEST +SECRET=4d7920736563726574 +INFO=00000000000000000000000000000000 +EXPECT=8930b01ea45ed7c97c31b5d98a84c48c198c3e5db28241ba9c8417ff1986b53bb4f0 diff --git a/include/openssl/kdf.h b/include/openssl/kdf.h index bb98970eea6..61da8c83223 100644 --- a/include/openssl/kdf.h +++ b/include/openssl/kdf.h @@ -32,6 +32,26 @@ OPENSSL_EXPORT int CRYPTO_tls1_prf(const EVP_MD *digest, const uint8_t *seed1, size_t seed1_len, const uint8_t *seed2, size_t seed2_len); +// SSKDF_DIGEST computes the One-step (Single-step) key derivation using the +// provided digest algorithm as the backing PRF. +// +// Returns a 1 on success, otherwise returns 0. +OPENSSL_EXPORT int SSKDF_DIGEST(uint8_t *out_key, size_t out_len, + const EVP_MD *digest, const uint8_t *secret, + size_t secret_len, const uint8_t *info, + size_t info_len); + +// SSKDF_HMAC computes the One-step (Single-step) key derivation using the +// provided digest algorithm with HMAC as the backing PRF. |salt| optional +// and may be |NULL|. +// +// Returns a 1 on success, otherwise returns 0. +OPENSSL_EXPORT int SSKDF_HMAC(uint8_t *out_key, size_t out_len, + const EVP_MD *digest, const uint8_t *secret, + size_t secret_len, const uint8_t *info, + size_t info_len, const uint8_t *salt, + size_t salt_len); + // KDF support for EVP. diff --git a/sources.cmake b/sources.cmake index 64cb0f71cb9..ba6789ddbb5 100644 --- a/sources.cmake +++ b/sources.cmake @@ -78,6 +78,7 @@ set( crypto/fipsmodule/ec/p256-nistz_tests.txt crypto/fipsmodule/ecdsa/ecdsa_sign_tests.txt crypto/fipsmodule/ecdsa/ecdsa_verify_tests.txt + crypto/fipsmodule/kdf/test/sskdf.txt crypto/fipsmodule/modes/gcm_tests.txt crypto/fipsmodule/rand/ctrdrbg_vectors.txt crypto/fipsmodule/sha/testvectors/SHAKE128VariableOut.txt