EVP_PKEY_METH_NEW(3ossl)

πŸ“¦ version 3.5.0, in opensuse-leap 16.0

πŸ’… EVP_PKEY_METH_NEW(3ossl) β€” the OpenSSL glow-up page

okay so bestie, buckle up πŸŽ€ this is EVP_PKEY_METH_NEW(3ossl) and it's the whole EVP_PKEY_METHOD saga β€” the big pile of functions for manipulating EVP_PKEY_METHOD structure. and yes, "manipulating" is literally in the name, this is not a drill πŸ’€

real talk first though: this whole page is deprecated. like, since OpenSSL 3.0. so read it for the lore, but don't go building new stuff on it, mkay?


✨ NAME ✨

So here's the full squad πŸ’– β€” every single one of these lives on this page:

  • EVP_PKEY_meth_new
  • EVP_PKEY_meth_free
  • EVP_PKEY_meth_copy
  • EVP_PKEY_meth_find
  • EVP_PKEY_meth_add0
  • EVP_PKEY_METHOD
  • EVP_PKEY_meth_set_init
  • EVP_PKEY_meth_set_copy
  • EVP_PKEY_meth_set_cleanup
  • EVP_PKEY_meth_set_paramgen
  • EVP_PKEY_meth_set_keygen
  • EVP_PKEY_meth_set_sign
  • EVP_PKEY_meth_set_verify
  • EVP_PKEY_meth_set_verify_recover
  • EVP_PKEY_meth_set_signctx
  • EVP_PKEY_meth_set_verifyctx
  • EVP_PKEY_meth_set_encrypt
  • EVP_PKEY_meth_set_decrypt
  • EVP_PKEY_meth_set_derive
  • EVP_PKEY_meth_set_ctrl
  • EVP_PKEY_meth_set_digestsign
  • EVP_PKEY_meth_set_digestverify
  • EVP_PKEY_meth_set_check
  • EVP_PKEY_meth_set_public_check
  • EVP_PKEY_meth_set_param_check
  • EVP_PKEY_meth_set_digest_custom
  • EVP_PKEY_meth_get_init
  • EVP_PKEY_meth_get_copy
  • EVP_PKEY_meth_get_cleanup
  • EVP_PKEY_meth_get_paramgen
  • EVP_PKEY_meth_get_keygen
  • EVP_PKEY_meth_get_sign
  • EVP_PKEY_meth_get_verify
  • EVP_PKEY_meth_get_verify_recover
  • EVP_PKEY_meth_get_signctx
  • EVP_PKEY_meth_get_verifyctx
  • EVP_PKEY_meth_get_encrypt
  • EVP_PKEY_meth_get_decrypt
  • EVP_PKEY_meth_get_derive
  • EVP_PKEY_meth_get_ctrl
  • EVP_PKEY_meth_get_digestsign
  • EVP_PKEY_meth_get_digestverify
  • EVP_PKEY_meth_get_check
  • EVP_PKEY_meth_get_public_check
  • EVP_PKEY_meth_get_param_check
  • EVP_PKEY_meth_get_digest_custom
  • EVP_PKEY_meth_remove

...and the grand prize: manipulating EVP_PKEY_METHOD structure. which, yeah, that's the whole vibe of this page πŸ’…


🌸 SYNOPSIS 🌸

start with the include, always:

#include <openssl/evp.h>
⚠️ deprecation alert ⚠️ ngl this is important: the following functions have been deprecated since OpenSSL 3.0, and you can hide them entirely by defining OPENSSL_API_COMPAT with a suitable version value. how do you know what's "suitable"? check openssl_user_macros(7) bestie 🫢

the type itself:

typedef struct evp_pkey_method_st EVP_PKEY_METHOD;

the lifecycle / registry crew 🌈:

EVP_PKEY_METHOD *EVP_PKEY_meth_new(int id, int flags);
void EVP_PKEY_meth_free(EVP_PKEY_METHOD *pmeth);
void EVP_PKEY_meth_copy(EVP_PKEY_METHOD *dst, const EVP_PKEY_METHOD *src);
const EVP_PKEY_METHOD *EVP_PKEY_meth_find(int type);
int EVP_PKEY_meth_add0(const EVP_PKEY_METHOD *pmeth);
int EVP_PKEY_meth_remove(const EVP_PKEY_METHOD *pmeth);

and now the giant wall of setters 😭 every one of them is void and every one of them takes pmeth first. here we go:

void EVP_PKEY_meth_set_init(EVP_PKEY_METHOD *pmeth,
                            int (*init) (EVP_PKEY_CTX *ctx));
void EVP_PKEY_meth_set_copy(EVP_PKEY_METHOD *pmeth,
                            int (*copy) (EVP_PKEY_CTX *dst,
                                         const EVP_PKEY_CTX *src));
void EVP_PKEY_meth_set_cleanup(EVP_PKEY_METHOD *pmeth,
                               void (*cleanup) (EVP_PKEY_CTX *ctx));
void EVP_PKEY_meth_set_paramgen(EVP_PKEY_METHOD *pmeth,
                                int (*paramgen_init) (EVP_PKEY_CTX *ctx),
                                int (*paramgen) (EVP_PKEY_CTX *ctx,
                                                 EVP_PKEY *pkey));
void EVP_PKEY_meth_set_keygen(EVP_PKEY_METHOD *pmeth,
                              int (*keygen_init) (EVP_PKEY_CTX *ctx),
                              int (*keygen) (EVP_PKEY_CTX *ctx,
                                             EVP_PKEY *pkey));
void EVP_PKEY_meth_set_sign(EVP_PKEY_METHOD *pmeth,
                            int (*sign_init) (EVP_PKEY_CTX *ctx),
                            int (*sign) (EVP_PKEY_CTX *ctx,
                                         unsigned char *sig, size_t *siglen,
                                         const unsigned char *tbs,
                                         size_t tbslen));
void EVP_PKEY_meth_set_verify(EVP_PKEY_METHOD *pmeth,
                              int (*verify_init) (EVP_PKEY_CTX *ctx),
                              int (*verify) (EVP_PKEY_CTX *ctx,
                                             const unsigned char *sig,
                                             size_t siglen,
                                             const unsigned char *tbs,
                                             size_t tbslen));
void EVP_PKEY_meth_set_verify_recover(EVP_PKEY_METHOD *pmeth,
                                      int (*verify_recover_init) (EVP_PKEY_CTX
                                                                  *ctx),
                                      int (*verify_recover) (EVP_PKEY_CTX
                                                             *ctx,
                                                             unsigned char
                                                             *sig,
                                                             size_t *siglen,
                                                             const unsigned
                                                             char *tbs,
                                                             size_t tbslen));
void EVP_PKEY_meth_set_signctx(EVP_PKEY_METHOD *pmeth,
                               int (*signctx_init) (EVP_PKEY_CTX *ctx,
                                                    EVP_MD_CTX *mctx),
                               int (*signctx) (EVP_PKEY_CTX *ctx,
                                               unsigned char *sig,
                                               size_t *siglen,
                                               EVP_MD_CTX *mctx));
void EVP_PKEY_meth_set_verifyctx(EVP_PKEY_METHOD *pmeth,
                                 int (*verifyctx_init) (EVP_PKEY_CTX *ctx,
                                                        EVP_MD_CTX *mctx),
                                 int (*verifyctx) (EVP_PKEY_CTX *ctx,
                                                   const unsigned char *sig,
                                                   int siglen,
                                                   EVP_MD_CTX *mctx));
void EVP_PKEY_meth_set_encrypt(EVP_PKEY_METHOD *pmeth,
                               int (*encrypt_init) (EVP_PKEY_CTX *ctx),
                               int (*encryptfn) (EVP_PKEY_CTX *ctx,
                                                 unsigned char *out,
                                                 size_t *outlen,
                                                 const unsigned char *in,
                                                 size_t inlen));
void EVP_PKEY_meth_set_decrypt(EVP_PKEY_METHOD *pmeth,
                               int (*decrypt_init) (EVP_PKEY_CTX *ctx),
                               int (*decrypt) (EVP_PKEY_CTX *ctx,
                                               unsigned char *out,
                                               size_t *outlen,
                                               const unsigned char *in,
                                               size_t inlen));
void EVP_PKEY_meth_set_derive(EVP_PKEY_METHOD *pmeth,
                              int (*derive_init) (EVP_PKEY_CTX *ctx),
                              int (*derive) (EVP_PKEY_CTX *ctx,
                                             unsigned char *key,
                                             size_t *keylen));
void EVP_PKEY_meth_set_ctrl(EVP_PKEY_METHOD *pmeth,
                            int (*ctrl) (EVP_PKEY_CTX *ctx, int type, int p1,
                                         void *p2),
                            int (*ctrl_str) (EVP_PKEY_CTX *ctx,
                                             const char *type,
                                             const char *value));
void EVP_PKEY_meth_set_digestsign(EVP_PKEY_METHOD *pmeth,
                                  int (*digestsign) (EVP_MD_CTX *ctx,
                                                     unsigned char *sig,
                                                     size_t *siglen,
                                                     const unsigned char *tbs,
                                                     size_t tbslen));
void EVP_PKEY_meth_set_digestverify(EVP_PKEY_METHOD *pmeth,
                                    int (*digestverify) (EVP_MD_CTX *ctx,
                                                         const unsigned char *sig,
                                                         size_t siglen,
                                                         const unsigned char *tbs,
                                                         size_t tbslen));
void EVP_PKEY_meth_set_check(EVP_PKEY_METHOD *pmeth,
                             int (*check) (EVP_PKEY *pkey));
void EVP_PKEY_meth_set_public_check(EVP_PKEY_METHOD *pmeth,
                                    int (*check) (EVP_PKEY *pkey));
void EVP_PKEY_meth_set_param_check(EVP_PKEY_METHOD *pmeth,
                                   int (*check) (EVP_PKEY *pkey));
void EVP_PKEY_meth_set_digest_custom(EVP_PKEY_METHOD *pmeth,
                                    int (*digest_custom) (EVP_PKEY_CTX *ctx,
                                                          EVP_MD_CTX *mctx));

okay that's the synopsis bestie, breathe 🧚 (and heads up β€” more of this page is coming, don't go anywhere πŸ’œ)

        void EVP_PKEY_meth_get_init(const EVP_PKEY_METHOD *pmeth,
                                    int (**pinit) (EVP_PKEY_CTX *ctx));
        void EVP_PKEY_meth_get_copy(const EVP_PKEY_METHOD *pmeth,
                                    int (**pcopy) (EVP_PKEY_CTX *dst,
                                                   EVP_PKEY_CTX *src));
        void EVP_PKEY_meth_get_cleanup(const EVP_PKEY_METHOD *pmeth,
                                       void (**pcleanup) (EVP_PKEY_CTX *ctx));
        void EVP_PKEY_meth_get_paramgen(const EVP_PKEY_METHOD *pmeth,
                                        int (**pparamgen_init) (EVP_PKEY_CTX *ctx),
                                        int (**pparamgen) (EVP_PKEY_CTX *ctx,
                                                           EVP_PKEY *pkey));
        void EVP_PKEY_meth_get_keygen(const EVP_PKEY_METHOD *pmeth,
                                      int (**pkeygen_init) (EVP_PKEY_CTX *ctx),
                                      int (**pkeygen) (EVP_PKEY_CTX *ctx,
                                                       EVP_PKEY *pkey));
        void EVP_PKEY_meth_get_sign(const EVP_PKEY_METHOD *pmeth,
                                    int (**psign_init) (EVP_PKEY_CTX *ctx),
                                    int (**psign) (EVP_PKEY_CTX *ctx,
                                                   unsigned char *sig, size_t *siglen,
                                                   const unsigned char *tbs,
                                                   size_t tbslen));
        void EVP_PKEY_meth_get_verify(const EVP_PKEY_METHOD *pmeth,
                                      int (**pverify_init) (EVP_PKEY_CTX *ctx),
                                      int (**pverify) (EVP_PKEY_CTX *ctx,
                                                       const unsigned char *sig,
                                                       size_t siglen,
                                                       const unsigned char *tbs,
                                                       size_t tbslen));
        void EVP_PKEY_meth_get_verify_recover(const EVP_PKEY_METHOD *pmeth,
                                              int (**pverify_recover_init) (EVP_PKEY_CTX
                                                                            *ctx),
                                              int (**pverify_recover) (EVP_PKEY_CTX
                                                                       *ctx,
                                                                       unsigned char
                                                                       *sig,
                                                                       size_t *siglen,
                                                                       const unsigned
                                                                       char *tbs,
                                                                       size_t tbslen));
        void EVP_PKEY_meth_get_signctx(const EVP_PKEY_METHOD *pmeth,
                                       int (**psignctx_init) (EVP_PKEY_CTX *ctx,
                                                              EVP_MD_CTX *mctx),
                                       int (**psignctx) (EVP_PKEY_CTX *ctx,
                                                         unsigned char *sig,
                                                         size_t *siglen,
                                                         EVP_MD_CTX *mctx));
        void EVP_PKEY_meth_get_verifyctx(const EVP_PKEY_METHOD *pmeth,
                                         int (**pverifyctx_init) (EVP_PKEY_CTX *ctx,
                                                                  EVP_MD_CTX *mctx),
                                         int (**pverifyctx) (EVP_PKEY_CTX *ctx,
                                                             const unsigned char *sig,
                                                             int siglen,
                                                             EVP_MD_CTX *mctx));
        void EVP_PKEY_meth_get_encrypt(const EVP_PKEY_METHOD *pmeth,
                                       int (**pencrypt_init) (EVP_PKEY_CTX *ctx),
                                       int (**pencryptfn) (EVP_PKEY_CTX *ctx,
                                                           unsigned char *out,
                                                           size_t *outlen,
                                                           const unsigned char *in,
                                                           size_t inlen));
        void EVP_PKEY_meth_get_decrypt(const EVP_PKEY_METHOD *pmeth,
                                       int (**pdecrypt_init) (EVP_PKEY_CTX *ctx),
                                       int (**pdecrypt) (EVP_PKEY_CTX *ctx,
                                                         unsigned char *out,
                                                         size_t *outlen,
                                                         const unsigned char *in,
                                                         size_t inlen));
        void EVP_PKEY_meth_get_derive(const EVP_PKEY_METHOD *pmeth,
                                      int (**pderive_init) (EVP_PKEY_CTX *ctx),
                                      int (**pderive) (EVP_PKEY_CTX *ctx,
                                                       unsigned char *key,
                                                       size_t *keylen));
        void EVP_PKEY_meth_get_ctrl(const EVP_PKEY_METHOD *pmeth,
                                    int (**pctrl) (EVP_PKEY_CTX *ctx, int type, int p1,
                                                   void *p2),
                                    int (**pctrl_str) (EVP_PKEY_CTX *ctx,
                                                       const char *type,
                                                       const char *value));
        void EVP_PKEY_meth_get_digestsign(const EVP_PKEY_METHOD *pmeth,
                                          int (**digestsign) (EVP_MD_CTX *ctx,
                                                              unsigned char *sig,
                                                              size_t *siglen,
                                                              const unsigned char *tbs,
                                                              size_t tbslen));
        void EVP_PKEY_meth_get_digestverify(const EVP_PKEY_METHOD *pmeth,
                                            int (**digestverify) (EVP_MD_CTX *ctx,
                                                                  const unsigned char *sig,
                                                                  size_t siglen,
                                                                  const unsigned char *tbs,
                                                                  size_t tbslen));
        void EVP_PKEY_meth_get_check(const EVP_PKEY_METHOD *pmeth,
                                     int (**pcheck) (EVP_PKEY *pkey));
        void EVP_PKEY_meth_get_public_check(const EVP_PKEY_METHOD *pmeth,
                                            int (**pcheck) (EVP_PKEY *pkey));
        void EVP_PKEY_meth_get_param_check(const EVP_PKEY_METHOD *pmeth,
                                           int (**pcheck) (EVP_PKEY *pkey));
        void EVP_PKEY_meth_get_digest_custom(const EVP_PKEY_METHOD *pmeth,
                                            int (**pdigest_custom) (EVP_PKEY_CTX *ctx,
                                                                    EVP_MD_CTX *mctx));

✨ DESCRIPTION ✨

Okay so picture an EVP_PKEY_METHOD as the ~recipe card~ for one public-key algorithm β€” it's the thing that holds all the little function pointers that actually do the work. πŸŽ€

This whole pile of EVP_PKEY_meth_get_*() functions is the "so what's actually on the recipe card?" side of things. You hand it a pmeth (a const EVP_PKEY_METHOD *, thank you very much) plus one or more pointer-to-function-pointer out-params, and it fills those out-params with the matching callback. That double-pointer thing (int (**pinit) (EVP_PKEY_CTX *ctx)) is just how you get a function pointer back out of a function, bestie β€” no cap. 🫢

Every getter is named after the callback it fishes out, so you can basically read the name and know what you're getting. Obsessed, honestly. πŸ˜­πŸ’…

🌸 the lifecycle trio

  • EVP_PKEY_meth_get_init() β€” pulls out the init callback into *pinit, signature int (**pinit) (EVP_PKEY_CTX *ctx).
  • EVP_PKEY_meth_get_copy() β€” pulls out the copy callback into *pcopy, signature int (**pcopy) (EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) β€” note it takes a destination and a source context. πŸ‘€
  • EVP_PKEY_meth_get_cleanup() β€” pulls out the cleanup callback into *pcleanup, and heads up, it returns void, not int, so its type is void (**pcleanup) (EVP_PKEY_CTX *ctx).

πŸ¦‹ generating stuff

  • EVP_PKEY_meth_get_paramgen() β€” gives you two callbacks at once: *pparamgen_init (int (**pparamgen_init) (EVP_PKEY_CTX *ctx)) and *pparamgen (int (**pparamgen) (EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)).
  • EVP_PKEY_meth_get_keygen() β€” same deal, a pair: *pkeygen_init (int (**pkeygen_init) (EVP_PKEY_CTX *ctx)) and *pkeygen (int (**pkeygen) (EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)).

πŸŽ€ signing & verifying (the classic way)

  • EVP_PKEY_meth_get_sign() β€” hands back *psign_init (int (**psign_init) (EVP_PKEY_CTX *ctx)) and *psign, whose type is int (**psign) (EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, const unsigned char *tbs, size_t tbslen). Yes siglen is a size_t *, she's flexible like that. ✨
  • EVP_PKEY_meth_get_verify() β€” hands back *pverify_init (int (**pverify_init) (EVP_PKEY_CTX *ctx)) and *pverify (int (**pverify) (EVP_PKEY_CTX *ctx, const unsigned char *sig, size_t siglen, const unsigned char *tbs, size_t tbslen)). Notice verify's siglen is a plain size_t while sign's is a pointer β€” that's not a typo, that's literally how it is. πŸ’€
  • EVP_PKEY_meth_get_verify_recover() β€” the long one, and she is long: *pverify_recover_init is int (**pverify_recover_init) (EVP_PKEY_CTX *ctx) and *pverify_recover is int (**pverify_recover) (EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, const unsigned char *tbs, size_t tbslen).

🧚 signing & verifying (the md-context way)

  • EVP_PKEY_meth_get_signctx() β€” *psignctx_init (int (**psignctx_init) (EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx)) plus *psignctx (int (**psignctx) (EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, EVP_MD_CTX *mctx)). mctx girlies rise up. 🌈
  • EVP_PKEY_meth_get_verifyctx() β€” *pverifyctx_init (int (**pverifyctx_init) (EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx)) plus *pverifyctx (int (**pverifyctx) (EVP_PKEY_CTX *ctx, const unsigned char *sig, int siglen, EVP_MD_CTX *mctx)). And yes β€” siglen here is an int, not a size_t. Keep your eyes on that one, iykyk. πŸ™ˆ

πŸ”₯ encrypt / decrypt / derive

  • EVP_PKEY_meth_get_encrypt() β€” *pencrypt_init (int (**pencrypt_init) (EVP_PKEY_CTX *ctx)) and *pencryptfn (int (**pencryptfn) (EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, const unsigned char *in, size_t inlen)). Cute little detail: the function pointer itself is called pencryptfn, not pencrypt. πŸ“
  • EVP_PKEY_meth_get_decrypt() β€” *pdecrypt_init (int (**pdecrypt_init) (EVP_PKEY_CTX *ctx)) and *pdecrypt (int (**pdecrypt) (EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, const unsigned char *in, size_t inlen)).
  • EVP_PKEY_meth_get_derive() β€” *pderive_init (int (**pderive_init) (EVP_PKEY_CTX *ctx)) and *pderive (int (**pderive) (EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen)).

πŸ’œ ctrl, because of course there's a ctrl

  • EVP_PKEY_meth_get_ctrl() β€” grabs both control callbacks: *pctrl, which is int (**pctrl) (EVP_PKEY_CTX *ctx, int type, int p1, void *p2), and *pctrl_str, which is int (**pctrl_str) (EVP_PKEY_CTX *ctx, const char *type, const char *value). Two flavours, one getter. Slay. πŸ‘‘

⭐ the digest-signing shortcuts

  • EVP_PKEY_meth_get_digestsign() β€” hands you *digestsign, typed int (**digestsign) (EVP_MD_CTX *ctx, unsigned char *sig, size_t *siglen, const unsigned char *tbs, size_t tbslen). Notice the context is an EVP_MD_CTX * here, not an EVP_PKEY_CTX *.
  • EVP_PKEY_meth_get_digestverify() β€” hands you *digestverify, typed int (**digestverify) (EVP_MD_CTX *ctx, const unsigned char *sig, size_t siglen, const unsigned char *tbs, size_t tbslen). Also EVP_MD_CTX *. Iconic. ✨

πŸ‘‘ the check family

All three of these hand back a single int (**pcheck) (EVP_PKEY *pkey) β€” the out-param is literally named pcheck in every one of them, so squint at which function you called, not the parameter name. 😭

  • EVP_PKEY_meth_get_check() β€” retrieves the check callback.
  • EVP_PKEY_meth_get_public_check() β€” retrieves the public-check callback.
  • EVP_PKEY_meth_get_param_check() β€” retrieves the param-check callback.

🌸 and one more for the road

  • EVP_PKEY_meth_get_digest_custom() β€” hands back *pdigest_custom, typed int (**pdigest_custom) (EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx). Yep, she takes both kinds of context. Versatile queen. 🫢

✨ DESCRIPTION ✨

Okay bestie, first things first and I need you to hear me on this one: all of the functions described on this page are deprecated. Like, every single one. The glow-up is real and the move is to use the OSSL_PROVIDER APIs instead. Periodt. πŸ’…

So EVP_PKEY_METHOD is a struct that holds a whole little set of methods for one specific public key crypto algorithm. And those methods? They're the ones doing the actual jobs β€” generating a key, signing or verifying, encrypting or decrypting, all of it. It's giving "one algorithm, one very organized little crew." 🫢

Now, there are exactly two places where EVP_PKEY_METHOD objects live:

  • a built-in static array that represents the standard methods for the different algorithms, and
  • a stack of user-defined application-specific methods, which you can mess with using EVP_PKEY_meth_add0(3).

And these EVP_PKEY_METHOD objects are usually referenced by EVP_PKEY_CTX objects. That's the relationship. That's the lore. πŸ”₯

Methods 🧚

These methods are the underlying implementations of a particular public key algorithm, present by the EVP_PKEY_CTX object. Let's meet the whole cast, shall we?

 int (*init) (EVP_PKEY_CTX *ctx);
 int (*copy) (EVP_PKEY_CTX *dst, const EVP_PKEY_CTX *src);
 void (*cleanup) (EVP_PKEY_CTX *ctx);

So init() gets called to set up the algorithm-specific data when a new EVP_PKEY_CTX is created. And then β€” plot twist β€” cleanup() is basically the opposite energy, called when an EVP_PKEY_CTX gets freed. Meanwhile copy() shows up whenever an EVP_PKEY_CTX is being duplicated. If you want the receipts, go peek at EVP_PKEY_CTX_new(3), EVP_PKEY_CTX_new_id(3), EVP_PKEY_CTX_free(3) and EVP_PKEY_CTX_dup(3). πŸ“š

 int (*paramgen_init) (EVP_PKEY_CTX *ctx);
 int (*paramgen) (EVP_PKEY_CTX *ctx, EVP_PKEY *pkey);

paramgen_init() and paramgen() are the key parameter generation girlies. EVP_PKEY_paramgen_init(3) and EVP_PKEY_paramgen(3) call them to handle the whole parameter generation process. Parameters first, always. πŸ’–

 int (*keygen_init) (EVP_PKEY_CTX *ctx);
 int (*keygen) (EVP_PKEY_CTX *ctx, EVP_PKEY *pkey);

keygen_init() and keygen() are the ones that actually generate the key for the specified algorithm. They get called by EVP_PKEY_keygen_init(3) and EVP_PKEY_keygen(3). Main character energy, honestly. πŸ‘‘

 int (*sign_init) (EVP_PKEY_CTX *ctx);
 int (*sign) (EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
             const unsigned char *tbs, size_t tbslen);

sign_init() and sign() generate the signature of a piece of data using a private key. Called by EVP_PKEY_sign_init(3) and EVP_PKEY_sign(3). Slay. ✨

 int (*verify_init) (EVP_PKEY_CTX *ctx);
 int (*verify) (EVP_PKEY_CTX *ctx,
               const unsigned char *sig, size_t siglen,
               const unsigned char *tbs, size_t tbslen);

verify_init() and verify() check whether a signature is actually valid. They're called by EVP_PKEY_verify_init(3) and EVP_PKEY_verify(3). Trust but verify, bestie. πŸ”

 int (*verify_recover_init) (EVP_PKEY_CTX *ctx);
 int (*verify_recover) (EVP_PKEY_CTX *ctx,
                       unsigned char *rout, size_t *routlen,
                       const unsigned char *sig, size_t siglen);

verify_recover_init() and verify_recover() verify a signature and then recover the digest from that signature β€” think, like, a signature that was generated by the RSA signing algorithm. Called by EVP_PKEY_verify_recover_init(3) and EVP_PKEY_verify_recover(3). Two jobs, one icon. πŸ’…

 int (*signctx_init) (EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx);
 int (*signctx) (EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
                EVP_MD_CTX *mctx);

signctx_init() and signctx() sign a digest that's present in an EVP_MD_CTX object. The EVP_DigestSign functions call them. Details are over in EVP_DigestSignInit(3) if you're nosy. πŸŽ€

 int (*verifyctx_init) (EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx);
 int (*verifyctx) (EVP_PKEY_CTX *ctx, const unsigned char *sig, int siglen,
                  EVP_MD_CTX *mctx);

verifyctx_init() and verifyctx() verify a signature against the data in an EVP_MD_CTX object. The various EVP_DigestVerify functions call them. Again: EVP_DigestVerifyInit(3) for the full tea. πŸ“

 int (*encrypt_init) (EVP_PKEY_CTX *ctx);
 int (*encrypt) (EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen,
                 const unsigned char *in, size_t inlen);

encrypt_init() and encrypt() encrypt a piece of data. Called by EVP_PKEY_encrypt_init(3) and EVP_PKEY_encrypt(3). Lock it up. πŸ”’

 int (*decrypt_init) (EVP_PKEY_CTX *ctx);
 int (*decrypt) (EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen,
                 const unsigned char *in, size_t inlen);

decrypt_init() and decrypt() decrypt a piece of data. Called by EVP_PKEY_decrypt_init(3) and EVP_PKEY_decrypt(3). And we unlock it. πŸ”“

 int (*derive_init) (EVP_PKEY_CTX *ctx);
 int (*derive) (EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen);

derive_init() and derive() derive the shared secret from a public key algorithm β€” the DH algorithm being the classic example here. Called by EVP_PKEY_derive_init(3) and EVP_PKEY_derive(3). Sharing is caring. 🫢

 int (*ctrl) (EVP_PKEY_CTX *ctx, int type, int p1, void *p2);
 int (*ctrl_str) (EVP_PKEY_CTX *ctx, const char *type, const char *value);

ctrl() and ctrl_str() adjust algorithm-specific settings. For the full picture, see EVP_PKEY_CTX_ctrl(3) and its related functions. πŸŽ›οΈ

 int (*digestsign) (EVP_MD_CTX *ctx, unsigned char *sig, size_t *siglen,
                    const unsigned char *tbs, size_t tbslen);
 int (*digestverify) (EVP_MD_CTX *ctx, const unsigned char *sig,
                      size_t siglen, const unsigned char *tbs,
                      size_t tbslen);

digestsign() and digestverify() generate or verify a signature in one-shot mode. They could be called by EVP_DigestSign(3) and EVP_DigestVerify(3). One and done, no notes. ⚑

 int (*check) (EVP_PKEY *pkey);
 int (*public_check) (EVP_PKEY *pkey);
 int (*param_check) (EVP_PKEY *pkey);

check(), public_check() and param_check() validate a key-pair, the public component, and parameters respectively, for a given pkey. They could be called by EVP_PKEY_check(3), EVP_PKEY_public_check(3) and EVP_PKEY_param_check(3) respectively. Vibe check, but make it cryptographic. βœ…

 int (*digest_custom) (EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx);

digest_custom() generates customized digest content before the real message gets passed to functions like EVP_DigestSignUpdate(3) or EVP_DigestVerifyInit(3). Some public key signature algorithms lowkey require this β€” SM2, for example, needs a hashed prefix to the message being signed. The digest_custom() function will be called by EVP_DigestSignInit(3) and EVP_DigestVerifyInit(3). Customization is a lifestyle. 🌸

Functions πŸŽ€

EVP_PKEY_meth_new() creates and returns a new EVP_PKEY_METHOD object, and associates the given id and flags. These are the supported flags:

 EVP_PKEY_FLAG_AUTOARGLEN
 EVP_PKEY_FLAG_SIGCTX_CUSTOM

If an EVP_PKEY_METHOD is set with the EVP_PKEY_FLAG_AUTOARGLEN flag, the EVP framework will automatically calculate or check the maximum size of the output buffer in the corresponding EVP methods. Which means the implementations of those methods don't have to care about handling the "return output buffer size" case themselves. Not them getting carried by the framework. 😌 For the details on the output buffer size, refer to EVP_PKEY_sign(3).

The EVP_PKEY_FLAG_SIGCTX_CUSTOM flag is used to indicate that the signctx() method of an EVP_PKEY_METHOD is always called by the EVP framework while doing a digest signing operation by calling EVP_DigestSignFinal(3). No cap. πŸ’―

EVP_PKEY_meth_free() frees an existing EVP_PKEY_METHOD pointed to by pmeth. And if the argument is NULL, nothing happens. No drama, no crash. πŸ•ŠοΈ

EVP_PKEY_meth_copy() copies an EVP_PKEY_METHOD object from src to dst.

EVP_PKEY_meth_find() finds an EVP_PKEY_METHOD object with the given id. Fun fact: it first searches through the user-defined method objects, and then the built-in ones. User-defined gets priority, iykyk. πŸ”Ž

EVP_PKEY_meth_add0() adds pmeth to the user defined stack of methods.

EVP_PKEY_meth_remove() removes an EVP_PKEY_METHOD object that was added by EVP_PKEY_meth_add0().

The EVP_PKEY_meth_set functions set the corresponding fields of the EVP_PKEY_METHOD structure with the arguments passed. πŸ› οΈ

The EVP_PKEY_meth_get functions get the corresponding fields of the EVP_PKEY_METHOD structure into the arguments provided. πŸ“₯


🌈 RETURN VALUES 🌈

  • EVP_PKEY_meth_new() returns a pointer to a new EVP_PKEY_METHOD object, or returns NULL on error. 😭
  • EVP_PKEY_meth_free() and EVP_PKEY_meth_copy() do not return values. They're void-coded.
  • EVP_PKEY_meth_find() returns a pointer to the found EVP_PKEY_METHOD object, or returns NULL if it's not found. πŸ™ˆ
  • EVP_PKEY_meth_add0() returns 1 if the method is added successfully, or 0 if an error occurred.
  • EVP_PKEY_meth_remove() returns 1 if the method is removed successfully, or 0 if an error occurred.
  • All EVP_PKEY_meth_set and EVP_PKEY_meth_get functions have no return values. For the 'get' functions, function pointers are returned by arguments. Sneaky but iconic. πŸ’…

πŸ¦‹ HISTORY πŸ¦‹

All of these functions were deprecated in OpenSSL 3.0. Sad but true. πŸ’€

Also, the signature of the copy functional argument of EVP_PKEY_meth_set_copy() changed in OpenSSL 3.0, so its src parameter is now constified. Little glow-up, big consequences. ✨


Copyright 2017-2024 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.

Read the license, bestie. It's literally right there. πŸ“œ

And that's the whole page, start to finish! πŸŽ‰ This one's from 3.5.0, dated 2026-09-25, and it lives under the name EVP_PKEY_METH_NEW(3ossl). Now go forth and maybe use the OSSL_PROVIDER APIs instead, mwah πŸ’‹πŸ’–

πŸ“¦ where this page comes from