From e66c9ed0577d4e836e804fc9ce37d22843e7b152 Mon Sep 17 00:00:00 2001 From: Liu Zixian Date: Tue, 14 Oct 2025 09:17:21 +0800 Subject: [PATCH] Update OpenSSL API Signed-off-by: Liu Zixian --- lib/MessageCrypto.cc | 110 +++++++++++++++++++++++++++-------- lib/MessageCrypto.h | 10 +++- lib/auth/athenz/ZTSClient.cc | 34 +++++++++-- lib/auth/athenz/ZTSClient.h | 3 + 4 files changed, 123 insertions(+), 34 deletions(-) diff --git a/lib/MessageCrypto.cc b/lib/MessageCrypto.cc index dc636c00..b06ff652 100644 --- a/lib/MessageCrypto.cc +++ b/lib/MessageCrypto.cc @@ -35,9 +35,6 @@ MessageCrypto::MessageCrypto(const std::string& logCtx, bool keyGenNeeded) ivLen_(12), iv_(new unsigned char[ivLen_]), logCtx_(logCtx) { - SSL_library_init(); - SSL_load_error_strings(); - if (!keyGenNeeded) { mdCtx_ = EVP_MD_CTX_create(); EVP_MD_CTX_init(mdCtx_); @@ -50,9 +47,9 @@ MessageCrypto::MessageCrypto(const std::string& logCtx, bool keyGenNeeded) MessageCrypto::~MessageCrypto() {} -RSA* MessageCrypto::loadPublicKey(std::string& pubKeyStr) { +EVP_PKEY* MessageCrypto::loadPublicKey(std::string& pubKeyStr) { BIO* pubBio = NULL; - RSA* rsaPub = NULL; + EVP_PKEY* rsaPub = NULL; pubBio = BIO_new_mem_buf((char*)pubKeyStr.c_str(), -1); if (pubBio == NULL) { @@ -60,7 +57,7 @@ RSA* MessageCrypto::loadPublicKey(std::string& pubKeyStr) { return rsaPub; } - rsaPub = PEM_read_bio_RSA_PUBKEY(pubBio, NULL, NULL, NULL); + rsaPub = PEM_read_bio_PUBKEY(pubBio, NULL, NULL, NULL); if (rsaPub == NULL) { LOG_ERROR(logCtx_ << " Failed to load public key"); } @@ -69,9 +66,9 @@ RSA* MessageCrypto::loadPublicKey(std::string& pubKeyStr) { return rsaPub; } -RSA* MessageCrypto::loadPrivateKey(std::string& privateKeyStr) { +EVP_PKEY* MessageCrypto::loadPrivateKey(std::string& privateKeyStr) { BIO* privBio = NULL; - RSA* rsaPriv = NULL; + EVP_PKEY* rsaPriv = NULL; privBio = BIO_new_mem_buf((char*)privateKeyStr.c_str(), -1); if (privBio == NULL) { @@ -79,7 +76,7 @@ RSA* MessageCrypto::loadPrivateKey(std::string& privateKeyStr) { return rsaPriv; } - rsaPriv = PEM_read_bio_RSAPrivateKey(privBio, NULL, NULL, NULL); + rsaPriv = PEM_read_bio_PrivateKey(privBio, NULL, NULL, NULL); if (rsaPriv == NULL) { LOG_ERROR(logCtx_ << " Failed to load private key"); } @@ -88,6 +85,59 @@ RSA* MessageCrypto::loadPrivateKey(std::string& privateKeyStr) { return rsaPriv; } +bool MessageCrypto::rsaDecrypt(EVP_PKEY_CTX* ctx, const std::string& in, + boost::scoped_array& out, size_t& outLen) { + if (EVP_PKEY_decrypt_init(ctx) <= 0) { + LOG_ERROR(logCtx_ << "Failed to initialize decryption"); + return false; + } + if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) <= 0) { + LOG_ERROR(logCtx_ << "Failed to set RSA padding"); + return false; + } + auto inStr_ = reinterpret_cast(in.c_str()); + size_t rsaSize; + if (EVP_PKEY_decrypt(ctx, NULL, &rsaSize, inStr_, in.size()) <= 0) { + LOG_ERROR(logCtx_ << "Failed to determine decrypt buffer size"); + return false; + } + if (rsaSize != outLen) { + outLen = rsaSize; + out.reset(new unsigned char[outLen]); + } + if (EVP_PKEY_decrypt(ctx, out.get(), &outLen, inStr_, in.size()) <= 0) { + LOG_ERROR(logCtx_ << "Failed to decrypt."); + return false; + } + return true; +} + +bool MessageCrypto::rsaEncrypt(EVP_PKEY_CTX* ctx, boost::scoped_array& in, size_t inLen, + boost::scoped_array& out, size_t& outLen) { + if (EVP_PKEY_encrypt_init(ctx) <= 0) { + LOG_ERROR(logCtx_ << "Failed to initialize encryption"); + return false; + } + if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) <= 0) { + LOG_ERROR(logCtx_ << "Failed to set RSA padding"); + return false; + } + size_t rsaSize; + if (EVP_PKEY_encrypt(ctx, NULL, &rsaSize, in.get(), inLen) <= 0) { + LOG_ERROR(logCtx_ << "Failed to determine encrypt buffer size"); + return false; + } + if (rsaSize != outLen) { + outLen = rsaSize; + out.reset(new unsigned char[rsaSize]); + } + if (EVP_PKEY_encrypt(ctx, out.get(), &outLen, in.get(), inLen) <= 0) { + LOG_ERROR(logCtx_ << "Failed to encrypt."); + return false; + } + return true; +} + bool MessageCrypto::getDigest(const std::string& keyName, const void* input, unsigned int inputLen, unsigned char keyDigest[], unsigned int& digestLen) { if (EVP_DigestInit_ex(mdCtx_, EVP_md5(), NULL) != 1) { @@ -181,24 +231,29 @@ Result MessageCrypto::addPublicKeyCipher(const std::string& keyName, const Crypt return result; } - RSA* pubKey = loadPublicKey(keyInfo.getKey()); + auto* pubKey = loadPublicKey(keyInfo.getKey()); if (pubKey == NULL) { LOG_ERROR(logCtx_ << "Failed to load public key " << keyName); return ResultCryptoError; } LOG_DEBUG(logCtx_ << " Public key " << keyName << " loaded successfully."); - int inSize = RSA_size(pubKey); - boost::scoped_array encryptedKey(new unsigned char[inSize]); - - int outSize = - RSA_public_encrypt(dataKeyLen_, dataKey_.get(), encryptedKey.get(), pubKey, RSA_PKCS1_OAEP_PADDING); - - if (inSize != outSize) { - LOG_ERROR(logCtx_ << "Ciphertext is length not matching input key length for key " << keyName); + boost::scoped_array encryptedKey{nullptr}; + size_t encryptedKeyLen{0}; + auto* ctx = EVP_PKEY_CTX_new(pubKey, NULL); + if (!ctx) { + LOG_ERROR(logCtx_ << "Failed to create EVP_PKEY_CTX for " << keyName); + EVP_PKEY_free(pubKey); + return ResultCryptoError; + } + bool encrypted = rsaEncrypt(ctx, dataKey_, dataKeyLen_, encryptedKey, encryptedKeyLen); + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_free(pubKey); + if (!encrypted) { + LOG_ERROR(logCtx_ << "Failed to encrypt with " << keyName); return ResultCryptoError; } - std::string encryptedKeyStr(reinterpret_cast(encryptedKey.get()), inSize); + std::string encryptedKeyStr(reinterpret_cast(encryptedKey.get()), encryptedKeyLen); std::shared_ptr eki(new EncryptionKeyInfo()); eki->setKey(encryptedKeyStr); eki->setMetadata(keyInfo.getMetadata()); @@ -353,7 +408,7 @@ bool MessageCrypto::decryptDataKey(const proto::EncryptionKeys& encKeys, const C keyReader.getPrivateKey(keyName, keyMeta, keyInfo); // Convert key from string to RSA key - RSA* privKey = loadPrivateKey(keyInfo.getKey()); + auto* privKey = loadPrivateKey(keyInfo.getKey()); if (privKey == NULL) { LOG_ERROR(logCtx_ << " Failed to load private key " << keyName); return false; @@ -361,11 +416,16 @@ bool MessageCrypto::decryptDataKey(const proto::EncryptionKeys& encKeys, const C LOG_DEBUG(logCtx_ << " Private key " << keyName << " loaded successfully."); // Decrypt data key - int outSize = RSA_private_decrypt(encryptedDataKey.size(), - reinterpret_cast(encryptedDataKey.c_str()), - dataKey_.get(), privKey, RSA_PKCS1_OAEP_PADDING); - - if (outSize == -1) { + auto* ctx = EVP_PKEY_CTX_new(privKey, NULL); + if (!ctx) { + LOG_ERROR(logCtx_ << "Failed to create EVP_PKEY_CTX for " << keyName); + EVP_PKEY_free(privKey); + return false; + } + bool decrypted = rsaDecrypt(ctx, encryptedDataKey, dataKey_, dataKeyLen_); + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_free(privKey); + if (!decrypted) { LOG_ERROR(logCtx_ << "Failed to decrypt AES key for " << keyName); return false; } diff --git a/lib/MessageCrypto.h b/lib/MessageCrypto.h index 3e955d9e..cd07bf55 100644 --- a/lib/MessageCrypto.h +++ b/lib/MessageCrypto.h @@ -104,7 +104,7 @@ class MessageCrypto { typedef std::unique_lock Lock; std::mutex mutex_; - int dataKeyLen_; + size_t dataKeyLen_; boost::scoped_array dataKey_; int tagLen_; @@ -125,8 +125,12 @@ class MessageCrypto { EVP_MD_CTX* mdCtx_; - RSA* loadPublicKey(std::string& pubKeyStr); - RSA* loadPrivateKey(std::string& privateKeyStr); + EVP_PKEY* loadPublicKey(std::string& pubKeyStr); + EVP_PKEY* loadPrivateKey(std::string& privateKeyStr); + bool rsaDecrypt(EVP_PKEY_CTX* ctx, const std::string& in, boost::scoped_array& out, + size_t& outLen); + bool rsaEncrypt(EVP_PKEY_CTX* ctx, boost::scoped_array& in, size_t inLen, + boost::scoped_array& out, size_t& outLen); bool getDigest(const std::string& keyName, const void* input, unsigned int inputLen, unsigned char keyDigest[], unsigned int& digestLen); void removeExpiredDataKey(); diff --git a/lib/auth/athenz/ZTSClient.cc b/lib/auth/athenz/ZTSClient.cc index 35387d96..7d511f4e 100644 --- a/lib/auth/athenz/ZTSClient.cc +++ b/lib/auth/athenz/ZTSClient.cc @@ -226,9 +226,9 @@ const std::string ZTSClient::getPrincipalToken() const { const char *unsignedToken = unsignedTokenString.c_str(); unsigned char signature[BUFSIZ] = {}; unsigned char hash[SHA256_DIGEST_LENGTH] = {}; - unsigned int siglen; + size_t siglen; FILE *fp; - RSA *privateKey; + EVP_PKEY *privateKey; if (privateKeyUri_.scheme == "data") { if (privateKeyUri_.mediaTypeAndEncodingType != "application/x-pem-file;base64") { @@ -249,7 +249,7 @@ const std::string ZTSClient::getPrincipalToken() const { free(decodeStr); return ""; } - privateKey = PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, NULL); + privateKey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL); BIO_free(bio); free(decodeStr); if (privateKey == NULL) { @@ -263,7 +263,7 @@ const std::string ZTSClient::getPrincipalToken() const { return ""; } - privateKey = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL); + privateKey = PEM_read_PrivateKey(fp, NULL, NULL, NULL); fclose(fp); if (privateKey == NULL) { LOG_ERROR("Failed to read private key: " << privateKeyUri_.path); @@ -275,16 +275,38 @@ const std::string ZTSClient::getPrincipalToken() const { } SHA256((unsigned char *)unsignedToken, unsignedTokenString.length(), hash); - RSA_sign(NID_sha256, hash, SHA256_DIGEST_LENGTH, signature, &siglen, privateKey); + auto *ctx = EVP_MD_CTX_new(); + if (ctx == NULL) { + LOG_ERROR("Failed to create EVP_MD_CTX."); + return ""; + } + + bool sign = rsaSign(ctx, privateKey, signature, &siglen, hash); + EVP_MD_CTX_free(ctx); + if (!sign) { + LOG_ERROR("Failed to sign with " << privateKeyUri_.path); + return ""; + } std::string principalToken = unsignedTokenString + ";s=" + ybase64Encode(signature, siglen); LOG_DEBUG("Created signed principal token: " << principalToken); - RSA_free(privateKey); + EVP_PKEY_free(privateKey); return principalToken; } +bool ZTSClient::rsaSign(EVP_MD_CTX *ctx, EVP_PKEY *privateKey, unsigned char *signature, size_t *siglen, + unsigned char *hash) const { + if (EVP_DigestSignInit(ctx, NULL, EVP_sha256(), NULL, privateKey) != 1) { + return false; + } + if (EVP_DigestSign(ctx, signature, siglen, hash, SHA256_DIGEST_LENGTH) != 1) { + return false; + } + return true; +} + std::mutex cacheMtx_; const std::string ZTSClient::getRoleToken() { RoleToken roleToken; diff --git a/lib/auth/athenz/ZTSClient.h b/lib/auth/athenz/ZTSClient.h index 6fcbd69e..fa415773 100644 --- a/lib/auth/athenz/ZTSClient.h +++ b/lib/auth/athenz/ZTSClient.h @@ -16,6 +16,7 @@ * specific language governing permissions and limitations * under the License. */ +#include #include #include @@ -63,6 +64,8 @@ class PULSAR_PUBLIC ZTSClient { static UriSt parseUri(const char* uri); static bool checkRequiredParams(std::map& params, const std::vector& requiredParams); + bool rsaSign(EVP_MD_CTX* ctx, EVP_PKEY* privateKey, unsigned char* signature, size_t* siglen, + unsigned char* hash) const; friend class ZTSClientWrapper; };