diff options
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/math/bigint/bigint.cpp | 2 | ||||
-rw-r--r-- | src/lib/math/ec_gfp/point_gfp.cpp | 241 | ||||
-rw-r--r-- | src/lib/math/ec_gfp/point_gfp.h | 148 | ||||
-rw-r--r-- | src/lib/math/ec_gfp/point_mul.cpp | 113 | ||||
-rw-r--r-- | src/lib/pubkey/ec_group/ec_group.cpp | 45 | ||||
-rw-r--r-- | src/lib/pubkey/ec_group/ec_group.h | 19 | ||||
-rw-r--r-- | src/lib/pubkey/ecdh/ecdh.cpp | 24 | ||||
-rw-r--r-- | src/lib/pubkey/ecdsa/ecdsa.cpp | 6 | ||||
-rw-r--r-- | src/lib/pubkey/ecgdsa/ecgdsa.cpp | 5 | ||||
-rw-r--r-- | src/lib/pubkey/ecies/ecies.cpp | 18 | ||||
-rw-r--r-- | src/lib/pubkey/eckcdsa/eckcdsa.cpp | 5 | ||||
-rw-r--r-- | src/lib/pubkey/gost_3410/gost_3410.cpp | 5 | ||||
-rw-r--r-- | src/lib/pubkey/sm2/sm2.cpp | 5 | ||||
-rw-r--r-- | src/lib/pubkey/sm2/sm2_enc.cpp | 29 |
14 files changed, 399 insertions, 266 deletions
diff --git a/src/lib/math/bigint/bigint.cpp b/src/lib/math/bigint/bigint.cpp index caa78de45..b63bd9be8 100644 --- a/src/lib/math/bigint/bigint.cpp +++ b/src/lib/math/bigint/bigint.cpp @@ -119,7 +119,7 @@ int32_t BigInt::cmp(const BigInt& other, bool check_signs) const uint32_t BigInt::get_substring(size_t offset, size_t length) const { if(length > 32) - throw Invalid_Argument("BigInt::get_substring: Substring size too big"); + throw Invalid_Argument("BigInt::get_substring: Substring size " + std::to_string(length) + " too big"); uint64_t piece = 0; for(size_t i = 0; i != 8; ++i) diff --git a/src/lib/math/ec_gfp/point_gfp.cpp b/src/lib/math/ec_gfp/point_gfp.cpp index f00f030d7..d9599e650 100644 --- a/src/lib/math/ec_gfp/point_gfp.cpp +++ b/src/lib/math/ec_gfp/point_gfp.cpp @@ -13,16 +13,16 @@ namespace Botan { - PointGFp::PointGFp(const CurveGFp& curve) : m_curve(curve), m_coord_x(0), m_coord_y(1), m_coord_z(0) { - m_curve.to_rep(m_coord_x, m_monty_ws); - m_curve.to_rep(m_coord_y, m_monty_ws); - m_curve.to_rep(m_coord_z, m_monty_ws); + secure_vector<word> monty_ws; + m_curve.to_rep(m_coord_x, monty_ws); + m_curve.to_rep(m_coord_y, monty_ws); + m_curve.to_rep(m_coord_z, monty_ws); } PointGFp::PointGFp(const CurveGFp& curve, const BigInt& x, const BigInt& y) : @@ -36,9 +36,10 @@ PointGFp::PointGFp(const CurveGFp& curve, const BigInt& x, const BigInt& y) : if(y <= 0 || y >= curve.get_p()) throw Invalid_Argument("Invalid PointGFp affine y"); - m_curve.to_rep(m_coord_x, m_monty_ws); - m_curve.to_rep(m_coord_y, m_monty_ws); - m_curve.to_rep(m_coord_z, m_monty_ws); + secure_vector<word> monty_ws; + m_curve.to_rep(m_coord_x, monty_ws); + m_curve.to_rep(m_coord_y, monty_ws); + m_curve.to_rep(m_coord_z, monty_ws); } void PointGFp::randomize_repr(RandomNumberGenerator& rng) @@ -49,13 +50,15 @@ void PointGFp::randomize_repr(RandomNumberGenerator& rng) while(mask.is_zero()) mask.randomize(rng, BOTAN_POINTGFP_RANDOMIZE_BLINDING_BITS, false); - m_curve.to_rep(mask, m_monty_ws); - const BigInt mask2 = curve_mult(mask, mask); - const BigInt mask3 = curve_mult(mask2, mask); + secure_vector<word> monty_ws; + + m_curve.to_rep(mask, monty_ws); + const BigInt mask2 = m_curve.mul(mask, mask, monty_ws); + const BigInt mask3 = m_curve.mul(mask2, mask, monty_ws); - m_coord_x = curve_mult(m_coord_x, mask2); - m_coord_y = curve_mult(m_coord_y, mask3); - m_coord_z = curve_mult(m_coord_z, mask); + m_coord_x = m_curve.mul(m_coord_x, mask2, monty_ws); + m_coord_y = m_curve.mul(m_coord_y, mask3, monty_ws); + m_coord_z = m_curve.mul(m_coord_z, mask, monty_ws); } } @@ -85,17 +88,23 @@ void PointGFp::add(const PointGFp& rhs, std::vector<BigInt>& ws_bn) BigInt& H = ws_bn[6]; BigInt& r = ws_bn[7]; + secure_vector<word>& monty_ws = ws_bn[8].get_word_vector(); + /* https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-1998-cmo-2 */ - curve_sqr(rhs_z2, rhs.m_coord_z); - curve_mult(U1, m_coord_x, rhs_z2); - curve_mult(S1, m_coord_y, curve_mult(rhs.m_coord_z, rhs_z2)); + m_curve.sqr(rhs_z2, rhs.m_coord_z, monty_ws); + m_curve.mul(U1, m_coord_x, rhs_z2, monty_ws); + m_curve.mul(S1, m_coord_y, + m_curve.mul(rhs.m_coord_z, rhs_z2, monty_ws), + monty_ws); - curve_sqr(lhs_z2, m_coord_z); - curve_mult(U2, rhs.m_coord_x, lhs_z2); - curve_mult(S2, rhs.m_coord_y, curve_mult(m_coord_z, lhs_z2)); + m_curve.sqr(lhs_z2, m_coord_z, monty_ws); + m_curve.mul(U2, rhs.m_coord_x, lhs_z2, monty_ws); + m_curve.mul(S2, rhs.m_coord_y, + m_curve.mul(m_coord_z, lhs_z2, monty_ws), + monty_ws); H = U2; H -= U1; @@ -122,13 +131,13 @@ void PointGFp::add(const PointGFp& rhs, std::vector<BigInt>& ws_bn) return; } - curve_sqr(U2, H); + m_curve.sqr(U2, H, monty_ws); - curve_mult(S2, U2, H); + m_curve.mul(S2, U2, H, monty_ws); - U2 = curve_mult(U1, U2); + U2 = m_curve.mul(U1, U2, monty_ws); - curve_sqr(m_coord_x, r); + m_curve.sqr(m_coord_x, r, monty_ws); m_coord_x -= S2; m_coord_x -= (U2 << 1); while(m_coord_x.is_negative()) @@ -138,12 +147,14 @@ void PointGFp::add(const PointGFp& rhs, std::vector<BigInt>& ws_bn) if(U2.is_negative()) U2 += p; - curve_mult(m_coord_y, r, U2); - m_coord_y -= curve_mult(S1, S2); + m_curve.mul(m_coord_y, r, U2, monty_ws); + m_coord_y -= m_curve.mul(S1, S2, monty_ws); if(m_coord_y.is_negative()) m_coord_y += p; - curve_mult(m_coord_z, curve_mult(m_coord_z, rhs.m_coord_z), H); + m_curve.mul(m_coord_z, + m_curve.mul(m_coord_z, rhs.m_coord_z, monty_ws), + H, monty_ws); } // *this *= 2 @@ -151,7 +162,8 @@ void PointGFp::mult2(std::vector<BigInt>& ws_bn) { if(is_zero()) return; - else if(m_coord_y.is_zero()) + + if(m_coord_y.is_zero()) { *this = PointGFp(m_curve); // setting myself to zero return; @@ -173,28 +185,30 @@ void PointGFp::mult2(std::vector<BigInt>& ws_bn) BigInt& y = ws_bn[7]; BigInt& z = ws_bn[8]; - curve_sqr(y_2, m_coord_y); + secure_vector<word>& monty_ws = ws_bn[9].get_word_vector(); + + m_curve.sqr(y_2, m_coord_y, monty_ws); - curve_mult(S, m_coord_x, y_2); + m_curve.mul(S, m_coord_x, y_2, monty_ws); S <<= 2; // * 4 while(S >= p) S -= p; - curve_sqr(z4, curve_sqr(m_coord_z)); - curve_mult(a_z4, m_curve.get_a_rep(), z4); + m_curve.sqr(z4, m_curve.sqr(m_coord_z, monty_ws), monty_ws); + m_curve.mul(a_z4, m_curve.get_a_rep(), z4, monty_ws); - M = curve_sqr(m_coord_x); + M = m_curve.sqr(m_coord_x, monty_ws); M *= 3; M += a_z4; while(M >= p) M -= p; - curve_sqr(x, M); + m_curve.sqr(x, M, monty_ws); x -= (S << 1); while(x.is_negative()) x += p; - curve_sqr(U, y_2); + m_curve.sqr(U, y_2, monty_ws); U <<= 3; while(U >= p) U -= p; @@ -203,12 +217,12 @@ void PointGFp::mult2(std::vector<BigInt>& ws_bn) while(S.is_negative()) S += p; - curve_mult(y, M, S); + m_curve.mul(y, M, S, monty_ws); y -= U; if(y.is_negative()) y += p; - curve_mult(z, m_coord_y, m_coord_z); + m_curve.mul(z, m_coord_y, m_coord_z, monty_ws); z <<= 1; if(z >= p) z -= p; @@ -221,7 +235,7 @@ void PointGFp::mult2(std::vector<BigInt>& ws_bn) // arithmetic operators PointGFp& PointGFp::operator+=(const PointGFp& rhs) { - std::vector<BigInt> ws(9); + std::vector<BigInt> ws(PointGFp::WORKSPACE_SIZE); add(rhs, ws); return *this; } @@ -247,28 +261,28 @@ PointGFp& PointGFp::operator*=(const BigInt& scalar) PointGFp multi_exponentiate(const PointGFp& p1, const BigInt& z1, const PointGFp& p2, const BigInt& z2) { - const PointGFp p3 = p1 + p2; + PointGFp H = p1.zero(); + const size_t z_bits = std::max(z1.bits(), z2.bits()); - PointGFp H(p1.get_curve()); // create as zero - size_t bits_left = std::max(z1.bits(), z2.bits()); + std::vector<BigInt> ws(PointGFp::WORKSPACE_SIZE); - std::vector<BigInt> ws(9); + PointGFp M[4] = { + p1.zero(), + p1, + p2, + p1 + p2, + }; - while(bits_left) + for(size_t i = 0; i != z_bits; ++i) { H.mult2(ws); - const bool z1_b = z1.get_bit(bits_left - 1); - const bool z2_b = z2.get_bit(bits_left - 1); + const uint8_t z1_b = z1.get_bit(z_bits - i - 1); + const uint8_t z2_b = z2.get_bit(z_bits - i - 1); - if(z1_b == true && z2_b == true) - H.add(p3, ws); - else if(z1_b) - H.add(p1, ws); - else if(z2_b) - H.add(p2, ws); + const uint8_t z12 = (2*z2_b) + z1_b; - --bits_left; + H.add(M[z12], ws); } if(z1.is_negative() != z2.is_negative()) @@ -281,13 +295,11 @@ PointGFp operator*(const BigInt& scalar, const PointGFp& point) { //BOTAN_ASSERT(point.on_the_curve(), "Input is on the curve"); - const CurveGFp& curve = point.get_curve(); - const size_t scalar_bits = scalar.bits(); - std::vector<BigInt> ws(9); + std::vector<BigInt> ws(PointGFp::WORKSPACE_SIZE); - PointGFp R[2] = { PointGFp(curve), point }; + PointGFp R[2] = { point.zero(), point }; for(size_t i = scalar_bits; i > 0; i--) { @@ -304,98 +316,17 @@ PointGFp operator*(const BigInt& scalar, const PointGFp& point) return R[0]; } -Blinded_Point_Multiply::Blinded_Point_Multiply(const PointGFp& base, const BigInt& order, size_t h) : - m_h(h > 0 ? h : 4), m_order(order), m_ws(9) - { - // Upper bound is a sanity check rather than hard limit - if(m_h < 1 || m_h > 8) - throw Invalid_Argument("Blinded_Point_Multiply invalid h param"); - - const CurveGFp& curve = base.get_curve(); - - const PointGFp inv = -base; - - m_U.resize(6*m_h + 3); - - m_U[3*m_h+0] = inv; - m_U[3*m_h+1] = PointGFp::zero_of(curve); - m_U[3*m_h+2] = base; - - for(size_t i = 1; i <= 3 * m_h + 1; ++i) - { - m_U[3*m_h+1+i] = m_U[3*m_h+i]; - m_U[3*m_h+1+i].add(base, m_ws); - - m_U[3*m_h+1-i] = m_U[3*m_h+2-i]; - m_U[3*m_h+1-i].add(inv, m_ws); - } - } - -PointGFp Blinded_Point_Multiply::blinded_multiply(const BigInt& scalar_in, - RandomNumberGenerator& rng) - { - if(scalar_in.is_negative()) - throw Invalid_Argument("Blinded_Point_Multiply scalar must be positive"); - -#if BOTAN_POINTGFP_USE_SCALAR_BLINDING - // Choose a small mask m and use k' = k + m*order (Coron's 1st countermeasure) - const BigInt mask(rng, (m_order.bits()+1)/2, false); - const BigInt scalar = scalar_in + m_order * mask; -#else - const BigInt& scalar = scalar_in; -#endif - - const size_t scalar_bits = scalar.bits(); - - // Randomize each point representation (Coron's 3rd countermeasure) - for(size_t i = 0; i != m_U.size(); ++i) - m_U[i].randomize_repr(rng); - - PointGFp R = m_U.at(3*m_h + 2); // base point - int32_t alpha = 0; - - R.randomize_repr(rng); - - /* - Algorithm 7 from "Randomizing the Montgomery Powering Ladder" - Duc-Phong Le, Chik How Tan and Michael Tunstall - https://eprint.iacr.org/2015/657 - - It takes a random walk through (a subset of) the set of addition - chains that end in k. - */ - for(size_t i = scalar_bits; i > 0; i--) - { - const int32_t ki = scalar.get_bit(i); - - // choose gamma from -h,...,h - const int32_t gamma = static_cast<int32_t>((rng.next_byte() % (2*m_h))) - m_h; - const int32_t l = gamma - 2*alpha + ki - (ki ^ 1); - - R.mult2(m_ws); - R.add(m_U.at(3*m_h + 1 + l), m_ws); - alpha = gamma; - } - - const int32_t k0 = scalar.get_bit(0); - R.add(m_U[3*m_h + 1 - alpha - (k0 ^ 1)], m_ws); - - - //BOTAN_ASSERT(R.on_the_curve(), "Output is on the curve"); - - return R; - } - BigInt PointGFp::get_affine_x() const { if(is_zero()) throw Illegal_Transformation("Cannot convert zero point to affine"); - BigInt z2 = curve_sqr(m_coord_z); - m_curve.from_rep(z2, m_monty_ws); + secure_vector<word> monty_ws; + BigInt z2 = m_curve.sqr(m_coord_z, monty_ws); + m_curve.from_rep(z2, monty_ws); z2 = inverse_mod(z2, m_curve.get_p()); - return curve_mult(z2, m_coord_x); + return m_curve.mul(z2, m_coord_x, monty_ws); } BigInt PointGFp::get_affine_y() const @@ -403,11 +334,12 @@ BigInt PointGFp::get_affine_y() const if(is_zero()) throw Illegal_Transformation("Cannot convert zero point to affine"); - BigInt z3 = curve_mult(m_coord_z, curve_sqr(m_coord_z)); + secure_vector<word> monty_ws; + BigInt z3 = m_curve.mul(m_coord_z, m_curve.sqr(m_coord_z, monty_ws), monty_ws); z3 = inverse_mod(z3, m_curve.get_p()); - m_curve.to_rep(z3, m_monty_ws); + m_curve.to_rep(z3, monty_ws); - return curve_mult(z3, m_coord_y); + return m_curve.mul(z3, m_coord_y, monty_ws); } bool PointGFp::on_the_curve() const @@ -421,22 +353,24 @@ bool PointGFp::on_the_curve() const if(is_zero()) return true; - const BigInt y2 = m_curve.from_rep(curve_sqr(m_coord_y), m_monty_ws); - const BigInt x3 = curve_mult(m_coord_x, curve_sqr(m_coord_x)); - const BigInt ax = curve_mult(m_coord_x, m_curve.get_a_rep()); - const BigInt z2 = curve_sqr(m_coord_z); + secure_vector<word> monty_ws; + + const BigInt y2 = m_curve.from_rep(m_curve.sqr(m_coord_y, monty_ws), monty_ws); + const BigInt x3 = m_curve.mul(m_coord_x, m_curve.sqr(m_coord_x, monty_ws), monty_ws); + const BigInt ax = m_curve.mul(m_coord_x, m_curve.get_a_rep(), monty_ws); + const BigInt z2 = m_curve.sqr(m_coord_z, monty_ws); if(m_coord_z == z2) // Is z equal to 1 (in Montgomery form)? { - if(y2 != m_curve.from_rep(x3 + ax + m_curve.get_b_rep(), m_monty_ws)) + if(y2 != m_curve.from_rep(x3 + ax + m_curve.get_b_rep(), monty_ws)) return false; } - const BigInt z3 = curve_mult(m_coord_z, z2); - const BigInt ax_z4 = curve_mult(ax, curve_sqr(z2)); - const BigInt b_z6 = curve_mult(m_curve.get_b_rep(), curve_sqr(z3)); + const BigInt z3 = m_curve.mul(m_coord_z, z2, monty_ws); + const BigInt ax_z4 = m_curve.mul(ax, m_curve.sqr(z2, monty_ws), monty_ws); + const BigInt b_z6 = m_curve.mul(m_curve.get_b_rep(), m_curve.sqr(z3, monty_ws), monty_ws); - if(y2 != m_curve.from_rep(x3 + ax_z4 + b_z6, m_monty_ws)) + if(y2 != m_curve.from_rep(x3 + ax_z4 + b_z6, monty_ws)) return false; return true; @@ -449,12 +383,11 @@ void PointGFp::swap(PointGFp& other) m_coord_x.swap(other.m_coord_x); m_coord_y.swap(other.m_coord_y); m_coord_z.swap(other.m_coord_z); - m_monty_ws.swap(other.m_monty_ws); } bool PointGFp::operator==(const PointGFp& other) const { - if(get_curve() != other.get_curve()) + if(m_curve != other.m_curve) return false; // If this is zero, only equal if other is also zero diff --git a/src/lib/math/ec_gfp/point_gfp.h b/src/lib/math/ec_gfp/point_gfp.h index 2e1c626bd..a2c7ae86a 100644 --- a/src/lib/math/ec_gfp/point_gfp.h +++ b/src/lib/math/ec_gfp/point_gfp.h @@ -49,6 +49,8 @@ class BOTAN_PUBLIC_API(2,0) PointGFp final HYBRID = 2 }; + enum { WORKSPACE_SIZE = 10 }; + /** * Construct an uninitialized PointGFp */ @@ -60,11 +62,6 @@ class BOTAN_PUBLIC_API(2,0) PointGFp final */ explicit PointGFp(const CurveGFp& curve); - static PointGFp zero_of(const CurveGFp& curve) - { - return PointGFp(curve); - } - /** * Copy constructor */ @@ -120,30 +117,9 @@ class BOTAN_PUBLIC_API(2,0) PointGFp final * @param scalar the PointGFp to multiply with *this * @result resulting PointGFp */ - PointGFp& operator*=(const BigInt& scalar); /** - * Multiplication Operator - * @param scalar the scalar value - * @param point the point value - * @return scalar*point on the curve - */ - friend BOTAN_PUBLIC_API(2,0) PointGFp operator*(const BigInt& scalar, const PointGFp& point); - - /** - * Multiexponentiation - * @param p1 a point - * @param z1 a scalar - * @param p2 a point - * @param z2 a scalar - * @result (p1 * z1 + p2 * z2) - */ - friend BOTAN_PUBLIC_API(2,0) PointGFp multi_exponentiate( - const PointGFp& p1, const BigInt& z1, - const PointGFp& p2, const BigInt& z2); - - /** * Negate this point * @return *this */ @@ -202,50 +178,49 @@ class BOTAN_PUBLIC_API(2,0) PointGFp final * Equality operator */ bool operator==(const PointGFp& other) const; - private: - friend class Blinded_Point_Multiply; - - BigInt curve_mult(const BigInt& x, const BigInt& y) const - { - BigInt z; - m_curve.mul(z, x, y, m_monty_ws); - return z; - } - - void curve_mult(BigInt& z, const BigInt& x, const BigInt& y) const - { - m_curve.mul(z, x, y, m_monty_ws); - } - - BigInt curve_sqr(const BigInt& x) const - { - BigInt z; - m_curve.sqr(z, x, m_monty_ws); - return z; - } - - void curve_sqr(BigInt& z, const BigInt& x) const - { - m_curve.sqr(z, x, m_monty_ws); - } /** * Point addition - * @param workspace temp space, at least 11 elements + * @param workspace temp space, at least 9 elements */ void add(const PointGFp& other, std::vector<BigInt>& workspace); /** * Point doubling - * @param workspace temp space, at least 9 elements + * @param workspace temp space, at least 10 elements */ void mult2(std::vector<BigInt>& workspace); + /** + * Return the zero (aka infinite) point associated with this curve + */ + PointGFp zero() const { return PointGFp(m_curve); } + + private: CurveGFp m_curve; BigInt m_coord_x, m_coord_y, m_coord_z; - mutable secure_vector<word> m_monty_ws; // workspace for Montgomery }; +/** +* Point multiplication operator +* @param scalar the scalar value +* @param point the point value +* @return scalar*point on the curve +*/ +BOTAN_PUBLIC_API(2,0) PointGFp operator*(const BigInt& scalar, const PointGFp& point); + +/** +* ECC point multiexponentiation +* @param p1 a point +* @param z1 a scalar +* @param p2 a point +* @param z2 a scalar +* @result (p1 * z1 + p2 * z2) +*/ +BOTAN_PUBLIC_API(2,0) PointGFp multi_exponentiate( + const PointGFp& p1, const BigInt& z1, + const PointGFp& p2, const BigInt& z2); + // relational operators inline bool operator!=(const PointGFp& lhs, const PointGFp& rhs) { @@ -299,19 +274,68 @@ PointGFp OS2ECP(const std::vector<uint8_t, Alloc>& data, const CurveGFp& curve) { return OS2ECP(data.data(), data.size(), curve); } /** - +* Blinded ECC point multiplication */ -class BOTAN_PUBLIC_API(2,0) Blinded_Point_Multiply final +class BOTAN_PUBLIC_API(2,5) PointGFp_Blinded_Multiplier final + { + public: + /** + * @param base_point the point that will be multiplied (eg, the base point of the curve) + * @param w the window bits (leave as zero to take a default value) + */ + PointGFp_Blinded_Multiplier(const PointGFp& base_point, + size_t w = 0); + + /** + * @param base_point the point that will be multiplied (eg, the base point of the curve) + * @param ws a temporary workspace + * @param w the window bits (leave as zero to take a default value) + */ + PointGFp_Blinded_Multiplier(const PointGFp& base_point, + std::vector<BigInt>& ws, + size_t w = 0); + + /** + * Randomize the internal state. Changing the values may provide + * some protection against side channel attacks. + * @param rng a random number generator + */ + void randomize(RandomNumberGenerator& rng); + + /** + * Perform blinded point multiplication + * @param k the scalar + * @param group_order the order of the group + * @param rng a random number generator + * @param ws a temporary workspace + * @return base_point*k + */ + PointGFp mul(const BigInt& k, + const BigInt& group_order, + RandomNumberGenerator& rng, + std::vector<BigInt>& ws) const; + private: + void init(const PointGFp& base_point, size_t w, std::vector<BigInt>& ws); + + std::vector<PointGFp> m_U; + size_t m_h; + }; + +class BOTAN_PUBLIC_API(2,0) BOTAN_DEPRECATED("Use PointGFp_Blinded_Multiplier") Blinded_Point_Multiply final { public: - Blinded_Point_Multiply(const PointGFp& base, const BigInt& order, size_t h = 0); + Blinded_Point_Multiply(const PointGFp& base, const BigInt& order, size_t h = 0) : + m_ws(PointGFp::WORKSPACE_SIZE), m_order(order), m_point_mul(base, m_ws, h) {} - PointGFp blinded_multiply(const BigInt& scalar, RandomNumberGenerator& rng); + PointGFp blinded_multiply(const BigInt& scalar, RandomNumberGenerator& rng) + { + m_point_mul.randomize(rng); + return m_point_mul.mul(scalar, m_order, rng, m_ws); + } private: - const size_t m_h; - const BigInt& m_order; std::vector<BigInt> m_ws; - std::vector<PointGFp> m_U; + const BigInt& m_order; + PointGFp_Blinded_Multiplier m_point_mul; }; } diff --git a/src/lib/math/ec_gfp/point_mul.cpp b/src/lib/math/ec_gfp/point_mul.cpp new file mode 100644 index 000000000..7fea02280 --- /dev/null +++ b/src/lib/math/ec_gfp/point_mul.cpp @@ -0,0 +1,113 @@ +/* +* (C) 2015,2018 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include <botan/point_gfp.h> +#include <botan/rng.h> +#include <botan/internal/rounding.h> + +namespace Botan { + +PointGFp_Blinded_Multiplier::PointGFp_Blinded_Multiplier(const PointGFp& base, + std::vector<BigInt>& ws, + size_t w) + { + init(base, w, ws); + } + +PointGFp_Blinded_Multiplier::PointGFp_Blinded_Multiplier(const PointGFp& base, + size_t w) + { + std::vector<BigInt> ws(9); + init(base, w, ws); + } + +void PointGFp_Blinded_Multiplier::init(const PointGFp& base, + size_t w, + std::vector<BigInt>& ws) + { + m_h = (w == 0 ? 5 : w); + + if(ws.size() < PointGFp::WORKSPACE_SIZE) + ws.resize(PointGFp::WORKSPACE_SIZE); + + // Upper bound is a sanity check rather than hard limit + if(m_h < 1 || m_h > 8) + throw Invalid_Argument("PointGFp_Blinded_Multiplier invalid w param"); + + m_U.resize(1 << m_h); + m_U[0] = base.zero(); + m_U[1] = base; + + for(size_t i = 2; i < m_U.size(); ++i) + { + m_U[i] = m_U[i-1]; + m_U[i].add(base, ws); + } + } + +void PointGFp_Blinded_Multiplier::randomize(RandomNumberGenerator& rng) + { + // Randomize each point representation (Coron's 3rd countermeasure) + for(size_t i = 0; i != m_U.size(); ++i) + m_U[i].randomize_repr(rng); + } + +PointGFp PointGFp_Blinded_Multiplier::mul(const BigInt& k, + const BigInt& group_order, + RandomNumberGenerator& rng, + std::vector<BigInt>& ws) const + { + if(k.is_negative()) + throw Invalid_Argument("PointGFp_Blinded_Multiplier scalar must be positive"); + +#if BOTAN_POINTGFP_USE_SCALAR_BLINDING + // Choose a small mask m and use k' = k + m*order (Coron's 1st countermeasure) + const BigInt mask(rng, group_order.bits() / 4, false); + const BigInt scalar = k + group_order * mask; +#else + const BigInt& scalar = k; +#endif + + if(ws.size() < PointGFp::WORKSPACE_SIZE) + ws.resize(PointGFp::WORKSPACE_SIZE); + + const size_t scalar_bits = scalar.bits(); + + size_t windows = round_up(scalar_bits, m_h) / m_h; + + PointGFp R = m_U[0]; + + if(windows > 0) + { + windows--; + const uint32_t nibble = scalar.get_substring(windows*m_h, m_h); + R.add(m_U[nibble], ws); + + /* + Randomize after adding the first nibble as before the addition R + is zero, and we cannot effectively randomize the point + representation of the zero point. + */ + R.randomize_repr(rng); + + while(windows) + { + for(size_t i = 0; i != m_h; ++i) + R.mult2(ws); + + const uint32_t inner_nibble = scalar.get_substring((windows-1)*m_h, m_h); + // cache side channel here, we are relying on blinding... + R.add(m_U[inner_nibble], ws); + windows--; + } + } + + //BOTAN_ASSERT(R.on_the_curve(), "Output is on the curve"); + + return R; + } + +} diff --git a/src/lib/pubkey/ec_group/ec_group.cpp b/src/lib/pubkey/ec_group/ec_group.cpp index 771bd4b0f..102eed6e5 100644 --- a/src/lib/pubkey/ec_group/ec_group.cpp +++ b/src/lib/pubkey/ec_group/ec_group.cpp @@ -17,6 +17,10 @@ #include <botan/mutex.h> #include <vector> +#if defined(BOTAN_HAS_SYSTEM_RNG) + #include <botan/system_rng.h> +#endif + namespace Botan { class EC_Group_Data final @@ -36,19 +40,28 @@ class EC_Group_Data final m_order(order), m_cofactor(cofactor), m_mod_order(order), + m_base_mult(m_base_point, 5), m_oid(oid), m_p_bits(p.bits()), - m_order_bits(order.bits()) + m_order_bits(order.bits()), + m_a_is_minus_3(a == p - 3) { +#if defined(BOTAN_HAS_SYSTEM_RNG) + m_base_mult.randomize(system_rng()); +#endif } bool match(const BigInt& p, const BigInt& a, const BigInt& b, const BigInt& g_x, const BigInt& g_y, const BigInt& order, const BigInt& cofactor) const { - return (this->p() == p && this->a() == a && this->b() == b && - this->order() == order && this->cofactor() == cofactor && - this->g_x() == g_x && this->g_y() == g_y); + return (this->p() == p && + this->a() == a && + this->b() == b && + this->order() == order && + this->cofactor() == cofactor && + this->g_x() == g_x && + this->g_y() == g_y); } const OID& oid() const { return m_oid; } @@ -69,6 +82,8 @@ class EC_Group_Data final const CurveGFp& curve() const { return m_curve; } const PointGFp& base_point() const { return m_base_point; } + bool a_is_minus_3() const { return m_a_is_minus_3; } + BigInt mod_order(const BigInt& x) const { return m_mod_order.reduce(x); } BigInt multiply_mod_order(const BigInt& x, const BigInt& y) const @@ -76,15 +91,24 @@ class EC_Group_Data final return m_mod_order.multiply(x, y); } + PointGFp blinded_base_point_multiply(const BigInt& k, + RandomNumberGenerator& rng, + std::vector<BigInt>& ws) const + { + return m_base_mult.mul(k, m_order, rng, ws); + } + private: CurveGFp m_curve; PointGFp m_base_point; BigInt m_order; BigInt m_cofactor; Modular_Reducer m_mod_order; + PointGFp_Blinded_Multiplier m_base_mult; OID m_oid; size_t m_p_bits; size_t m_order_bits; + bool m_a_is_minus_3; }; class EC_Group_Data_Map final @@ -349,6 +373,11 @@ const CurveGFp& EC_Group::get_curve() const return data().curve(); } +bool EC_Group::a_is_minus_3() const + { + return data().a_is_minus_3(); + } + size_t EC_Group::get_p_bits() const { return data().p_bits(); @@ -421,6 +450,7 @@ PointGFp EC_Group::OS2ECP(const uint8_t bits[], size_t len) const PointGFp EC_Group::point(const BigInt& x, const BigInt& y) const { + // TODO: randomize the representation? return PointGFp(data().curve(), x, y); } @@ -429,6 +459,13 @@ PointGFp EC_Group::point_multiply(const BigInt& x, const PointGFp& pt, const Big return multi_exponentiate(get_base_point(), x, pt, y); } +PointGFp EC_Group::blinded_base_point_multiply(const BigInt& k, + RandomNumberGenerator& rng, + std::vector<BigInt>& ws) const + { + return data().blinded_base_point_multiply(k, rng, ws); + } + PointGFp EC_Group::zero_point() const { return PointGFp(data().curve()); diff --git a/src/lib/pubkey/ec_group/ec_group.h b/src/lib/pubkey/ec_group/ec_group.h index a60c71157..2baa2555e 100644 --- a/src/lib/pubkey/ec_group/ec_group.h +++ b/src/lib/pubkey/ec_group/ec_group.h @@ -11,7 +11,6 @@ #define BOTAN_ECC_DOMAIN_PARAMETERS_H_ #include <botan/point_gfp.h> -#include <botan/curve_gfp.h> #include <botan/asn1_oid.h> #include <memory> #include <set> @@ -27,6 +26,8 @@ enum EC_Group_Encoding { EC_DOMPAR_ENC_OID = 2 }; +class CurveGFp; + class EC_Group_Data; class EC_Group_Data_Map; @@ -126,6 +127,11 @@ class BOTAN_PUBLIC_API(2,0) EC_Group final BOTAN_DEPRECATED("Avoid CurveGFp") const CurveGFp& get_curve() const; /** + * Return if a == -3 mod p + */ + bool a_is_minus_3() const; + + /** * Return the size of p in bits (same as get_p().bits()) */ size_t get_p_bits() const; @@ -206,12 +212,21 @@ class BOTAN_PUBLIC_API(2,0) EC_Group final PointGFp point(const BigInt& x, const BigInt& y) const; /** - * Multi exponentiate + * Multi exponentiate. Not constant time. * @return base_point*x + pt*y */ PointGFp point_multiply(const BigInt& x, const PointGFp& pt, const BigInt& y) const; /** + * Blinded point multiplication, attempts resistance to side channels + * @param k the scalar + * @param rng a random number generator + * @param ws a temp workspace + * @return base_point*k + */ + PointGFp blinded_base_point_multiply(const BigInt& k, RandomNumberGenerator& rng, std::vector<BigInt>& ws) const; + + /** * Return the zero (or infinite) point on this curve */ PointGFp zero_point() const; diff --git a/src/lib/pubkey/ecdh/ecdh.cpp b/src/lib/pubkey/ecdh/ecdh.cpp index 1850696e1..4989fa0a5 100644 --- a/src/lib/pubkey/ecdh/ecdh.cpp +++ b/src/lib/pubkey/ecdh/ecdh.cpp @@ -28,26 +28,30 @@ class ECDH_KA_Operation final : public PK_Ops::Key_Agreement_with_KDF ECDH_KA_Operation(const ECDH_PrivateKey& key, const std::string& kdf, RandomNumberGenerator& rng) : PK_Ops::Key_Agreement_with_KDF(kdf), - m_domain(key.domain()), + m_group(key.domain()), m_rng(rng) { - m_l_times_priv = inverse_mod(m_domain.get_cofactor(), m_domain.get_order()) * key.private_value(); + m_l_times_priv = inverse_mod(m_group.get_cofactor(), m_group.get_order()) * key.private_value(); } secure_vector<uint8_t> raw_agree(const uint8_t w[], size_t w_len) override { - PointGFp point = m_domain.OS2ECP(w, w_len); - PointGFp S = m_domain.get_cofactor() * point; - Blinded_Point_Multiply blinder(S, m_domain.get_order()); - S = blinder.blinded_multiply(m_l_times_priv, m_rng); - BOTAN_ASSERT(S.on_the_curve(), "ECDH agreed value was on the curve"); - return BigInt::encode_1363(S.get_affine_x(), m_domain.get_p_bytes()); + PointGFp input_point = m_group.get_cofactor() * m_group.OS2ECP(w, w_len); + input_point.randomize_repr(m_rng); + + PointGFp_Blinded_Multiplier blinder(input_point, m_ws); + + const PointGFp S = blinder.mul(m_l_times_priv, m_group.get_order(), m_rng, m_ws); + + if(S.on_the_curve() == false) + throw Internal_Error("ECDH agreed value was not on the curve"); + return BigInt::encode_1363(S.get_affine_x(), m_group.get_p_bytes()); } private: - const EC_Group& m_domain; + const EC_Group m_group; BigInt m_l_times_priv; RandomNumberGenerator& m_rng; - + std::vector<BigInt> m_ws; }; } diff --git a/src/lib/pubkey/ecdsa/ecdsa.cpp b/src/lib/pubkey/ecdsa/ecdsa.cpp index 12ccd9608..57bc197c5 100644 --- a/src/lib/pubkey/ecdsa/ecdsa.cpp +++ b/src/lib/pubkey/ecdsa/ecdsa.cpp @@ -53,7 +53,6 @@ class ECDSA_Signature_Operation final : public PK_Ops::Signature_with_EMSA const std::string& emsa) : PK_Ops::Signature_with_EMSA(emsa), m_group(ecdsa.domain()), - m_base_point(m_group.get_base_point(), m_group.get_order()), m_x(ecdsa.private_value()) { #if defined(BOTAN_HAS_RFC6979_GENERATOR) @@ -68,12 +67,13 @@ class ECDSA_Signature_Operation final : public PK_Ops::Signature_with_EMSA private: const EC_Group m_group; - Blinded_Point_Multiply m_base_point; const BigInt& m_x; #if defined(BOTAN_HAS_RFC6979_GENERATOR) std::string m_rfc6979_hash; #endif + + std::vector<BigInt> m_ws; }; secure_vector<uint8_t> @@ -89,7 +89,7 @@ ECDSA_Signature_Operation::raw_sign(const uint8_t msg[], size_t msg_len, #endif const BigInt k_inv = inverse_mod(k, m_group.get_order()); - const PointGFp k_times_P = m_base_point.blinded_multiply(k, rng); + const PointGFp k_times_P = m_group.blinded_base_point_multiply(k, rng, m_ws); const BigInt r = m_group.mod_order(k_times_P.get_affine_x()); const BigInt s = m_group.multiply_mod_order(k_inv, mul_add(m_x, r, m)); diff --git a/src/lib/pubkey/ecgdsa/ecgdsa.cpp b/src/lib/pubkey/ecgdsa/ecgdsa.cpp index f8e5744d9..6cbd3453b 100644 --- a/src/lib/pubkey/ecgdsa/ecgdsa.cpp +++ b/src/lib/pubkey/ecgdsa/ecgdsa.cpp @@ -38,7 +38,6 @@ class ECGDSA_Signature_Operation final : public PK_Ops::Signature_with_EMSA const std::string& emsa) : PK_Ops::Signature_with_EMSA(emsa), m_group(ecgdsa.domain()), - m_base_point(m_group.get_base_point(), m_group.get_order()), m_x(ecgdsa.private_value()) { } @@ -50,8 +49,8 @@ class ECGDSA_Signature_Operation final : public PK_Ops::Signature_with_EMSA private: const EC_Group m_group; - Blinded_Point_Multiply m_base_point; const BigInt& m_x; + std::vector<BigInt> m_ws; }; secure_vector<uint8_t> @@ -62,7 +61,7 @@ ECGDSA_Signature_Operation::raw_sign(const uint8_t msg[], size_t msg_len, BigInt k = BigInt::random_integer(rng, 1, m_group.get_order()); - const PointGFp k_times_P = m_base_point.blinded_multiply(k, rng); + const PointGFp k_times_P = m_group.blinded_base_point_multiply(k, rng, m_ws); const BigInt r = m_group.mod_order(k_times_P.get_affine_x()); const BigInt s = m_group.multiply_mod_order(m_x, mul_sub(k, r, m)); diff --git a/src/lib/pubkey/ecies/ecies.cpp b/src/lib/pubkey/ecies/ecies.cpp index cd09b4c52..1120a850a 100644 --- a/src/lib/pubkey/ecies/ecies.cpp +++ b/src/lib/pubkey/ecies/ecies.cpp @@ -66,16 +66,24 @@ class ECIES_ECDH_KA_Operation final : public PK_Ops::Key_Agreement_with_KDF secure_vector<uint8_t> raw_agree(const uint8_t w[], size_t w_len) override { - PointGFp point = m_key.domain().OS2ECP(w, w_len); - Blinded_Point_Multiply blinder(point, m_key.domain().get_order()); - PointGFp S = blinder.blinded_multiply(m_key.private_value(), m_rng); - BOTAN_ASSERT(S.on_the_curve(), "ECDH agreed value was on the curve"); - return BigInt::encode_1363(S.get_affine_x(), m_key.domain().get_p_bytes()); + const EC_Group& group = m_key.domain(); + + PointGFp input_point = group.OS2ECP(w, w_len); + input_point.randomize_repr(m_rng); + + PointGFp_Blinded_Multiplier blinder(input_point, m_ws); + + const PointGFp S = blinder.mul(m_key.private_value(), group.get_order(), m_rng, m_ws); + + if(S.on_the_curve() == false) + throw Internal_Error("ECDH agreed value was not on the curve"); + return BigInt::encode_1363(S.get_affine_x(), group.get_p_bytes()); } private: ECIES_PrivateKey m_key; RandomNumberGenerator& m_rng; + std::vector<BigInt> m_ws; }; std::unique_ptr<PK_Ops::Key_Agreement> diff --git a/src/lib/pubkey/eckcdsa/eckcdsa.cpp b/src/lib/pubkey/eckcdsa/eckcdsa.cpp index 743d5ab95..be721a6b6 100644 --- a/src/lib/pubkey/eckcdsa/eckcdsa.cpp +++ b/src/lib/pubkey/eckcdsa/eckcdsa.cpp @@ -45,7 +45,6 @@ class ECKCDSA_Signature_Operation final : public PK_Ops::Signature_with_EMSA const std::string& emsa) : PK_Ops::Signature_with_EMSA(emsa), m_group(eckcdsa.domain()), - m_base_point(m_group.get_base_point(), m_group.get_order()), m_x(eckcdsa.private_value()), m_prefix() { @@ -68,9 +67,9 @@ class ECKCDSA_Signature_Operation final : public PK_Ops::Signature_with_EMSA private: const EC_Group m_group; - Blinded_Point_Multiply m_base_point; const BigInt& m_x; secure_vector<uint8_t> m_prefix; + std::vector<BigInt> m_ws; }; secure_vector<uint8_t> @@ -78,7 +77,7 @@ ECKCDSA_Signature_Operation::raw_sign(const uint8_t msg[], size_t, RandomNumberGenerator& rng) { const BigInt k = BigInt::random_integer(rng, 1, m_group.get_order()); - const PointGFp k_times_P = m_base_point.blinded_multiply(k, rng); + const PointGFp k_times_P = m_group.blinded_base_point_multiply(k, rng, m_ws); const BigInt k_times_P_x = k_times_P.get_affine_x(); secure_vector<uint8_t> to_be_hashed(k_times_P_x.bytes()); diff --git a/src/lib/pubkey/gost_3410/gost_3410.cpp b/src/lib/pubkey/gost_3410/gost_3410.cpp index 760e667aa..79d3f204d 100644 --- a/src/lib/pubkey/gost_3410/gost_3410.cpp +++ b/src/lib/pubkey/gost_3410/gost_3410.cpp @@ -101,7 +101,6 @@ class GOST_3410_Signature_Operation final : public PK_Ops::Signature_with_EMSA const std::string& emsa) : PK_Ops::Signature_with_EMSA(emsa), m_group(gost_3410.domain()), - m_base_point(m_group.get_base_point(), m_group.get_order()), m_x(gost_3410.private_value()) {} @@ -112,8 +111,8 @@ class GOST_3410_Signature_Operation final : public PK_Ops::Signature_with_EMSA private: const EC_Group m_group; - Blinded_Point_Multiply m_base_point; const BigInt& m_x; + std::vector<BigInt> m_ws; }; secure_vector<uint8_t> @@ -133,7 +132,7 @@ GOST_3410_Signature_Operation::raw_sign(const uint8_t msg[], size_t msg_len, if(e == 0) e = 1; - const PointGFp k_times_P = m_base_point.blinded_multiply(k, rng); + const PointGFp k_times_P = m_group.blinded_base_point_multiply(k, rng, m_ws); BOTAN_ASSERT(k_times_P.on_the_curve(), "GOST 34.10 k*g is on the curve"); const BigInt r = m_group.mod_order(k_times_P.get_affine_x()); diff --git a/src/lib/pubkey/sm2/sm2.cpp b/src/lib/pubkey/sm2/sm2.cpp index 2af888bbc..9ef30d9bf 100644 --- a/src/lib/pubkey/sm2/sm2.cpp +++ b/src/lib/pubkey/sm2/sm2.cpp @@ -83,7 +83,6 @@ class SM2_Signature_Operation final : public PK_Ops::Signature const std::string& ident, const std::string& hash) : m_group(sm2.domain()), - m_base_point(m_group.get_base_point(), m_group.get_order()), m_x(sm2.private_value()), m_da_inv(sm2.get_da_inv()), m_hash(HashFunction::create_or_throw(hash)) @@ -102,12 +101,12 @@ class SM2_Signature_Operation final : public PK_Ops::Signature private: const EC_Group m_group; - Blinded_Point_Multiply m_base_point; const BigInt& m_x; const BigInt& m_da_inv; std::vector<uint8_t> m_za; std::unique_ptr<HashFunction> m_hash; + std::vector<BigInt> m_ws; }; secure_vector<uint8_t> @@ -115,7 +114,7 @@ SM2_Signature_Operation::sign(RandomNumberGenerator& rng) { const BigInt k = BigInt::random_integer(rng, 1, m_group.get_order()); - const PointGFp k_times_P = m_base_point.blinded_multiply(k, rng); + const PointGFp k_times_P = m_group.blinded_base_point_multiply(k, rng, m_ws); const BigInt e = BigInt::decode(m_hash->final()); const BigInt r = m_group.mod_order(k_times_P.get_affine_x() + e); diff --git a/src/lib/pubkey/sm2/sm2_enc.cpp b/src/lib/pubkey/sm2/sm2_enc.cpp index 462c4b968..b0d773635 100644 --- a/src/lib/pubkey/sm2/sm2_enc.cpp +++ b/src/lib/pubkey/sm2/sm2_enc.cpp @@ -47,8 +47,7 @@ class SM2_Encryption_Operation final : public PK_Ops::Encryption public: SM2_Encryption_Operation(const SM2_Encryption_PublicKey& key, const std::string& kdf_hash) : m_group(key.domain()), - m_base_point(m_group.get_base_point(), m_group.get_order()), - m_public_point(key.public_point(), m_group.get_order()), + m_mul_public_point(key.public_point()), m_kdf_hash(kdf_hash) {} @@ -69,7 +68,7 @@ class SM2_Encryption_Operation final : public PK_Ops::Encryption const BigInt k = BigInt::random_integer(rng, 1, m_group.get_order()); - const PointGFp C1 = m_base_point.blinded_multiply(k, rng); + const PointGFp C1 = m_group.blinded_base_point_multiply(k, rng, m_ws); const BigInt x1 = C1.get_affine_x(); const BigInt y1 = C1.get_affine_y(); std::vector<uint8_t> x1_bytes(p_bytes); @@ -77,7 +76,7 @@ class SM2_Encryption_Operation final : public PK_Ops::Encryption BigInt::encode_1363(x1_bytes.data(), x1_bytes.size(), x1); BigInt::encode_1363(y1_bytes.data(), y1_bytes.size(), y1); - const PointGFp kPB = m_public_point.blinded_multiply(k, rng); + const PointGFp kPB = m_mul_public_point.mul(k, m_group.get_order(), rng, m_ws); const BigInt x2 = kPB.get_affine_x(); const BigInt y2 = kPB.get_affine_y(); @@ -114,9 +113,9 @@ class SM2_Encryption_Operation final : public PK_Ops::Encryption private: const EC_Group m_group; - Blinded_Point_Multiply m_base_point; - Blinded_Point_Multiply m_public_point; + PointGFp_Blinded_Multiplier m_mul_public_point; const std::string m_kdf_hash; + std::vector<BigInt> m_ws; }; class SM2_Decryption_Operation final : public PK_Ops::Decryption @@ -134,8 +133,9 @@ class SM2_Decryption_Operation final : public PK_Ops::Decryption const uint8_t ciphertext[], size_t ciphertext_len) override { - const BigInt& cofactor = m_key.domain().get_cofactor(); - const size_t p_bytes = m_key.domain().get_p_bytes(); + const EC_Group& group = m_key.domain(); + const BigInt& cofactor = group.get_cofactor(); + const size_t p_bytes = group.get_p_bytes(); valid_mask = 0x00; @@ -160,18 +160,20 @@ class SM2_Decryption_Operation final : public PK_Ops::Decryption .end_cons() .verify_end(); - const PointGFp C1 = m_key.domain().point(x1, y1); + PointGFp C1 = group.point(x1, y1); if(!C1.on_the_curve()) return secure_vector<uint8_t>(); - Blinded_Point_Multiply C1_mul(C1, m_key.domain().get_order()); - - if(cofactor > 1 && C1_mul.blinded_multiply(cofactor, m_rng).is_zero()) + if(cofactor > 1 && (C1 * cofactor).is_zero()) { return secure_vector<uint8_t>(); } - const PointGFp dbC1 = C1_mul.blinded_multiply(m_key.private_value(), m_rng); + C1.randomize_repr(m_rng); + + PointGFp_Blinded_Multiplier C1_mul(C1); + + const PointGFp dbC1 = C1_mul.mul(m_key.private_value(), group.get_order(), m_rng, m_ws); const BigInt x2 = dbC1.get_affine_x(); const BigInt y2 = dbC1.get_affine_y(); @@ -205,6 +207,7 @@ class SM2_Decryption_Operation final : public PK_Ops::Decryption const SM2_Encryption_PrivateKey& m_key; RandomNumberGenerator& m_rng; const std::string m_kdf_hash; + std::vector<BigInt> m_ws; }; } |