Coverage Report

Created: 2022-09-23 06:05

/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
76
   {
45
76
   const size_t p_bits = domain().get_p_bits();
46
47
76
   if(p_bits == 256 || p_bits == 512)
48
76
      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
76
   }
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
90
   {
68
90
   OID ecc_param_id;
69
70
   // The parameters also includes hash and cipher OIDs
71
90
   BER_Decoder(alg_id.get_parameters()).start_sequence().decode(ecc_param_id);
72
73
90
   m_domain_params = EC_Group(ecc_param_id);
74
75
90
   const size_t p_bits = m_domain_params.get_p_bits();
76
90
   if(p_bits != 256 && p_bits != 512)
77
3
      throw Decoding_Error("GOST-34.10-2012 is not defined for parameters of size " +
78
3
                           std::to_string(p_bits));
79
80
87
   secure_vector<uint8_t> bits;
81
87
   BER_Decoder(key_bits).decode(bits, ASN1_Type::OctetString);
82
83
87
   if(bits.size() != 2*(p_bits/8))
84
3
      throw Decoding_Error("GOST-34.10-2020 invalid encoding of public key");
85
86
84
   const size_t part_size = bits.size() / 2;
87
88
   // Keys are stored in little endian format (WTF)
89
1.33k
   for(size_t i = 0; i != part_size / 2; ++i)
90
1.24k
      {
91
1.24k
      std::swap(bits[i], bits[part_size-1-i]);
92
1.24k
      std::swap(bits[part_size+i], bits[2*part_size-1-i]);
93
1.24k
      }
94
95
84
   BigInt x(bits.data(), part_size);
96
84
   BigInt y(&bits[part_size], part_size);
97
98
84
   m_public_key = domain().point(x, y);
99
100
84
   BOTAN_ASSERT(m_public_key.on_the_curve(),
101
84
                "Loaded GOST 34.10 public key is on the curve");
102
84
   }
Unexecuted instantiation: Botan::GOST_3410_PublicKey::GOST_3410_PublicKey(Botan::AlgorithmIdentifier const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> > const&)
Botan::GOST_3410_PublicKey::GOST_3410_PublicKey(Botan::AlgorithmIdentifier const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> > const&)
Line
Count
Source
67
90
   {
68
90
   OID ecc_param_id;
69
70
   // The parameters also includes hash and cipher OIDs
71
90
   BER_Decoder(alg_id.get_parameters()).start_sequence().decode(ecc_param_id);
72
73
90
   m_domain_params = EC_Group(ecc_param_id);
74
75
90
   const size_t p_bits = m_domain_params.get_p_bits();
76
90
   if(p_bits != 256 && p_bits != 512)
77
3
      throw Decoding_Error("GOST-34.10-2012 is not defined for parameters of size " +
78
3
                           std::to_string(p_bits));
79
80
87
   secure_vector<uint8_t> bits;
81
87
   BER_Decoder(key_bits).decode(bits, ASN1_Type::OctetString);
82
83
87
   if(bits.size() != 2*(p_bits/8))
84
3
      throw Decoding_Error("GOST-34.10-2020 invalid encoding of public key");
85
86
84
   const size_t part_size = bits.size() / 2;
87
88
   // Keys are stored in little endian format (WTF)
89
1.33k
   for(size_t i = 0; i != part_size / 2; ++i)
90
1.24k
      {
91
1.24k
      std::swap(bits[i], bits[part_size-1-i]);
92
1.24k
      std::swap(bits[part_size+i], bits[2*part_size-1-i]);
93
1.24k
      }
94
95
84
   BigInt x(bits.data(), part_size);
96
84
   BigInt y(&bits[part_size], part_size);
97
98
84
   m_public_key = domain().point(x, y);
99
100
84
   BOTAN_ASSERT(m_public_key.on_the_curve(),
101
84
                "Loaded GOST 34.10 public key is on the curve");
102
84
   }
103
104
GOST_3410_PrivateKey::GOST_3410_PrivateKey(RandomNumberGenerator& rng,
105
                                           const EC_Group& domain,
106
                                           const BigInt& x) :
107
   EC_PrivateKey(rng, domain, x)
108
0
   {
109
0
   const size_t p_bits = m_domain_params.get_p_bits();
110
0
   if(p_bits != 256 && p_bits != 512)
111
0
      throw Decoding_Error("GOST-34.10-2012 is not defined for parameters of size " +
112
0
                           std::to_string(p_bits));
113
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&)
114
115
std::unique_ptr<Public_Key> GOST_3410_PrivateKey::public_key() const
116
0
   {
117
0
   return std::make_unique<GOST_3410_PublicKey>(domain(), public_point());
118
0
   }
119
120
namespace {
121
122
BigInt decode_le(const uint8_t msg[], size_t msg_len)
123
69
   {
124
69
   secure_vector<uint8_t> msg_le(msg, msg + msg_len);
125
126
1.17k
   for(size_t i = 0; i != msg_le.size() / 2; ++i)
127
1.10k
      std::swap(msg_le[i], msg_le[msg_le.size()-1-i]);
128
129
69
   return BigInt(msg_le.data(), msg_le.size());
130
69
   }
131
132
/**
133
* GOST-34.10 signature operation
134
*/
135
class GOST_3410_Signature_Operation final : public PK_Ops::Signature_with_EMSA
136
   {
137
   public:
138
      GOST_3410_Signature_Operation(const GOST_3410_PrivateKey& gost_3410,
139
                                    const std::string& emsa) :
140
         PK_Ops::Signature_with_EMSA(emsa),
141
         m_group(gost_3410.domain()),
142
         m_x(gost_3410.private_value())
143
0
         {}
144
145
0
      size_t signature_length() const override { return 2*m_group.get_order_bytes(); }
146
147
0
      size_t max_input_bits() const override { return m_group.get_order_bits(); }
148
149
      secure_vector<uint8_t> raw_sign(const uint8_t msg[], size_t msg_len,
150
                                      RandomNumberGenerator& rng) override;
151
152
   private:
153
      const EC_Group m_group;
154
      const BigInt& m_x;
155
      std::vector<BigInt> m_ws;
156
   };
157
158
secure_vector<uint8_t>
159
GOST_3410_Signature_Operation::raw_sign(const uint8_t msg[], size_t msg_len,
160
                                        RandomNumberGenerator& rng)
161
0
   {
162
0
   const BigInt k = m_group.random_scalar(rng);
163
164
0
   BigInt e = decode_le(msg, msg_len);
165
166
0
   e = m_group.mod_order(e);
167
0
   if(e.is_zero())
168
0
      e = BigInt::one();
169
170
0
   const BigInt r = m_group.mod_order(
171
0
      m_group.blinded_base_point_multiply_x(k, rng, m_ws));
172
173
0
   const BigInt s = m_group.mod_order(
174
0
      m_group.multiply_mod_order(r, m_x) +
175
0
      m_group.multiply_mod_order(k, e));
176
177
0
   if(r == 0 || s == 0)
178
0
      throw Internal_Error("GOST 34.10 signature generation failed, r/s equal to zero");
179
180
0
   return BigInt::encode_fixed_length_int_pair(s, r, m_group.get_order_bytes());
181
0
   }
182
183
/**
184
* GOST-34.10 verification operation
185
*/
186
class GOST_3410_Verification_Operation final : public PK_Ops::Verification_with_EMSA
187
   {
188
   public:
189
190
      GOST_3410_Verification_Operation(const GOST_3410_PublicKey& gost,
191
                                       const std::string& emsa) :
192
         PK_Ops::Verification_with_EMSA(emsa),
193
         m_group(gost.domain()),
194
         m_gy_mul(m_group.get_base_point(), gost.public_point())
195
75
         {}
196
197
75
      size_t max_input_bits() const override { return m_group.get_order_bits(); }
198
199
75
      bool with_recovery() const override { return false; }
200
201
      bool verify(const uint8_t msg[], size_t msg_len,
202
                  const uint8_t sig[], size_t sig_len) override;
203
   private:
204
      const EC_Group m_group;
205
      const PointGFp_Multi_Point_Precompute m_gy_mul;
206
   };
207
208
bool GOST_3410_Verification_Operation::verify(const uint8_t msg[], size_t msg_len,
209
                                              const uint8_t sig[], size_t sig_len)
210
75
   {
211
75
   if(sig_len != m_group.get_order_bytes() * 2)
212
1
      return false;
213
214
74
   const BigInt s(sig, sig_len / 2);
215
74
   const BigInt r(sig + sig_len / 2, sig_len / 2);
216
217
74
   const BigInt& order = m_group.get_order();
218
219
74
   if(r <= 0 || r >= order || s <= 0 || s >= order)
220
5
      return false;
221
222
69
   BigInt e = decode_le(msg, msg_len);
223
69
   e = m_group.mod_order(e);
224
69
   if(e.is_zero())
225
0
      e = BigInt::one();
226
227
69
   const BigInt v = m_group.inverse_mod_order(e);
228
229
69
   const BigInt z1 = m_group.multiply_mod_order(s, v);
230
69
   const BigInt z2 = m_group.multiply_mod_order(-r, v);
231
232
69
   const PointGFp R = m_gy_mul.multi_exp(z1, z2);
233
234
69
   if(R.is_zero())
235
0
     return false;
236
237
69
   return (R.get_affine_x() == r);
238
69
   }
239
240
}
241
242
std::unique_ptr<PK_Ops::Verification>
243
GOST_3410_PublicKey::create_verification_op(const std::string& params,
244
                                            const std::string& provider) const
245
75
   {
246
75
   if(provider == "base" || provider.empty())
247
75
      return std::make_unique<GOST_3410_Verification_Operation>(*this, params);
248
0
   throw Provider_Not_Found(algo_name(), provider);
249
75
   }
250
251
std::unique_ptr<PK_Ops::Signature>
252
GOST_3410_PrivateKey::create_signature_op(RandomNumberGenerator& /*rng*/,
253
                                          const std::string& params,
254
                                          const std::string& provider) const
255
0
   {
256
0
   if(provider == "base" || provider.empty())
257
0
      return std::make_unique<GOST_3410_Signature_Operation>(*this, params);
258
0
   throw Provider_Not_Found(algo_name(), provider);
259
0
   }
260
261
}