Botan 2.19.0
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;
39 DER_Encoder(output).encode(bits, OCTET_STRING);
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_cons(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_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
112namespace {
113
114BigInt 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*/
127class 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
150secure_vector<uint8_t>
151GOST_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*/
178class 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
200bool 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
234std::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
243std::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}
#define BOTAN_ASSERT(expr, assertion_made)
Definition: assert.h:55
const std::vector< uint8_t > & get_parameters() const
Definition: asn1_obj.h:446
BER_Decoder start_cons(ASN1_Tag type_tag, ASN1_Tag class_tag=UNIVERSAL)
Definition: ber_dec.cpp:290
BER_Decoder & decode(bool &out)
Definition: ber_dec.h:170
void binary_encode(uint8_t buf[]) const
Definition: bigint.cpp:399
static secure_vector< uint8_t > encode_fixed_length_int_pair(const BigInt &n1, const BigInt &n2, size_t bytes)
Definition: big_code.cpp:133
size_t bytes() const
Definition: bigint.cpp:281
DER_Encoder & start_cons(ASN1_Tag type_tag, ASN1_Tag class_tag=UNIVERSAL)
Definition: der_enc.cpp:181
DER_Encoder & end_cons()
Definition: der_enc.cpp:191
DER_Encoder & encode(bool b)
Definition: der_enc.cpp:285
PointGFp point(const BigInt &x, const BigInt &y) const
Definition: ec_group.cpp:578
size_t get_p_bits() const
Definition: ec_group.cpp:469
const OID & get_curve_oid() const
Definition: ec_group.cpp:554
const EC_Group & domain() const
Definition: ecc_key.h:72
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:57
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:244
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:235
PointGFp multi_exp(const BigInt &k1, const BigInt &k2) const
Definition: point_mul.cpp:394
bool on_the_curve() const
Definition: point_gfp.cpp:544
BigInt get_affine_y() const
Definition: point_gfp.cpp:524
BigInt get_affine_x() const
Definition: point_gfp.cpp:505
virtual OID get_oid() const
Definition: pk_keys.cpp:53
int(* final)(unsigned char *, CTX *)
std::string to_string(const BER_Object &obj)
Definition: asn1_obj.cpp:213
Definition: alg_id.cpp:13
@ SEQUENCE
Definition: asn1_obj.h:42
@ OCTET_STRING
Definition: asn1_obj.h:38
std::vector< T, secure_allocator< T > > secure_vector
Definition: secmem.h:65