/* * Copyright (C) 2008-2017 TrinityCore * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ #include "RSA.h" #include "BigNumber.h" #include #include #include #include #include #include #define CHECK_AND_DECLARE_FUNCTION_TYPE(name, publicKey, privateKey) \ static_assert(std::is_same::value, \ "Public key and private key functions must have the same signature"); \ using name ## _t = decltype(&publicKey); \ template inline name ## _t get_ ## name () { return nullptr; } \ template <> inline name ## _t get_ ## name() { return &publicKey; } \ template <> inline name ## _t get_ ## name() { return &privateKey; } namespace { struct BIODeleter { void operator()(BIO* bio) { BIO_free(bio); } }; CHECK_AND_DECLARE_FUNCTION_TYPE(PEM_read, PEM_read_bio_RSAPublicKey, PEM_read_bio_RSAPrivateKey); CHECK_AND_DECLARE_FUNCTION_TYPE(RSA_encrypt, RSA_public_encrypt, RSA_private_encrypt); } Trinity::Crypto::RSA::RSA() { _rsa = RSA_new(); } Trinity::Crypto::RSA::RSA(RSA&& rsa) { _rsa = rsa._rsa; rsa._rsa = RSA_new(); } Trinity::Crypto::RSA::~RSA() { RSA_free(_rsa); } template bool Trinity::Crypto::RSA::LoadFromFile(std::string const& fileName, KeyTag) { std::unique_ptr keyBIO(BIO_new_file(fileName.c_str(), "r")); if (!keyBIO) return false; if (!get_PEM_read()(keyBIO.get(), &_rsa, nullptr, nullptr)) return false; return true; } template bool Trinity::Crypto::RSA::LoadFromString(std::string const& keyPem, KeyTag) { std::unique_ptr keyBIO(BIO_new_mem_buf( const_cast(keyPem.c_str()) /*api hack - this function assumes memory is readonly but lacks const modifier*/, keyPem.length() + 1)); if (!keyBIO) return false; if (!get_PEM_read()(keyBIO.get(), &_rsa, nullptr, nullptr)) return false; return true; } BigNumber Trinity::Crypto::RSA::GetModulus() const { BigNumber bn; BN_copy(bn.BN(), _rsa->n); return bn; } template bool Trinity::Crypto::RSA::Encrypt(uint8 const* data, std::size_t dataLength, uint8* output, int32 paddingType) { std::vector inputData(std::make_reverse_iterator(data + dataLength), std::make_reverse_iterator(data)); int result = get_RSA_encrypt()(inputData.size(), inputData.data(), output, _rsa, paddingType); std::reverse(output, output + GetOutputSize()); return result != -1; } bool Trinity::Crypto::RSA::Sign(int32 hashType, uint8 const* dataHash, std::size_t dataHashLength, uint8* output) { uint32 signatureLength = 0; int result = RSA_sign(hashType, dataHash, dataHashLength, output, &signatureLength, _rsa); std::reverse(output, output + GetOutputSize()); return result != -1; } namespace Trinity { namespace Crypto { template TC_COMMON_API bool RSA::LoadFromFile(std::string const& fileName, RSA::PublicKey); template TC_COMMON_API bool RSA::LoadFromFile(std::string const& fileName, RSA::PrivateKey); template TC_COMMON_API bool RSA::LoadFromString(std::string const& keyPem, RSA::PublicKey); template TC_COMMON_API bool RSA::LoadFromString(std::string const& keyPem, RSA::PrivateKey); template TC_COMMON_API bool RSA::Encrypt(uint8 const* data, std::size_t dataLength, uint8* output, int32 paddingType); template TC_COMMON_API bool RSA::Encrypt(uint8 const* data, std::size_t dataLength, uint8* output, int32 paddingType); } }