Coverage Report

Created: 2022-11-24 06:56

/src/botan/src/lib/pubkey/ecdsa/ecdsa.cpp
Line
Count
Source (jump to first uncovered line)
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/internal/keypair.h>
15
#include <botan/reducer.h>
16
#include <botan/internal/emsa.h>
17
18
#if defined(BOTAN_HAS_RFC6979_GENERATOR)
19
  #include <botan/internal/rfc6979.h>
20
#endif
21
22
namespace Botan {
23
24
namespace {
25
26
PointGFp recover_ecdsa_public_key(const EC_Group& group,
27
                                  const std::vector<uint8_t>& msg,
28
                                  const BigInt& r,
29
                                  const BigInt& s,
30
                                  uint8_t v)
31
0
   {
32
0
   if(group.get_cofactor() != 1)
33
0
      throw Invalid_Argument("ECDSA public key recovery only supported for prime order groups");
34
35
0
   if(v >= 4)
36
0
      throw Invalid_Argument("Unexpected v param for ECDSA public key recovery");
37
38
0
   const BigInt& group_order = group.get_order();
39
40
0
   if(r <= 0 || r >= group_order || s <= 0 || s >= group_order)
41
0
      {
42
0
      throw Invalid_Argument("Out of range r/s cannot recover ECDSA public key");
43
0
      }
44
45
0
   const uint8_t y_odd = v % 2;
46
0
   const uint8_t add_order = v >> 1;
47
0
   const size_t p_bytes = group.get_p_bytes();
48
49
0
   try
50
0
      {
51
0
      const BigInt e = BigInt::from_bytes_with_max_bits(msg.data(), msg.size(), group.get_order_bits());
52
0
      const BigInt r_inv = group.inverse_mod_order(r);
53
54
0
      BigInt x = r + add_order*group_order;
55
56
0
      std::vector<uint8_t> X(p_bytes + 1);
57
58
0
      X[0] = 0x02 | y_odd;
59
0
      BigInt::encode_1363(&X[1], p_bytes, x);
60
61
0
      const PointGFp R = group.OS2ECP(X);
62
63
0
      if((R*group_order).is_zero() == false)
64
0
         throw Decoding_Error("Unable to recover ECDSA public key");
65
66
      // Compute r_inv * (s*R - eG)
67
0
      PointGFp_Multi_Point_Precompute RG_mul(R, group.get_base_point());
68
0
      const BigInt ne = group.mod_order(group_order - e);
69
0
      return r_inv * RG_mul.multi_exp(s, ne);
70
0
      }
71
0
   catch(...)
72
0
      {
73
      // continue on and throw
74
0
      }
75
76
0
   throw Decoding_Error("Failed to recover ECDSA public key from signature/msg pair");
77
0
   }
78
79
}
80
81
ECDSA_PublicKey::ECDSA_PublicKey(const EC_Group& group,
82
                                 const std::vector<uint8_t>& msg,
83
                                 const BigInt& r,
84
                                 const BigInt& s,
85
                                 uint8_t v) :
86
0
   EC_PublicKey(group, recover_ecdsa_public_key(group, msg, r, s, v)) {}
Unexecuted instantiation: Botan::ECDSA_PublicKey::ECDSA_PublicKey(Botan::EC_Group const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> > const&, Botan::BigInt const&, Botan::BigInt const&, unsigned char)
Unexecuted instantiation: Botan::ECDSA_PublicKey::ECDSA_PublicKey(Botan::EC_Group const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> > const&, Botan::BigInt const&, Botan::BigInt const&, unsigned char)
87
88
89
uint8_t ECDSA_PublicKey::recovery_param(const std::vector<uint8_t>& msg,
90
                                        const BigInt& r,
91
                                        const BigInt& s) const
92
0
   {
93
0
   for(uint8_t v = 0; v != 4; ++v)
94
0
      {
95
0
      try
96
0
         {
97
0
         PointGFp R = recover_ecdsa_public_key(this->domain(), msg, r, s, v);
98
99
0
         if(R == this->public_point())
100
0
            {
101
0
            return v;
102
0
            }
103
0
         }
104
0
      catch(Decoding_Error&)
105
0
         {
106
         // try the next v
107
0
         }
108
0
      }
109
110
0
   throw Internal_Error("Could not determine ECDSA recovery parameter");
111
0
   }
112
113
std::unique_ptr<Public_Key> ECDSA_PrivateKey::public_key() const
114
0
   {
115
0
   return std::make_unique<ECDSA_PublicKey>(domain(), public_point());
116
0
   }
117
118
bool ECDSA_PrivateKey::check_key(RandomNumberGenerator& rng,
119
                                 bool strong) const
120
0
   {
121
0
   if(!public_point().on_the_curve())
122
0
      return false;
123
124
0
   if(!strong)
125
0
      return true;
126
127
0
   return KeyPair::signature_consistency_check(rng, *this, "EMSA1(SHA-256)");
128
0
   }
129
130
namespace {
131
132
/**
133
* ECDSA signature operation
134
*/
135
class ECDSA_Signature_Operation final : public PK_Ops::Signature_with_EMSA
136
   {
137
   public:
138
139
      ECDSA_Signature_Operation(const ECDSA_PrivateKey& ecdsa,
140
                                const std::string& emsa,
141
                                RandomNumberGenerator& rng) :
142
         PK_Ops::Signature_with_EMSA(emsa),
143
         m_group(ecdsa.domain()),
144
         m_x(ecdsa.private_value())
145
0
         {
146
0
#if defined(BOTAN_HAS_RFC6979_GENERATOR)
147
0
         m_rfc6979.reset(new RFC6979_Nonce_Generator(this->hash_for_signature(), m_group.get_order(), m_x));
148
0
#endif
149
150
0
         m_b = m_group.random_scalar(rng);
151
0
         m_b_inv = m_group.inverse_mod_order(m_b);
152
0
         }
153
154
0
      size_t signature_length() const override { return 2*m_group.get_order_bytes(); }
155
156
0
      size_t max_input_bits() const override { return m_group.get_order_bits(); }
157
158
      secure_vector<uint8_t> raw_sign(const uint8_t msg[], size_t msg_len,
159
                                      RandomNumberGenerator& rng) override;
160
161
   private:
162
      const EC_Group m_group;
163
      const BigInt& m_x;
164
165
#if defined(BOTAN_HAS_RFC6979_GENERATOR)
166
      std::unique_ptr<RFC6979_Nonce_Generator> m_rfc6979;
167
#endif
168
169
      std::vector<BigInt> m_ws;
170
171
      BigInt m_b, m_b_inv;
172
   };
173
174
secure_vector<uint8_t>
175
ECDSA_Signature_Operation::raw_sign(const uint8_t msg[], size_t msg_len,
176
                                    RandomNumberGenerator& rng)
177
0
   {
178
0
   BigInt m = BigInt::from_bytes_with_max_bits(msg, msg_len, m_group.get_order_bits());
179
180
0
#if defined(BOTAN_HAS_RFC6979_GENERATOR)
181
0
   const BigInt k = m_rfc6979->nonce_for(m);
182
#else
183
   const BigInt k = m_group.random_scalar(rng);
184
#endif
185
186
0
   const BigInt r = m_group.mod_order(
187
0
      m_group.blinded_base_point_multiply_x(k, rng, m_ws));
188
189
0
   const BigInt k_inv = m_group.inverse_mod_order(k);
190
191
   /*
192
   * Blind the input message and compute x*r+m as (x*r*b + m*b)/b
193
   */
194
0
   m_b = m_group.square_mod_order(m_b);
195
0
   m_b_inv = m_group.square_mod_order(m_b_inv);
196
197
0
   m = m_group.multiply_mod_order(m_b, m_group.mod_order(m));
198
0
   const BigInt xr_m = m_group.mod_order(m_group.multiply_mod_order(m_x, m_b, r) + m);
199
200
0
   const BigInt s = m_group.multiply_mod_order(k_inv, xr_m, m_b_inv);
201
202
   // With overwhelming probability, a bug rather than actual zero r/s
203
0
   if(r.is_zero() || s.is_zero())
204
0
      throw Internal_Error("During ECDSA signature generated zero r/s");
205
206
0
   return BigInt::encode_fixed_length_int_pair(r, s, m_group.get_order_bytes());
207
0
   }
208
209
/**
210
* ECDSA verification operation
211
*/
212
class ECDSA_Verification_Operation final : public PK_Ops::Verification_with_EMSA
213
   {
214
   public:
215
      ECDSA_Verification_Operation(const ECDSA_PublicKey& ecdsa,
216
                                   const std::string& emsa) :
217
         PK_Ops::Verification_with_EMSA(emsa),
218
         m_group(ecdsa.domain()),
219
         m_gy_mul(m_group.get_base_point(), ecdsa.public_point())
220
522
         {
221
522
         }
222
223
296
      size_t max_input_bits() const override { return m_group.get_order_bits(); }
224
225
296
      bool with_recovery() const override { return false; }
226
227
      bool verify(const uint8_t msg[], size_t msg_len,
228
                  const uint8_t sig[], size_t sig_len) override;
229
   private:
230
      const EC_Group m_group;
231
      const PointGFp_Multi_Point_Precompute m_gy_mul;
232
   };
233
234
bool ECDSA_Verification_Operation::verify(const uint8_t msg[], size_t msg_len,
235
                                          const uint8_t sig[], size_t sig_len)
236
296
   {
237
296
   if(sig_len != m_group.get_order_bytes() * 2)
238
0
      return false;
239
240
296
   const BigInt e = BigInt::from_bytes_with_max_bits(msg, msg_len, m_group.get_order_bits());
241
242
296
   const BigInt r(sig, sig_len / 2);
243
296
   const BigInt s(sig + sig_len / 2, sig_len / 2);
244
245
   // Cannot be negative here since we just decoded from binary
246
296
   if(r.is_zero() || s.is_zero())
247
6
      return false;
248
249
290
   if(r >= m_group.get_order() || s >= m_group.get_order())
250
2
      return false;
251
252
288
   const BigInt w = m_group.inverse_mod_order(s);
253
254
288
   const BigInt u1 = m_group.multiply_mod_order(m_group.mod_order(e), w);
255
288
   const BigInt u2 = m_group.multiply_mod_order(r, w);
256
288
   const PointGFp R = m_gy_mul.multi_exp(u1, u2);
257
258
288
   if(R.is_zero())
259
0
      return false;
260
261
288
   const BigInt v = m_group.mod_order(R.get_affine_x());
262
288
   return (v == r);
263
288
   }
264
265
}
266
267
std::unique_ptr<PK_Ops::Verification>
268
ECDSA_PublicKey::create_verification_op(const std::string& params,
269
                                        const std::string& provider) const
270
522
   {
271
522
   if(provider == "base" || provider.empty())
272
522
      return std::make_unique<ECDSA_Verification_Operation>(*this, params);
273
274
0
   throw Provider_Not_Found(algo_name(), provider);
275
522
   }
276
277
std::unique_ptr<PK_Ops::Signature>
278
ECDSA_PrivateKey::create_signature_op(RandomNumberGenerator& rng,
279
                                      const std::string& params,
280
                                      const std::string& provider) const
281
0
   {
282
0
   if(provider == "base" || provider.empty())
283
0
      return std::make_unique<ECDSA_Signature_Operation>(*this, params, rng);
284
285
0
   throw Provider_Not_Found(algo_name(), provider);
286
0
   }
287
288
}