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