Crypto++  8.0
Free C++ class library of cryptographic schemes
misc.cpp
1 // misc.cpp - originally written and placed in the public domain by Wei Dai
2 
3 #include "pch.h"
4 #include "config.h"
5 
6 #if CRYPTOPP_MSC_VERSION
7 # pragma warning(disable: 4189)
8 # if (CRYPTOPP_MSC_VERSION >= 1400)
9 # pragma warning(disable: 6237)
10 # endif
11 #endif
12 
13 #ifndef CRYPTOPP_IMPORTS
14 
15 #include "misc.h"
16 #include "words.h"
17 #include "words.h"
18 #include "stdcpp.h"
19 #include "integer.h"
20 
21 // for memalign
22 #if defined(CRYPTOPP_MEMALIGN_AVAILABLE) || defined(CRYPTOPP_MM_MALLOC_AVAILABLE) || defined(QNX)
23 # include <malloc.h>
24 #endif
25 // for posix_memalign
26 #if defined(CRYPTOPP_POSIX_MEMALIGN_AVAILABLE)
27 # include <stdlib.h>
28 #endif
29 
30 NAMESPACE_BEGIN(CryptoPP)
31 
32 void xorbuf(byte *buf, const byte *mask, size_t count)
33 {
34  CRYPTOPP_ASSERT(buf != NULLPTR);
35  CRYPTOPP_ASSERT(mask != NULLPTR);
36  CRYPTOPP_ASSERT(count > 0);
37 
38  size_t i=0;
39  if (IsAligned<word32>(buf) && IsAligned<word32>(mask))
40  {
41  if (!CRYPTOPP_BOOL_SLOW_WORD64 && IsAligned<word64>(buf) && IsAligned<word64>(mask))
42  {
43  for (i=0; i<count/8; i++)
44  ((word64*)(void*)buf)[i] ^= ((word64*)(void*)mask)[i];
45  count -= 8*i;
46  if (!count)
47  return;
48  buf += 8*i;
49  mask += 8*i;
50  }
51 
52  for (i=0; i<count/4; i++)
53  ((word32*)(void*)buf)[i] ^= ((word32*)(void*)mask)[i];
54  count -= 4*i;
55  if (!count)
56  return;
57  buf += 4*i;
58  mask += 4*i;
59  }
60 
61  for (i=0; i<count; i++)
62  buf[i] ^= mask[i];
63 }
64 
65 void xorbuf(byte *output, const byte *input, const byte *mask, size_t count)
66 {
67  CRYPTOPP_ASSERT(output != NULLPTR);
68  CRYPTOPP_ASSERT(input != NULLPTR);
69  CRYPTOPP_ASSERT(count > 0);
70 
71  size_t i=0;
72  if (IsAligned<word32>(output) && IsAligned<word32>(input) && IsAligned<word32>(mask))
73  {
74  if (!CRYPTOPP_BOOL_SLOW_WORD64 && IsAligned<word64>(output) && IsAligned<word64>(input) && IsAligned<word64>(mask))
75  {
76  for (i=0; i<count/8; i++)
77  ((word64*)(void*)output)[i] = ((word64*)(void*)input)[i] ^ ((word64*)(void*)mask)[i];
78  count -= 8*i;
79  if (!count)
80  return;
81  output += 8*i;
82  input += 8*i;
83  mask += 8*i;
84  }
85 
86  for (i=0; i<count/4; i++)
87  ((word32*)(void*)output)[i] = ((word32*)(void*)input)[i] ^ ((word32*)(void*)mask)[i];
88  count -= 4*i;
89  if (!count)
90  return;
91  output += 4*i;
92  input += 4*i;
93  mask += 4*i;
94  }
95 
96  for (i=0; i<count; i++)
97  output[i] = input[i] ^ mask[i];
98 }
99 
100 bool VerifyBufsEqual(const byte *buf, const byte *mask, size_t count)
101 {
102  CRYPTOPP_ASSERT(buf != NULLPTR);
103  CRYPTOPP_ASSERT(mask != NULLPTR);
104  CRYPTOPP_ASSERT(count > 0);
105 
106  size_t i=0;
107  byte acc8 = 0;
108 
109  if (IsAligned<word32>(buf) && IsAligned<word32>(mask))
110  {
111  word32 acc32 = 0;
112  if (!CRYPTOPP_BOOL_SLOW_WORD64 && IsAligned<word64>(buf) && IsAligned<word64>(mask))
113  {
114  word64 acc64 = 0;
115  for (i=0; i<count/8; i++)
116  acc64 |= ((word64*)(void*)buf)[i] ^ ((word64*)(void*)mask)[i];
117  count -= 8*i;
118  if (!count)
119  return acc64 == 0;
120  buf += 8*i;
121  mask += 8*i;
122  acc32 = word32(acc64) | word32(acc64>>32);
123  }
124 
125  for (i=0; i<count/4; i++)
126  acc32 |= ((word32*)(void*)buf)[i] ^ ((word32*)(void*)mask)[i];
127  count -= 4*i;
128  if (!count)
129  return acc32 == 0;
130  buf += 4*i;
131  mask += 4*i;
132  acc8 = byte(acc32) | byte(acc32>>8) | byte(acc32>>16) | byte(acc32>>24);
133  }
134 
135  for (i=0; i<count; i++)
136  acc8 |= buf[i] ^ mask[i];
137  return acc8 == 0;
138 }
139 
140 std::string StringNarrow(const wchar_t *str, bool throwOnError)
141 {
142  CRYPTOPP_ASSERT(str);
143  std::string result;
144 
145  // Safer functions on Windows for C&A, https://github.com/weidai11/cryptopp/issues/55
146 #if (CRYPTOPP_MSC_VERSION >= 1400)
147  size_t len=0, size=0;
148  errno_t err = 0;
149 
150  //const wchar_t* ptr = str;
151  //while (*ptr++) len++;
152  len = wcslen(str)+1;
153 
154  err = wcstombs_s(&size, NULLPTR, 0, str, len*sizeof(wchar_t));
155  CRYPTOPP_ASSERT(err == 0);
156  if (err != 0)
157  {
158  if (throwOnError)
159  throw InvalidArgument("StringNarrow: wcstombs_s() call failed with error " + IntToString(err));
160  else
161  return std::string();
162  }
163 
164  result.resize(size);
165  err = wcstombs_s(&size, &result[0], size, str, len*sizeof(wchar_t));
166  CRYPTOPP_ASSERT(err == 0);
167  if (err != 0)
168  {
169  if (throwOnError)
170  throw InvalidArgument("StringNarrow: wcstombs_s() call failed with error " + IntToString(err));
171  else
172  return std::string();
173  }
174 
175  // The safe routine's size includes the NULL.
176  if (!result.empty() && result[size - 1] == '\0')
177  result.erase(size - 1);
178 #else
179  size_t size = wcstombs(NULLPTR, str, 0);
180  CRYPTOPP_ASSERT(size != (size_t)-1);
181  if (size == (size_t)-1)
182  {
183  if (throwOnError)
184  throw InvalidArgument("StringNarrow: wcstombs() call failed");
185  else
186  return std::string();
187  }
188 
189  result.resize(size);
190  size = wcstombs(&result[0], str, size);
191  CRYPTOPP_ASSERT(size != (size_t)-1);
192  if (size == (size_t)-1)
193  {
194  if (throwOnError)
195  throw InvalidArgument("StringNarrow: wcstombs() call failed");
196  else
197  return std::string();
198  }
199 #endif
200 
201  return result;
202 }
203 
204 std::wstring StringWiden(const char *str, bool throwOnError)
205 {
206  CRYPTOPP_ASSERT(str);
207  std::wstring result;
208 
209  // Safer functions on Windows for C&A, https://github.com/weidai11/cryptopp/issues/55
210 #if (CRYPTOPP_MSC_VERSION >= 1400)
211  size_t len=0, size=0;
212  errno_t err = 0;
213 
214  //const char* ptr = str;
215  //while (*ptr++) len++;
216  len = std::strlen(str)+1;
217 
218  err = mbstowcs_s(&size, NULLPTR, 0, str, len);
219  CRYPTOPP_ASSERT(err == 0);
220  if (err != 0)
221  {
222  if (throwOnError)
223  throw InvalidArgument("StringWiden: wcstombs_s() call failed with error " + IntToString(err));
224  else
225  return std::wstring();
226  }
227 
228  result.resize(size);
229  err = mbstowcs_s(&size, &result[0], size, str, len);
230  CRYPTOPP_ASSERT(err == 0);
231  if (err != 0)
232  {
233  if (throwOnError)
234  throw InvalidArgument("StringWiden: wcstombs_s() call failed with error " + IntToString(err));
235  else
236  return std::wstring();
237  }
238 
239  // The safe routine's size includes the NULL.
240  if (!result.empty() && result[size - 1] == '\0')
241  result.erase(size - 1);
242 #else
243  size_t size = mbstowcs(NULLPTR, str, 0);
244  CRYPTOPP_ASSERT(size != (size_t)-1);
245  if (size == (size_t)-1)
246  {
247  if (throwOnError)
248  throw InvalidArgument("StringWiden: mbstowcs() call failed");
249  else
250  return std::wstring();
251  }
252 
253  result.resize(size);
254  size = mbstowcs(&result[0], str, size);
255  CRYPTOPP_ASSERT(size != (size_t)-1);
256  if (size == (size_t)-1)
257  {
258  if (throwOnError)
259  throw InvalidArgument("StringWiden: mbstowcs() call failed");
260  else
261  return std::wstring();
262  }
263 #endif
264 
265  return result;
266 }
267 
269 {
270  using std::new_handler;
271  using std::set_new_handler;
272 
273  new_handler newHandler = set_new_handler(NULLPTR);
274  if (newHandler)
275  set_new_handler(newHandler);
276 
277  if (newHandler)
278  newHandler();
279  else
280  throw std::bad_alloc();
281 }
282 
283 void * AlignedAllocate(size_t size)
284 {
285  byte *p;
286 #if defined(CRYPTOPP_MM_MALLOC_AVAILABLE)
287  while ((p = (byte *)_mm_malloc(size, 16)) == NULLPTR)
288 #elif defined(CRYPTOPP_MEMALIGN_AVAILABLE)
289  while ((p = (byte *)memalign(16, size)) == NULLPTR)
290 #elif defined(CRYPTOPP_MALLOC_ALIGNMENT_IS_16)
291  while ((p = (byte *)malloc(size)) == NULLPTR)
292 #elif defined(CRYPTOPP_POSIX_MEMALIGN_AVAILABLE)
293  while (posix_memalign(reinterpret_cast<void**>(&p), 16, size) != 0)
294 #else
295  while ((p = (byte *)malloc(size + 16)) == NULLPTR)
296 #endif
297  CallNewHandler();
298 
299 #ifdef CRYPTOPP_NO_ALIGNED_ALLOC
300  size_t adjustment = 16-((size_t)p%16);
301  CRYPTOPP_ASSERT(adjustment > 0);
302  p += adjustment;
303  p[-1] = (byte)adjustment;
304 #endif
305 
306  // If this assert fires then there are problems that need
307  // to be fixed. Please open a bug report.
309  return p;
310 }
311 
312 void AlignedDeallocate(void *p)
313 {
314 #ifdef CRYPTOPP_MM_MALLOC_AVAILABLE
315  _mm_free(p);
316 #elif defined(CRYPTOPP_NO_ALIGNED_ALLOC)
317  p = (byte *)p - ((byte *)p)[-1];
318  free(p);
319 #else
320  free(p);
321 #endif
322 }
323 
324 void * UnalignedAllocate(size_t size)
325 {
326  void *p;
327  while ((p = malloc(size)) == NULLPTR)
328  CallNewHandler();
329  return p;
330 }
331 
332 void UnalignedDeallocate(void *p)
333 {
334  free(p);
335 }
336 
337 NAMESPACE_END
338 
339 #endif
An invalid argument was detected.
Definition: cryptlib.h:202
std::string StringNarrow(const wchar_t *str, bool throwOnError=true)
Converts a wide character C-string to a multibyte string.
Definition: misc.cpp:140
Utility functions for the Crypto++ library.
void AlignedDeallocate(void *ptr)
Frees a buffer allocated with AlignedAllocate.
Definition: misc.cpp:312
Library configuration file.
Common C++ header files.
bool IsAlignedOn(const void *ptr, unsigned int alignment)
Determines whether ptr is aligned to a minimum value.
Definition: misc.h:1111
void * UnalignedAllocate(size_t size)
Allocates a buffer.
Definition: misc.cpp:324
void CallNewHandler()
Attempts to reclaim unused memory.
Definition: misc.cpp:268
Precompiled header file.
#define CRYPTOPP_ASSERT(exp)
Debugging and diagnostic assertion.
Definition: trap.h:69
std::wstring StringWiden(const char *str, bool throwOnError=true)
Converts a multibyte C-string to a wide character string.
Definition: misc.cpp:204
void xorbuf(byte *buf, const byte *mask, size_t count)
Performs an XOR of a buffer with a mask.
Definition: misc.cpp:32
std::string IntToString(T value, unsigned int base=10)
Converts a value to a string.
Definition: misc.h:604
bool VerifyBufsEqual(const byte *buf1, const byte *buf2, size_t count)
Performs a near constant-time comparison of two equally sized buffers.
Definition: misc.cpp:100
Multiple precision integer with arithmetic operations.
Crypto++ library namespace.
void UnalignedDeallocate(void *ptr)
Frees a buffer allocated with UnalignedAllocate.
Definition: misc.cpp:332
void * AlignedAllocate(size_t size)
Allocates a buffer on 16-byte boundary.
Definition: misc.cpp:283