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
NAMESPACE_BEGIN(CryptoPP)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
ConstBytePtr(const SecByteBlock & str)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
BytePtrSize(const SecByteBlock & str)41 size_t BytePtrSize(const SecByteBlock& str)
42 {
43 return str.size();
44 }
45
xorbuf(byte * buf,const byte * mask,size_t count)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
xorbuf(byte * output,const byte * input,const byte * mask,size_t count)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
VerifyBufsEqual(const byte * buf,const byte * mask,size_t count)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
StringNarrow(const wchar_t * str,bool throwOnError)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
StringWiden(const char * str,bool throwOnError)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
285