From 67aa9d138c9f8b966015d480fc77351c6fd77b68 Mon Sep 17 00:00:00 2001 From: Benjamin Barenblat Date: Tue, 23 Jun 2015 15:42:22 -0400 Subject: Initial commit --- src/lib.urp | 5 ++++ src/random.cc | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/random.h | 32 +++++++++++++++++++++ src/random.urs | 21 ++++++++++++++ 4 files changed, 149 insertions(+) create mode 100644 src/lib.urp create mode 100644 src/random.cc create mode 100644 src/random.h create mode 100644 src/random.urs (limited to 'src') diff --git a/src/lib.urp b/src/lib.urp new file mode 100644 index 0000000..62b02ba --- /dev/null +++ b/src/lib.urp @@ -0,0 +1,5 @@ +ffi random +benignEffectful Random.bytes +benignEffectful Random.int +include random.h +link -lurweb_crypto_random_openssl -lcrypto diff --git a/src/random.cc b/src/random.cc new file mode 100644 index 0000000..12deaf0 --- /dev/null +++ b/src/random.cc @@ -0,0 +1,91 @@ +// 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 "random.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); +} + +char* RandomBytes(struct uw_context* const context, const int n_bytes) { + Assert(context, 0 <= n_bytes, + "cannot produce a negative number of random bytes"); + // Allocate for the result. Ensure that no precision gets lost when casting + // from int to std::size_t. + static_assert(std::numeric_limits::max() + <= std::numeric_limits::max(), + "int is larger than expected"); + unsigned char* const result_bytes = + static_cast(uw_malloc(context, + static_cast(n_bytes))); + // Fill it with random data. + Assert(context, RAND_bytes(result_bytes, n_bytes) == 1, BOUNDED_RETRY, + "cannot generate random data"); + return reinterpret_cast(result_bytes); +} + +} // namespace + +uw_Basis_int uw_Random_int(struct uw_context* const context) { + return *reinterpret_cast(RandomBytes(context, + sizeof(uw_Basis_int))); +} + +uw_Basis_blob uw_Random_bytes(struct uw_context* const context, + const uw_Basis_int ur_n_bytes) { + // We need to use ur_n_bytes as a number of different types in this function. + // The smallest one, however, is almost certainly int. Ensure that that's the + // case. + static_assert(std::numeric_limits::max() + <= std::numeric_limits::max(), + "int is larger than expected"); + static_assert(std::numeric_limits::max() + <= std::numeric_limits::max(), + "int is larger than expected"); + // Ensure that we don't lose precision when converting ur_n_bytes to int, and + // do so. + Assert(context, 0 <= ur_n_bytes, + "cannot produce a negative number of random bytes"); + Assert(context, ur_n_bytes < std::numeric_limits::max(), + "requested number of bytes is larger than supported"); + const int n_bytes = static_cast(ur_n_bytes); + // Generate random data. + return uw_Basis_blob{static_cast(n_bytes), + RandomBytes(context, n_bytes)}; +} diff --git a/src/random.h b/src/random.h new file mode 100644 index 0000000..4d05ac3 --- /dev/null +++ b/src/random.h @@ -0,0 +1,32 @@ +// 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. + +#ifndef URWEB_CRYPTO_RANDOM_OPENSSL_RANDOM_H +#define URWEB_CRYPTO_RANDOM_OPENSSL_RANDOM_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +uw_Basis_int uw_Random_int(struct uw_context*); + +uw_Basis_blob uw_Random_bytes(struct uw_context*, const uw_Basis_int); + +#ifdef __cplusplus +} +#endif + +#endif // URWEB_CRYPTO_RANDOM_OPENSSL_RANDOM_H diff --git a/src/random.urs b/src/random.urs new file mode 100644 index 0000000..284336b --- /dev/null +++ b/src/random.urs @@ -0,0 +1,21 @@ +(* Copyright 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. *) + +(* Generates a random int, chosen uniformly using a cryptographically secure +entropy pool. *) +val int : transaction int + +(* Returns a blob containing the specified number of cryptographically secure +pseudorandom bytes. You must specify a nonnegative number equal or less than +INT_MAX as defined by your platform. *) +val bytes : int -> transaction blob -- cgit v1.2.3