bool BotanRSA::reconstructPrivateKey(PrivateKey** ppPrivateKey, ByteString& serialisedData) { // Check input if ((ppPrivateKey == NULL) || (serialisedData.size() == 0)) { return false; } BotanRSAPrivateKey* priv = new BotanRSAPrivateKey(); if (!priv->deserialise(serialisedData)) { delete priv; return false; } *ppPrivateKey = priv; return true; }
// Decryption functions bool BotanRSA::decrypt(PrivateKey* privateKey, const ByteString& encryptedData, ByteString& data, const AsymMech::Type 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 eme; switch (padding) { case AsymMech::RSA_PKCS: eme = "PKCS1v15"; break; case AsymMech::RSA_PKCS_OAEP: eme = "EME1(SHA-160)"; break; case AsymMech::RSA: eme = "Raw"; break; default: ERROR_MSG("Invalid padding mechanism supplied (%i)", padding); 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 #if BOTAN_VERSION_MINOR == 11 Botan::secure_vector<Botan::byte> decResult; #else Botan::SecureVector<Botan::byte> decResult; #endif 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 (padding == AsymMech::RSA) { // We compensate that Botan removes leading zeros int modSize = pk->getN().size(); int decSize = decResult.size(); data.resize(modSize); #if BOTAN_VERSION_MINOR == 11 memcpy(&data[0] + modSize - decSize, decResult.data(), decSize); #else memcpy(&data[0] + modSize - decSize, decResult.begin(), decSize); #endif } else { data.resize(decResult.size()); #if BOTAN_VERSION_MINOR == 11 memcpy(&data[0], decResult.data(), decResult.size()); #else memcpy(&data[0], decResult.begin(), decResult.size()); #endif } delete decryptor; return true; }
// Signing functions bool BotanRSA::sign(PrivateKey* privateKey, const ByteString& dataToSign, ByteString& signature, const AsymMech::Type mechanism, const void* param /* = NULL */, const size_t paramLen /* = 0 */) { std::string emsa = ""; switch (mechanism) { case AsymMech::RSA: emsa = "Raw"; break; case AsymMech::RSA_PKCS: emsa = "EMSA3(Raw)"; break; default: // Call default implementation return AsymmetricAlgorithm::sign(privateKey, dataToSign, signature, mechanism, param, paramLen); } // Check if the private key is the right type if (!privateKey->isOfType(BotanRSAPrivateKey::type)) { ERROR_MSG("Invalid key type supplied"); 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; } 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 (std::exception& e) { ERROR_MSG("Could not sign the data: %s", e.what()); 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; }
bool BotanRSA::signInit(PrivateKey* privateKey, const AsymMech::Type mechanism, const void* param /* = NULL */, const size_t paramLen /* = 0 */) { if (!AsymmetricAlgorithm::signInit(privateKey, mechanism, param, paramLen)) { return false; } // Check if the private key is the right type if (!privateKey->isOfType(BotanRSAPrivateKey::type)) { ERROR_MSG("Invalid key type supplied"); ByteString dummy; AsymmetricAlgorithm::signFinal(dummy); return false; } std::string emsa; std::ostringstream request; size_t sLen; switch (mechanism) { case AsymMech::RSA_MD5_PKCS: emsa = "EMSA3(MD5)"; break; case AsymMech::RSA_SHA1_PKCS: emsa = "EMSA3(SHA-160)"; break; case AsymMech::RSA_SHA224_PKCS: emsa = "EMSA3(SHA-224)"; break; case AsymMech::RSA_SHA256_PKCS: emsa = "EMSA3(SHA-256)"; break; case AsymMech::RSA_SHA384_PKCS: emsa = "EMSA3(SHA-384)"; break; case AsymMech::RSA_SHA512_PKCS: emsa = "EMSA3(SHA-512)"; break; case AsymMech::RSA_SHA1_PKCS_PSS: if (param == NULL || paramLen != sizeof(RSA_PKCS_PSS_PARAMS) || ((RSA_PKCS_PSS_PARAMS*) param)->hashAlg != HashAlgo::SHA1 || ((RSA_PKCS_PSS_PARAMS*) param)->mgf != AsymRSAMGF::MGF1_SHA1) { ERROR_MSG("Invalid parameters"); ByteString dummy; AsymmetricAlgorithm::signFinal(dummy); return false; } sLen = ((RSA_PKCS_PSS_PARAMS*) param)->sLen; if (sLen > ((privateKey->getBitLength()+6)/8-2-20)) { ERROR_MSG("sLen (%lu) is too large for current key size (%lu)", (unsigned long)sLen, privateKey->getBitLength()); ByteString dummy; AsymmetricAlgorithm::signFinal(dummy); return false; } request << "EMSA4(SHA-160,MGF1," << sLen << ")"; emsa = request.str(); break; case AsymMech::RSA_SHA224_PKCS_PSS: if (param == NULL || paramLen != sizeof(RSA_PKCS_PSS_PARAMS) || ((RSA_PKCS_PSS_PARAMS*) param)->hashAlg != HashAlgo::SHA224 || ((RSA_PKCS_PSS_PARAMS*) param)->mgf != AsymRSAMGF::MGF1_SHA224) { ERROR_MSG("Invalid parameters"); ByteString dummy; AsymmetricAlgorithm::signFinal(dummy); return false; } sLen = ((RSA_PKCS_PSS_PARAMS*) param)->sLen; if (sLen > ((privateKey->getBitLength()+6)/8-2-28)) { ERROR_MSG("sLen (%lu) is too large for current key size (%lu)", (unsigned long)sLen, privateKey->getBitLength()); ByteString dummy; AsymmetricAlgorithm::signFinal(dummy); return false; } request << "EMSA4(SHA-224,MGF1," << sLen << ")"; emsa = request.str(); break; case AsymMech::RSA_SHA256_PKCS_PSS: if (param == NULL || paramLen != sizeof(RSA_PKCS_PSS_PARAMS) || ((RSA_PKCS_PSS_PARAMS*) param)->hashAlg != HashAlgo::SHA256 || ((RSA_PKCS_PSS_PARAMS*) param)->mgf != AsymRSAMGF::MGF1_SHA256) { ERROR_MSG("Invalid parameters"); ByteString dummy; AsymmetricAlgorithm::signFinal(dummy); return false; } sLen = ((RSA_PKCS_PSS_PARAMS*) param)->sLen; if (sLen > ((privateKey->getBitLength()+6)/8-2-32)) { ERROR_MSG("sLen (%lu) is too large for current key size (%lu)", (unsigned long)sLen, privateKey->getBitLength()); ByteString dummy; AsymmetricAlgorithm::signFinal(dummy); return false; } request << "EMSA4(SHA-256,MGF1," << sLen << ")"; emsa = request.str(); break; case AsymMech::RSA_SHA384_PKCS_PSS: if (param == NULL || paramLen != sizeof(RSA_PKCS_PSS_PARAMS) || ((RSA_PKCS_PSS_PARAMS*) param)->hashAlg != HashAlgo::SHA384 || ((RSA_PKCS_PSS_PARAMS*) param)->mgf != AsymRSAMGF::MGF1_SHA384) { ERROR_MSG("Invalid parameters"); ByteString dummy; AsymmetricAlgorithm::signFinal(dummy); return false; } sLen = ((RSA_PKCS_PSS_PARAMS*) param)->sLen; if (sLen > ((privateKey->getBitLength()+6)/8-2-48)) { ERROR_MSG("sLen (%lu) is too large for current key size (%lu)", (unsigned long)sLen, privateKey->getBitLength()); ByteString dummy; AsymmetricAlgorithm::signFinal(dummy); return false; } request << "EMSA4(SHA-384,MGF1," << sLen << ")"; emsa = request.str(); break; case AsymMech::RSA_SHA512_PKCS_PSS: if (param == NULL || paramLen != sizeof(RSA_PKCS_PSS_PARAMS) || ((RSA_PKCS_PSS_PARAMS*) param)->hashAlg != HashAlgo::SHA512 || ((RSA_PKCS_PSS_PARAMS*) param)->mgf != AsymRSAMGF::MGF1_SHA512) { ERROR_MSG("Invalid parameters"); ByteString dummy; AsymmetricAlgorithm::signFinal(dummy); return false; } sLen = ((RSA_PKCS_PSS_PARAMS*) param)->sLen; if (sLen > ((privateKey->getBitLength()+6)/8-2-64)) { ERROR_MSG("sLen (%lu) is too large for current key size (%lu)", (unsigned long)sLen, privateKey->getBitLength()); ByteString dummy; AsymmetricAlgorithm::signFinal(dummy); return false; } request << "EMSA4(SHA-512,MGF1," << sLen << ")"; emsa = request.str(); break; case AsymMech::RSA_SSL: emsa = "EMSA3(Parallel(MD5,SHA-160))"; break; default: ERROR_MSG("Invalid mechanism supplied (%i)", mechanism); ByteString dummy; AsymmetricAlgorithm::signFinal(dummy); return false; } BotanRSAPrivateKey* pk = (BotanRSAPrivateKey*) currentPrivateKey; Botan::RSA_PrivateKey* botanKey = pk->getBotanKey(); if (!botanKey) { ERROR_MSG("Could not get the Botan private key"); ByteString dummy; AsymmetricAlgorithm::signFinal(dummy); 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"); ByteString dummy; AsymmetricAlgorithm::signFinal(dummy); return false; } return true; }
// 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; }
// Signing functions bool BotanRSA::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("rsa-pkcs")) { emsa = "EMSA3(Raw)"; } else if (!lowerMechanism.compare("rsa-raw")) { 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(BotanRSAPrivateKey::type)) { ERROR_MSG("Invalid key type supplied"); 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; } 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; }
bool BotanRSA::signInit(PrivateKey* privateKey, const std::string mechanism) { if (!AsymmetricAlgorithm::signInit(privateKey, mechanism)) { return false; } // Check if the private key is the right type if (!privateKey->isOfType(BotanRSAPrivateKey::type)) { ERROR_MSG("Invalid key type supplied"); ByteString dummy; AsymmetricAlgorithm::signFinal(dummy); return false; } std::string lowerMechanism; lowerMechanism.resize(mechanism.size()); std::transform(mechanism.begin(), mechanism.end(), lowerMechanism.begin(), tolower); std::string emsa; if (!lowerMechanism.compare("rsa-md5-pkcs")) { emsa = "EMSA3(MD5)"; } else if (!lowerMechanism.compare("rsa-sha1-pkcs")) { emsa = "EMSA3(SHA-160)"; } else if (!lowerMechanism.compare("rsa-sha224-pkcs")) { emsa = "EMSA3(SHA-224)"; } else if (!lowerMechanism.compare("rsa-sha256-pkcs")) { emsa = "EMSA3(SHA-256)"; } else if (!lowerMechanism.compare("rsa-sha384-pkcs")) { emsa = "EMSA3(SHA-384)"; } else if (!lowerMechanism.compare("rsa-sha512-pkcs")) { emsa = "EMSA3(SHA-512)"; } else if (!lowerMechanism.compare("rsa-ssl")) { emsa = "EMSA3(Parallel(MD5,SHA-160))"; } else { ERROR_MSG("Invalid mechanism supplied (%s)", mechanism.c_str()); ByteString dummy; AsymmetricAlgorithm::signFinal(dummy); return false; } BotanRSAPrivateKey* pk = (BotanRSAPrivateKey*) currentPrivateKey; Botan::RSA_PrivateKey* botanKey = pk->getBotanKey(); if (!botanKey) { ERROR_MSG("Could not get the Botan private key"); ByteString dummy; AsymmetricAlgorithm::signFinal(dummy); 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"); ByteString dummy; AsymmetricAlgorithm::signFinal(dummy); return false; } return true; }