diff options
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/ffi/ffi.h | 6 | ||||
-rw-r--r-- | src/lib/ffi/ffi_pkey_algs.cpp | 36 | ||||
-rw-r--r-- | src/lib/pubkey/sm2/sm2.cpp | 44 | ||||
-rw-r--r-- | src/lib/pubkey/sm2/sm2_enc.cpp | 30 |
4 files changed, 96 insertions, 20 deletions
diff --git a/src/lib/ffi/ffi.h b/src/lib/ffi/ffi.h index fecb10978..de752f43c 100644 --- a/src/lib/ffi/ffi.h +++ b/src/lib/ffi/ffi.h @@ -963,6 +963,12 @@ BOTAN_DLL int botan_privkey_load_sm2_enc(botan_privkey_t* key, const botan_mp_t scalar, const char* curve_name); +BOTAN_DLL int botan_pubkey_sm2_compute_za(uint8_t out[], + size_t* out_len, + const char* ident, + const char* hash_algo, + const botan_pubkey_t key); + /* * Public Key Encryption */ diff --git a/src/lib/ffi/ffi_pkey_algs.cpp b/src/lib/ffi/ffi_pkey_algs.cpp index b06fd113c..83ee51768 100644 --- a/src/lib/ffi/ffi_pkey_algs.cpp +++ b/src/lib/ffi/ffi_pkey_algs.cpp @@ -6,6 +6,7 @@ */ #include <botan/ffi.h> +#include <botan/hash.h> #include <botan/internal/ffi_util.h> #include <botan/internal/ffi_pkey.h> #include <botan/internal/ffi_rng.h> @@ -570,6 +571,41 @@ int botan_privkey_load_ecdh(botan_privkey_t* key, /* SM2 specific operations */ +int botan_pubkey_sm2_compute_za(uint8_t out[], + size_t* out_len, + const char* ident, + const char* hash_algo, + const botan_pubkey_t key) + { + if(out == nullptr || out_len == nullptr) + return BOTAN_FFI_ERROR_NULL_POINTER; + if(ident == nullptr || hash_algo == nullptr || key == nullptr) + return BOTAN_FFI_ERROR_NULL_POINTER; + +#if defined(BOTAN_HAS_SM2) + return ffi_guard_thunk(BOTAN_CURRENT_FUNCTION, [=]() { + const Botan::Public_Key& pub_key = safe_get(key); + const Botan::EC_PublicKey* ec_key = dynamic_cast<const Botan::EC_PublicKey*>(&pub_key); + if(key == nullptr) + return BOTAN_FFI_ERROR_BAD_PARAMETER; + + if(ec_key->algo_name() != "SM2_Sig" && ec_key->algo_name() != "SM2_Enc") + return BOTAN_FFI_ERROR_BAD_PARAMETER; + + const std::string ident_str(ident); + std::unique_ptr<Botan::HashFunction> hash = + Botan::HashFunction::create_or_throw(hash_algo); + + const std::vector<uint8_t> za = + Botan::sm2_compute_za(*hash, ident_str, ec_key->domain(), ec_key->public_point()); + + return write_vec_output(out, out_len, za); + }); +#else + return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; +#endif + } + int botan_pubkey_load_sm2(botan_pubkey_t* key, const botan_mp_t public_x, const botan_mp_t public_y, diff --git a/src/lib/pubkey/sm2/sm2.cpp b/src/lib/pubkey/sm2/sm2.cpp index 2882cb0ad..dbb22ca6d 100644 --- a/src/lib/pubkey/sm2/sm2.cpp +++ b/src/lib/pubkey/sm2/sm2.cpp @@ -1,5 +1,5 @@ /* -* SM2 +* SM2 Signatures * (C) 2017 Ribose Inc * * Botan is released under the Simplified BSD License (see license.txt) @@ -79,13 +79,14 @@ class SM2_Signature_Operation : public PK_Ops::Signature public: SM2_Signature_Operation(const SM2_Signature_PrivateKey& sm2, - const std::string& ident) : + const std::string& ident, + const std::string& hash) : m_order(sm2.domain().get_order()), m_base_point(sm2.domain().get_base_point(), m_order), m_x(sm2.private_value()), m_da_inv(sm2.get_da_inv()), m_mod_order(m_order), - m_hash(HashFunction::create_or_throw("SM3")) + m_hash(HashFunction::create_or_throw(hash)) { // ZA=H256(ENTLA || IDA || a || b || xG || yG || xA || yA) m_za = sm2_compute_za(*m_hash, ident, sm2.domain(), sm2.public_point()); @@ -134,12 +135,13 @@ class SM2_Verification_Operation : public PK_Ops::Verification { public: SM2_Verification_Operation(const SM2_Signature_PublicKey& sm2, - const std::string& ident) : + const std::string& ident, + const std::string& hash) : m_base_point(sm2.domain().get_base_point()), m_public_point(sm2.public_point()), m_order(sm2.domain().get_order()), m_mod_order(m_order), - m_hash(HashFunction::create_or_throw("SM3")) + m_hash(HashFunction::create_or_throw(hash)) { // ZA=H256(ENTLA || IDA || a || b || xG || yG || xA || yA) m_za = sm2_compute_za(*m_hash, ident, sm2.domain(), sm2.public_point()); @@ -199,7 +201,21 @@ SM2_Signature_PublicKey::create_verification_op(const std::string& params, const std::string& provider) const { if(provider == "base" || provider.empty()) - return std::unique_ptr<PK_Ops::Verification>(new SM2_Verification_Operation(*this, params)); + { + std::string userid = ""; + std::string hash = "SM3"; + + auto comma = params.find(','); + if(comma == std::string::npos) + userid = params; + else + { + userid = params.substr(0, comma); + hash = params.substr(comma+1, std::string::npos); + } + + return std::unique_ptr<PK_Ops::Verification>(new SM2_Verification_Operation(*this, userid, hash)); + } throw Provider_Not_Found(algo_name(), provider); } @@ -210,7 +226,21 @@ SM2_Signature_PrivateKey::create_signature_op(RandomNumberGenerator& /*rng*/, const std::string& provider) const { if(provider == "base" || provider.empty()) - return std::unique_ptr<PK_Ops::Signature>(new SM2_Signature_Operation(*this, params)); + { + std::string userid = ""; + std::string hash = "SM3"; + + auto comma = params.find(','); + if(comma == std::string::npos) + userid = params; + else + { + userid = params.substr(0, comma); + hash = params.substr(comma+1, std::string::npos); + } + + return std::unique_ptr<PK_Ops::Signature>(new SM2_Signature_Operation(*this, userid, hash)); + } throw Provider_Not_Found(algo_name(), provider); } diff --git a/src/lib/pubkey/sm2/sm2_enc.cpp b/src/lib/pubkey/sm2/sm2_enc.cpp index a832dd1ac..9bd4bf11c 100644 --- a/src/lib/pubkey/sm2/sm2_enc.cpp +++ b/src/lib/pubkey/sm2/sm2_enc.cpp @@ -43,11 +43,12 @@ namespace { class SM2_Encryption_Operation : public PK_Ops::Encryption { public: - SM2_Encryption_Operation(const SM2_Encryption_PublicKey& key) : + SM2_Encryption_Operation(const SM2_Encryption_PublicKey& key, const std::string& kdf_hash) : m_p_bytes(key.domain().get_curve().get_p().bytes()), m_order(key.domain().get_order()), m_base_point(key.domain().get_base_point(), m_order), - m_public_point(key.public_point(), m_order) + m_public_point(key.public_point(), m_order), + m_kdf_hash(kdf_hash) {} size_t max_input_bits() const override @@ -60,8 +61,8 @@ class SM2_Encryption_Operation : public PK_Ops::Encryption size_t msg_len, RandomNumberGenerator& rng) override { - std::unique_ptr<HashFunction> hash = HashFunction::create("SM3"); - std::unique_ptr<KDF> kdf = KDF::create("KDF2(SM3)"); + std::unique_ptr<HashFunction> hash = HashFunction::create_or_throw(m_kdf_hash); + std::unique_ptr<KDF> kdf = KDF::create_or_throw("KDF2(" + m_kdf_hash + ")"); secure_vector<uint8_t> ciphertext; ciphertext.reserve(1 + m_p_bytes*2 + msg_len + hash->output_length()); @@ -115,15 +116,18 @@ class SM2_Encryption_Operation : public PK_Ops::Encryption const BigInt& m_order; Blinded_Point_Multiply m_base_point; Blinded_Point_Multiply m_public_point; + const std::string m_kdf_hash; }; class SM2_Decryption_Operation : public PK_Ops::Decryption { public: SM2_Decryption_Operation(const SM2_Encryption_PrivateKey& key, - RandomNumberGenerator& rng) : + RandomNumberGenerator& rng, + const std::string& kdf_hash) : m_key(key), - m_rng(rng) + m_rng(rng), + m_kdf_hash(kdf_hash) {} secure_vector<uint8_t> decrypt(uint8_t& valid_mask, @@ -135,7 +139,8 @@ class SM2_Decryption_Operation : public PK_Ops::Decryption valid_mask = 0; - std::unique_ptr<HashFunction> hash = HashFunction::create("SM3"); + std::unique_ptr<HashFunction> hash = HashFunction::create_or_throw(m_kdf_hash); + std::unique_ptr<KDF> kdf = KDF::create_or_throw("KDF2(" + m_kdf_hash + ")"); // Too short to be valid - no timing problem from early return if(ciphertext_len < 1 + p_bytes*2 + hash->output_length()) @@ -174,7 +179,6 @@ class SM2_Decryption_Operation : public PK_Ops::Decryption const size_t msg_len = ciphertext_len - (1 + p_bytes*2 + hash->output_length()); - std::unique_ptr<KDF> kdf = KDF::create("KDF2(SM3)"); const secure_vector<uint8_t> kdf_output = kdf->derive_key(msg_len, kdf_input.data(), kdf_input.size()); @@ -195,7 +199,7 @@ class SM2_Decryption_Operation : public PK_Ops::Decryption private: const SM2_Encryption_PrivateKey& m_key; RandomNumberGenerator& m_rng; - const std::string m_ident; + const std::string m_kdf_hash; }; } @@ -207,8 +211,8 @@ SM2_Encryption_PublicKey::create_encryption_op(RandomNumberGenerator& /*rng*/, { if(provider == "base" || provider.empty()) { - if(params == "") - return std::unique_ptr<PK_Ops::Encryption>(new SM2_Encryption_Operation(*this)); + const std::string kdf_hash = (params.empty() ? "SM3" : params); + return std::unique_ptr<PK_Ops::Encryption>(new SM2_Encryption_Operation(*this, kdf_hash)); } throw Provider_Not_Found(algo_name(), provider); @@ -221,8 +225,8 @@ SM2_Encryption_PrivateKey::create_decryption_op(RandomNumberGenerator& rng, { if(provider == "base" || provider.empty()) { - if(params == "") - return std::unique_ptr<PK_Ops::Decryption>(new SM2_Decryption_Operation(*this, rng)); + const std::string kdf_hash = (params.empty() ? "SM3" : params); + return std::unique_ptr<PK_Ops::Decryption>(new SM2_Decryption_Operation(*this, rng, kdf_hash)); } throw Provider_Not_Found(algo_name(), provider); |