diff options
Diffstat (limited to 'src/lib/crypto/mem.h')
-rw-r--r-- | src/lib/crypto/mem.h | 158 |
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_ |