summaryrefslogtreecommitdiffstats
path: root/src/lib/crypto/mem.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/crypto/mem.h')
-rw-r--r--src/lib/crypto/mem.h158
1 files changed, 158 insertions, 0 deletions
diff --git a/src/lib/crypto/mem.h b/src/lib/crypto/mem.h
new file mode 100644
index 0000000..fe574da
--- /dev/null
+++ b/src/lib/crypto/mem.h
@@ -0,0 +1,158 @@
+/*-
+ * Copyright (c) 2021 Ribose Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CRYPTO_MEM_H_
+#define CRYPTO_MEM_H_
+
+#include "config.h"
+#include <array>
+#include <vector>
+#if defined(CRYPTO_BACKEND_BOTAN)
+#include <botan/secmem.h>
+#include <botan/ffi.h>
+#elif defined(CRYPTO_BACKEND_OPENSSL)
+#include <openssl/crypto.h>
+#endif
+
+namespace rnp {
+
+#if defined(CRYPTO_BACKEND_BOTAN)
+template <typename T> using secure_vector = Botan::secure_vector<T>;
+#elif defined(CRYPTO_BACKEND_OPENSSL)
+template <typename T> class ossl_allocator {
+ public:
+ static_assert(std::is_integral<T>::value, "T must be integral type");
+
+ typedef T value_type;
+ typedef std::size_t size_type;
+
+ ossl_allocator() noexcept = default;
+ ossl_allocator(const ossl_allocator &) noexcept = default;
+ ossl_allocator &operator=(const ossl_allocator &) noexcept = default;
+ ~ossl_allocator() noexcept = default;
+
+ template <typename U> ossl_allocator(const ossl_allocator<U> &) noexcept
+ {
+ }
+
+ T *
+ allocate(std::size_t n)
+ {
+ if (!n) {
+ return nullptr;
+ }
+
+ /* attempt to use OpenSSL secure alloc */
+ T *ptr = static_cast<T *>(OPENSSL_secure_zalloc(n * sizeof(T)));
+ if (ptr) {
+ return ptr;
+ }
+ /* fallback to std::alloc if failed */
+ ptr = static_cast<T *>(std::calloc(n, sizeof(T)));
+ if (!ptr)
+ throw std::bad_alloc();
+ return ptr;
+ }
+
+ void
+ deallocate(T *p, std::size_t n)
+ {
+ if (!p) {
+ return;
+ }
+ if (CRYPTO_secure_allocated(p)) {
+ OPENSSL_secure_clear_free(p, n * sizeof(T));
+ return;
+ }
+ OPENSSL_cleanse(p, n * sizeof(T));
+ std::free(p);
+ }
+};
+
+template <typename T> using secure_vector = std::vector<T, ossl_allocator<T> >;
+#else
+#error Unsupported backend.
+#endif
+
+template <typename T, std::size_t N> struct secure_array {
+ private:
+ static_assert(std::is_integral<T>::value, "T must be integer type");
+ std::array<T, N> data_;
+
+ public:
+ secure_array() : data_({0})
+ {
+ }
+
+ T *
+ data()
+ {
+ return &data_[0];
+ }
+
+ std::size_t
+ size() const
+ {
+ return data_.size();
+ }
+
+ T
+ operator[](size_t idx) const
+ {
+ return data_[idx];
+ }
+
+ T &
+ operator[](size_t idx)
+ {
+ return data_[idx];
+ }
+
+ ~secure_array()
+ {
+#if defined(CRYPTO_BACKEND_BOTAN)
+ botan_scrub_mem(&data_[0], sizeof(data_));
+#elif defined(CRYPTO_BACKEND_OPENSSL)
+ OPENSSL_cleanse(&data_[0], sizeof(data_));
+#else
+#error "Unsupported crypto backend."
+#endif
+ }
+};
+
+typedef enum { HEX_LOWERCASE, HEX_UPPERCASE } hex_format_t;
+
+bool hex_encode(const uint8_t *buf,
+ size_t buf_len,
+ char * hex,
+ size_t hex_len,
+ hex_format_t format = HEX_UPPERCASE);
+size_t hex_decode(const char *hex, uint8_t *buf, size_t buf_len);
+} // namespace rnp
+
+void secure_clear(void *vp, size_t size);
+
+#endif // CRYPTO_MEM_H_