Coverage Report

Created: 2020-03-26 13:53

/src/botan/src/lib/pubkey/gost_3410/gost_3410.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
* GOST 34.10-2012
3
* (C) 2007 Falko Strenzke, FlexSecure GmbH
4
*          Manuel Hartl, FlexSecure GmbH
5
* (C) 2008-2010,2015,2018 Jack Lloyd
6
*
7
* Botan is released under the Simplified BSD License (see license.txt)
8
*/
9
10
#include <botan/gost_3410.h>
11
#include <botan/internal/pk_ops_impl.h>
12
#include <botan/internal/point_mul.h>
13
#include <botan/reducer.h>
14
#include <botan/der_enc.h>
15
#include <botan/ber_dec.h>
16
17
namespace Botan {
18
19
std::vector<uint8_t> GOST_3410_PublicKey::public_key_bits() const
20
0
   {
21
0
   const BigInt x = public_point().get_affine_x();
22
0
   const BigInt y = public_point().get_affine_y();
23
0
24
0
   size_t part_size = std::max(x.bytes(), y.bytes());
25
0
26
0
   std::vector<uint8_t> bits(2*part_size);
27
0
28
0
   x.binary_encode(&bits[part_size - x.bytes()]);
29
0
   y.binary_encode(&bits[2*part_size - y.bytes()]);
30
0
31
0
   // Keys are stored in little endian format (WTF)
32
0
   for(size_t i = 0; i != part_size / 2; ++i)
33
0
      {
34
0
      std::swap(bits[i], bits[part_size-1-i]);
35
0
      std::swap(bits[part_size+i], bits[2*part_size-1-i]);
36
0
      }
37
0
38
0
   std::vector<uint8_t> output;
39
0
   DER_Encoder(output).encode(bits, OCTET_STRING);
40
0
   return output;
41
0
   }
42
43
std::string GOST_3410_PublicKey::algo_name() const
44
0
   {
45
0
   const size_t p_bits = domain().get_p_bits();
46
0
47
0
   if(p_bits == 256 || p_bits == 512)
48
0
      return "GOST-34.10-2012-" + std::to_string(p_bits);
49
0
   else
50
0
      throw Encoding_Error("GOST-34.10-2012 is not defined for parameters of this size");
51
0
   }
52
53
AlgorithmIdentifier GOST_3410_PublicKey::algorithm_identifier() const
54
0
   {
55
0
   std::vector<uint8_t> params;
56
0
57
0
   DER_Encoder(params)
58
0
      .start_cons(SEQUENCE)
59
0
         .encode(domain().get_curve_oid())
60
0
      .end_cons();
61
0
62
0
   return AlgorithmIdentifier(get_oid(), params);
63
0
   }
64
65
GOST_3410_PublicKey::GOST_3410_PublicKey(const AlgorithmIdentifier& alg_id,
66
                                         const std::vector<uint8_t>& key_bits)
67
0
   {
68
0
   OID ecc_param_id;
69
0
70
0
   // The parameters also includes hash and cipher OIDs
71
0
   BER_Decoder(alg_id.get_parameters()).start_cons(SEQUENCE).decode(ecc_param_id);
72
0
73
0
   m_domain_params = EC_Group(ecc_param_id);
74
0
75
0
   const size_t p_bits = m_domain_params.get_p_bits();
76
0
   if(p_bits != 256 && p_bits != 512)
77
0
      throw Decoding_Error("GOST-34.10-2012 is not defined for parameters of size " +
78
0
                           std::to_string(p_bits));
79
0
80
0
   secure_vector<uint8_t> bits;
81
0
   BER_Decoder(key_bits).decode(bits, OCTET_STRING);
82
0
83
0
   const size_t part_size = bits.size() / 2;
84
0
85
0
   // Keys are stored in little endian format (WTF)
86
0
   for(size_t i = 0; i != part_size / 2; ++i)
87
0
      {
88
0
      std::swap(bits[i], bits[part_size-1-i]);
89
0
      std::swap(bits[part_size+i], bits[2*part_size-1-i]);
90
0
      }
91
0
92
0
   BigInt x(bits.data(), part_size);
93
0
   BigInt y(&bits[part_size], part_size);
94
0
95
0
   m_public_key = domain().point(x, y);
96
0
97
0
   BOTAN_ASSERT(m_public_key.on_the_curve(),
98
0
                "Loaded GOST 34.10 public key is on the curve");
99
0
   }
Unexecuted instantiation: Botan::GOST_3410_PublicKey::GOST_3410_PublicKey(Botan::AlgorithmIdentifier const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> > const&)
Unexecuted instantiation: Botan::GOST_3410_PublicKey::GOST_3410_PublicKey(Botan::AlgorithmIdentifier const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> > const&)
100
101
GOST_3410_PrivateKey::GOST_3410_PrivateKey(RandomNumberGenerator& rng,
102
                                           const EC_Group& domain,
103
                                           const BigInt& x) :
104
   EC_PrivateKey(rng, domain, x)
105
0
   {
106
0
   const size_t p_bits = m_domain_params.get_p_bits();
107
0
   if(p_bits != 256 && p_bits != 512)
108
0
      throw Decoding_Error("GOST-34.10-2012 is not defined for parameters of size " +
109
0
                           std::to_string(p_bits));
110
0
   }
Unexecuted instantiation: Botan::GOST_3410_PrivateKey::GOST_3410_PrivateKey(Botan::RandomNumberGenerator&, Botan::EC_Group const&, Botan::BigInt const&)
Unexecuted instantiation: Botan::GOST_3410_PrivateKey::GOST_3410_PrivateKey(Botan::RandomNumberGenerator&, Botan::EC_Group const&, Botan::BigInt const&)
111
112
namespace {
113
114
BigInt decode_le(const uint8_t msg[], size_t msg_len)
115
0
   {
116
0
   secure_vector<uint8_t> msg_le(msg, msg + msg_len);
117
0
118
0
   for(size_t i = 0; i != msg_le.size() / 2; ++i)
119
0
      std::swap(msg_le[i], msg_le[msg_le.size()-1-i]);
120
0
121
0
   return BigInt(msg_le.data(), msg_le.size());
122
0
   }
123
124
/**
125
* GOST-34.10 signature operation
126
*/
127
class GOST_3410_Signature_Operation final : public PK_Ops::Signature_with_EMSA
128
   {
129
   public:
130
      GOST_3410_Signature_Operation(const GOST_3410_PrivateKey& gost_3410,
131
                                    const std::string& emsa) :
132
         PK_Ops::Signature_with_EMSA(emsa),
133
         m_group(gost_3410.domain()),
134
         m_x(gost_3410.private_value())
135
0
         {}
136
137
0
      size_t signature_length() const override { return 2*m_group.get_order_bytes(); }
138
139
0
      size_t max_input_bits() const override { return m_group.get_order_bits(); }
140
141
      secure_vector<uint8_t> raw_sign(const uint8_t msg[], size_t msg_len,
142
                                      RandomNumberGenerator& rng) override;
143
144
   private:
145
      const EC_Group m_group;
146
      const BigInt& m_x;
147
      std::vector<BigInt> m_ws;
148
   };
149
150
secure_vector<uint8_t>
151
GOST_3410_Signature_Operation::raw_sign(const uint8_t msg[], size_t msg_len,
152
                                        RandomNumberGenerator& rng)
153
0
   {
154
0
   const BigInt k = m_group.random_scalar(rng);
155
0
156
0
   BigInt e = decode_le(msg, msg_len);
157
0
158
0
   e = m_group.mod_order(e);
159
0
   if(e == 0)
160
0
      e = 1;
161
0
162
0
   const BigInt r = m_group.mod_order(
163
0
      m_group.blinded_base_point_multiply_x(k, rng, m_ws));
164
0
165
0
   const BigInt s = m_group.mod_order(
166
0
      m_group.multiply_mod_order(r, m_x) +
167
0
      m_group.multiply_mod_order(k, e));
168
0
169
0
   if(r == 0 || s == 0)
170
0
      throw Internal_Error("GOST 34.10 signature generation failed, r/s equal to zero");
171
0
172
0
   return BigInt::encode_fixed_length_int_pair(s, r, m_group.get_order_bytes());
173
0
   }
174
175
/**
176
* GOST-34.10 verification operation
177
*/
178
class GOST_3410_Verification_Operation final : public PK_Ops::Verification_with_EMSA
179
   {
180
   public:
181
182
      GOST_3410_Verification_Operation(const GOST_3410_PublicKey& gost,
183
                                       const std::string& emsa) :
184
         PK_Ops::Verification_with_EMSA(emsa),
185
         m_group(gost.domain()),
186
         m_gy_mul(m_group.get_base_point(), gost.public_point())
187
0
         {}
188
189
0
      size_t max_input_bits() const override { return m_group.get_order_bits(); }
190
191
0
      bool with_recovery() const override { return false; }
192
193
      bool verify(const uint8_t msg[], size_t msg_len,
194
                  const uint8_t sig[], size_t sig_len) override;
195
   private:
196
      const EC_Group m_group;
197
      const PointGFp_Multi_Point_Precompute m_gy_mul;
198
   };
199
200
bool GOST_3410_Verification_Operation::verify(const uint8_t msg[], size_t msg_len,
201
                                              const uint8_t sig[], size_t sig_len)
202
0
   {
203
0
   if(sig_len != m_group.get_order_bytes() * 2)
204
0
      return false;
205
0
206
0
   const BigInt s(sig, sig_len / 2);
207
0
   const BigInt r(sig + sig_len / 2, sig_len / 2);
208
0
209
0
   const BigInt& order = m_group.get_order();
210
0
211
0
   if(r <= 0 || r >= order || s <= 0 || s >= order)
212
0
      return false;
213
0
214
0
   BigInt e = decode_le(msg, msg_len);
215
0
   e = m_group.mod_order(e);
216
0
   if(e == 0)
217
0
      e = 1;
218
0
219
0
   const BigInt v = m_group.inverse_mod_order(e);
220
0
221
0
   const BigInt z1 = m_group.multiply_mod_order(s, v);
222
0
   const BigInt z2 = m_group.multiply_mod_order(-r, v);
223
0
224
0
   const PointGFp R = m_gy_mul.multi_exp(z1, z2);
225
0
226
0
   if(R.is_zero())
227
0
     return false;
228
0
229
0
   return (R.get_affine_x() == r);
230
0
   }
231
232
}
233
234
std::unique_ptr<PK_Ops::Verification>
235
GOST_3410_PublicKey::create_verification_op(const std::string& params,
236
                                            const std::string& provider) const
237
0
   {
238
0
   if(provider == "base" || provider.empty())
239
0
      return std::unique_ptr<PK_Ops::Verification>(new GOST_3410_Verification_Operation(*this, params));
240
0
   throw Provider_Not_Found(algo_name(), provider);
241
0
   }
242
243
std::unique_ptr<PK_Ops::Signature>
244
GOST_3410_PrivateKey::create_signature_op(RandomNumberGenerator& /*rng*/,
245
                                          const std::string& params,
246
                                          const std::string& provider) const
247
0
   {
248
0
   if(provider == "base" || provider.empty())
249
0
      return std::unique_ptr<PK_Ops::Signature>(new GOST_3410_Signature_Operation(*this, params));
250
0
   throw Provider_Not_Found(algo_name(), provider);
251
0
   }
252
253
}