1 // fipsalgt.cpp - originally written and placed in the public domain by Wei Dai 2 3 // This file implements the various algorithm tests needed to pass FIPS 140 validation. 4 // They're preserved here (commented out) in case Crypto++ needs to be revalidated. 5 6 #if 0 7 #ifndef CRYPTOPP_IMPORTS 8 #define CRYPTOPP_DEFAULT_NO_DLL 9 #endif 10 11 #include "dll.h" 12 #include "cryptlib.h" 13 #include "smartptr.h" 14 #include "filters.h" 15 #include "oids.h" 16 17 USING_NAMESPACE(CryptoPP) 18 19 class LineBreakParser : public AutoSignaling<Bufferless<Filter> > 20 { 21 public: 22 LineBreakParser(BufferedTransformation *attachment=NULLPTR, byte lineEnd='\n') 23 : m_lineEnd(lineEnd) {Detach(attachment);} 24 25 size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking) 26 { 27 if (!blocking) 28 throw BlockingInputOnly("LineBreakParser"); 29 30 unsigned int i, last = 0; 31 for (i=0; i<length; i++) 32 { 33 if (begin[i] == m_lineEnd) 34 { 35 AttachedTransformation()->Put2(begin+last, i-last, GetAutoSignalPropagation(), blocking); 36 last = i+1; 37 } 38 } 39 if (last != i) 40 AttachedTransformation()->Put2(begin+last, i-last, 0, blocking); 41 42 if (messageEnd && GetAutoSignalPropagation()) 43 { 44 AttachedTransformation()->MessageEnd(GetAutoSignalPropagation()-1, blocking); 45 AttachedTransformation()->MessageSeriesEnd(GetAutoSignalPropagation()-1, blocking); 46 } 47 48 return 0; 49 } 50 51 private: 52 byte m_lineEnd; 53 }; 54 55 class TestDataParser : public Unflushable<FilterWithInputQueue> 56 { 57 public: 58 enum DataType {OTHER, COUNT, KEY_T, IV, INPUT, OUTPUT}; 59 60 TestDataParser(std::string algorithm, std::string test, std::string mode, unsigned int feedbackSize, bool encrypt, BufferedTransformation *attachment) 61 : m_algorithm(algorithm), m_test(test), m_mode(mode), m_feedbackSize(feedbackSize) 62 , m_firstLine(true), m_blankLineTransition(0) 63 { 64 Detach(attachment); 65 66 m_typeToName[COUNT] = "COUNT"; 67 68 m_nameToType["COUNT"] = COUNT; 69 m_nameToType["KEY"] = KEY_T; 70 m_nameToType["KEYs"] = KEY_T; 71 m_nameToType["key"] = KEY_T; 72 m_nameToType["Key"] = KEY_T; 73 m_nameToType["IV"] = IV; 74 m_nameToType["IV1"] = IV; 75 m_nameToType["CV"] = IV; 76 m_nameToType["CV1"] = IV; 77 m_nameToType["IB"] = IV; 78 m_nameToType["TEXT"] = INPUT; 79 m_nameToType["RESULT"] = OUTPUT; 80 m_nameToType["Msg"] = INPUT; 81 m_nameToType["Seed"] = INPUT; 82 m_nameToType["V"] = INPUT; 83 m_nameToType["DT"] = IV; 84 SetEncrypt(encrypt); 85 86 if (m_algorithm == "DSA" || m_algorithm == "ECDSA") 87 { 88 if (m_test == "PKV") 89 m_trigger = "Qy"; 90 else if (m_test == "KeyPair") 91 m_trigger = "N"; 92 else if (m_test == "SigGen") 93 m_trigger = "Msg"; 94 else if (m_test == "SigVer") 95 m_trigger = "S"; 96 else if (m_test == "PQGGen") 97 m_trigger = "N"; 98 else if (m_test == "PQGVer") 99 m_trigger = "H"; 100 } 101 else if (m_algorithm == "HMAC") 102 m_trigger = "Msg"; 103 else if (m_algorithm == "SHA") 104 m_trigger = (m_test == "MONTE") ? "Seed" : "Msg"; 105 else if (m_algorithm == "RNG") 106 m_trigger = "V"; 107 else if (m_algorithm == "RSA") 108 m_trigger = (m_test == "Ver") ? "S" : "Msg"; 109 } 110 111 void SetEncrypt(bool encrypt) 112 { 113 m_encrypt = encrypt; 114 if (encrypt) 115 { 116 m_nameToType["PLAINTEXT"] = INPUT; 117 m_nameToType["CIPHERTEXT"] = OUTPUT; 118 m_nameToType["PT"] = INPUT; 119 m_nameToType["CT"] = OUTPUT; 120 } 121 else 122 { 123 m_nameToType["PLAINTEXT"] = OUTPUT; 124 m_nameToType["CIPHERTEXT"] = INPUT; 125 m_nameToType["PT"] = OUTPUT; 126 m_nameToType["CT"] = INPUT; 127 } 128 129 if (m_algorithm == "AES" || m_algorithm == "TDES") 130 { 131 if (encrypt) 132 { 133 m_trigger = "PLAINTEXT"; 134 m_typeToName[OUTPUT] = "CIPHERTEXT"; 135 } 136 else 137 { 138 m_trigger = "CIPHERTEXT"; 139 m_typeToName[OUTPUT] = "PLAINTEXT"; 140 } 141 m_count = 0; 142 } 143 } 144 145 protected: 146 void OutputData(std::string &output, const std::string &key, const std::string &data) 147 { 148 output += key; 149 output += "= "; 150 output += data; 151 output += "\n"; 152 } 153 154 void OutputData(std::string &output, const std::string &key, int data) 155 { 156 OutputData(output, key, IntToString(data)); 157 } 158 159 void OutputData(std::string &output, const std::string &key, const SecByteBlock &data) 160 { 161 output += key; 162 output += "= "; 163 HexEncoder(new StringSink(output), false).Put(data, data.size()); 164 output += "\n"; 165 } 166 167 void OutputData(std::string &output, const std::string &key, const Integer &data, int size=-1) 168 { 169 SecByteBlock s(size < 0 ? data.MinEncodedSize() : size); 170 data.Encode(s, s.size()); 171 OutputData(output, key, s); 172 } 173 174 void OutputData(std::string &output, const std::string &key, const PolynomialMod2 &data, int size=-1) 175 { 176 SecByteBlock s(size < 0 ? data.MinEncodedSize() : size); 177 data.Encode(s, s.size()); 178 OutputData(output, key, s); 179 } 180 181 void OutputData(std::string &output, DataType t, const std::string &data) 182 { 183 if (m_algorithm == "SKIPJACK") 184 { 185 if (m_test == "KAT") 186 { 187 if (t == OUTPUT) 188 output = m_line + data + "\n"; 189 } 190 else 191 { 192 if (t != COUNT) 193 { 194 output += m_typeToName[t]; 195 output += "="; 196 } 197 output += data; 198 output += t == OUTPUT ? "\n" : " "; 199 } 200 } 201 else if (m_algorithm == "TDES" && t == KEY_T && m_typeToName[KEY_T].empty()) 202 { 203 output += "KEY1 = "; 204 output += data.substr(0, 16); 205 output += "\nKEY2 = "; 206 output += data.size() > 16 ? data.substr(16, 16) : data.substr(0, 16); 207 output += "\nKEY3 = "; 208 output += data.size() > 32 ? data.substr(32, 16) : data.substr(0, 16); 209 output += "\n"; 210 } 211 else 212 { 213 output += m_typeToName[t]; 214 output += " = "; 215 output += data; 216 output += "\n"; 217 } 218 } 219 220 void OutputData(std::string &output, DataType t, int i) 221 { 222 OutputData(output, t, IntToString(i)); 223 } 224 225 void OutputData(std::string &output, DataType t, const SecByteBlock &data) 226 { 227 std::string hexData; 228 StringSource(data.begin(), data.size(), true, new HexEncoder(new StringSink(hexData), false)); 229 OutputData(output, t, hexData); 230 } 231 232 void OutputGivenData(std::string &output, DataType t, bool optional = false) 233 { 234 if (m_data.find(m_typeToName[t]) == m_data.end()) 235 { 236 if (optional) 237 return; 238 throw Exception(Exception::OTHER_ERROR, "TestDataParser: key not found: " + m_typeToName[t]); 239 } 240 241 OutputData(output, t, m_data[m_typeToName[t]]); 242 } 243 244 template <class T> 245 BlockCipher * NewBT(T *) 246 { 247 if (!m_encrypt && (m_mode == "ECB" || m_mode == "CBC")) 248 return new typename T::Decryption; 249 else 250 return new typename T::Encryption; 251 } 252 253 template <class T> 254 SymmetricCipher * NewMode(T *, BlockCipher &bt, const byte *iv) 255 { 256 if (!m_encrypt) 257 return new typename T::Decryption(bt, iv, m_feedbackSize/8); 258 else 259 return new typename T::Encryption(bt, iv, m_feedbackSize/8); 260 } 261 262 static inline void Xor(SecByteBlock &z, const SecByteBlock &x, const SecByteBlock &y) 263 { 264 CRYPTOPP_ASSERT(x.size() == y.size()); 265 z.resize(x.size()); 266 xorbuf(z, x, y, x.size()); 267 } 268 269 SecByteBlock UpdateKey(SecByteBlock key, const SecByteBlock *text) 270 { 271 unsigned int innerCount = (m_algorithm == "AES") ? 1000 : 10000; 272 int keySize = key.size(), blockSize = text[0].size(); 273 SecByteBlock x(keySize); 274 for (int k=0; k<keySize;) 275 { 276 int pos = innerCount * blockSize - keySize + k; 277 memcpy(x + k, text[pos / blockSize] + pos % blockSize, blockSize - pos % blockSize); 278 k += blockSize - pos % blockSize; 279 } 280 281 if (m_algorithm == "TDES" || m_algorithm == "DES") 282 { 283 for (int i=0; i<keySize; i+=8) 284 { 285 xorbuf(key+i, x+keySize-8-i, 8); 286 DES::CorrectKeyParityBits(key+i); 287 } 288 } 289 else 290 xorbuf(key, x, keySize); 291 292 return key; 293 } 294 295 static inline void AssignLeftMostBits(SecByteBlock &z, const SecByteBlock &x, unsigned int K) 296 { 297 z.Assign(x, K/8); 298 } 299 300 template <class EC> 301 void EC_KeyPair(string &output, int n, const OID &oid) 302 { 303 DL_GroupParameters_EC<EC> params(oid); 304 for (int i=0; i<n; i++) 305 { 306 DL_PrivateKey_EC<EC> priv; 307 DL_PublicKey_EC<EC> pub; 308 priv.Initialize(m_rng, params); 309 priv.MakePublicKey(pub); 310 311 OutputData(output, "d ", priv.GetPrivateExponent()); 312 OutputData(output, "Qx ", pub.GetPublicElement().x, params.GetCurve().GetField().MaxElementByteLength()); 313 OutputData(output, "Qy ", pub.GetPublicElement().y, params.GetCurve().GetField().MaxElementByteLength()); 314 } 315 } 316 317 template <class EC> 318 void EC_SigGen(string &output, const OID &oid) 319 { 320 DL_GroupParameters_EC<EC> params(oid); 321 typename ECDSA<EC, SHA1>::PrivateKey priv; 322 typename ECDSA<EC, SHA1>::PublicKey pub; 323 priv.Initialize(m_rng, params); 324 priv.MakePublicKey(pub); 325 326 typename ECDSA<EC, SHA1>::Signer signer(priv); 327 SecByteBlock sig(signer.SignatureLength()); 328 StringSource(m_data["Msg"], true, new HexDecoder(new SignerFilter(m_rng, signer, new ArraySink(sig, sig.size())))); 329 SecByteBlock R(sig, sig.size()/2), S(sig+sig.size()/2, sig.size()/2); 330 331 OutputData(output, "Qx ", pub.GetPublicElement().x, params.GetCurve().GetField().MaxElementByteLength()); 332 OutputData(output, "Qy ", pub.GetPublicElement().y, params.GetCurve().GetField().MaxElementByteLength()); 333 OutputData(output, "R ", R); 334 OutputData(output, "S ", S); 335 } 336 337 template <class EC> 338 void EC_SigVer(string &output, const OID &oid) 339 { 340 SecByteBlock x(DecodeHex(m_data["Qx"])); 341 SecByteBlock y(DecodeHex(m_data["Qy"])); 342 Integer r((m_data["R"]+"h").c_str()); 343 Integer s((m_data["S"]+"h").c_str()); 344 345 typename EC::FieldElement Qx(x, x.size()); 346 typename EC::FieldElement Qy(y, y.size()); 347 typename EC::Element Q(Qx, Qy); 348 349 DL_GroupParameters_EC<EC> params(oid); 350 typename ECDSA<EC, SHA1>::PublicKey pub; 351 pub.Initialize(params, Q); 352 typename ECDSA<EC, SHA1>::Verifier verifier(pub); 353 354 SecByteBlock sig(verifier.SignatureLength()); 355 r.Encode(sig, sig.size()/2); 356 s.Encode(sig+sig.size()/2, sig.size()/2); 357 358 SignatureVerificationFilter filter(verifier); 359 filter.Put(sig, sig.size()); 360 StringSource(m_data["Msg"], true, new HexDecoder(new Redirector(filter, Redirector::DATA_ONLY))); 361 filter.MessageEnd(); 362 byte b; 363 filter.Get(b); 364 OutputData(output, "Result ", b ? "P" : "F"); 365 } 366 367 template <class EC> 368 static bool EC_PKV(RandomNumberGenerator &rng, const SecByteBlock &x, const SecByteBlock &y, const OID &oid) 369 { 370 typename EC::FieldElement Qx(x, x.size()); 371 typename EC::FieldElement Qy(y, y.size()); 372 typename EC::Element Q(Qx, Qy); 373 374 DL_GroupParameters_EC<EC> params(oid); 375 typename ECDSA<EC, SHA1>::PublicKey pub; 376 pub.Initialize(params, Q); 377 return pub.Validate(rng, 3); 378 } 379 380 template <class H, class Result> 381 Result * CreateRSA2(const std::string &standard) 382 { 383 if (typeid(Result) == typeid(PK_Verifier)) 384 { 385 if (standard == "R") 386 return (Result *) new typename RSASS_ISO<H>::Verifier; 387 else if (standard == "P") 388 return (Result *) new typename RSASS<PSS, H>::Verifier; 389 else if (standard == "1") 390 return (Result *) new typename RSASS<PKCS1v15, H>::Verifier; 391 } 392 else if (typeid(Result) == typeid(PK_Signer)) 393 { 394 if (standard == "R") 395 return (Result *) new typename RSASS_ISO<H>::Signer; 396 else if (standard == "P") 397 return (Result *) new typename RSASS<PSS, H>::Signer; 398 else if (standard == "1") 399 return (Result *) new typename RSASS<PKCS1v15, H>::Signer; 400 } 401 402 return NULLPTR; 403 } 404 405 template <class Result> 406 Result * CreateRSA(const std::string &standard, const std::string &hash) 407 { 408 if (hash == "1") 409 return CreateRSA2<SHA1, Result>(standard); 410 else if (hash == "224") 411 return CreateRSA2<SHA224, Result>(standard); 412 else if (hash == "256") 413 return CreateRSA2<SHA256, Result>(standard); 414 else if (hash == "384") 415 return CreateRSA2<SHA384, Result>(standard); 416 else if (hash == "512") 417 return CreateRSA2<SHA512, Result>(standard); 418 else 419 return NULLPTR; 420 } 421 422 virtual void DoTest() 423 { 424 std::string output; 425 426 if (m_algorithm == "DSA") 427 { 428 if (m_test == "KeyPair") 429 { 430 DL_GroupParameters_DSA pqg; 431 int modLen = atol(m_bracketString.substr(6).c_str()); 432 pqg.GenerateRandomWithKeySize(m_rng, modLen); 433 434 OutputData(output, "P ", pqg.GetModulus()); 435 OutputData(output, "Q ", pqg.GetSubgroupOrder()); 436 OutputData(output, "G ", pqg.GetSubgroupGenerator()); 437 438 int n = atol(m_data["N"].c_str()); 439 for (int i=0; i<n; i++) 440 { 441 DSA::Signer priv; 442 priv.AccessKey().GenerateRandom(m_rng, pqg); 443 DSA::Verifier pub(priv); 444 445 OutputData(output, "X ", priv.GetKey().GetPrivateExponent()); 446 OutputData(output, "Y ", pub.GetKey().GetPublicElement()); 447 AttachedTransformation()->Put((byte *)output.data(), output.size()); 448 output.resize(0); 449 } 450 } 451 else if (m_test == "PQGGen") 452 { 453 int n = atol(m_data["N"].c_str()); 454 for (int i=0; i<n; i++) 455 { 456 Integer p, q, h, g; 457 int counter; 458 459 SecByteBlock seed(SHA1::DIGESTSIZE); 460 do 461 { 462 m_rng.GenerateBlock(seed, seed.size()); 463 } 464 while (!DSA::GeneratePrimes(seed, seed.size()*8, counter, p, 1024, q)); 465 h.Randomize(m_rng, 2, p-2); 466 g = a_exp_b_mod_c(h, (p-1)/q, p); 467 468 OutputData(output, "P ", p); 469 OutputData(output, "Q ", q); 470 OutputData(output, "G ", g); 471 OutputData(output, "Seed ", seed); 472 OutputData(output, "c ", counter); 473 OutputData(output, "H ", h, p.ByteCount()); 474 AttachedTransformation()->Put((byte *)output.data(), output.size()); 475 output.resize(0); 476 } 477 } 478 else if (m_test == "SigGen") 479 { 480 std::string &encodedKey = m_data["PrivKey"]; 481 int modLen = atol(m_bracketString.substr(6).c_str()); 482 DSA::PrivateKey priv; 483 484 if (!encodedKey.empty()) 485 { 486 StringStore s(encodedKey); 487 priv.BERDecode(s); 488 if (priv.GetGroupParameters().GetModulus().BitCount() != modLen) 489 encodedKey.clear(); 490 } 491 492 if (encodedKey.empty()) 493 { 494 priv.Initialize(m_rng, modLen); 495 StringSink s(encodedKey); 496 priv.DEREncode(s); 497 OutputData(output, "P ", priv.GetGroupParameters().GetModulus()); 498 OutputData(output, "Q ", priv.GetGroupParameters().GetSubgroupOrder()); 499 OutputData(output, "G ", priv.GetGroupParameters().GetSubgroupGenerator()); 500 } 501 502 DSA::Signer signer(priv); 503 DSA::Verifier pub(signer); 504 OutputData(output, "Msg ", m_data["Msg"]); 505 OutputData(output, "Y ", pub.GetKey().GetPublicElement()); 506 507 SecByteBlock sig(signer.SignatureLength()); 508 StringSource(m_data["Msg"], true, new HexDecoder(new SignerFilter(m_rng, signer, new ArraySink(sig, sig.size())))); 509 SecByteBlock R(sig, sig.size()/2), S(sig+sig.size()/2, sig.size()/2); 510 OutputData(output, "R ", R); 511 OutputData(output, "S ", S); 512 AttachedTransformation()->Put((byte *)output.data(), output.size()); 513 output.resize(0); 514 } 515 else if (m_test == "SigVer") 516 { 517 Integer p((m_data["P"] + "h").c_str()); 518 Integer q((m_data["Q"] + "h").c_str()); 519 Integer g((m_data["G"] + "h").c_str()); 520 Integer y((m_data["Y"] + "h").c_str()); 521 DSA::Verifier verifier(p, q, g, y); 522 523 HexDecoder filter(new SignatureVerificationFilter(verifier)); 524 StringSource(m_data["R"], true, new Redirector(filter, Redirector::DATA_ONLY)); 525 StringSource(m_data["S"], true, new Redirector(filter, Redirector::DATA_ONLY)); 526 StringSource(m_data["Msg"], true, new Redirector(filter, Redirector::DATA_ONLY)); 527 filter.MessageEnd(); 528 byte b; 529 filter.Get(b); 530 OutputData(output, "Result ", b ? "P" : "F"); 531 AttachedTransformation()->Put((byte *)output.data(), output.size()); 532 output.resize(0); 533 } 534 else if (m_test == "PQGVer") 535 { 536 Integer p((m_data["P"] + "h").c_str()); 537 Integer q((m_data["Q"] + "h").c_str()); 538 Integer g((m_data["G"] + "h").c_str()); 539 Integer h((m_data["H"] + "h").c_str()); 540 int c = atol(m_data["c"].c_str()); 541 SecByteBlock seed(m_data["Seed"].size()/2); 542 StringSource(m_data["Seed"], true, new HexDecoder(new ArraySink(seed, seed.size()))); 543 544 Integer p1, q1; 545 bool result = DSA::GeneratePrimes(seed, seed.size()*8, c, p1, 1024, q1, true); 546 result = result && (p1 == p && q1 == q); 547 result = result && g == a_exp_b_mod_c(h, (p-1)/q, p); 548 549 OutputData(output, "Result ", result ? "P" : "F"); 550 AttachedTransformation()->Put((byte *)output.data(), output.size()); 551 output.resize(0); 552 } 553 554 return; 555 } 556 557 if (m_algorithm == "ECDSA") 558 { 559 std::map<std::string, OID> name2oid; 560 name2oid["P-192"] = ASN1::secp192r1(); 561 name2oid["P-224"] = ASN1::secp224r1(); 562 name2oid["P-256"] = ASN1::secp256r1(); 563 name2oid["P-384"] = ASN1::secp384r1(); 564 name2oid["P-521"] = ASN1::secp521r1(); 565 name2oid["K-163"] = ASN1::sect163k1(); 566 name2oid["K-233"] = ASN1::sect233k1(); 567 name2oid["K-283"] = ASN1::sect283k1(); 568 name2oid["K-409"] = ASN1::sect409k1(); 569 name2oid["K-571"] = ASN1::sect571k1(); 570 name2oid["B-163"] = ASN1::sect163r2(); 571 name2oid["B-233"] = ASN1::sect233r1(); 572 name2oid["B-283"] = ASN1::sect283r1(); 573 name2oid["B-409"] = ASN1::sect409r1(); 574 name2oid["B-571"] = ASN1::sect571r1(); 575 576 if (m_test == "PKV") 577 { 578 bool pass; 579 if (m_bracketString[0] == 'P') 580 pass = EC_PKV<ECP>(m_rng, DecodeHex(m_data["Qx"]), DecodeHex(m_data["Qy"]), name2oid[m_bracketString]); 581 else 582 pass = EC_PKV<EC2N>(m_rng, DecodeHex(m_data["Qx"]), DecodeHex(m_data["Qy"]), name2oid[m_bracketString]); 583 584 OutputData(output, "Result ", pass ? "P" : "F"); 585 } 586 else if (m_test == "KeyPair") 587 { 588 if (m_bracketString[0] == 'P') 589 EC_KeyPair<ECP>(output, atol(m_data["N"].c_str()), name2oid[m_bracketString]); 590 else 591 EC_KeyPair<EC2N>(output, atol(m_data["N"].c_str()), name2oid[m_bracketString]); 592 } 593 else if (m_test == "SigGen") 594 { 595 if (m_bracketString[0] == 'P') 596 EC_SigGen<ECP>(output, name2oid[m_bracketString]); 597 else 598 EC_SigGen<EC2N>(output, name2oid[m_bracketString]); 599 } 600 else if (m_test == "SigVer") 601 { 602 if (m_bracketString[0] == 'P') 603 EC_SigVer<ECP>(output, name2oid[m_bracketString]); 604 else 605 EC_SigVer<EC2N>(output, name2oid[m_bracketString]); 606 } 607 608 AttachedTransformation()->Put((byte *)output.data(), output.size()); 609 output.resize(0); 610 return; 611 } 612 613 if (m_algorithm == "RSA") 614 { 615 std::string shaAlg = m_data["SHAAlg"].substr(3); 616 617 if (m_test == "Ver") 618 { 619 Integer n((m_data["n"] + "h").c_str()); 620 Integer e((m_data["e"] + "h").c_str()); 621 RSA::PublicKey pub; 622 pub.Initialize(n, e); 623 624 member_ptr<PK_Verifier> pV(CreateRSA<PK_Verifier>(m_mode, shaAlg)); 625 pV->AccessMaterial().AssignFrom(pub); 626 627 HexDecoder filter(new SignatureVerificationFilter(*pV)); 628 for (unsigned int i=m_data["S"].size(); i<pV->SignatureLength()*2; i++) 629 filter.Put('0'); 630 StringSource(m_data["S"], true, new Redirector(filter, Redirector::DATA_ONLY)); 631 StringSource(m_data["Msg"], true, new Redirector(filter, Redirector::DATA_ONLY)); 632 filter.MessageEnd(); 633 byte b; 634 filter.Get(b); 635 OutputData(output, "Result ", b ? "P" : "F"); 636 } 637 else 638 { 639 CRYPTOPP_ASSERT(m_test == "Gen"); 640 int modLen = atol(m_bracketString.substr(6).c_str()); 641 std::string &encodedKey = m_data["PrivKey"]; 642 RSA::PrivateKey priv; 643 644 if (!encodedKey.empty()) 645 { 646 StringStore s(encodedKey); 647 priv.BERDecode(s); 648 if (priv.GetModulus().BitCount() != modLen) 649 encodedKey.clear(); 650 } 651 652 if (encodedKey.empty()) 653 { 654 priv.Initialize(m_rng, modLen); 655 StringSink s(encodedKey); 656 priv.DEREncode(s); 657 OutputData(output, "n ", priv.GetModulus()); 658 OutputData(output, "e ", priv.GetPublicExponent(), modLen/8); 659 } 660 661 member_ptr<PK_Signer> pS(CreateRSA<PK_Signer>(m_mode, shaAlg)); 662 pS->AccessMaterial().AssignFrom(priv); 663 664 SecByteBlock sig(pS->SignatureLength()); 665 StringSource(m_data["Msg"], true, new HexDecoder(new SignerFilter(m_rng, *pS, new ArraySink(sig, sig.size())))); 666 OutputData(output, "SHAAlg ", m_data["SHAAlg"]); 667 OutputData(output, "Msg ", m_data["Msg"]); 668 OutputData(output, "S ", sig); 669 } 670 671 AttachedTransformation()->Put((byte *)output.data(), output.size()); 672 output.resize(0); 673 return; 674 } 675 676 if (m_algorithm == "SHA") 677 { 678 member_ptr<HashFunction> pHF; 679 680 if (m_mode == "1") 681 pHF.reset(new SHA1); 682 else if (m_mode == "224") 683 pHF.reset(new SHA224); 684 else if (m_mode == "256") 685 pHF.reset(new SHA256); 686 else if (m_mode == "384") 687 pHF.reset(new SHA384); 688 else if (m_mode == "512") 689 pHF.reset(new SHA512); 690 691 if (m_test == "MONTE") 692 { 693 SecByteBlock seed = m_data2[INPUT]; 694 SecByteBlock MD[1003]; 695 int i,j; 696 697 for (j=0; j<100; j++) 698 { 699 MD[0] = MD[1] = MD[2] = seed; 700 for (i=3; i<1003; i++) 701 { 702 SecByteBlock Mi = MD[i-3] + MD[i-2] + MD[i-1]; 703 MD[i].resize(pHF->DigestSize()); 704 pHF->CalculateDigest(MD[i], Mi, Mi.size()); 705 } 706 seed = MD[1002]; 707 OutputData(output, "COUNT ", j); 708 OutputData(output, "MD ", seed); 709 AttachedTransformation()->Put((byte *)output.data(), output.size()); 710 output.resize(0); 711 } 712 } 713 else 714 { 715 SecByteBlock tag(pHF->DigestSize()); 716 SecByteBlock &msg(m_data2[INPUT]); 717 int len = atol(m_data["Len"].c_str()); 718 StringSource(msg.begin(), len/8, true, new HashFilter(*pHF, new ArraySink(tag, tag.size()))); 719 OutputData(output, "MD ", tag); 720 AttachedTransformation()->Put((byte *)output.data(), output.size()); 721 output.resize(0); 722 } 723 return; 724 } 725 726 SecByteBlock &key = m_data2[KEY_T]; 727 728 if (m_algorithm == "TDES") 729 { 730 if (!m_data["KEY1"].empty()) 731 { 732 const std::string keys[3] = {m_data["KEY1"], m_data["KEY2"], m_data["KEY3"]}; 733 key.resize(24); 734 HexDecoder hexDec(new ArraySink(key, key.size())); 735 for (int i=0; i<3; i++) 736 hexDec.Put((byte *)keys[i].data(), keys[i].size()); 737 738 if (keys[0] == keys[2]) 739 { 740 if (keys[0] == keys[1]) 741 key.resize(8); 742 else 743 key.resize(16); 744 } 745 else 746 key.resize(24); 747 } 748 } 749 750 if (m_algorithm == "RNG") 751 { 752 key.resize(24); 753 StringSource(m_data["Key1"] + m_data["Key2"] + m_data["Key3"], true, new HexDecoder(new ArraySink(key, key.size()))); 754 755 SecByteBlock seed(m_data2[INPUT]), dt(m_data2[IV]), r(8); 756 X917RNG rng(new DES_EDE3::Encryption(key, key.size()), seed, dt); 757 758 if (m_test == "MCT") 759 { 760 for (int i=0; i<10000; i++) 761 rng.GenerateBlock(r, r.size()); 762 } 763 else 764 { 765 rng.GenerateBlock(r, r.size()); 766 } 767 768 OutputData(output, "R ", r); 769 AttachedTransformation()->Put((byte *)output.data(), output.size()); 770 output.resize(0); 771 return; 772 } 773 774 if (m_algorithm == "HMAC") 775 { 776 member_ptr<MessageAuthenticationCode> pMAC; 777 778 if (m_bracketString == "L=20") 779 pMAC.reset(new HMAC<SHA1>); 780 else if (m_bracketString == "L=28") 781 pMAC.reset(new HMAC<SHA224>); 782 else if (m_bracketString == "L=32") 783 pMAC.reset(new HMAC<SHA256>); 784 else if (m_bracketString == "L=48") 785 pMAC.reset(new HMAC<SHA384>); 786 else if (m_bracketString == "L=64") 787 pMAC.reset(new HMAC<SHA512>); 788 else 789 throw Exception(Exception::OTHER_ERROR, "TestDataParser: unexpected HMAC bracket string: " + m_bracketString); 790 791 pMAC->SetKey(key, key.size()); 792 int Tlen = atol(m_data["Tlen"].c_str()); 793 SecByteBlock tag(Tlen); 794 StringSource(m_data["Msg"], true, new HexDecoder(new HashFilter(*pMAC, new ArraySink(tag, Tlen), false, Tlen))); 795 OutputData(output, "Mac ", tag); 796 AttachedTransformation()->Put((byte *)output.data(), output.size()); 797 output.resize(0); 798 return; 799 } 800 801 member_ptr<BlockCipher> pBT; 802 if (m_algorithm == "DES") 803 pBT.reset(NewBT((DES*)0)); 804 else if (m_algorithm == "TDES") 805 { 806 if (key.size() == 8) 807 pBT.reset(NewBT((DES*)0)); 808 else if (key.size() == 16) 809 pBT.reset(NewBT((DES_EDE2*)0)); 810 else 811 pBT.reset(NewBT((DES_EDE3*)0)); 812 } 813 else if (m_algorithm == "SKIPJACK") 814 pBT.reset(NewBT((SKIPJACK*)0)); 815 else if (m_algorithm == "AES") 816 pBT.reset(NewBT((AES*)0)); 817 else 818 throw Exception(Exception::OTHER_ERROR, "TestDataParser: unexpected algorithm: " + m_algorithm); 819 820 if (!pBT->IsValidKeyLength(key.size())) 821 key.CleanNew(pBT->DefaultKeyLength()); // for Scbcvrct 822 pBT->SetKey(key.data(), key.size()); 823 824 SecByteBlock &iv = m_data2[IV]; 825 if (iv.empty()) 826 iv.CleanNew(pBT->BlockSize()); 827 828 member_ptr<SymmetricCipher> pCipher; 829 unsigned int K = m_feedbackSize; 830 831 if (m_mode == "ECB") 832 pCipher.reset(NewMode((ECB_Mode_ExternalCipher*)0, *pBT, iv)); 833 else if (m_mode == "CBC") 834 pCipher.reset(NewMode((CBC_Mode_ExternalCipher*)0, *pBT, iv)); 835 else if (m_mode == "CFB") 836 pCipher.reset(NewMode((CFB_Mode_ExternalCipher*)0, *pBT, iv)); 837 else if (m_mode == "OFB") 838 pCipher.reset(NewMode((OFB_Mode_ExternalCipher*)0, *pBT, iv)); 839 else 840 throw Exception(Exception::OTHER_ERROR, "TestDataParser: unexpected mode: " + m_mode); 841 842 bool encrypt = m_encrypt; 843 844 if (m_test == "MONTE") 845 { 846 SecByteBlock KEY[401]; 847 KEY[0] = key; 848 int keySize = key.size(); 849 int blockSize = pBT->BlockSize(); 850 851 std::vector<SecByteBlock> IB(10001), OB(10001), PT(10001), CT(10001), RESULT(10001), TXT(10001), CV(10001); 852 PT[0] = GetData("PLAINTEXT"); 853 CT[0] = GetData("CIPHERTEXT"); 854 CV[0] = IB[0] = iv; 855 TXT[0] = GetData("TEXT"); 856 857 int outerCount = (m_algorithm == "AES") ? 100 : 400; 858 int innerCount = (m_algorithm == "AES") ? 1000 : 10000; 859 860 for (int i=0; i<outerCount; i++) 861 { 862 pBT->SetKey(KEY[i], keySize); 863 864 for (int j=0; j<innerCount; j++) 865 { 866 if (m_mode == "ECB") 867 { 868 if (encrypt) 869 { 870 IB[j] = PT[j]; 871 CT[j].resize(blockSize); 872 pBT->ProcessBlock(IB[j], CT[j]); 873 PT[j+1] = CT[j]; 874 } 875 else 876 { 877 IB[j] = CT[j]; 878 PT[j].resize(blockSize); 879 pBT->ProcessBlock(IB[j], PT[j]); 880 CT[j+1] = PT[j]; 881 } 882 } 883 else if (m_mode == "OFB") 884 { 885 OB[j].resize(blockSize); 886 pBT->ProcessBlock(IB[j], OB[j]); 887 Xor(RESULT[j], OB[j], TXT[j]); 888 TXT[j+1] = IB[j]; 889 IB[j+1] = OB[j]; 890 } 891 else if (m_mode == "CBC") 892 { 893 if (encrypt) 894 { 895 Xor(IB[j], PT[j], CV[j]); 896 CT[j].resize(blockSize); 897 pBT->ProcessBlock(IB[j], CT[j]); 898 PT[j+1] = CV[j]; 899 CV[j+1] = CT[j]; 900 } 901 else 902 { 903 IB[j] = CT[j]; 904 OB[j].resize(blockSize); 905 pBT->ProcessBlock(IB[j], OB[j]); 906 Xor(PT[j], OB[j], CV[j]); 907 CV[j+1] = CT[j]; 908 CT[j+1] = PT[j]; 909 } 910 } 911 else if (m_mode == "CFB") 912 { 913 if (encrypt) 914 { 915 OB[j].resize(blockSize); 916 pBT->ProcessBlock(IB[j], OB[j]); 917 AssignLeftMostBits(CT[j], OB[j], K); 918 Xor(CT[j], CT[j], PT[j]); 919 AssignLeftMostBits(PT[j+1], IB[j], K); 920 IB[j+1].resize(blockSize); 921 memcpy(IB[j+1], IB[j]+K/8, blockSize-K/8); 922 memcpy(IB[j+1]+blockSize-K/8, CT[j], K/8); 923 } 924 else 925 { 926 OB[j].resize(blockSize); 927 pBT->ProcessBlock(IB[j], OB[j]); 928 AssignLeftMostBits(PT[j], OB[j], K); 929 Xor(PT[j], PT[j], CT[j]); 930 IB[j+1].resize(blockSize); 931 memcpy(IB[j+1], IB[j]+K/8, blockSize-K/8); 932 memcpy(IB[j+1]+blockSize-K/8, CT[j], K/8); 933 AssignLeftMostBits(CT[j+1], OB[j], K); 934 } 935 } 936 else 937 throw Exception(Exception::OTHER_ERROR, "TestDataParser: unexpected mode: " + m_mode); 938 } 939 940 OutputData(output, COUNT, IntToString(i)); 941 OutputData(output, KEY_T, KEY[i]); 942 if (m_mode == "CBC") 943 OutputData(output, IV, CV[0]); 944 if (m_mode == "OFB" || m_mode == "CFB") 945 OutputData(output, IV, IB[0]); 946 if (m_mode == "ECB" || m_mode == "CBC" || m_mode == "CFB") 947 { 948 if (encrypt) 949 { 950 OutputData(output, INPUT, PT[0]); 951 OutputData(output, OUTPUT, CT[innerCount-1]); 952 KEY[i+1] = UpdateKey(KEY[i], &CT[0]); 953 } 954 else 955 { 956 OutputData(output, INPUT, CT[0]); 957 OutputData(output, OUTPUT, PT[innerCount-1]); 958 KEY[i+1] = UpdateKey(KEY[i], &PT[0]); 959 } 960 PT[0] = PT[innerCount]; 961 IB[0] = IB[innerCount]; 962 CV[0] = CV[innerCount]; 963 CT[0] = CT[innerCount]; 964 } 965 else if (m_mode == "OFB") 966 { 967 OutputData(output, INPUT, TXT[0]); 968 OutputData(output, OUTPUT, RESULT[innerCount-1]); 969 KEY[i+1] = UpdateKey(KEY[i], &RESULT[0]); 970 Xor(TXT[0], TXT[0], IB[innerCount-1]); 971 IB[0] = OB[innerCount-1]; 972 } 973 output += "\n"; 974 AttachedTransformation()->Put((byte *)output.data(), output.size()); 975 output.resize(0); 976 } 977 } 978 else if (m_test == "MCT") 979 { 980 SecByteBlock KEY[101]; 981 KEY[0] = key; 982 int keySize = key.size(); 983 int blockSize = pBT->BlockSize(); 984 985 SecByteBlock ivs[101], inputs[1001], outputs[1001]; 986 ivs[0] = iv; 987 inputs[0] = m_data2[INPUT]; 988 989 for (int i=0; i<100; i++) 990 { 991 pCipher->SetKey(KEY[i], keySize, MakeParameters(Name::IV(), (const byte *)ivs[i])(Name::FeedbackSize(), (int)K/8, false)); 992 993 for (int j=0; j<1000; j++) 994 { 995 outputs[j] = inputs[j]; 996 pCipher->ProcessString(outputs[j], outputs[j].size()); 997 if (K==8 && m_mode == "CFB") 998 { 999 if (j<16) 1000 inputs[j+1].Assign(ivs[i]+j, 1); 1001 else 1002 inputs[j+1] = outputs[j-16]; 1003 } 1004 else if (m_mode == "ECB") 1005 inputs[j+1] = outputs[j]; 1006 else if (j == 0) 1007 inputs[j+1] = ivs[i]; 1008 else 1009 inputs[j+1] = outputs[j-1]; 1010 } 1011 1012 if (m_algorithm == "AES") 1013 OutputData(output, COUNT, m_count++); 1014 OutputData(output, KEY_T, KEY[i]); 1015 if (m_mode != "ECB") 1016 OutputData(output, IV, ivs[i]); 1017 OutputData(output, INPUT, inputs[0]); 1018 OutputData(output, OUTPUT, outputs[999]); 1019 output += "\n"; 1020 AttachedTransformation()->Put((byte *)output.data(), output.size()); 1021 output.resize(0); 1022 1023 KEY[i+1] = UpdateKey(KEY[i], outputs); 1024 ivs[i+1].CleanNew(pCipher->IVSize()); 1025 ivs[i+1] = UpdateKey(ivs[i+1], outputs); 1026 if (K==8 && m_mode == "CFB") 1027 inputs[0] = outputs[999-16]; 1028 else if (m_mode == "ECB") 1029 inputs[0] = outputs[999]; 1030 else 1031 inputs[0] = outputs[998]; 1032 } 1033 } 1034 else 1035 { 1036 CRYPTOPP_ASSERT(m_test == "KAT"); 1037 1038 SecByteBlock &input = m_data2[INPUT]; 1039 SecByteBlock result(input.size()); 1040 member_ptr<Filter> pFilter(new StreamTransformationFilter(*pCipher, new ArraySink(result, result.size()), StreamTransformationFilter::NO_PADDING)); 1041 StringSource(input.data(), input.size(), true, pFilter.release()); 1042 1043 OutputGivenData(output, COUNT, true); 1044 OutputData(output, KEY_T, key); 1045 OutputGivenData(output, IV, true); 1046 OutputGivenData(output, INPUT); 1047 OutputData(output, OUTPUT, result); 1048 output += "\n"; 1049 AttachedTransformation()->Put((byte *)output.data(), output.size()); 1050 } 1051 } 1052 1053 std::vector<std::string> Tokenize(const std::string &line) 1054 { 1055 std::vector<std::string> result; 1056 std::string s; 1057 for (unsigned int i=0; i<line.size(); i++) 1058 { 1059 if (isalnum(line[i]) || line[i] == '^') 1060 s += line[i]; 1061 else if (!s.empty()) 1062 { 1063 result.push_back(s); 1064 s = ""; 1065 } 1066 if (line[i] == '=') 1067 result.push_back("="); 1068 } 1069 if (!s.empty()) 1070 result.push_back(s); 1071 return result; 1072 } 1073 1074 bool IsolatedMessageEnd(bool blocking) 1075 { 1076 if (!blocking) 1077 throw BlockingInputOnly("TestDataParser"); 1078 1079 m_line.resize(0); 1080 m_inQueue.TransferTo(StringSink(m_line).Ref()); 1081 1082 if (m_line[0] == '#') 1083 return false; 1084 1085 bool copyLine = false; 1086 1087 if (m_line[0] == '[') 1088 { 1089 m_bracketString = m_line.substr(1, m_line.size()-2); 1090 if (m_bracketString == "ENCRYPT") 1091 SetEncrypt(true); 1092 if (m_bracketString == "DECRYPT") 1093 SetEncrypt(false); 1094 copyLine = true; 1095 } 1096 1097 if (m_line.substr(0, 2) == "H>") 1098 { 1099 CRYPTOPP_ASSERT(m_test == "sha"); 1100 m_bracketString = m_line.substr(2, m_line.size()-4); 1101 m_line = m_line.substr(0, 13) + "Hashes<H"; 1102 copyLine = true; 1103 } 1104 1105 if (m_line == "D>") 1106 copyLine = true; 1107 1108 if (m_line == "<D") 1109 { 1110 m_line += "\n"; 1111 copyLine = true; 1112 } 1113 1114 if (copyLine) 1115 { 1116 m_line += '\n'; 1117 AttachedTransformation()->Put((byte *)m_line.data(), m_line.size(), blocking); 1118 return false; 1119 } 1120 1121 std::vector<std::string> tokens = Tokenize(m_line); 1122 1123 if (m_algorithm == "DSA" && m_test == "sha") 1124 { 1125 for (unsigned int i = 0; i < tokens.size(); i++) 1126 { 1127 if (tokens[i] == "^") 1128 DoTest(); 1129 else if (tokens[i] != "") 1130 m_compactString.push_back(atol(tokens[i].c_str())); 1131 } 1132 } 1133 else 1134 { 1135 if (!m_line.empty() && ((m_algorithm == "RSA" && m_test != "Gen") || m_algorithm == "RNG" || m_algorithm == "HMAC" || m_algorithm == "SHA" || (m_algorithm == "ECDSA" && m_test != "KeyPair") || (m_algorithm == "DSA" && (m_test == "PQGVer" || m_test == "SigVer")))) 1136 { 1137 // copy input to output 1138 std::string output = m_line + '\n'; 1139 AttachedTransformation()->Put((byte *)output.data(), output.size()); 1140 } 1141 1142 for (unsigned int i = 0; i < tokens.size(); i++) 1143 { 1144 if (m_firstLine && m_algorithm != "DSA") 1145 { 1146 if (tokens[i] == "Encrypt" || tokens[i] == "OFB") 1147 SetEncrypt(true); 1148 else if (tokens[i] == "Decrypt") 1149 SetEncrypt(false); 1150 else if (tokens[i] == "Modes") 1151 m_test = "MONTE"; 1152 } 1153 else 1154 { 1155 if (tokens[i] != "=") 1156 continue; 1157 1158 if (i == 0) 1159 throw Exception(Exception::OTHER_ERROR, "TestDataParser: unexpected data: " + m_line); 1160 1161 const std::string &key = tokens[i-1]; 1162 std::string &data = m_data[key]; 1163 data = (tokens.size() > i+1) ? tokens[i+1] : ""; 1164 DataType t = m_nameToType[key]; 1165 m_typeToName[t] = key; 1166 m_data2[t] = DecodeHex(data); 1167 1168 if (key == m_trigger || (t == OUTPUT && !m_data2[INPUT].empty() && !isspace(m_line[0]))) 1169 DoTest(); 1170 } 1171 } 1172 } 1173 1174 m_firstLine = false; 1175 1176 return false; 1177 } 1178 1179 inline const SecByteBlock & GetData(const std::string &key) 1180 { 1181 return m_data2[m_nameToType[key]]; 1182 } 1183 1184 static SecByteBlock DecodeHex(const std::string &data) 1185 { 1186 SecByteBlock data2(data.size() / 2); 1187 StringSource(data, true, new HexDecoder(new ArraySink(data2, data2.size()))); 1188 return data2; 1189 } 1190 1191 std::string m_algorithm, m_test, m_mode, m_line, m_bracketString, m_trigger; 1192 unsigned int m_feedbackSize, m_blankLineTransition; 1193 bool m_encrypt, m_firstLine; 1194 1195 typedef std::map<std::string, DataType> NameToTypeMap; 1196 NameToTypeMap m_nameToType; 1197 typedef std::map<DataType, std::string> TypeToNameMap; 1198 TypeToNameMap m_typeToName; 1199 1200 typedef std::map<std::string, std::string> Map; 1201 Map m_data; // raw data 1202 typedef std::map<DataType, SecByteBlock> Map2; 1203 Map2 m_data2; 1204 int m_count; 1205 1206 AutoSeededX917RNG<AES> m_rng; 1207 std::vector<unsigned int> m_compactString; 1208 }; 1209 1210 int FIPS_140_AlgorithmTest(int argc, char **argv) 1211 { 1212 argc--; 1213 argv++; 1214 1215 std::string algorithm = argv[1]; 1216 std::string pathname = argv[2]; 1217 unsigned int i = pathname.find_last_of("\\/"); 1218 std::string filename = pathname.substr(i == std::string::npos ? 0 : i+1); 1219 std::string dirname = pathname.substr(0, i); 1220 1221 if (algorithm == "auto") 1222 { 1223 string algTable[] = {"AES", "ECDSA", "DSA", "HMAC", "RNG", "RSA", "TDES", "SKIPJACK", "SHA"}; // order is important here 1224 for (i=0; i<sizeof(algTable)/sizeof(algTable[0]); i++) 1225 { 1226 if (dirname.find(algTable[i]) != std::string::npos) 1227 { 1228 algorithm = algTable[i]; 1229 break; 1230 } 1231 } 1232 } 1233 1234 try 1235 { 1236 std::string mode; 1237 if (algorithm == "SHA") 1238 mode = IntToString(atol(filename.substr(3, 3).c_str())); 1239 else if (algorithm == "RSA") 1240 mode = filename.substr(6, 1); 1241 else if (filename[0] == 'S' || filename[0] == 'T') 1242 mode = filename.substr(1, 3); 1243 else 1244 mode = filename.substr(0, 3); 1245 for (i = 0; i<mode.size(); i++) 1246 mode[i] = toupper(mode[i]); 1247 unsigned int feedbackSize = mode == "CFB" ? atoi(filename.substr(filename.find_first_of("0123456789")).c_str()) : 0; 1248 std::string test; 1249 if (algorithm == "DSA" || algorithm == "ECDSA") 1250 test = filename.substr(0, filename.size() - 4); 1251 else if (algorithm == "RSA") 1252 test = filename.substr(3, 3); 1253 else if (filename.find("Monte") != std::string::npos) 1254 test = "MONTE"; 1255 else if (filename.find("MCT") != std::string::npos) 1256 test = "MCT"; 1257 else 1258 test = "KAT"; 1259 bool encrypt = (filename.find("vrct") == std::string::npos); 1260 1261 BufferedTransformation *pSink = NULLPTR; 1262 1263 if (argc > 3) 1264 { 1265 std::string outDir = argv[3]; 1266 1267 if (outDir == "auto") 1268 { 1269 if (dirname.substr(dirname.size()-3) == "req") 1270 outDir = dirname.substr(0, dirname.size()-3) + "resp"; 1271 } 1272 1273 if (*outDir.rbegin() != '\\' && *outDir.rbegin() != '/') 1274 outDir += '/'; 1275 std::string outPathname = outDir + filename.substr(0, filename.size() - 3) + "rsp"; 1276 pSink = new FileSink(outPathname.c_str(), false); 1277 } 1278 else 1279 pSink = new FileSink(cout); 1280 1281 FileSource(pathname.c_str(), true, new LineBreakParser(new TestDataParser(algorithm, test, mode, feedbackSize, encrypt, pSink)), false); 1282 } 1283 catch (...) 1284 { 1285 cout << "file: " << filename << endl; 1286 throw; 1287 } 1288 return 0; 1289 } 1290 1291 extern int (*AdhocTest)(int argc, char *argv[]); 1292 static int s_i = (AdhocTest = &FIPS_140_AlgorithmTest, 0); 1293 #endif 1294