diff options
author | Dr. David von Oheimb <David.von.Oheimb@siemens.com> | 2022-05-09 21:00:03 +0200 |
---|---|---|
committer | Dr. David von Oheimb <dev@ddvo.net> | 2022-06-28 17:51:21 +0200 |
commit | e2f6960fc5fe1d6eb2178adf51db1ed206ff9e90 (patch) | |
tree | bc336323cf198db2c004e7490bbf47e24fe23740 | |
parent | 61f510600e2c7cdee6e61f8b7075fb0e939eb179 (diff) | |
download | openssl-new-e2f6960fc5fe1d6eb2178adf51db1ed206ff9e90.tar.gz |
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)
-rw-r--r-- | crypto/asn1/asn1_item_list.h | 1 | ||||
-rw-r--r-- | crypto/cms/cms_env.c | 37 | ||||
-rw-r--r-- | crypto/cms/cms_local.h | 1 | ||||
-rw-r--r-- | doc/man3/CMS_EncryptedData_decrypt.pod | 27 | ||||
-rw-r--r-- | doc/man3/CMS_EnvelopedData_create.pod | 12 | ||||
-rw-r--r-- | doc/man3/CMS_decrypt.pod | 49 | ||||
-rw-r--r-- | doc/man3/X509_dup.pod | 1 | ||||
-rw-r--r-- | include/openssl/cms.h.in | 23 | ||||
-rw-r--r-- | util/libcrypto.num | 2 | ||||
-rw-r--r-- | util/missingcrypto.txt | 1 |
10 files changed, 113 insertions, 41 deletions
diff --git a/crypto/asn1/asn1_item_list.h b/crypto/asn1/asn1_item_list.h index 1432012b7c..72299a7b6b 100644 --- a/crypto/asn1/asn1_item_list.h +++ b/crypto/asn1/asn1_item_list.h @@ -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), diff --git a/crypto/cms/cms_env.c b/crypto/cms/cms_env.c index 24632fa9c1..471676d2f5 100644 --- a/crypto/cms/cms_env.c +++ b/crypto/cms/cms_env.c @@ -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) diff --git a/crypto/cms/cms_local.h b/crypto/cms/cms_local.h index 096235c0fa..d16ca95176 100644 --- a/crypto/cms/cms_local.h +++ b/crypto/cms/cms_local.h @@ -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; diff --git a/doc/man3/CMS_EncryptedData_decrypt.pod b/doc/man3/CMS_EncryptedData_decrypt.pod index 17850a98af..930ac3340b 100644 --- a/doc/man3/CMS_EncryptedData_decrypt.pod +++ b/doc/man3/CMS_EncryptedData_decrypt.pod @@ -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 diff --git a/doc/man3/CMS_EnvelopedData_create.pod b/doc/man3/CMS_EnvelopedData_create.pod index e5ff269e47..9dfd0ad77d 100644 --- a/doc/man3/CMS_EnvelopedData_create.pod +++ b/doc/man3/CMS_EnvelopedData_create.pod @@ -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. diff --git a/doc/man3/CMS_decrypt.pod b/doc/man3/CMS_decrypt.pod index 4f8d32fbbb..3d3a4e0693 100644 --- a/doc/man3/CMS_decrypt.pod +++ b/doc/man3/CMS_decrypt.pod @@ -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 diff --git a/doc/man3/X509_dup.pod b/doc/man3/X509_dup.pod index bc80caa51c..e24922bcf1 100644 --- a/doc/man3/X509_dup.pod +++ b/doc/man3/X509_dup.pod @@ -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, diff --git a/include/openssl/cms.h.in b/include/openssl/cms.h.in index 749b92cbcf..4be44b4bac 100644 --- a/include/openssl/cms.h.in +++ b/include/openssl/cms.h.in @@ -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, diff --git a/util/libcrypto.num b/util/libcrypto.num index dcd9d02924..cb0d48cfca 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -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: diff --git a/util/missingcrypto.txt b/util/missingcrypto.txt index b93a081f6d..a0937d4d98 100644 --- a/util/missingcrypto.txt +++ b/util/missingcrypto.txt @@ -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) |