You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
394 lines
11 KiB
394 lines
11 KiB
![]()
4 years ago
|
// validate.h - originally written and placed in the public domain by Wei Dai
|
||
|
// CryptoPP::Test namespace added by JW in February 2017
|
||
|
|
||
|
#ifndef CRYPTOPP_VALIDATE_H
|
||
|
#define CRYPTOPP_VALIDATE_H
|
||
|
|
||
|
#include "cryptlib.h"
|
||
|
#include "misc.h"
|
||
|
#include "files.h"
|
||
|
#include "argnames.h"
|
||
|
#include "algparam.h"
|
||
|
#include "hex.h"
|
||
|
|
||
|
#include <iostream>
|
||
|
#include <sstream>
|
||
|
#include <iomanip>
|
||
|
#include <ctime>
|
||
|
#include <cctype>
|
||
|
|
||
|
NAMESPACE_BEGIN(CryptoPP)
|
||
|
NAMESPACE_BEGIN(Test)
|
||
|
|
||
|
// A hint to help locate TestData/ and TestVectors/ after install. Due to
|
||
|
// execve the path can be malicious. If the path is ficticous then we move
|
||
|
// onto the next potential path. Also note we only read from the path; we
|
||
|
// never write through it. Storage for the string is in test.cpp.
|
||
|
extern std::string g_argvPathHint;
|
||
|
|
||
|
bool ValidateAll(bool thorough);
|
||
|
bool TestSettings();
|
||
|
bool TestOS_RNG();
|
||
|
// bool TestSecRandom();
|
||
|
bool TestRandomPool();
|
||
|
#if !defined(NO_OS_DEPENDENCE)
|
||
|
bool TestAutoSeededX917();
|
||
|
#endif
|
||
|
#if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64)
|
||
|
bool TestRDRAND();
|
||
|
bool TestRDSEED();
|
||
|
bool TestPadlockRNG();
|
||
|
#endif
|
||
|
#if (CRYPTOPP_BOOL_PPC32 || CRYPTOPP_BOOL_PPC64)
|
||
|
bool TestDARN();
|
||
|
#endif
|
||
|
bool ValidateBaseCode();
|
||
|
bool ValidateEncoder();
|
||
|
bool ValidateCRC32();
|
||
|
bool ValidateCRC32C();
|
||
|
bool ValidateAdler32();
|
||
|
bool ValidateMD2();
|
||
|
bool ValidateMD4();
|
||
|
bool ValidateMD5();
|
||
|
bool ValidateSHA();
|
||
|
bool ValidateSHA2();
|
||
|
bool ValidateSHA3();
|
||
|
bool ValidateSHAKE(); // output <= r, where r is blocksize
|
||
|
bool ValidateSHAKE_XOF(); // output > r, needs hand crafted tests
|
||
|
bool ValidateKeccak();
|
||
|
bool ValidateTiger();
|
||
|
bool ValidateRIPEMD();
|
||
|
bool ValidatePanama();
|
||
|
bool ValidateWhirlpool();
|
||
|
|
||
|
bool ValidateSM3();
|
||
|
bool ValidateBLAKE2s();
|
||
|
bool ValidateBLAKE2b();
|
||
|
bool ValidatePoly1305();
|
||
|
bool ValidateSipHash();
|
||
|
|
||
|
bool ValidateHMAC();
|
||
|
bool ValidateTTMAC();
|
||
|
|
||
|
bool ValidateCipherModes();
|
||
|
bool ValidatePBKDF();
|
||
|
bool ValidateHKDF();
|
||
|
bool ValidateScrypt();
|
||
|
|
||
|
bool ValidateDES();
|
||
|
bool ValidateIDEA();
|
||
|
bool ValidateSAFER();
|
||
|
bool ValidateRC2();
|
||
|
bool ValidateARC4();
|
||
|
|
||
|
bool ValidateRC5();
|
||
|
bool ValidateBlowfish();
|
||
|
bool ValidateBlowfishCompat();
|
||
|
bool ValidateThreeWay();
|
||
|
bool ValidateGOST();
|
||
|
bool ValidateSHARK();
|
||
|
bool ValidateSEAL();
|
||
|
bool ValidateCAST();
|
||
|
bool ValidateSquare();
|
||
|
bool ValidateSKIPJACK();
|
||
|
bool ValidateRC6();
|
||
|
bool ValidateMARS();
|
||
|
bool ValidateRijndael();
|
||
|
bool ValidateTwofish();
|
||
|
bool ValidateSerpent();
|
||
|
bool ValidateSHACAL2();
|
||
|
bool ValidateARIA();
|
||
|
bool ValidateSIMECK();
|
||
|
bool ValidateCHAM();
|
||
|
bool ValidateHIGHT();
|
||
|
bool ValidateLEA();
|
||
|
bool ValidateSIMON();
|
||
|
bool ValidateSPECK();
|
||
|
bool ValidateCamellia();
|
||
|
|
||
|
bool ValidateHC128();
|
||
|
bool ValidateHC256();
|
||
|
bool ValidateRabbit();
|
||
|
bool ValidateSalsa();
|
||
|
bool ValidateChaCha();
|
||
|
bool ValidateChaChaTLS();
|
||
|
bool ValidateSosemanuk();
|
||
|
|
||
|
bool ValidateVMAC();
|
||
|
bool ValidateCCM();
|
||
|
bool ValidateGCM();
|
||
|
bool ValidateXTS();
|
||
|
bool ValidateCMAC();
|
||
|
|
||
|
bool ValidateBBS();
|
||
|
bool ValidateDH();
|
||
|
bool ValidateMQV();
|
||
|
bool ValidateHMQV();
|
||
|
bool ValidateFHMQV();
|
||
|
bool ValidateRSA();
|
||
|
bool ValidateElGamal();
|
||
|
bool ValidateDLIES();
|
||
|
bool ValidateNR();
|
||
|
bool ValidateDSA(bool thorough);
|
||
|
bool ValidateLUC();
|
||
|
bool ValidateLUC_DL();
|
||
|
bool ValidateLUC_DH();
|
||
|
bool ValidateXTR_DH();
|
||
|
bool ValidateRabin();
|
||
|
bool ValidateRW();
|
||
|
bool ValidateECP();
|
||
|
bool ValidateEC2N();
|
||
|
bool ValidateECDSA();
|
||
|
bool ValidateECDSA_RFC6979();
|
||
|
bool ValidateECGDSA(bool thorough);
|
||
|
bool ValidateESIGN();
|
||
|
|
||
|
bool ValidateHashDRBG();
|
||
|
bool ValidateHmacDRBG();
|
||
|
|
||
|
bool TestX25519();
|
||
|
bool TestEd25519();
|
||
|
bool ValidateX25519();
|
||
|
bool ValidateEd25519();
|
||
|
bool ValidateNaCl();
|
||
|
|
||
|
// If CRYPTOPP_DEBUG or CRYPTOPP_COVERAGE is in effect, then perform additional tests
|
||
|
#if (defined(CRYPTOPP_DEBUG) || defined(CRYPTOPP_COVERAGE)) && !defined(CRYPTOPP_IMPORTS)
|
||
|
# define CRYPTOPP_EXTENDED_VALIDATION 1
|
||
|
#endif
|
||
|
|
||
|
#if defined(CRYPTOPP_EXTENDED_VALIDATION)
|
||
|
// http://github.com/weidai11/cryptopp/issues/92
|
||
|
bool TestSecBlock();
|
||
|
// http://github.com/weidai11/cryptopp/issues/64
|
||
|
bool TestPolynomialMod2();
|
||
|
// http://github.com/weidai11/cryptopp/issues/336
|
||
|
bool TestIntegerBitops();
|
||
|
// http://github.com/weidai11/cryptopp/issues/602
|
||
|
bool TestIntegerOps();
|
||
|
// http://github.com/weidai11/cryptopp/issues/360
|
||
|
bool TestRounding();
|
||
|
// http://github.com/weidai11/cryptopp/issues/242
|
||
|
bool TestHuffmanCodes();
|
||
|
// http://github.com/weidai11/cryptopp/issues/346
|
||
|
bool TestASN1Parse();
|
||
|
// https://github.com/weidai11/cryptopp/pull/334
|
||
|
bool TestStringSink();
|
||
|
// Additional tests due to no coverage
|
||
|
bool TestCompressors();
|
||
|
bool TestEncryptors();
|
||
|
bool TestMersenne();
|
||
|
bool TestSharing();
|
||
|
# if defined(CRYPTOPP_ALTIVEC_AVAILABLE)
|
||
|
bool TestAltivecOps();
|
||
|
# endif
|
||
|
#endif
|
||
|
|
||
|
class FixedRNG : public RandomNumberGenerator
|
||
|
{
|
||
|
public:
|
||
|
FixedRNG(BufferedTransformation &source) : m_source(source) {}
|
||
|
|
||
|
void GenerateBlock(byte *output, size_t size)
|
||
|
{
|
||
|
m_source.Get(output, size);
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
BufferedTransformation &m_source;
|
||
|
};
|
||
|
|
||
|
// Safer functions on Windows for C&A, http://github.com/weidai11/cryptopp/issues/55
|
||
|
inline std::string TimeToString(const time_t& t)
|
||
|
{
|
||
|
#if (CRYPTOPP_MSC_VERSION >= 1400)
|
||
|
tm localTime;
|
||
|
char timeBuf[64];
|
||
|
errno_t err;
|
||
|
|
||
|
err = ::localtime_s(&localTime, &t);
|
||
|
CRYPTOPP_ASSERT(err == 0);
|
||
|
err = ::asctime_s(timeBuf, sizeof(timeBuf), &localTime);
|
||
|
CRYPTOPP_ASSERT(err == 0);
|
||
|
|
||
|
std::string str(err == 0 ? timeBuf : "");
|
||
|
#elif defined(__MINGW32__) || defined(__MINGW64__)
|
||
|
char* timeString = ::asctime(::localtime(&t));
|
||
|
std::string str(timeString ? timeString : "");
|
||
|
#elif (_POSIX_C_SOURCE >= 1 || _XOPEN_SOURCE || _BSD_SOURCE || _SVID_SOURCE || defined(_POSIX_SOURCE))
|
||
|
tm localTime;
|
||
|
char timeBuf[64];
|
||
|
char* timeString = ::asctime_r(::localtime_r(&t, &localTime), timeBuf);
|
||
|
std::string str(timeString ? timeString : "");
|
||
|
#else
|
||
|
char* timeString = ::asctime(::localtime(&t));
|
||
|
std::string str(timeString ? timeString : "");
|
||
|
#endif
|
||
|
|
||
|
// Cleanup whitespace
|
||
|
std::string::size_type pos = 0;
|
||
|
while (!str.empty() && std::isspace(str[str.length()-1]))
|
||
|
{str.erase(str.end()-1);}
|
||
|
while (!str.empty() && std::string::npos != (pos = str.find(" ", pos)))
|
||
|
{str.erase(pos, 1);}
|
||
|
|
||
|
return str;
|
||
|
}
|
||
|
|
||
|
// Coverity finding
|
||
|
template <class T, bool NON_NEGATIVE>
|
||
|
inline T StringToValue(const std::string& str)
|
||
|
{
|
||
|
std::istringstream iss(str);
|
||
|
|
||
|
// Arbitrary, but we need to clear a Coverity finding TAINTED_SCALAR
|
||
|
if (iss.str().length() > 25)
|
||
|
throw InvalidArgument(str + "' is too long");
|
||
|
|
||
|
T value;
|
||
|
iss >> std::noskipws >> value;
|
||
|
|
||
|
// Use fail(), not bad()
|
||
|
if (iss.fail())
|
||
|
throw InvalidArgument(str + "' is not a value");
|
||
|
|
||
|
if (NON_NEGATIVE && value < 0)
|
||
|
throw InvalidArgument(str + "' is negative");
|
||
|
|
||
|
return value;
|
||
|
}
|
||
|
|
||
|
// Coverity finding
|
||
|
template<>
|
||
|
inline int StringToValue<int, true>(const std::string& str)
|
||
|
{
|
||
|
Integer n(str.c_str());
|
||
|
long l = n.ConvertToLong();
|
||
|
|
||
|
int r;
|
||
|
if (!SafeConvert(l, r))
|
||
|
throw InvalidArgument(str + "' is not an integer value");
|
||
|
|
||
|
return r;
|
||
|
}
|
||
|
|
||
|
inline std::string AddSeparator(std::string str)
|
||
|
{
|
||
|
if (str.empty()) return "";
|
||
|
const char last = str[str.length()-1];
|
||
|
if (last != '/' && last != '\\')
|
||
|
return str + "/";
|
||
|
return str;
|
||
|
}
|
||
|
|
||
|
// Use CRYPTOPP_DATA_DIR last. The problem this sidesteps is, finding an
|
||
|
// old version of Crypto++ library in CRYPTOPP_DATA_DIR when the library
|
||
|
// has been staged in DESTDIR. Using CRYPTOPP_DATA_DIR first only works
|
||
|
// as expected when CRYPTOPP_DATA_DIR is empty before an install. We
|
||
|
// encountered this problem rather quickly during testing of Crypto++ 8.1
|
||
|
// when Crypto++ 8.0 was installed locally. It took some time to realize
|
||
|
// where the old test data was coming from.
|
||
|
static std::string GetDataDir()
|
||
|
{
|
||
|
std::ifstream file;
|
||
|
std::string name, filename = "TestData/usage.dat";
|
||
|
|
||
|
#ifndef CRYPTOPP_DISABLE_DATA_DIR_SEARCH
|
||
|
// Look in $ORIGIN/../share/. This is likely a Linux install directory.
|
||
|
name = AddSeparator(g_argvPathHint) + std::string("../share/cryptopp/") + filename;
|
||
|
file.open(name.c_str());
|
||
|
if (file.is_open())
|
||
|
return AddSeparator(g_argvPathHint) + std::string("../share/cryptopp/");
|
||
|
#endif
|
||
|
#ifndef CRYPTOPP_DISABLE_DATA_DIR_SEARCH
|
||
|
// Look in current working directory
|
||
|
name = AddSeparator(g_argvPathHint) + filename;
|
||
|
file.open(name.c_str());
|
||
|
if (file.is_open())
|
||
|
return AddSeparator(g_argvPathHint);
|
||
|
#endif
|
||
|
#ifdef CRYPTOPP_DATA_DIR
|
||
|
// Honor CRYPTOPP_DATA_DIR. This is likely an install directory if it is not "./".
|
||
|
name = AddSeparator(CRYPTOPP_DATA_DIR) + filename;
|
||
|
file.open(name.c_str());
|
||
|
if (file.is_open())
|
||
|
return AddSeparator(CRYPTOPP_DATA_DIR);
|
||
|
#endif
|
||
|
return "./";
|
||
|
}
|
||
|
|
||
|
inline std::string DataDir(const std::string& filename)
|
||
|
{
|
||
|
std::string name;
|
||
|
std::ifstream file;
|
||
|
|
||
|
#if CRYPTOPP_CXX11_STATIC_INIT
|
||
|
static std::string path = AddSeparator(GetDataDir());
|
||
|
name = path + filename;
|
||
|
file.open(name.c_str());
|
||
|
if (file.is_open())
|
||
|
return name;
|
||
|
#else
|
||
|
// Avoid static initialization problems
|
||
|
name = AddSeparator(GetDataDir()) + filename;
|
||
|
file.open(name.c_str());
|
||
|
if (file.is_open())
|
||
|
return name;
|
||
|
#endif
|
||
|
|
||
|
// This will cause the expected exception in the caller
|
||
|
return filename;
|
||
|
}
|
||
|
|
||
|
// Definition in test.cpp
|
||
|
RandomNumberGenerator& GlobalRNG();
|
||
|
|
||
|
// Definition in datatest.cpp
|
||
|
bool RunTestDataFile(const char *filename, const NameValuePairs &overrideParameters=g_nullNameValuePairs, bool thorough=true);
|
||
|
|
||
|
// Definitions in validat6.cpp
|
||
|
bool CryptoSystemValidate(PK_Decryptor &priv, PK_Encryptor &pub, bool thorough = false);
|
||
|
bool SimpleKeyAgreementValidate(SimpleKeyAgreementDomain &d);
|
||
|
bool AuthenticatedKeyAgreementWithRolesValidate(AuthenticatedKeyAgreementDomain &initiator, AuthenticatedKeyAgreementDomain &recipient);
|
||
|
bool AuthenticatedKeyAgreementValidate(AuthenticatedKeyAgreementDomain &d);
|
||
|
bool SignatureValidate(PK_Signer &priv, PK_Verifier &pub, bool thorough = false);
|
||
|
|
||
|
// Miscellaneous PK definitions in validat6.cpp
|
||
|
// Key Agreement definitions in validat7.cpp
|
||
|
// Encryption and Decryption definitions in validat8.cpp
|
||
|
// Sign and Verify definitions in validat9.cpp
|
||
|
|
||
|
bool ValidateECP();
|
||
|
bool ValidateEC2N();
|
||
|
|
||
|
bool ValidateRSA_Encrypt();
|
||
|
bool ValidateRSA_Sign();
|
||
|
|
||
|
bool ValidateLUC_Encrypt();
|
||
|
bool ValidateLUC_Sign();
|
||
|
|
||
|
bool ValidateLUC_DL_Encrypt();
|
||
|
bool ValidateLUC_DL_Sign();
|
||
|
|
||
|
bool ValidateRabin_Encrypt();
|
||
|
bool ValidateRabin_Sign();
|
||
|
|
||
|
bool ValidateECP();
|
||
|
bool ValidateECP_Agreement();
|
||
|
bool ValidateECP_Encrypt();
|
||
|
bool ValidateECP_Sign();
|
||
|
|
||
|
bool ValidateECP_Legacy_Encrypt();
|
||
|
bool ValidateEC2N_Legacy_Encrypt();
|
||
|
bool ValidateECP_NULLDigest_Encrypt();
|
||
|
|
||
|
bool ValidateEC2N();
|
||
|
bool ValidateEC2N_Agreement();
|
||
|
bool ValidateEC2N_Encrypt();
|
||
|
bool ValidateEC2N_Sign();
|
||
|
|
||
|
NAMESPACE_END // Test
|
||
|
NAMESPACE_END // CryptoPP
|
||
|
|
||
|
#endif
|