CMS_DECRYPT(3ossl)
π CMS_DECRYPT β the OpenSSL 3ossl girlie's guide π
okay so this page is all about CMS_decrypt and its little set1_ squad, and it lives in the OpenSSL manual, section 3ossl. we're talking decrypting content from a CMS envelopedData structure and honestly? it's giving locked-treasure-chest energy πβ¨
πΈ SYNOPSIS πΈ
like, the vibes are three headers and four functions, no biggie:
#include <openssl/cms.h>
int CMS_decrypt(CMS_ContentInfo *cms, EVP_PKEY *pkey, X509 *cert,
BIO *dcont, BIO *out, unsigned int flags);
int CMS_decrypt_set1_pkey_and_peer(CMS_ContentInfo *cms,
EVP_PKEY *pk, X509 *cert, X509 *peer);
int CMS_decrypt_set1_pkey(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert);
int CMS_decrypt_set1_password(CMS_ContentInfo *cms,
unsigned char *pass, ossl_ssize_t passlen);
β¨ DESCRIPTION β¨
bestie, let's go one by one π
π CMS_decrypt()
okay so CMS_decrypt() extracts the decrypted content from a CMS EnvelopedData or AuthEnvelopedData structure β like unzipping the vibe, yk?
it uses CMS_decrypt_set1_pkey() to decrypt the content with the recipient private key pkey β if pkey is not NULL. and in this case, the associated certificate is recommended to provide in cert (peep the NOTES below, iykyk π). out is a BIO to write the content to, and flags is an optional set of flags.
but wait β if pkey is NULL, the function assumes decryption was already done (e.g., using CMS_decrypt_set1_pkey() or CMS_decrypt_set1_password()) and just provides the content, unless cert, dcont, and out are NULL as well. lowkey efficient β¨
the dcont parameter is used in the rare case where the encrypted content is detached. it will normally be set to NULL.
π¦ CMS_decrypt_set1_pkey_and_peer()
this one decrypts the CMS_ContentInfo structure cms using the private key pkey, the corresponding certificate cert (which is recommended but may be NULL), and the (optional) originator certificate peer.
on success, it also records in cms the decryption key pkey, and then should be followed by "CMS_decrypt(cms, NULL, NULL, dcont, out, flags)". and heads up β this call deallocates any decryption key stored in cms. periodt. π
π CMS_decrypt_set1_pkey()
literally just CMS_decrypt_set1_pkey_and_peer() with peer being NULL. same icon, smaller accessory. π«Ά
π CMS_decrypt_set1_password()
this one decrypts the CMS_ContentInfo structure cms using the secret pass of length passlen.
on success, it also records in cms the decryption key used, and then should be followed by "CMS_decrypt(cms, NULL, NULL, dcont, out, flags)". also β this call deallocates any decryption key stored in cms. so don't come crying later, bestie π
π NOTES π
ngl this part is the main character energy of the whole page. read it. fr fr.
although the recipient's certificate is not needed to decrypt the data, it is needed to locate the appropriate (of possible several) recipients in the CMS structure. so like, use it pls π
if cert is set to NULL, all possible recipients are tried. this case however is problematic. π¨ to thwart the MMA attack (Bleichenbacher's attack on PKCS #1 v1.5 RSA padding) all recipients are tried whether they succeed or not. if no recipient succeeds, then a random symmetric key is used to decrypt the content: this will typically output garbage and may (but is not guaranteed to) ultimately return a padding error only.
π the reason is timing: if CMS_decrypt() just returned an error when all recipient encrypted keys failed to decrypt, an attacker could use this in a timing attack. so the paranoia is load-bearing.
if the special flag CMS_DEBUG_DECRYPT is set, then the above behaviour is modified and an error is returned if no recipient encrypted key can be decrypted without generating a random content encryption key. but bestie β applications should use this flag with extreme caution, especially in automated gateways, as it can leave them open to attack. π₯ seriously. see EVP_PKEY_decrypt(3) for more details.
it is possible to determine the correct recipient key by other means (for example, looking them up in a database) and setting them in the CMS structure in advance using the CMS utility functions such as CMS_set1_pkey(), or use CMS_decrypt_set1_password() if the recipient has a symmetric key. in these cases both cert and pkey should be set to NULL. cute and clean β¨
to process KEKRecipientInfo types, CMS_set1_key() or CMS_RecipientInfo_set0_key() and CMS_RecipientInfo_decrypt() should be called before CMS_decrypt(), and cert and pkey set to NULL. order matters, bb π
π§ the flags parameter
the following flags can be passed in the flags parameter:
CMS_TEXTβ if this flag is set, MIME headers for type"text/plain"are deleted from the content. if the content is not of type"text/plain", then an error is returned. no mixing vibes π«
β RETURN VALUES β
CMS_decrypt(), CMS_decrypt_set1_pkey_and_peer(), CMS_decrypt_set1_pkey(), and CMS_decrypt_set1_password() all return either 1 for success or 0 for failure. and the error can be obtained from ERR_get_error(3). so when it flops, go ask ERR_get_error(3) what happened π
π BUGS π
- the
set1_part of these function names is misleading and should better read:with_. like, not me reading "set1_" and getting it wrong every time π (we keep the names as-is, obviously β don't go renaming anything, bestie.) - the lack of single pass processing and the need to hold all data in memory, as mentioned in
CMS_verify(), also applies toCMS_decrypt(). so yeah, memory go brrr π
π SEE ALSO π
go read these next, they're the supporting cast:
πΈ HISTORY πΈ
CMS_decrypt_set1_pkey_and_peer() and CMS_decrypt_set1_password() were added in OpenSSL 3.0. newer icons, same slay π
π COPYRIGHT π
Copyright 2008-2020 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 π«Ά mwah π β this masterpiece dropped as part of OpenSSL 3.5.0, dated 2026-09-25, and yes the page itself is CMS_DECRYPT(3ossl) πβ¨
π¦ where this page comes from
- opensuse-leap 16.0: openssl-3-doc 3.5.0-160000.11.1 Β· Apache-2.0
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms