Botan 3.5.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 auto bits = public_point().xy_bytes();
23
24 const size_t part_size = bits.size() / 2;
25
26 // GOST keys are stored in little endian format (WTF)
27 for(size_t i = 0; i != part_size / 2; ++i) {
28 std::swap(bits[i], bits[part_size - 1 - i]);
29 std::swap(bits[part_size + i], bits[2 * part_size - 1 - i]);
30 }
31
32 std::vector<uint8_t> output;
34 return output;
35}
36
37std::string GOST_3410_PublicKey::algo_name() const {
38 const size_t p_bits = domain().get_p_bits();
39
40 if(p_bits == 256 || p_bits == 512) {
41 return fmt("GOST-34.10-2012-{}", p_bits);
42 } else {
43 throw Encoding_Error("GOST-34.10-2012 is not defined for parameters of this size");
44 }
45}
46
48 std::vector<uint8_t> params;
49
50 const OID gost_oid = object_identifier();
51 const OID domain_oid = domain().get_curve_oid();
52
53 DER_Encoder(params).start_sequence().encode(domain_oid).end_cons();
54
55 return AlgorithmIdentifier(gost_oid, params);
56}
57
58GOST_3410_PublicKey::GOST_3410_PublicKey(const AlgorithmIdentifier& alg_id, std::span<const uint8_t> key_bits) {
59 OID ecc_param_id;
60
61 // The parameters also includes hash and cipher OIDs
62 BER_Decoder(alg_id.parameters()).start_sequence().decode(ecc_param_id);
63
64 m_domain_params = EC_Group::from_OID(ecc_param_id);
65
66 const size_t p_bits = m_domain_params.get_p_bits();
67 if(p_bits != 256 && p_bits != 512) {
68 throw Decoding_Error(fmt("GOST-34.10-2012 is not defined for parameters of size {}", p_bits));
69 }
70
73
74 if(bits.size() != 2 * (p_bits / 8)) {
75 throw Decoding_Error("GOST-34.10-2020 invalid encoding of public key");
76 }
77
78 const size_t part_size = bits.size() / 2;
79
80 // Keys are stored in little endian format (WTF)
81 for(size_t i = 0; i != part_size / 2; ++i) {
82 std::swap(bits[i], bits[part_size - 1 - i]);
83 std::swap(bits[part_size + i], bits[2 * part_size - 1 - i]);
84 }
85
86 BigInt x(bits.data(), part_size);
87 BigInt y(&bits[part_size], part_size);
88
89 m_public_key = domain().point(x, y);
90
91 BOTAN_ASSERT(m_public_key.on_the_curve(), "Loaded GOST 34.10 public key is on the curve");
92}
93
95 EC_PrivateKey(rng, domain, x) {
96 const size_t p_bits = m_domain_params.get_p_bits();
97 if(p_bits != 256 && p_bits != 512) {
98 throw Decoding_Error(fmt("GOST-34.10-2012 is not defined for parameters of size {}", p_bits));
99 }
100}
101
102std::unique_ptr<Public_Key> GOST_3410_PrivateKey::public_key() const {
103 return std::make_unique<GOST_3410_PublicKey>(domain(), public_point());
104}
105
106namespace {
107
108BigInt decode_le(const uint8_t msg[], size_t msg_len) {
109 secure_vector<uint8_t> msg_le(msg, msg + msg_len);
110
111 for(size_t i = 0; i != msg_le.size() / 2; ++i) {
112 std::swap(msg_le[i], msg_le[msg_le.size() - 1 - i]);
113 }
114
115 return BigInt(msg_le.data(), msg_le.size());
116}
117
118/**
119* GOST-34.10 signature operation
120*/
121class GOST_3410_Signature_Operation final : public PK_Ops::Signature_with_Hash {
122 public:
123 GOST_3410_Signature_Operation(const GOST_3410_PrivateKey& gost_3410, std::string_view emsa) :
124 PK_Ops::Signature_with_Hash(emsa), m_group(gost_3410.domain()), m_x(gost_3410.private_value()) {}
125
126 size_t signature_length() const override { return 2 * m_group.get_order_bytes(); }
127
128 AlgorithmIdentifier algorithm_identifier() const override;
129
130 secure_vector<uint8_t> raw_sign(const uint8_t msg[], size_t msg_len, RandomNumberGenerator& rng) override;
131
132 private:
133 const EC_Group m_group;
134 const BigInt m_x;
135 std::vector<BigInt> m_ws;
136};
137
138AlgorithmIdentifier GOST_3410_Signature_Operation::algorithm_identifier() const {
139 const std::string hash_fn = hash_function();
140
141 const size_t p_bits = m_group.get_p_bits();
142
143 std::string oid_name;
144 if(hash_fn == "GOST-R-34.11-94") {
145 oid_name = "GOST-34.10/GOST-R-34.11-94";
146 } else if(hash_fn == "Streebog-256" && p_bits == 256) {
147 oid_name = "GOST-34.10-2012-256/Streebog-256";
148 } else if(hash_fn == "Streebog-512" && p_bits == 512) {
149 oid_name = "GOST-34.10-2012-512/Streebog-512";
150 } else if(hash_fn == "SHA-256" && p_bits == 256) {
151 oid_name = "GOST-34.10-2012-256/SHA-256";
152 }
153
154 if(oid_name.empty()) {
155 throw Not_Implemented("No encoding defined for GOST with " + hash_fn);
156 }
157
158 return AlgorithmIdentifier(oid_name, AlgorithmIdentifier::USE_EMPTY_PARAM);
159}
160
161secure_vector<uint8_t> GOST_3410_Signature_Operation::raw_sign(const uint8_t msg[],
162 size_t msg_len,
163 RandomNumberGenerator& rng) {
164 const BigInt k = m_group.random_scalar(rng);
165
166 BigInt e = decode_le(msg, msg_len);
167
168 e = m_group.mod_order(e);
169 if(e.is_zero()) {
170 e = BigInt::one();
171 }
172
173 const BigInt r = m_group.mod_order(m_group.blinded_base_point_multiply_x(k, rng, m_ws));
174
175 const BigInt s = m_group.mod_order(m_group.multiply_mod_order(r, m_x) + 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
181 return BigInt::encode_fixed_length_int_pair(s, r, m_group.get_order_bytes());
182}
183
184std::string gost_hash_from_algid(const AlgorithmIdentifier& alg_id) {
185 if(!alg_id.parameters_are_empty()) {
186 throw Decoding_Error("Unexpected non-empty AlgorithmIdentifier parameters for GOST 34.10 signature");
187 }
188
189 const std::string oid_str = alg_id.oid().to_formatted_string();
190 if(oid_str == "GOST-34.10/GOST-R-34.11-94") {
191 return "GOST-R-34.11-94";
192 }
193 if(oid_str == "GOST-34.10-2012-256/Streebog-256") {
194 return "Streebog-256";
195 }
196 if(oid_str == "GOST-34.10-2012-512/Streebog-512") {
197 return "Streebog-512";
198 }
199 if(oid_str == "GOST-34.10-2012-256/SHA-256") {
200 return "SHA-256";
201 }
202
203 throw Decoding_Error(fmt("Unknown OID ({}) for GOST 34.10 signatures", alg_id.oid()));
204}
205
206/**
207* GOST-34.10 verification operation
208*/
209class GOST_3410_Verification_Operation final : public PK_Ops::Verification_with_Hash {
210 public:
211 GOST_3410_Verification_Operation(const GOST_3410_PublicKey& gost, std::string_view padding) :
212 PK_Ops::Verification_with_Hash(padding),
213 m_group(gost.domain()),
214 m_gy_mul(m_group.get_base_point(), gost.public_point()) {}
215
216 GOST_3410_Verification_Operation(const GOST_3410_PublicKey& gost, const AlgorithmIdentifier& alg_id) :
217 PK_Ops::Verification_with_Hash(gost_hash_from_algid(alg_id)),
218 m_group(gost.domain()),
219 m_gy_mul(m_group.get_base_point(), gost.public_point()) {}
220
221 bool verify(const uint8_t msg[], size_t msg_len, const uint8_t sig[], size_t sig_len) override;
222
223 private:
224 const EC_Group m_group;
225 const EC_Point_Multi_Point_Precompute m_gy_mul;
226};
227
228bool GOST_3410_Verification_Operation::verify(const uint8_t msg[],
229 size_t msg_len,
230 const uint8_t sig[],
231 size_t sig_len) {
232 if(sig_len != m_group.get_order_bytes() * 2) {
233 return false;
234 }
235
236 const BigInt s(sig, sig_len / 2);
237 const BigInt r(sig + sig_len / 2, sig_len / 2);
238
239 const BigInt& order = m_group.get_order();
240
241 if(r <= 0 || r >= order || s <= 0 || s >= order) {
242 return false;
243 }
244
245 BigInt e = decode_le(msg, msg_len);
246 e = m_group.mod_order(e);
247 if(e.is_zero()) {
248 e = BigInt::one();
249 }
250
251 const BigInt v = m_group.inverse_mod_order(e);
252
253 const BigInt z1 = m_group.multiply_mod_order(s, v);
254 const BigInt z2 = m_group.multiply_mod_order(-r, v);
255
256 const EC_Point R = m_gy_mul.multi_exp(z1, z2);
257
258 if(R.is_zero()) {
259 return false;
260 }
261
262 return (R.get_affine_x() == r);
263}
264
265} // namespace
266
267std::unique_ptr<Private_Key> GOST_3410_PublicKey::generate_another(RandomNumberGenerator& rng) const {
268 return std::make_unique<GOST_3410_PrivateKey>(rng, domain());
269}
270
271std::unique_ptr<PK_Ops::Verification> GOST_3410_PublicKey::create_verification_op(std::string_view params,
272 std::string_view provider) const {
273 if(provider == "base" || provider.empty()) {
274 return std::make_unique<GOST_3410_Verification_Operation>(*this, params);
275 }
276 throw Provider_Not_Found(algo_name(), provider);
277}
278
279std::unique_ptr<PK_Ops::Verification> GOST_3410_PublicKey::create_x509_verification_op(
280 const AlgorithmIdentifier& signature_algorithm, std::string_view provider) const {
281 if(provider == "base" || provider.empty()) {
282 return std::make_unique<GOST_3410_Verification_Operation>(*this, signature_algorithm);
283 }
284
285 throw Provider_Not_Found(algo_name(), provider);
286}
287
288std::unique_ptr<PK_Ops::Signature> GOST_3410_PrivateKey::create_signature_op(RandomNumberGenerator& /*rng*/,
289 std::string_view params,
290 std::string_view provider) const {
291 if(provider == "base" || provider.empty()) {
292 return std::make_unique<GOST_3410_Signature_Operation>(*this, params);
293 }
294 throw Provider_Not_Found(algo_name(), provider);
295}
296
297} // namespace Botan
#define BOTAN_ASSERT(expr, assertion_made)
Definition assert.h:50
const std::vector< uint8_t > & parameters() const
Definition asn1_obj.h:466
virtual OID object_identifier() const
Definition pk_keys.cpp:22
BER_Decoder & decode(bool &out)
Definition ber_dec.h:186
BER_Decoder start_sequence()
Definition ber_dec.h:123
DER_Encoder & start_sequence()
Definition der_enc.h:64
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:648
BigInt mod_order(const BigInt &x) const
Definition ec_group.cpp:587
BigInt multiply_mod_order(const BigInt &x, const BigInt &y) const
Definition ec_group.cpp:599
const BigInt & get_order() const
Definition ec_group.cpp:571
size_t get_p_bits() const
Definition ec_group.cpp:539
EC_Point point(const BigInt &x, const BigInt &y) const
Definition ec_group.cpp:632
static EC_Group from_OID(const OID &oid)
Definition ec_group.cpp:409
const OID & get_curve_oid() const
Definition ec_group.cpp:611
BigInt inverse_mod_order(const BigInt &x) const
Definition ec_group.cpp:607
BigInt random_scalar(RandomNumberGenerator &rng) const
Definition ec_group.cpp:659
size_t get_order_bytes() const
Definition ec_group.cpp:551
EC_Point multi_exp(const BigInt &k1, const BigInt &k2) const
secure_vector< uint8_t > xy_bytes() const
Definition ec_point.cpp:482
bool on_the_curve() const
Definition ec_point.cpp:531
const EC_Group & domain() const
Definition ecc_key.h:56
EC_Group m_domain_params
Definition ecc_key.h:110
EC_Point m_public_key
Definition ecc_key.h:111
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:47
std::string algo_name() const override
Definition gost_3410.cpp:37
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