Beispiel #1
1
bool OSSLRSA::verifyFinal(const ByteString& signature)
{
	// Save necessary state before calling super class verifyFinal
	OSSLRSAPublicKey* pk = (OSSLRSAPublicKey*) currentPublicKey;
	AsymMech::Type mechanism = currentMechanism;

	if (!AsymmetricAlgorithm::verifyFinal(signature))
	{
		return false;
	}

	ByteString firstHash, secondHash;

	bool bFirstResult = pCurrentHash->hashFinal(firstHash);
	bool bSecondResult = (pSecondHash != NULL) ? pSecondHash->hashFinal(secondHash) : true;

	delete pCurrentHash;
	pCurrentHash = NULL;

	if (pSecondHash != NULL)
	{
		delete pSecondHash;

		pSecondHash = NULL;
	}

	if (!bFirstResult || !bSecondResult)
	{
		return false;
	}

	ByteString digest = firstHash + secondHash;

	// Determine the signature NID type
	int type = 0;
	bool isPSS = false;
	const EVP_MD* hash = NULL;

	switch (mechanism)
	{
		case AsymMech::RSA_MD5_PKCS:
			type = NID_md5;
			break;
		case AsymMech::RSA_SHA1_PKCS:
			type = NID_sha1;
			break;
		case AsymMech::RSA_SHA224_PKCS:
			type = NID_sha224;
			break;
		case AsymMech::RSA_SHA256_PKCS:
			type = NID_sha256;
			break;
		case AsymMech::RSA_SHA384_PKCS:
			type = NID_sha384;
			break;
		case AsymMech::RSA_SHA512_PKCS:
			type = NID_sha512;
			break;
		case AsymMech::RSA_SHA1_PKCS_PSS:
			isPSS = true;
			hash = EVP_sha1();
			break;
		case AsymMech::RSA_SHA224_PKCS_PSS:
			isPSS = true;
			hash = EVP_sha224();
			break;
		case AsymMech::RSA_SHA256_PKCS_PSS:
			isPSS = true;
			hash = EVP_sha256();
			break;
		case AsymMech::RSA_SHA384_PKCS_PSS:
			isPSS = true;
			hash = EVP_sha384();
			break;
		case AsymMech::RSA_SHA512_PKCS_PSS:
			isPSS = true;
			hash = EVP_sha512();
			break;
		case AsymMech::RSA_SSL:
			type = NID_md5_sha1;
			break;
		default:
			break;
	}

	// Perform the verify operation
	bool rv;

	if (isPSS)
	{
		ByteString plain;
		plain.resize(pk->getN().size());
		int result = RSA_public_decrypt(signature.size(),
						(unsigned char*) signature.const_byte_str(),
						&plain[0],
						pk->getOSSLKey(),
						RSA_NO_PADDING);
		if (result < 0)
		{
			rv = false;
			ERROR_MSG("RSA public decrypt failed (0x%08X)", ERR_get_error());
		}
		else
		{
			plain.resize(result);
			result = RSA_verify_PKCS1_PSS(pk->getOSSLKey(), &digest[0],
						      hash, &plain[0], sLen);
			if (result == 1)
			{
				rv = true;
			}
			else
			{
				rv = false;
				ERROR_MSG("RSA PSS verify failed (0x%08X)", ERR_get_error());
			}
		}
	}
	else
	{
		rv = (RSA_verify(type, &digest[0], digest.size(), (unsigned char*) signature.const_byte_str(), signature.size(), pk->getOSSLKey()) == 1);

		if (!rv) ERROR_MSG("RSA verify failed (0x%08X)", ERR_get_error());
	}

	return rv;
}
Beispiel #2
0
// Signing functions
bool OSSLRSA::sign(PrivateKey* privateKey, const ByteString& dataToSign,
		   ByteString& signature, const AsymMech::Type mechanism,
		   const void* param /* = NULL */, const size_t paramLen /* = 0 */)
{
	if (mechanism == AsymMech::RSA_PKCS)
	{
		// Separate implementation for RSA PKCS #1 signing without hash computation

		// Check if the private key is the right type
		if (!privateKey->isOfType(OSSLRSAPrivateKey::type))
		{
			ERROR_MSG("Invalid key type supplied");

			return false;
		}

		// In case of PKCS #1 signing the length of the input data may not exceed 40% of the
		// modulus size
		OSSLRSAPrivateKey* osslKey = (OSSLRSAPrivateKey*) privateKey;

		size_t allowedLen = osslKey->getN().size() - 11;

		if (dataToSign.size() > allowedLen)
		{
			ERROR_MSG("Data to sign exceeds maximum for PKCS #1 signature");

			return false;
		}

		// Perform the signature operation
		signature.resize(osslKey->getN().size());

		RSA* rsa = osslKey->getOSSLKey();

		if (!RSA_blinding_on(rsa, NULL))
		{
			ERROR_MSG("Failed to turn on blinding for OpenSSL RSA key");

			return false;
		}

		int sigLen = RSA_private_encrypt(dataToSign.size(), (unsigned char*) dataToSign.const_byte_str(), &signature[0], rsa, RSA_PKCS1_PADDING);

		RSA_blinding_off(rsa);

		if (sigLen == -1)
		{
			ERROR_MSG("An error occurred while performing a PKCS #1 signature");

			return false;
		}

		signature.resize(sigLen);

		return true;
	}
	else if (mechanism == AsymMech::RSA)
	{
		// Separate implementation for raw RSA signing

		// Check if the private key is the right type
		if (!privateKey->isOfType(OSSLRSAPrivateKey::type))
		{
			ERROR_MSG("Invalid key type supplied");

			return false;
		}

		// In case of raw RSA, the length of the input data must match the length of the modulus
		OSSLRSAPrivateKey* osslKey = (OSSLRSAPrivateKey*) privateKey;

		if (dataToSign.size() != osslKey->getN().size())
		{
			ERROR_MSG("Size of data to sign does not match the modulus size");

			return false;
		}

		// Perform the signature operation
		signature.resize(osslKey->getN().size());

		RSA* rsa = osslKey->getOSSLKey();

		if (!RSA_blinding_on(rsa, NULL))
		{
			ERROR_MSG("Failed to turn on blinding for OpenSSL RSA key");

			return false;
		}

		int sigLen = RSA_private_encrypt(dataToSign.size(), (unsigned char*) dataToSign.const_byte_str(), &signature[0], rsa, RSA_NO_PADDING);

		RSA_blinding_off(rsa);

		if (sigLen == -1)
		{
			ERROR_MSG("An error occurred while performing a raw RSA signature");

			return false;
		}

		signature.resize(sigLen);

		return true;
	}
	else
	{
		// Call default implementation
		return AsymmetricAlgorithm::sign(privateKey, dataToSign, signature, mechanism, param, paramLen);
	}
}
Beispiel #3
0
// Encryption functions
bool OSSLRSA::encrypt(PublicKey* publicKey, const ByteString& data,
		      ByteString& encryptedData, const AsymMech::Type padding)
{
	// Check if the public key is the right type
	if (!publicKey->isOfType(OSSLRSAPublicKey::type))
	{
		ERROR_MSG("Invalid key type supplied");

		return false;
	}

	// Retrieve the OpenSSL key object
	RSA* rsa = ((OSSLRSAPublicKey*) publicKey)->getOSSLKey();

	// Check the data and padding algorithm
	int osslPadding = 0;

	if (padding == AsymMech::RSA_PKCS)
	{
		// The size of the input data cannot be more than the modulus
		// length of the key - 11
		if (data.size() > (size_t) (RSA_size(rsa) - 11))
		{
			ERROR_MSG("Too much data supplied for RSA PKCS #1 encryption");

			return false;
		}

		osslPadding = RSA_PKCS1_PADDING;
	}
	else if (padding == AsymMech::RSA_PKCS_OAEP)
	{
		// The size of the input data cannot be more than the modulus
		// length of the key - 41
		if (data.size() > (size_t) (RSA_size(rsa) - 41))
		{
			ERROR_MSG("Too much data supplied for RSA OAEP encryption");

			return false;
		}

		osslPadding = RSA_PKCS1_OAEP_PADDING;
	}
	else if (padding == AsymMech::RSA)
	{
		// The size of the input data should be exactly equal to the modulus length
		if (data.size() != (size_t) RSA_size(rsa))
		{
			ERROR_MSG("Incorrect amount of input data supplied for raw RSA encryption");

			return false;
		}

		osslPadding = RSA_NO_PADDING;
	}
	else
	{
		ERROR_MSG("Invalid padding mechanism supplied (%i)", padding);

		return false;
	}

	// Perform the RSA operation
	encryptedData.resize(RSA_size(rsa));

	if (RSA_public_encrypt(data.size(), (unsigned char*) data.const_byte_str(), &encryptedData[0], rsa, osslPadding) == -1)
	{
		ERROR_MSG("RSA public key encryption failed (0x%08X)", ERR_get_error());

		return false;
	}

	return true;
}
Beispiel #4
0
// Verification functions
bool OSSLRSA::verify(PublicKey* publicKey, const ByteString& originalData,
		     const ByteString& signature, const AsymMech::Type mechanism,
		     const void* param /* = NULL */, const size_t paramLen /* = 0 */)
{
	if (mechanism == AsymMech::RSA_PKCS)
	{
		// Specific implementation for PKCS #1 only verification; originalData is assumed to contain
		// a digestInfo structure and verification is performed by comparing originalData to the data
		// recovered from the signature

		// Check if the public key is the right type
		if (!publicKey->isOfType(OSSLRSAPublicKey::type))
		{
			ERROR_MSG("Invalid key type supplied");

			return false;
		}

		// Perform the RSA public key operation
		OSSLRSAPublicKey* osslKey = (OSSLRSAPublicKey*) publicKey;

		ByteString recoveredData;

		recoveredData.resize(osslKey->getN().size());

		RSA* rsa = osslKey->getOSSLKey();

		int retLen = RSA_public_decrypt(signature.size(), (unsigned char*) signature.const_byte_str(), &recoveredData[0], rsa, RSA_PKCS1_PADDING);

		if (retLen == -1)
		{
			ERROR_MSG("Public key operation failed");

			return false;
		}

		recoveredData.resize(retLen);

		return (originalData == recoveredData);
	}
	else if (mechanism == AsymMech::RSA)
	{
		// Specific implementation for raw RSA verifiction; originalData is assumed to contain the
		// full input data used to compute the signature and verification is performed by comparing
		// originalData to the data recovered from the signature

		// Check if the public key is the right type
		if (!publicKey->isOfType(OSSLRSAPublicKey::type))
		{
			ERROR_MSG("Invalid key type supplied");

			return false;
		}

		// Perform the RSA public key operation
		OSSLRSAPublicKey* osslKey = (OSSLRSAPublicKey*) publicKey;

		ByteString recoveredData;

		recoveredData.resize(osslKey->getN().size());

		RSA* rsa = osslKey->getOSSLKey();

		int retLen = RSA_public_decrypt(signature.size(), (unsigned char*) signature.const_byte_str(), &recoveredData[0], rsa, RSA_NO_PADDING);

		if (retLen == -1)
		{
			ERROR_MSG("Public key operation failed");

			return false;
		}

		recoveredData.resize(retLen);

		return (originalData == recoveredData);
	}
	else
	{
		// Call the generic function
		return AsymmetricAlgorithm::verify(publicKey, originalData, signature, mechanism, param, paramLen);
	}
}
Beispiel #5
0
// Signing functions
bool BotanDSA::sign(PrivateKey* privateKey, const ByteString& dataToSign,
		    ByteString& signature, const std::string mechanism)
{
	std::string lowerMechanism;
	lowerMechanism.resize(mechanism.size());
	std::transform(mechanism.begin(), mechanism.end(), lowerMechanism.begin(), tolower);
	std::string emsa;

	if (!lowerMechanism.compare("dsa"))
	{
		emsa = "Raw";
	}
	else
        {
		// Call default implementation
		return AsymmetricAlgorithm::sign(privateKey, dataToSign, signature, mechanism);
        }

	// Check if the private key is the right type
	if (!privateKey->isOfType(BotanDSAPrivateKey::type))
	{
		ERROR_MSG("Invalid key type supplied");

		return false;
	}

        BotanDSAPrivateKey* pk = (BotanDSAPrivateKey*) privateKey;
        Botan::DSA_PrivateKey* botanKey = pk->getBotanKey();

        if (!botanKey)
        {
		ERROR_MSG("Could not get the Botan private key");

		return false;
	}

	try
	{       
		signer = new Botan::PK_Signer(*botanKey, emsa);
		// Should we add DISABLE_FAULT_PROTECTION? Makes this operation faster.
	}
	catch (...)
	{
		ERROR_MSG("Could not create the signer token");

		return false;
	}

	// Perform the signature operation
	Botan::SecureVector<Botan::byte> signResult;
	try
	{
		BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
		signResult = signer->sign_message(dataToSign.const_byte_str(), dataToSign.size(), *rng->getRNG());
	}
	catch (...)
	{
		ERROR_MSG("Could not sign the data");

		delete signer;
		signer = NULL;

		return false;
	}

	// Return the result
	signature.resize(signResult.size());
	memcpy(&signature[0], signResult.begin(), signResult.size());

	delete signer;
	signer = NULL;

	return true;
}
// Verification functions
bool OSSLECDSA::verify(PublicKey* publicKey, const ByteString& originalData,
		       const ByteString& signature, const AsymMech::Type mechanism,
		       const void* /* param = NULL */, const size_t /* paramLen = 0 */)
{
	if (mechanism != AsymMech::ECDSA)
	{
		ERROR_MSG("Invalid mechanism supplied (%i)", mechanism);
		return false;
	}

	// Check if the private key is the right type
	if (!publicKey->isOfType(OSSLECPublicKey::type))
	{
		ERROR_MSG("Invalid key type supplied");

		return false;
	}

	OSSLECPublicKey* pk = (OSSLECPublicKey*) publicKey;
	EC_KEY* eckey = pk->getOSSLKey();

	if (eckey == NULL)
	{
		ERROR_MSG("Could not get the OpenSSL public key");

		return false;
	}

	// Use the OpenSSL implementation and not any engine
	ECDSA_set_method(eckey, ECDSA_OpenSSL());

	// Perform the verify operation
	size_t len = pk->getOrderLength();
	if (len == 0)
	{
		ERROR_MSG("Could not get the order length");
		return false;
	}
	if (signature.size() != 2 * len)
	{
		ERROR_MSG("Invalid buffer length");
		return false;
	}
	ECDSA_SIG* sig = ECDSA_SIG_new();
	if (sig == NULL)
	{
		ERROR_MSG("Could not create an ECDSA_SIG object");
		return false;
	}
	if (sig->r != NULL)
		BN_clear_free(sig->r);
	const unsigned char *s = signature.const_byte_str();
	sig->r = BN_bin2bn(s, len, NULL);
	if (sig->s != NULL)
		BN_clear_free(sig->s);
	sig->s = BN_bin2bn(s + len, len, NULL);
	if (sig->r == NULL || sig->s == NULL)
	{
		ERROR_MSG("Could not add data to the ECDSA_SIG object");
		ECDSA_SIG_free(sig);
		return false;
	}
	int ret = ECDSA_do_verify(originalData.const_byte_str(), originalData.size(), sig, eckey);
	if (ret != 1)
	{
		if (ret < 0)
			ERROR_MSG("ECDSA verify failed (0x%08X)", ERR_get_error());

		ECDSA_SIG_free(sig);
		return false;
	}

	ECDSA_SIG_free(sig);
	return true;
}
// Encryption functions
bool BotanSymmetricAlgorithm::encryptInit(const SymmetricKey* key, const SymMode::Type mode /* = SymMode:CBC */, const ByteString& IV /* = ByteString()*/, bool padding /* = true */)
{
	// Call the superclass initialiser
	if (!SymmetricAlgorithm::encryptInit(key, mode, IV, padding))
	{
		return false;
	}

	// Check the IV
	if ((IV.size() > 0) && (IV.size() != getBlockSize()))
	{
		ERROR_MSG("Invalid IV size (%d bytes, expected %d bytes)", IV.size(), getBlockSize());

		ByteString dummy;
		SymmetricAlgorithm::encryptFinal(dummy);

		return false;
	}

	ByteString iv;

	if (IV.size() > 0)
	{
		iv = IV;
	}
	else
	{
		iv.wipe(getBlockSize());
	}

	// Determine the cipher
	std::string cipherName = getCipher();

	if (cipherName == "")
	{
		ERROR_MSG("Invalid encryption cipher");

		ByteString dummy;
		SymmetricAlgorithm::encryptFinal(dummy);

		return false;
	}

	// Allocate the context
	try
	{
		Botan::SymmetricKey botanKey = Botan::SymmetricKey(key->getKeyBits().const_byte_str(), key->getKeyBits().size());
		if (mode == SymMode::ECB)
		{
			cryption = new Botan::Pipe(Botan::get_cipher(cipherName, botanKey, Botan::ENCRYPTION));
		}
		else
		{
			Botan::InitializationVector botanIV = Botan::InitializationVector(IV.const_byte_str(), IV.size());
			cryption = new Botan::Pipe(Botan::get_cipher(cipherName, botanKey, botanIV, Botan::ENCRYPTION));
		}
		cryption->start_msg();
	}
	catch (...)
	{
		ERROR_MSG("Failed to create the encryption token");

		ByteString dummy;
		SymmetricAlgorithm::encryptFinal(dummy);

		delete cryption;
		cryption = NULL;

		return false;
	}

	return true;
}
Beispiel #8
0
// Verification functions
bool BotanDSA::verify(PublicKey* publicKey, const ByteString& originalData,
		      const ByteString& signature, const std::string mechanism)
{
	std::string lowerMechanism;
	lowerMechanism.resize(mechanism.size());
	std::transform(mechanism.begin(), mechanism.end(), lowerMechanism.begin(), tolower);
	std::string emsa;

	if (!lowerMechanism.compare("dsa"))
	{
		emsa = "Raw";
	}
        else
        {
		// Call the generic function
		return AsymmetricAlgorithm::verify(publicKey, originalData, signature, mechanism);
	}

	// Check if the public key is the right type
	if (!publicKey->isOfType(BotanDSAPublicKey::type))
	{
		ERROR_MSG("Invalid key type supplied");

		return false;
	}

	BotanDSAPublicKey* pk = (BotanDSAPublicKey*) publicKey;
	Botan::DSA_PublicKey* botanKey = pk->getBotanKey();

	if (!botanKey)
	{
		ERROR_MSG("Could not get the Botan public key");

		return false;
	}

	try
	{
		verifier = new Botan::PK_Verifier(*botanKey, emsa);
	}
	catch (...)
	{
		ERROR_MSG("Could not create the verifier token");

		return false;
	}

	// Perform the verify operation
	bool verResult;
	try
	{
		verResult = verifier->verify_message(originalData.const_byte_str(),
							originalData.size(),
							signature.const_byte_str(),
							signature.size());
	}
	catch (...)
	{
		ERROR_MSG("Could not check the signature");

		delete verifier;                     
		verifier = NULL;

		return false;
	}

	delete verifier;
	verifier = NULL;

	return verResult;
}
// Wrap/Unwrap keys
bool BotanAES::wrapKey(const SymmetricKey* key, const SymWrap::Type mode, const ByteString& in, ByteString& out)
{
	// Check key bit length; AES only supports 128, 192 or 256 bit keys
	if ((key->getBitLen() != 128) &&
	    (key->getBitLen() != 192) &&
	    (key->getBitLen() != 256))
	{
		ERROR_MSG("Invalid AES key length (%d bits)", key->getBitLen());

		return false;
	}

	// Determine the wrapping mode
	if (mode == SymWrap::AES_KEYWRAP)
	{
		// RFC 3394 AES key wrap
		if (in.size() < 16)
		{
			ERROR_MSG("key data to wrap too small");

			return false;
		}
		if ((in.size() % 8) != 0)
		{
			ERROR_MSG("key data to wrap not aligned");

			return false;
		}

#if BOTAN_VERSION_MINOR == 11
		Botan::secure_vector<Botan::byte> data(in.size());
		memcpy(data.data(), in.const_byte_str(), in.size());
		Botan::secure_vector<Botan::byte> wrapped;
#else
		Botan::MemoryVector<Botan::byte> data(in.size());
		memcpy(data.begin(), in.const_byte_str(), in.size());
		Botan::SecureVector<Botan::byte> wrapped;
#endif
		Botan::SymmetricKey botanKey = Botan::SymmetricKey(key->getKeyBits().const_byte_str(), key->getKeyBits().size());
		Botan::Algorithm_Factory& af = Botan::global_state().algorithm_factory();
		try
		{
			wrapped = Botan::rfc3394_keywrap(data, botanKey, af);
		}
		catch (...)
		{
			ERROR_MSG("AES key wrap failed");

			return false;
		}
		out.resize(wrapped.size());
#if BOTAN_VERSION_MINOR == 11
		memcpy(&out[0], wrapped.data(), out.size());
#else
		memcpy(&out[0], wrapped.begin(), out.size());
#endif

		return  true;
	}
#ifdef HAVE_AES_KEY_WRAP_PAD
	else if (mode == SymWrap::AES_KEYWRAP_PAD)
	{
		// RFC 5649 AES key wrap with pad
#if BOTAN_VERSION_MINOR == 11
		Botan::secure_vector<Botan::byte> data(in.size());
		memcpy(data.data(), in.const_byte_str(), in.size());
		Botan::secure_vector<Botan::byte> wrapped;
#else
		Botan::MemoryVector<Botan::byte> data(in.size());
		memcpy(data.begin(), in.const_byte_str(), in.size());
		Botan::SecureVector<Botan::byte> wrapped;
#endif
		Botan::SymmetricKey botanKey = Botan::SymmetricKey(key->getKeyBits().const_byte_str(), key->getKeyBits().size());
		Botan::Algorithm_Factory& af = Botan::global_state().algorithm_factory();
		try
		{
			wrapped = Botan::rfc5649_keywrap(data, botanKey, af);
		}
		catch (...)
		{
			ERROR_MSG("AES key wrap failed");

			return false;
		}
		out.resize(wrapped.size());
#if BOTAN_VERSION_MINOR == 11
		memcpy(&out[0], wrapped.data(), out.size());
#else
		memcpy(&out[0], wrapped.begin(), out.size());
#endif

		return  true;
	}
#endif
	else
	{
		ERROR_MSG("unknown AES key wrap mode %i", mode);

		return false;
	}
}
Beispiel #10
0
// Decryption functions
bool BotanRSA::decrypt(PrivateKey* privateKey, const ByteString& encryptedData, ByteString& data, const std::string padding)
{
	// Check if the private key is the right type
	if (!privateKey->isOfType(BotanRSAPrivateKey::type))
	{
		ERROR_MSG("Invalid key type supplied");

		return false;
	}

	std::string lowerPadding;
	lowerPadding.resize(padding.size());
	std::transform(padding.begin(), padding.end(), lowerPadding.begin(), tolower);
	std::string eme;

	if (!lowerPadding.compare("rsa-pkcs"))
	{
		eme = "PKCS1v15";
	}
	else if (!lowerPadding.compare("rsa-pkcs-oaep"))
	{
		eme = "EME1(SHA-160)";
	}
	else if (!lowerPadding.compare("rsa-raw"))
	{
		eme = "Raw";
	}
	else
	{
		ERROR_MSG("Invalid padding mechanism supplied (%s)", padding.c_str());

		return false;
	}

	BotanRSAPrivateKey* pk = (BotanRSAPrivateKey*) privateKey;
	Botan::RSA_PrivateKey* botanKey = pk->getBotanKey();

	if (!botanKey)
	{
		ERROR_MSG("Could not get the Botan private key");

		return false;
	}

	Botan::PK_Decryptor_EME* decryptor = NULL;
	try
	{
		decryptor = new Botan::PK_Decryptor_EME(*botanKey, eme);
	}
	catch (...)
	{
		ERROR_MSG("Could not create the decryptor token");

		return false;
	}

	// Perform the decryption operation
	Botan::SecureVector<Botan::byte> decResult;
	try
	{
		decResult = decryptor->decrypt(encryptedData.const_byte_str(), encryptedData.size());
	}
	catch (...)
	{
		ERROR_MSG("Could not decrypt the data");

		delete decryptor;

		return false;
	}

	// Return the result
	if (!eme.compare("Raw"))
	{
		// We compensate that Botan removes leading zeros
		int modSize = pk->getN().size();
		int decSize = decResult.size();
		data.resize(modSize);
		memcpy(&data[0] + modSize - decSize, decResult.begin(), decSize);
	}
	else
	{
		data.resize(decResult.size());
		memcpy(&data[0], decResult.begin(), decResult.size());
	}

	delete decryptor;

	return true;
}
Beispiel #11
0
// Encryption functions
bool BotanRSA::encrypt(PublicKey* publicKey, const ByteString& data, ByteString& encryptedData, const std::string padding)
{
	// Check if the public key is the right type
	if (!publicKey->isOfType(BotanRSAPublicKey::type))
	{
		ERROR_MSG("Invalid key type supplied");

		return false;
	}

	std::string lowerPadding;
	lowerPadding.resize(padding.size());
	std::transform(padding.begin(), padding.end(), lowerPadding.begin(), tolower);
	std::string eme;

	if (!lowerPadding.compare("rsa-pkcs"))
	{
		eme = "PKCS1v15";
	}
	else if (!lowerPadding.compare("rsa-pkcs-oaep"))
	{
		eme = "EME1(SHA-160)";
	}
	else if (!lowerPadding.compare("rsa-raw"))
	{
		eme = "Raw";
	}
	else
	{
		ERROR_MSG("Invalid padding mechanism supplied (%s)", padding.c_str());

		return false;
	}

	BotanRSAPublicKey* pk = (BotanRSAPublicKey*) publicKey;
	Botan::RSA_PublicKey* botanKey = pk->getBotanKey();

	if (!botanKey)
	{
		ERROR_MSG("Could not get the Botan public key");

		return false;
	}

	Botan::PK_Encryptor_EME* encryptor = NULL;
	try
	{
		encryptor = new Botan::PK_Encryptor_EME(*botanKey, eme);
	}
	catch (...)
	{
		ERROR_MSG("Could not create the encryptor token");

		return false;
	}

	// Perform the encryption operation
	Botan::SecureVector<Botan::byte> encResult;
	try
	{
		BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
		encResult = encryptor->encrypt(data.const_byte_str(), data.size(), *rng->getRNG());
	}
	catch (...)
	{
		ERROR_MSG("Could not encrypt the data");

		delete encryptor;

		return false;
	}

	// Return the result
	encryptedData.resize(encResult.size());
	memcpy(&encryptedData[0], encResult.begin(), encResult.size());

	delete encryptor;

	return true;
}
// Signing functions
bool BotanDSA::sign(PrivateKey* privateKey, const ByteString& dataToSign,
		    ByteString& signature, const AsymMech::Type mechanism,
		    const void* param /* = NULL */, const size_t paramLen /* = 0 */)
{
	std::string emsa;

	if (mechanism == AsymMech::DSA)
	{
		emsa = "Raw";
	}
	else
        {
		// Call default implementation
		return AsymmetricAlgorithm::sign(privateKey, dataToSign, signature, mechanism, param, paramLen);
        }

	// Check if the private key is the right type
	if (!privateKey->isOfType(BotanDSAPrivateKey::type))
	{
		ERROR_MSG("Invalid key type supplied");

		return false;
	}

        BotanDSAPrivateKey* pk = (BotanDSAPrivateKey*) privateKey;
        Botan::DSA_PrivateKey* botanKey = pk->getBotanKey();

        if (!botanKey)
        {
		ERROR_MSG("Could not get the Botan private key");

		return false;
	}

	try
	{
		signer = new Botan::PK_Signer(*botanKey, emsa);
		// Should we add DISABLE_FAULT_PROTECTION? Makes this operation faster.
	}
	catch (...)
	{
		ERROR_MSG("Could not create the signer token");

		return false;
	}

	// Perform the signature operation
#if BOTAN_VERSION_MINOR == 11
	std::vector<Botan::byte> signResult;
#else
	Botan::SecureVector<Botan::byte> signResult;
#endif
	try
	{
		BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
		signResult = signer->sign_message(dataToSign.const_byte_str(), dataToSign.size(), *rng->getRNG());
	}
	catch (...)
	{
		ERROR_MSG("Could not sign the data");

		delete signer;
		signer = NULL;

		return false;
	}

	// Return the result
	signature.resize(signResult.size());
#if BOTAN_VERSION_MINOR == 11
	memcpy(&signature[0], signResult.data(), signResult.size());
#else
	memcpy(&signature[0], signResult.begin(), signResult.size());
#endif

	delete signer;
	signer = NULL;

	return true;
}
// Verification functions
bool BotanDSA::verify(PublicKey* publicKey, const ByteString& originalData,
		      const ByteString& signature, const AsymMech::Type mechanism,
		      const void* param /* = NULL */, const size_t paramLen /* = 0 */)
{
	std::string emsa;

	if (mechanism == AsymMech::DSA)
	{
		emsa = "Raw";
	}
        else
        {
		// Call the generic function
		return AsymmetricAlgorithm::verify(publicKey, originalData, signature, mechanism, param, paramLen);
	}

	// Check if the public key is the right type
	if (!publicKey->isOfType(BotanDSAPublicKey::type))
	{
		ERROR_MSG("Invalid key type supplied");

		return false;
	}

	BotanDSAPublicKey* pk = (BotanDSAPublicKey*) publicKey;
	Botan::DSA_PublicKey* botanKey = pk->getBotanKey();

	if (!botanKey)
	{
		ERROR_MSG("Could not get the Botan public key");

		return false;
	}

	try
	{
		verifier = new Botan::PK_Verifier(*botanKey, emsa);
	}
	catch (...)
	{
		ERROR_MSG("Could not create the verifier token");

		return false;
	}

	// Perform the verify operation
	bool verResult;
	try
	{
		verResult = verifier->verify_message(originalData.const_byte_str(),
							originalData.size(),
							signature.const_byte_str(),
							signature.size());
	}
	catch (...)
	{
		ERROR_MSG("Could not check the signature");

		delete verifier;
		verifier = NULL;

		return false;
	}

	delete verifier;
	verifier = NULL;

	return verResult;
}