Botan  2.6.0
Crypto and TLS for C++11
ecdsa.cpp
Go to the documentation of this file.
1 /*
2 * ECDSA implemenation
3 * (C) 2007 Manuel Hartl, FlexSecure GmbH
4 * 2007 Falko Strenzke, FlexSecure GmbH
5 * 2008-2010,2015,2016,2018 Jack Lloyd
6 * 2016 RenĂ© Korthaus
7 *
8 * Botan is released under the Simplified BSD License (see license.txt)
9 */
10 
11 #include <botan/ecdsa.h>
12 #include <botan/internal/pk_ops_impl.h>
13 #include <botan/internal/point_mul.h>
14 #include <botan/keypair.h>
15 #include <botan/reducer.h>
16 #include <botan/emsa.h>
17 
18 #if defined(BOTAN_HAS_RFC6979_GENERATOR)
19  #include <botan/rfc6979.h>
20 #endif
21 
22 #if defined(BOTAN_HAS_BEARSSL)
23  #include <botan/internal/bearssl.h>
24 #endif
25 
26 #if defined(BOTAN_HAS_OPENSSL)
27  #include <botan/internal/openssl.h>
28 #endif
29 
30 namespace Botan {
31 
33  bool strong) const
34  {
35  if(!public_point().on_the_curve())
36  return false;
37 
38  if(!strong)
39  return true;
40 
41  return KeyPair::signature_consistency_check(rng, *this, "EMSA1(SHA-256)");
42  }
43 
44 namespace {
45 
46 /**
47 * ECDSA signature operation
48 */
49 class ECDSA_Signature_Operation final : public PK_Ops::Signature_with_EMSA
50  {
51  public:
52 
53  ECDSA_Signature_Operation(const ECDSA_PrivateKey& ecdsa,
54  const std::string& emsa) :
55  PK_Ops::Signature_with_EMSA(emsa),
56  m_group(ecdsa.domain()),
57  m_x(ecdsa.private_value())
58  {
59 #if defined(BOTAN_HAS_RFC6979_GENERATOR)
60  m_rfc6979_hash = hash_for_emsa(emsa);
61 #endif
62  }
63 
64  size_t max_input_bits() const override { return m_group.get_order_bits(); }
65 
66  secure_vector<uint8_t> raw_sign(const uint8_t msg[], size_t msg_len,
67  RandomNumberGenerator& rng) override;
68 
69  private:
70  const EC_Group m_group;
71  const BigInt& m_x;
72 
73 #if defined(BOTAN_HAS_RFC6979_GENERATOR)
74  std::string m_rfc6979_hash;
75 #endif
76 
77  std::vector<BigInt> m_ws;
78  };
79 
80 secure_vector<uint8_t>
81 ECDSA_Signature_Operation::raw_sign(const uint8_t msg[], size_t msg_len,
82  RandomNumberGenerator& rng)
83  {
84  BigInt m(msg, msg_len, m_group.get_order_bits());
85 
86 #if defined(BOTAN_HAS_RFC6979_GENERATOR)
87  const BigInt k = generate_rfc6979_nonce(m_x, m_group.get_order(), m, m_rfc6979_hash);
88 #else
89  const BigInt k = m_group.random_scalar(rng);
90 #endif
91 
92  const BigInt k_inv = inverse_mod(k, m_group.get_order());
93  const BigInt r = m_group.mod_order(
94  m_group.blinded_base_point_multiply_x(k, rng, m_ws));
95 
96  const BigInt xrm = m_group.mod_order(m_group.multiply_mod_order(m_x, r) + m);
97  const BigInt s = m_group.multiply_mod_order(k_inv, xrm);
98 
99  // With overwhelming probability, a bug rather than actual zero r/s
100  if(r.is_zero() || s.is_zero())
101  throw Internal_Error("During ECDSA signature generated zero r/s");
102 
103  return BigInt::encode_fixed_length_int_pair(r, s, m_group.get_order_bytes());
104  }
105 
106 /**
107 * ECDSA verification operation
108 */
109 class ECDSA_Verification_Operation final : public PK_Ops::Verification_with_EMSA
110  {
111  public:
112  ECDSA_Verification_Operation(const ECDSA_PublicKey& ecdsa,
113  const std::string& emsa) :
114  PK_Ops::Verification_with_EMSA(emsa),
115  m_group(ecdsa.domain()),
116  m_gy_mul(m_group.get_base_point(), ecdsa.public_point())
117  {
118  }
119 
120  size_t max_input_bits() const override { return m_group.get_order_bits(); }
121 
122  bool with_recovery() const override { return false; }
123 
124  bool verify(const uint8_t msg[], size_t msg_len,
125  const uint8_t sig[], size_t sig_len) override;
126  private:
127  const EC_Group m_group;
128  const PointGFp_Multi_Point_Precompute m_gy_mul;
129  };
130 
131 bool ECDSA_Verification_Operation::verify(const uint8_t msg[], size_t msg_len,
132  const uint8_t sig[], size_t sig_len)
133  {
134  if(sig_len != m_group.get_order_bytes() * 2)
135  return false;
136 
137  const BigInt e(msg, msg_len, m_group.get_order_bits());
138 
139  const BigInt r(sig, sig_len / 2);
140  const BigInt s(sig + sig_len / 2, sig_len / 2);
141 
142  if(r <= 0 || r >= m_group.get_order() || s <= 0 || s >= m_group.get_order())
143  return false;
144 
145  const BigInt w = inverse_mod(s, m_group.get_order());
146 
147  const BigInt u1 = m_group.multiply_mod_order(e, w);
148  const BigInt u2 = m_group.multiply_mod_order(r, w);
149  const PointGFp R = m_gy_mul.multi_exp(u1, u2);
150 
151  if(R.is_zero())
152  return false;
153 
154  const BigInt v = m_group.mod_order(R.get_affine_x());
155  return (v == r);
156  }
157 
158 }
159 
160 std::unique_ptr<PK_Ops::Verification>
161 ECDSA_PublicKey::create_verification_op(const std::string& params,
162  const std::string& provider) const
163  {
164 #if defined(BOTAN_HAS_BEARSSL)
165  if(provider == "bearssl" || provider.empty())
166  {
167  try
168  {
169  return make_bearssl_ecdsa_ver_op(*this, params);
170  }
171  catch(Lookup_Error& e)
172  {
173  if(provider == "bearssl")
174  throw;
175  }
176  }
177 #endif
178 
179 #if defined(BOTAN_HAS_OPENSSL)
180  if(provider == "openssl" || provider.empty())
181  {
182  try
183  {
184  return make_openssl_ecdsa_ver_op(*this, params);
185  }
186  catch(Lookup_Error& e)
187  {
188  if(provider == "openssl")
189  throw;
190  }
191  }
192 #endif
193 
194  if(provider == "base" || provider.empty())
195  return std::unique_ptr<PK_Ops::Verification>(new ECDSA_Verification_Operation(*this, params));
196 
197  throw Provider_Not_Found(algo_name(), provider);
198  }
199 
200 std::unique_ptr<PK_Ops::Signature>
202  const std::string& params,
203  const std::string& provider) const
204  {
205 #if defined(BOTAN_HAS_BEARSSL)
206  if(provider == "bearssl" || provider.empty())
207  {
208  try
209  {
210  return make_bearssl_ecdsa_sig_op(*this, params);
211  }
212  catch(Lookup_Error& e)
213  {
214  if(provider == "bearssl")
215  throw;
216  }
217  }
218 #endif
219 
220 #if defined(BOTAN_HAS_OPENSSL)
221  if(provider == "openssl" || provider.empty())
222  {
223  try
224  {
225  return make_openssl_ecdsa_sig_op(*this, params);
226  }
227  catch(Lookup_Error& e)
228  {
229  if(provider == "openssl")
230  throw;
231  }
232  }
233 #endif
234 
235  if(provider == "base" || provider.empty())
236  return std::unique_ptr<PK_Ops::Signature>(new ECDSA_Signature_Operation(*this, params));
237 
238  throw Provider_Not_Found(algo_name(), provider);
239  }
240 
241 }
bool check_key(RandomNumberGenerator &rng, bool) const override
Definition: ecdsa.cpp:32
PointGFp multi_exp(const BigInt &k1, const BigInt &k2) const
Definition: point_mul.cpp:251
const PointGFp & public_point() const
Definition: ecc_key.h:57
BigInt generate_rfc6979_nonce(const BigInt &x, const BigInt &q, const BigInt &h, const std::string &hash)
Definition: rfc6979.cpp:49
bool signature_consistency_check(RandomNumberGenerator &rng, const Private_Key &private_key, const Public_Key &public_key, const std::string &padding)
Definition: keypair.cpp:49
std::string hash_for_emsa(const std::string &algo_spec)
Definition: emsa.cpp:168
BigInt inverse_mod(const BigInt &n, const BigInt &mod)
Definition: numthry.cpp:279
std::unique_ptr< PK_Ops::Verification > create_verification_op(const std::string &params, const std::string &provider) const override
Definition: ecdsa.cpp:161
Definition: alg_id.cpp:13
std::unique_ptr< PK_Ops::Signature > create_signature_op(RandomNumberGenerator &rng, const std::string &params, const std::string &provider) const override
Definition: ecdsa.cpp:201
std::string algo_name() const override
Definition: ecdsa.h:46
static secure_vector< uint8_t > encode_fixed_length_int_pair(const BigInt &n1, const BigInt &n2, size_t bytes)
Definition: big_code.cpp:103