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