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