diff --git a/CVE-2012-0884.patch b/CVE-2012-0884.patch new file mode 100644 index 0000000..2fc26c6 --- /dev/null +++ b/CVE-2012-0884.patch @@ -0,0 +1,357 @@ +Index: openssl-1.0.0c/crypto/cms/cms.h +=================================================================== +--- openssl-1.0.0c.orig/crypto/cms/cms.h ++++ openssl-1.0.0c/crypto/cms/cms.h +@@ -111,6 +111,7 @@ DECLARE_ASN1_PRINT_FUNCTION(CMS_ContentI + #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); + +Index: openssl-1.0.0c/crypto/cms/cms_enc.c +=================================================================== +--- openssl-1.0.0c.orig/crypto/cms/cms_enc.c ++++ openssl-1.0.0c/crypto/cms/cms_enc.c +@@ -73,6 +73,8 @@ BIO *cms_EncryptedContent_init_bio(CMS_E + 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; + +@@ -139,30 +141,55 @@ BIO *cms_EncryptedContent_init_bio(CMS_E + } + + +- 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_E + OPENSSL_free(ec->key); + ec->key = NULL; + } ++ if (tkey) ++ { ++ OPENSSL_cleanse(tkey, tkeylen); ++ OPENSSL_free(tkey); ++ } + if (ok) + return b; + BIO_free(b); +Index: openssl-1.0.0c/crypto/cms/cms_env.c +=================================================================== +--- openssl-1.0.0c.orig/crypto/cms/cms_env.c ++++ openssl-1.0.0c/crypto/cms/cms_env.c +@@ -371,6 +371,8 @@ static int cms_RecipientInfo_ktri_decryp + unsigned char *ek = NULL; + size_t eklen; + int ret = 0; ++ CMS_EncryptedContentInfo *ec; ++ ec = cms->d.envelopedData->encryptedContentInfo; + + if (ktri->pkey == NULL) + { +@@ -417,8 +419,14 @@ static int cms_RecipientInfo_ktri_decryp + + 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) +Index: openssl-1.0.0c/crypto/cms/cms_lcl.h +=================================================================== +--- openssl-1.0.0c.orig/crypto/cms/cms_lcl.h ++++ openssl-1.0.0c/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 +Index: openssl-1.0.0c/crypto/cms/cms_smime.c +=================================================================== +--- openssl-1.0.0c.orig/crypto/cms/cms_smime.c ++++ openssl-1.0.0c/crypto/cms/cms_smime.c +@@ -611,7 +611,10 @@ int CMS_decrypt_set1_pkey(CMS_ContentInf + 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_ContentInf + 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; +@@ -694,6 +718,12 @@ int CMS_decrypt(CMS_ContentInfo *cms, EV + } + 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; + +Index: openssl-1.0.0c/crypto/pkcs7/pk7_doit.c +=================================================================== +--- openssl-1.0.0c.orig/crypto/pkcs7/pk7_doit.c ++++ openssl-1.0.0c/crypto/pkcs7/pk7_doit.c +@@ -204,11 +204,11 @@ static int pkcs7_decrypt_rinfo(unsigned + unsigned char *ek = NULL; + size_t eklen; + +- int ret = 0; ++ int ret = -1; + + pctx = EVP_PKEY_CTX_new(pkey, NULL); + if (!pctx) +- return 0; ++ return -1; + + if (EVP_PKEY_decrypt_init(pctx) <= 0) + goto err; +@@ -235,12 +235,19 @@ static int pkcs7_decrypt_rinfo(unsigned + if (EVP_PKEY_decrypt(pctx, ek, &eklen, + ri->enc_key->data, ri->enc_key->length) <= 0) + { ++ ret = 0; + PKCS7err(PKCS7_F_PKCS7_DECRYPT_RINFO, ERR_R_EVP_LIB); + goto err; + } + + ret = 1; + ++ if (*pek) ++ { ++ OPENSSL_cleanse(*pek, *peklen); ++ OPENSSL_free(*pek); ++ } ++ + *pek = ek; + *peklen = eklen; + +@@ -500,8 +507,8 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKE + int max; + X509_OBJECT ret; + #endif +- unsigned char *ek = NULL; +- int eklen; ++ unsigned char *ek = NULL, *tkey = NULL; ++ int eklen, tkeylen; + + if ((etmp=BIO_new(BIO_f_cipher())) == NULL) + { +@@ -537,26 +544,25 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKE + + if (pcert == NULL) + { ++ /* Always attempt to decrypt all rinfo even ++ * after sucess as a defence against MMA timing ++ * attacks. ++ */ + for (i=0; i 0) +- break; ++ ri, pkey) < 0) ++ goto err; + ERR_clear_error(); +- ri = NULL; +- } +- if (ri == NULL) +- { +- PKCS7err(PKCS7_F_PKCS7_DATADECODE, +- PKCS7_R_NO_RECIPIENT_MATCHES_KEY); +- goto err; + } + } + else + { +- if (pkcs7_decrypt_rinfo(&ek, &eklen, ri, pkey) <= 0) ++ /* Only exit on fatal errors, not decrypt failure */ ++ if (pkcs7_decrypt_rinfo(&ek, &eklen, ri, pkey) < 0) + goto err; ++ ERR_clear_error(); + } + + evp_ctx=NULL; +@@ -566,6 +572,20 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKE + if (EVP_CIPHER_asn1_to_param(evp_ctx,enc_alg->parameter) < 0) + goto err; + ++ /* Generate random key as MMA defence */ ++ tkeylen = EVP_CIPHER_CTX_key_length(evp_ctx); ++ tkey = OPENSSL_malloc(tkeylen); ++ if (!tkey) ++ goto err; ++ if (EVP_CIPHER_CTX_rand_key(evp_ctx, tkey) <= 0) ++ goto err; ++ if (ek == NULL) ++ { ++ ek = tkey; ++ eklen = tkeylen; ++ tkey = NULL; ++ } ++ + if (eklen != EVP_CIPHER_CTX_key_length(evp_ctx)) { + /* Some S/MIME clients don't use the same key + * and effective key length. The key length is +@@ -573,11 +593,16 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKE + */ + if(!EVP_CIPHER_CTX_set_key_length(evp_ctx, eklen)) + { +- PKCS7err(PKCS7_F_PKCS7_DATADECODE, +- PKCS7_R_DECRYPTED_KEY_IS_WRONG_LENGTH); +- goto err; ++ /* Use random key as MMA defence */ ++ OPENSSL_cleanse(ek, eklen); ++ OPENSSL_free(ek); ++ ek = tkey; ++ eklen = tkeylen; ++ tkey = NULL; + } + } ++ /* Clear errors so we don't leak information useful in MMA */ ++ ERR_clear_error(); + if (EVP_CipherInit_ex(evp_ctx,NULL,NULL,ek,NULL,0) <= 0) + goto err; + +@@ -587,6 +612,12 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKE + OPENSSL_free(ek); + } + ++ if (tkey) ++ { ++ OPENSSL_cleanse(tkey,tkeylen); ++ OPENSSL_free(tkey); ++ } ++ + if (out == NULL) + out=etmp; + else diff --git a/CVE-2012-1165.patch b/CVE-2012-1165.patch new file mode 100644 index 0000000..2575088 --- /dev/null +++ b/CVE-2012-1165.patch @@ -0,0 +1,25 @@ +Index: openssl-1.0.0g/crypto/asn1/asn_mime.c +=================================================================== +--- openssl-1.0.0g.orig/crypto/asn1/asn_mime.c ++++ openssl-1.0.0g/crypto/asn1/asn_mime.c +@@ -858,9 +858,8 @@ static int mime_hdr_addparam(MIME_HEADER + static int mime_hdr_cmp(const MIME_HEADER * const *a, + const MIME_HEADER * const *b) + { +- if ((*a)->name == NULL || (*b)->name == NULL) +- return (*a)->name - (*b)->name < 0 ? -1 : +- (*a)->name - (*b)->name > 0 ? 1 : 0; ++ if (!(*a)->name || !(*b)->name) ++ return !!(*a)->name - !!(*b)->name; + + return(strcmp((*a)->name, (*b)->name)); + } +@@ -868,6 +867,8 @@ static int mime_hdr_cmp(const MIME_HEADE + static int mime_param_cmp(const MIME_PARAM * const *a, + const MIME_PARAM * const *b) + { ++ if (!(*a)->param_name || !(*b)->param_name) ++ return !!(*a)->param_name - !!(*b)->param_name; + return(strcmp((*a)->param_name, (*b)->param_name)); + } + diff --git a/bug749210-Symmetric-crypto-errors-in-PKCS7_decrypt.patch b/bug749210-Symmetric-crypto-errors-in-PKCS7_decrypt.patch new file mode 100644 index 0000000..16d5c06 --- /dev/null +++ b/bug749210-Symmetric-crypto-errors-in-PKCS7_decrypt.patch @@ -0,0 +1,37 @@ +Index: openssl-1.0.0g/crypto/pkcs7/pk7_smime.c +=================================================================== +--- openssl-1.0.0g.orig/crypto/pkcs7/pk7_smime.c ++++ openssl-1.0.0g/crypto/pkcs7/pk7_smime.c +@@ -573,15 +573,30 @@ int PKCS7_decrypt(PKCS7 *p7, EVP_PKEY *p + return 0; + } + ret = SMIME_text(bread, data); ++ if (ret > 0 && BIO_method_type(tmpmem) == BIO_TYPE_CIPHER) ++ { ++ if (!BIO_get_cipher_status(tmpmem)) ++ ret = 0; ++ } + BIO_free_all(bread); + return ret; + } else { + for(;;) { + i = BIO_read(tmpmem, buf, sizeof(buf)); +- if(i <= 0) break; ++ if(i <= 0) ++ { ++ ret = 1; ++ if (BIO_method_type(tmpmem) == BIO_TYPE_CIPHER) ++ { ++ if (!BIO_get_cipher_status(tmpmem)) ++ ret = 0; ++ } ++ ++ break; ++ } + BIO_write(data, buf, i); + } + BIO_free_all(tmpmem); +- return 1; ++ return ret; + } + } diff --git a/bug749213-Free-headers-after-use.patch b/bug749213-Free-headers-after-use.patch new file mode 100644 index 0000000..6665b7e --- /dev/null +++ b/bug749213-Free-headers-after-use.patch @@ -0,0 +1,15 @@ +Index: openssl-1.0.0g/crypto/asn1/asn_mime.c +=================================================================== +--- openssl-1.0.0g.orig/crypto/asn1/asn_mime.c ++++ openssl-1.0.0g/crypto/asn1/asn_mime.c +@@ -486,9 +486,9 @@ ASN1_VALUE *SMIME_read_ASN1(BIO *bio, BI + + if(strcmp(hdr->value, "application/x-pkcs7-signature") && + strcmp(hdr->value, "application/pkcs7-signature")) { +- sk_MIME_HEADER_pop_free(headers, mime_hdr_free); + ASN1err(ASN1_F_SMIME_READ_ASN1,ASN1_R_SIG_INVALID_MIME_TYPE); + ERR_add_error_data(2, "type: ", hdr->value); ++ sk_MIME_HEADER_pop_free(headers, mime_hdr_free); + sk_BIO_pop_free(parts, BIO_vfree); + return NULL; + } diff --git a/bug749735.patch b/bug749735.patch new file mode 100644 index 0000000..8c27096 --- /dev/null +++ b/bug749735.patch @@ -0,0 +1,22 @@ +Index: openssl-1.0.0c/crypto/asn1/x_pubkey.c +=================================================================== +--- openssl-1.0.0c.orig/crypto/asn1/x_pubkey.c ++++ openssl-1.0.0c/crypto/asn1/x_pubkey.c +@@ -171,7 +171,16 @@ EVP_PKEY *X509_PUBKEY_get(X509_PUBKEY *k + goto error; + } + +- key->pkey = ret; ++ /* Check to see if another thread set key->pkey first */ ++ CRYPTO_w_lock(CRYPTO_LOCK_EVP_PKEY); ++ if (key->pkey) ++ { ++ EVP_PKEY_free(ret); ++ ret = key->pkey; ++ } ++ else ++ key->pkey = ret; ++ CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY); + CRYPTO_add(&ret->references, 1, CRYPTO_LOCK_EVP_PKEY); + + return ret; diff --git a/openssl.changes b/openssl.changes index 08653c0..ecd44fe 100644 --- a/openssl.changes +++ b/openssl.changes @@ -1,14 +1,33 @@ +------------------------------------------------------------------- +Tue Mar 27 09:16:37 UTC 2012 - gjhe@suse.com + +- fix bug[bnc#749735] - Memory leak when creating public keys. + fix bug[bnc#751977] - CMS and S/MIME Bleichenbacher attack + CVE-2012-0884 + +------------------------------------------------------------------- +Thu Mar 22 03:24:20 UTC 2012 - gjhe@suse.com + +- fix bug[bnc#751946] - S/MIME verification may erroneously fail + CVE-2012-1165 + +------------------------------------------------------------------- +Wed Mar 21 02:44:41 UTC 2012 - gjhe@suse.com + +- fix bug[bnc#749213]-Free headers after use in error message + and bug[bnc#749210]-Symmetric crypto errors in PKCS7_decrypt + ------------------------------------------------------------------- Tue Mar 20 14:29:24 UTC 2012 - cfarrell@suse.com - license update: OpenSSL - ------------------------------------------------------------------- Fri Feb 24 02:33:22 UTC 2012 - gjhe@suse.com - fix bug[bnc#748738] - Tolerate bad MIME headers in openssl's asn1 parser. + CVE-2006-7250 ------------------------------------------------------------------- Thu Feb 2 06:55:12 UTC 2012 - gjhe@suse.com diff --git a/openssl.spec b/openssl.spec index 46c8b1f..75c6f6d 100644 --- a/openssl.spec +++ b/openssl.spec @@ -50,6 +50,11 @@ Patch7: openssl-1.0.0b-aesni.patch #Patch8: CVE-2011-0014.patch Patch10: openssl-call-engine-reg-comp.patch Patch11: Bug748738_Tolerate_bad_MIME_headers.patch +Patch12: bug749213-Free-headers-after-use.patch +Patch13: bug749210-Symmetric-crypto-errors-in-PKCS7_decrypt.patch +Patch14: CVE-2012-1165.patch +Patch15: CVE-2012-0884.patch +Patch16: bug749735.patch BuildRoot: %{_tmppath}/%{name}-%{version}-build %description @@ -188,6 +193,11 @@ Authors: #%patch8 -p1 %patch10 %patch11 -p1 +%patch12 -p1 +%patch13 -p1 +%patch14 -p1 +%patch15 -p1 +%patch16 -p1 cp -p %{S:10} . echo "adding/overwriting some entries in the 'table' hash in Configure" # $dso_scheme:$shared_target:$shared_cflag:$shared_ldflag:$shared_extension:$ranlib:$arflags