Coverage Report

Created: 2021-06-10 10:30

/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
24
0
   size_t part_size = std::max(x.bytes(), y.bytes());
25
26
0
   std::vector<uint8_t> bits(2*part_size);
27
28
0
   x.binary_encode(&bits[part_size - x.bytes()]);
29
0
   y.binary_encode(&bits[2*part_size - y.bytes()]);
30
31
   // 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
38
0
   std::vector<uint8_t> output;
39
0
   DER_Encoder(output).encode(bits, ASN1_Type::OctetString);
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
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
57
0
   const OID gost_oid = get_oid();
58
0
   const OID domain_oid = domain().get_curve_oid();
59
60
0
   DER_Encoder(params).start_sequence().encode(domain_oid).end_cons();
61
62
0
   return AlgorithmIdentifier(gost_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
70
   // The parameters also includes hash and cipher OIDs
71
0
   BER_Decoder(alg_id.get_parameters()).start_sequence().decode(ecc_param_id);
72
73
0
   m_domain_params = EC_Group(ecc_param_id);
74
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
80
0
   secure_vector<uint8_t> bits;
81
0
   BER_Decoder(key_bits).decode(bits, ASN1_Type::OctetString);
82
83
0
   const size_t part_size = bits.size() / 2;
84
85
   // 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
92
0
   BigInt x(bits.data(), part_size);
93
0
   BigInt y(&bits[part_size], part_size);
94
95
0
   m_public_key = domain().point(x, y);
96
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
std::unique_ptr<Public_Key> GOST_3410_PrivateKey::public_key() const
113
0
   {
114
0
   return std::make_unique<GOST_3410_PublicKey>(domain(), public_point());
115
0
   }
116
117
namespace {
118
119
BigInt decode_le(const uint8_t msg[], size_t msg_len)
120
0
   {
121
0
   secure_vector<uint8_t> msg_le(msg, msg + msg_len);
122
123
0
   for(size_t i = 0; i != msg_le.size() / 2; ++i)
124
0
      std::swap(msg_le[i], msg_le[msg_le.size()-1-i]);
125
126
0
   return BigInt(msg_le.data(), msg_le.size());
127
0
   }
128
129
/**
130
* GOST-34.10 signature operation
131
*/
132
class GOST_3410_Signature_Operation final : public PK_Ops::Signature_with_EMSA
133
   {
134
   public:
135
      GOST_3410_Signature_Operation(const GOST_3410_PrivateKey& gost_3410,
136
                                    const std::string& emsa) :
137
         PK_Ops::Signature_with_EMSA(emsa),
138
         m_group(gost_3410.domain()),
139
         m_x(gost_3410.private_value())
140
0
         {}
141
142
0
      size_t signature_length() const override { return 2*m_group.get_order_bytes(); }
143
144
0
      size_t max_input_bits() const override { return m_group.get_order_bits(); }
145
146
      secure_vector<uint8_t> raw_sign(const uint8_t msg[], size_t msg_len,
147
                                      RandomNumberGenerator& rng) override;
148
149
   private:
150
      const EC_Group m_group;
151
      const BigInt& m_x;
152
      std::vector<BigInt> m_ws;
153
   };
154
155
secure_vector<uint8_t>
156
GOST_3410_Signature_Operation::raw_sign(const uint8_t msg[], size_t msg_len,
157
                                        RandomNumberGenerator& rng)
158
0
   {
159
0
   const BigInt k = m_group.random_scalar(rng);
160
161
0
   BigInt e = decode_le(msg, msg_len);
162
163
0
   e = m_group.mod_order(e);
164
0
   if(e.is_zero())
165
0
      e = BigInt::one();
166
167
0
   const BigInt r = m_group.mod_order(
168
0
      m_group.blinded_base_point_multiply_x(k, rng, m_ws));
169
170
0
   const BigInt s = m_group.mod_order(
171
0
      m_group.multiply_mod_order(r, m_x) +
172
0
      m_group.multiply_mod_order(k, e));
173
174
0
   if(r == 0 || s == 0)
175
0
      throw Internal_Error("GOST 34.10 signature generation failed, r/s equal to zero");
176
177
0
   return BigInt::encode_fixed_length_int_pair(s, r, m_group.get_order_bytes());
178
0
   }
179
180
/**
181
* GOST-34.10 verification operation
182
*/
183
class GOST_3410_Verification_Operation final : public PK_Ops::Verification_with_EMSA
184
   {
185
   public:
186
187
      GOST_3410_Verification_Operation(const GOST_3410_PublicKey& gost,
188
                                       const std::string& emsa) :
189
         PK_Ops::Verification_with_EMSA(emsa),
190
         m_group(gost.domain()),
191
         m_gy_mul(m_group.get_base_point(), gost.public_point())
192
0
         {}
193
194
0
      size_t max_input_bits() const override { return m_group.get_order_bits(); }
195
196
0
      bool with_recovery() const override { return false; }
197
198
      bool verify(const uint8_t msg[], size_t msg_len,
199
                  const uint8_t sig[], size_t sig_len) override;
200
   private:
201
      const EC_Group m_group;
202
      const PointGFp_Multi_Point_Precompute m_gy_mul;
203
   };
204
205
bool GOST_3410_Verification_Operation::verify(const uint8_t msg[], size_t msg_len,
206
                                              const uint8_t sig[], size_t sig_len)
207
0
   {
208
0
   if(sig_len != m_group.get_order_bytes() * 2)
209
0
      return false;
210
211
0
   const BigInt s(sig, sig_len / 2);
212
0
   const BigInt r(sig + sig_len / 2, sig_len / 2);
213
214
0
   const BigInt& order = m_group.get_order();
215
216
0
   if(r <= 0 || r >= order || s <= 0 || s >= order)
217
0
      return false;
218
219
0
   BigInt e = decode_le(msg, msg_len);
220
0
   e = m_group.mod_order(e);
221
0
   if(e.is_zero())
222
0
      e = BigInt::one();
223
224
0
   const BigInt v = m_group.inverse_mod_order(e);
225
226
0
   const BigInt z1 = m_group.multiply_mod_order(s, v);
227
0
   const BigInt z2 = m_group.multiply_mod_order(-r, v);
228
229
0
   const PointGFp R = m_gy_mul.multi_exp(z1, z2);
230
231
0
   if(R.is_zero())
232
0
     return false;
233
234
0
   return (R.get_affine_x() == r);
235
0
   }
236
237
}
238
239
std::unique_ptr<PK_Ops::Verification>
240
GOST_3410_PublicKey::create_verification_op(const std::string& params,
241
                                            const std::string& provider) const
242
0
   {
243
0
   if(provider == "base" || provider.empty())
244
0
      return std::make_unique<GOST_3410_Verification_Operation>(*this, params);
245
0
   throw Provider_Not_Found(algo_name(), provider);
246
0
   }
247
248
std::unique_ptr<PK_Ops::Signature>
249
GOST_3410_PrivateKey::create_signature_op(RandomNumberGenerator& /*rng*/,
250
                                          const std::string& params,
251
                                          const std::string& provider) const
252
0
   {
253
0
   if(provider == "base" || provider.empty())
254
0
      return std::make_unique<GOST_3410_Signature_Operation>(*this, params);
255
0
   throw Provider_Not_Found(algo_name(), provider);
256
0
   }
257
258
}