aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2017-05-18 11:42:36 -0400
committerJack Lloyd <[email protected]>2017-05-18 11:42:36 -0400
commit2c21c5ca62062f82d160b8ef8d0e386e9d38f111 (patch)
tree67079d158f02e9794d864b3ad473d4b630fcb399 /src
parent2f53dc937f33816445c7646b88e0ad826d197482 (diff)
Add botan_pkcs_hash_id to FFI
Extend EMSA_PKCS1v15_Raw to optionally take a hash function for which the PKCS hash id is prefixed to the message as usual. This allows signing a message using PKCSv1.5 padding where the hash is provided externally.
Diffstat (limited to 'src')
-rw-r--r--src/lib/ffi/ffi.cpp21
-rw-r--r--src/lib/ffi/ffi.h2
-rw-r--r--src/lib/pk_pad/emsa.cpp6
-rw-r--r--src/lib/pk_pad/emsa_pkcs1/emsa_pkcs1.cpp25
-rw-r--r--src/lib/pk_pad/emsa_pkcs1/emsa_pkcs1.h7
-rw-r--r--src/tests/data/pubkey/rsa_sig.vec8
-rw-r--r--src/tests/test_ffi.cpp27
7 files changed, 93 insertions, 3 deletions
diff --git a/src/lib/ffi/ffi.cpp b/src/lib/ffi/ffi.cpp
index 94e83122e..a48a438be 100644
--- a/src/lib/ffi/ffi.cpp
+++ b/src/lib/ffi/ffi.cpp
@@ -73,6 +73,10 @@
#include <botan/bcrypt.h>
#endif
+#if defined(BOTAN_HAS_HASH_ID)
+ #include <botan/hash_id.h>
+#endif
+
#if defined(BOTAN_HAS_TLS)
#include <botan/tls_client.h>
#include <botan/tls_server.h>
@@ -2249,6 +2253,23 @@ int botan_x509_cert_allowed_usage(botan_x509_cert_t cert, unsigned int key_usage
});
}
+int botan_pkcs_hash_id(const char* hash_name, uint8_t pkcs_id[], size_t* pkcs_id_len)
+ {
+#if defined(BOTAN_HAS_HASH_ID)
+ try
+ {
+ const std::vector<uint8_t> hash_id = Botan::pkcs_hash_id(hash_name);
+ return write_output(pkcs_id, pkcs_id_len, hash_id.data(), hash_id.size());
+ }
+ catch(...)
+ {
+ return BOTAN_FFI_ERROR_EXCEPTION_THROWN;
+ }
+#else
+ return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
+#endif
+ }
+
int botan_mceies_decrypt(botan_privkey_t mce_key_obj,
const char* aead,
const uint8_t ct[], size_t ct_len,
diff --git a/src/lib/ffi/ffi.h b/src/lib/ffi/ffi.h
index f93265e22..4953bce06 100644
--- a/src/lib/ffi/ffi.h
+++ b/src/lib/ffi/ffi.h
@@ -911,6 +911,8 @@ BOTAN_DLL int botan_pk_op_key_agreement(botan_pk_op_ka_t op,
const uint8_t other_key[], size_t other_key_len,
const uint8_t salt[], size_t salt_len);
+BOTAN_DLL int botan_pkcs_hash_id(const char* hash_name, uint8_t pkcs_id[], size_t* pkcs_id_len);
+
/*
*
diff --git a/src/lib/pk_pad/emsa.cpp b/src/lib/pk_pad/emsa.cpp
index 94274916e..074af273a 100644
--- a/src/lib/pk_pad/emsa.cpp
+++ b/src/lib/pk_pad/emsa.cpp
@@ -50,7 +50,11 @@ EMSA* get_emsa(const std::string& algo_spec)
req.algo_name() == "EMSA-PKCS1-v1_5" ||
req.algo_name() == "EMSA3")
{
- if(req.arg_count() == 1)
+ if(req.arg_count() == 2 && req.arg(0) == "Raw")
+ {
+ return new EMSA_PKCS1v15_Raw(req.arg(1));
+ }
+ else if(req.arg_count() == 1)
{
if(req.arg(0) == "Raw")
{
diff --git a/src/lib/pk_pad/emsa_pkcs1/emsa_pkcs1.cpp b/src/lib/pk_pad/emsa_pkcs1/emsa_pkcs1.cpp
index ebe6f5fa7..d5a6aa8fb 100644
--- a/src/lib/pk_pad/emsa_pkcs1/emsa_pkcs1.cpp
+++ b/src/lib/pk_pad/emsa_pkcs1/emsa_pkcs1.cpp
@@ -85,6 +85,20 @@ EMSA_PKCS1v15::EMSA_PKCS1v15(HashFunction* hash) : m_hash(hash)
m_hash_id = pkcs_hash_id(m_hash->name());
}
+EMSA_PKCS1v15_Raw::EMSA_PKCS1v15_Raw(const std::string& hash_algo)
+ {
+ if(!hash_algo.empty())
+ {
+ m_hash_id = pkcs_hash_id(hash_algo);
+ std::unique_ptr<HashFunction> hash(HashFunction::create(hash_algo));
+ m_hash_output_len = hash->output_length();
+ }
+ else
+ {
+ m_hash_output_len = 0;
+ }
+ }
+
void EMSA_PKCS1v15_Raw::update(const uint8_t input[], size_t length)
{
m_message += std::make_pair(input, length);
@@ -94,6 +108,10 @@ secure_vector<uint8_t> EMSA_PKCS1v15_Raw::raw_data()
{
secure_vector<uint8_t> ret;
std::swap(ret, m_message);
+
+ if(m_hash_output_len > 0 && ret.size() != m_hash_output_len)
+ throw Encoding_Error("EMSA_PKCS1v15_Raw::encoding_of: Bad input length");
+
return ret;
}
@@ -102,16 +120,19 @@ EMSA_PKCS1v15_Raw::encoding_of(const secure_vector<uint8_t>& msg,
size_t output_bits,
RandomNumberGenerator&)
{
- return emsa3_encoding(msg, output_bits, nullptr, 0);
+ return emsa3_encoding(msg, output_bits, m_hash_id.data(), m_hash_id.size());
}
bool EMSA_PKCS1v15_Raw::verify(const secure_vector<uint8_t>& coded,
const secure_vector<uint8_t>& raw,
size_t key_bits)
{
+ if(m_hash_output_len > 0 && raw.size() != m_hash_output_len)
+ return false;
+
try
{
- return (coded == emsa3_encoding(raw, key_bits, nullptr, 0));
+ return (coded == emsa3_encoding(raw, key_bits, m_hash_id.data(), m_hash_id.size()));
}
catch(...)
{
diff --git a/src/lib/pk_pad/emsa_pkcs1/emsa_pkcs1.h b/src/lib/pk_pad/emsa_pkcs1/emsa_pkcs1.h
index 95ccafa4d..ddfabeae3 100644
--- a/src/lib/pk_pad/emsa_pkcs1/emsa_pkcs1.h
+++ b/src/lib/pk_pad/emsa_pkcs1/emsa_pkcs1.h
@@ -62,7 +62,14 @@ class BOTAN_DLL EMSA_PKCS1v15_Raw final : public EMSA
bool verify(const secure_vector<uint8_t>&, const secure_vector<uint8_t>&,
size_t) override;
+ /**
+ * @param hash_algo if non-empty, the digest id for that hash is
+ * included in the signature.
+ */
+ EMSA_PKCS1v15_Raw(const std::string& hash_algo = "");
private:
+ size_t m_hash_output_len = 0;
+ std::vector<uint8_t> m_hash_id;
secure_vector<uint8_t> m_message;
};
diff --git a/src/tests/data/pubkey/rsa_sig.vec b/src/tests/data/pubkey/rsa_sig.vec
index 19641cc19..1560a78d6 100644
--- a/src/tests/data/pubkey/rsa_sig.vec
+++ b/src/tests/data/pubkey/rsa_sig.vec
@@ -239,6 +239,14 @@ Q = 1300628500736091066469357724169131719350514861299470388096939255066412050709
Msg = 2C88F626457046190AEB16FF2A499DF5820240A5248074445B2D54DDF0C298F57BFF
Signature = 0EB5DC0D319B97F56F1C71E381BC26F40012054BB9A597484946955886F83333D21E916D60C3FB667869383CF9AAF6C0A98641ECECCB9F3BD71943696A78609E6324386B2030D2B2DEF1692677E205282617AA40EBAEB48C86B884CF51884BC807BE2D7C83AE3C671DB24E141B76646F0466B0DBFF20362991D465F7A0F7B4324E54092A742E0FE4C66A200AF324706B7D1BDE1C0371AB5FAFD58EBDE5555D24DECF399553C94E45A3E5B3F491BEF76EA9B08C41C2F233F13F83C99D6D88EDAD
+Padding = EMSA3(Raw,MD5)
+E = 17
+P = 13029564622157791280616891297384459345543528892729268050647908228725108502227809382105716872483480064224030258864846430267698903993578412414816903162894041
+Q = 11607519244599001458239888881356890329831441554346650600093035021905318722027819107556373878744770935515508357488960347997325733372608114236427580844273703
+Msg = BA34C71DB7D125ED4E6B3A246D6F235C
+Signature = AA5E96F061E0F6FEAEEDAABA83BEA346BD4129B1F9F8380E8CB1E61860E47DA5262F0A2ADFECE7DBC02A53FFEA0C24EE162ABD8B818D4C125BC8351CCE0FA7C533C18EC7264593C3CB9201A5C0889DBB211CEB659135854C6510F3FE96DFD5A172D1037C4C7B1CFA6BA56529B6C5FAB72754F6518E114CB14F1CF63AD12E3B2A
+
+
Padding = EMSA3(MD5)
E = 17
P = 13029564622157791280616891297384459345543528892729268050647908228725108502227809382105716872483480064224030258864846430267698903993578412414816903162894041
diff --git a/src/tests/test_ffi.cpp b/src/tests/test_ffi.cpp
index 45c4c8a5b..624b01032 100644
--- a/src/tests/test_ffi.cpp
+++ b/src/tests/test_ffi.cpp
@@ -341,6 +341,7 @@ class FFI_Unit_Tests : public Test
results.push_back(ffi_test_ciphers_cbc());
results.push_back(ffi_test_ciphers_aead());
results.push_back(ffi_test_stream_ciphers());
+ results.push_back(ffi_test_pkcs_hash_id());
#if defined(BOTAN_HAS_RSA)
results.push_back(ffi_test_rsa(rng));
@@ -373,6 +374,32 @@ class FFI_Unit_Tests : public Test
}
private:
+ Test::Result ffi_test_pkcs_hash_id()
+ {
+ Test::Result result("FFI PKCS hash id");
+
+#if defined(BOTAN_HAS_HASH_ID)
+ std::vector<uint8_t> hash_id(64);
+ size_t hash_id_len;
+
+ hash_id_len = 3; // too short
+ TEST_FFI_RC(BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE,
+ botan_pkcs_hash_id, ("SHA-256", hash_id.data(), &hash_id_len));
+
+ result.test_eq("Expected SHA-256 PKCS hash id len", hash_id_len, 19);
+
+ TEST_FFI_OK(botan_pkcs_hash_id, ("SHA-256", hash_id.data(), &hash_id_len));
+
+ result.test_eq("Expected SHA-256 PKCS hash id len", hash_id_len, 19);
+
+ hash_id.resize(hash_id_len);
+ result.test_eq("Expected SHA_256 PKCS hash id",
+ hash_id, "3031300D060960864801650304020105000420");
+#endif
+
+ return result;
+ }
+
Test::Result ffi_test_ciphers_cbc()
{
Test::Result result("FFI CBC cipher");