Botan 3.0.0-alpha0
Crypto and TLS for C&
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
17namespace Botan {
18
19std::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;
40 return output;
41 }
42
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 const OID gost_oid = get_oid();
58 const OID domain_oid = domain().get_curve_oid();
59
60 DER_Encoder(params).start_sequence().encode(domain_oid).end_cons();
61
62 return AlgorithmIdentifier(gost_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_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
82
83 if(bits.size() != 2*(p_bits/8))
84 throw Decoding_Error("GOST-34.10-2020 invalid encoding of public key");
85
86 const size_t part_size = bits.size() / 2;
87
88 // Keys are stored in little endian format (WTF)
89 for(size_t i = 0; i != part_size / 2; ++i)
90 {
91 std::swap(bits[i], bits[part_size-1-i]);
92 std::swap(bits[part_size+i], bits[2*part_size-1-i]);
93 }
94
95 BigInt x(bits.data(), part_size);
96 BigInt y(&bits[part_size], part_size);
97
98 m_public_key = domain().point(x, y);
99
101 "Loaded GOST 34.10 public key is on the curve");
102 }
103
105 const EC_Group& domain,
106 const BigInt& x) :
107 EC_PrivateKey(rng, domain, x)
108 {
109 const size_t p_bits = m_domain_params.get_p_bits();
110 if(p_bits != 256 && p_bits != 512)
111 throw Decoding_Error("GOST-34.10-2012 is not defined for parameters of size " +
112 std::to_string(p_bits));
113 }
114
115std::unique_ptr<Public_Key> GOST_3410_PrivateKey::public_key() const
116 {
117 return std::make_unique<GOST_3410_PublicKey>(domain(), public_point());
118 }
119
120namespace {
121
122BigInt decode_le(const uint8_t msg[], size_t msg_len)
123 {
124 secure_vector<uint8_t> msg_le(msg, msg + msg_len);
125
126 for(size_t i = 0; i != msg_le.size() / 2; ++i)
127 std::swap(msg_le[i], msg_le[msg_le.size()-1-i]);
128
129 return BigInt(msg_le.data(), msg_le.size());
130 }
131
132/**
133* GOST-34.10 signature operation
134*/
135class 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 {}
144
145 size_t signature_length() const override { return 2*m_group.get_order_bytes(); }
146
147 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
158secure_vector<uint8_t>
159GOST_3410_Signature_Operation::raw_sign(const uint8_t msg[], size_t msg_len,
160 RandomNumberGenerator& rng)
161 {
162 const BigInt k = m_group.random_scalar(rng);
163
164 BigInt e = decode_le(msg, msg_len);
165
166 e = m_group.mod_order(e);
167 if(e.is_zero())
168 e = BigInt::one();
169
170 const BigInt r = m_group.mod_order(
171 m_group.blinded_base_point_multiply_x(k, rng, m_ws));
172
173 const BigInt s = m_group.mod_order(
174 m_group.multiply_mod_order(r, m_x) +
175 m_group.multiply_mod_order(k, e));
176
177 if(r == 0 || s == 0)
178 throw Internal_Error("GOST 34.10 signature generation failed, r/s equal to zero");
179
180 return BigInt::encode_fixed_length_int_pair(s, r, m_group.get_order_bytes());
181 }
182
183/**
184* GOST-34.10 verification operation
185*/
186class 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 {}
196
197 size_t max_input_bits() const override { return m_group.get_order_bits(); }
198
199 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
208bool GOST_3410_Verification_Operation::verify(const uint8_t msg[], size_t msg_len,
209 const uint8_t sig[], size_t sig_len)
210 {
211 if(sig_len != m_group.get_order_bytes() * 2)
212 return false;
213
214 const BigInt s(sig, sig_len / 2);
215 const BigInt r(sig + sig_len / 2, sig_len / 2);
216
217 const BigInt& order = m_group.get_order();
218
219 if(r <= 0 || r >= order || s <= 0 || s >= order)
220 return false;
221
222 BigInt e = decode_le(msg, msg_len);
223 e = m_group.mod_order(e);
224 if(e.is_zero())
225 e = BigInt::one();
226
227 const BigInt v = m_group.inverse_mod_order(e);
228
229 const BigInt z1 = m_group.multiply_mod_order(s, v);
230 const BigInt z2 = m_group.multiply_mod_order(-r, v);
231
232 const PointGFp R = m_gy_mul.multi_exp(z1, z2);
233
234 if(R.is_zero())
235 return false;
236
237 return (R.get_affine_x() == r);
238 }
239
240}
241
242std::unique_ptr<PK_Ops::Verification>
244 const std::string& provider) const
245 {
246 if(provider == "base" || provider.empty())
247 return std::make_unique<GOST_3410_Verification_Operation>(*this, params);
248 throw Provider_Not_Found(algo_name(), provider);
249 }
250
251std::unique_ptr<PK_Ops::Signature>
253 const std::string& params,
254 const std::string& provider) const
255 {
256 if(provider == "base" || provider.empty())
257 return std::make_unique<GOST_3410_Signature_Operation>(*this, params);
258 throw Provider_Not_Found(algo_name(), provider);
259 }
260
261}
#define BOTAN_ASSERT(expr, assertion_made)
Definition: assert.h:54
const std::vector< uint8_t > & get_parameters() const
Definition: asn1_obj.h:448
BER_Decoder & decode(bool &out)
Definition: ber_dec.h:187
BER_Decoder start_sequence()
Definition: ber_dec.h:111
void binary_encode(uint8_t buf[]) const
Definition: bigint.cpp:395
static BigInt one()
Definition: bigint.h:50
static secure_vector< uint8_t > encode_fixed_length_int_pair(const BigInt &n1, const BigInt &n2, size_t bytes)
Definition: big_code.cpp:128
size_t bytes() const
Definition: bigint.cpp:294
DER_Encoder & start_sequence()
Definition: der_enc.h:66
DER_Encoder & end_cons()
Definition: der_enc.cpp:194
DER_Encoder & encode(bool b)
Definition: der_enc.cpp:288
PointGFp point(const BigInt &x, const BigInt &y) const
Definition: ec_group.cpp:618
size_t get_p_bits() const
Definition: ec_group.cpp:509
const OID & get_curve_oid() const
Definition: ec_group.cpp:594
const EC_Group & domain() const
Definition: ecc_key.h:56
PointGFp m_public_key
Definition: ecc_key.h:115
EC_Group m_domain_params
Definition: ecc_key.h:114
const PointGFp & public_point() const
Definition: ecc_key.h:41
std::unique_ptr< Public_Key > public_key() const override
Definition: gost_3410.cpp:115
GOST_3410_PrivateKey(const AlgorithmIdentifier &alg_id, const secure_vector< uint8_t > &key_bits)
Definition: gost_3410.h:79
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:252
AlgorithmIdentifier algorithm_identifier() const override
Definition: gost_3410.cpp:53
std::string algo_name() const override
Definition: gost_3410.cpp:43
std::vector< uint8_t > public_key_bits() const override
Definition: gost_3410.cpp:19
std::unique_ptr< PK_Ops::Verification > create_verification_op(const std::string &params, const std::string &provider) const override
Definition: gost_3410.cpp:243
PointGFp multi_exp(const BigInt &k1, const BigInt &k2) const
Definition: point_mul.cpp:377
bool on_the_curve() const
Definition: point_gfp.cpp:543
BigInt get_affine_y() const
Definition: point_gfp.cpp:523
BigInt get_affine_x() const
Definition: point_gfp.cpp:504
virtual OID get_oid() const
Definition: pk_keys.cpp:53
int(* final)(unsigned char *, CTX *)
Polynomial v
Definition: kyber.cpp:822
std::string to_string(const BER_Object &obj)
Definition: asn1_obj.cpp:209
Definition: alg_id.cpp:13
std::vector< T, secure_allocator< T > > secure_vector
Definition: secmem.h:65