Coverage Report

Created: 2022-06-23 06:44

/src/botan/src/lib/pubkey/eckcdsa/eckcdsa.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
* ECKCDSA (ISO/IEC 14888-3:2006/Cor.2:2009)
3
* (C) 2016 René Korthaus, Sirrix AG
4
* (C) 2018 Jack Lloyd
5
*
6
* Botan is released under the Simplified BSD License (see license.txt)
7
*/
8
9
#include <botan/eckcdsa.h>
10
#include <botan/internal/pk_ops_impl.h>
11
#include <botan/internal/point_mul.h>
12
#include <botan/internal/keypair.h>
13
#include <botan/reducer.h>
14
#include <botan/internal/emsa.h>
15
#include <botan/hash.h>
16
#include <botan/rng.h>
17
18
namespace Botan {
19
20
std::unique_ptr<Public_Key> ECKCDSA_PrivateKey::public_key() const
21
0
   {
22
0
   return std::make_unique<ECKCDSA_PublicKey>(domain(), public_point());
23
0
   }
24
25
bool ECKCDSA_PrivateKey::check_key(RandomNumberGenerator& rng,
26
                                   bool strong) const
27
0
   {
28
0
   if(!public_point().on_the_curve())
29
0
      {
30
0
      return false;
31
0
      }
32
33
0
   if(!strong)
34
0
      {
35
0
      return true;
36
0
      }
37
38
0
   return KeyPair::signature_consistency_check(rng, *this, "EMSA1(SHA-256)");
39
0
   }
40
41
namespace {
42
43
/**
44
* ECKCDSA signature operation
45
*/
46
class ECKCDSA_Signature_Operation final : public PK_Ops::Signature_with_EMSA
47
   {
48
   public:
49
50
      ECKCDSA_Signature_Operation(const ECKCDSA_PrivateKey& eckcdsa,
51
                                  const std::string& emsa) :
52
         PK_Ops::Signature_with_EMSA(emsa),
53
         m_group(eckcdsa.domain()),
54
         m_x(eckcdsa.private_value()),
55
         m_prefix()
56
0
         {
57
0
         const BigInt public_point_x = eckcdsa.public_point().get_affine_x();
58
0
         const BigInt public_point_y = eckcdsa.public_point().get_affine_y();
59
60
0
         const size_t order_bytes = m_group.get_order_bytes();
61
62
0
         m_prefix.resize(2*order_bytes);
63
0
         BigInt::encode_1363(&m_prefix[0], order_bytes, public_point_x);
64
0
         BigInt::encode_1363(&m_prefix[order_bytes], order_bytes, public_point_y);
65
66
0
         const size_t block_size = HashFunction::create(hash_for_signature())->hash_block_size();
67
         // Either truncate or zero-extend to match the hash block size
68
0
         m_prefix.resize(block_size);
69
0
         }
70
71
      secure_vector<uint8_t> raw_sign(const uint8_t msg[], size_t msg_len,
72
                                      RandomNumberGenerator& rng) override;
73
74
0
      size_t signature_length() const override { return 2*m_group.get_order_bytes(); }
75
0
      size_t max_input_bits() const override { return m_group.get_order_bits(); }
76
77
0
      bool has_prefix() override { return true; }
78
0
      secure_vector<uint8_t> message_prefix() const override { return m_prefix; }
79
80
   private:
81
      const EC_Group m_group;
82
      const BigInt& m_x;
83
      secure_vector<uint8_t> m_prefix;
84
      std::vector<BigInt> m_ws;
85
   };
86
87
secure_vector<uint8_t>
88
ECKCDSA_Signature_Operation::raw_sign(const uint8_t msg[], size_t /*msg_len*/,
89
                                      RandomNumberGenerator& rng)
90
0
   {
91
0
   const BigInt k = m_group.random_scalar(rng);
92
0
   const BigInt k_times_P_x = m_group.blinded_base_point_multiply_x(k, rng, m_ws);
93
94
0
   secure_vector<uint8_t> to_be_hashed(k_times_P_x.bytes());
95
0
   k_times_P_x.binary_encode(to_be_hashed.data());
96
97
0
   std::unique_ptr<EMSA> emsa = this->clone_emsa();
98
0
   emsa->update(to_be_hashed.data(), to_be_hashed.size());
99
0
   secure_vector<uint8_t> c = emsa->raw_data();
100
0
   c = emsa->encoding_of(c, max_input_bits(), rng);
101
102
0
   const BigInt r(c.data(), c.size());
103
104
0
   xor_buf(c, msg, c.size());
105
0
   BigInt w(c.data(), c.size());
106
0
   w = m_group.mod_order(w);
107
108
0
   const BigInt s = m_group.multiply_mod_order(m_x, k - w);
109
0
   if(s.is_zero())
110
0
      throw Internal_Error("During ECKCDSA signature generation created zero s");
111
112
0
   secure_vector<uint8_t> output = BigInt::encode_1363(r, c.size());
113
0
   output += BigInt::encode_1363(s, m_group.get_order_bytes());
114
0
   return output;
115
0
   }
116
117
/**
118
* ECKCDSA verification operation
119
*/
120
class ECKCDSA_Verification_Operation final : public PK_Ops::Verification_with_EMSA
121
   {
122
   public:
123
124
      ECKCDSA_Verification_Operation(const ECKCDSA_PublicKey& eckcdsa,
125
                                     const std::string& emsa) :
126
         PK_Ops::Verification_with_EMSA(emsa),
127
         m_group(eckcdsa.domain()),
128
         m_gy_mul(m_group.get_base_point(), eckcdsa.public_point()),
129
         m_prefix()
130
0
         {
131
0
         const BigInt public_point_x = eckcdsa.public_point().get_affine_x();
132
0
         const BigInt public_point_y = eckcdsa.public_point().get_affine_y();
133
134
0
         const size_t order_bytes = m_group.get_order_bytes();
135
136
0
         m_prefix.resize(2*order_bytes);
137
0
         BigInt::encode_1363(&m_prefix[0], order_bytes, public_point_x);
138
0
         BigInt::encode_1363(&m_prefix[order_bytes], order_bytes, public_point_y);
139
140
0
         const size_t block_size = HashFunction::create(hash_for_signature())->hash_block_size();
141
         // Either truncate or zero-extend to match the hash block size
142
0
         m_prefix.resize(block_size);
143
0
         }
144
145
0
      bool has_prefix() override { return true; }
146
0
      secure_vector<uint8_t> message_prefix() const override { return m_prefix; }
147
148
0
      size_t max_input_bits() const override { return m_group.get_order_bits(); }
149
150
0
      bool with_recovery() const override { return false; }
151
152
      bool verify(const uint8_t msg[], size_t msg_len,
153
                  const uint8_t sig[], size_t sig_len) override;
154
   private:
155
      const EC_Group m_group;
156
      const PointGFp_Multi_Point_Precompute m_gy_mul;
157
      secure_vector<uint8_t> m_prefix;
158
   };
159
160
bool ECKCDSA_Verification_Operation::verify(const uint8_t msg[], size_t /*msg_len*/,
161
                                            const uint8_t sig[], size_t sig_len)
162
0
   {
163
0
   const std::unique_ptr<HashFunction> hash = HashFunction::create(hash_for_signature());
164
   //calculate size of r
165
166
0
   const size_t order_bytes = m_group.get_order_bytes();
167
168
0
   const size_t size_r = std::min(hash -> output_length(), order_bytes);
169
0
   if(sig_len != size_r + order_bytes)
170
0
      {
171
0
      return false;
172
0
      }
173
174
0
   secure_vector<uint8_t> r(sig, sig + size_r);
175
176
   // check that 0 < s < q
177
0
   const BigInt s(sig + size_r, order_bytes);
178
179
0
   if(s <= 0 || s >= m_group.get_order())
180
0
      {
181
0
      return false;
182
0
      }
183
184
0
   secure_vector<uint8_t> r_xor_e(r);
185
0
   xor_buf(r_xor_e, msg, r.size());
186
0
   BigInt w(r_xor_e.data(), r_xor_e.size());
187
0
   w = m_group.mod_order(w);
188
189
0
   const PointGFp q = m_gy_mul.multi_exp(w, s);
190
0
   if(q.is_zero())
191
0
      {
192
0
      return false;
193
0
      }
194
195
0
   const BigInt q_x = q.get_affine_x();
196
0
   secure_vector<uint8_t> c(q_x.bytes());
197
0
   q_x.binary_encode(c.data());
198
0
   std::unique_ptr<EMSA> emsa = this->clone_emsa();
199
0
   emsa->update(c.data(), c.size());
200
0
   secure_vector<uint8_t> v = emsa->raw_data();
201
0
   Null_RNG rng;
202
0
   v = emsa->encoding_of(v, max_input_bits(), rng);
203
204
0
   return (v == r);
205
0
   }
206
207
}
208
209
std::unique_ptr<PK_Ops::Verification>
210
ECKCDSA_PublicKey::create_verification_op(const std::string& params,
211
                                          const std::string& provider) const
212
0
   {
213
0
   if(provider == "base" || provider.empty())
214
0
      return std::make_unique<ECKCDSA_Verification_Operation>(*this, params);
215
0
   throw Provider_Not_Found(algo_name(), provider);
216
0
   }
217
218
std::unique_ptr<PK_Ops::Signature>
219
ECKCDSA_PrivateKey::create_signature_op(RandomNumberGenerator& /*rng*/,
220
                                        const std::string& params,
221
                                        const std::string& provider) const
222
0
   {
223
0
   if(provider == "base" || provider.empty())
224
0
      return std::make_unique<ECKCDSA_Signature_Operation>(*this, params);
225
0
   throw Provider_Not_Found(algo_name(), provider);
226
0
   }
227
228
}