updated FIPS algorithm tests

pull/2/head
weidai 2006-12-09 17:15:38 +00:00
parent e94ff46d6f
commit 85b68c9b71
1 changed files with 128 additions and 139 deletions

View File

@ -19,7 +19,7 @@ public:
LineBreakParser(BufferedTransformation *attachment=NULL, byte lineEnd='\n') LineBreakParser(BufferedTransformation *attachment=NULL, byte lineEnd='\n')
: m_lineEnd(lineEnd) {Detach(attachment);} : m_lineEnd(lineEnd) {Detach(attachment);}
unsigned int Put2(const byte *begin, unsigned int length, int messageEnd, bool blocking) size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking)
{ {
if (!blocking) if (!blocking)
throw BlockingInputOnly("LineBreakParser"); throw BlockingInputOnly("LineBreakParser");
@ -60,6 +60,8 @@ public:
{ {
Detach(attachment); Detach(attachment);
m_typeToName[COUNT] = "COUNT";
m_nameToType["COUNT"] = COUNT; m_nameToType["COUNT"] = COUNT;
m_nameToType["KEY"] = KEY_T; m_nameToType["KEY"] = KEY_T;
m_nameToType["KEYs"] = KEY_T; m_nameToType["KEYs"] = KEY_T;
@ -78,26 +80,7 @@ public:
m_nameToType["DT"] = IV; m_nameToType["DT"] = IV;
SetEncrypt(encrypt); SetEncrypt(encrypt);
if (m_algorithm == "DSS") if (m_algorithm == "DSA" || m_algorithm == "ECDSA")
{
if (m_test == "prime")
m_trigger = "Prime";
else if (m_test == "pqg")
m_trigger = "N";
else if (m_test == "xy")
m_trigger = "G";
else if (m_test == "gensig")
m_trigger = "Msg";
else if (m_test == "versig")
m_trigger = "Sig";
else if (m_test == "verpqg")
m_trigger = "c";
}
else if (m_algorithm == "HMAC")
m_trigger = "Msg";
else if (m_algorithm == "SHA2")
m_trigger = (m_test == "MONTE") ? "Seed" : "Msg";
else if (m_algorithm == "ECDSA")
{ {
if (m_test == "PKV") if (m_test == "PKV")
m_trigger = "Qy"; m_trigger = "Qy";
@ -107,7 +90,15 @@ public:
m_trigger = "Msg"; m_trigger = "Msg";
else if (m_test == "SigVer") else if (m_test == "SigVer")
m_trigger = "S"; m_trigger = "S";
else if (m_test == "PQGGen")
m_trigger = "N";
else if (m_test == "PQGVer")
m_trigger = "H";
} }
else if (m_algorithm == "HMAC")
m_trigger = "Msg";
else if (m_algorithm == "SHA")
m_trigger = (m_test == "MONTE") ? "Seed" : "Msg";
else if (m_algorithm == "RNG") else if (m_algorithm == "RNG")
m_trigger = "V"; m_trigger = "V";
else if (m_algorithm == "RSA") else if (m_algorithm == "RSA")
@ -324,12 +315,12 @@ protected:
void EC_SigGen(string &output, const OID &oid) void EC_SigGen(string &output, const OID &oid)
{ {
DL_GroupParameters_EC<EC> params(oid); DL_GroupParameters_EC<EC> params(oid);
ECDSA<EC, SHA1>::PrivateKey priv; typename ECDSA<EC, SHA1>::PrivateKey priv;
ECDSA<EC, SHA1>::PublicKey pub; typename ECDSA<EC, SHA1>::PublicKey pub;
priv.Initialize(m_rng, params); priv.Initialize(m_rng, params);
priv.MakePublicKey(pub); priv.MakePublicKey(pub);
ECDSA<EC, SHA1>::Signer signer(priv); typename ECDSA<EC, SHA1>::Signer signer(priv);
SecByteBlock sig(signer.SignatureLength()); SecByteBlock sig(signer.SignatureLength());
StringSource(m_data["Msg"], true, new HexDecoder(new SignerFilter(m_rng, signer, new ArraySink(sig, sig.size())))); StringSource(m_data["Msg"], true, new HexDecoder(new SignerFilter(m_rng, signer, new ArraySink(sig, sig.size()))));
SecByteBlock R(sig, sig.size()/2), S(sig+sig.size()/2, sig.size()/2); SecByteBlock R(sig, sig.size()/2), S(sig+sig.size()/2, sig.size()/2);
@ -348,14 +339,14 @@ protected:
Integer r((m_data["R"]+"h").c_str()); Integer r((m_data["R"]+"h").c_str());
Integer s((m_data["S"]+"h").c_str()); Integer s((m_data["S"]+"h").c_str());
EC::FieldElement Qx(x, x.size()); typename EC::FieldElement Qx(x, x.size());
EC::FieldElement Qy(y, y.size()); typename EC::FieldElement Qy(y, y.size());
EC::Element Q(Qx, Qy); typename EC::Element Q(Qx, Qy);
DL_GroupParameters_EC<EC> params(oid); DL_GroupParameters_EC<EC> params(oid);
ECDSA<EC, SHA1>::PublicKey pub; typename ECDSA<EC, SHA1>::PublicKey pub;
pub.Initialize(params, Q); pub.Initialize(params, Q);
ECDSA<EC, SHA1>::Verifier verifier(pub); typename ECDSA<EC, SHA1>::Verifier verifier(pub);
SecByteBlock sig(verifier.SignatureLength()); SecByteBlock sig(verifier.SignatureLength());
r.Encode(sig, sig.size()/2); r.Encode(sig, sig.size()/2);
@ -373,12 +364,12 @@ protected:
template <class EC> template <class EC>
static bool EC_PKV(RandomNumberGenerator &rng, const SecByteBlock &x, const SecByteBlock &y, const OID &oid) static bool EC_PKV(RandomNumberGenerator &rng, const SecByteBlock &x, const SecByteBlock &y, const OID &oid)
{ {
EC::FieldElement Qx(x, x.size()); typename EC::FieldElement Qx(x, x.size());
EC::FieldElement Qy(y, y.size()); typename EC::FieldElement Qy(y, y.size());
EC::Element Q(Qx, Qy); typename EC::Element Q(Qx, Qy);
DL_GroupParameters_EC<EC> params(oid); DL_GroupParameters_EC<EC> params(oid);
ECDSA<EC, SHA1>::PublicKey pub; typename ECDSA<EC, SHA1>::PublicKey pub;
pub.Initialize(params, Q); pub.Initialize(params, Q);
return pub.Validate(rng, 3); return pub.Validate(rng, 3);
} }
@ -389,20 +380,20 @@ protected:
if (typeid(Result) == typeid(PK_Verifier)) if (typeid(Result) == typeid(PK_Verifier))
{ {
if (standard == "R") if (standard == "R")
return (Result *) new RSASS_ISO<H>::Verifier; return (Result *) new typename RSASS_ISO<H>::Verifier;
else if (standard == "P") else if (standard == "P")
return (Result *) new RSASS<PSS, H>::Verifier; return (Result *) new typename RSASS<PSS, H>::Verifier;
else if (standard == "1") else if (standard == "1")
return (Result *) new RSASS<PKCS1v15, H>::Verifier; return (Result *) new typename RSASS<PKCS1v15, H>::Verifier;
} }
else if (typeid(Result) == typeid(PK_Signer)) else if (typeid(Result) == typeid(PK_Signer))
{ {
if (standard == "R") if (standard == "R")
return (Result *) new RSASS_ISO<H>::Signer; return (Result *) new typename RSASS_ISO<H>::Signer;
else if (standard == "P") else if (standard == "P")
return (Result *) new RSASS<PSS, H>::Signer; return (Result *) new typename RSASS<PSS, H>::Signer;
else if (standard == "1") else if (standard == "1")
return (Result *) new RSASS<PKCS1v15, H>::Signer; return (Result *) new typename RSASS<PKCS1v15, H>::Signer;
} }
return NULL; return NULL;
@ -429,66 +420,32 @@ protected:
{ {
std::string output; std::string output;
if (m_algorithm == "DSS") if (m_algorithm == "DSA")
{ {
if (m_test == "sha") if (m_test == "KeyPair")
{ {
assert(m_compactString.size() >= 2); DL_GroupParameters_DSA pqg;
assert(m_compactString[0] == m_compactString.size()-2); int modLen = atol(m_bracketString.substr(6).c_str());
bool b = !!m_compactString[1]; pqg.GenerateRandomWithKeySize(m_rng, modLen);
Integer m;
unsigned int bitLength = 0;
for (unsigned int j = 2; j < m_compactString.size(); j++) OutputData(output, "P ", pqg.GetModulus());
{ OutputData(output, "Q ", pqg.GetSubgroupOrder());
m <<= m_compactString[j]; OutputData(output, "G ", pqg.GetSubgroupGenerator());
for (unsigned int k = 0; k < m_compactString[j]; k++)
m.SetBit(k, b);
bitLength += m_compactString[j];
b = !b;
}
m_compactString.clear();
assert(bitLength % 8 == 0);
SecByteBlock message(bitLength / 8); int n = atol(m_data["N"].c_str());
m.Encode(message, message.size()); for (int i=0; i<n; i++)
SHA sha; {
DSA::Signer priv;
priv.AccessKey().GenerateRandom(m_rng, pqg);
DSA::Verifier pub(priv);
if (m_bracketString == "SHS Type 3 Strings") OutputData(output, "X ", priv.GetKey().GetPrivateExponent());
{ OutputData(output, "Y ", pub.GetKey().GetPublicElement());
SecByteBlock m1;
for (int j = 0; j < 100; j++)
{
for (word32 i = 1; i <= 50000; i++)
{
m1.resize(message.size() + j/4 + 3 + 4);
memcpy(m1, message, message.size());
memset(m1 + message.size(), 0, j/4 + 3);
PutWord(false, BIG_ENDIAN_ORDER, m1 + m1.size() - 4, i);
message.resize(sha.DigestSize());
sha.CalculateDigest(message, m1, m1.size());
}
StringSource(message, message.size(), true, new HexEncoder(new StringSink(output)));
output += " ^\n";
AttachedTransformation()->Put((byte *)output.data(), output.size()); AttachedTransformation()->Put((byte *)output.data(), output.size());
output.resize(0); output.resize(0);
} }
} }
else else if (m_test == "PQGGen")
{
StringSource(message, message.size(), true, new HashFilter(sha, new HexEncoder(new StringSink(output))));
output += " ^\n";
AttachedTransformation()->Put((byte *)output.data(), output.size());
}
}
else if (m_test == "prime")
{
Integer p((m_data["Prime"] + "h").c_str());
OutputData(output, "result", VerifyPrime(m_rng, p, 2) ? "P" : "F");
AttachedTransformation()->Put((byte *)output.data(), output.size());
output.resize(0);
}
else if (m_test == "pqg")
{ {
int n = atol(m_data["N"].c_str()); int n = atol(m_data["N"].c_str());
for (int i=0; i<n; i++) for (int i=0; i<n; i++)
@ -505,48 +462,54 @@ protected:
h.Randomize(m_rng, 2, p-2); h.Randomize(m_rng, 2, p-2);
g = a_exp_b_mod_c(h, (p-1)/q, p); g = a_exp_b_mod_c(h, (p-1)/q, p);
OutputData(output, "P", p); OutputData(output, "P ", p);
OutputData(output, "Q", q); OutputData(output, "Q ", q);
OutputData(output, "G", g); OutputData(output, "G ", g);
OutputData(output, "Seed", seed); OutputData(output, "Seed ", seed);
OutputData(output, "H", h, p.ByteCount()); OutputData(output, "c ", counter);
OutputData(output, "c", counter); OutputData(output, "H ", h, p.ByteCount());
AttachedTransformation()->Put((byte *)output.data(), output.size()); AttachedTransformation()->Put((byte *)output.data(), output.size());
output.resize(0); output.resize(0);
} }
} }
else if (m_test == "xy") else if (m_test == "SigGen")
{ {
Integer p((m_data["P"] + "h").c_str()); std::string &encodedKey = m_data["PrivKey"];
Integer q((m_data["Q"] + "h").c_str()); int modLen = atol(m_bracketString.substr(6).c_str());
Integer g((m_data["G"] + "h").c_str()); DSA::PrivateKey priv;
for (int i=0; i<10; i++) if (!encodedKey.empty())
{ {
DSA::Signer priv(m_rng, p, q, g); StringStore s(encodedKey);
DSA::Verifier pub(priv); priv.BERDecode(s);
if (priv.GetGroupParameters().GetModulus().BitCount() != modLen)
encodedKey.clear();
}
OutputData(output, "X", priv.GetKey().GetPrivateExponent()); if (encodedKey.empty())
OutputData(output, "Y", pub.GetKey().GetPublicElement());
AttachedTransformation()->Put((byte *)output.data(), output.size());
output.resize(0);
}
}
else if (m_test == "gensig")
{ {
Integer p((m_data["P"] + "h").c_str()); priv.Initialize(m_rng, modLen);
Integer q((m_data["Q"] + "h").c_str()); StringSink s(encodedKey);
Integer g((m_data["G"] + "h").c_str()); priv.DEREncode(s);
Integer x((m_data["X"] + "h").c_str()); OutputData(output, "P ", priv.GetGroupParameters().GetModulus());
DSA::Signer signer(p, q, g, x); OutputData(output, "Q ", priv.GetGroupParameters().GetSubgroupOrder());
OutputData(output, "G ", priv.GetGroupParameters().GetSubgroupGenerator());
}
DSA::Signer signer(priv);
DSA::Verifier pub(signer);
OutputData(output, "Msg ", m_data["Msg"]);
OutputData(output, "Y ", pub.GetKey().GetPublicElement());
SecByteBlock sig(signer.SignatureLength()); SecByteBlock sig(signer.SignatureLength());
StringSource(m_data["Msg"], true, new HexDecoder(new SignerFilter(m_rng, signer, new ArraySink(sig, sig.size())))); StringSource(m_data["Msg"], true, new HexDecoder(new SignerFilter(m_rng, signer, new ArraySink(sig, sig.size()))));
OutputData(output, "Sig", sig); SecByteBlock R(sig, sig.size()/2), S(sig+sig.size()/2, sig.size()/2);
OutputData(output, "R ", R);
OutputData(output, "S ", S);
AttachedTransformation()->Put((byte *)output.data(), output.size()); AttachedTransformation()->Put((byte *)output.data(), output.size());
output.resize(0); output.resize(0);
} }
else if (m_test == "versig") else if (m_test == "SigVer")
{ {
Integer p((m_data["P"] + "h").c_str()); Integer p((m_data["P"] + "h").c_str());
Integer q((m_data["Q"] + "h").c_str()); Integer q((m_data["Q"] + "h").c_str());
@ -555,16 +518,17 @@ protected:
DSA::Verifier verifier(p, q, g, y); DSA::Verifier verifier(p, q, g, y);
HexDecoder filter(new SignatureVerificationFilter(verifier)); HexDecoder filter(new SignatureVerificationFilter(verifier));
StringSource(m_data["Sig"], true, new Redirector(filter, Redirector::DATA_ONLY)); StringSource(m_data["R"], true, new Redirector(filter, Redirector::DATA_ONLY));
StringSource(m_data["S"], true, new Redirector(filter, Redirector::DATA_ONLY));
StringSource(m_data["Msg"], true, new Redirector(filter, Redirector::DATA_ONLY)); StringSource(m_data["Msg"], true, new Redirector(filter, Redirector::DATA_ONLY));
filter.MessageEnd(); filter.MessageEnd();
byte b; byte b;
filter.Get(b); filter.Get(b);
OutputData(output, "result", b ? "P" : "F"); OutputData(output, "Result ", b ? "P" : "F");
AttachedTransformation()->Put((byte *)output.data(), output.size()); AttachedTransformation()->Put((byte *)output.data(), output.size());
output.resize(0); output.resize(0);
} }
else if (m_test == "verpqg") else if (m_test == "PQGVer")
{ {
Integer p((m_data["P"] + "h").c_str()); Integer p((m_data["P"] + "h").c_str());
Integer q((m_data["Q"] + "h").c_str()); Integer q((m_data["Q"] + "h").c_str());
@ -579,7 +543,7 @@ protected:
result = result && (p1 == p && q1 == q); result = result && (p1 == p && q1 == q);
result = result && g == a_exp_b_mod_c(h, (p-1)/q, p); result = result && g == a_exp_b_mod_c(h, (p-1)/q, p);
OutputData(output, "result", result ? "P" : "F"); OutputData(output, "Result ", result ? "P" : "F");
AttachedTransformation()->Put((byte *)output.data(), output.size()); AttachedTransformation()->Put((byte *)output.data(), output.size());
output.resize(0); output.resize(0);
} }
@ -706,11 +670,13 @@ protected:
return; return;
} }
if (m_algorithm == "SHA2") if (m_algorithm == "SHA")
{ {
member_ptr<HashFunction> pHF; member_ptr<HashFunction> pHF;
if (m_mode == "224") if (m_mode == "1")
pHF.reset(new SHA1);
else if (m_mode == "224")
pHF.reset(new SHA224); pHF.reset(new SHA224);
else if (m_mode == "256") else if (m_mode == "256")
pHF.reset(new SHA256); pHF.reset(new SHA256);
@ -881,7 +847,7 @@ protected:
int keySize = key.size(); int keySize = key.size();
int blockSize = pBT->BlockSize(); int blockSize = pBT->BlockSize();
SecByteBlock IB[10001], OB[10001], PT[10001], CT[10001], RESULT[10001], TXT[10001], CV[10001]; std::vector<SecByteBlock> IB(10001), OB(10001), PT(10001), CT(10001), RESULT(10001), TXT(10001), CV(10001);
PT[0] = GetData("PLAINTEXT"); PT[0] = GetData("PLAINTEXT");
CT[0] = GetData("CIPHERTEXT"); CT[0] = GetData("CIPHERTEXT");
CV[0] = IB[0] = iv; CV[0] = IB[0] = iv;
@ -970,7 +936,7 @@ protected:
throw Exception(Exception::OTHER_ERROR, "TestDataParser: unexpected mode: " + m_mode); throw Exception(Exception::OTHER_ERROR, "TestDataParser: unexpected mode: " + m_mode);
} }
OutputData(output, "COUNT ", i); OutputData(output, COUNT, IntToString(i));
OutputData(output, KEY_T, KEY[i]); OutputData(output, KEY_T, KEY[i]);
if (m_mode == "CBC") if (m_mode == "CBC")
OutputData(output, IV, CV[0]); OutputData(output, IV, CV[0]);
@ -982,13 +948,13 @@ protected:
{ {
OutputData(output, INPUT, PT[0]); OutputData(output, INPUT, PT[0]);
OutputData(output, OUTPUT, CT[innerCount-1]); OutputData(output, OUTPUT, CT[innerCount-1]);
KEY[i+1] = UpdateKey(KEY[i], CT); KEY[i+1] = UpdateKey(KEY[i], &CT[0]);
} }
else else
{ {
OutputData(output, INPUT, CT[0]); OutputData(output, INPUT, CT[0]);
OutputData(output, OUTPUT, PT[innerCount-1]); OutputData(output, OUTPUT, PT[innerCount-1]);
KEY[i+1] = UpdateKey(KEY[i], PT); KEY[i+1] = UpdateKey(KEY[i], &PT[0]);
} }
PT[0] = PT[innerCount]; PT[0] = PT[innerCount];
IB[0] = IB[innerCount]; IB[0] = IB[innerCount];
@ -999,7 +965,7 @@ protected:
{ {
OutputData(output, INPUT, TXT[0]); OutputData(output, INPUT, TXT[0]);
OutputData(output, OUTPUT, RESULT[innerCount-1]); OutputData(output, OUTPUT, RESULT[innerCount-1]);
KEY[i+1] = UpdateKey(KEY[i], RESULT); KEY[i+1] = UpdateKey(KEY[i], &RESULT[0]);
Xor(TXT[0], TXT[0], IB[innerCount-1]); Xor(TXT[0], TXT[0], IB[innerCount-1]);
IB[0] = OB[innerCount-1]; IB[0] = OB[innerCount-1];
} }
@ -1099,6 +1065,7 @@ protected:
if (line[i] == '=') if (line[i] == '=')
result.push_back("="); result.push_back("=");
} }
if (!s.empty())
result.push_back(s); result.push_back(s);
return result; return result;
} }
@ -1152,7 +1119,7 @@ protected:
std::vector<std::string> tokens = Tokenize(m_line); std::vector<std::string> tokens = Tokenize(m_line);
if (m_algorithm == "DSS" && m_test == "sha") if (m_algorithm == "DSA" && m_test == "sha")
{ {
for (unsigned int i = 0; i < tokens.size(); i++) for (unsigned int i = 0; i < tokens.size(); i++)
{ {
@ -1164,7 +1131,7 @@ protected:
} }
else else
{ {
if (!m_line.empty() && ((m_algorithm == "RSA" && m_test != "Gen") || m_algorithm == "RNG" || m_algorithm == "HMAC" || m_algorithm == "SHA2" || (m_algorithm == "ECDSA" && m_test != "KeyPair") || (m_algorithm == "DSS" && m_test != "pqg"))) 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"))))
{ {
// copy input to output // copy input to output
std::string output = m_line + '\n'; std::string output = m_line + '\n';
@ -1173,7 +1140,7 @@ protected:
for (unsigned int i = 0; i < tokens.size(); i++) for (unsigned int i = 0; i < tokens.size(); i++)
{ {
if (m_firstLine && m_algorithm != "DSS") if (m_firstLine && m_algorithm != "DSA")
{ {
if (tokens[i] == "Encrypt" || tokens[i] == "OFB") if (tokens[i] == "Encrypt" || tokens[i] == "OFB")
SetEncrypt(true); SetEncrypt(true);
@ -1192,12 +1159,12 @@ protected:
const std::string &key = tokens[i-1]; const std::string &key = tokens[i-1];
std::string &data = m_data[key]; std::string &data = m_data[key];
data = tokens[i+1]; data = (tokens.size() > i+1) ? tokens[i+1] : "";
DataType t = m_nameToType[key]; DataType t = m_nameToType[key];
m_typeToName[t] = key; m_typeToName[t] = key;
m_data2[t] = DecodeHex(data); m_data2[t] = DecodeHex(data);
if (key == m_trigger || (t == OUTPUT && !m_data2[INPUT].empty())) if (key == m_trigger || (t == OUTPUT && !m_data2[INPUT].empty() && !isspace(m_line[0])))
DoTest(); DoTest();
} }
} }
@ -1248,11 +1215,26 @@ int FIPS_140_AlgorithmTest(int argc, char **argv)
std::string pathname = argv[2]; std::string pathname = argv[2];
unsigned int i = pathname.find_last_of("\\/"); unsigned int i = pathname.find_last_of("\\/");
std::string filename = pathname.substr(i == std::string::npos ? 0 : i+1); std::string filename = pathname.substr(i == std::string::npos ? 0 : i+1);
std::string dirname = pathname.substr(0, i);
if (algorithm == "auto")
{
string algTable[] = {"AES", "ECDSA", "DSA", "HMAC", "RNG", "RSA", "TDES", "SKIPJACK", "SHA"}; // order is important here
for (i=0; i<sizeof(algTable)/sizeof(algTable[0]); i++)
{
if (dirname.find(algTable[i]) != std::string::npos)
{
algorithm = algTable[i];
break;
}
}
}
try try
{ {
std::string mode; std::string mode;
if (algorithm == "SHA2") if (algorithm == "SHA")
mode = filename.substr(3, 3); mode = IntToString(atol(filename.substr(3, 3).c_str()));
else if (algorithm == "RSA") else if (algorithm == "RSA")
mode = filename.substr(6, 1); mode = filename.substr(6, 1);
else if (filename[0] == 'S' || filename[0] == 'T') else if (filename[0] == 'S' || filename[0] == 'T')
@ -1263,7 +1245,7 @@ int FIPS_140_AlgorithmTest(int argc, char **argv)
mode[i] = toupper(mode[i]); mode[i] = toupper(mode[i]);
unsigned int feedbackSize = mode == "CFB" ? atoi(filename.substr(filename.find_first_of("0123456789")).c_str()) : 0; unsigned int feedbackSize = mode == "CFB" ? atoi(filename.substr(filename.find_first_of("0123456789")).c_str()) : 0;
std::string test; std::string test;
if (algorithm == "DSS" || algorithm == "ECDSA") if (algorithm == "DSA" || algorithm == "ECDSA")
test = filename.substr(0, filename.size() - 4); test = filename.substr(0, filename.size() - 4);
else if (algorithm == "RSA") else if (algorithm == "RSA")
test = filename.substr(3, 3); test = filename.substr(3, 3);
@ -1280,6 +1262,13 @@ int FIPS_140_AlgorithmTest(int argc, char **argv)
if (argc > 3) if (argc > 3)
{ {
std::string outDir = argv[3]; std::string outDir = argv[3];
if (outDir == "auto")
{
if (dirname.substr(dirname.size()-3) == "req")
outDir = dirname.substr(0, dirname.size()-3) + "resp";
}
if (*outDir.rbegin() != '\\' && *outDir.rbegin() != '/') if (*outDir.rbegin() != '\\' && *outDir.rbegin() != '/')
outDir += '/'; outDir += '/';
std::string outPathname = outDir + filename.substr(0, filename.size() - 3) + "rsp"; std::string outPathname = outDir + filename.substr(0, filename.size() - 3) + "rsp";