// 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; }
// 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; } }