diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/build-data/sonar-project.properties | 2 | ||||
-rw-r--r-- | src/lib/ffi/ffi.h | 8 | ||||
-rw-r--r-- | src/lib/ffi/ffi_kdf.cpp | 2 | ||||
-rw-r--r-- | src/lib/ffi/ffi_pk_op.cpp | 2 | ||||
-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 | ||||
-rw-r--r-- | src/tests/data/pubkey/sm2_sig.vec | 1 | ||||
-rw-r--r-- | src/tests/test_ffi.cpp | 26 | ||||
-rw-r--r-- | src/tests/test_sm2.cpp | 10 |
10 files changed, 125 insertions, 36 deletions
diff --git a/src/build-data/sonar-project.properties b/src/build-data/sonar-project.properties index 7577a7b1e..db45eaa40 100644 --- a/src/build-data/sonar-project.properties +++ b/src/build-data/sonar-project.properties @@ -20,3 +20,5 @@ sonar.cfamily.build-wrapper-output=bw-outputs # Encoding of the source code. Default is default system encoding sonar.sourceEncoding=UTF-8 + +sonar.exclusions=build/* diff --git a/src/lib/ffi/ffi.h b/src/lib/ffi/ffi.h index 565d5ce7b..de752f43c 100644 --- a/src/lib/ffi/ffi.h +++ b/src/lib/ffi/ffi.h @@ -136,6 +136,8 @@ doesn't exactly work well either! */ #define BOTAN_FFI_SUCCESS (0) +#define BOTAN_FFI_INVALID_VERIFIER (1) + #define BOTAN_FFI_ERROR_INVALID_INPUT (-1) #define BOTAN_FFI_ERROR_BAD_MAC (-2) @@ -961,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_kdf.cpp b/src/lib/ffi/ffi_kdf.cpp index 1a4c40893..7aaf2dbe8 100644 --- a/src/lib/ffi/ffi_kdf.cpp +++ b/src/lib/ffi/ffi_kdf.cpp @@ -88,7 +88,7 @@ int botan_bcrypt_is_valid(const char* pass, const char* hash) { #if defined(BOTAN_HAS_BCRYPT) return ffi_guard_thunk(BOTAN_CURRENT_FUNCTION, [=]() { - return Botan::check_bcrypt(pass, hash) ? 0 : 1; + return Botan::check_bcrypt(pass, hash) ? BOTAN_FFI_SUCCESS : BOTAN_FFI_INVALID_VERIFIER; }); #else return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; diff --git a/src/lib/ffi/ffi_pk_op.cpp b/src/lib/ffi/ffi_pk_op.cpp index d0ac8e3c7..fa3b32725 100644 --- a/src/lib/ffi/ffi_pk_op.cpp +++ b/src/lib/ffi/ffi_pk_op.cpp @@ -164,7 +164,7 @@ int botan_pk_op_verify_finish(botan_pk_op_verify_t op, const uint8_t sig[], size if(legit) return BOTAN_FFI_SUCCESS; else - return BOTAN_FFI_ERROR_INVALID_INPUT; + return BOTAN_FFI_INVALID_VERIFIER; }); } 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); diff --git a/src/tests/data/pubkey/sm2_sig.vec b/src/tests/data/pubkey/sm2_sig.vec index d3356cceb..8a86dfc7d 100644 --- a/src/tests/data/pubkey/sm2_sig.vec +++ b/src/tests/data/pubkey/sm2_sig.vec @@ -7,6 +7,7 @@ yG = 0x0680512BCBB42C07D47349D2153B70C4E5D7FDFCBFA36EA1A85841B9E46E09A2 Order = 0x8542D69E4C044F18E8B92435BF6FF7DD297720630485628D5AE74EE7C32E79B7 Cofactor = 1 +Hash = SM3 Ident = [email protected] Msg = 6D65737361676520646967657374 x = 0x128B2FA8BD433C6C068C8D803DFF79792A519A55171B1B650C23661D15897263 diff --git a/src/tests/test_ffi.cpp b/src/tests/test_ffi.cpp index 41fa3a044..33be07cdf 100644 --- a/src/tests/test_ffi.cpp +++ b/src/tests/test_ffi.cpp @@ -1282,15 +1282,15 @@ class FFI_Unit_Tests : public Test // TODO: randomize this signature[0] ^= 1; TEST_FFI_OK(botan_pk_op_verify_update, (verifier, message.data(), message.size())); - TEST_FFI_FAIL("bad signature", botan_pk_op_verify_finish, (verifier, signature.data(), signature.size())); + TEST_FFI_RC(BOTAN_FFI_INVALID_VERIFIER, botan_pk_op_verify_finish, (verifier, signature.data(), signature.size())); message[0] ^= 1; TEST_FFI_OK(botan_pk_op_verify_update, (verifier, message.data(), message.size())); - TEST_FFI_FAIL("bad signature", botan_pk_op_verify_finish, (verifier, signature.data(), signature.size())); + TEST_FFI_RC(BOTAN_FFI_INVALID_VERIFIER, botan_pk_op_verify_finish, (verifier, signature.data(), signature.size())); signature[0] ^= 1; TEST_FFI_OK(botan_pk_op_verify_update, (verifier, message.data(), message.size())); - TEST_FFI_FAIL("bad signature", botan_pk_op_verify_finish, (verifier, signature.data(), signature.size())); + TEST_FFI_RC(BOTAN_FFI_INVALID_VERIFIER, botan_pk_op_verify_finish, (verifier, signature.data(), signature.size())); message[0] ^= 1; TEST_FFI_OK(botan_pk_op_verify_update, (verifier, message.data(), message.size())); @@ -1366,15 +1366,15 @@ class FFI_Unit_Tests : public Test // TODO: randomize this signature[0] ^= 1; TEST_FFI_OK(botan_pk_op_verify_update, (verifier, message.data(), message.size())); - TEST_FFI_FAIL("bad signature", botan_pk_op_verify_finish, (verifier, signature.data(), signature.size())); + TEST_FFI_RC(BOTAN_FFI_INVALID_VERIFIER, botan_pk_op_verify_finish, (verifier, signature.data(), signature.size())); message[0] ^= 1; TEST_FFI_OK(botan_pk_op_verify_update, (verifier, message.data(), message.size())); - TEST_FFI_FAIL("bad signature", botan_pk_op_verify_finish, (verifier, signature.data(), signature.size())); + TEST_FFI_RC(BOTAN_FFI_INVALID_VERIFIER, botan_pk_op_verify_finish, (verifier, signature.data(), signature.size())); signature[0] ^= 1; TEST_FFI_OK(botan_pk_op_verify_update, (verifier, message.data(), message.size())); - TEST_FFI_FAIL("bad signature", botan_pk_op_verify_finish, (verifier, signature.data(), signature.size())); + TEST_FFI_RC(BOTAN_FFI_INVALID_VERIFIER, botan_pk_op_verify_finish, (verifier, signature.data(), signature.size())); message[0] ^= 1; TEST_FFI_OK(botan_pk_op_verify_update, (verifier, message.data(), message.size())); @@ -1408,6 +1408,10 @@ class FFI_Unit_Tests : public Test TEST_FFI_OK(botan_privkey_export_pubkey, (&pub, priv)); ffi_test_pubkey_export(result, pub, priv, rng); + uint8_t za[32]; + size_t sizeof_za = sizeof(za); + TEST_FFI_OK(botan_pubkey_sm2_compute_za, (za, &sizeof_za, "Ident", "SM3", pub)); + // Check key load functions botan_mp_t private_scalar, public_x, public_y; botan_mp_init(&private_scalar); @@ -1454,15 +1458,15 @@ class FFI_Unit_Tests : public Test // TODO: randomize this signature[0] ^= 1; TEST_FFI_OK(botan_pk_op_verify_update, (verifier, message.data(), message.size())); - TEST_FFI_FAIL("bad signature", botan_pk_op_verify_finish, (verifier, signature.data(), signature.size())); + TEST_FFI_RC(BOTAN_FFI_INVALID_VERIFIER, botan_pk_op_verify_finish, (verifier, signature.data(), signature.size())); message[0] ^= 1; TEST_FFI_OK(botan_pk_op_verify_update, (verifier, message.data(), message.size())); - TEST_FFI_FAIL("bad signature", botan_pk_op_verify_finish, (verifier, signature.data(), signature.size())); + TEST_FFI_RC(BOTAN_FFI_INVALID_VERIFIER, botan_pk_op_verify_finish, (verifier, signature.data(), signature.size())); signature[0] ^= 1; TEST_FFI_OK(botan_pk_op_verify_update, (verifier, message.data(), message.size())); - TEST_FFI_FAIL("bad signature", botan_pk_op_verify_finish, (verifier, signature.data(), signature.size())); + TEST_FFI_RC(BOTAN_FFI_INVALID_VERIFIER, botan_pk_op_verify_finish, (verifier, signature.data(), signature.size())); message[0] ^= 1; TEST_FFI_OK(botan_pk_op_verify_update, (verifier, message.data(), message.size())); @@ -1495,6 +1499,10 @@ class FFI_Unit_Tests : public Test TEST_FFI_OK(botan_privkey_export_pubkey, (&pub, priv)); ffi_test_pubkey_export(result, pub, priv, rng); + uint8_t za[32]; + size_t sizeof_za = sizeof(za); + TEST_FFI_OK(botan_pubkey_sm2_compute_za, (za, &sizeof_za, "Ident", "SM3", pub)); + // Check key load functions botan_mp_t private_scalar, public_x, public_y; botan_mp_init(&private_scalar); diff --git a/src/tests/test_sm2.cpp b/src/tests/test_sm2.cpp index 88d872435..0497ccedd 100644 --- a/src/tests/test_sm2.cpp +++ b/src/tests/test_sm2.cpp @@ -27,11 +27,11 @@ class SM2_Signature_KAT_Tests : public PK_Signature_Generation_Test "SM2", "pubkey/sm2_sig.vec", "P,A,B,xG,yG,Order,Cofactor,Ident,Msg,x,Nonce,Signature", - "") {} + "Hash") {} virtual std::string default_padding(const VarMap& vars) const override { - return get_req_str(vars, "Ident"); + return get_req_str(vars, "Ident") + "," + get_opt_str(vars, "Hash", "SM3"); } Botan::RandomNumberGenerator* test_rng(const std::vector<uint8_t>& nonce) const override @@ -71,11 +71,11 @@ class SM2_Encryption_KAT_Tests : public PK_Encryption_Decryption_Test "SM2", "pubkey/sm2_enc.vec", "P,A,B,xG,yG,Order,Cofactor,Msg,x,Nonce,Ciphertext", - "") {} + "Hash") {} - virtual std::string default_padding(const VarMap&) const override + virtual std::string default_padding(const VarMap& vars) const override { - return ""; + return get_opt_str(vars, "Hash", "SM3"); } Botan::RandomNumberGenerator* test_rng(const std::vector<uint8_t>& nonce) const override |