PROVIDER-KDF(7ossl)

πŸ“¦
version 15.1 Β· 3 versions
, in freebsd 15.1

πŸ’… PROVIDER-KDF πŸ’…

ok so bestie, welcome to PROVIDER-KDF(7ossl) β€” yes that's the header, and the manual name is OpenSSL, section 7ossl, so you know exactly where you are πŸ’–. This is the page that explains the whole KDF library <-> provider handshake situation, and ngl it's kind of iconic.

✨ NAME ✨

provider-kdf β€” literally The KDF library <-> provider functions. that's it, that's the name, no notes πŸŽ€

🌸 SYNOPSIS 🌸

ok so real talk first: none of the things below are actual functions you can just call. they're displayed like this because they're the function signatures for functions that get offered as function pointers in OSSL_DISPATCH arrays. iykyk πŸ¦‹

So you gotta pull in the headers first:

#include <openssl/core_dispatch.h>
#include <openssl/core_names.h>

and here's the full annotated vibe check, in the original order, because we do not skip a single line in this house πŸ‘‘

/*
 * None of these are actual functions, but are displayed like this for
 * the function signatures for functions that are offered as function
 * pointers in OSSL_DISPATCH arrays.
 */

/* Context management */
void *OSSL_FUNC_kdf_newctx(void *provctx);
void OSSL_FUNC_kdf_freectx(void *kctx);
void *OSSL_FUNC_kdf_dupctx(void *src);

/* Encryption/decryption */
int OSSL_FUNC_kdf_reset(void *kctx);
int OSSL_FUNC_kdf_derive(void *kctx, unsigned char *key, size_t keylen,
                         const OSSL_PARAM params[]);

/* KDF parameter descriptors */
const OSSL_PARAM *OSSL_FUNC_kdf_gettable_params(void *provctx);
const OSSL_PARAM *OSSL_FUNC_kdf_gettable_ctx_params(void *kcxt, void *provctx);
const OSSL_PARAM *OSSL_FUNC_kdf_settable_ctx_params(void *kcxt, void *provctx);

/* KDF parameters */
int OSSL_FUNC_kdf_get_params(OSSL_PARAM params[]);
int OSSL_FUNC_kdf_get_ctx_params(void *kctx, OSSL_PARAM params[]);
int OSSL_FUNC_kdf_set_ctx_params(void *kctx, const OSSL_PARAM params[]);

let's break the groups down so it actually lands, because the comments in there are doing a LOT of the heavy lifting 🫢

  • Context management 🌱 β€” the little trio that handles a KDF context's whole life cycle.
    • void *OSSL_FUNC_kdf_newctx(void *provctx); β€” makes you a fresh context, takes the provider context provctx, hands back a shiny new one. main character energy.
    • void OSSL_FUNC_kdf_freectx(void *kctx); β€” cleans up after kctx. say bye bestie 😭
    • void *OSSL_FUNC_kdf_dupctx(void *src); β€” duplicates the context src, because sometimes you need two of the exact same vibe.
  • Encryption/decryption πŸ”₯ β€” yes the comment header really says that, we're not touching it, and yes these are the doing-the-actual-work ones.
    • int OSSL_FUNC_kdf_reset(void *kctx); β€” resets kctx so you can run it again without starting over from scratch.
    • int OSSL_FUNC_kdf_derive(void *kctx, unsigned char *key, size_t keylen, const OSSL_PARAM params[]); β€” the whole point tbh: derive a key into key, which is keylen long, using the params in params. the moment we've all been waiting for ⭐
  • KDF parameter descriptors πŸ’œ β€” the "what params even exist" squad, all returning const OSSL_PARAM *.
    • const OSSL_PARAM *OSSL_FUNC_kdf_gettable_params(void *provctx); β€” the params you can get, provider-wide, from provctx.
    • const OSSL_PARAM *OSSL_FUNC_kdf_gettable_ctx_params(void *kcxt, void *provctx); β€” the params you can get off a specific context kcxt (with provctx along for the ride).
    • const OSSL_PARAM *OSSL_FUNC_kdf_settable_ctx_params(void *kcxt, void *provctx); β€” the params you're allowed to set on kcxt. know your limits, respectfully πŸ™ˆ
  • KDF parameters πŸŽ€ β€” the actual getters and setters, all returning int.
    • int OSSL_FUNC_kdf_get_params(OSSL_PARAM params[]); β€” fills in the params array, provider-level.
    • int OSSL_FUNC_kdf_get_ctx_params(void *kctx, OSSL_PARAM params[]); β€” reads stuff out of kctx into params.
    • int OSSL_FUNC_kdf_set_ctx_params(void *kctx, const OSSL_PARAM params[]); β€” pushes the params you pass in onto kctx. slay.

that's the shape of it β€” every signature above is verbatim, every comment preserved, and we are so not done yet, there's more coming πŸ’–

Hey bestie, quick heads-up before we dive in: this page is literally for provider authors, so if you're just out here trying to use a KDF, go peek at provider(7) first. Still with me? Okay. Slay. Let's go. πŸ’–

The KDF operation is what lets providers implement KDF algorithms and then make them available to applications through the API functions EVP_KDF_CTX_reset(3) and EVP_KDF_derive(3). That's the whole vibe. 🫢

Every "function" mentioned down here is passed as a function pointer between libcrypto and the provider, and it travels inside OSSL_DISPATCH(3) arrays, which themselves come back through OSSL_ALGORITHM(3) arrays returned by the provider's provider_query_operation() function (peep "Provider Functions" in provider-base(7) if you want the lore).

Each of these "functions" has a matching function type definition named OSSL_FUNC_{name}_fn, plus a lil helper function that pulls the function pointer out of an OSSL_DISPATCH(3) element named OSSL_FUNC_{name}. So for example, the "function" OSSL_FUNC_kdf_newctx() gets these two besties:

 typedef void *(OSSL_FUNC_kdf_newctx_fn)(void *provctx);
 static ossl_inline OSSL_FUNC_kdf_newctx_fn
     OSSL_FUNC_kdf_newctx(const OSSL_DISPATCH *opf);

OSSL_DISPATCH(3) array entries are identified by numbers, and those numbers are handed to you as macros in openssl-core_dispatch.h(7). The full matching set, no cap:

 OSSL_FUNC_kdf_newctx               OSSL_FUNC_KDF_NEWCTX
 OSSL_FUNC_kdf_freectx              OSSL_FUNC_KDF_FREECTX
 OSSL_FUNC_kdf_dupctx               OSSL_FUNC_KDF_DUPCTX

 OSSL_FUNC_kdf_reset                OSSL_FUNC_KDF_RESET
 OSSL_FUNC_kdf_derive               OSSL_FUNC_KDF_DERIVE

 OSSL_FUNC_kdf_get_params           OSSL_FUNC_KDF_GET_PARAMS
 OSSL_FUNC_kdf_get_ctx_params       OSSL_FUNC_KDF_GET_CTX_PARAMS
 OSSL_FUNC_kdf_set_ctx_params       OSSL_FUNC_KDF_SET_CTX_PARAMS

 OSSL_FUNC_kdf_gettable_params      OSSL_FUNC_KDF_GETTABLE_PARAMS
 OSSL_FUNC_kdf_gettable_ctx_params  OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS
 OSSL_FUNC_kdf_settable_ctx_params  OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS

Now, a KDF algorithm implementation doesn't have to implement all of these β€” but to be a consistent set of functions, these four are the non-negotiables: OSSL_FUNC_kdf_newctx(), OSSL_FUNC_kdf_freectx(), OSSL_FUNC_kdf_set_ctx_params(), OSSL_FUNC_kdf_derive(). Everything else is optional, bestie. The bare minimum. πŸŽ€


🧚 Context Management Functions 🧚

  • OSSL_FUNC_kdf_newctx() β€” should create and return a pointer to a provider side structure that holds context info during a KDF operation. That context pointer gets passed back to you in a bunch of the other KDF operation function calls. The provctx parameter is the provider context that was generated during provider initialisation (check provider(7) if you need a refresher).
  • OSSL_FUNC_kdf_freectx() β€” gets handed a pointer to the provider side KDF context in the kctx parameter. Heads up: if it receives NULL as the kctx value, it should not do anything other than return. Otherwise, this function should free any resources associated with that context.
  • OSSL_FUNC_kdf_dupctx() β€” should duplicate the provider side KDF context in the kctx parameter and return the duplicate copy. Copy paste but make it cryptographic. ✨

πŸ” Encryption/Decryption Functions πŸ”

  • OSSL_FUNC_kdf_reset() β€” initialises a KDF operation given a provider side KDF context in the kctx parameter.
  • OSSL_FUNC_kdf_derive() β€” actually performs the KDF operation, after processing the params as per OSSL_FUNC_kdf_set_ctx_params(). The kctx parameter holds a pointer to the provider side context. The resulting key of the desired keylen should be written to key. And if the algorithm does not support the requested keylen, the function must return error. No silently truncating, no vibes-based output. πŸ’€

πŸ’… KDF Parameters πŸ’…

OSSL_PARAM(3) has all the further details on the parameters structure these functions use, so go read that if you're nosy.

  • OSSL_FUNC_kdf_get_params() β€” gets details of parameter values associated with the provider algorithm and stores them in params.
  • OSSL_FUNC_kdf_set_ctx_params() β€” sets KDF parameters associated with the given provider side KDF context kctx to params. Any parameter settings are additional to any that were previously set (additive, not a reset, iykyk). Passing NULL for params should return true.
  • OSSL_FUNC_kdf_get_ctx_params() β€” retrieves gettable parameter values associated with the given provider side KDF context kctx and stores them in params. Passing NULL for params should return true.
  • OSSL_FUNC_kdf_gettable_params(), OSSL_FUNC_kdf_gettable_ctx_params(), and OSSL_FUNC_kdf_settable_ctx_params() β€” all return constant OSSL_PARAM(3) arrays that act as descriptors of the parameters that OSSL_FUNC_kdf_get_params(), OSSL_FUNC_kdf_get_ctx_params(), and OSSL_FUNC_kdf_set_ctx_params() can handle, respectively. And here's the tea: OSSL_FUNC_kdf_gettable_ctx_params() and OSSL_FUNC_kdf_settable_ctx_params() return the parameters associated with the provider side context kctx in its current state if it's not NULL. Otherwise, they return the parameters associated with the provider side algorithm provctx.

So. The parameters that built-in KDFs currently recognise are listed below. Fair warning: not all of these are relevant to, or even understood by, all KDFs. Read the room. 🌸

  • "size" (OSSL_KDF_PARAM_SIZE) <unsigned integer> β€” gets the output size from the associated KDF ctx. If the algorithm produces a variable amount of output, SIZE_MAX should be returned. If the input parameters required to calculate the fixed output size have not yet been supplied, 0 should be returned, indicating an error. (Zero means "can't compute yet", not "zero bytes", bestie.)
  • "key" (OSSL_KDF_PARAM_KEY) <octet string> β€” sets the key in the associated KDF ctx.
  • "secret" (OSSL_KDF_PARAM_SECRET) <octet string> β€” sets the secret in the associated KDF ctx.
  • "pass" (OSSL_KDF_PARAM_PASSWORD) <octet string> β€” sets the password in the associated KDF ctx.
  • "cipher" (OSSL_KDF_PARAM_CIPHER) <UTF8 string>, "digest" (OSSL_KDF_PARAM_DIGEST) <UTF8 string>, "mac" (OSSL_KDF_PARAM_MAC) <UTF8 string> β€” sets the name of the underlying cipher, digest or MAC to be used. It must name a suitable algorithm for the KDF that's being used. Pick the right one, okay? πŸ™ˆ
  • "maclen" (OSSL_KDF_PARAM_MAC_SIZE) <octet string> β€” sets the length of the MAC in the associated KDF ctx.
  • "properties" (OSSL_KDF_PARAM_PROPERTIES) <UTF8 string> β€” sets the properties to be queried when trying to fetch the underlying algorithm. This must be given together with the algorithm naming parameter to be considered valid. Two for one, no exceptions.
  • "iter" (OSSL_KDF_PARAM_ITER) <unsigned integer> β€” sets the number of iterations in the associated KDF ctx.
  • "mode" (OSSL_KDF_PARAM_MODE) <UTF8 string> β€” sets the mode in the associated KDF ctx.
  • "pkcs5" (OSSL_KDF_PARAM_PKCS5) <integer> β€” enables or disables the SP800-132 compliance checks. A mode of 0 enables the compliance checks. (Yes, 0 turns the checks on. That's just how it is, don't @ me.)

The checks performed are:

  • the iteration count is at least 1000.
  • the salt length is at least 128 bits.
  • the derived key length is at least 112 bits.
  • "ukm" (OSSL_KDF_PARAM_UKM) <octet string> β€” sets an optional random string that is provided by the sender, called "partyAInfo". In CMS this is the user keying material.
  • "cekalg" (OSSL_KDF_PARAM_CEK_ALG) <UTF8 string> β€” sets the CEK wrapping algorithm name in the associated KDF ctx.
  • "n" (OSSL_KDF_PARAM_SCRYPT_N) <unsigned integer> β€” sets the scrypt work factor parameter N in the associated KDF ctx.
  • "r" (OSSL_KDF_PARAM_SCRYPT_R) <unsigned integer> β€” sets the scrypt work factor parameter r in the associated KDF ctx.
  • "p" (OSSL_KDF_PARAM_SCRYPT_P) <unsigned integer> β€” sets the scrypt work factor parameter p in the associated KDF ctx.
  • "maxmem_bytes" (OSSL_KDF_PARAM_SCRYPT_MAXMEM) <unsigned integer> β€” sets the scrypt work factor parameter maxmem in the associated KDF ctx.
  • "prefix" (OSSL_KDF_PARAM_PREFIX) <octet string> β€” sets the prefix string used by the TLS 1.3 version of HKDF in the associated KDF ctx.
  • "label" (OSSL_KDF_PARAM_LABEL) <octet string> β€” sets the label string used by the TLS 1.3 version of HKDF in the associated KDF ctx.
  • "data" (OSSL_KDF_PARAM_DATA) <octet string> β€” sets the context string used by the TLS 1.3 version of HKDF in the associated KDF ctx.
  • "info" (OSSL_KDF_PARAM_INFO) <octet string> β€” sets the optional shared info in the associated KDF ctx.
  • "seed" (OSSL_KDF_PARAM_SEED) <octet string> β€” sets the IV in the associated KDF ctx.
  • "xcghash" (OSSL_KDF_PARAM_SSHKDF_XCGHASH) <octet string> β€” sets the xcghash in the associated KDF ctx.
  • "session_id" (OSSL_KDF_PARAM_SSHKDF_SESSION_ID) <octet string> β€” sets the session ID in the associated KDF ctx.
  • "type" (OSSL_KDF_PARAM_SSHKDF_TYPE) <UTF8 string> β€” sets the SSH KDF type parameter in the associated KDF ctx. There are six supported types, and honestly they're all just one ASCII letter wearing a fancy name:
    • EVP_KDF_SSHKDF_TYPE_INITIAL_IV_CLI_TO_SRV β€” the Initial IV from client to server. A single char of value 65 (ASCII char 'A').
    • EVP_KDF_SSHKDF_TYPE_INITIAL_IV_SRV_TO_CLI β€” the Initial IV from server to client. A single char of value 66 (ASCII char 'B').
    • EVP_KDF_SSHKDF_TYPE_ENCRYPTION_KEY_CLI_TO_SRV β€” the Encryption Key from client to server. A single char of value 67 (ASCII char 'C').
    • EVP_KDF_SSHKDF_TYPE_ENCRYPTION_KEY_SRV_TO_CLI β€” the Encryption Key from server to client. A single char of value 68 (ASCII char 'D').
    • EVP_KDF_SSHKDF_TYPE_INTEGRITY_KEY_CLI_TO_SRV β€” the Integrity Key from client to server. A single char of value 69 (ASCII char 'E').
    • EVP_KDF_SSHKDF_TYPE_INTEGRITY_KEY_SRV_TO_CLI β€” the Integrity Key from client to server. A single char of value 70 (ASCII char 'F').
  • "constant" (OSSL_KDF_PARAM_CONSTANT) <octet string> β€” sets the constant value in the associated KDF ctx.
  • "id" (OSSL_KDF_PARAM_PKCS12_ID) <integer> β€” sets the intended usage of the output bits in the associated KDF ctx. It is defined as per RFC 7292 section B.3.

🌈 RETURN VALUES 🌈

Okay so here's what you return, and be honest about it:

  • OSSL_FUNC_kdf_newctx() and OSSL_FUNC_kdf_dupctx() should return the newly created provider side KDF context, or NULL on failure.
  • OSSL_FUNC_kdf_derive(), OSSL_FUNC_kdf_get_params(), OSSL_FUNC_kdf_get_ctx_params() and OSSL_FUNC_kdf_set_ctx_params() should return 1 for success or 0 on error. Classic. One or zero. That's the whole system. βœ…
  • OSSL_FUNC_kdf_gettable_params(), OSSL_FUNC_kdf_gettable_ctx_params() and OSSL_FUNC_kdf_settable_ctx_params() should return a constant OSSL_PARAM(3) array, or NULL if none is offered.

okay bestie, legal era β€” but make it cute. Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved. ✨

This file is licensed under the Apache License 2.0 (the "License"). The way that means you literally may not use this file except in compliance with the License β€” no cap, that's the whole vibe check. 🫢

You can grab your very own copy of the License here, iconic behavior:

bestie this is the boring-but-load-bearing part, so don't skip it β€” the license terms are the terms, periodt. πŸ’…

and that's the whole page, we ate and left no crumbs πŸŽ€ this one ships as 3.5.6, dated 2026-04-07 β€” mwah, go forth and kdf responsibly, iykyk πŸ’–πŸ¦‹πŸ‘‘

πŸ“¦ where this page comes from