Esempio n. 1
0
void BenchMark(const char *name, RandomNumberGenerator &rng, double timeTotal)
{
	const int BUF_SIZE = 2048U;
	AlignedSecByteBlock buf(BUF_SIZE);
	Test::GlobalRNG().GenerateBlock(buf, BUF_SIZE);
	buf.SetMark(16);

	SymmetricCipher * cipher = dynamic_cast<SymmetricCipher*>(&rng);
	if (cipher != NULLPTR)
	{
		const size_t size = cipher->DefaultKeyLength();
		if (cipher->IsResynchronizable())
			cipher->SetKeyWithIV(buf, size, buf+size);
		else
			cipher->SetKey(buf, size);
	}

	unsigned long long blocks = 1;
	double timeTaken;

	clock_t start = ::clock();
	do
	{
		rng.GenerateBlock(buf, buf.size());
		blocks++;
		timeTaken = double(::clock() - start) / CLOCK_TICKS_PER_SECOND;
	} while (timeTaken < timeTotal);

	OutputResultBytes(name, double(blocks) * BUF_SIZE, timeTaken);
}
Esempio n. 2
0
bool TestModeIV(SymmetricCipher &e, SymmetricCipher &d)
{
	SecByteBlock lastIV, iv(e.IVSize());
	StreamTransformationFilter filter(e, new StreamTransformationFilter(d));
	byte plaintext[20480];

	for (unsigned int i=1; i<sizeof(plaintext); i*=2)
	{
		e.GetNextIV(GlobalRNG(), iv);
		if (iv == lastIV)
			return false;
		else
			lastIV = iv;

		e.Resynchronize(iv);
		d.Resynchronize(iv);

		unsigned int length = STDMAX(GlobalRNG().GenerateWord32(0, i), (word32)e.MinLastBlockSize());
		GlobalRNG().GenerateBlock(plaintext, length);

		if (!TestFilter(filter, plaintext, length, plaintext, length))
			return false;
	}

	return true;
}
Esempio n. 3
0
void TestSymmetricCipher(TestData &v, const NameValuePairs &overrideParameters)
{
	std::string name = GetRequiredDatum(v, "Name");
	std::string test = GetRequiredDatum(v, "Test");

	std::string key = GetDecodedDatum(v, "Key");
	std::string plaintext = GetDecodedDatum(v, "Plaintext");

	TestDataNameValuePairs testDataPairs(v);
	CombinedNameValuePairs pairs(overrideParameters, testDataPairs);

	if (test == "Encrypt" || test == "EncryptXorDigest" || test == "Resync" || test == "EncryptionMCT" || test == "DecryptionMCT")
	{
		static member_ptr<SymmetricCipher> encryptor, decryptor;
		static std::string lastName;

		if (name != lastName)
		{
			encryptor.reset(ObjectFactoryRegistry<SymmetricCipher, ENCRYPTION>::Registry().CreateObject(name.c_str()));
			decryptor.reset(ObjectFactoryRegistry<SymmetricCipher, DECRYPTION>::Registry().CreateObject(name.c_str()));
			lastName = name;
		}

		ConstByteArrayParameter iv;
		if (pairs.GetValue(Name::IV(), iv) && iv.size() != encryptor->IVSize())
			SignalTestFailure();

		if (test == "Resync")
		{
			encryptor->Resynchronize(iv.begin(), (int)iv.size());
			decryptor->Resynchronize(iv.begin(), (int)iv.size());
		}
		else
		{
			encryptor->SetKey((const byte *)key.data(), key.size(), pairs);
			decryptor->SetKey((const byte *)key.data(), key.size(), pairs);
		}

		int seek = pairs.GetIntValueWithDefault("Seek", 0);
		if (seek)
		{
			encryptor->Seek(seek);
			decryptor->Seek(seek);
		}

		std::string encrypted, xorDigest, ciphertext, ciphertextXorDigest;
		if (test == "EncryptionMCT" || test == "DecryptionMCT")
		{
			SymmetricCipher *cipher = encryptor.get();
			SecByteBlock buf((byte *)plaintext.data(), plaintext.size()), keybuf((byte *)key.data(), key.size());

			if (test == "DecryptionMCT")
			{
				cipher = decryptor.get();
				ciphertext = GetDecodedDatum(v, "Ciphertext");
				buf.Assign((byte *)ciphertext.data(), ciphertext.size());
			}

			for (int i=0; i<400; i++)
			{
				encrypted.reserve(10000 * plaintext.size());
				for (int j=0; j<10000; j++)
				{
					cipher->ProcessString(buf.begin(), buf.size());
					encrypted.append((char *)buf.begin(), buf.size());
				}

				encrypted.erase(0, encrypted.size() - keybuf.size());
				xorbuf(keybuf.begin(), (const byte *)encrypted.data(), keybuf.size());
				cipher->SetKey(keybuf, keybuf.size());
			}
			encrypted.assign((char *)buf.begin(), buf.size());
			ciphertext = GetDecodedDatum(v, test == "EncryptionMCT" ? "Ciphertext" : "Plaintext");
			if (encrypted != ciphertext)
			{
				std::cout << "incorrectly encrypted: ";
				StringSource xx(encrypted, false, new HexEncoder(new FileSink(std::cout)));
				xx.Pump(256); xx.Flush(false);
				std::cout << "\n";
				SignalTestFailure();
			}
			return;
		}

		StreamTransformationFilter encFilter(*encryptor, new StringSink(encrypted), StreamTransformationFilter::NO_PADDING);
		RandomizedTransfer(StringStore(plaintext).Ref(), encFilter, true);
		encFilter.MessageEnd();
		/*{
			std::string z;
			encryptor->Seek(seek);
			StringSource ss(plaintext, false, new StreamTransformationFilter(*encryptor, new StringSink(z), StreamTransformationFilter::NO_PADDING));
			while (ss.Pump(64)) {}
			ss.PumpAll();
			for (int i=0; i<z.length(); i++)
				assert(encrypted[i] == z[i]);
		}*/
		if (test != "EncryptXorDigest")
			ciphertext = GetDecodedDatum(v, "Ciphertext");
		else
		{
			ciphertextXorDigest = GetDecodedDatum(v, "CiphertextXorDigest");
			xorDigest.append(encrypted, 0, 64);
			for (size_t i=64; i<encrypted.size(); i++)
				xorDigest[i%64] ^= encrypted[i];
		}
		if (test != "EncryptXorDigest" ? encrypted != ciphertext : xorDigest != ciphertextXorDigest)
		{
			std::cout << "incorrectly encrypted: ";
			StringSource xx(encrypted, false, new HexEncoder(new FileSink(std::cout)));
			xx.Pump(2048); xx.Flush(false);
			std::cout << "\n";
			SignalTestFailure();
		}
		std::string decrypted;
		StreamTransformationFilter decFilter(*decryptor, new StringSink(decrypted), StreamTransformationFilter::NO_PADDING);
		RandomizedTransfer(StringStore(encrypted).Ref(), decFilter, true);
		decFilter.MessageEnd();
		if (decrypted != plaintext)
		{
			std::cout << "incorrectly decrypted: ";
			StringSource xx(decrypted, false, new HexEncoder(new FileSink(std::cout)));
			xx.Pump(256); xx.Flush(false);
			std::cout << "\n";
			SignalTestFailure();
		}
	}
	else
	{
		std::cout << "unexpected test name\n";
		SignalTestError();
	}
}
Esempio n. 4
0
void PEM_CipherForAlgorithm(const EncapsulatedHeader& header, const char* password, size_t length, auto_ptr<StreamTransformation>& stream)
{
    unsigned int ksize, vsize;
    
    string algorithm(header.m_algorithm);
    std::transform(algorithm.begin(), algorithm.end(), algorithm.begin(),  (int(*)(int))std::toupper);
    
    if(algorithm == "AES-256-CBC")
    {
        ksize = 32;
        vsize = 16;
        
        stream = auto_ptr<StreamTransformation>(new CBC_Mode<AES>::Decryption);
    }
    else if(algorithm == "AES-192-CBC")
    {
        ksize = 24;
        vsize = 16;
        
        stream = auto_ptr<StreamTransformation>(new CBC_Mode<AES>::Decryption);
    }
    else if(algorithm == "AES-128-CBC")
    {
        ksize = 16;
        vsize = 16;
        
        stream = auto_ptr<StreamTransformation>(new CBC_Mode<AES>::Decryption);
    }
    else if(algorithm == "CAMELLIA-256-CBC")
    {
        ksize = 32;
        vsize = 16;
        
        stream = auto_ptr<StreamTransformation>(new CBC_Mode<Camellia>::Decryption);
    }
    else if(algorithm == "CAMELLIA-192-CBC")
    {
        ksize = 24;
        vsize = 16;
        
        stream = auto_ptr<StreamTransformation>(new CBC_Mode<Camellia>::Decryption);
    }
    else if(algorithm == "CAMELLIA-128-CBC")
    {
        ksize = 16;
        vsize = 16;
        
        stream = auto_ptr<StreamTransformation>(new CBC_Mode<Camellia>::Decryption);
    }
    else if(algorithm == "DES-EDE3-CBC")
    {
        ksize = 24;
        vsize = 8;
        
        stream = auto_ptr<StreamTransformation>(new CBC_Mode<DES_EDE3>::Decryption);
    }
    else if(algorithm == "IDEA-CBC")
    {
        ksize = 16;
        vsize = 8;
        
        stream = auto_ptr<StreamTransformation>(new CBC_Mode<IDEA>::Decryption);
    }
    else if(algorithm == "DES-CBC")
    {
        ksize = 8;
        vsize = 8;
        
        stream = auto_ptr<StreamTransformation>(new CBC_Mode<DES>::Decryption);
    }
    else
    {
        throw NotImplemented("PEM_CipherForAlgorithm: '" + header.m_algorithm + "' is not implemented");
    }
    
    const unsigned char* _pword = reinterpret_cast<const unsigned char*>(password);
    const size_t _plen = length;
    
    // Decode the IV. It used as the Salt in EVP_BytesToKey,
    //   and its used as the IV in the cipher.
    HexDecoder hex;
    hex.Put((const byte*)header.m_iv.data(), header.m_iv.size());
    hex.MessageEnd();
    
    // If the IV size is wrong, SetKeyWithIV will throw an exception.
    size_t size = hex.MaxRetrievable();
    size = std::min(size, static_cast<size_t>(vsize));
    
    SecByteBlock _key(ksize);
    SecByteBlock _iv(size);
    SecByteBlock _salt(size);
    
    hex.Get(_iv.data(), _iv.size());
    
    // The IV pulls double duty. First, the first PKCS5_SALT_LEN bytes are used
    //   as the Salt in EVP_BytesToKey. Second, its used as the IV in the cipher.
    _salt = _iv;
    assert(_salt.size() >= OPENSSL_PKCS5_SALT_LEN);
    
    // MD5 is engrained OpenSSL goodness. MD5, IV and Password are IN; KEY is OUT.
    //   {NULL,0} parameters are the OUT IV. However, the original IV in the PEM
    //   header is used; and not the derived IV.
    Weak::MD5 md5;
    int ret = OPENSSL_EVP_BytesToKey(md5, _iv.data(), _pword, _plen, 1, _key.data(), _key.size(), NULL, 0);
    if(ret != static_cast<int>(ksize))
        throw Exception(Exception::OTHER_ERROR, "PEM_CipherForAlgorithm: EVP_BytesToKey failed");
    
    SymmetricCipher* cipher = dynamic_cast<SymmetricCipher*>(stream.get());
    assert(cipher != NULL);
    
    cipher->SetKeyWithIV(_key.data(), _key.size(), _iv.data(), _iv.size());
}