Electroneum
wipeable_string.cpp
Go to the documentation of this file.
1 // Copyright (c) 2017-2019, The Monero Project
2 //
3 // All rights reserved.
4 //
5 // Redistribution and use in source and binary forms, with or without modification, are
6 // permitted provided that the following conditions are met:
7 //
8 // 1. Redistributions of source code must retain the above copyright notice, this list of
9 // conditions and the following disclaimer.
10 //
11 // 2. Redistributions in binary form must reproduce the above copyright notice, this list
12 // of conditions and the following disclaimer in the documentation and/or other
13 // materials provided with the distribution.
14 //
15 // 3. Neither the name of the copyright holder nor the names of its contributors may be
16 // used to endorse or promote products derived from this software without specific
17 // prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
20 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
22 // THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
27 // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 
29 #include <boost/optional/optional.hpp>
30 #include <string.h>
31 #include "memwipe.h"
32 #include "misc_log_ex.h"
33 #include "wipeable_string.h"
34 
35 static constexpr const char hex[] = u8"0123456789abcdef";
36 
37 namespace
38 {
39  int atolower(int c)
40  {
41  if (c >= 'A' && c <= 'Z')
42  c |= 32;
43  return c;
44  }
45 }
46 
47 namespace epee
48 {
49 
51  buffer(other.buffer)
52 {
53 }
54 
56 {
57  if (&other == this)
58  return;
59  buffer = std::move(other.buffer);
60 }
61 
63 {
64  grow(other.size());
65  if (size() > 0)
66  memcpy(buffer.data(), other.c_str(), size());
67 }
68 
70 {
71  grow(other.size());
72  if (size() > 0)
73  memcpy(buffer.data(), other.c_str(), size());
74  if (!other.empty())
75  {
76  memwipe(&other[0], other.size()); // we're kinda left with this again aren't we
77  other = std::string();
78  }
79 }
80 
82 {
83  grow(strlen(s));
84  if (size() > 0)
85  memcpy(buffer.data(), s, size());
86 }
87 
88 wipeable_string::wipeable_string(const char *s, size_t len)
89 {
90  grow(len);
91  memcpy(buffer.data(), s, len);
92 }
93 
95 {
96  wipe();
97 }
98 
100 {
101  if (!buffer.empty())
102  memwipe(buffer.data(), buffer.size() * sizeof(char));
103 }
104 
105 void wipeable_string::grow(size_t sz, size_t reserved)
106 {
107  if (reserved < sz)
108  reserved = sz;
109  if (reserved <= buffer.capacity())
110  {
111  if (sz < buffer.size())
112  memwipe(buffer.data() + sz, buffer.size() - sz);
113  buffer.resize(sz);
114  return;
115  }
116  size_t old_sz = buffer.size();
117  std::unique_ptr<char[]> tmp{new char[old_sz]};
118  if (old_sz > 0)
119  {
120  memcpy(tmp.get(), buffer.data(), old_sz * sizeof(char));
121  memwipe(buffer.data(), old_sz * sizeof(char));
122  }
123  buffer.reserve(reserved);
124  buffer.resize(sz);
125  if (old_sz > 0)
126  {
127  memcpy(buffer.data(), tmp.get(), old_sz * sizeof(char));
128  memwipe(tmp.get(), old_sz * sizeof(char));
129  }
130 }
131 
133 {
134  grow(size() + 1);
135  buffer.back() = c;
136 }
137 
139 {
140  push_back(c);
141 }
142 
143 void wipeable_string::append(const char *ptr, size_t len)
144 {
145  const size_t orgsz = size();
146  CHECK_AND_ASSERT_THROW_MES(orgsz < std::numeric_limits<size_t>::max() - len, "Appended data too large");
147  grow(orgsz + len);
148  if (len > 0)
149  memcpy(data() + orgsz, ptr, len);
150 }
151 
152 void wipeable_string::operator+=(const char *s)
153 {
154  append(s, strlen(s));
155 }
156 
158 {
159  append(s.data(), s.size());
160 }
161 
163 {
164  append(s.c_str(), s.size());
165 }
166 
168 {
169  size_t prefix = 0;
170  while (prefix < size() && data()[prefix] == ' ')
171  ++prefix;
172  if (prefix > 0)
173  memmove(buffer.data(), buffer.data() + prefix, size() - prefix);
174 
175  size_t suffix = 0;
176  while (suffix < size()-prefix && data()[size() - 1 - prefix - suffix] == ' ')
177  ++suffix;
178 
179  resize(size() - prefix - suffix);
180 }
181 
182 void wipeable_string::split(std::vector<wipeable_string> &fields) const
183 {
184  fields.clear();
185  size_t len = size();
186  const char *ptr = data();
187  bool space = true;
188  while (len--)
189  {
190  const char c = *ptr++;
191  if (c != ' ')
192  {
193  if (space)
194  fields.push_back({});
195  fields.back().push_back(c);
196  }
197  space = c == ' ';
198  }
199 }
200 
201 boost::optional<epee::wipeable_string> wipeable_string::parse_hexstr() const
202 {
203  if (size() % 2 != 0)
204  return boost::none;
205  boost::optional<epee::wipeable_string> res = epee::wipeable_string("");
206  const size_t len = size();
207  const char *d = data();
208  res->grow(0, len / 2);
209  for (size_t i = 0; i < len; i += 2)
210  {
211  char c = atolower(d[i]);
212  const char *ptr0 = strchr(hex, c);
213  if (!ptr0)
214  return boost::none;
215  c = atolower(d[i+1]);
216  const char *ptr1 = strchr(hex, c);
217  if (!ptr1)
218  return boost::none;
219  res->push_back(((ptr0-hex)<<4) | (ptr1-hex));
220  }
221  return res;
222 }
223 
225 {
226  const size_t sz = size();
227  CHECK_AND_ASSERT_THROW_MES(sz > 0, "Popping from an empty string");
228  const char c = buffer.back();
229  resize(sz - 1);
230  return c;
231 }
232 
233 void wipeable_string::resize(size_t sz)
234 {
235  grow(sz);
236 }
237 
239 {
240  grow(size(), sz);
241 }
242 
244 {
245  resize(0);
246 }
247 
249 {
250  if (&other != this)
251  buffer = std::move(other.buffer);
252  return *this;
253 }
254 
256 {
257  if (&other != this)
258  buffer = other.buffer;
259  return *this;
260 }
261 
262 }
unsigned char u8
Definition: chacha_private.h:9
void split(std::vector< wipeable_string > &fields) const
void append(const char *ptr, size_t len)
const char * data() const noexcept
boost::optional< wipeable_string > parse_hexstr() const
wipeable_string & operator=(wipeable_string &&other)
size_t size() const noexcept
void * memcpy(void *a, const void *b, size_t c)
void * memmove(void *a, const void *b, size_t c)
const char * res
Definition: hmac_keccak.cpp:41
void * memwipe(void *src, size_t n)
#define CHECK_AND_ASSERT_THROW_MES(expr, message)
Definition: misc_log_ex.h:173
::std::string string
Definition: gtest-port.h:1097
const T & move(const T &t)
Definition: gtest-port.h:1317