/*- * 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 #include #if defined(CRYPTO_BACKEND_BOTAN) #include #include #elif defined(CRYPTO_BACKEND_OPENSSL) #include #endif namespace rnp { #if defined(CRYPTO_BACKEND_BOTAN) template using secure_vector = Botan::secure_vector; #elif defined(CRYPTO_BACKEND_OPENSSL) template class ossl_allocator { public: static_assert(std::is_integral::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 ossl_allocator(const ossl_allocator &) noexcept { } T * allocate(std::size_t n) { if (!n) { return nullptr; } /* attempt to use OpenSSL secure alloc */ T *ptr = static_cast(OPENSSL_secure_zalloc(n * sizeof(T))); if (ptr) { return ptr; } /* fallback to std::alloc if failed */ ptr = static_cast(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 using secure_vector = std::vector >; #else #error Unsupported backend. #endif template struct secure_array { private: static_assert(std::is_integral::value, "T must be integer type"); std::array 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_