PROVIDER-CIPHER(7SSL)
π provider-cipher(7SSL) π
okay bestie, buckle up π this is the page that explains how a cipher talks back and forth between the library and the provider β like, the whole little friendship contract between the two sides. it's giving backstage pass energy. there's no actual callable function anywhere on this page (more on that in a sec), so don't go trying to link against it, okay? π₯
πΈ NAME πΈ
provider-cipher β the cipher library <-> provider functions π¦
β¨ SYNOPSIS β¨
#include <openssl/core_dispatch.h>
#include <openssl/core_names.h>
/*
* 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_cipher_newctx(void *provctx);
void OSSL_FUNC_cipher_freectx(void *cctx);
void *OSSL_FUNC_cipher_dupctx(void *cctx);
/* Encryption/decryption */
int OSSL_FUNC_cipher_encrypt_init(void *cctx, const unsigned char *key,
size_t keylen, const unsigned char *iv,
size_t ivlen, const OSSL_PARAM params[]);
int OSSL_FUNC_cipher_decrypt_init(void *cctx, const unsigned char *key,
size_t keylen, const unsigned char *iv,
size_t ivlen, const OSSL_PARAM params[]);
int OSSL_FUNC_cipher_encrypt_skey_init(void *cctx, void *skeydata,
const unsigned char *iv, size_t ivlen,
const OSSL_PARAM params[]);
int OSSL_FUNC_cipher_encrypt_skey_init(void *cctx, void *skeydata,
const unsigned char *iv, size_t ivlen,
const OSSL_PARAM params[]);
int OSSL_FUNC_cipher_update(void *cctx, unsigned char *out, size_t *outl,
size_t outsize, const unsigned char *in, size_t inl);
int OSSL_FUNC_cipher_final(void *cctx, unsigned char *out, size_t *outl,
size_t outsize);
int OSSL_FUNC_cipher_cipher(void *cctx, unsigned char *out, size_t *outl,
size_t outsize, const unsigned char *in, size_t inl);
/* Encryption/decryption using cipher pipeline */
int OSSL_FUNC_cipher_pipeline_encrypt_init(void *cctx, const unsigned char *key,
size_t keylen, size_t numpipes,
const unsigned char **iv, size_t ivlen,
const OSSL_PARAM params[]))
int OSSL_FUNC_cipher_pipeline_decrypt_init(void *cctx, const unsigned char *key,
size_t keylen, size_t numpipes,
const unsigned char **iv, size_t ivlen,
const OSSL_PARAM params[]))
int OSSL_FUNC_cipher_pipeline_update(void *cctx, size_t numpipes,
unsigned char **out, size_t *outl,
const size_t *outsize,
const unsigned char **in, const size_t *inl))
int OSSL_FUNC_cipher_pipeline_final(void *cctx, size_t numpipes,
unsigned char **out, size_t *outl,
const size_t *outsize))
/* Cipher parameter descriptors */
const OSSL_PARAM *OSSL_FUNC_cipher_gettable_params(void *provctx);
/* Cipher operation parameter descriptors */
const OSSL_PARAM *OSSL_FUNC_cipher_gettable_ctx_params(void *cctx,
void *provctx);
const OSSL_PARAM *OSSL_FUNC_cipher_settable_ctx_params(void *cctx,
void *provctx);
/* Cipher parameters */
int OSSL_FUNC_cipher_get_params(OSSL_PARAM params[]);
/* Cipher operation parameters */
int OSSL_FUNC_cipher_get_ctx_params(void *cctx, OSSL_PARAM params[]);
int OSSL_FUNC_cipher_set_ctx_params(void *cctx, const OSSL_PARAM params[]);
π«Ά real talk for a sec: none of these are actual functions. they're the signatures of functions that a provider hands over as function pointers inside OSSL_DISPATCH arrays. so they look like C functions 'cause that's the clearest way to show you the shape of 'em, but you'll never find a symbol with these names to call. β¨
okay and that's just the sneak peek π β the actual tea about what each of these does is coming in the next part, so stay with me bestie π
π DESCRIPTION π
okay so bestie, listen up β this whole page is primarily for provider authors. like, the girlies writing the actual crypto backends. if you're not one of those, go peek at provider(7) for the full lore first, mmkay?
The CIPHER operation is what lets providers implement cipher algorithms and hand them off to applications through the API functions EVP_EncryptInit_ex(3), EVP_EncryptUpdate(3) and EVP_EncryptFinal(3) β plus all the decrypt equivalents and the other related functions that tag along. it's giving... cryptography delivery service π
so all the "functions" I'm about to talk about? they're not like, actual functions. they're function pointers that get passed between libcrypto and the provider inside OSSL_DISPATCH(3) arrays, which in turn live inside OSSL_ALGORITHM(3) arrays β and those get returned by the provider's provider_query_operation() function. (check "Provider Functions" in provider-base(7) if you want the receipts π«Ά)
every one of these "functions" has a matching function type definition named OSSL_FUNC_{name}_fn, plus a little helper function that fishes the function pointer out of an OSSL_DISPATCH(3) element named OSSL_FUNC_{name}. for example, the "function" OSSL_FUNC_cipher_newctx() comes with these two ride-or-dies:
typedef void *(OSSL_FUNC_cipher_newctx_fn)(void *provctx);
static ossl_inline OSSL_FUNC_cipher_newctx_fn
OSSL_FUNC_cipher_newctx(const OSSL_DISPATCH *opf);
OSSL_DISPATCH(3) arrays are indexed by numbers, and those numbers are provided as macros in openssl-core_dispatch.h(7). the glow-up looks like this:
OSSL_FUNC_cipher_newctx OSSL_FUNC_CIPHER_NEWCTX
OSSL_FUNC_cipher_freectx OSSL_FUNC_CIPHER_FREECTX
OSSL_FUNC_cipher_dupctx OSSL_FUNC_CIPHER_DUPCTX
OSSL_FUNC_cipher_encrypt_init OSSL_FUNC_CIPHER_ENCRYPT_INIT
OSSL_FUNC_cipher_decrypt_init OSSL_FUNC_CIPHER_DECRYPT_INIT
OSSL_FUNC_cipher_encrypt_skey_init OSSL_FUNC_CIPHER_ENCRYPT_SKEY_INIT
OSSL_FUNC_cipher_decrypt_skey_init OSSL_FUNC_CIPHER_DECRYPT_SKEY_INIT
OSSL_FUNC_cipher_update OSSL_FUNC_CIPHER_UPDATE
OSSL_FUNC_cipher_final OSSL_FUNC_CIPHER_FINAL
OSSL_FUNC_cipher_cipher OSSL_FUNC_CIPHER_CIPHER
OSSL_FUNC_cipher_pipeline_encrypt_init OSSL_FUNC_CIPHER_PIPELINE_ENCRYPT_INIT
OSSL_FUNC_cipher_pipeline_decrypt_init OSSL_FUNC_CIPHER_PIPELINE_DECRYPT_INIT
OSSL_FUNC_cipher_pipeline_update OSSL_FUNC_CIPHER_PIPELINE_UPDATE
OSSL_FUNC_cipher_pipeline_final OSSL_FUNC_CIPHER_PIPELINE_FINAL
OSSL_FUNC_cipher_get_params OSSL_FUNC_CIPHER_GET_PARAMS
OSSL_FUNC_cipher_get_ctx_params OSSL_FUNC_CIPHER_GET_CTX_PARAMS
OSSL_FUNC_cipher_set_ctx_params OSSL_FUNC_CIPHER_SET_CTX_PARAMS
OSSL_FUNC_cipher_gettable_params OSSL_FUNC_CIPHER_GETTABLE_PARAMS
OSSL_FUNC_cipher_gettable_ctx_params OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS
OSSL_FUNC_cipher_settable_ctx_params OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS
and here's the vibe check on which ones you actually need: a cipher algorithm implementation doesn't have to implement all of these. β¨ but to be a consistent set of functions, you need at least one of these three situations:
- a complete set of "encrypt" functions, or
- a complete set of "decrypt" functions, or
- a single "cipher" function.
same energy for pipelines β you can have a complete set of pipeline "encrypt" functions, and/or a complete set of pipeline "decrypt" functions. π₯
but in ALL cases β every single one, no exceptions β OSSL_FUNC_cipher_get_params, OSSL_FUNC_cipher_newctx and OSSL_FUNC_cipher_freectx must be present. everything else is optional, bestie. do with that what you will π
π Context Management Functions π
OSSL_FUNC_cipher_newctx() should create and return a pointer to a provider side structure β this is the little home where context info lives during a cipher operation. a pointer to this context gets passed back in a bunch of the other cipher operation function calls. the provctx parameter is the provider context that got generated during provider initialisation (peep provider(7) for that one).
OSSL_FUNC_cipher_freectx() gets handed a pointer to the provider side cipher context in the cctx parameter, and it should free up all the resources associated with that context. clean up after yourself, periodt π§Ή
OSSL_FUNC_cipher_dupctx() should duplicate the provider side cipher context in the cctx parameter and return the duplicate copy. twin moment π―
π Encryption/Decryption Functions π
OSSL_FUNC_cipher_encrypt_init() initialises a cipher operation for encryption, given a freshly created provider side cipher context in the cctx parameter. the key it's gonna use comes in key, which is keylen bytes long. the IV comes in iv, which is ivlen bytes long. and params, if it's not NULL, should be set on the context kinda the same way you'd do it with OSSL_FUNC_cipher_set_ctx_params().
OSSL_FUNC_cipher_decrypt_init() is literally the same as OSSL_FUNC_cipher_encrypt_init() except it initialises the context for a decryption operation instead. you know, decrypting. the other one. π
OSSL_FUNC_cipher_encrypt_skey_init() and OSSL_FUNC_cipher_decrypt_skey_init() are variants of OSSL_FUNC_cipher_encrypt_init() and OSSL_FUNC_cipher_decrypt_init() for working with opaque objects containing provider-specific key handles instead of raw bytes. fancy. mysterious. we love her.
OSSL_FUNC_cipher_update() gets called to supply data that needs to be encrypted/decrypted, as part of a cipher operation that's already been initialised. the cctx parameter holds a pointer to a previously initialised provider side context. OSSL_FUNC_cipher_update() should encrypt/decrypt inl bytes of data at the location pointed to by in. the encrypted data should be stored in out, and the amount of data written goes to *outl β which should not exceed outsize bytes, no cap.
OSSL_FUNC_cipher_update() may be called multiple times for a single cipher operation, so don't get cocky. and it's the cipher implementation's responsibility to handle input lengths that aren't multiples of the block length. in those cases, a cipher implementation will typically cache partial blocks of input data until it has a whole complete block to work with. π§©
the pointers out and in may point to the same location β and if they do, the encryption must be done in-place. if out and in point to different locations, the requirements of EVP_EncryptUpdate(3) and EVP_DecryptUpdate(3) guarantee that the two buffers are disjoint. and similarly, the requirements of EVP_EncryptUpdate(3) and EVP_DecryptUpdate(3) ensure that the buffer pointed to by out contains sufficient room for the operation being performed. so like, the space is handled. breathe. π«Ά
OSSL_FUNC_cipher_final() completes an encryption or decryption that got started through previous OSSL_FUNC_cipher_encrypt_init() or OSSL_FUNC_cipher_decrypt_init() and OSSL_FUNC_cipher_update() calls. the cctx parameter holds a pointer to the provider side context. any final encryption/decryption output should be written to out, and the amount of data written goes to *outl β which should not exceed outsize bytes. the same expectations apply to outsize as documented for EVP_EncryptFinal(3) and EVP_DecryptFinal(3). π
OSSL_FUNC_cipher_cipher() performs encryption/decryption using the provider side cipher context in the cctx parameter, which should have been previously initialised via a call to OSSL_FUNC_cipher_encrypt_init() or OSSL_FUNC_cipher_decrypt_init(). this one should call the raw underlying cipher function without any padding. it'll get invoked in the provider as a result of the application calling EVP_Cipher(3).
heads up bestie: with this one, the application is responsible for making sure the input is a multiple of the block length. not you. them. okay? iconic of them.
the data to be encrypted/decrypted will be in in, and it'll be inl bytes in length. the output from the encryption/decryption should be stored in out, and the amount of data stored should be put in *outl β which should be no more than outsize bytes.
OSSL_FUNC_cipher_pipeline_encrypt_init(), OSSL_FUNC_cipher_pipeline_decrypt_init(), OSSL_FUNC_cipher_pipeline_update(), and OSSL_FUNC_cipher_pipeline_final() are all similar to the non-pipeline variants, BUT they get used when the application is using cipher pipelining. π° here's the deets:
- the
numpipesparameter is the number of pipes in the pipeline. - the
ivparameter is an array of buffers with IVs, eachivlenbytes long. - the
inandoutare arrays of buffer pointers. - the
inlandoutl,outsizeare arrays ofsize_trepresenting corresponding buffer length, similar to the non-pipeline variants. - all arrays are of length
numpipes.
want more? see EVP_CipherPipelineEncryptInit(3) for more information. π
πΈ Cipher Parameters πΈ
see OSSL_PARAM(3) for further details on the parameters structure these functions use. (yes, the params structure. we stan a well-documented struct.)
OSSL_FUNC_cipher_get_params() gets the details of the algorithm implementation and stores them in params.
OSSL_FUNC_cipher_set_ctx_params() sets cipher operation parameters for the provider side cipher context cctx to params. any parameter settings are additional to any that were previously set. and passing NULL for params should return true. yes, really.
OSSL_FUNC_cipher_get_ctx_params() gets cipher operation details β details details, the original says it twice and honestly, same, it's that important β from the given provider side cipher context cctx and stores them in params. passing NULL for params should return true here too.
OSSL_FUNC_cipher_gettable_params(), OSSL_FUNC_cipher_gettable_ctx_params(), and OSSL_FUNC_cipher_settable_ctx_params() all return constant OSSL_PARAM(3) arrays, acting as descriptors of the parameters that OSSL_FUNC_cipher_get_params(), OSSL_FUNC_cipher_get_ctx_params(), and OSSL_FUNC_cipher_set_ctx_params() can handle, respectively. gettable/gettable/settable. you got this. π
OSSL_FUNC_cipher_gettable_ctx_params() and OSSL_FUNC_cipher_settable_ctx_params() will return the parameters associated with the provider side context cctx in its current state if it is not NULL. otherwise, they return the parameters associated with the provider side algorithm provctx.
the parameters currently recognised by built-in ciphers are listed in "PARAMETERS" in EVP_EncryptInit(3). and ngl β not all parameters are relevant to, or understood by, all ciphers. every cipher is on its own journey. π¦
β RETURN VALUES β
OSSL_FUNC_cipher_newctx() and OSSL_FUNC_cipher_dupctx() should return the newly created provider side cipher context, or NULL on failure. simple as.
these ones should all return 1 for success or 0 on error:
OSSL_FUNC_cipher_encrypt_init()OSSL_FUNC_cipher_decrypt_init()OSSL_FUNC_cipher_update()OSSL_FUNC_cipher_final()OSSL_FUNC_cipher_cipher()OSSL_FUNC_cipher_encrypt_skey_init()OSSL_FUNC_cipher_decrypt_skey_init()OSSL_FUNC_cipher_pipeline_encrypt_init()OSSL_FUNC_cipher_pipeline_decrypt_init()OSSL_FUNC_cipher_pipeline_update()OSSL_FUNC_cipher_pipeline_final()OSSL_FUNC_cipher_get_params()OSSL_FUNC_cipher_get_ctx_params()OSSL_FUNC_cipher_set_ctx_params()
and then OSSL_FUNC_cipher_gettable_params(), OSSL_FUNC_cipher_gettable_ctx_params() and OSSL_FUNC_cipher_settable_ctx_params() should return a constant OSSL_PARAM(3) array, or NULL if none is offered. that's the whole vibe. π
π SEE ALSO π
provider(7), OSSL_PROVIDER-FIPS(7), OSSL_PROVIDER-default(7), OSSL_PROVIDER-legacy(7), EVP_CIPHER-AES(7), EVP_CIPHER-ARIA(7), EVP_CIPHER-BLOWFISH(7), EVP_CIPHER-CAMELLIA(7), EVP_CIPHER-CAST(7), EVP_CIPHER-CHACHA(7), EVP_CIPHER-DES(7), EVP_CIPHER-IDEA(7), EVP_CIPHER-RC2(7), EVP_CIPHER-RC4(7), EVP_CIPHER-RC5(7), EVP_CIPHER-SEED(7), EVP_CIPHER-SM4(7), EVP_CIPHER-NULL(7), life_cycle-cipher(7), EVP_EncryptInit(3) π«Άβ¨
β¨ HISTORY β¨
okay so storytime π β the provider CIPHER interface? brand new baby in OpenSSL 3.0. that's when it dropped, that's when the whole cipher-provider era started, and honestly the girls were gagged. π
and then LATER, bestie, we got more. the functions OSSL_FUNC_cipher_encrypt_skey_init() and OSSL_FUNC_cipher_decrypt_skey_init()? those pulled up fashionably late in OpenSSL 3.5. β¨ so if you were writing provider code before 3.5 and wondering where the skey init love wasβ¦ yeah, it wasn't born yet. it's giving glow-up, it's giving character development. π¦
π COPYRIGHT π
Copyright 2019-2025 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the Apache License 2.0 (the "License"). bestie you literally may not use this file except in compliance with the License β no cap, that part is not a vibe suggestion, it's the rules. π
you can grab a copy of the License right here:
- in the file
LICENSEin the source distribution, or - at <https://www.openssl.org/source/license.html>
legal girlies stay winning π read the LICENSE, it's iconic, it's required
and that's a wrap on PROVIDER-CIPHER(7SSL) π«Ά tysm for reading the whole thing, my little cipher-obsessed main characters. this page is from the 4.0.3 era, dated 2026-09-29 β so go forth, write your providers, and slay. ππΈπ¦βπ
π¦ where this page comes from
- ubuntu stonking: openssl 4.0.3-1ubuntu1
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms