diff options
author | moneromooo-monero <moneromooo-monero@users.noreply.github.com> | 2018-07-07 00:03:15 +0100 |
---|---|---|
committer | moneromooo-monero <moneromooo-monero@users.noreply.github.com> | 2018-08-16 09:17:52 +0000 |
commit | ea37614efe518ff8f363ddf2465301687e04d977 (patch) | |
tree | 17a975260d2943c18f3a19c51bb6bc88dd26b98c /contrib | |
parent | Merge pull request #4191 (diff) | |
download | monero-ea37614efe518ff8f363ddf2465301687e04d977.tar.xz |
wallet: wipe seed from memory where appropriate
Diffstat (limited to 'contrib')
-rw-r--r-- | contrib/epee/include/fnv1.h | 45 | ||||
-rw-r--r-- | contrib/epee/include/hex.h | 5 | ||||
-rw-r--r-- | contrib/epee/include/wipeable_string.h | 28 | ||||
-rw-r--r-- | contrib/epee/src/hex.cpp | 10 | ||||
-rw-r--r-- | contrib/epee/src/wipeable_string.cpp | 112 |
5 files changed, 194 insertions, 6 deletions
diff --git a/contrib/epee/include/fnv1.h b/contrib/epee/include/fnv1.h new file mode 100644 index 000000000..c04389bca --- /dev/null +++ b/contrib/epee/include/fnv1.h @@ -0,0 +1,45 @@ +// Copyright (c) 2018, The Monero Project +// +// 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. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// 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 HOLDER 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. + +#pragma once + +namespace epee +{ + +namespace fnv +{ + inline uint64_t FNV1a(const char *ptr, size_t sz) + { + uint64_t h = 0xcbf29ce484222325; + for (size_t i = 0; i < sz; ++i) + h = (h ^ *(const uint8_t*)ptr++) * 0x100000001b3; + return h; + } +} + +} diff --git a/contrib/epee/include/hex.h b/contrib/epee/include/hex.h index e960da1d2..02600c320 100644 --- a/contrib/epee/include/hex.h +++ b/contrib/epee/include/hex.h @@ -33,6 +33,7 @@ #include <iosfwd> #include <string> +#include "wipeable_string.h" #include "span.h" namespace epee @@ -41,6 +42,8 @@ namespace epee { //! \return A std::string containing hex of `src`. static std::string string(const span<const std::uint8_t> src); + //! \return A epee::wipeable_string containing hex of `src`. + static epee::wipeable_string wipeable_string(const span<const std::uint8_t> src); //! \return An array containing hex of `src`. template<std::size_t N> @@ -59,6 +62,8 @@ namespace epee static void formatted(std::ostream& out, const span<const std::uint8_t> src); private: + template<typename T> T static convert(const span<const std::uint8_t> src); + //! Write `src` bytes as hex to `out`. `out` must be twice the length static void buffer_unchecked(char* out, const span<const std::uint8_t> src) noexcept; }; diff --git a/contrib/epee/include/wipeable_string.h b/contrib/epee/include/wipeable_string.h index 70d1a9586..4cebe5fdf 100644 --- a/contrib/epee/include/wipeable_string.h +++ b/contrib/epee/include/wipeable_string.h @@ -28,28 +28,43 @@ #pragma once +#include <boost/optional/optional_fwd.hpp> #include <stddef.h> #include <vector> #include <string> +#include "fnv1.h" namespace epee { class wipeable_string { public: + typedef char value_type; + wipeable_string() {} wipeable_string(const wipeable_string &other); wipeable_string(wipeable_string &&other); wipeable_string(const std::string &other); wipeable_string(std::string &&other); wipeable_string(const char *s); + wipeable_string(const char *s, size_t len); ~wipeable_string(); void wipe(); void push_back(char c); - void pop_back(); + void operator+=(char c); + void operator+=(const std::string &s); + void operator+=(const epee::wipeable_string &s); + void operator+=(const char *s); + void append(const char *ptr, size_t len); + char pop_back(); const char *data() const noexcept { return buffer.data(); } + char *data() noexcept { return buffer.data(); } size_t size() const noexcept { return buffer.size(); } + size_t length() const noexcept { return buffer.size(); } bool empty() const noexcept { return buffer.empty(); } + void trim(); + void split(std::vector<wipeable_string> &fields) const; + boost::optional<wipeable_string> parse_hexstr() const; void resize(size_t sz); void reserve(size_t sz); void clear(); @@ -65,3 +80,14 @@ namespace epee std::vector<char> buffer; }; } + +namespace std +{ + template<> struct hash<epee::wipeable_string> + { + size_t operator()(const epee::wipeable_string &s) const + { + return epee::fnv::FNV1a(s.data(), s.size()); + } + }; +} diff --git a/contrib/epee/src/hex.cpp b/contrib/epee/src/hex.cpp index c143b2dc2..5c8acc8be 100644 --- a/contrib/epee/src/hex.cpp +++ b/contrib/epee/src/hex.cpp @@ -52,17 +52,21 @@ namespace epee } } - std::string to_hex::string(const span<const std::uint8_t> src) + template<typename T> + T to_hex::convert(const span<const std::uint8_t> src) { if (std::numeric_limits<std::size_t>::max() / 2 < src.size()) throw std::range_error("hex_view::to_string exceeded maximum size"); - std::string out{}; + T out{}; out.resize(src.size() * 2); - buffer_unchecked(std::addressof(out[0]), src); + to_hex::buffer_unchecked((char*)out.data(), src); // can't see the non const version in wipeable_string?? return out; } + std::string to_hex::string(const span<const std::uint8_t> src) { return convert<std::string>(src); } + epee::wipeable_string to_hex::wipeable_string(const span<const std::uint8_t> src) { return convert<epee::wipeable_string>(src); } + void to_hex::buffer(std::ostream& out, const span<const std::uint8_t> src) { write_hex(std::ostreambuf_iterator<char>{out}, src); diff --git a/contrib/epee/src/wipeable_string.cpp b/contrib/epee/src/wipeable_string.cpp index 6ed4ee8a2..7c9722765 100644 --- a/contrib/epee/src/wipeable_string.cpp +++ b/contrib/epee/src/wipeable_string.cpp @@ -26,11 +26,22 @@ // 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. +#include <boost/optional/optional.hpp> #include <string.h> #include "memwipe.h" #include "misc_log_ex.h" #include "wipeable_string.h" +namespace +{ + int atolower(int c) + { + if (c >= 'A' && c <= 'Z') + c |= 32; + return c; + } +} + namespace epee { @@ -69,6 +80,12 @@ wipeable_string::wipeable_string(const char *s) memcpy(buffer.data(), s, size()); } +wipeable_string::wipeable_string(const char *s, size_t len) +{ + grow(len); + memcpy(buffer.data(), s, len); +} + wipeable_string::~wipeable_string() { wipe(); @@ -109,9 +126,100 @@ void wipeable_string::push_back(char c) buffer.back() = c; } -void wipeable_string::pop_back() +void wipeable_string::operator+=(char c) +{ + push_back(c); +} + +void wipeable_string::append(const char *ptr, size_t len) +{ + const size_t orgsz = size(); + CHECK_AND_ASSERT_THROW_MES(orgsz < std::numeric_limits<size_t>::max() - len, "Appended data too large"); + grow(orgsz + len); + if (len > 0) + memcpy(data() + orgsz, ptr, len); +} + +void wipeable_string::operator+=(const char *s) +{ + append(s, strlen(s)); +} + +void wipeable_string::operator+=(const epee::wipeable_string &s) +{ + append(s.data(), s.size()); +} + +void wipeable_string::operator+=(const std::string &s) +{ + append(s.c_str(), s.size()); +} + +void wipeable_string::trim() +{ + size_t prefix = 0; + while (prefix < size() && data()[prefix] == ' ') + ++prefix; + if (prefix > 0) + memmove(buffer.data(), buffer.data() + prefix, size() - prefix); + + size_t suffix = 0; + while (suffix < size()-prefix && data()[size() - 1 - prefix - suffix] == ' ') + ++suffix; + + resize(size() - prefix - suffix); +} + +void wipeable_string::split(std::vector<wipeable_string> &fields) const +{ + fields.clear(); + size_t len = size(); + const char *ptr = data(); + bool space = true; + while (len--) + { + const char c = *ptr++; + if (c != ' ') + { + if (space) + fields.push_back({}); + fields.back().push_back(c); + } + space = c == ' '; + } +} + +boost::optional<epee::wipeable_string> wipeable_string::parse_hexstr() const +{ + if (size() % 2 != 0) + return boost::none; + boost::optional<epee::wipeable_string> res = epee::wipeable_string(""); + const size_t len = size(); + const char *d = data(); + res->grow(0, len / 2); + static constexpr const char hex[] = u8"0123456789abcdef"; + for (size_t i = 0; i < len; i += 2) + { + char c = atolower(d[i]); + const char *ptr0 = strchr(hex, c); + if (!ptr0) + return boost::none; + c = atolower(d[i+1]); + const char *ptr1 = strchr(hex, c); + if (!ptr1) + return boost::none; + res->push_back(((ptr0-hex)<<4) | (ptr1-hex)); + } + return res; +} + +char wipeable_string::pop_back() { - resize(size() - 1); + const size_t sz = size(); + CHECK_AND_ASSERT_THROW_MES(sz > 0, "Popping from an empty string"); + const char c = buffer.back(); + resize(sz - 1); + return c; } void wipeable_string::resize(size_t sz) |