1 // validat6.cpp - originally written and placed in the public domain by Wei Dai
2 //                CryptoPP::Test namespace added by JW in February 2017.
3 //                Source files split in July 2018 to expedite compiles.
4 
5 #include "pch.h"
6 
7 #define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1
8 
9 #include "cryptlib.h"
10 #include "cpu.h"
11 #include "validate.h"
12 
13 #include "asn.h"
14 #include "oids.h"
15 #include "blumshub.h"
16 #include "eccrypto.h"
17 
18 #include <iostream>
19 #include <iomanip>
20 #include <sstream>
21 
22 // Aggressive stack checking with VS2005 SP1 and above.
23 #if (_MSC_FULL_VER >= 140050727)
24 # pragma strict_gs_check (on)
25 #endif
26 
27 #if CRYPTOPP_MSC_VERSION
28 # pragma warning(disable: 4505 4355)
29 #endif
30 
31 NAMESPACE_BEGIN(CryptoPP)
NAMESPACE_BEGIN(Test)32 NAMESPACE_BEGIN(Test)
33 
34 bool CryptoSystemValidate(PK_Decryptor &priv, PK_Encryptor &pub, bool thorough)
35 {
36 	bool pass = true, fail;
37 
38 	fail = !pub.GetMaterial().Validate(GlobalRNG(), thorough ? 3 : 2) || !priv.GetMaterial().Validate(GlobalRNG(), thorough ? 3 : 2);
39 	pass = pass && !fail;
40 
41 	std::cout << (fail ? "FAILED    " : "passed    ");
42 	std::cout << "cryptosystem key validation\n";
43 
44 	const byte message[] = "test message";
45 	const int messageLen = 12;
46 	SecByteBlock ciphertext(priv.CiphertextLength(messageLen));
47 	SecByteBlock plaintext(priv.MaxPlaintextLength(ciphertext.size()));
48 
49 	pub.Encrypt(GlobalRNG(), message, messageLen, ciphertext);
50 	fail = priv.Decrypt(GlobalRNG(), ciphertext, priv.CiphertextLength(messageLen), plaintext) != DecodingResult(messageLen);
51 	fail = fail || memcmp(message, plaintext, messageLen);
52 	pass = pass && !fail;
53 
54 	std::cout << (fail ? "FAILED    " : "passed    ");
55 	std::cout << "encryption and decryption\n";
56 
57 	return pass;
58 }
59 
SimpleKeyAgreementValidate(SimpleKeyAgreementDomain & d)60 bool SimpleKeyAgreementValidate(SimpleKeyAgreementDomain &d)
61 {
62 	if (d.GetCryptoParameters().Validate(GlobalRNG(), 3))
63 		std::cout << "passed    simple key agreement domain parameters validation" << std::endl;
64 	else
65 	{
66 		std::cout << "FAILED    simple key agreement domain parameters invalid" << std::endl;
67 		return false;
68 	}
69 
70 	SecByteBlock priv1(d.PrivateKeyLength()), priv2(d.PrivateKeyLength());
71 	SecByteBlock pub1(d.PublicKeyLength()), pub2(d.PublicKeyLength());
72 	SecByteBlock val1(d.AgreedValueLength()), val2(d.AgreedValueLength());
73 
74 	d.GenerateKeyPair(GlobalRNG(), priv1, pub1);
75 	d.GenerateKeyPair(GlobalRNG(), priv2, pub2);
76 
77 	memset(val1.begin(), 0x10, val1.size());
78 	memset(val2.begin(), 0x11, val2.size());
79 
80 	if (!(d.Agree(val1, priv1, pub2) && d.Agree(val2, priv2, pub1)))
81 	{
82 		std::cout << "FAILED    simple key agreement failed" << std::endl;
83 		return false;
84 	}
85 
86 	if (memcmp(val1.begin(), val2.begin(), d.AgreedValueLength()))
87 	{
88 		std::cout << "FAILED    simple agreed values not equal" << std::endl;
89 		return false;
90 	}
91 
92 	std::cout << "passed    simple key agreement" << std::endl;
93 	return true;
94 }
95 
AuthenticatedKeyAgreementValidate(AuthenticatedKeyAgreementDomain & d)96 bool AuthenticatedKeyAgreementValidate(AuthenticatedKeyAgreementDomain &d)
97 {
98 	if (d.GetCryptoParameters().Validate(GlobalRNG(), 3))
99 		std::cout << "passed    authenticated key agreement domain parameters validation" << std::endl;
100 	else
101 	{
102 		std::cout << "FAILED    authenticated key agreement domain parameters invalid" << std::endl;
103 		return false;
104 	}
105 
106 	SecByteBlock spriv1(d.StaticPrivateKeyLength()), spriv2(d.StaticPrivateKeyLength());
107 	SecByteBlock epriv1(d.EphemeralPrivateKeyLength()), epriv2(d.EphemeralPrivateKeyLength());
108 	SecByteBlock spub1(d.StaticPublicKeyLength()), spub2(d.StaticPublicKeyLength());
109 	SecByteBlock epub1(d.EphemeralPublicKeyLength()), epub2(d.EphemeralPublicKeyLength());
110 	SecByteBlock val1(d.AgreedValueLength()), val2(d.AgreedValueLength());
111 
112 	d.GenerateStaticKeyPair(GlobalRNG(), spriv1, spub1);
113 	d.GenerateStaticKeyPair(GlobalRNG(), spriv2, spub2);
114 	d.GenerateEphemeralKeyPair(GlobalRNG(), epriv1, epub1);
115 	d.GenerateEphemeralKeyPair(GlobalRNG(), epriv2, epub2);
116 
117 	memset(val1.begin(), 0x10, val1.size());
118 	memset(val2.begin(), 0x11, val2.size());
119 
120 	if (d.Agree(val1, spriv1, epriv1, spub2, epub2) && d.Agree(val2, spriv2, epriv2, spub1, epub1))
121 	{
122 		std::cout << "passed    authenticated key agreement protocol execution" << std::endl;
123 	}
124 	else
125 	{
126 		std::cout << "FAILED    authenticated key agreement protocol execution" << std::endl;
127 		return false;
128 	}
129 
130 	if (memcmp(val1.begin(), val2.begin(), d.AgreedValueLength()))
131 	{
132 		std::cout << "FAILED    authenticated agreed values not equal" << std::endl;
133 		return false;
134 	}
135 
136 	std::cout << "passed    authenticated key agreement" << std::endl;
137 	return true;
138 }
139 
AuthenticatedKeyAgreementWithRolesValidate(AuthenticatedKeyAgreementDomain & initiator,AuthenticatedKeyAgreementDomain & recipient)140 bool AuthenticatedKeyAgreementWithRolesValidate(AuthenticatedKeyAgreementDomain &initiator, AuthenticatedKeyAgreementDomain &recipient)
141 {
142 	if (initiator.GetCryptoParameters().Validate(GlobalRNG(), 3))
143 		std::cout << "passed    authenticated key agreement domain parameters validation (initiator)" << std::endl;
144 	else
145 	{
146 		std::cout << "FAILED    authenticated key agreement domain parameters invalid (initiator)" << std::endl;
147 		return false;
148 	}
149 
150 	if (recipient.GetCryptoParameters().Validate(GlobalRNG(), 3))
151 		std::cout << "passed    authenticated key agreement domain parameters validation (recipient)" << std::endl;
152 	else
153 	{
154 		std::cout << "FAILED    authenticated key agreement domain parameters invalid (recipient)" << std::endl;
155 		return false;
156 	}
157 
158 	if (initiator.StaticPrivateKeyLength() != recipient.StaticPrivateKeyLength() ||
159 	    initiator.EphemeralPrivateKeyLength() != recipient.EphemeralPrivateKeyLength() ||
160 	    initiator.StaticPublicKeyLength() != recipient.StaticPublicKeyLength() ||
161 	    initiator.EphemeralPublicKeyLength() != recipient.EphemeralPublicKeyLength() ||
162 	    initiator.AgreedValueLength() != recipient.AgreedValueLength())
163 	{
164 		std::cout << "FAILED    authenticated key agreement domain parameter consistency" << std::endl;
165 		return false;
166 	}
167 	else
168 	{
169 		std::cout << "passed    authenticated key agreement domain parameter consistency" << std::endl;
170 	}
171 
172 	SecByteBlock spriv1(initiator.StaticPrivateKeyLength()), spriv2(recipient.StaticPrivateKeyLength());
173 	SecByteBlock epriv1(initiator.EphemeralPrivateKeyLength()), epriv2(recipient.EphemeralPrivateKeyLength());
174 	SecByteBlock spub1(initiator.StaticPublicKeyLength()), spub2(recipient.StaticPublicKeyLength());
175 	SecByteBlock epub1(initiator.EphemeralPublicKeyLength()), epub2(recipient.EphemeralPublicKeyLength());
176 	SecByteBlock val1(initiator.AgreedValueLength()), val2(recipient.AgreedValueLength());
177 
178 	initiator.GenerateStaticKeyPair(GlobalRNG(), spriv1, spub1);
179 	recipient.GenerateStaticKeyPair(GlobalRNG(), spriv2, spub2);
180 	initiator.GenerateEphemeralKeyPair(GlobalRNG(), epriv1, epub1);
181 	recipient.GenerateEphemeralKeyPair(GlobalRNG(), epriv2, epub2);
182 
183 	memset(val1.begin(), 0x10, val1.size());
184 	memset(val2.begin(), 0x11, val2.size());
185 
186 	if (initiator.Agree(val1, spriv1, epriv1, spub2, epub2) && recipient.Agree(val2, spriv2, epriv2, spub1, epub1))
187 	{
188 		std::cout << "passed    authenticated key agreement protocol execution" << std::endl;
189 	}
190 	else
191 	{
192 		std::cout << "FAILED    authenticated key agreement protocol execution" << std::endl;
193 		return false;
194 	}
195 
196 	if (memcmp(val1.begin(), val2.begin(), initiator.AgreedValueLength()))
197 	{
198 		std::cout << "FAILED    authenticated agreed values not equal" << std::endl;
199 		return false;
200 	}
201 
202 	std::cout << "passed    authenticated key agreement shared secret" << std::endl;
203 	return true;
204 }
205 
SignatureValidate(PK_Signer & priv,PK_Verifier & pub,bool thorough)206 bool SignatureValidate(PK_Signer &priv, PK_Verifier &pub, bool thorough)
207 {
208 	bool pass = true, fail;
209 
210 	fail = !pub.GetMaterial().Validate(GlobalRNG(), thorough ? 3 : 2) || !priv.GetMaterial().Validate(GlobalRNG(), thorough ? 3 : 2);
211 	pass = pass && !fail;
212 
213 	std::cout << (fail ? "FAILED    " : "passed    ");
214 	std::cout << "signature key validation\n";
215 
216 	const byte message[] = "test message";
217 	const int messageLen = 12;
218 
219 	SecByteBlock signature(priv.MaxSignatureLength());
220 	size_t signatureLength = priv.SignMessage(GlobalRNG(), message, messageLen, signature);
221 	fail = !pub.VerifyMessage(message, messageLen, signature, signatureLength);
222 	pass = pass && !fail;
223 
224 	std::cout << (fail ? "FAILED    " : "passed    ");
225 	std::cout << "signature and verification\n";
226 
227 	++signature[0];
228 	fail = pub.VerifyMessage(message, messageLen, signature, signatureLength);
229 	pass = pass && !fail;
230 
231 	std::cout << (fail ? "FAILED    " : "passed    ");
232 	std::cout << "checking invalid signature" << std::endl;
233 
234 	if (priv.MaxRecoverableLength() > 0)
235 	{
236 		signatureLength = priv.SignMessageWithRecovery(GlobalRNG(), message, messageLen, NULLPTR, 0, signature);
237 		SecByteBlock recovered(priv.MaxRecoverableLengthFromSignatureLength(signatureLength));
238 		DecodingResult result = pub.RecoverMessage(recovered, NULLPTR, 0, signature, signatureLength);
239 		fail = !(result.isValidCoding && result.messageLength == messageLen && memcmp(recovered, message, messageLen) == 0);
240 		pass = pass && !fail;
241 
242 		std::cout << (fail ? "FAILED    " : "passed    ");
243 		std::cout << "signature and verification with recovery" << std::endl;
244 
245 		++signature[0];
246 		result = pub.RecoverMessage(recovered, NULLPTR, 0, signature, signatureLength);
247 		fail = result.isValidCoding;
248 		pass = pass && !fail;
249 
250 		std::cout << (fail ? "FAILED    " : "passed    ");
251 		std::cout << "recovery with invalid signature" << std::endl;
252 	}
253 
254 	return pass;
255 }
256 
ValidateBBS()257 bool ValidateBBS()
258 {
259 	std::cout << "\nBlumBlumShub validation suite running...\n\n";
260 
261 	Integer p("212004934506826557583707108431463840565872545889679278744389317666981496005411448865750399674653351");
262 	Integer q("100677295735404212434355574418077394581488455772477016953458064183204108039226017738610663984508231");
263 	Integer seed("63239752671357255800299643604761065219897634268887145610573595874544114193025997412441121667211431");
264 	BlumBlumShub bbs(p, q, seed);
265 	bool pass = true, fail;
266 	int j;
267 
268 	const byte output1[] = {
269 		0x49,0xEA,0x2C,0xFD,0xB0,0x10,0x64,0xA0,0xBB,0xB9,
270 		0x2A,0xF1,0x01,0xDA,0xC1,0x8A,0x94,0xF7,0xB7,0xCE};
271 	const byte output2[] = {
272 		0x74,0x45,0x48,0xAE,0xAC,0xB7,0x0E,0xDF,0xAF,0xD7,
273 		0xD5,0x0E,0x8E,0x29,0x83,0x75,0x6B,0x27,0x46,0xA1};
274 
275 	byte buf[20];
276 	std::ostringstream oss;
277 
278 	bbs.GenerateBlock(buf, 20);
279 	fail = memcmp(output1, buf, 20) != 0;
280 	pass = pass && !fail;
281 
282 	oss << (fail ? "FAILED    " : "passed    ");
283 	for (j=0;j<20;j++)
284 		oss << std::setw(2) << std::setfill('0') << std::hex << (int)buf[j];
285 	oss << std::endl;
286 
287 	bbs.Seek(10);
288 	bbs.GenerateBlock(buf, 10);
289 	fail = memcmp(output1+10, buf, 10) != 0;
290 	pass = pass && !fail;
291 
292 	oss << (fail ? "FAILED    " : "passed    ");
293 	for (j=0;j<10;j++)
294 		oss << std::setw(2) << std::setfill('0') << std::hex << (int)buf[j];
295 	oss << std::endl;
296 
297 	bbs.Seek(1234567);
298 	bbs.GenerateBlock(buf, 20);
299 	fail = memcmp(output2, buf, 20) != 0;
300 	pass = pass && !fail;
301 
302 	oss << (fail ? "FAILED    " : "passed    ");
303 	for (j=0;j<20;j++)
304 		oss << std::setw(2) << std::setfill('0') << std::hex << (int)buf[j];
305 	oss << std::endl;
306 
307 	std::cout << oss.str();
308 	return pass;
309 }
310 
ValidateECP()311 bool ValidateECP()
312 {
313 	// Remove word recommend. Some ECP curves may not be recommended depending
314 	// on whom you ask. ECP is more descriptive item in this case.
315 	std::cout << "\nTesting SEC 2, NIST and Brainpool ECP curves...\n\n";
316 	bool pass = true; OID oid;
317 
318 	while (!(oid = DL_GroupParameters_EC<ECP>::GetNextRecommendedParametersOID(oid)).GetValues().empty())
319 	{
320 		DL_GroupParameters_EC<ECP> params(oid);
321 		pass = params.Validate(GlobalRNG(), 2);
322 
323 		// Test addition of identity element
324 		DL_GroupParameters_EC<ECP>::Element e1;
325 		e1 = params.GetCurve().Add(e1, e1);
326 		pass = params.IsIdentity(e1) && pass;
327 
328 		// Test doubling of identity element
329 		DL_GroupParameters_EC<ECP>::Element e2;
330 		e2 = params.GetCurve().Double(e2);
331 		pass = params.IsIdentity(e2) && pass;
332 
333 		// Test multiplication of identity element
334 		DL_GroupParameters_EC<ECP>::Element e3;
335 		Integer two = Integer::Two();
336 		e3 = params.GetCurve().Multiply(two, e3);
337 		pass = params.IsIdentity(e3) && pass;
338 
339 		std::cout << (pass ? "passed" : "FAILED") << "    " << std::dec << params.GetCurve().GetField().MaxElementBitLength() << " bits\n";
340 	}
341 
342 	std::cout << "\nECP validation suite running...\n\n";
343 	return ValidateECP_Agreement() && ValidateECP_Encrypt() && ValidateECP_NULLDigest_Encrypt() && ValidateECP_Sign() && pass;
344 }
345 
ValidateEC2N()346 bool ValidateEC2N()
347 {
348 	// Remove word recommend. Binary curves may not be recommended depending
349 	// on whom you ask. EC2N is more descriptive item in this case.
350 	std::cout << "\nTesting SEC 2 EC2N curves...\n\n";
351 	bool pass = true; OID oid;
352 
353 #if 1	// TODO: turn this back on when I make EC2N faster for pentanomial basis
354 	while (!(oid = DL_GroupParameters_EC<EC2N>::GetNextRecommendedParametersOID(oid)).GetValues().empty())
355 	{
356 		DL_GroupParameters_EC<EC2N> params(oid);
357 		pass = params.Validate(GlobalRNG(), 2);
358 
359 		// Test addition of identity element
360 		DL_GroupParameters_EC<EC2N>::Element e1;
361 		e1 = params.GetCurve().Add(e1, e1);
362 		pass = params.IsIdentity(e1) && pass;
363 
364 		// Test doubling of identity element
365 		DL_GroupParameters_EC<EC2N>::Element e2;
366 		e2 = params.GetCurve().Double(e2);
367 		pass = params.IsIdentity(e2) && pass;
368 
369 		// Test multiplication of identity element
370 		DL_GroupParameters_EC<EC2N>::Element e3;
371 		Integer two = Integer::Two();
372 		e3 = params.GetCurve().Multiply(two, e3);
373 		pass = params.IsIdentity(e3) && pass;
374 
375 		std::cout << (pass ? "passed" : "FAILED") << "    " << params.GetCurve().GetField().MaxElementBitLength() << " bits\n";
376 	}
377 #endif
378 
379 	std::cout << "\nEC2N validation suite running...\n\n";
380 	return ValidateEC2N_Agreement() && ValidateEC2N_Encrypt() && ValidateEC2N_Sign() && pass;
381 }
382 
ValidateRSA()383 bool ValidateRSA()
384 {
385 	std::cout << "\nRSA validation suite running...\n\n";
386 	return ValidateRSA_Encrypt() && ValidateRSA_Sign();
387 }
388 
ValidateLUC()389 bool ValidateLUC()
390 {
391 	std::cout << "\nLUC validation suite running...\n\n";
392 	return ValidateLUC_Encrypt() && ValidateLUC_Sign();
393 }
394 
ValidateLUC_DL()395 bool ValidateLUC_DL()
396 {
397 	// Prologue printed in each function
398 	return ValidateLUC_DL_Encrypt() && ValidateLUC_DL_Sign();
399 }
400 
ValidateRabin()401 bool ValidateRabin()
402 {
403 	std::cout << "\nRabin validation suite running...\n\n";
404 	return ValidateRabin_Encrypt() && ValidateRabin_Sign();
405 }
406 
407 NAMESPACE_END  // Test
408 NAMESPACE_END  // CryptoPP
409