aboutsummaryrefslogtreecommitdiff
path: root/openssl/crypto/cms
diff options
context:
space:
mode:
Diffstat (limited to 'openssl/crypto/cms')
-rw-r--r--openssl/crypto/cms/Makefile24
-rw-r--r--openssl/crypto/cms/cms.h22
-rw-r--r--openssl/crypto/cms/cms_asn1.c9
-rw-r--r--openssl/crypto/cms/cms_enc.c60
-rw-r--r--openssl/crypto/cms/cms_env.c22
-rw-r--r--openssl/crypto/cms/cms_err.c13
-rw-r--r--openssl/crypto/cms/cms_lcl.h12
-rw-r--r--openssl/crypto/cms/cms_lib.c3
-rw-r--r--openssl/crypto/cms/cms_pwri.c454
-rw-r--r--openssl/crypto/cms/cms_sd.c3
-rw-r--r--openssl/crypto/cms/cms_smime.c61
11 files changed, 654 insertions, 29 deletions
diff --git a/openssl/crypto/cms/Makefile b/openssl/crypto/cms/Makefile
index 583704972..9820adb21 100644
--- a/openssl/crypto/cms/Makefile
+++ b/openssl/crypto/cms/Makefile
@@ -18,9 +18,11 @@ APPS=
LIB=$(TOP)/libcrypto.a
LIBSRC= cms_lib.c cms_asn1.c cms_att.c cms_io.c cms_smime.c cms_err.c \
- cms_sd.c cms_dd.c cms_cd.c cms_env.c cms_enc.c cms_ess.c
+ cms_sd.c cms_dd.c cms_cd.c cms_env.c cms_enc.c cms_ess.c \
+ cms_pwri.c
LIBOBJ= cms_lib.o cms_asn1.o cms_att.o cms_io.o cms_smime.o cms_err.o \
- cms_sd.o cms_dd.o cms_cd.o cms_env.o cms_enc.o cms_ess.o
+ cms_sd.o cms_dd.o cms_cd.o cms_env.o cms_enc.o cms_ess.o \
+ cms_pwri.o
SRC= $(LIBSRC)
@@ -230,6 +232,24 @@ cms_lib.o: ../../include/openssl/safestack.h ../../include/openssl/sha.h
cms_lib.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h
cms_lib.o: ../../include/openssl/x509.h ../../include/openssl/x509_vfy.h cms.h
cms_lib.o: cms_lcl.h cms_lib.c
+cms_pwri.o: ../../e_os.h ../../include/openssl/aes.h
+cms_pwri.o: ../../include/openssl/asn1.h ../../include/openssl/asn1t.h
+cms_pwri.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h
+cms_pwri.o: ../../include/openssl/cms.h ../../include/openssl/conf.h
+cms_pwri.o: ../../include/openssl/crypto.h ../../include/openssl/e_os2.h
+cms_pwri.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h
+cms_pwri.o: ../../include/openssl/ecdsa.h ../../include/openssl/err.h
+cms_pwri.o: ../../include/openssl/evp.h ../../include/openssl/lhash.h
+cms_pwri.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h
+cms_pwri.o: ../../include/openssl/opensslconf.h
+cms_pwri.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
+cms_pwri.o: ../../include/openssl/pem.h ../../include/openssl/pem2.h
+cms_pwri.o: ../../include/openssl/pkcs7.h ../../include/openssl/rand.h
+cms_pwri.o: ../../include/openssl/safestack.h ../../include/openssl/sha.h
+cms_pwri.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h
+cms_pwri.o: ../../include/openssl/x509.h ../../include/openssl/x509_vfy.h
+cms_pwri.o: ../../include/openssl/x509v3.h ../asn1/asn1_locl.h ../cryptlib.h
+cms_pwri.o: cms_lcl.h cms_pwri.c
cms_sd.o: ../../e_os.h ../../include/openssl/asn1.h
cms_sd.o: ../../include/openssl/asn1t.h ../../include/openssl/bio.h
cms_sd.o: ../../include/openssl/buffer.h ../../include/openssl/cms.h
diff --git a/openssl/crypto/cms/cms.h b/openssl/crypto/cms/cms.h
index 09c45d041..36994fa6a 100644
--- a/openssl/crypto/cms/cms.h
+++ b/openssl/crypto/cms/cms.h
@@ -111,6 +111,7 @@ DECLARE_ASN1_PRINT_FUNCTION(CMS_ContentInfo)
#define CMS_PARTIAL 0x4000
#define CMS_REUSE_DIGEST 0x8000
#define CMS_USE_KEYID 0x10000
+#define CMS_DEBUG_DECRYPT 0x20000
const ASN1_OBJECT *CMS_get0_type(CMS_ContentInfo *cms);
@@ -184,6 +185,8 @@ int CMS_decrypt_set1_pkey(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert);
int CMS_decrypt_set1_key(CMS_ContentInfo *cms,
unsigned char *key, size_t keylen,
unsigned char *id, size_t idlen);
+int CMS_decrypt_set1_password(CMS_ContentInfo *cms,
+ unsigned char *pass, ossl_ssize_t passlen);
STACK_OF(CMS_RecipientInfo) *CMS_get0_RecipientInfos(CMS_ContentInfo *cms);
int CMS_RecipientInfo_type(CMS_RecipientInfo *ri);
@@ -219,6 +222,16 @@ int CMS_RecipientInfo_set0_key(CMS_RecipientInfo *ri,
int CMS_RecipientInfo_kekri_id_cmp(CMS_RecipientInfo *ri,
const unsigned char *id, size_t idlen);
+int CMS_RecipientInfo_set0_password(CMS_RecipientInfo *ri,
+ unsigned char *pass,
+ ossl_ssize_t passlen);
+
+CMS_RecipientInfo *CMS_add0_recipient_password(CMS_ContentInfo *cms,
+ int iter, int wrap_nid, int pbe_nid,
+ unsigned char *pass,
+ ossl_ssize_t passlen,
+ const EVP_CIPHER *kekciph);
+
int CMS_RecipientInfo_decrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri);
int CMS_uncompress(CMS_ContentInfo *cms, BIO *dcont, BIO *out,
@@ -330,6 +343,7 @@ void ERR_load_CMS_strings(void);
#define CMS_F_CHECK_CONTENT 99
#define CMS_F_CMS_ADD0_CERT 164
#define CMS_F_CMS_ADD0_RECIPIENT_KEY 100
+#define CMS_F_CMS_ADD0_RECIPIENT_PASSWORD 165
#define CMS_F_CMS_ADD1_RECEIPTREQUEST 158
#define CMS_F_CMS_ADD1_RECIPIENT_CERT 101
#define CMS_F_CMS_ADD1_SIGNER 102
@@ -344,6 +358,7 @@ void ERR_load_CMS_strings(void);
#define CMS_F_CMS_DATAINIT 111
#define CMS_F_CMS_DECRYPT 112
#define CMS_F_CMS_DECRYPT_SET1_KEY 113
+#define CMS_F_CMS_DECRYPT_SET1_PASSWORD 166
#define CMS_F_CMS_DECRYPT_SET1_PKEY 114
#define CMS_F_CMS_DIGESTALGORITHM_FIND_CTX 115
#define CMS_F_CMS_DIGESTALGORITHM_INIT_BIO 116
@@ -378,7 +393,9 @@ void ERR_load_CMS_strings(void);
#define CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT 141
#define CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_ALGS 142
#define CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_SIGNER_ID 143
+#define CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT 167
#define CMS_F_CMS_RECIPIENTINFO_SET0_KEY 144
+#define CMS_F_CMS_RECIPIENTINFO_SET0_PASSWORD 168
#define CMS_F_CMS_RECIPIENTINFO_SET0_PKEY 145
#define CMS_F_CMS_SET1_SIGNERIDENTIFIER 146
#define CMS_F_CMS_SET_DETACHED 147
@@ -419,6 +436,7 @@ void ERR_load_CMS_strings(void);
#define CMS_R_ERROR_SETTING_KEY 115
#define CMS_R_ERROR_SETTING_RECIPIENTINFO 116
#define CMS_R_INVALID_ENCRYPTED_KEY_LENGTH 117
+#define CMS_R_INVALID_KEY_ENCRYPTION_PARAMETER 176
#define CMS_R_INVALID_KEY_LENGTH 118
#define CMS_R_MD_BIO_INIT_ERROR 119
#define CMS_R_MESSAGEDIGEST_ATTRIBUTE_WRONG_LENGTH 120
@@ -431,6 +449,7 @@ void ERR_load_CMS_strings(void);
#define CMS_R_NOT_ENCRYPTED_DATA 122
#define CMS_R_NOT_KEK 123
#define CMS_R_NOT_KEY_TRANSPORT 124
+#define CMS_R_NOT_PWRI 177
#define CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE 125
#define CMS_R_NO_CIPHER 126
#define CMS_R_NO_CONTENT 127
@@ -443,6 +462,7 @@ void ERR_load_CMS_strings(void);
#define CMS_R_NO_MATCHING_RECIPIENT 132
#define CMS_R_NO_MATCHING_SIGNATURE 166
#define CMS_R_NO_MSGSIGDIGEST 167
+#define CMS_R_NO_PASSWORD 178
#define CMS_R_NO_PRIVATE_KEY 133
#define CMS_R_NO_PUBLIC_KEY 134
#define CMS_R_NO_RECEIPT_REQUEST 168
@@ -466,10 +486,12 @@ void ERR_load_CMS_strings(void);
#define CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM 151
#define CMS_R_UNSUPPORTED_CONTENT_TYPE 152
#define CMS_R_UNSUPPORTED_KEK_ALGORITHM 153
+#define CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM 179
#define CMS_R_UNSUPPORTED_RECIPIENT_TYPE 154
#define CMS_R_UNSUPPORTED_RECPIENTINFO_TYPE 155
#define CMS_R_UNSUPPORTED_TYPE 156
#define CMS_R_UNWRAP_ERROR 157
+#define CMS_R_UNWRAP_FAILURE 180
#define CMS_R_VERIFICATION_FAILURE 158
#define CMS_R_WRAP_ERROR 159
diff --git a/openssl/crypto/cms/cms_asn1.c b/openssl/crypto/cms/cms_asn1.c
index fcba4dcbc..cfe67fb6c 100644
--- a/openssl/crypto/cms/cms_asn1.c
+++ b/openssl/crypto/cms/cms_asn1.c
@@ -237,6 +237,15 @@ static int cms_ri_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
OPENSSL_free(kekri->key);
}
}
+ else if (ri->type == CMS_RECIPINFO_PASS)
+ {
+ CMS_PasswordRecipientInfo *pwri = ri->d.pwri;
+ if (pwri->pass)
+ {
+ OPENSSL_cleanse(pwri->pass, pwri->passlen);
+ OPENSSL_free(pwri->pass);
+ }
+ }
}
return 1;
}
diff --git a/openssl/crypto/cms/cms_enc.c b/openssl/crypto/cms/cms_enc.c
index bab26235b..580083b45 100644
--- a/openssl/crypto/cms/cms_enc.c
+++ b/openssl/crypto/cms/cms_enc.c
@@ -73,6 +73,8 @@ BIO *cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec)
const EVP_CIPHER *ciph;
X509_ALGOR *calg = ec->contentEncryptionAlgorithm;
unsigned char iv[EVP_MAX_IV_LENGTH], *piv = NULL;
+ unsigned char *tkey = NULL;
+ size_t tkeylen;
int ok = 0;
@@ -137,32 +139,57 @@ BIO *cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec)
CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR);
goto err;
}
-
-
- if (enc && !ec->key)
+ /* Generate random session key */
+ if (!enc || !ec->key)
{
- /* Generate random key */
- if (!ec->keylen)
- ec->keylen = EVP_CIPHER_CTX_key_length(ctx);
- ec->key = OPENSSL_malloc(ec->keylen);
- if (!ec->key)
+ tkeylen = EVP_CIPHER_CTX_key_length(ctx);
+ tkey = OPENSSL_malloc(tkeylen);
+ if (!tkey)
{
CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO,
ERR_R_MALLOC_FAILURE);
goto err;
}
- if (EVP_CIPHER_CTX_rand_key(ctx, ec->key) <= 0)
+ if (EVP_CIPHER_CTX_rand_key(ctx, tkey) <= 0)
goto err;
- keep_key = 1;
}
- else if (ec->keylen != (unsigned int)EVP_CIPHER_CTX_key_length(ctx))
+
+ if (!ec->key)
+ {
+ ec->key = tkey;
+ ec->keylen = tkeylen;
+ tkey = NULL;
+ if (enc)
+ keep_key = 1;
+ else
+ ERR_clear_error();
+
+ }
+
+ if (ec->keylen != tkeylen)
{
/* If necessary set key length */
if (EVP_CIPHER_CTX_set_key_length(ctx, ec->keylen) <= 0)
{
- CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO,
- CMS_R_INVALID_KEY_LENGTH);
- goto err;
+ /* Only reveal failure if debugging so we don't
+ * leak information which may be useful in MMA.
+ */
+ if (ec->debug)
+ {
+ CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO,
+ CMS_R_INVALID_KEY_LENGTH);
+ goto err;
+ }
+ else
+ {
+ /* Use random key */
+ OPENSSL_cleanse(ec->key, ec->keylen);
+ OPENSSL_free(ec->key);
+ ec->key = tkey;
+ ec->keylen = tkeylen;
+ tkey = NULL;
+ ERR_clear_error();
+ }
}
}
@@ -198,6 +225,11 @@ BIO *cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec)
OPENSSL_free(ec->key);
ec->key = NULL;
}
+ if (tkey)
+ {
+ OPENSSL_cleanse(tkey, tkeylen);
+ OPENSSL_free(tkey);
+ }
if (ok)
return b;
BIO_free(b);
diff --git a/openssl/crypto/cms/cms_env.c b/openssl/crypto/cms/cms_env.c
index b3237d4b9..be20b1c02 100644
--- a/openssl/crypto/cms/cms_env.c
+++ b/openssl/crypto/cms/cms_env.c
@@ -65,14 +65,13 @@
/* CMS EnvelopedData Utilities */
DECLARE_ASN1_ITEM(CMS_EnvelopedData)
-DECLARE_ASN1_ITEM(CMS_RecipientInfo)
DECLARE_ASN1_ITEM(CMS_KeyTransRecipientInfo)
DECLARE_ASN1_ITEM(CMS_KEKRecipientInfo)
DECLARE_ASN1_ITEM(CMS_OtherKeyAttribute)
DECLARE_STACK_OF(CMS_RecipientInfo)
-static CMS_EnvelopedData *cms_get0_enveloped(CMS_ContentInfo *cms)
+CMS_EnvelopedData *cms_get0_enveloped(CMS_ContentInfo *cms)
{
if (OBJ_obj2nid(cms->contentType) != NID_pkcs7_enveloped)
{
@@ -371,6 +370,8 @@ static int cms_RecipientInfo_ktri_decrypt(CMS_ContentInfo *cms,
unsigned char *ek = NULL;
size_t eklen;
int ret = 0;
+ CMS_EncryptedContentInfo *ec;
+ ec = cms->d.envelopedData->encryptedContentInfo;
if (ktri->pkey == NULL)
{
@@ -417,8 +418,14 @@ static int cms_RecipientInfo_ktri_decrypt(CMS_ContentInfo *cms,
ret = 1;
- cms->d.envelopedData->encryptedContentInfo->key = ek;
- cms->d.envelopedData->encryptedContentInfo->keylen = eklen;
+ if (ec->key)
+ {
+ OPENSSL_cleanse(ec->key, ec->keylen);
+ OPENSSL_free(ec->key);
+ }
+
+ ec->key = ek;
+ ec->keylen = eklen;
err:
if (pctx)
@@ -786,6 +793,9 @@ int CMS_RecipientInfo_decrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri)
case CMS_RECIPINFO_KEK:
return cms_RecipientInfo_kekri_decrypt(cms, ri);
+ case CMS_RECIPINFO_PASS:
+ return cms_RecipientInfo_pwri_crypt(cms, ri, 0);
+
default:
CMSerr(CMS_F_CMS_RECIPIENTINFO_DECRYPT,
CMS_R_UNSUPPORTED_RECPIENTINFO_TYPE);
@@ -829,6 +839,10 @@ BIO *cms_EnvelopedData_init_bio(CMS_ContentInfo *cms)
r = cms_RecipientInfo_kekri_encrypt(cms, ri);
break;
+ case CMS_RECIPINFO_PASS:
+ r = cms_RecipientInfo_pwri_crypt(cms, ri, 1);
+ break;
+
default:
CMSerr(CMS_F_CMS_ENVELOPEDDATA_INIT_BIO,
CMS_R_UNSUPPORTED_RECIPIENT_TYPE);
diff --git a/openssl/crypto/cms/cms_err.c b/openssl/crypto/cms/cms_err.c
index ff7b0309e..8330ead7e 100644
--- a/openssl/crypto/cms/cms_err.c
+++ b/openssl/crypto/cms/cms_err.c
@@ -1,6 +1,6 @@
/* crypto/cms/cms_err.c */
/* ====================================================================
- * Copyright (c) 1999-2007 The OpenSSL Project. All rights reserved.
+ * Copyright (c) 1999-2009 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -73,6 +73,7 @@ static ERR_STRING_DATA CMS_str_functs[]=
{ERR_FUNC(CMS_F_CHECK_CONTENT), "CHECK_CONTENT"},
{ERR_FUNC(CMS_F_CMS_ADD0_CERT), "CMS_add0_cert"},
{ERR_FUNC(CMS_F_CMS_ADD0_RECIPIENT_KEY), "CMS_add0_recipient_key"},
+{ERR_FUNC(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD), "CMS_add0_recipient_password"},
{ERR_FUNC(CMS_F_CMS_ADD1_RECEIPTREQUEST), "CMS_add1_ReceiptRequest"},
{ERR_FUNC(CMS_F_CMS_ADD1_RECIPIENT_CERT), "CMS_add1_recipient_cert"},
{ERR_FUNC(CMS_F_CMS_ADD1_SIGNER), "CMS_add1_signer"},
@@ -87,6 +88,7 @@ static ERR_STRING_DATA CMS_str_functs[]=
{ERR_FUNC(CMS_F_CMS_DATAINIT), "CMS_dataInit"},
{ERR_FUNC(CMS_F_CMS_DECRYPT), "CMS_decrypt"},
{ERR_FUNC(CMS_F_CMS_DECRYPT_SET1_KEY), "CMS_decrypt_set1_key"},
+{ERR_FUNC(CMS_F_CMS_DECRYPT_SET1_PASSWORD), "CMS_decrypt_set1_password"},
{ERR_FUNC(CMS_F_CMS_DECRYPT_SET1_PKEY), "CMS_decrypt_set1_pkey"},
{ERR_FUNC(CMS_F_CMS_DIGESTALGORITHM_FIND_CTX), "cms_DigestAlgorithm_find_ctx"},
{ERR_FUNC(CMS_F_CMS_DIGESTALGORITHM_INIT_BIO), "cms_DigestAlgorithm_init_bio"},
@@ -105,7 +107,7 @@ static ERR_STRING_DATA CMS_str_functs[]=
{ERR_FUNC(CMS_F_CMS_GET0_CERTIFICATE_CHOICES), "CMS_GET0_CERTIFICATE_CHOICES"},
{ERR_FUNC(CMS_F_CMS_GET0_CONTENT), "CMS_get0_content"},
{ERR_FUNC(CMS_F_CMS_GET0_ECONTENT_TYPE), "CMS_GET0_ECONTENT_TYPE"},
-{ERR_FUNC(CMS_F_CMS_GET0_ENVELOPED), "CMS_GET0_ENVELOPED"},
+{ERR_FUNC(CMS_F_CMS_GET0_ENVELOPED), "cms_get0_enveloped"},
{ERR_FUNC(CMS_F_CMS_GET0_REVOCATION_CHOICES), "CMS_GET0_REVOCATION_CHOICES"},
{ERR_FUNC(CMS_F_CMS_GET0_SIGNED), "CMS_GET0_SIGNED"},
{ERR_FUNC(CMS_F_CMS_MSGSIGDIGEST_ADD1), "cms_msgSigDigest_add1"},
@@ -121,7 +123,9 @@ static ERR_STRING_DATA CMS_str_functs[]=
{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT), "CMS_RECIPIENTINFO_KTRI_ENCRYPT"},
{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_ALGS), "CMS_RecipientInfo_ktri_get0_algs"},
{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_SIGNER_ID), "CMS_RecipientInfo_ktri_get0_signer_id"},
+{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT), "cms_RecipientInfo_pwri_crypt"},
{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_SET0_KEY), "CMS_RecipientInfo_set0_key"},
+{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_SET0_PASSWORD), "CMS_RecipientInfo_set0_password"},
{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_SET0_PKEY), "CMS_RecipientInfo_set0_pkey"},
{ERR_FUNC(CMS_F_CMS_SET1_SIGNERIDENTIFIER), "cms_set1_SignerIdentifier"},
{ERR_FUNC(CMS_F_CMS_SET_DETACHED), "CMS_set_detached"},
@@ -165,6 +169,7 @@ static ERR_STRING_DATA CMS_str_reasons[]=
{ERR_REASON(CMS_R_ERROR_SETTING_KEY) ,"error setting key"},
{ERR_REASON(CMS_R_ERROR_SETTING_RECIPIENTINFO),"error setting recipientinfo"},
{ERR_REASON(CMS_R_INVALID_ENCRYPTED_KEY_LENGTH),"invalid encrypted key length"},
+{ERR_REASON(CMS_R_INVALID_KEY_ENCRYPTION_PARAMETER),"invalid key encryption parameter"},
{ERR_REASON(CMS_R_INVALID_KEY_LENGTH) ,"invalid key length"},
{ERR_REASON(CMS_R_MD_BIO_INIT_ERROR) ,"md bio init error"},
{ERR_REASON(CMS_R_MESSAGEDIGEST_ATTRIBUTE_WRONG_LENGTH),"messagedigest attribute wrong length"},
@@ -177,6 +182,7 @@ static ERR_STRING_DATA CMS_str_reasons[]=
{ERR_REASON(CMS_R_NOT_ENCRYPTED_DATA) ,"not encrypted data"},
{ERR_REASON(CMS_R_NOT_KEK) ,"not kek"},
{ERR_REASON(CMS_R_NOT_KEY_TRANSPORT) ,"not key transport"},
+{ERR_REASON(CMS_R_NOT_PWRI) ,"not pwri"},
{ERR_REASON(CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE),"not supported for this key type"},
{ERR_REASON(CMS_R_NO_CIPHER) ,"no cipher"},
{ERR_REASON(CMS_R_NO_CONTENT) ,"no content"},
@@ -189,6 +195,7 @@ static ERR_STRING_DATA CMS_str_reasons[]=
{ERR_REASON(CMS_R_NO_MATCHING_RECIPIENT) ,"no matching recipient"},
{ERR_REASON(CMS_R_NO_MATCHING_SIGNATURE) ,"no matching signature"},
{ERR_REASON(CMS_R_NO_MSGSIGDIGEST) ,"no msgsigdigest"},
+{ERR_REASON(CMS_R_NO_PASSWORD) ,"no password"},
{ERR_REASON(CMS_R_NO_PRIVATE_KEY) ,"no private key"},
{ERR_REASON(CMS_R_NO_PUBLIC_KEY) ,"no public key"},
{ERR_REASON(CMS_R_NO_RECEIPT_REQUEST) ,"no receipt request"},
@@ -212,10 +219,12 @@ static ERR_STRING_DATA CMS_str_reasons[]=
{ERR_REASON(CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM),"unsupported compression algorithm"},
{ERR_REASON(CMS_R_UNSUPPORTED_CONTENT_TYPE),"unsupported content type"},
{ERR_REASON(CMS_R_UNSUPPORTED_KEK_ALGORITHM),"unsupported kek algorithm"},
+{ERR_REASON(CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM),"unsupported key encryption algorithm"},
{ERR_REASON(CMS_R_UNSUPPORTED_RECIPIENT_TYPE),"unsupported recipient type"},
{ERR_REASON(CMS_R_UNSUPPORTED_RECPIENTINFO_TYPE),"unsupported recpientinfo type"},
{ERR_REASON(CMS_R_UNSUPPORTED_TYPE) ,"unsupported type"},
{ERR_REASON(CMS_R_UNWRAP_ERROR) ,"unwrap error"},
+{ERR_REASON(CMS_R_UNWRAP_FAILURE) ,"unwrap failure"},
{ERR_REASON(CMS_R_VERIFICATION_FAILURE) ,"verification failure"},
{ERR_REASON(CMS_R_WRAP_ERROR) ,"wrap error"},
{0,NULL}
diff --git a/openssl/crypto/cms/cms_lcl.h b/openssl/crypto/cms/cms_lcl.h
index c8ecfa724..a9f973015 100644
--- a/openssl/crypto/cms/cms_lcl.h
+++ b/openssl/crypto/cms/cms_lcl.h
@@ -175,6 +175,8 @@ struct CMS_EncryptedContentInfo_st
const EVP_CIPHER *cipher;
unsigned char *key;
size_t keylen;
+ /* Set to 1 if we are debugging decrypt and don't fake keys for MMA */
+ int debug;
};
struct CMS_RecipientInfo_st
@@ -273,6 +275,9 @@ struct CMS_PasswordRecipientInfo_st
X509_ALGOR *keyDerivationAlgorithm;
X509_ALGOR *keyEncryptionAlgorithm;
ASN1_OCTET_STRING *encryptedKey;
+ /* Extra info: password to use */
+ unsigned char *pass;
+ size_t passlen;
};
struct CMS_OtherRecipientInfo_st
@@ -411,6 +416,8 @@ DECLARE_ASN1_ITEM(CMS_SignerInfo)
DECLARE_ASN1_ITEM(CMS_IssuerAndSerialNumber)
DECLARE_ASN1_ITEM(CMS_Attributes_Sign)
DECLARE_ASN1_ITEM(CMS_Attributes_Verify)
+DECLARE_ASN1_ITEM(CMS_RecipientInfo)
+DECLARE_ASN1_ITEM(CMS_PasswordRecipientInfo)
DECLARE_ASN1_ALLOC_FUNCTIONS(CMS_IssuerAndSerialNumber)
#define CMS_SIGNERINFO_ISSUER_SERIAL 0
@@ -454,6 +461,11 @@ int cms_msgSigDigest_add1(CMS_SignerInfo *dest, CMS_SignerInfo *src);
ASN1_OCTET_STRING *cms_encode_Receipt(CMS_SignerInfo *si);
BIO *cms_EnvelopedData_init_bio(CMS_ContentInfo *cms);
+CMS_EnvelopedData *cms_get0_enveloped(CMS_ContentInfo *cms);
+
+/* PWRI routines */
+int cms_RecipientInfo_pwri_crypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri,
+ int en_de);
#ifdef __cplusplus
}
diff --git a/openssl/crypto/cms/cms_lib.c b/openssl/crypto/cms/cms_lib.c
index d00fe0f87..f88e8f3b5 100644
--- a/openssl/crypto/cms/cms_lib.c
+++ b/openssl/crypto/cms/cms_lib.c
@@ -412,8 +412,7 @@ int cms_DigestAlgorithm_find_ctx(EVP_MD_CTX *mctx, BIO *chain,
*/
|| EVP_MD_pkey_type(EVP_MD_CTX_md(mtmp)) == nid)
{
- EVP_MD_CTX_copy_ex(mctx, mtmp);
- return 1;
+ return EVP_MD_CTX_copy_ex(mctx, mtmp);
}
chain = BIO_next(chain);
}
diff --git a/openssl/crypto/cms/cms_pwri.c b/openssl/crypto/cms/cms_pwri.c
new file mode 100644
index 000000000..b79612a12
--- /dev/null
+++ b/openssl/crypto/cms/cms_pwri.c
@@ -0,0 +1,454 @@
+/* crypto/cms/cms_pwri.c */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project.
+ */
+/* ====================================================================
+ * Copyright (c) 2009 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ */
+
+#include "cryptlib.h"
+#include <openssl/asn1t.h>
+#include <openssl/pem.h>
+#include <openssl/x509v3.h>
+#include <openssl/err.h>
+#include <openssl/cms.h>
+#include <openssl/rand.h>
+#include <openssl/aes.h>
+#include "cms_lcl.h"
+#include "asn1_locl.h"
+
+int CMS_RecipientInfo_set0_password(CMS_RecipientInfo *ri,
+ unsigned char *pass, ossl_ssize_t passlen)
+ {
+ CMS_PasswordRecipientInfo *pwri;
+ if (ri->type != CMS_RECIPINFO_PASS)
+ {
+ CMSerr(CMS_F_CMS_RECIPIENTINFO_SET0_PASSWORD, CMS_R_NOT_PWRI);
+ return 0;
+ }
+
+ pwri = ri->d.pwri;
+ pwri->pass = pass;
+ if (pass && passlen < 0)
+ passlen = strlen((char *)pass);
+ pwri->passlen = passlen;
+ return 1;
+ }
+
+CMS_RecipientInfo *CMS_add0_recipient_password(CMS_ContentInfo *cms,
+ int iter, int wrap_nid, int pbe_nid,
+ unsigned char *pass,
+ ossl_ssize_t passlen,
+ const EVP_CIPHER *kekciph)
+ {
+ CMS_RecipientInfo *ri = NULL;
+ CMS_EnvelopedData *env;
+ CMS_PasswordRecipientInfo *pwri;
+ EVP_CIPHER_CTX ctx;
+ X509_ALGOR *encalg = NULL;
+ unsigned char iv[EVP_MAX_IV_LENGTH];
+ int ivlen;
+ env = cms_get0_enveloped(cms);
+ if (!env)
+ goto err;
+
+ if (wrap_nid <= 0)
+ wrap_nid = NID_id_alg_PWRI_KEK;
+
+ if (pbe_nid <= 0)
+ pbe_nid = NID_id_pbkdf2;
+
+ /* Get from enveloped data */
+ if (kekciph == NULL)
+ kekciph = env->encryptedContentInfo->cipher;
+
+ if (kekciph == NULL)
+ {
+ CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, CMS_R_NO_CIPHER);
+ return NULL;
+ }
+ if (wrap_nid != NID_id_alg_PWRI_KEK)
+ {
+ CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD,
+ CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM);
+ return NULL;
+ }
+
+ /* Setup algorithm identifier for cipher */
+ encalg = X509_ALGOR_new();
+ EVP_CIPHER_CTX_init(&ctx);
+
+ if (EVP_EncryptInit_ex(&ctx, kekciph, NULL, NULL, NULL) <= 0)
+ {
+ CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, ERR_R_EVP_LIB);
+ goto err;
+ }
+
+ ivlen = EVP_CIPHER_CTX_iv_length(&ctx);
+
+ if (ivlen > 0)
+ {
+ if (RAND_pseudo_bytes(iv, ivlen) <= 0)
+ goto err;
+ if (EVP_EncryptInit_ex(&ctx, NULL, NULL, NULL, iv) <= 0)
+ {
+ CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD,
+ ERR_R_EVP_LIB);
+ goto err;
+ }
+ encalg->parameter = ASN1_TYPE_new();
+ if (!encalg->parameter)
+ {
+ CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ if (EVP_CIPHER_param_to_asn1(&ctx, encalg->parameter) <= 0)
+ {
+ CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD,
+ CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR);
+ goto err;
+ }
+ }
+
+
+ encalg->algorithm = OBJ_nid2obj(EVP_CIPHER_CTX_type(&ctx));
+
+ EVP_CIPHER_CTX_cleanup(&ctx);
+
+ /* Initialize recipient info */
+ ri = M_ASN1_new_of(CMS_RecipientInfo);
+ if (!ri)
+ goto merr;
+
+ ri->d.pwri = M_ASN1_new_of(CMS_PasswordRecipientInfo);
+ if (!ri->d.pwri)
+ goto merr;
+ ri->type = CMS_RECIPINFO_PASS;
+
+ pwri = ri->d.pwri;
+ /* Since this is overwritten, free up empty structure already there */
+ X509_ALGOR_free(pwri->keyEncryptionAlgorithm);
+ pwri->keyEncryptionAlgorithm = X509_ALGOR_new();
+ if (!pwri->keyEncryptionAlgorithm)
+ goto merr;
+ pwri->keyEncryptionAlgorithm->algorithm = OBJ_nid2obj(wrap_nid);
+ pwri->keyEncryptionAlgorithm->parameter = ASN1_TYPE_new();
+ if (!pwri->keyEncryptionAlgorithm->parameter)
+ goto merr;
+
+ if(!ASN1_item_pack(encalg, ASN1_ITEM_rptr(X509_ALGOR),
+ &pwri->keyEncryptionAlgorithm->parameter->value.sequence))
+ goto merr;
+ pwri->keyEncryptionAlgorithm->parameter->type = V_ASN1_SEQUENCE;
+
+ X509_ALGOR_free(encalg);
+ encalg = NULL;
+
+ /* Setup PBE algorithm */
+
+ pwri->keyDerivationAlgorithm = PKCS5_pbkdf2_set(iter, NULL, 0, -1, -1);
+
+ if (!pwri->keyDerivationAlgorithm)
+ goto err;
+
+ CMS_RecipientInfo_set0_password(ri, pass, passlen);
+ pwri->version = 0;
+
+ if (!sk_CMS_RecipientInfo_push(env->recipientInfos, ri))
+ goto merr;
+
+ return ri;
+
+ merr:
+ CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, ERR_R_MALLOC_FAILURE);
+ err:
+ EVP_CIPHER_CTX_cleanup(&ctx);
+ if (ri)
+ M_ASN1_free_of(ri, CMS_RecipientInfo);
+ if (encalg)
+ X509_ALGOR_free(encalg);
+ return NULL;
+
+ }
+
+/* This is an implementation of the key wrapping mechanism in RFC3211,
+ * at some point this should go into EVP.
+ */
+
+static int kek_unwrap_key(unsigned char *out, size_t *outlen,
+ const unsigned char *in, size_t inlen, EVP_CIPHER_CTX *ctx)
+ {
+ size_t blocklen = EVP_CIPHER_CTX_block_size(ctx);
+ unsigned char *tmp;
+ int outl, rv = 0;
+ if (inlen < 2 * blocklen)
+ {
+ /* too small */
+ return 0;
+ }
+ if (inlen % blocklen)
+ {
+ /* Invalid size */
+ return 0;
+ }
+ tmp = OPENSSL_malloc(inlen);
+ /* setup IV by decrypting last two blocks */
+ EVP_DecryptUpdate(ctx, tmp + inlen - 2 * blocklen, &outl,
+ in + inlen - 2 * blocklen, blocklen * 2);
+ /* Do a decrypt of last decrypted block to set IV to correct value
+ * output it to start of buffer so we don't corrupt decrypted block
+ * this works because buffer is at least two block lengths long.
+ */
+ EVP_DecryptUpdate(ctx, tmp, &outl,
+ tmp + inlen - blocklen, blocklen);
+ /* Can now decrypt first n - 1 blocks */
+ EVP_DecryptUpdate(ctx, tmp, &outl, in, inlen - blocklen);
+
+ /* Reset IV to original value */
+ EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, NULL);
+ /* Decrypt again */
+ EVP_DecryptUpdate(ctx, tmp, &outl, tmp, inlen);
+ /* Check check bytes */
+ if (((tmp[1] ^ tmp[4]) & (tmp[2] ^ tmp[5]) & (tmp[3] ^ tmp[6])) != 0xff)
+ {
+ /* Check byte failure */
+ goto err;
+ }
+ if (inlen < (size_t)(tmp[0] - 4 ))
+ {
+ /* Invalid length value */
+ goto err;
+ }
+ *outlen = (size_t)tmp[0];
+ memcpy(out, tmp + 4, *outlen);
+ rv = 1;
+ err:
+ OPENSSL_cleanse(tmp, inlen);
+ OPENSSL_free(tmp);
+ return rv;
+
+ }
+
+static int kek_wrap_key(unsigned char *out, size_t *outlen,
+ const unsigned char *in, size_t inlen, EVP_CIPHER_CTX *ctx)
+ {
+ size_t blocklen = EVP_CIPHER_CTX_block_size(ctx);
+ size_t olen;
+ int dummy;
+ /* First decide length of output buffer: need header and round up to
+ * multiple of block length.
+ */
+ olen = (inlen + 4 + blocklen - 1)/blocklen;
+ olen *= blocklen;
+ if (olen < 2 * blocklen)
+ {
+ /* Key too small */
+ return 0;
+ }
+ if (inlen > 0xFF)
+ {
+ /* Key too large */
+ return 0;
+ }
+ if (out)
+ {
+ /* Set header */
+ out[0] = (unsigned char)inlen;
+ out[1] = in[0] ^ 0xFF;
+ out[2] = in[1] ^ 0xFF;
+ out[3] = in[2] ^ 0xFF;
+ memcpy(out + 4, in, inlen);
+ /* Add random padding to end */
+ if (olen > inlen + 4)
+ RAND_pseudo_bytes(out + 4 + inlen, olen - 4 - inlen);
+ /* Encrypt twice */
+ EVP_EncryptUpdate(ctx, out, &dummy, out, olen);
+ EVP_EncryptUpdate(ctx, out, &dummy, out, olen);
+ }
+
+ *outlen = olen;
+
+ return 1;
+ }
+
+/* Encrypt/Decrypt content key in PWRI recipient info */
+
+int cms_RecipientInfo_pwri_crypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri,
+ int en_de)
+ {
+ CMS_EncryptedContentInfo *ec;
+ CMS_PasswordRecipientInfo *pwri;
+ const unsigned char *p = NULL;
+ int plen;
+ int r = 0;
+ X509_ALGOR *algtmp, *kekalg = NULL;
+ EVP_CIPHER_CTX kekctx;
+ const EVP_CIPHER *kekcipher;
+ unsigned char *key = NULL;
+ size_t keylen;
+
+ ec = cms->d.envelopedData->encryptedContentInfo;
+
+ pwri = ri->d.pwri;
+ EVP_CIPHER_CTX_init(&kekctx);
+
+ if (!pwri->pass)
+ {
+ CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, CMS_R_NO_PASSWORD);
+ return 0;
+ }
+ algtmp = pwri->keyEncryptionAlgorithm;
+
+ if (!algtmp || OBJ_obj2nid(algtmp->algorithm) != NID_id_alg_PWRI_KEK)
+ {
+ CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT,
+ CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM);
+ return 0;
+ }
+
+ if (algtmp->parameter->type == V_ASN1_SEQUENCE)
+ {
+ p = algtmp->parameter->value.sequence->data;
+ plen = algtmp->parameter->value.sequence->length;
+ kekalg = d2i_X509_ALGOR(NULL, &p, plen);
+ }
+ if (kekalg == NULL)
+ {
+ CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT,
+ CMS_R_INVALID_KEY_ENCRYPTION_PARAMETER);
+ return 0;
+ }
+
+ kekcipher = EVP_get_cipherbyobj(kekalg->algorithm);
+
+ if(!kekcipher)
+ {
+ CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT,
+ CMS_R_UNKNOWN_CIPHER);
+ goto err;
+ }
+
+ /* Fixup cipher based on AlgorithmIdentifier to set IV etc */
+ if (!EVP_CipherInit_ex(&kekctx, kekcipher, NULL, NULL, NULL, en_de))
+ goto err;
+ EVP_CIPHER_CTX_set_padding(&kekctx, 0);
+ if(EVP_CIPHER_asn1_to_param(&kekctx, kekalg->parameter) < 0)
+ {
+ CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT,
+ CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR);
+ goto err;
+ }
+
+ algtmp = pwri->keyDerivationAlgorithm;
+
+ /* Finish password based key derivation to setup key in "ctx" */
+
+ if (EVP_PBE_CipherInit(algtmp->algorithm,
+ (char *)pwri->pass, pwri->passlen,
+ algtmp->parameter, &kekctx, en_de) < 0)
+ {
+ CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, ERR_R_EVP_LIB);
+ goto err;
+ }
+
+ /* Finally wrap/unwrap the key */
+
+ if (en_de)
+ {
+
+ if (!kek_wrap_key(NULL, &keylen, ec->key, ec->keylen, &kekctx))
+ goto err;
+
+ key = OPENSSL_malloc(keylen);
+
+ if (!key)
+ goto err;
+
+ if (!kek_wrap_key(key, &keylen, ec->key, ec->keylen, &kekctx))
+ goto err;
+ pwri->encryptedKey->data = key;
+ pwri->encryptedKey->length = keylen;
+ }
+ else
+ {
+ key = OPENSSL_malloc(pwri->encryptedKey->length);
+
+ if (!key)
+ {
+ CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ if (!kek_unwrap_key(key, &keylen,
+ pwri->encryptedKey->data,
+ pwri->encryptedKey->length, &kekctx))
+ {
+ CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT,
+ CMS_R_UNWRAP_FAILURE);
+ goto err;
+ }
+
+ ec->key = key;
+ ec->keylen = keylen;
+
+ }
+
+ r = 1;
+
+ err:
+
+ EVP_CIPHER_CTX_cleanup(&kekctx);
+
+ if (!r && key)
+ OPENSSL_free(key);
+ X509_ALGOR_free(kekalg);
+
+ return r;
+
+ }
diff --git a/openssl/crypto/cms/cms_sd.c b/openssl/crypto/cms/cms_sd.c
index e3192b9c5..77fbd1359 100644
--- a/openssl/crypto/cms/cms_sd.c
+++ b/openssl/crypto/cms/cms_sd.c
@@ -641,7 +641,8 @@ static int cms_SignerInfo_content_sign(CMS_ContentInfo *cms,
cms->d.signedData->encapContentInfo->eContentType;
unsigned char md[EVP_MAX_MD_SIZE];
unsigned int mdlen;
- EVP_DigestFinal_ex(&mctx, md, &mdlen);
+ if (!EVP_DigestFinal_ex(&mctx, md, &mdlen))
+ goto err;
if (!CMS_signed_add1_attr_by_NID(si, NID_pkcs9_messageDigest,
V_ASN1_OCTET_STRING,
md, mdlen))
diff --git a/openssl/crypto/cms/cms_smime.c b/openssl/crypto/cms/cms_smime.c
index 4a799eb89..8c56e3a85 100644
--- a/openssl/crypto/cms/cms_smime.c
+++ b/openssl/crypto/cms/cms_smime.c
@@ -611,7 +611,10 @@ int CMS_decrypt_set1_pkey(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert)
STACK_OF(CMS_RecipientInfo) *ris;
CMS_RecipientInfo *ri;
int i, r;
+ int debug = 0;
ris = CMS_get0_RecipientInfos(cms);
+ if (ris)
+ debug = cms->d.envelopedData->encryptedContentInfo->debug;
for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++)
{
ri = sk_CMS_RecipientInfo_value(ris, i);
@@ -625,17 +628,38 @@ int CMS_decrypt_set1_pkey(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert)
CMS_RecipientInfo_set0_pkey(ri, pk);
r = CMS_RecipientInfo_decrypt(cms, ri);
CMS_RecipientInfo_set0_pkey(ri, NULL);
- if (r > 0)
- return 1;
if (cert)
{
+ /* If not debugging clear any error and
+ * return success to avoid leaking of
+ * information useful to MMA
+ */
+ if (!debug)
+ {
+ ERR_clear_error();
+ return 1;
+ }
+ if (r > 0)
+ return 1;
CMSerr(CMS_F_CMS_DECRYPT_SET1_PKEY,
CMS_R_DECRYPT_ERROR);
return 0;
}
- ERR_clear_error();
+ /* If no cert and not debugging don't leave loop
+ * after first successful decrypt. Always attempt
+ * to decrypt all recipients to avoid leaking timing
+ * of a successful decrypt.
+ */
+ else if (r > 0 && debug)
+ return 1;
}
}
+ /* If no cert and not debugging always return success */
+ if (!cert && !debug)
+ {
+ ERR_clear_error();
+ return 1;
+ }
CMSerr(CMS_F_CMS_DECRYPT_SET1_PKEY, CMS_R_NO_MATCHING_RECIPIENT);
return 0;
@@ -680,6 +704,30 @@ int CMS_decrypt_set1_key(CMS_ContentInfo *cms,
return 0;
}
+
+int CMS_decrypt_set1_password(CMS_ContentInfo *cms,
+ unsigned char *pass, ossl_ssize_t passlen)
+ {
+ STACK_OF(CMS_RecipientInfo) *ris;
+ CMS_RecipientInfo *ri;
+ int i, r;
+ ris = CMS_get0_RecipientInfos(cms);
+ for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++)
+ {
+ ri = sk_CMS_RecipientInfo_value(ris, i);
+ if (CMS_RecipientInfo_type(ri) != CMS_RECIPINFO_PASS)
+ continue;
+ CMS_RecipientInfo_set0_password(ri, pass, passlen);
+ r = CMS_RecipientInfo_decrypt(cms, ri);
+ CMS_RecipientInfo_set0_password(ri, NULL, 0);
+ if (r > 0)
+ return 1;
+ }
+
+ CMSerr(CMS_F_CMS_DECRYPT_SET1_PASSWORD, CMS_R_NO_MATCHING_RECIPIENT);
+ return 0;
+
+ }
int CMS_decrypt(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert,
BIO *dcont, BIO *out,
@@ -694,9 +742,14 @@ int CMS_decrypt(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert,
}
if (!dcont && !check_content(cms))
return 0;
+ if (flags & CMS_DEBUG_DECRYPT)
+ cms->d.envelopedData->encryptedContentInfo->debug = 1;
+ else
+ cms->d.envelopedData->encryptedContentInfo->debug = 0;
+ if (!pk && !cert && !dcont && !out)
+ return 1;
if (pk && !CMS_decrypt_set1_pkey(cms, pk, cert))
return 0;
-
cont = CMS_dataInit(cms, dcont);
if (!cont)
return 0;