Crypto++  8.2
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 "trap.h"
17 #include "words.h"
18 #include "stdcpp.h"
19 #include "integer.h"
20 #include "secblock.h"
21 
22 NAMESPACE_BEGIN(CryptoPP)
23 
24 byte* BytePtr(SecByteBlock& str)
25 {
26  // Caller wants a writeable pointer
27  CRYPTOPP_ASSERT(str.empty() == false);
28 
29  if (str.empty())
30  return NULLPTR;
31  return reinterpret_cast<byte*>(str.data());
32 }
33 
34 const byte* ConstBytePtr(const SecByteBlock& str)
35 {
36  if (str.empty())
37  return NULLPTR;
38  return reinterpret_cast<const byte*>(str.data());
39 }
40 
41 size_t BytePtrSize(const SecByteBlock& str)
42 {
43  return str.size();
44 }
45 
46 void xorbuf(byte *buf, const byte *mask, size_t count)
47 {
48  CRYPTOPP_ASSERT(buf != NULLPTR);
49  CRYPTOPP_ASSERT(mask != NULLPTR);
50  CRYPTOPP_ASSERT(count > 0);
51 
52  size_t i=0;
53  if (IsAligned<word32>(buf) && IsAligned<word32>(mask))
54  {
55  if (!CRYPTOPP_BOOL_SLOW_WORD64 && IsAligned<word64>(buf) && IsAligned<word64>(mask))
56  {
57  for (i=0; i<count/8; i++)
58  ((word64*)(void*)buf)[i] ^= ((word64*)(void*)mask)[i];
59  count -= 8*i;
60  if (!count)
61  return;
62  buf += 8*i;
63  mask += 8*i;
64  }
65 
66  for (i=0; i<count/4; i++)
67  ((word32*)(void*)buf)[i] ^= ((word32*)(void*)mask)[i];
68  count -= 4*i;
69  if (!count)
70  return;
71  buf += 4*i;
72  mask += 4*i;
73  }
74 
75  for (i=0; i<count; i++)
76  buf[i] ^= mask[i];
77 }
78 
79 void xorbuf(byte *output, const byte *input, const byte *mask, size_t count)
80 {
81  CRYPTOPP_ASSERT(output != NULLPTR);
82  CRYPTOPP_ASSERT(input != NULLPTR);
83  CRYPTOPP_ASSERT(count > 0);
84 
85  size_t i=0;
86  if (IsAligned<word32>(output) && IsAligned<word32>(input) && IsAligned<word32>(mask))
87  {
88  if (!CRYPTOPP_BOOL_SLOW_WORD64 && IsAligned<word64>(output) && IsAligned<word64>(input) && IsAligned<word64>(mask))
89  {
90  for (i=0; i<count/8; i++)
91  ((word64*)(void*)output)[i] = ((word64*)(void*)input)[i] ^ ((word64*)(void*)mask)[i];
92  count -= 8*i;
93  if (!count)
94  return;
95  output += 8*i;
96  input += 8*i;
97  mask += 8*i;
98  }
99 
100  for (i=0; i<count/4; i++)
101  ((word32*)(void*)output)[i] = ((word32*)(void*)input)[i] ^ ((word32*)(void*)mask)[i];
102  count -= 4*i;
103  if (!count)
104  return;
105  output += 4*i;
106  input += 4*i;
107  mask += 4*i;
108  }
109 
110  for (i=0; i<count; i++)
111  output[i] = input[i] ^ mask[i];
112 }
113 
114 bool VerifyBufsEqual(const byte *buf, const byte *mask, size_t count)
115 {
116  CRYPTOPP_ASSERT(buf != NULLPTR);
117  CRYPTOPP_ASSERT(mask != NULLPTR);
118  // CRYPTOPP_ASSERT(count > 0);
119 
120  size_t i=0;
121  byte acc8 = 0;
122 
123  if (IsAligned<word32>(buf) && IsAligned<word32>(mask) && count)
124  {
125  word32 acc32 = 0;
126  if (!CRYPTOPP_BOOL_SLOW_WORD64 && IsAligned<word64>(buf) && IsAligned<word64>(mask))
127  {
128  word64 acc64 = 0;
129  for (i=0; i<count/8; i++)
130  acc64 |= ((word64*)(void*)buf)[i] ^ ((word64*)(void*)mask)[i];
131  count -= 8*i;
132  if (!count)
133  return acc64 == 0;
134  buf += 8*i;
135  mask += 8*i;
136  acc32 = word32(acc64) | word32(acc64>>32);
137  }
138 
139  for (i=0; i<count/4; i++)
140  acc32 |= ((word32*)(void*)buf)[i] ^ ((word32*)(void*)mask)[i];
141  count -= 4*i;
142  if (!count)
143  return acc32 == 0;
144  buf += 4*i;
145  mask += 4*i;
146  acc8 = byte(acc32) | byte(acc32>>8) | byte(acc32>>16) | byte(acc32>>24);
147  }
148 
149  for (i=0; i<count; i++)
150  acc8 |= buf[i] ^ mask[i];
151  return acc8 == 0;
152 }
153 
154 std::string StringNarrow(const wchar_t *str, bool throwOnError)
155 {
156  CRYPTOPP_ASSERT(str);
157  std::string result;
158 
159  // Safer functions on Windows for C&A, https://github.com/weidai11/cryptopp/issues/55
160 #if (CRYPTOPP_MSC_VERSION >= 1400)
161  size_t len=0, size=0;
162  errno_t err = 0;
163 
164  //const wchar_t* ptr = str;
165  //while (*ptr++) len++;
166  len = wcslen(str)+1;
167 
168  err = wcstombs_s(&size, NULLPTR, 0, str, len*sizeof(wchar_t));
169  CRYPTOPP_ASSERT(err == 0);
170  if (err != 0)
171  {
172  if (throwOnError)
173  throw InvalidArgument("StringNarrow: wcstombs_s() call failed with error " + IntToString(err));
174  else
175  return std::string();
176  }
177 
178  result.resize(size);
179  err = wcstombs_s(&size, &result[0], size, str, len*sizeof(wchar_t));
180  CRYPTOPP_ASSERT(err == 0);
181  if (err != 0)
182  {
183  if (throwOnError)
184  throw InvalidArgument("StringNarrow: wcstombs_s() call failed with error " + IntToString(err));
185  else
186  return std::string();
187  }
188 
189  // The safe routine's size includes the NULL.
190  if (!result.empty() && result[size - 1] == '\0')
191  result.erase(size - 1);
192 #else
193  size_t size = wcstombs(NULLPTR, str, 0);
194  CRYPTOPP_ASSERT(size != (size_t)-1);
195  if (size == (size_t)-1)
196  {
197  if (throwOnError)
198  throw InvalidArgument("StringNarrow: wcstombs() call failed");
199  else
200  return std::string();
201  }
202 
203  result.resize(size);
204  size = wcstombs(&result[0], str, size);
205  CRYPTOPP_ASSERT(size != (size_t)-1);
206  if (size == (size_t)-1)
207  {
208  if (throwOnError)
209  throw InvalidArgument("StringNarrow: wcstombs() call failed");
210  else
211  return std::string();
212  }
213 #endif
214 
215  return result;
216 }
217 
218 std::wstring StringWiden(const char *str, bool throwOnError)
219 {
220  CRYPTOPP_ASSERT(str);
221  std::wstring result;
222 
223  // Safer functions on Windows for C&A, https://github.com/weidai11/cryptopp/issues/55
224 #if (CRYPTOPP_MSC_VERSION >= 1400)
225  size_t len=0, size=0;
226  errno_t err = 0;
227 
228  //const char* ptr = str;
229  //while (*ptr++) len++;
230  len = std::strlen(str)+1;
231 
232  err = mbstowcs_s(&size, NULLPTR, 0, str, len);
233  CRYPTOPP_ASSERT(err == 0);
234  if (err != 0)
235  {
236  if (throwOnError)
237  throw InvalidArgument("StringWiden: wcstombs_s() call failed with error " + IntToString(err));
238  else
239  return std::wstring();
240  }
241 
242  result.resize(size);
243  err = mbstowcs_s(&size, &result[0], size, str, len);
244  CRYPTOPP_ASSERT(err == 0);
245  if (err != 0)
246  {
247  if (throwOnError)
248  throw InvalidArgument("StringWiden: wcstombs_s() call failed with error " + IntToString(err));
249  else
250  return std::wstring();
251  }
252 
253  // The safe routine's size includes the NULL.
254  if (!result.empty() && result[size - 1] == '\0')
255  result.erase(size - 1);
256 #else
257  size_t size = mbstowcs(NULLPTR, str, 0);
258  CRYPTOPP_ASSERT(size != (size_t)-1);
259  if (size == (size_t)-1)
260  {
261  if (throwOnError)
262  throw InvalidArgument("StringWiden: mbstowcs() call failed");
263  else
264  return std::wstring();
265  }
266 
267  result.resize(size);
268  size = mbstowcs(&result[0], str, size);
269  CRYPTOPP_ASSERT(size != (size_t)-1);
270  if (size == (size_t)-1)
271  {
272  if (throwOnError)
273  throw InvalidArgument("StringWiden: mbstowcs() call failed");
274  else
275  return std::wstring();
276  }
277 #endif
278 
279  return result;
280 }
281 
282 NAMESPACE_END
283 
284 #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:154
Utility functions for the Crypto++ library.
byte * BytePtr(std::string &str)
Pointer to the first element of a string.
Definition: misc.h:437
Library configuration file.
Common C++ header files.
SecBlock<byte> typedef.
Definition: secblock.h:1090
Support functions for word operations.
Classes and functions for secure memory allocations.
CRYPTOPP_DLL bool CRYPTOPP_API VerifyBufsEqual(const byte *buf1, const byte *buf2, size_t count)
Performs a near constant-time comparison of two equally sized buffers.
Definition: misc.cpp:114
A::pointer data()
Provides a pointer to the first element in the memory block.
Definition: secblock.h:820
const byte * ConstBytePtr(const std::string &str)
Const pointer to the first element of a string.
Definition: misc.h:459
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:218
Debugging and diagnostic assertions.
std::string IntToString(T value, unsigned int base=10)
Converts a value to a string.
Definition: misc.h:699
CRYPTOPP_DLL void CRYPTOPP_API xorbuf(byte *buf, const byte *mask, size_t count)
Performs an XOR of a buffer with a mask.
Definition: misc.cpp:46
Multiple precision integer with arithmetic operations.
Crypto++ library namespace.
size_t BytePtrSize(const std::string &str)
Size of a string.
Definition: misc.h:476
bool empty() const
Determines if the SecBlock is empty.
Definition: secblock.h:831
size_type size() const
Provides the count of elements in the SecBlock.
Definition: secblock.h:828