Botan 2.13.0 Crypto and TLS for C++11

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

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
53 AlgorithmIdentifier GOST_3410_PublicKey::algorithm_identifier() const
54 {
55 std::vector<uint8_t> params;
56
57 DER_Encoder(params)
58 .start_cons(SEQUENCE)
59 .encode(domain().get_curve_oid())
60 .end_cons();
61
62 return AlgorithmIdentifier(get_oid(), params);
63 }
64
65 GOST_3410_PublicKey::GOST_3410_PublicKey(const AlgorithmIdentifier& alg_id,
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
80 secure_vector<uint8_t> bits;
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
97 BOTAN_ASSERT(m_public_key.on_the_curve(),
98 "Loaded GOST 34.10 public key is on the curve");
99 }
100
101 GOST_3410_PrivateKey::GOST_3410_PrivateKey(RandomNumberGenerator& rng,
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>
235 GOST_3410_PublicKey::create_verification_op(const std::string& params,
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>
244 GOST_3410_PrivateKey::create_signature_op(RandomNumberGenerator& /*rng*/,
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 }
Botan::BigInt::binary_encode
void binary_encode(uint8_t buf[]) const
Definition: bigint.cpp:391
Botan::BigInt
Definition: bigint.h:24
Botan::PointGFp::get_affine_y
BigInt get_affine_y() const
Definition: point_gfp.cpp:518
Botan::EC_PublicKey::domain
const EC_Group & domain() const
Definition: ecc_key.h:72
Botan::RandomNumberGenerator
Definition: rng.h:24
Botan::EC_Group::point
PointGFp point(const BigInt &x, const BigInt &y) const
Definition: ec_group.cpp:542
final
int(* final)(unsigned char *, CTX *)
Definition: commoncrypto_hash.cpp:28
Botan::EC_Group::inverse_mod_order
BigInt inverse_mod_order(const BigInt &x) const
Definition: ec_group.cpp:518
Botan::EC_PublicKey::m_public_key
PointGFp m_public_key
Definition: ecc_key.h:115
Botan::ASN1::to_string
std::string to_string(const BER_Object &obj)
Definition: asn1_obj.cpp:213
Botan::DER_Encoder::end_cons
DER_Encoder & end_cons()
Definition: der_enc.cpp:191
Botan::EC_Group::multiply_mod_order
BigInt multiply_mod_order(const BigInt &x, const BigInt &y) const
Definition: ec_group.cpp:508
Botan::BER_Decoder::decode
BER_Decoder & decode(bool &out)
Definition: ber_dec.h:170
Botan::GOST_3410_PrivateKey::create_signature_op
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
Botan::Public_Key::get_oid
virtual OID get_oid() const
Definition: pk_keys.cpp:53
Botan::EC_PrivateKey
Definition: ecc_key.h:123
Botan::EC_PublicKey::public_point
const PointGFp & public_point() const
Definition: ecc_key.h:57
BOTAN_ASSERT
#define BOTAN_ASSERT(expr, assertion_made)
Definition: assert.h:55
Botan::Decoding_Error
Definition: exceptn.h:199
Botan::EC_Group::get_order_bytes
size_t get_order_bytes() const
Definition: ec_group.cpp:453
Botan::PointGFp::get_affine_x
BigInt get_affine_x() const
Definition: point_gfp.cpp:499
Botan::GOST_3410_PublicKey::public_key_bits
std::vector< uint8_t > public_key_bits() const override
Definition: gost_3410.cpp:19
Botan::DER_Encoder::encode
DER_Encoder & encode(bool b)
Definition: der_enc.cpp:285
Botan::SEQUENCE
Definition: asn1_obj.h:40
Botan::DER_Encoder
Definition: der_enc.h:23
Botan::secure_vector
std::vector< T, secure_allocator< T >> secure_vector
Definition: secmem.h:65
Botan::EC_Group::mod_order
BigInt mod_order(const BigInt &x) const
Definition: ec_group.cpp:498
Botan::EC_Group::get_order
const BigInt & get_order() const
Definition: ec_group.cpp:478
m_gy_mul
const PointGFp_Multi_Point_Precompute m_gy_mul
Definition: gost_3410.cpp:197
m_ws
std::vector< BigInt > m_ws
Definition: gost_3410.cpp:147
Botan
Definition: alg_id.cpp:13
Botan::GOST_3410_PublicKey::GOST_3410_PublicKey
GOST_3410_PublicKey()=default
Botan::EC_Group
Definition: ec_group.h:40
Botan::OCTET_STRING
Definition: asn1_obj.h:36
m_x
const BigInt & m_x
Definition: gost_3410.cpp:146
Botan::Encoding_Error
Definition: exceptn.h:184
Botan::GOST_3410_PublicKey::algo_name
std::string algo_name() const override
Definition: gost_3410.cpp:43
Botan::EC_Group::get_p_bits
size_t get_p_bits() const
Definition: ec_group.cpp:438
Botan::GOST_3410_PublicKey::algorithm_identifier
AlgorithmIdentifier algorithm_identifier() const override
Definition: gost_3410.cpp:53
Botan::EC_Group::blinded_base_point_multiply_x
BigInt blinded_base_point_multiply_x(const BigInt &k, RandomNumberGenerator &rng, std::vector< BigInt > &ws) const
Definition: ec_group.cpp:561
Botan::PointGFp::on_the_curve
bool on_the_curve() const
Definition: point_gfp.cpp:538
Botan::AlgorithmIdentifier
Definition: alg_id.h:21
Botan::DER_Encoder::start_cons
DER_Encoder & start_cons(ASN1_Tag type_tag, ASN1_Tag class_tag=UNIVERSAL)
Definition: der_enc.cpp:181
Botan::GOST_3410_PublicKey::create_verification_op
std::unique_ptr< PK_Ops::Verification > create_verification_op(const std::string &params, const std::string &provider) const override
Definition: gost_3410.cpp:235
Botan::OCSP::Response_Status_Code::Internal_Error
m_group
const EC_Group m_group
Definition: gost_3410.cpp:145
Botan::Provider_Not_Found
Definition: exceptn.h:278
Botan::BigInt::encode_fixed_length_int_pair
static secure_vector< uint8_t > encode_fixed_length_int_pair(const BigInt &n1, const BigInt &n2, size_t bytes)
Definition: big_code.cpp:133
Botan::OID
Definition: asn1_oid.h:20
Botan::BER_Decoder
Definition: ber_dec.h:21
Botan::PointGFp_Multi_Point_Precompute::multi_exp
PointGFp multi_exp(const BigInt &k1, const BigInt &k2) const
Definition: point_mul.cpp:379
Botan::EC_PublicKey::m_domain_params
EC_Group m_domain_params
Definition: ecc_key.h:114
Botan::EC_Group::random_scalar
BigInt random_scalar(RandomNumberGenerator &rng) const
Definition: ec_group.cpp:572
Botan::AlgorithmIdentifier::get_parameters
const std::vector< uint8_t > & get_parameters() const
Definition: alg_id.h:38
Botan::GOST_3410_PrivateKey::GOST_3410_PrivateKey
GOST_3410_PrivateKey(const AlgorithmIdentifier &alg_id, const secure_vector< uint8_t > &key_bits)
Definition: gost_3410.h:79
Botan::BigInt::bytes
size_t bytes() const
Definition: bigint.cpp:273