aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/ffi/ffi.h6
-rw-r--r--src/lib/ffi/ffi_pkey_algs.cpp36
-rw-r--r--src/lib/pubkey/sm2/sm2.cpp44
-rw-r--r--src/lib/pubkey/sm2/sm2_enc.cpp30
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);