summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/hashFFI.cc52
1 files changed, 21 insertions, 31 deletions
diff --git a/src/hashFFI.cc b/src/hashFFI.cc
index f349ba4..dcc7375 100644
--- a/src/hashFFI.cc
+++ b/src/hashFFI.cc
@@ -16,6 +16,7 @@
#include <array>
#include <cstdio>
+#include <functional>
#include <openssl/md5.h>
#include <openssl/sha.h>
@@ -28,6 +29,10 @@ static_assert(sizeof(unsigned char) == 1, "unsigned char is not a single byte");
namespace {
+using OpenSSLHashFunction =
+ std::function<unsigned char*(const unsigned char*, std::size_t,
+ unsigned char*)>;
+
// Asserts a condition without crashing or releasing information about where the
// error occurred. This function is essential for web programming, where an
// attacker should not be able to bring down the app by causing an assertion
@@ -44,15 +49,14 @@ void Assert(uw_context* const context,
Assert(context, condition, FATAL, message);
}
-} // namespace
-
-uw_Basis_string uw_HashFFI_md5(uw_context* const context,
- const uw_Basis_blob input) {
- using Digest = std::array<unsigned char, MD5_DIGEST_LENGTH>;
- // Perform the MD5 operation.
+template<std::size_t digest_length>
+uw_Basis_string Hash(uw_context* const context, const uw_Basis_blob input,
+ OpenSSLHashFunction hash) {
+ using Digest = std::array<unsigned char, digest_length>;
+ // Perform the hash operation.
Digest raw_result;
- MD5(reinterpret_cast<unsigned char*>(input.data), input.size,
- raw_result.data());
+ hash(reinterpret_cast<unsigned char*>(input.data), input.size,
+ raw_result.data());
// Convert it to a hex string. This will be twice as large (two hex digits
// per byte), plus an additional byte for the null terminator.
const auto result_length = 2 * raw_result.size() + 1;
@@ -60,7 +64,7 @@ uw_Basis_string uw_HashFFI_md5(uw_context* const context,
reinterpret_cast<uw_Basis_string>(uw_malloc(context, result_length));
Assert(context, result, BOUNDED_RETRY,
"unable to allocate memory for digest");
- for (Digest::size_type i = 0; i < raw_result.size(); i++) {
+ for (typename Digest::size_type i = 0; i < raw_result.size(); i++) {
sprintf(result + 2 * i, "%02x", raw_result[i]);
}
// Make sure the string is properly terminated.
@@ -72,28 +76,14 @@ uw_Basis_string uw_HashFFI_md5(uw_context* const context,
return result;
}
+} // namespace
+
+uw_Basis_string uw_HashFFI_md5(uw_context* const context,
+ const uw_Basis_blob input) {
+ return Hash<MD5_DIGEST_LENGTH>(context, input, MD5);
+}
+
uw_Basis_string uw_HashFFI_sha1(uw_context* const context,
const uw_Basis_blob input) {
- using Digest = std::array<unsigned char, SHA_DIGEST_LENGTH>;
- // Perform the SHA-1 operation.
- Digest raw_result;
- SHA1(reinterpret_cast<unsigned char*>(input.data), input.size,
- raw_result.data());
- // Convert it to a hex string. This will be twice as large (two hex digits
- // per byte), plus an additional byte for the null terminator.
- const auto result_length = 2 * raw_result.size() + 1;
- uw_Basis_string result =
- reinterpret_cast<uw_Basis_string>(uw_malloc(context, result_length));
- Assert(context, result, BOUNDED_RETRY,
- "unable to allocate memory for digest");
- for (Digest::size_type i = 0; i < raw_result.size(); i++) {
- sprintf(result + 2 * i, "%02x", raw_result[i]);
- }
- // Make sure the string is properly terminated.
- for (std::size_t i = 0; i < result_length - 2; i++) {
- Assert(context, result[i] != '\0', "null byte in digest");
- }
- Assert(context, result[result_length - 1] == '\0',
- "failed to properly terminate digest");
- return result;
+ return Hash<SHA_DIGEST_LENGTH>(context, input, SHA1);
}