Hello community, here is the log from the commit of package openssl-1_0_0 for openSUSE:Factory checked in at 2019-09-23 12:00:41 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/openssl-1_0_0 (Old) and /work/SRC/openSUSE:Factory/.openssl-1_0_0.new.7948 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "openssl-1_0_0" Mon Sep 23 12:00:41 2019 rev:17 rq:730424 version:1.0.2r Changes: -------- --- /work/SRC/openSUSE:Factory/openssl-1_0_0/openssl-1_0_0.changes 2019-03-04 09:14:13.644667358 +0100 +++ /work/SRC/openSUSE:Factory/.openssl-1_0_0.new.7948/openssl-1_0_0.changes 2019-09-23 12:00:42.781971720 +0200 @@ -1,0 +2,10 @@ +Thu Sep 12 09:53:12 UTC 2019 - Pedro Monreal Gonzalez <[email protected]> + +- OpenSSL Security Advisory [10 September 2019] + * EC_GROUP_set_generator side channel attack avoidance. [bsc#1150003, CVE-2019-1547] + * Bleichenbacher attack against cms/pkcs7 encryption transported key [bsc#1150250, CVE-2019-1563] +- Added patches: + * openssl-CVE-2019-1547.patch + * openssl-CVE-2019-1563.patch + +------------------------------------------------------------------- New: ---- openssl-CVE-2019-1547.patch openssl-CVE-2019-1563.patch ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ openssl-1_0_0.spec ++++++ --- /var/tmp/diff_new_pack.xtNOsK/_old 2019-09-23 12:00:44.129971497 +0200 +++ /var/tmp/diff_new_pack.xtNOsK/_new 2019-09-23 12:00:44.133971497 +0200 @@ -91,6 +91,9 @@ Patch78: 0001-Set-FIPS-thread-id-callback.patch Patch79: openssl-CVE-2018-0737-fips.patch Patch80: openssl-One_and_Done.patch +# OpenSSL Security Advisory [10 September 2019] +Patch81: openssl-CVE-2019-1547.patch +Patch82: openssl-CVE-2019-1563.patch # steam patches Patch100: openssl-fix-cpuid_setup.patch BuildRequires: bc @@ -231,6 +234,8 @@ %patch78 -R -p1 %patch79 -p1 %patch80 -p1 +%patch81 -p1 +%patch82 -p1 # clean up patching leftovers find . -name '*.orig' -delete ++++++ openssl-CVE-2019-1547.patch ++++++ >From 21c856b75d81eff61aa63b4f036bb64a85bf6d46 Mon Sep 17 00:00:00 2001 From: Billy Brumley <[email protected]> Date: Sat, 7 Sep 2019 10:50:58 +0300 Subject: [PATCH] [crypto/ec] for ECC parameters with NULL or zero cofactor, compute it The cofactor argument to EC_GROUP_set_generator is optional, and SCA mitigations for ECC currently use it. So the library currently falls back to very old SCA-vulnerable code if the cofactor is not present. This PR allows EC_GROUP_set_generator to compute the cofactor for all curves of cryptographic interest. Steering scalar multiplication to more SCA-robust code. This issue affects persisted private keys in explicit parameter form, where the (optional) cofactor field is zero or absent. It also affects curves not built-in to the library, but constructed programatically with explicit parameters, then calling EC_GROUP_set_generator with a nonsensical value (NULL, zero). The very old scalar multiplication code is known to be vulnerable to local uarch attacks, outside of the OpenSSL threat model. New results suggest the code path is also vulnerable to traditional wall clock timing attacks. CVE-2019-1547 Reviewed-by: Nicola Tuveri <[email protected]> Reviewed-by: Matt Caswell <[email protected]> (Merged from https://github.com/openssl/openssl/pull/9799) --- CHANGES | 7 ++++ crypto/ec/ec.h | 6 ++- crypto/ec/ec_err.c | 3 +- crypto/ec/ec_lib.c | 102 +++++++++++++++++++++++++++++++++++++++++---- 4 files changed, 108 insertions(+), 10 deletions(-) diff --git a/crypto/ec/ec.h b/crypto/ec/ec.h index 81e6faf6c5..b62613da55 100644 --- a/crypto/ec/ec.h +++ b/crypto/ec/ec.h @@ -1270,13 +1271,14 @@ void ERR_load_EC_strings(void); # define EC_R_SLOT_FULL 108 # define EC_R_UNDEFINED_GENERATOR 113 # define EC_R_UNDEFINED_ORDER 128 +# define EC_R_UNKNOWN_COFACTOR 152 # define EC_R_UNKNOWN_GROUP 129 # define EC_R_UNKNOWN_ORDER 114 # define EC_R_UNSUPPORTED_FIELD 131 # define EC_R_WRONG_CURVE_PARAMETERS 145 # define EC_R_WRONG_ORDER 130 -#ifdef __cplusplus +# ifdef __cplusplus } -#endif +# endif #endif diff --git a/crypto/ec/ec_err.c b/crypto/ec/ec_err.c index 6fe5baafd4..220541161e 100644 --- a/crypto/ec/ec_err.c +++ b/crypto/ec/ec_err.c @@ -310,6 +310,7 @@ static ERR_STRING_DATA EC_str_reasons[] = { {ERR_REASON(EC_R_SLOT_FULL), "slot full"}, {ERR_REASON(EC_R_UNDEFINED_GENERATOR), "undefined generator"}, {ERR_REASON(EC_R_UNDEFINED_ORDER), "undefined order"}, + {ERR_REASON(EC_R_UNKNOWN_COFACTOR), "unknown cofactor"}, {ERR_REASON(EC_R_UNKNOWN_GROUP), "unknown group"}, {ERR_REASON(EC_R_UNKNOWN_ORDER), "unknown order"}, {ERR_REASON(EC_R_UNSUPPORTED_FIELD), "unsupported field"}, diff --git a/crypto/ec/ec_lib.c b/crypto/ec/ec_lib.c index cd2c420176..15302322f7 100644 --- a/crypto/ec/ec_lib.c +++ b/crypto/ec/ec_lib.c @@ -294,6 +294,67 @@ int EC_METHOD_get_field_type(const EC_METHOD *meth) return meth->field_type; } +/*- + * Try computing cofactor from the generator order (n) and field cardinality (q). + * This works for all curves of cryptographic interest. + * + * Hasse thm: q + 1 - 2*sqrt(q) <= n*h <= q + 1 + 2*sqrt(q) + * h_min = (q + 1 - 2*sqrt(q))/n + * h_max = (q + 1 + 2*sqrt(q))/n + * h_max - h_min = 4*sqrt(q)/n + * So if n > 4*sqrt(q) holds, there is only one possible value for h: + * h = \lfloor (h_min + h_max)/2 \rceil = \lfloor (q + 1)/n \rceil + * + * Otherwise, zero cofactor and return success. + */ +static int ec_guess_cofactor(EC_GROUP *group) { + int ret = 0; + BN_CTX *ctx = NULL; + BIGNUM *q = NULL; + + /*- + * If the cofactor is too large, we cannot guess it. + * The RHS of below is a strict overestimate of lg(4 * sqrt(q)) + */ + if (BN_num_bits(&group->order) <= (BN_num_bits(&group->field) + 1) / 2 + 3) { + /* default to 0 */ + BN_zero(&group->cofactor); + /* return success */ + return 1; + } + + if ((ctx = BN_CTX_new()) == NULL) + return 0; + + BN_CTX_start(ctx); + if ((q = BN_CTX_get(ctx)) == NULL) + goto err; + + /* set q = 2**m for binary fields; q = p otherwise */ + if (group->meth->field_type == NID_X9_62_characteristic_two_field) { + BN_zero(q); + if (!BN_set_bit(q, BN_num_bits(&group->field) - 1)) + goto err; + } else { + if (!BN_copy(q, &group->field)) + goto err; + } + + /* compute h = \lfloor (q + 1)/n \rceil = \lfloor (q + 1 + n/2)/n \rfloor */ + if (!BN_rshift1(&group->cofactor, &group->order) /* n/2 */ + || !BN_add(&group->cofactor, &group->cofactor, q) /* q + n/2 */ + /* q + 1 + n/2 */ + || !BN_add(&group->cofactor, &group->cofactor, BN_value_one()) + /* (q + 1 + n/2)/n */ + || !BN_div(&group->cofactor, NULL, &group->cofactor, &group->order, ctx)) + goto err; + ret = 1; + err: + BN_CTX_end(ctx); + BN_CTX_free(ctx); + return ret; +} + int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, const BIGNUM *order, const BIGNUM *cofactor) { @@ -302,6 +363,33 @@ int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, return 0; } + /* require group->field >= 1 */ + if (BN_is_zero(&group->field) || BN_is_negative(&group->field)) { + ECerr(EC_F_EC_GROUP_SET_GENERATOR, EC_R_INVALID_FIELD); + return 0; + } + + /*- + * - require order >= 1 + * - enforce upper bound due to Hasse thm: order can be no more than one bit + * longer than field cardinality + */ + if (order == NULL || BN_is_zero(order) || BN_is_negative(order) + || BN_num_bits(order) > BN_num_bits(&group->field) + 1) { + ECerr(EC_F_EC_GROUP_SET_GENERATOR, EC_R_INVALID_GROUP_ORDER); + return 0; + } + + /*- + * Unfortunately the cofactor is an optional field in many standards. + * Internally, the lib uses 0 cofactor as a marker for "unknown cofactor". + * So accept cofactor == NULL or cofactor >= 0. + */ + if (cofactor != NULL && BN_is_negative(cofactor)) { + ECerr(EC_F_EC_GROUP_SET_GENERATOR, EC_R_UNKNOWN_COFACTOR); + return 0; + } + if (group->generator == NULL) { group->generator = EC_POINT_new(group); if (group->generator == NULL) @@ -310,17 +398,17 @@ int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, if (!EC_POINT_copy(group->generator, generator)) return 0; - if (order != NULL) { - if (!BN_copy(&group->order, order)) - return 0; - } else - BN_zero(&group->order); + if (!BN_copy(&group->order, order)) + return 0; - if (cofactor != NULL) { + /* Either take the provided positive cofactor, or try to compute it */ + if (cofactor != NULL && !BN_is_zero(cofactor)) { if (!BN_copy(&group->cofactor, cofactor)) return 0; - } else + } else if (!ec_guess_cofactor(group)) { BN_zero(&group->cofactor); + return 0; + } /*- * Access to the `mont_data` field of an EC_GROUP struct should always be -- 2.17.1 ++++++ openssl-CVE-2019-1563.patch ++++++ >From e21f8cf78a125cd3c8c0d1a1a6c8bb0b901f893f Mon Sep 17 00:00:00 2001 From: Bernd Edlinger <[email protected]> Date: Sun, 1 Sep 2019 00:16:28 +0200 Subject: [PATCH] Fix a padding oracle in PKCS7_dataDecode and CMS_decrypt_set1_pkey An attack is simple, if the first CMS_recipientInfo is valid but the second CMS_recipientInfo is chosen ciphertext. If the second recipientInfo decodes to PKCS #1 v1.5 form plaintext, the correct encryption key will be replaced by garbage, and the message cannot be decoded, but if the RSA decryption fails, the correct encryption key is used and the recipient will not notice the attack. As a work around for this potential attack the length of the decrypted key must be equal to the cipher default key length, in case the certifiate is not given and all recipientInfo are tried out. The old behaviour can be re-enabled in the CMS code by setting the CMS_DEBUG_DECRYPT flag. Reviewed-by: Matt Caswell <[email protected]> (Merged from https://github.com/openssl/openssl/pull/9777) (cherry picked from commit 5840ed0cd1e6487d247efbc1a04136a41d7b3a37) --- CHANGES | 14 ++++++++++++++ crypto/cms/cms_env.c | 18 +++++++++++++++++- crypto/cms/cms_lcl.h | 2 ++ crypto/cms/cms_smime.c | 4 ++++ crypto/pkcs7/pk7_doit.c | 12 ++++++++---- 5 files changed, 45 insertions(+), 5 deletions(-) diff --git a/crypto/cms/cms_env.c b/crypto/cms/cms_env.c index 93c06cb00a..77c8f0a483 100644 --- a/crypto/cms/cms_env.c +++ b/crypto/cms/cms_env.c @@ -422,6 +422,7 @@ static int cms_RecipientInfo_ktri_decrypt(CMS_ContentInfo *cms, unsigned char *ek = NULL; size_t eklen; int ret = 0; + size_t fixlen = 0; CMS_EncryptedContentInfo *ec; ec = cms->d.envelopedData->encryptedContentInfo; @@ -430,6 +431,19 @@ static int cms_RecipientInfo_ktri_decrypt(CMS_ContentInfo *cms, return 0; } + if (cms->d.envelopedData->encryptedContentInfo->havenocert + && !cms->d.envelopedData->encryptedContentInfo->debug) { + X509_ALGOR *calg = ec->contentEncryptionAlgorithm; + const EVP_CIPHER *ciph = EVP_get_cipherbyobj(calg->algorithm); + + if (ciph == NULL) { + CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT, CMS_R_UNKNOWN_CIPHER); + return 0; + } + + fixlen = EVP_CIPHER_key_length(ciph); + } + ktri->pctx = EVP_PKEY_CTX_new(pkey, NULL); if (!ktri->pctx) return 0; @@ -460,7 +474,9 @@ static int cms_RecipientInfo_ktri_decrypt(CMS_ContentInfo *cms, if (EVP_PKEY_decrypt(ktri->pctx, ek, &eklen, ktri->encryptedKey->data, - ktri->encryptedKey->length) <= 0) { + ktri->encryptedKey->length) <= 0 + || eklen == 0 + || (fixlen != 0 && eklen != fixlen)) { CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT, CMS_R_CMS_LIB); goto err; } diff --git a/crypto/cms/cms_lcl.h b/crypto/cms/cms_lcl.h index 20f2c25f5a..f1f78e6a47 100644 --- a/crypto/cms/cms_lcl.h +++ b/crypto/cms/cms_lcl.h @@ -172,6 +172,8 @@ struct CMS_EncryptedContentInfo_st { size_t keylen; /* Set to 1 if we are debugging decrypt and don't fake keys for MMA */ int debug; + /* Set to 1 if we have no cert and need extra safety measures for MMA */ + int havenocert; }; struct CMS_RecipientInfo_st { diff --git a/crypto/cms/cms_smime.c b/crypto/cms/cms_smime.c index 07e3472e10..0b3d96ca62 100644 --- a/crypto/cms/cms_smime.c +++ b/crypto/cms/cms_smime.c @@ -737,6 +737,10 @@ int CMS_decrypt(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert, cms->d.envelopedData->encryptedContentInfo->debug = 1; else cms->d.envelopedData->encryptedContentInfo->debug = 0; + if (!cert) + cms->d.envelopedData->encryptedContentInfo->havenocert = 1; + else + cms->d.envelopedData->encryptedContentInfo->havenocert = 0; if (!pk && !cert && !dcont && !out) return 1; if (pk && !CMS_decrypt_set1_pkey(cms, pk, cert)) diff --git a/crypto/pkcs7/pk7_doit.c b/crypto/pkcs7/pk7_doit.c index 6a463680d7..63bc88269f 100644 --- a/crypto/pkcs7/pk7_doit.c +++ b/crypto/pkcs7/pk7_doit.c @@ -191,7 +191,8 @@ static int pkcs7_encode_rinfo(PKCS7_RECIP_INFO *ri, } static int pkcs7_decrypt_rinfo(unsigned char **pek, int *peklen, - PKCS7_RECIP_INFO *ri, EVP_PKEY *pkey) + PKCS7_RECIP_INFO *ri, EVP_PKEY *pkey, + size_t fixlen) { EVP_PKEY_CTX *pctx = NULL; unsigned char *ek = NULL; @@ -224,7 +225,9 @@ static int pkcs7_decrypt_rinfo(unsigned char **pek, int *peklen, } if (EVP_PKEY_decrypt(pctx, ek, &eklen, - ri->enc_key->data, ri->enc_key->length) <= 0) { + ri->enc_key->data, ri->enc_key->length) <= 0 + || eklen == 0 + || (fixlen != 0 && eklen != fixlen)) { ret = 0; PKCS7err(PKCS7_F_PKCS7_DECRYPT_RINFO, ERR_R_EVP_LIB); goto err; @@ -571,13 +574,14 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert) for (i = 0; i < sk_PKCS7_RECIP_INFO_num(rsk); i++) { ri = sk_PKCS7_RECIP_INFO_value(rsk, i); - if (pkcs7_decrypt_rinfo(&ek, &eklen, ri, pkey) < 0) + if (pkcs7_decrypt_rinfo(&ek, &eklen, ri, pkey, + EVP_CIPHER_key_length(evp_cipher)) < 0) goto err; ERR_clear_error(); } } else { /* Only exit on fatal errors, not decrypt failure */ - if (pkcs7_decrypt_rinfo(&ek, &eklen, ri, pkey) < 0) + if (pkcs7_decrypt_rinfo(&ek, &eklen, ri, pkey, 0) < 0) goto err; ERR_clear_error(); } -- 2.17.1
