mirror of
https://github.com/panda3d/panda3d.git
synced 2025-09-30 08:44:19 -04:00
prc: Fix bf-cbc encryption/decryption regression with OpenSSL 3.0
Loads the legacy provider to continue supporting this algorithm
This commit is contained in:
parent
8ca804086f
commit
d621df47ac
@ -23,6 +23,32 @@
|
|||||||
#include <openssl/rand.h>
|
#include <openssl/rand.h>
|
||||||
#include <openssl/evp.h>
|
#include <openssl/evp.h>
|
||||||
|
|
||||||
|
#if OPENSSL_VERSION_MAJOR >= 3
|
||||||
|
#include <openssl/provider.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tries to load the legacy provider in OpenSSL. Returns true if the provider
|
||||||
|
* was just loaded, false if it was already loaded or couldn't be loaded.
|
||||||
|
*/
|
||||||
|
static bool load_legacy_provider() {
|
||||||
|
static bool tried = false;
|
||||||
|
if (!tried) {
|
||||||
|
tried = true;
|
||||||
|
if (OSSL_PROVIDER_try_load(nullptr, "legacy", 1) != nullptr) {
|
||||||
|
if (prc_cat.is_debug()) {
|
||||||
|
prc_cat.debug()
|
||||||
|
<< "Loaded legacy OpenSSL provider.\n";
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
prc_cat.warning()
|
||||||
|
<< "Failed to load legacy OpenSSL provider.\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif // OPENSSL_VERSION_MAJOR
|
||||||
|
|
||||||
// The iteration count is scaled by this factor for writing to the stream.
|
// The iteration count is scaled by this factor for writing to the stream.
|
||||||
static const int iteration_count_factor = 1000;
|
static const int iteration_count_factor = 1000;
|
||||||
|
|
||||||
@ -122,7 +148,31 @@ open_read(std::istream *source, bool owns_source, const std::string &password) {
|
|||||||
int key_length = sr.get_uint16();
|
int key_length = sr.get_uint16();
|
||||||
int count = sr.get_uint16();
|
int count = sr.get_uint16();
|
||||||
|
|
||||||
|
#if OPENSSL_VERSION_MAJOR >= 3
|
||||||
|
// First, convert the cipher's nid to its full name.
|
||||||
|
const char *cipher_name = OBJ_nid2ln(nid);
|
||||||
|
|
||||||
|
const EVP_CIPHER *cipher = nullptr;
|
||||||
|
if (cipher_name != nullptr) {
|
||||||
|
// Now, fetch the cipher known by this name.
|
||||||
|
cipher = EVP_CIPHER_fetch(nullptr, cipher_name, nullptr);
|
||||||
|
|
||||||
|
if (cipher == nullptr && EVP_get_cipherbynid(nid) != nullptr) {
|
||||||
|
if (load_legacy_provider()) {
|
||||||
|
cipher = EVP_CIPHER_fetch(nullptr, cipher_name, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cipher == nullptr) {
|
||||||
|
prc_cat.error()
|
||||||
|
<< "No implementation available for encryption algorithm in stream: "
|
||||||
|
<< cipher_name << "\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
const EVP_CIPHER *cipher = EVP_get_cipherbynid(nid);
|
const EVP_CIPHER *cipher = EVP_get_cipherbynid(nid);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (cipher == nullptr) {
|
if (cipher == nullptr) {
|
||||||
prc_cat.error()
|
prc_cat.error()
|
||||||
@ -219,8 +269,29 @@ open_write(std::ostream *dest, bool owns_dest, const std::string &password) {
|
|||||||
_dest = dest;
|
_dest = dest;
|
||||||
_owns_dest = owns_dest;
|
_owns_dest = owns_dest;
|
||||||
|
|
||||||
|
#if OPENSSL_VERSION_MAJOR >= 3
|
||||||
|
// This checks that there is actually an implementation available.
|
||||||
|
const EVP_CIPHER *cipher =
|
||||||
|
EVP_CIPHER_fetch(nullptr, _algorithm.c_str(), nullptr);
|
||||||
|
|
||||||
|
if (cipher == nullptr &&
|
||||||
|
EVP_get_cipherbyname(_algorithm.c_str()) != nullptr) {
|
||||||
|
// The cipher does exist, though, do we need to load the legacy provider?
|
||||||
|
if (load_legacy_provider()) {
|
||||||
|
cipher = EVP_CIPHER_fetch(nullptr, _algorithm.c_str(), nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cipher == nullptr) {
|
||||||
|
prc_cat.error()
|
||||||
|
<< "No implementation available for encryption algorithm: "
|
||||||
|
<< _algorithm << "\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
const EVP_CIPHER *cipher =
|
const EVP_CIPHER *cipher =
|
||||||
EVP_get_cipherbyname(_algorithm.c_str());
|
EVP_get_cipherbyname(_algorithm.c_str());
|
||||||
|
#endif
|
||||||
|
|
||||||
if (cipher == nullptr) {
|
if (cipher == nullptr) {
|
||||||
prc_cat.error()
|
prc_cat.error()
|
||||||
|
20
tests/express/test_encrypt.py
Normal file
20
tests/express/test_encrypt.py
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
from panda3d import core
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
|
def test_encrypt_string():
|
||||||
|
# Test encrypt and then decrypt cycle
|
||||||
|
for algorithm in ('', 'bf-cbc', 'aes-256-cbc'):
|
||||||
|
enc = core.encrypt_string('abcdefg', '12345', algorithm)
|
||||||
|
assert len(enc) > 0
|
||||||
|
|
||||||
|
dec = core.decrypt_string(enc, '12345')
|
||||||
|
assert dec == 'abcdefg'
|
||||||
|
|
||||||
|
# Test pre-encrypted bf-cbc string
|
||||||
|
enc = b'[\x00\x10\x00d\x00\xb5\x7f\xc44Y\xb7\xd9\x15\xe3\xbd\xcf\xb3yK\xfb\xf6'
|
||||||
|
assert 'test' == core.decrypt_string(enc, '98765')
|
||||||
|
|
||||||
|
# Test pre-encrypted aes-256-cbc string
|
||||||
|
enc = b'\xab\x01 \x00d\x00\xf1WP\xb0\x96h\xf8\xc5\xf4\x8d\x0b>q0\xf15\x185\xf8+\x1b\xe4\xae8\x88\xf2\x91\x15\xb8\x8fh\x88'
|
||||||
|
assert 'test' == core.decrypt_string(enc, '98765')
|
Loading…
x
Reference in New Issue
Block a user