9#include <botan/internal/point_mul.h>
10#include <botan/pk_ops.h>
11#include <botan/der_enc.h>
12#include <botan/ber_dec.h>
14#include <botan/hash.h>
20class SM2_Encryption_Operation
final :
public PK_Ops::Encryption
24 RandomNumberGenerator& rng,
25 const std::string& kdf_hash) :
26 m_group(key.domain()),
28 m_ws(PointGFp::WORKSPACE_SIZE),
29 m_mul_public_point(key.public_point(), rng, m_ws)
32 m_hash_size =
hash->output_length();
35 size_t max_input_bits()
const override
41 size_t ciphertext_length(
size_t ptext_len)
const override
43 const size_t elem_size = m_group.get_order_bytes();
44 const size_t der_overhead = 16;
46 return der_overhead + 2*elem_size + m_hash_size + ptext_len;
49 secure_vector<uint8_t>
encrypt(
const uint8_t msg[],
51 RandomNumberGenerator& rng)
override
56 const size_t p_bytes = m_group.get_p_bytes();
58 const BigInt k = m_group.random_scalar(rng);
60 const PointGFp C1 = m_group.blinded_base_point_multiply(k, rng, m_ws);
61 const BigInt x1 = C1.get_affine_x();
62 const BigInt y1 = C1.get_affine_y();
63 std::vector<uint8_t> x1_bytes(p_bytes);
64 std::vector<uint8_t> y1_bytes(p_bytes);
68 const PointGFp kPB = m_mul_public_point.mul(k, rng, m_group.get_order(), m_ws);
70 const BigInt x2 = kPB.get_affine_x();
71 const BigInt y2 = kPB.get_affine_y();
72 std::vector<uint8_t> x2_bytes(p_bytes);
73 std::vector<uint8_t> y2_bytes(p_bytes);
77 secure_vector<uint8_t> kdf_input;
78 kdf_input += x2_bytes;
79 kdf_input += y2_bytes;
81 const secure_vector<uint8_t> kdf_output =
82 kdf->derive_key(msg_len, kdf_input.data(), kdf_input.size());
84 secure_vector<uint8_t> masked_msg(msg_len);
85 xor_buf(masked_msg.data(), msg, kdf_output.data(), msg_len);
87 hash->update(x2_bytes);
88 hash->update(msg, msg_len);
89 hash->update(y2_bytes);
90 std::vector<uint8_t> C3(
hash->output_length());
91 hash->final(C3.data());
104 const EC_Group m_group;
105 const std::string m_kdf_hash;
107 std::vector<BigInt> m_ws;
108 PointGFp_Var_Point_Precompute m_mul_public_point;
112class SM2_Decryption_Operation
final :
public PK_Ops::Decryption
116 RandomNumberGenerator& rng,
117 const std::string& kdf_hash) :
123 m_hash_size =
hash->output_length();
126 size_t plaintext_length(
size_t ptext_len)
const override
132 const size_t elem_size = m_key.domain().get_order_bytes();
134 if(ptext_len < 2*elem_size + m_hash_size)
137 return ptext_len - (2*elem_size + m_hash_size);
140 secure_vector<uint8_t>
decrypt(uint8_t& valid_mask,
141 const uint8_t ciphertext[],
142 size_t ciphertext_len)
override
144 const EC_Group& group = m_key.domain();
145 const BigInt& cofactor = group.get_cofactor();
146 const size_t p_bytes = group.get_p_bytes();
154 if(ciphertext_len < 1 + p_bytes*2 + hash->output_length())
156 return secure_vector<uint8_t>();
160 secure_vector<uint8_t> C3, masked_msg;
162 BER_Decoder(ciphertext, ciphertext_len)
171 std::vector<uint8_t> recode_ctext;
172 DER_Encoder(recode_ctext)
180 if(recode_ctext.size() != ciphertext_len)
181 return secure_vector<uint8_t>();
183 if(
same_mem(recode_ctext.data(), ciphertext, ciphertext_len) ==
false)
184 return secure_vector<uint8_t>();
186 PointGFp C1 = group.point(x1, y1);
187 C1.randomize_repr(m_rng);
190 if(!C1.on_the_curve())
191 return secure_vector<uint8_t>();
193 if(cofactor > 1 && (C1 * cofactor).is_zero())
195 return secure_vector<uint8_t>();
198 const PointGFp dbC1 = group.blinded_var_point_multiply(
199 C1, m_key.private_value(), m_rng, m_ws);
201 const BigInt x2 = dbC1.get_affine_x();
202 const BigInt y2 = dbC1.get_affine_y();
204 secure_vector<uint8_t> x2_bytes(p_bytes);
205 secure_vector<uint8_t> y2_bytes(p_bytes);
209 secure_vector<uint8_t> kdf_input;
210 kdf_input += x2_bytes;
211 kdf_input += y2_bytes;
213 const secure_vector<uint8_t> kdf_output =
214 kdf->derive_key(masked_msg.size(), kdf_input.data(), kdf_input.size());
216 xor_buf(masked_msg.data(), kdf_output.data(), kdf_output.size());
218 hash->update(x2_bytes);
219 hash->update(masked_msg);
220 hash->update(y2_bytes);
221 secure_vector<uint8_t> u =
hash->final();
224 return secure_vector<uint8_t>();
231 RandomNumberGenerator& m_rng;
232 const std::string m_kdf_hash;
233 std::vector<BigInt> m_ws;
239std::unique_ptr<PK_Ops::Encryption>
241 const std::string& params,
242 const std::string& provider)
const
244 if(provider ==
"base" || provider.empty())
246 const std::string kdf_hash = (params.empty() ?
"SM3" : params);
247 return std::unique_ptr<PK_Ops::Encryption>(
new SM2_Encryption_Operation(*
this, rng, kdf_hash));
253std::unique_ptr<PK_Ops::Decryption>
255 const std::string& params,
256 const std::string& provider)
const
258 if(provider ==
"base" || provider.empty())
260 const std::string kdf_hash = (params.empty() ?
"SM3" : params);
261 return std::unique_ptr<PK_Ops::Decryption>(
new SM2_Decryption_Operation(*
this, rng, kdf_hash));
static secure_vector< uint8_t > encode_1363(const BigInt &n, size_t bytes)
static std::unique_ptr< HashFunction > create_or_throw(const std::string &algo_spec, const std::string &provider="")
static std::unique_ptr< KDF > create_or_throw(const std::string &algo_spec, const std::string &provider="")
std::unique_ptr< PK_Ops::Decryption > create_decryption_op(RandomNumberGenerator &rng, const std::string ¶ms, const std::string &provider) const override
std::string algo_name() const override
std::unique_ptr< PK_Ops::Encryption > create_encryption_op(RandomNumberGenerator &rng, const std::string ¶ms, const std::string &provider) const override
int(* final)(unsigned char *, CTX *)
std::string decrypt(const uint8_t input[], size_t input_len, const std::string &passphrase)
std::string encrypt(const uint8_t input[], size_t input_len, const std::string &passphrase, RandomNumberGenerator &rng)
SM2_PublicKey SM2_Encryption_PublicKey
bool constant_time_compare(const uint8_t x[], const uint8_t y[], size_t len)
void xor_buf(uint8_t out[], const uint8_t in[], size_t length)
SM2_PrivateKey SM2_Encryption_PrivateKey
bool same_mem(const T *p1, const T *p2, size_t n)