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