aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authormoneromooo-monero <moneromooo-monero@users.noreply.github.com>2018-07-07 00:03:15 +0100
committermoneromooo-monero <moneromooo-monero@users.noreply.github.com>2018-08-16 09:17:52 +0000
commitea37614efe518ff8f363ddf2465301687e04d977 (patch)
tree17a975260d2943c18f3a19c51bb6bc88dd26b98c /tests
parentMerge pull request #4191 (diff)
downloadmonero-ea37614efe518ff8f363ddf2465301687e04d977.tar.xz
wallet: wipe seed from memory where appropriate
Diffstat (limited to 'tests')
-rw-r--r--tests/unit_tests/CMakeLists.txt3
-rw-r--r--tests/unit_tests/mnemonics.cpp30
-rw-r--r--tests/unit_tests/wipeable_string.cpp204
3 files changed, 231 insertions, 6 deletions
diff --git a/tests/unit_tests/CMakeLists.txt b/tests/unit_tests/CMakeLists.txt
index 3c7414640..f47192ea9 100644
--- a/tests/unit_tests/CMakeLists.txt
+++ b/tests/unit_tests/CMakeLists.txt
@@ -72,7 +72,8 @@ set(unit_tests_sources
ringct.cpp
output_selection.cpp
vercmp.cpp
- ringdb.cpp)
+ ringdb.cpp
+ wipeable_string.cpp)
set(unit_tests_headers
unit_tests_utils.h)
diff --git a/tests/unit_tests/mnemonics.cpp b/tests/unit_tests/mnemonics.cpp
index 8fa3192b9..0b74a6b94 100644
--- a/tests/unit_tests/mnemonics.cpp
+++ b/tests/unit_tests/mnemonics.cpp
@@ -27,6 +27,8 @@
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "gtest/gtest.h"
+#include "wipeable_string.h"
+#include "mnemonics/language_base.h"
#include "mnemonics/electrum-words.h"
#include "crypto/crypto.h"
#include <stdlib.h>
@@ -74,14 +76,16 @@ namespace
void test_language(const Language::Base &language)
{
const std::vector<std::string> &word_list = language.get_word_list();
- std::string seed = "", return_seed = "";
+ epee::wipeable_string w_seed = "", w_return_seed = "";
+ std::string seed, return_seed;
// Generate a random seed without checksum
crypto::secret_key randkey;
for (size_t ii = 0; ii < sizeof(randkey); ++ii)
{
randkey.data[ii] = rand();
}
- crypto::ElectrumWords::bytes_to_words(randkey, seed, language.get_language_name());
+ crypto::ElectrumWords::bytes_to_words(randkey, w_seed, language.get_language_name());
+ seed = std::string(w_seed.data(), w_seed.size());
// remove the checksum word
const char *space = strrchr(seed.c_str(), ' ');
ASSERT_TRUE(space != NULL);
@@ -103,7 +107,8 @@ namespace
ASSERT_STREQ(language.get_language_name().c_str(), language_name.c_str());
// Convert the secret key back to seed
- crypto::ElectrumWords::bytes_to_words(key, return_seed, language.get_language_name());
+ crypto::ElectrumWords::bytes_to_words(key, w_return_seed, language.get_language_name());
+ return_seed = std::string(w_return_seed.data(), w_return_seed.size());
ASSERT_EQ(true, res);
std::cout << "Returned seed:\n";
std::cout << return_seed << std::endl;
@@ -126,8 +131,9 @@ namespace
std::cout << "Detected language: " << language_name << std::endl;
ASSERT_STREQ(language.get_language_name().c_str(), language_name.c_str());
- return_seed = "";
- crypto::ElectrumWords::bytes_to_words(key, return_seed, language.get_language_name());
+ w_return_seed = "";
+ crypto::ElectrumWords::bytes_to_words(key, w_return_seed, language.get_language_name());
+ return_seed = std::string(w_return_seed.data(), w_return_seed.size());
ASSERT_EQ(true, res);
std::cout << "Returned seed:\n";
std::cout << return_seed << std::endl;
@@ -202,3 +208,17 @@ TEST(mnemonics, language_detection_with_bad_checksum)
ASSERT_EQ(true, res);
ASSERT_STREQ(language_name.c_str(), "Português");
}
+
+TEST(mnemonics, utf8prefix)
+{
+ ASSERT_TRUE(Language::utf8prefix(epee::wipeable_string("foo"), 0) == "");
+ ASSERT_TRUE(Language::utf8prefix(epee::wipeable_string("foo"), 1) == "f");
+ ASSERT_TRUE(Language::utf8prefix(epee::wipeable_string("foo"), 2) == "fo");
+ ASSERT_TRUE(Language::utf8prefix(epee::wipeable_string("foo"), 3) == "foo");
+ ASSERT_TRUE(Language::utf8prefix(epee::wipeable_string("foo"), 4) == "foo");
+ ASSERT_TRUE(Language::utf8prefix(epee::wipeable_string("æon"), 0) == "");
+ ASSERT_TRUE(Language::utf8prefix(epee::wipeable_string("æon"), 1) == "æ");
+ ASSERT_TRUE(Language::utf8prefix(epee::wipeable_string("æon"), 2) == "æo");
+ ASSERT_TRUE(Language::utf8prefix(epee::wipeable_string("æon"), 3) == "æon");
+ ASSERT_TRUE(Language::utf8prefix(epee::wipeable_string("æon"), 4) == "æon");
+}
diff --git a/tests/unit_tests/wipeable_string.cpp b/tests/unit_tests/wipeable_string.cpp
new file mode 100644
index 000000000..5ea1c1729
--- /dev/null
+++ b/tests/unit_tests/wipeable_string.cpp
@@ -0,0 +1,204 @@
+// 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.
+
+#include <boost/optional/optional.hpp>
+#include <string.h>
+#include "gtest/gtest.h"
+
+#include "misc_log_ex.h"
+#include "wipeable_string.h"
+
+TEST(wipeable_string, ctor)
+{
+ epee::wipeable_string s0;
+ ASSERT_EQ(s0.size(), 0);
+
+ epee::wipeable_string s1(std::string("foo"));
+ ASSERT_EQ(s1.size(), 3);
+ ASSERT_TRUE(!memcmp(s1.data(), "foo", s1.size()));
+
+ epee::wipeable_string s2(std::string("bar"));
+ ASSERT_EQ(s2.size(), 3);
+ ASSERT_TRUE(!memcmp(s2.data(), "bar", s2.size()));
+
+ epee::wipeable_string s3(std::string("quux"));
+ ASSERT_EQ(s3.size(), 4);
+ ASSERT_TRUE(!memcmp(s3.data(), "quux", s3.size()));
+}
+
+TEST(wipeable_string, wipe)
+{
+ epee::wipeable_string s0(std::string("foo"));
+ ASSERT_EQ(s0.size(), 3);
+ s0.wipe();
+ ASSERT_EQ(s0.size(), 3);
+ ASSERT_TRUE(!memcmp(s0.data(), "\0\0\0", 3));
+}
+
+TEST(wipeable_string, clear)
+{
+ epee::wipeable_string s0(std::string("foo"));
+ ASSERT_EQ(s0.size(), 3);
+ s0.clear();
+ ASSERT_EQ(s0.size(), 0);
+}
+
+TEST(wipeable_string, push_back)
+{
+ epee::wipeable_string s0(std::string("fo"));
+ ASSERT_EQ(s0.size(), 2);
+ s0.push_back('o');
+ ASSERT_EQ(s0.size(), 3);
+ ASSERT_TRUE(!memcmp(s0.data(), "foo", s0.size()));
+}
+
+TEST(wipeable_string, append_char)
+{
+ epee::wipeable_string s0(std::string("fo"));
+ ASSERT_EQ(s0.size(), 2);
+ s0 += 'o';
+ ASSERT_EQ(s0.size(), 3);
+ ASSERT_TRUE(!memcmp(s0.data(), "foo", s0.size()));
+}
+
+TEST(wipeable_string, append_string)
+{
+ epee::wipeable_string s0(std::string("foo"));
+ ASSERT_EQ(s0.size(), 3);
+ s0 += "bar";
+ ASSERT_EQ(s0.size(), 6);
+ ASSERT_TRUE(!memcmp(s0.data(), "foobar", s0.size()));
+}
+
+TEST(wipeable_string, empty)
+{
+ epee::wipeable_string s0;
+ ASSERT_TRUE(s0.empty());
+ s0.push_back(' ');
+ ASSERT_FALSE(s0.empty());
+ ASSERT_EQ(s0.pop_back(), ' ');
+ ASSERT_TRUE(s0.empty());
+}
+
+TEST(wipeable_string, pop_back)
+{
+ epee::wipeable_string s = "test";
+ ASSERT_EQ(s.size(), 4);
+ ASSERT_EQ(s.pop_back(), 't');
+ ASSERT_EQ(s.size(), 3);
+ ASSERT_TRUE(!memcmp(s.data(), "tes", s.size()));
+}
+
+TEST(wipeable_string, equal)
+{
+ epee::wipeable_string s0 = "foo";
+ epee::wipeable_string s1 = "bar";
+ epee::wipeable_string s0_2 = "foo";
+ ASSERT_TRUE(s0 == s0);
+ ASSERT_TRUE(s0 == s0_2);
+ ASSERT_TRUE(s1 == s1);
+ ASSERT_FALSE(s1 == s0);
+ ASSERT_FALSE(s1 == s0_2);
+}
+
+TEST(wipeable_string, not_equal)
+{
+ epee::wipeable_string s0 = "foo";
+ epee::wipeable_string s1 = "bar";
+ epee::wipeable_string s0_2 = "foo";
+ ASSERT_FALSE(s0 != s0);
+ ASSERT_FALSE(s0 != s0_2);
+ ASSERT_FALSE(s1 != s1);
+ ASSERT_TRUE(s1 != s0);
+ ASSERT_TRUE(s1 != s0_2);
+}
+
+static epee::wipeable_string trimmed(const char *s)
+{
+ epee::wipeable_string str(s);
+ str.trim();
+ return str;
+}
+
+TEST(wipeable_string, trim)
+{
+ ASSERT_TRUE(trimmed("") == "");
+ ASSERT_TRUE(trimmed(" ") == "");
+ ASSERT_TRUE(trimmed(" ") == "");
+ ASSERT_TRUE(trimmed("a") == "a");
+ ASSERT_TRUE(trimmed(" a") == "a");
+ ASSERT_TRUE(trimmed(" a") == "a");
+ ASSERT_TRUE(trimmed("a ") == "a");
+ ASSERT_TRUE(trimmed("a ") == "a");
+ ASSERT_TRUE(trimmed(" a ") == "a");
+ ASSERT_TRUE(trimmed(" a ") == "a");
+ ASSERT_TRUE(trimmed(" ab ") == "ab");
+ ASSERT_TRUE(trimmed(" a b ") == "a b");
+ ASSERT_TRUE(trimmed(" a b ") == "a b");
+}
+
+static bool check_split(const char *s, const std::vector<epee::wipeable_string> &v)
+{
+ epee::wipeable_string str(s);
+ std::vector<epee::wipeable_string> fields;
+ str.split(fields);
+ return v == fields;
+}
+
+TEST(wipeable_string, split)
+{
+ ASSERT_TRUE(check_split("", {}));
+ ASSERT_TRUE(check_split("foo", {"foo"}));
+ ASSERT_TRUE(check_split(" foo ", {"foo"}));
+ ASSERT_TRUE(check_split("foo bar", {"foo", "bar"}));
+ ASSERT_TRUE(check_split("foo bar", {"foo", "bar"}));
+ ASSERT_TRUE(check_split("foo bar baz", {"foo", "bar", "baz"}));
+ ASSERT_TRUE(check_split(" foo bar baz ", {"foo", "bar", "baz"}));
+ ASSERT_TRUE(check_split(" foo bar baz", {"foo", "bar", "baz"}));
+ ASSERT_TRUE(check_split("foo bar baz ", {"foo", "bar", "baz"}));
+}
+
+TEST(wipeable_string, parse_hexstr)
+{
+ boost::optional<epee::wipeable_string> s;
+
+ ASSERT_EQ(boost::none, epee::wipeable_string("x").parse_hexstr());
+ ASSERT_EQ(boost::none, epee::wipeable_string("x0000000000000000").parse_hexstr());
+ ASSERT_EQ(boost::none, epee::wipeable_string("0000000000000000x").parse_hexstr());
+ ASSERT_EQ(boost::none, epee::wipeable_string("0").parse_hexstr());
+ ASSERT_EQ(boost::none, epee::wipeable_string("000").parse_hexstr());
+
+ ASSERT_TRUE((s = epee::wipeable_string("").parse_hexstr()));
+ ASSERT_EQ(*s, "");
+ ASSERT_TRUE((s = epee::wipeable_string("00").parse_hexstr()));
+ ASSERT_EQ(*s, epee::wipeable_string("", 1));
+ ASSERT_TRUE((s = epee::wipeable_string("41").parse_hexstr()));
+ ASSERT_EQ(*s, epee::wipeable_string("A"));
+ ASSERT_TRUE((s = epee::wipeable_string("414243").parse_hexstr()));
+ ASSERT_EQ(*s, epee::wipeable_string("ABC"));
+}