CMS: Export CMS_EnvelopedData and add CMS_EnvelopedData_decrypt()

Also document CMS_decrypt_set1_password() and fix CMS_EnvelopedData_create.pod.

Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: David von Oheimb <david.von.oheimb@siemens.com>
(Merged from https://github.com/openssl/openssl/pull/18301)
This commit is contained in:
Dr. David von Oheimb 2022-05-09 21:00:03 +02:00 committed by Dr. David von Oheimb
parent 61f510600e
commit e2f6960fc5
10 changed files with 113 additions and 41 deletions

View File

@ -52,6 +52,7 @@ static ASN1_ITEM_EXP *asn1_item_list[] = {
ASN1_ITEM_ref(CERTIFICATEPOLICIES),
#ifndef OPENSSL_NO_CMS
ASN1_ITEM_ref(CMS_ContentInfo),
ASN1_ITEM_ref(CMS_EnvelopedData),
ASN1_ITEM_ref(CMS_ReceiptRequest),
#endif
ASN1_ITEM_ref(CRL_DIST_POINTS),

View File

@ -242,6 +242,43 @@ CMS_ContentInfo *CMS_EnvelopedData_create(const EVP_CIPHER *cipher)
return CMS_EnvelopedData_create_ex(cipher, NULL, NULL);
}
BIO *CMS_EnvelopedData_decrypt(CMS_EnvelopedData *env, BIO *detached_data,
EVP_PKEY *pkey, X509 *cert,
ASN1_OCTET_STRING *secret, unsigned int flags,
OSSL_LIB_CTX *libctx, const char *propq)
{
CMS_ContentInfo *ci;
BIO *bio = NULL;
int res = 0;
if (env == NULL) {
ERR_raise(ERR_LIB_CMS, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
}
if ((ci = CMS_ContentInfo_new_ex(libctx, propq)) == NULL
|| (bio = BIO_new(BIO_s_mem())) == NULL)
goto end;
ci->contentType = OBJ_nid2obj(NID_pkcs7_enveloped);
ci->d.envelopedData = env;
if (secret != NULL
&& CMS_decrypt_set1_password(ci, (unsigned char *)
ASN1_STRING_get0_data(secret),
ASN1_STRING_length(secret)) != 1)
goto end;
res = CMS_decrypt(ci, pkey, cert, detached_data, bio, flags);
end:
if (ci != NULL)
ci->d.envelopedData = NULL;
CMS_ContentInfo_free(ci);
if (!res) {
BIO_free(bio);
bio = NULL;
}
return bio;
}
CMS_ContentInfo *
CMS_AuthEnvelopedData_create_ex(const EVP_CIPHER *cipher, OSSL_LIB_CTX *libctx,
const char *propq)

View File

@ -25,7 +25,6 @@ typedef struct CMS_SignedData_st CMS_SignedData;
typedef struct CMS_OtherRevocationInfoFormat_st CMS_OtherRevocationInfoFormat;
typedef struct CMS_OriginatorInfo_st CMS_OriginatorInfo;
typedef struct CMS_EncryptedContentInfo_st CMS_EncryptedContentInfo;
typedef struct CMS_EnvelopedData_st CMS_EnvelopedData;
typedef struct CMS_DigestedData_st CMS_DigestedData;
typedef struct CMS_EncryptedData_st CMS_EncryptedData;
typedef struct CMS_AuthenticatedData_st CMS_AuthenticatedData;

View File

@ -2,8 +2,8 @@
=head1 NAME
CMS_EncryptedData_decrypt
- Decrypt CMS EncryptedData
CMS_EncryptedData_decrypt, CMS_EnvelopedData_decrypt
- Decrypt CMS EncryptedData or EnvelopedData
=head1 SYNOPSIS
@ -13,6 +13,11 @@ CMS_EncryptedData_decrypt
const unsigned char *key, size_t keylen,
BIO *dcont, BIO *out, unsigned int flags);
BIO *CMS_EnvelopedData_decrypt(CMS_EnvelopedData *env, BIO *detached_data,
EVP_PKEY *pkey, X509 *cert,
ASN1_OCTET_STRING *secret, unsigned int flags,
OSSL_LIB_CTX *libctx, const char *propq);
=head1 DESCRIPTION
CMS_EncryptedData_decrypt() decrypts a I<cms> EncryptedData object using the
@ -27,15 +32,27 @@ If the B<CMS_TEXT> flag is set MIME headers for type B<text/plain> are deleted
from the content. If the content is not of type B<text/plain> then an error is
returned.
CMS_EnvelopedData_decrypt() decrypts, similarly to CMS_decrypt(3),
a CMS EnvelopedData object I<env> using the symmetric key I<secret> or
the private key of the recipient B<pkey> and its associated certificate B<cert>.
The optional parameters I<flags> and I<dcont> are used as described above.
The optional parameters library context I<libctx> and property query I<propq>
are used when retrieving algorithms from providers.
=head1 RETURN VALUES
CMS_EncryptedData_decrypt() returns 0 if an error occurred otherwise it
returns 1.
CMS_EncryptedData_decrypt() returns 0 if an error occurred otherwise returns 1.
CMS_EnvelopedData_decrypt() returns NULL if an error occurred,
otherwise a BIO containing the decypted content.
=head1 SEE ALSO
L<ERR_get_error(3)>, L<CMS_EncryptedData_encrypt(3)>
L<ERR_get_error(3)>, L<CMS_EncryptedData_encrypt(3)>, L<CMS_decrypt(3)>
=head1 HISTORY
CMS_EnvelopedData_decrypt() was added in OpenSSL 3.1.
=head1 COPYRIGHT

View File

@ -42,20 +42,22 @@ L<CMS_add0_recipient_key(3)>.
The B<CMS_ContentInfo> structure needs to be finalized using L<CMS_final(3)>
and then freed using L<CMS_ContentInfo_free(3)>.
CMS_EnvelopedData_create() and CMS_AuthEnvelopedData_create are similar to
CMS_EnvelopedData_create_ex() and
CMS_AuthEnvelopedData_create_ex() but use default values of NULL for
CMS_EnvelopedData_create() and CMS_AuthEnvelopedData_create() are similar to
CMS_EnvelopedData_create_ex() and CMS_AuthEnvelopedData_create_ex()
but use default values of NULL for
the library context I<libctx> and the property query I<propq>.
=head1 NOTES
Although CMS_EnvelopedData_create() and CMS_AuthEnvelopedData_create() allocate
Although CMS_EnvelopedData_create_ex(), and CMS_EnvelopedData_create(),
CMS_AuthEnvelopedData_create_ex(), and CMS_AuthEnvelopedData_create() allocate
a new B<CMS_ContentInfo> structure, they are not usually used in applications.
The wrappers L<CMS_encrypt(3)> and L<CMS_decrypt(3)> are often used instead.
=head1 RETURN VALUES
If the allocation fails, CMS_EnvelopedData_create() and
If the allocation fails, CMS_EnvelopedData_create_ex(),
CMS_EnvelopedData_create(), CMS_AuthEnvelopedData_create_ex(), and
CMS_AuthEnvelopedData_create() return NULL and set an error code that can be
obtained by L<ERR_get_error(3)>. Otherwise they return a pointer to the newly
allocated structure.

View File

@ -2,8 +2,9 @@
=head1 NAME
CMS_decrypt, CMS_decrypt_set1_pkey_and_peer, CMS_decrypt_set1_pkey - decrypt
content from a CMS envelopedData structure
CMS_decrypt, CMS_decrypt_set1_pkey_and_peer,
CMS_decrypt_set1_pkey, CMS_decrypt_set1_password
- decrypt content from a CMS envelopedData structure
=head1 SYNOPSIS
@ -14,23 +15,28 @@ content from a CMS envelopedData structure
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);
=head1 DESCRIPTION
CMS_decrypt() extracts and decrypts the content from a CMS EnvelopedData
or AuthEnvelopedData structure. B<pkey> is the private key of the recipient,
B<cert> is the recipient's certificate, B<out> is a BIO to write the content to
and B<flags> is an optional set of flags.
or AuthEnvelopedData structure. I<pkey> is the private key of the recipient,
I<cert> is the recipient's certificate, I<out> is a BIO to write the content to
and I<flags> is an optional set of flags.
The B<dcont> parameter is used in the rare case where the encrypted content
The I<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() associates the private key B<pkey>, the
corresponding certificate B<cert> and the originator certificate B<peer> with
the CMS_ContentInfo structure B<cms>.
CMS_decrypt_set1_pkey_and_peer() associates the private key I<pkey>, the
corresponding certificate I<cert> and the originator certificate I<peer> with
the CMS_ContentInfo structure I<cms>.
CMS_decrypt_set1_pkey() associates the private key B<pkey>, corresponding
certificate B<cert> with the CMS_ContentInfo structure B<cms>.
CMS_decrypt_set1_pkey() associates the private key I<pkey> and the corresponding
certificate I<cert> with the CMS_ContentInfo structure I<cms>.
CMS_decrypt_set1_password() associates the secret I<pass> of length I<passlen>
with the CMS_ContentInfo structure I<cms>.
=head1 NOTES
@ -38,7 +44,7 @@ Although the recipients certificate is not needed to decrypt the data it is
needed to locate the appropriate (of possible several) recipients in the CMS
structure.
If B<cert> is set to NULL all possible recipients are tried. This case however
If I<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
@ -55,22 +61,24 @@ open to attack.
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(). In this
case both B<cert> and B<pkey> should be set to NULL.
case both I<cert> and I<pkey> should be set to NULL.
To process KEKRecipientInfo types CMS_set1_key() or CMS_RecipientInfo_set0_key()
and CMS_RecipientInfo_decrypt() should be called before CMS_decrypt() and
B<cert> and B<pkey> set to NULL.
I<cert> and I<pkey> set to NULL.
The following flags can be passed in the B<flags> parameter.
The following flags can be passed in the I<flags> parameter.
If the B<CMS_TEXT> flag is set MIME headers for type B<text/plain> are deleted
from the content. If the content is not of type B<text/plain> then an error is
If the B<CMS_TEXT> flag is set MIME headers for type C<text/plain> are deleted
from the content. If the content is not of type C<text/plain> then an error is
returned.
=head1 RETURN VALUES
CMS_decrypt() returns either 1 for success or 0 for failure.
The error can be obtained from ERR_get_error(3)
CMS_decrypt(), CMS_decrypt_set1_pkey_and_peer(),
CMS_decrypt_set1_pkey(), and CMS_decrypt_set1_password()
return either 1 for success or 0 for failure.
The error can be obtained from ERR_get_error(3).
=head1 BUGS
@ -83,7 +91,8 @@ L<ERR_get_error(3)>, L<CMS_encrypt(3)>
=head1 HISTORY
B<CMS_decrypt_set1_pkey_and_peer> was added in OpenSSL 3.0.
CMS_decrypt_set1_pkey_and_peer() and CMS_decrypt_set1_password()
were added in OpenSSL 3.0.
=head1 COPYRIGHT

View File

@ -31,6 +31,7 @@ CMS_ContentInfo_free,
CMS_ContentInfo_new,
CMS_ContentInfo_new_ex,
CMS_ContentInfo_print_ctx,
CMS_EnvelopedData_it,
CMS_ReceiptRequest_free,
CMS_ReceiptRequest_new,
CRL_DIST_POINTS_free,

View File

@ -32,6 +32,7 @@ use OpenSSL::stackhash qw(generate_stack_macros);
extern "C" {
# endif
typedef struct CMS_EnvelopedData_st CMS_EnvelopedData;
typedef struct CMS_ContentInfo_st CMS_ContentInfo;
typedef struct CMS_SignerInfo_st CMS_SignerInfo;
typedef struct CMS_CertificateChoices CMS_CertificateChoices;
@ -49,6 +50,7 @@ typedef struct CMS_OtherKeyAttribute_st CMS_OtherKeyAttribute;
.generate_stack_macros("CMS_RevocationInfoChoice");
-}
DECLARE_ASN1_ITEM(CMS_EnvelopedData)
DECLARE_ASN1_FUNCTIONS(CMS_ContentInfo)
DECLARE_ASN1_FUNCTIONS(CMS_ReceiptRequest)
DECLARE_ASN1_PRINT_FUNCTION(CMS_ContentInfo)
@ -128,7 +130,7 @@ CMS_ContentInfo *CMS_sign(X509 *signcert, EVP_PKEY *pkey,
unsigned int flags);
CMS_ContentInfo *CMS_sign_ex(X509 *signcert, EVP_PKEY *pkey,
STACK_OF(X509) *certs, BIO *data,
unsigned int flags, OSSL_LIB_CTX *ctx,
unsigned int flags, OSSL_LIB_CTX *libctx,
const char *propq);
CMS_ContentInfo *CMS_sign_receipt(CMS_SignerInfo *si,
@ -138,27 +140,26 @@ CMS_ContentInfo *CMS_sign_receipt(CMS_SignerInfo *si,
int CMS_data(CMS_ContentInfo *cms, BIO *out, unsigned int flags);
CMS_ContentInfo *CMS_data_create(BIO *in, unsigned int flags);
CMS_ContentInfo *CMS_data_create_ex(BIO *in, unsigned int flags,
OSSL_LIB_CTX *ctx, const char *propq);
OSSL_LIB_CTX *libctx, const char *propq);
int CMS_digest_verify(CMS_ContentInfo *cms, BIO *dcont, BIO *out,
unsigned int flags);
CMS_ContentInfo *CMS_digest_create(BIO *in, const EVP_MD *md,
unsigned int flags);
CMS_ContentInfo *CMS_digest_create_ex(BIO *in, const EVP_MD *md,
unsigned int flags, OSSL_LIB_CTX *ctx,
unsigned int flags, OSSL_LIB_CTX *libctx,
const char *propq);
int CMS_EncryptedData_decrypt(CMS_ContentInfo *cms,
const unsigned char *key, size_t keylen,
BIO *dcont, BIO *out, unsigned int flags);
CMS_ContentInfo *CMS_EncryptedData_encrypt(BIO *in, const EVP_CIPHER *cipher,
const unsigned char *key,
size_t keylen, unsigned int flags);
CMS_ContentInfo *CMS_EncryptedData_encrypt_ex(BIO *in, const EVP_CIPHER *cipher,
const unsigned char *key,
size_t keylen, unsigned int flags,
OSSL_LIB_CTX *ctx,
OSSL_LIB_CTX *libctx,
const char *propq);
int CMS_EncryptedData_set1_key(CMS_ContentInfo *cms, const EVP_CIPHER *ciph,
@ -177,7 +178,7 @@ CMS_ContentInfo *CMS_encrypt(STACK_OF(X509) *certs, BIO *in,
const EVP_CIPHER *cipher, unsigned int flags);
CMS_ContentInfo *CMS_encrypt_ex(STACK_OF(X509) *certs, BIO *in,
const EVP_CIPHER *cipher, unsigned int flags,
OSSL_LIB_CTX *ctx, const char *propq);
OSSL_LIB_CTX *libctx, const char *propq);
int CMS_decrypt(CMS_ContentInfo *cms, EVP_PKEY *pkey, X509 *cert,
BIO *dcont, BIO *out, unsigned int flags);
@ -196,12 +197,16 @@ int CMS_RecipientInfo_type(CMS_RecipientInfo *ri);
EVP_PKEY_CTX *CMS_RecipientInfo_get0_pkey_ctx(CMS_RecipientInfo *ri);
CMS_ContentInfo *CMS_AuthEnvelopedData_create(const EVP_CIPHER *cipher);
CMS_ContentInfo *
CMS_AuthEnvelopedData_create_ex(const EVP_CIPHER *cipher, OSSL_LIB_CTX *ctx,
CMS_AuthEnvelopedData_create_ex(const EVP_CIPHER *cipher, OSSL_LIB_CTX *libctx,
const char *propq);
CMS_ContentInfo *CMS_EnvelopedData_create(const EVP_CIPHER *cipher);
CMS_ContentInfo *CMS_EnvelopedData_create_ex(const EVP_CIPHER *cipher,
OSSL_LIB_CTX *ctx,
OSSL_LIB_CTX *libctx,
const char *propq);
BIO *CMS_EnvelopedData_decrypt(CMS_EnvelopedData *env, BIO *detached_data,
EVP_PKEY *pkey, X509 *cert,
ASN1_OCTET_STRING *secret, unsigned int flags,
OSSL_LIB_CTX *libctx, const char *propq);
CMS_RecipientInfo *CMS_add1_recipient_cert(CMS_ContentInfo *cms,
X509 *recip, unsigned int flags);
@ -346,7 +351,7 @@ CMS_ReceiptRequest *CMS_ReceiptRequest_create0_ex(
unsigned char *id, int idlen, int allorfirst,
STACK_OF(GENERAL_NAMES) *receiptList,
STACK_OF(GENERAL_NAMES) *receiptsTo,
OSSL_LIB_CTX *ctx);
OSSL_LIB_CTX *libctx);
int CMS_add1_ReceiptRequest(CMS_SignerInfo *si, CMS_ReceiptRequest *rr);
void CMS_ReceiptRequest_get0_values(CMS_ReceiptRequest *rr,

View File

@ -5438,5 +5438,7 @@ ASYNC_set_mem_functions ? 3_1_0 EXIST::FUNCTION:
ASYNC_get_mem_functions ? 3_1_0 EXIST::FUNCTION:
BIO_ADDR_dup ? 3_1_0 EXIST::FUNCTION:SOCK
CMS_final_digest ? 3_1_0 EXIST::FUNCTION:CMS
CMS_EnvelopedData_it ? 3_1_0 EXIST::FUNCTION:CMS
CMS_EnvelopedData_decrypt ? 3_1_0 EXIST::FUNCTION:CMS
OPENSSL_strcasecmp ? 3_0_3 EXIST::FUNCTION:
OPENSSL_strncasecmp ? 3_0_3 EXIST::FUNCTION:

View File

@ -328,7 +328,6 @@ CMS_data(3)
CMS_dataFinal(3)
CMS_dataInit(3)
CMS_decrypt_set1_key(3)
CMS_decrypt_set1_password(3)
CMS_digest_verify(3)
CMS_is_detached(3)
CMS_set1_signers_certs(3)