10#include <botan/ber_dec.h>
11#include <botan/der_enc.h>
12#include <botan/hash.h>
14#include <botan/pk_ops.h>
15#include <botan/internal/ct_utils.h>
16#include <botan/internal/fmt.h>
17#include <botan/internal/point_mul.h>
23class SM2_Encryption_Operation
final :
public PK_Ops::Encryption {
26 RandomNumberGenerator& rng,
27 std::string_view kdf_hash) :
28 m_group(key.domain()), m_ws(EC_Point::WORKSPACE_SIZE), m_mul_public_point(key.public_point(), rng, m_ws) {
31 const std::string kdf_name =
fmt(
"KDF2({})", kdf_hash);
35 size_t max_input_bits()
const override {
40 size_t ciphertext_length(
size_t ptext_len)
const override {
41 const size_t elem_size = m_group.get_order_bytes();
42 const size_t der_overhead = 16;
44 return der_overhead + 2 * elem_size + m_hash->output_length() + ptext_len;
48 const BigInt k = m_group.random_scalar(rng);
50 const EC_Point C1 = m_group.blinded_base_point_multiply(k, rng, m_ws);
51 const BigInt x1 = C1.get_affine_x();
52 const BigInt y1 = C1.get_affine_y();
54 const EC_Point kPB = m_mul_public_point.mul(k, rng, m_group.get_order(), m_ws);
56 const auto x2_bytes = kPB.x_bytes();
57 const auto y2_bytes = kPB.y_bytes();
60 kdf_input += x2_bytes;
61 kdf_input += y2_bytes;
65 std::vector<uint8_t> masked_msg(msg_len);
66 xor_buf(masked_msg.data(), msg, kdf_output.data(), msg_len);
68 m_hash->update(x2_bytes);
69 m_hash->update(msg, msg_len);
70 m_hash->update(y2_bytes);
71 const auto C3 = m_hash->final<std::vector<uint8_t>>();
84 const EC_Group m_group;
85 std::unique_ptr<HashFunction> m_hash;
86 std::unique_ptr<KDF> m_kdf;
87 std::vector<BigInt> m_ws;
88 EC_Point_Var_Point_Precompute m_mul_public_point;
91class SM2_Decryption_Operation
final :
public PK_Ops::Decryption {
94 RandomNumberGenerator& rng,
95 std::string_view kdf_hash) :
96 m_key(key), m_rng(rng) {
99 const std::string kdf_name =
fmt(
"KDF2({})", kdf_hash);
103 size_t plaintext_length(
size_t ptext_len)
const override {
108 const size_t elem_size = m_key.domain().get_order_bytes();
110 if(ptext_len < 2 * elem_size + m_hash->output_length()) {
114 return ptext_len - (2 * elem_size + m_hash->output_length());
118 const EC_Group& group = m_key.domain();
119 const BigInt& cofactor = group.get_cofactor();
120 const size_t p_bytes = group.get_p_bytes();
125 if(ciphertext_len < 1 + p_bytes * 2 + m_hash->output_length()) {
132 BER_Decoder(ciphertext, ciphertext_len)
141 std::vector<uint8_t> recode_ctext;
142 DER_Encoder(recode_ctext)
150 if(recode_ctext.size() != ciphertext_len) {
154 if(
CT::is_equal(recode_ctext.data(), ciphertext, ciphertext_len).as_bool() ==
false) {
158 EC_Point C1 = group.point(x1, y1);
159 C1.randomize_repr(m_rng);
162 if(!C1.on_the_curve()) {
166 if(cofactor > 1 && (C1 * cofactor).is_zero()) {
170 const EC_Point dbC1 = group.blinded_var_point_multiply(C1, m_key.private_value(), m_rng, m_ws);
172 const auto x2_bytes = dbC1.x_bytes();
173 const auto y2_bytes = dbC1.y_bytes();
176 kdf_input += x2_bytes;
177 kdf_input += y2_bytes;
180 m_kdf->derive_key(masked_msg.size(), kdf_input.data(), kdf_input.size());
182 xor_buf(masked_msg.data(), kdf_output.data(), kdf_output.size());
184 m_hash->update(x2_bytes);
185 m_hash->update(masked_msg);
186 m_hash->update(y2_bytes);
189 if(!
CT::is_equal(u.data(), C3.data(), m_hash->output_length()).as_bool()) {
199 RandomNumberGenerator& m_rng;
200 std::vector<BigInt> m_ws;
201 std::unique_ptr<HashFunction> m_hash;
202 std::unique_ptr<KDF> m_kdf;
208 std::string_view params,
209 std::string_view provider)
const {
210 if(provider ==
"base" || provider.empty()) {
212 return std::make_unique<SM2_Encryption_Operation>(*
this, rng,
"SM3");
214 return std::make_unique<SM2_Encryption_Operation>(*
this, rng, params);
222 std::string_view params,
223 std::string_view provider)
const {
224 if(provider ==
"base" || provider.empty()) {
226 return std::make_unique<SM2_Decryption_Operation>(*
this, rng,
"SM3");
228 return std::make_unique<SM2_Decryption_Operation>(*
this, rng, params);
static std::unique_ptr< HashFunction > create_or_throw(std::string_view algo_spec, std::string_view provider="")
static std::unique_ptr< KDF > create_or_throw(std::string_view algo_spec, std::string_view provider="")
std::unique_ptr< PK_Ops::Decryption > create_decryption_op(RandomNumberGenerator &rng, std::string_view params, std::string_view provider) const override
std::unique_ptr< PK_Ops::Encryption > create_encryption_op(RandomNumberGenerator &rng, std::string_view params, std::string_view provider) const override
std::string algo_name() const override
int(* final)(unsigned char *, CTX *)
constexpr CT::Mask< T > is_equal(const T x[], const T y[], size_t len)
std::string encrypt(const uint8_t input[], size_t input_len, std::string_view passphrase, RandomNumberGenerator &rng)
std::string decrypt(const uint8_t input[], size_t input_len, std::string_view passphrase)
SM2_PublicKey SM2_Encryption_PublicKey
std::string fmt(std::string_view format, const T &... args)
SM2_PrivateKey SM2_Encryption_PrivateKey
constexpr void xor_buf(ranges::contiguous_output_range< uint8_t > auto &&out, ranges::contiguous_range< uint8_t > auto &&in)
std::vector< T, secure_allocator< T > > secure_vector