EVP_PKEY_DERIVE(3SSL)

πŸ“¦
version 4.0.3 Β· 3 versions
, in ubuntu stonking

✨ EVP_PKEY_DERIVE ✨ (that's the EVP_PKEY_DERIVE(3SSL) page bestie, OpenSSL's little shared-secret-maker)

okay so picture this: you and your peer have keys, you wanna agree on a secret without shouting it across the network β€” that's a shared secret derivation and this whole page is the group chat where that happens πŸ’–

🌸 NAME 🌸

EVP_PKEY_derive_init, EVP_PKEY_derive_init_ex, EVP_PKEY_derive_set_peer_ex, EVP_PKEY_derive_set_peer, EVP_PKEY_derive, EVP_PKEY_derive_SKEY β€” the icons that derive a public key algorithm shared secret πŸ‘‘


πŸŽ€ SYNOPSIS πŸŽ€

#include <openssl/evp.h>

int EVP_PKEY_derive_init(EVP_PKEY_CTX *ctx);
int EVP_PKEY_derive_init_ex(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[]);
int EVP_PKEY_derive_set_peer_ex(EVP_PKEY_CTX *ctx, EVP_PKEY *peer,
                                int validate_peer);
int EVP_PKEY_derive_set_peer(EVP_PKEY_CTX *ctx, EVP_PKEY *peer);
int EVP_PKEY_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen);
EVP_SKEY *EVP_PKEY_derive_SKEY(EVP_PKEY_CTX *ctx, EVP_SKEYMGMT *mgmt,
                               const char *key_type, const char *propquery,
                               size_t keylen, const OSSL_PARAM params[]);

πŸ’… DESCRIPTION πŸ’…

So like, EVP_PKEY_derive_init() gets a public key algorithm context ctx all set up and ready for shared secret derivation, using whichever algorithm the context was born with back when you made it with EVP_PKEY_CTX_new(3) or one of its lil variants. That algorithm is what's used to implicitly fetch an EVP_KEYEXCH method β€” and if you're like "bestie what is an implicit fetch??" then go read "Implicit fetch" in provider(7), it's all explained there fr fr πŸ“š

Then EVP_PKEY_derive_init_ex() is literally the same thing as EVP_PKEY_derive_init(), EXCEPT it also sets the parameters you pass in params on the context before it hands control back. cute right ✨

EVP_PKEY_derive_set_peer_ex() is the one that sets the peer key β€” and normally that's gonna be a public key. And validate_peer? If that value is non zero, the public key gets validated. non-zero = yes please check it πŸ•΅οΈβ™€οΈ

EVP_PKEY_derive_set_peer() is just EVP_PKEY_derive_set_peer_ex() but with validate_peer set to 1. same vibes, less typing 🫢

EVP_PKEY_derive() is the main event β€” it derives a shared secret using ctx. And here's the two-mode thing you gotta know:

  • if key is NULL, then the maximum size of the output buffer gets written into the keylen parameter (this is your "how much room do I need, bestie" call)
  • if key is NOT NULL, then before the call keylen should already contain the length of your key buffer, and if the call works out, the shared secret gets written into key and the amount of data actually written goes into keylen πŸ”₯

EVP_PKEY_derive_SKEY() is EVP_PKEY_derive() coded slightly differently: instead of dumping bytes into a buffer, it hands you back an EVP_SKEY object that stores the opaque data for the derived key. Now β€” if you pass an EVP_SKEYMGMT argument, it gets explicitly used for the EVP_SKEY creation, periodt. Otherwise the EVP_SKEYMGMT object used for EVP_SKEY gets fetched according to skeymgmtname and propquery. And if skeymgmtname is NULL, it just assumes the name matching the key exchange method name. slay, no notes πŸ’œ

🌈 NOTES 🌈

Once EVP_PKEY_derive_init() has been called, you can do algorithm specific control operations to set up whatever parameters the operation needs. go off, set your params πŸŽ€

Also iconic: EVP_PKEY_derive() can be called more than once on the same context, as long as you're doing several operations with the same parameters. reuse is self-care ♻️

lowkey a reminder that the synopsis uses key_type and propquery while the description talks about skeymgmtname and propquery β€” that's just how the page is written, don't come for me, I'm keeping it exactly as-is πŸ’€

⭐ RETURN VALUES ⭐

  • EVP_PKEY_derive_init() and EVP_PKEY_derive() return 1 for success, and 0 or a negative value for failure. and um, specifically: a return value of -2 means the operation is not supported by the public key algorithm 😭
  • EVP_PKEY_derive_SKEY() returns a freshly created EVP_SKEY object on success, or NULL on failure. no cap πŸ‘‘

πŸ¦‹ EXAMPLES πŸ¦‹

Derive a shared secret (for example DH or EC keys):

#include <openssl/evp.h>
#include <openssl/rsa.h>

EVP_PKEY_CTX *ctx;
unsigned char *skey;
size_t skeylen;
EVP_PKEY *pkey, *peerkey;
/* NB: assumes pkey, peerkey have been already set up */

ctx = EVP_PKEY_CTX_new(pkey, NULL);
if (!ctx)
    /* Error occurred */
if (EVP_PKEY_derive_init(ctx) <= 0)
    /* Error */
if (EVP_PKEY_derive_set_peer(ctx, peerkey) <= 0)
    /* Error */

/* Determine buffer length */
if (EVP_PKEY_derive(ctx, NULL, &skeylen) <= 0)
    /* Error */

skey = OPENSSL_malloc(skeylen);

if (!skey)
    /* malloc failure */

if (EVP_PKEY_derive(ctx, skey, &skeylen) <= 0)
    /* Error */

/* Shared secret is skey bytes written to buffer skey */

πŸ‘‘ SEE ALSO πŸ‘‘

πŸ“œ HISTORY πŸ“œ

  • EVP_PKEY_derive_init(), EVP_PKEY_derive_set_peer() and EVP_PKEY_derive() β€” the originals, added all the way back in OpenSSL 1.0.0 🌱
  • EVP_PKEY_derive_init_ex() and EVP_PKEY_derive_set_peer_ex() β€” added in OpenSSL 3.0 ✨
  • EVP_PKEY_derive_SKEY() β€” the newest baby, added in OpenSSL 3.6 🍼

Copyright 2006-2025 The OpenSSL Project Authors. All Rights Reserved.

Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy in the file LICENSE in the source distribution or at <https://www.openssl.org/source/license.html>.


okay that's the whole page bestie, go derive something safe 🫢 this was OpenSSL 4.0.3, dated 2026-09-29, and yeah it's the EVP_PKEY_DERIVE(3SSL) manual β€” mwah, study it, love it, don't skip the return values πŸ’…πŸŒΈ

πŸ“¦ where this page comes from