Botan 3.4.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
12#include <botan/ber_dec.h>
13#include <botan/der_enc.h>
14#include <botan/reducer.h>
15#include <botan/internal/fmt.h>
16#include <botan/internal/pk_ops_impl.h>
17#include <botan/internal/point_mul.h>
18
19namespace Botan {
20
21std::vector<uint8_t> GOST_3410_PublicKey::public_key_bits() const {
22 const BigInt x = public_point().get_affine_x();
23 const BigInt y = public_point().get_affine_y();
24
25 const size_t part_size = domain().get_p_bytes();
26
27 std::vector<uint8_t> bits(2 * part_size);
28
29 x.binary_encode(&bits[part_size - x.bytes()]);
30 y.binary_encode(&bits[2 * part_size - y.bytes()]);
31
32 // Keys are stored in little endian format (WTF)
33 for(size_t i = 0; i != part_size / 2; ++i) {
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
43std::string GOST_3410_PublicKey::algo_name() const {
44 const size_t p_bits = domain().get_p_bits();
45
46 if(p_bits == 256 || p_bits == 512) {
47 return fmt("GOST-34.10-2012-{}", p_bits);
48 } else {
49 throw Encoding_Error("GOST-34.10-2012 is not defined for parameters of this size");
50 }
51}
52
54 std::vector<uint8_t> params;
55
56 const OID gost_oid = object_identifier();
57 const OID domain_oid = domain().get_curve_oid();
58
59 DER_Encoder(params).start_sequence().encode(domain_oid).end_cons();
60
61 return AlgorithmIdentifier(gost_oid, params);
62}
63
64GOST_3410_PublicKey::GOST_3410_PublicKey(const AlgorithmIdentifier& alg_id, std::span<const uint8_t> key_bits) {
65 OID ecc_param_id;
66
67 // The parameters also includes hash and cipher OIDs
68 BER_Decoder(alg_id.parameters()).start_sequence().decode(ecc_param_id);
69
70 m_domain_params = EC_Group(ecc_param_id);
71
72 const size_t p_bits = m_domain_params.get_p_bits();
73 if(p_bits != 256 && p_bits != 512) {
74 throw Decoding_Error(fmt("GOST-34.10-2012 is not defined for parameters of size {}", p_bits));
75 }
76
79
80 if(bits.size() != 2 * (p_bits / 8)) {
81 throw Decoding_Error("GOST-34.10-2020 invalid encoding of public key");
82 }
83
84 const size_t part_size = bits.size() / 2;
85
86 // Keys are stored in little endian format (WTF)
87 for(size_t i = 0; i != part_size / 2; ++i) {
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
97 BOTAN_ASSERT(m_public_key.on_the_curve(), "Loaded GOST 34.10 public key is on the curve");
98}
99
101 EC_PrivateKey(rng, domain, x) {
102 const size_t p_bits = m_domain_params.get_p_bits();
103 if(p_bits != 256 && p_bits != 512) {
104 throw Decoding_Error(fmt("GOST-34.10-2012 is not defined for parameters of size {}", p_bits));
105 }
106}
107
108std::unique_ptr<Public_Key> GOST_3410_PrivateKey::public_key() const {
109 return std::make_unique<GOST_3410_PublicKey>(domain(), public_point());
110}
111
112namespace {
113
114BigInt decode_le(const uint8_t msg[], size_t msg_len) {
115 secure_vector<uint8_t> msg_le(msg, msg + msg_len);
116
117 for(size_t i = 0; i != msg_le.size() / 2; ++i) {
118 std::swap(msg_le[i], msg_le[msg_le.size() - 1 - i]);
119 }
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_Hash {
128 public:
129 GOST_3410_Signature_Operation(const GOST_3410_PrivateKey& gost_3410, std::string_view emsa) :
130 PK_Ops::Signature_with_Hash(emsa), m_group(gost_3410.domain()), m_x(gost_3410.private_value()) {}
131
132 size_t signature_length() const override { return 2 * m_group.get_order_bytes(); }
133
134 AlgorithmIdentifier algorithm_identifier() const override;
135
136 secure_vector<uint8_t> raw_sign(const uint8_t msg[], size_t msg_len, RandomNumberGenerator& rng) override;
137
138 private:
139 const EC_Group m_group;
140 const BigInt m_x;
141 std::vector<BigInt> m_ws;
142};
143
144AlgorithmIdentifier GOST_3410_Signature_Operation::algorithm_identifier() const {
145 const std::string hash_fn = hash_function();
146
147 const size_t p_bits = m_group.get_p_bits();
148
149 std::string oid_name;
150 if(hash_fn == "GOST-R-34.11-94") {
151 oid_name = "GOST-34.10/GOST-R-34.11-94";
152 } else if(hash_fn == "Streebog-256" && p_bits == 256) {
153 oid_name = "GOST-34.10-2012-256/Streebog-256";
154 } else if(hash_fn == "Streebog-512" && p_bits == 512) {
155 oid_name = "GOST-34.10-2012-512/Streebog-512";
156 } else if(hash_fn == "SHA-256" && p_bits == 256) {
157 oid_name = "GOST-34.10-2012-256/SHA-256";
158 }
159
160 if(oid_name.empty()) {
161 throw Not_Implemented("No encoding defined for GOST with " + hash_fn);
162 }
163
164 return AlgorithmIdentifier(oid_name, AlgorithmIdentifier::USE_EMPTY_PARAM);
165}
166
167secure_vector<uint8_t> GOST_3410_Signature_Operation::raw_sign(const uint8_t msg[],
168 size_t msg_len,
169 RandomNumberGenerator& rng) {
170 const BigInt k = m_group.random_scalar(rng);
171
172 BigInt e = decode_le(msg, msg_len);
173
174 e = m_group.mod_order(e);
175 if(e.is_zero()) {
176 e = BigInt::one();
177 }
178
179 const BigInt r = m_group.mod_order(m_group.blinded_base_point_multiply_x(k, rng, m_ws));
180
181 const BigInt s = m_group.mod_order(m_group.multiply_mod_order(r, m_x) + m_group.multiply_mod_order(k, e));
182
183 if(r == 0 || s == 0) {
184 throw Internal_Error("GOST 34.10 signature generation failed, r/s equal to zero");
185 }
186
187 return BigInt::encode_fixed_length_int_pair(s, r, m_group.get_order_bytes());
188}
189
190std::string gost_hash_from_algid(const AlgorithmIdentifier& alg_id) {
191 if(!alg_id.parameters_are_empty()) {
192 throw Decoding_Error("Unexpected non-empty AlgorithmIdentifier parameters for GOST 34.10 signature");
193 }
194
195 const std::string oid_str = alg_id.oid().to_formatted_string();
196 if(oid_str == "GOST-34.10/GOST-R-34.11-94") {
197 return "GOST-R-34.11-94";
198 }
199 if(oid_str == "GOST-34.10-2012-256/Streebog-256") {
200 return "Streebog-256";
201 }
202 if(oid_str == "GOST-34.10-2012-512/Streebog-512") {
203 return "Streebog-512";
204 }
205 if(oid_str == "GOST-34.10-2012-256/SHA-256") {
206 return "SHA-256";
207 }
208
209 throw Decoding_Error(fmt("Unknown OID ({}) for GOST 34.10 signatures", alg_id.oid()));
210}
211
212/**
213* GOST-34.10 verification operation
214*/
215class GOST_3410_Verification_Operation final : public PK_Ops::Verification_with_Hash {
216 public:
217 GOST_3410_Verification_Operation(const GOST_3410_PublicKey& gost, std::string_view padding) :
218 PK_Ops::Verification_with_Hash(padding),
219 m_group(gost.domain()),
220 m_gy_mul(m_group.get_base_point(), gost.public_point()) {}
221
222 GOST_3410_Verification_Operation(const GOST_3410_PublicKey& gost, const AlgorithmIdentifier& alg_id) :
223 PK_Ops::Verification_with_Hash(gost_hash_from_algid(alg_id)),
224 m_group(gost.domain()),
225 m_gy_mul(m_group.get_base_point(), gost.public_point()) {}
226
227 bool verify(const uint8_t msg[], size_t msg_len, const uint8_t sig[], size_t sig_len) override;
228
229 private:
230 const EC_Group m_group;
231 const EC_Point_Multi_Point_Precompute m_gy_mul;
232};
233
234bool GOST_3410_Verification_Operation::verify(const uint8_t msg[],
235 size_t msg_len,
236 const uint8_t sig[],
237 size_t sig_len) {
238 if(sig_len != m_group.get_order_bytes() * 2) {
239 return false;
240 }
241
242 const BigInt s(sig, sig_len / 2);
243 const BigInt r(sig + sig_len / 2, sig_len / 2);
244
245 const BigInt& order = m_group.get_order();
246
247 if(r <= 0 || r >= order || s <= 0 || s >= order) {
248 return false;
249 }
250
251 BigInt e = decode_le(msg, msg_len);
252 e = m_group.mod_order(e);
253 if(e.is_zero()) {
254 e = BigInt::one();
255 }
256
257 const BigInt v = m_group.inverse_mod_order(e);
258
259 const BigInt z1 = m_group.multiply_mod_order(s, v);
260 const BigInt z2 = m_group.multiply_mod_order(-r, v);
261
262 const EC_Point R = m_gy_mul.multi_exp(z1, z2);
263
264 if(R.is_zero()) {
265 return false;
266 }
267
268 return (R.get_affine_x() == r);
269}
270
271} // namespace
272
273std::unique_ptr<Private_Key> GOST_3410_PublicKey::generate_another(RandomNumberGenerator& rng) const {
274 return std::make_unique<GOST_3410_PrivateKey>(rng, domain());
275}
276
277std::unique_ptr<PK_Ops::Verification> GOST_3410_PublicKey::create_verification_op(std::string_view params,
278 std::string_view provider) const {
279 if(provider == "base" || provider.empty()) {
280 return std::make_unique<GOST_3410_Verification_Operation>(*this, params);
281 }
282 throw Provider_Not_Found(algo_name(), provider);
283}
284
285std::unique_ptr<PK_Ops::Verification> GOST_3410_PublicKey::create_x509_verification_op(
286 const AlgorithmIdentifier& signature_algorithm, std::string_view provider) const {
287 if(provider == "base" || provider.empty()) {
288 return std::make_unique<GOST_3410_Verification_Operation>(*this, signature_algorithm);
289 }
290
291 throw Provider_Not_Found(algo_name(), provider);
292}
293
294std::unique_ptr<PK_Ops::Signature> GOST_3410_PrivateKey::create_signature_op(RandomNumberGenerator& /*rng*/,
295 std::string_view params,
296 std::string_view provider) const {
297 if(provider == "base" || provider.empty()) {
298 return std::make_unique<GOST_3410_Signature_Operation>(*this, params);
299 }
300 throw Provider_Not_Found(algo_name(), provider);
301}
302
303} // namespace Botan
#define BOTAN_ASSERT(expr, assertion_made)
Definition assert.h:50
const std::vector< uint8_t > & parameters() const
Definition asn1_obj.h:457
virtual OID object_identifier() const
Definition pk_keys.cpp:22
BER_Decoder & decode(bool &out)
Definition ber_dec.h:176
BER_Decoder start_sequence()
Definition ber_dec.h:113
void binary_encode(uint8_t buf[]) const
Definition bigint.cpp:375
size_t bytes() const
Definition bigint.cpp:277
DER_Encoder & start_sequence()
Definition der_enc.h:65
DER_Encoder & end_cons()
Definition der_enc.cpp:171
DER_Encoder & encode(bool b)
Definition der_enc.cpp:250
BigInt blinded_base_point_multiply_x(const BigInt &k, RandomNumberGenerator &rng, std::vector< BigInt > &ws) const
Definition ec_group.cpp:581
BigInt mod_order(const BigInt &x) const
Definition ec_group.cpp:524
BigInt multiply_mod_order(const BigInt &x, const BigInt &y) const
Definition ec_group.cpp:532
const BigInt & get_order() const
Definition ec_group.cpp:508
size_t get_p_bits() const
Definition ec_group.cpp:476
EC_Point point(const BigInt &x, const BigInt &y) const
Definition ec_group.cpp:565
const OID & get_curve_oid() const
Definition ec_group.cpp:544
BigInt inverse_mod_order(const BigInt &x) const
Definition ec_group.cpp:540
size_t get_p_bytes() const
Definition ec_group.cpp:480
BigInt random_scalar(RandomNumberGenerator &rng) const
Definition ec_group.cpp:592
size_t get_order_bytes() const
Definition ec_group.cpp:488
EC_Point multi_exp(const BigInt &k1, const BigInt &k2) const
BigInt get_affine_x() const
Definition ec_point.cpp:469
bool on_the_curve() const
Definition ec_point.cpp:510
BigInt get_affine_y() const
Definition ec_point.cpp:489
const EC_Group & domain() const
Definition ecc_key.h:54
EC_Group m_domain_params
Definition ecc_key.h:108
EC_Point m_public_key
Definition ecc_key.h:109
const EC_Point & public_point() const
Definition ecc_key.h:40
std::unique_ptr< PK_Ops::Signature > create_signature_op(RandomNumberGenerator &rng, std::string_view params, std::string_view provider) const override
std::unique_ptr< Public_Key > public_key() const override
GOST_3410_PrivateKey(const AlgorithmIdentifier &alg_id, std::span< const uint8_t > key_bits)
Definition gost_3410.h:82
AlgorithmIdentifier algorithm_identifier() const override
Definition gost_3410.cpp:53
std::string algo_name() const override
Definition gost_3410.cpp:43
std::unique_ptr< PK_Ops::Verification > create_x509_verification_op(const AlgorithmIdentifier &signature_algorithm, std::string_view provider) const override
std::unique_ptr< PK_Ops::Verification > create_verification_op(std::string_view params, std::string_view provider) const override
std::unique_ptr< Private_Key > generate_another(RandomNumberGenerator &rng) const final
std::vector< uint8_t > public_key_bits() const override
Definition gost_3410.cpp:21
int(* final)(unsigned char *, CTX *)
std::string fmt(std::string_view format, const T &... args)
Definition fmt.h:53
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:61