From 7be330ece931ae5c98351890e3627f3c0c04cac2 Mon Sep 17 00:00:00 2001 From: maxice8 Date: Wed, 3 Oct 2018 17:26:29 -0300 Subject: [PATCH] botan: fix CVE-2018-12435 --- .../botan/patches/CVE-2018-12435_part1.patch | 132 +++++++++ .../botan/patches/CVE-2018-12435_part2.patch | 269 ++++++++++++++++++ srcpkgs/botan/template | 2 +- 3 files changed, 402 insertions(+), 1 deletion(-) create mode 100644 srcpkgs/botan/patches/CVE-2018-12435_part1.patch create mode 100644 srcpkgs/botan/patches/CVE-2018-12435_part2.patch diff --git a/srcpkgs/botan/patches/CVE-2018-12435_part1.patch b/srcpkgs/botan/patches/CVE-2018-12435_part1.patch new file mode 100644 index 00000000000..a6b374b1076 --- /dev/null +++ b/srcpkgs/botan/patches/CVE-2018-12435_part1.patch @@ -0,0 +1,132 @@ +From 2cfa191a940b7b884f24d23d94227ff382c672b4 Mon Sep 17 00:00:00 2001 +From: Jack Lloyd +Date: Tue, 17 Apr 2018 18:06:34 -0400 +Subject: [PATCH] Add EC_Group::inverse_mod_order + +Centralizing this logic allows curve specific implementations such +as using a precomputed ladder for exponentiating by p - 2 + +GH #1479 +--- + src/lib/pubkey/ec_group/ec_group.cpp | 10 ++++++++++ + src/lib/pubkey/ec_group/ec_group.h | 5 +++++ + src/lib/pubkey/ecdh/ecdh.cpp | 2 +- + src/lib/pubkey/ecdsa/ecdsa.cpp | 4 ++-- + src/lib/pubkey/ecgdsa/ecgdsa.cpp | 2 +- + src/lib/pubkey/sm2/sm2.cpp | 4 ++-- + 6 files changed, 21 insertions(+), 6 deletions(-) + +diff --git a/src/lib/pubkey/ec_group/ec_group.cpp b/src/lib/pubkey/ec_group/ec_group.cpp +index fc512b7332..ac23aa151e 100644 +--- src/lib/pubkey/ec_group/ec_group.cpp ++++ src/lib/pubkey/ec_group/ec_group.cpp +@@ -87,6 +87,11 @@ class EC_Group_Data final + return m_mod_order.multiply(x, y); + } + ++ BigInt inverse_mod_order(const BigInt& x) const ++ { ++ return inverse_mod(x, m_order); ++ } ++ + PointGFp blinded_base_point_multiply(const BigInt& k, + RandomNumberGenerator& rng, + std::vector& ws) const +@@ -469,6 +476,11 @@ BigInt EC_Group::multiply_mod_order(const BigInt& x, const BigInt& y) const + return data().multiply_mod_order(x, y); + } + ++BigInt EC_Group::inverse_mod_order(const BigInt& x) const ++ { ++ return data().inverse_mod_order(x); ++ } ++ + const OID& EC_Group::get_curve_oid() const + { + return data().oid(); +diff --git a/src/lib/pubkey/ec_group/ec_group.h b/src/lib/pubkey/ec_group/ec_group.h +index 8bb1a30448..f273108d2b 100644 +--- src/lib/pubkey/ec_group/ec_group.h ++++ src/lib/pubkey/ec_group/ec_group.h +@@ -193,6 +193,11 @@ class BOTAN_PUBLIC_API(2,0) EC_Group final + */ + BigInt mod_order(const BigInt& x) const; + ++ /* ++ * Return inverse of x modulo the order ++ */ ++ BigInt inverse_mod_order(const BigInt& x) const; ++ + /* + * Reduce (x*y) modulo the order + */ +diff --git a/src/lib/pubkey/ecdh/ecdh.cpp b/src/lib/pubkey/ecdh/ecdh.cpp +index adadb27036..59f245a00c 100644 +--- src/lib/pubkey/ecdh/ecdh.cpp ++++ src/lib/pubkey/ecdh/ecdh.cpp +@@ -31,7 +31,7 @@ class ECDH_KA_Operation final : public PK_Ops::Key_Agreement_with_KDF + m_group(key.domain()), + m_rng(rng) + { +- m_l_times_priv = inverse_mod(m_group.get_cofactor(), m_group.get_order()) * key.private_value(); ++ m_l_times_priv = m_group.inverse_mod_order(m_group.get_cofactor()) * key.private_value(); + } + + secure_vector raw_agree(const uint8_t w[], size_t w_len) override +diff --git a/src/lib/pubkey/ecdsa/ecdsa.cpp b/src/lib/pubkey/ecdsa/ecdsa.cpp +index 03f5e57ab6..6e104f1641 100644 +--- src/lib/pubkey/ecdsa/ecdsa.cpp ++++ src/lib/pubkey/ecdsa/ecdsa.cpp +@@ -89,7 +89,7 @@ ECDSA_Signature_Operation::raw_sign(const uint8_t msg[], size_t msg_len, + const BigInt k = m_group.random_scalar(rng); + #endif + +- const BigInt k_inv = inverse_mod(k, m_group.get_order()); ++ const BigInt k_inv = m_group.inverse_mod_order(k); + const BigInt r = m_group.mod_order( + m_group.blinded_base_point_multiply_x(k, rng, m_ws)); + +@@ -142,7 +142,7 @@ bool ECDSA_Verification_Operation::verify(const uint8_t msg[], size_t msg_len, + if(r <= 0 || r >= m_group.get_order() || s <= 0 || s >= m_group.get_order()) + return false; + +- const BigInt w = inverse_mod(s, m_group.get_order()); ++ const BigInt w = m_group.inverse_mod_order(s); + + const BigInt u1 = m_group.multiply_mod_order(e, w); + const BigInt u2 = m_group.multiply_mod_order(r, w); +diff --git a/src/lib/pubkey/ecgdsa/ecgdsa.cpp b/src/lib/pubkey/ecgdsa/ecgdsa.cpp +index 192d999a8e..61b7ae0558 100644 +--- src/lib/pubkey/ecgdsa/ecgdsa.cpp ++++ src/lib/pubkey/ecgdsa/ecgdsa.cpp +@@ -115,7 +115,7 @@ bool ECGDSA_Verification_Operation::verify(const uint8_t msg[], size_t msg_len, + if(r <= 0 || r >= m_group.get_order() || s <= 0 || s >= m_group.get_order()) + return false; + +- const BigInt w = inverse_mod(r, m_group.get_order()); ++ const BigInt w = m_group.inverse_mod_order(r); + + const BigInt u1 = m_group.multiply_mod_order(e, w); + const BigInt u2 = m_group.multiply_mod_order(s, w); +diff --git a/src/lib/pubkey/sm2/sm2.cpp b/src/lib/pubkey/sm2/sm2.cpp +index 95fe28f147..1096ea99f5 100644 +--- src/lib/pubkey/sm2/sm2.cpp ++++ src/lib/pubkey/sm2/sm2.cpp +@@ -30,7 +30,7 @@ SM2_Signature_PrivateKey::SM2_Signature_PrivateKey(const AlgorithmIdentifier& al + const secure_vector& key_bits) : + EC_PrivateKey(alg_id, key_bits) + { +- m_da_inv = inverse_mod(m_private_key + 1, domain().get_order()); ++ m_da_inv = domain().inverse_mod_order(m_private_key + 1); + } + + SM2_Signature_PrivateKey::SM2_Signature_PrivateKey(RandomNumberGenerator& rng, +@@ -38,7 +38,7 @@ SM2_Signature_PrivateKey::SM2_Signature_PrivateKey(RandomNumberGenerator& rng, + const BigInt& x) : + EC_PrivateKey(rng, domain, x) + { +- m_da_inv = inverse_mod(m_private_key + 1, domain.get_order()); ++ m_da_inv = domain.inverse_mod_order(m_private_key + 1); + } + + std::vector sm2_compute_za(HashFunction& hash, diff --git a/srcpkgs/botan/patches/CVE-2018-12435_part2.patch b/srcpkgs/botan/patches/CVE-2018-12435_part2.patch new file mode 100644 index 00000000000..e02bea33930 --- /dev/null +++ b/srcpkgs/botan/patches/CVE-2018-12435_part2.patch @@ -0,0 +1,269 @@ +From 48fc8df51d99f9d8ba251219367b3d629cc848e3 Mon Sep 17 00:00:00 2001 +From: Jack Lloyd +Date: Tue, 5 Jun 2018 18:40:14 -0400 +Subject: [PATCH] Address DSA/ECDSA side channel + +--- + src/lib/pubkey/dsa/dsa.cpp | 38 ++++++++++++++++++++++++++---------- + src/lib/pubkey/ec_group/ec_group.cpp | 20 +++++++++++++++++++ + src/lib/pubkey/ec_group/ec_group.h | 10 ++++++++++ + src/lib/pubkey/ecdsa/ecdsa.cpp | 29 ++++++++++++++++++++------- + 4 files changed, 80 insertions(+), 17 deletions(-) + +diff --git a/src/lib/pubkey/dsa/dsa.cpp b/src/lib/pubkey/dsa/dsa.cpp +index 1728049727..7142e47880 100644 +--- src/lib/pubkey/dsa/dsa.cpp ++++ src/lib/pubkey/dsa/dsa.cpp +@@ -75,7 +75,9 @@ namespace { + class DSA_Signature_Operation final : public PK_Ops::Signature_with_EMSA + { + public: +- DSA_Signature_Operation(const DSA_PrivateKey& dsa, const std::string& emsa) : ++ DSA_Signature_Operation(const DSA_PrivateKey& dsa, ++ const std::string& emsa, ++ RandomNumberGenerator& rng) : + PK_Ops::Signature_with_EMSA(emsa), + m_group(dsa.get_group()), + m_x(dsa.get_x()), +@@ -84,6 +86,9 @@ class DSA_Signature_Operation final : public PK_Ops::Signature_with_EMSA + #if defined(BOTAN_HAS_RFC6979_GENERATOR) + m_rfc6979_hash = hash_for_emsa(emsa); + #endif ++ ++ m_b = BigInt::random_integer(rng, 2, dsa.group_q()); ++ m_b_inv = inverse_mod(m_b, dsa.group_q()); + } + + size_t max_input_bits() const override { return m_group.get_q().bits(); } +@@ -97,6 +102,8 @@ class DSA_Signature_Operation final : public PK_Ops::Signature_with_EMSA + #if defined(BOTAN_HAS_RFC6979_GENERATOR) + std::string m_rfc6979_hash; + #endif ++ ++ BigInt m_b, m_b_inv; + }; + + secure_vector +@@ -105,22 +112,32 @@ DSA_Signature_Operation::raw_sign(const uint8_t msg[], size_t msg_len, + { + const BigInt& q = m_group.get_q(); + +- BigInt i(msg, msg_len, q.bits()); ++ BigInt m(msg, msg_len, q.bits()); + +- while(i >= q) +- i -= q; ++ while(m >= q) ++ m -= q; + + #if defined(BOTAN_HAS_RFC6979_GENERATOR) + BOTAN_UNUSED(rng); +- const BigInt k = generate_rfc6979_nonce(m_x, q, i, m_rfc6979_hash); ++ const BigInt k = generate_rfc6979_nonce(m_x, q, m, m_rfc6979_hash); + #else + const BigInt k = BigInt::random_integer(rng, 1, q); + #endif + +- BigInt s = inverse_mod(k, q); ++ const BigInt k_inv = inverse_mod(k, q); ++ + const BigInt r = m_mod_q.reduce(m_group.power_g_p(k)); + +- s = m_mod_q.multiply(s, mul_add(m_x, r, i)); ++ /* ++ * Blind the input message and compute x*r+m as (x*r*b + m*b)/b ++ */ ++ m_b = m_mod_q.square(m_b); ++ m_b_inv = m_mod_q.square(m_b_inv); ++ ++ m = m_mod_q.multiply(m_b, m); ++ const BigInt xr = m_mod_q.multiply(m_mod_q.multiply(m_x, m_b), r); ++ ++ const BigInt s = m_mod_q.multiply(m_b_inv, m_mod_q.multiply(k_inv, xr + m)); + + // With overwhelming probability, a bug rather than actual zero r/s + if(r.is_zero() || s.is_zero()) +@@ -141,7 +158,8 @@ class DSA_Verification_Operation final : public PK_Ops::Verification_with_EMSA + m_group(dsa.get_group()), + m_y(dsa.get_y()), + m_mod_q(dsa.group_q()) +- {} ++ { ++ } + + size_t max_input_bits() const override { return m_group.get_q().bits(); } + +@@ -194,12 +212,12 @@ DSA_PublicKey::create_verification_op(const std::string& params, + } + + std::unique_ptr +-DSA_PrivateKey::create_signature_op(RandomNumberGenerator& /*rng*/, ++DSA_PrivateKey::create_signature_op(RandomNumberGenerator& rng, + const std::string& params, + const std::string& provider) const + { + if(provider == "base" || provider.empty()) +- return std::unique_ptr(new DSA_Signature_Operation(*this, params)); ++ return std::unique_ptr(new DSA_Signature_Operation(*this, params, rng)); + throw Provider_Not_Found(algo_name(), provider); + } + +diff --git a/src/lib/pubkey/ec_group/ec_group.cpp b/src/lib/pubkey/ec_group/ec_group.cpp +index 004708c7cc..2dfcdc0d94 100644 +--- src/lib/pubkey/ec_group/ec_group.cpp ++++ src/lib/pubkey/ec_group/ec_group.cpp +@@ -82,11 +82,21 @@ class EC_Group_Data final + + BigInt mod_order(const BigInt& x) const { return m_mod_order.reduce(x); } + ++ BigInt square_mod_order(const BigInt& x) const ++ { ++ return m_mod_order.square(x); ++ } ++ + BigInt multiply_mod_order(const BigInt& x, const BigInt& y) const + { + return m_mod_order.multiply(x, y); + } + ++ BigInt multiply_mod_order(const BigInt& x, const BigInt& y, const BigInt& z) const ++ { ++ return m_mod_order.multiply(m_mod_order.multiply(x, y), z); ++ } ++ + BigInt inverse_mod_order(const BigInt& x) const + { + return inverse_mod(x, m_order); +@@ -469,11 +479,21 @@ BigInt EC_Group::mod_order(const BigInt& k) const + return data().mod_order(k); + } + ++BigInt EC_Group::square_mod_order(const BigInt& x) const ++ { ++ return data().square_mod_order(x); ++ } ++ + BigInt EC_Group::multiply_mod_order(const BigInt& x, const BigInt& y) const + { + return data().multiply_mod_order(x, y); + } + ++BigInt EC_Group::multiply_mod_order(const BigInt& x, const BigInt& y, const BigInt& z) const ++ { ++ return data().multiply_mod_order(x, y, z); ++ } ++ + BigInt EC_Group::inverse_mod_order(const BigInt& x) const + { + return data().inverse_mod_order(x); +diff --git a/src/lib/pubkey/ec_group/ec_group.h b/src/lib/pubkey/ec_group/ec_group.h +index f273108d2b..f8c1c1a123 100644 +--- src/lib/pubkey/ec_group/ec_group.h ++++ src/lib/pubkey/ec_group/ec_group.h +@@ -198,11 +198,21 @@ class BOTAN_PUBLIC_API(2,0) EC_Group final + */ + BigInt inverse_mod_order(const BigInt& x) const; + ++ /* ++ * Reduce (x*x) modulo the order ++ */ ++ BigInt square_mod_order(const BigInt& x) const; ++ + /* + * Reduce (x*y) modulo the order + */ + BigInt multiply_mod_order(const BigInt& x, const BigInt& y) const; + ++ /* ++ * Reduce (x*y*z) modulo the order ++ */ ++ BigInt multiply_mod_order(const BigInt& x, const BigInt& y, const BigInt& z) const; ++ + /** + * Return the cofactor + * @result the cofactor +diff --git a/src/lib/pubkey/ecdsa/ecdsa.cpp b/src/lib/pubkey/ecdsa/ecdsa.cpp +index 6e104f1641..2409d8f0d2 100644 +--- src/lib/pubkey/ecdsa/ecdsa.cpp ++++ src/lib/pubkey/ecdsa/ecdsa.cpp +@@ -51,7 +51,8 @@ class ECDSA_Signature_Operation final : public PK_Ops::Signature_with_EMSA + public: + + ECDSA_Signature_Operation(const ECDSA_PrivateKey& ecdsa, +- const std::string& emsa) : ++ const std::string& emsa, ++ RandomNumberGenerator& rng) : + PK_Ops::Signature_with_EMSA(emsa), + m_group(ecdsa.domain()), + m_x(ecdsa.private_value()) +@@ -59,6 +60,9 @@ class ECDSA_Signature_Operation final : public PK_Ops::Signature_with_EMSA + #if defined(BOTAN_HAS_RFC6979_GENERATOR) + m_rfc6979_hash = hash_for_emsa(emsa); + #endif ++ ++ m_b = m_group.random_scalar(rng); ++ m_b_inv = m_group.inverse_mod_order(m_b); + } + + size_t max_input_bits() const override { return m_group.get_order_bits(); } +@@ -75,6 +79,8 @@ class ECDSA_Signature_Operation final : public PK_Ops::Signature_with_EMSA + #endif + + std::vector m_ws; ++ ++ BigInt m_b, m_b_inv; + }; + + secure_vector +@@ -89,12 +95,21 @@ ECDSA_Signature_Operation::raw_sign(const uint8_t msg[], size_t msg_len, + const BigInt k = m_group.random_scalar(rng); + #endif + +- const BigInt k_inv = m_group.inverse_mod_order(k); + const BigInt r = m_group.mod_order( + m_group.blinded_base_point_multiply_x(k, rng, m_ws)); + +- const BigInt xrm = m_group.mod_order(m_group.multiply_mod_order(m_x, r) + m); +- const BigInt s = m_group.multiply_mod_order(k_inv, xrm); ++ const BigInt k_inv = m_group.inverse_mod_order(k); ++ ++ /* ++ * Blind the input message and compute x*r+m as (x*r*b + m*b)/b ++ */ ++ m_b = m_group.square_mod_order(m_b); ++ m_b_inv = m_group.square_mod_order(m_b_inv); ++ ++ m = m_group.multiply_mod_order(m_b, m); ++ const BigInt xr = m_group.multiply_mod_order(m_x, m_b, r); ++ ++ const BigInt s = m_group.multiply_mod_order(k_inv, xr + m, m_b_inv); + + // With overwhelming probability, a bug rather than actual zero r/s + if(r.is_zero() || s.is_zero()) +@@ -144,7 +159,7 @@ bool ECDSA_Verification_Operation::verify(const uint8_t msg[], size_t msg_len, + + const BigInt w = m_group.inverse_mod_order(s); + +- const BigInt u1 = m_group.multiply_mod_order(e, w); ++ const BigInt u1 = m_group.multiply_mod_order(m_group.mod_order(e), w); + const BigInt u2 = m_group.multiply_mod_order(r, w); + const PointGFp R = m_gy_mul.multi_exp(u1, u2); + +@@ -198,7 +213,7 @@ ECDSA_PublicKey::create_verification_op(const std::string& params, + } + + std::unique_ptr +-ECDSA_PrivateKey::create_signature_op(RandomNumberGenerator& /*rng*/, ++ECDSA_PrivateKey::create_signature_op(RandomNumberGenerator& rng, + const std::string& params, + const std::string& provider) const + { +@@ -233,7 +248,7 @@ ECDSA_PrivateKey::create_signature_op(RandomNumberGenerator& /*rng*/, + #endif + + if(provider == "base" || provider.empty()) +- return std::unique_ptr(new ECDSA_Signature_Operation(*this, params)); ++ return std::unique_ptr(new ECDSA_Signature_Operation(*this, params, rng)); + + throw Provider_Not_Found(algo_name(), provider); + } diff --git a/srcpkgs/botan/template b/srcpkgs/botan/template index c729637c64e..c3126cd418c 100644 --- a/srcpkgs/botan/template +++ b/srcpkgs/botan/template @@ -1,7 +1,7 @@ # Template file for 'botan' pkgname=botan version=2.6.0 -revision=2 +revision=3 wrksrc="${pkgname^}-${version}" build_style=gnu-makefile hostmakedepends="doxygen epstopdf python"