From 5a54ad4ac01a69c554a05eddf077eea08cd766b1 Mon Sep 17 00:00:00 2001 From: Benjamin Barenblat Date: Mon, 15 Jun 2015 14:27:45 -0400 Subject: Initial commit of the cryptographic hash library --- src/hashFFI.cc | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 src/hashFFI.cc (limited to 'src/hashFFI.cc') diff --git a/src/hashFFI.cc b/src/hashFFI.cc new file mode 100644 index 0000000..ab20030 --- /dev/null +++ b/src/hashFFI.cc @@ -0,0 +1,72 @@ +// Copyright (C) 2015 the Massachusetts Institute of Technology +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. + +#include "hashFFI.h" + +#include +#include + +#include +extern "C" { +#include +} + +static_assert(sizeof(char) == 1, "char is not a single byte"); +static_assert(sizeof(unsigned char) == 1, "unsigned char is not a single byte"); + +namespace { + +// 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 +// failure. +void Assert(uw_context* const context, const bool condition, + const failure_kind action, const char* const message) { + if (!condition) { + uw_error(context, action, message); + } +} + +void Assert(uw_context* const context, + const bool condition, const char* const message) { + 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; + // Perform the MD5 operation. + Digest raw_result; + MD5(reinterpret_cast(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_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; +} -- cgit v1.2.3