Botan  2.13.0
Crypto and TLS for C++11
gost_3410.cpp
Go to the documentation of this file.
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  {
21  const BigInt x = public_point().get_affine_x();
22  const BigInt y = public_point().get_affine_y();
23 
24  size_t part_size = std::max(x.bytes(), y.bytes());
25 
26  std::vector<uint8_t> bits(2*part_size);
27 
28  x.binary_encode(&bits[part_size - x.bytes()]);
29  y.binary_encode(&bits[2*part_size - y.bytes()]);
30 
31  // Keys are stored in little endian format (WTF)
32  for(size_t i = 0; i != part_size / 2; ++i)
33  {
34  std::swap(bits[i], bits[part_size-1-i]);
35  std::swap(bits[part_size+i], bits[2*part_size-1-i]);
36  }
37 
38  std::vector<uint8_t> output;
39  DER_Encoder(output).encode(bits, OCTET_STRING);
40  return output;
41  }
42 
43 std::string GOST_3410_PublicKey::algo_name() const
44  {
45  const size_t p_bits = domain().get_p_bits();
46 
47  if(p_bits == 256 || p_bits == 512)
48  return "GOST-34.10-2012-" + std::to_string(p_bits);
49  else
50  throw Encoding_Error("GOST-34.10-2012 is not defined for parameters of this size");
51  }
52 
54  {
55  std::vector<uint8_t> params;
56 
57  DER_Encoder(params)
59  .encode(domain().get_curve_oid())
60  .end_cons();
61 
62  return AlgorithmIdentifier(get_oid(), params);
63  }
64 
66  const std::vector<uint8_t>& key_bits)
67  {
68  OID ecc_param_id;
69 
70  // The parameters also includes hash and cipher OIDs
71  BER_Decoder(alg_id.get_parameters()).start_cons(SEQUENCE).decode(ecc_param_id);
72 
73  m_domain_params = EC_Group(ecc_param_id);
74 
75  const size_t p_bits = m_domain_params.get_p_bits();
76  if(p_bits != 256 && p_bits != 512)
77  throw Decoding_Error("GOST-34.10-2012 is not defined for parameters of size " +
78  std::to_string(p_bits));
79 
81  BER_Decoder(key_bits).decode(bits, OCTET_STRING);
82 
83  const size_t part_size = bits.size() / 2;
84 
85  // Keys are stored in little endian format (WTF)
86  for(size_t i = 0; i != part_size / 2; ++i)
87  {
88  std::swap(bits[i], bits[part_size-1-i]);
89  std::swap(bits[part_size+i], bits[2*part_size-1-i]);
90  }
91 
92  BigInt x(bits.data(), part_size);
93  BigInt y(&bits[part_size], part_size);
94 
95  m_public_key = domain().point(x, y);
96 
98  "Loaded GOST 34.10 public key is on the curve");
99  }
100 
102  const EC_Group& domain,
103  const BigInt& x) :
104  EC_PrivateKey(rng, domain, x)
105  {
106  const size_t p_bits = m_domain_params.get_p_bits();
107  if(p_bits != 256 && p_bits != 512)
108  throw Decoding_Error("GOST-34.10-2012 is not defined for parameters of size " +
109  std::to_string(p_bits));
110  }
111 
112 namespace {
113 
114 BigInt decode_le(const uint8_t msg[], size_t msg_len)
115  {
116  secure_vector<uint8_t> msg_le(msg, msg + msg_len);
117 
118  for(size_t i = 0; i != msg_le.size() / 2; ++i)
119  std::swap(msg_le[i], msg_le[msg_le.size()-1-i]);
120 
121  return BigInt(msg_le.data(), msg_le.size());
122  }
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  {}
136 
137  size_t signature_length() const override { return 2*m_group.get_order_bytes(); }
138 
139  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  {
154  const BigInt k = m_group.random_scalar(rng);
155 
156  BigInt e = decode_le(msg, msg_len);
157 
158  e = m_group.mod_order(e);
159  if(e == 0)
160  e = 1;
161 
162  const BigInt r = m_group.mod_order(
163  m_group.blinded_base_point_multiply_x(k, rng, m_ws));
164 
165  const BigInt s = m_group.mod_order(
166  m_group.multiply_mod_order(r, m_x) +
167  m_group.multiply_mod_order(k, e));
168 
169  if(r == 0 || s == 0)
170  throw Internal_Error("GOST 34.10 signature generation failed, r/s equal to zero");
171 
172  return BigInt::encode_fixed_length_int_pair(s, r, m_group.get_order_bytes());
173  }
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  {}
188 
189  size_t max_input_bits() const override { return m_group.get_order_bits(); }
190 
191  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  {
203  if(sig_len != m_group.get_order_bytes() * 2)
204  return false;
205 
206  const BigInt s(sig, sig_len / 2);
207  const BigInt r(sig + sig_len / 2, sig_len / 2);
208 
209  const BigInt& order = m_group.get_order();
210 
211  if(r <= 0 || r >= order || s <= 0 || s >= order)
212  return false;
213 
214  BigInt e = decode_le(msg, msg_len);
215  e = m_group.mod_order(e);
216  if(e == 0)
217  e = 1;
218 
219  const BigInt v = m_group.inverse_mod_order(e);
220 
221  const BigInt z1 = m_group.multiply_mod_order(s, v);
222  const BigInt z2 = m_group.multiply_mod_order(-r, v);
223 
224  const PointGFp R = m_gy_mul.multi_exp(z1, z2);
225 
226  if(R.is_zero())
227  return false;
228 
229  return (R.get_affine_x() == r);
230  }
231 
232 }
233 
234 std::unique_ptr<PK_Ops::Verification>
236  const std::string& provider) const
237  {
238  if(provider == "base" || provider.empty())
239  return std::unique_ptr<PK_Ops::Verification>(new GOST_3410_Verification_Operation(*this, params));
240  throw Provider_Not_Found(algo_name(), provider);
241  }
242 
243 std::unique_ptr<PK_Ops::Signature>
245  const std::string& params,
246  const std::string& provider) const
247  {
248  if(provider == "base" || provider.empty())
249  return std::unique_ptr<PK_Ops::Signature>(new GOST_3410_Signature_Operation(*this, params));
250  throw Provider_Not_Found(algo_name(), provider);
251  }
252 
253 }
PointGFp point(const BigInt &x, const BigInt &y) const
Definition: ec_group.cpp:542
PointGFp multi_exp(const BigInt &k1, const BigInt &k2) const
Definition: point_mul.cpp:379
size_t get_p_bits() const
Definition: ec_group.cpp:438
const PointGFp & public_point() const
Definition: ecc_key.h:57
int(* final)(unsigned char *, CTX *)
PointGFp m_public_key
Definition: ecc_key.h:115
std::string to_string(const BER_Object &obj)
Definition: asn1_obj.cpp:213
void binary_encode(uint8_t buf[]) const
Definition: bigint.cpp:391
DER_Encoder & end_cons()
Definition: der_enc.cpp:191
BER_Decoder & decode(bool &out)
Definition: ber_dec.h:170
BigInt get_affine_x() const
Definition: point_gfp.cpp:499
std::unique_ptr< PK_Ops::Signature > create_signature_op(RandomNumberGenerator &rng, const std::string &params, const std::string &provider) const override
Definition: gost_3410.cpp:244
BigInt get_affine_y() const
Definition: point_gfp.cpp:518
#define BOTAN_ASSERT(expr, assertion_made)
Definition: assert.h:55
std::vector< uint8_t > public_key_bits() const override
Definition: gost_3410.cpp:19
DER_Encoder & encode(bool b)
Definition: der_enc.cpp:285
virtual OID get_oid() const
Definition: pk_keys.cpp:53
const EC_Group & domain() const
Definition: ecc_key.h:72
Definition: alg_id.cpp:13
size_t bytes() const
Definition: bigint.cpp:273
const std::vector< uint8_t > & get_parameters() const
Definition: alg_id.h:38
bool on_the_curve() const
Definition: point_gfp.cpp:538
std::string algo_name() const override
Definition: gost_3410.cpp:43
AlgorithmIdentifier algorithm_identifier() const override
Definition: gost_3410.cpp:53
DER_Encoder & start_cons(ASN1_Tag type_tag, ASN1_Tag class_tag=UNIVERSAL)
Definition: der_enc.cpp:181
std::unique_ptr< PK_Ops::Verification > create_verification_op(const std::string &params, const std::string &provider) const override
Definition: gost_3410.cpp:235
std::vector< T, secure_allocator< T > > secure_vector
Definition: secmem.h:65
static secure_vector< uint8_t > encode_fixed_length_int_pair(const BigInt &n1, const BigInt &n2, size_t bytes)
Definition: big_code.cpp:133
EC_Group m_domain_params
Definition: ecc_key.h:114
GOST_3410_PrivateKey(const AlgorithmIdentifier &alg_id, const secure_vector< uint8_t > &key_bits)
Definition: gost_3410.h:79