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
268 void CallNewHandler()
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.
308 CRYPTOPP_ASSERT(IsAlignedOn(p, 16));
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
InvalidArgument
An invalid argument was detected.
Definition: cryptlib.h:202
StringNarrow
std::string StringNarrow(const wchar_t *str, bool throwOnError=true)
Converts a wide character C-string to a multibyte string.
Definition: misc.cpp:140
misc.h
Utility functions for the Crypto++ library.
AlignedDeallocate
void AlignedDeallocate(void *ptr)
Frees a buffer allocated with AlignedAllocate.
Definition: misc.cpp:312
config.h
Library configuration file.
stdcpp.h
Common C++ header files.
IsAlignedOn
bool IsAlignedOn(const void *ptr, unsigned int alignment)
Determines whether ptr is aligned to a minimum value.
Definition: misc.h:1111
UnalignedAllocate
void * UnalignedAllocate(size_t size)
Allocates a buffer.
Definition: misc.cpp:324
CallNewHandler
void CallNewHandler()
Attempts to reclaim unused memory.
Definition: misc.cpp:268
pch.h
Precompiled header file.
CRYPTOPP_ASSERT
#define CRYPTOPP_ASSERT(exp)
Debugging and diagnostic assertion.
Definition: trap.h:69
StringWiden
std::wstring StringWiden(const char *str, bool throwOnError=true)
Converts a multibyte C-string to a wide character string.
Definition: misc.cpp:204
xorbuf
void xorbuf(byte *buf, const byte *mask, size_t count)
Performs an XOR of a buffer with a mask.
Definition: misc.cpp:32
IntToString
std::string IntToString(T value, unsigned int base=10)
Converts a value to a string.
Definition: misc.h:604
VerifyBufsEqual
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
integer.h
Multiple precision integer with arithmetic operations.
CryptoPP
Crypto++ library namespace.
UnalignedDeallocate
void UnalignedDeallocate(void *ptr)
Frees a buffer allocated with UnalignedAllocate.
Definition: misc.cpp:332
AlignedAllocate
void * AlignedAllocate(size_t size)
Allocates a buffer on 16-byte boundary.
Definition: misc.cpp:283