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