Skip to content

Commit

Permalink
Refactor OpenSSL resolving (#7802)
Browse files Browse the repository at this point in the history
Use deCONZ library functions instead of Qt + platform defines.
  • Loading branch information
manup authored Jun 2, 2024
1 parent 2f8ea71 commit acf9108
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 454 deletions.
44 changes: 27 additions & 17 deletions crypto/mmohash.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,19 @@
/*
* Copyright (c) 2021-2024 dresden elektronik ingenieurtechnik gmbh.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
* style license a copy of which has been included with this distribution in
* the LICENSE.txt file.
*
*/

#include "deconz/u_library_ex.h"
#include "deconz/u_memory.h"
#include "crypto/mmohash.h"

#ifdef HAS_OPENSSL

#include <QLibrary>
#include <openssl/evp.h>

#define AES_BLOCK_SIZE 16
Expand All @@ -29,7 +40,7 @@ static bool aesMmoHash(unsigned char *result, unsigned char *data, unsigned data
unsigned char block[AES_BLOCK_SIZE];
unsigned char encrypted_block[AES_BLOCK_SIZE * 2] = {0};

memcpy(&block[0], &data[0], AES_BLOCK_SIZE);
U_memcpy(&block[0], &data[0], AES_BLOCK_SIZE);

int outlen = 0;
if (lib_EVP_EncryptUpdate(lib_ctx, &encrypted_block[0], &outlen, &block[0], AES_BLOCK_SIZE) != 1)
Expand Down Expand Up @@ -98,20 +109,19 @@ static unsigned short ccit_crc16(unsigned char *data_p, unsigned short length)
*/
bool CRYPTO_GetMmoHashFromInstallCode(const std::string &hexString, std::vector<unsigned char> &result)
{
#ifdef Q_OS_WIN
QLibrary libCrypto(QLatin1String("libcrypto-1_1.dll"));
#elif defined (__APPLE__)
QLibrary libCrypto(QLatin1String("../Frameworks/libcrypto.3.dylib"));
#else
QLibrary libCrypto("crypto");
#endif

lib_EVP_CIPHER_CTX_new = (EVP_CIPHER_CTX *(*)(void))libCrypto.resolve("EVP_CIPHER_CTX_new");
lib_EVP_EncryptInit = (void (*)(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, const unsigned char *key, const unsigned char *iv))libCrypto.resolve("EVP_EncryptInit");
lib_EVP_EncryptUpdate = (int (*)(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, const unsigned char *in, int inl))libCrypto.resolve("EVP_EncryptUpdate");
lib_EVP_EncryptFinal_ex = (int (*)(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl))libCrypto.resolve("EVP_EncryptFinal_ex");
lib_EVP_CIPHER_CTX_free = (void (*)(EVP_CIPHER_CTX *ctx))libCrypto.resolve("EVP_CIPHER_CTX_free");
lib_EVP_aes_128_ecb = (const EVP_CIPHER *(*)(void))libCrypto.resolve("EVP_aes_128_ecb");
void *libCrypto = U_library_open_ex("libcrypto");

if (!libCrypto)
{
return false;
}

lib_EVP_CIPHER_CTX_new = (EVP_CIPHER_CTX *(*)(void))U_library_symbol(libCrypto, "EVP_CIPHER_CTX_new");
lib_EVP_EncryptInit = (void (*)(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, const unsigned char *key, const unsigned char *iv))U_library_symbol(libCrypto, "EVP_EncryptInit");
lib_EVP_EncryptUpdate = (int (*)(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, const unsigned char *in, int inl))U_library_symbol(libCrypto, "EVP_EncryptUpdate");
lib_EVP_EncryptFinal_ex = (int (*)(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl))U_library_symbol(libCrypto, "EVP_EncryptFinal_ex");
lib_EVP_CIPHER_CTX_free = (void (*)(EVP_CIPHER_CTX *ctx))U_library_symbol(libCrypto, "EVP_CIPHER_CTX_free");
lib_EVP_aes_128_ecb = (const EVP_CIPHER *(*)(void))U_library_symbol(libCrypto, "EVP_aes_128_ecb");

if (!lib_EVP_CIPHER_CTX_new || !lib_EVP_EncryptInit || !lib_EVP_EncryptUpdate || !lib_EVP_EncryptFinal_ex || !lib_EVP_CIPHER_CTX_free | !lib_EVP_aes_128_ecb)
{
Expand Down Expand Up @@ -195,7 +205,7 @@ bool CRYPTO_GetMmoHashFromInstallCode(const std::string &hexString, std::vector<
if (AES_BLOCK_SIZE - moreDataLength < 3)
{
aesMmoHash(hashResult, &temp[0], AES_BLOCK_SIZE);
memset(&temp[0], 0x00, sizeof(temp));
U_memset(&temp[0], 0x00, sizeof(temp));
}

temp[AES_BLOCK_SIZE - 2] = (dataLength >> 5) & 0xFF;
Expand Down
82 changes: 10 additions & 72 deletions crypto/random.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021 dresden elektronik ingenieurtechnik gmbh.
* Copyright (c) 2021-2024 dresden elektronik ingenieurtechnik gmbh.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
Expand All @@ -9,82 +9,13 @@
*/

#include <random>
#include <stdlib.h>
#include "random.h"
#include "deconz/u_library_ex.h"

// OpenSSL reference to RAND_bytes()
typedef int (*RAND_bytes_t)(unsigned char *buf, int num);
static RAND_bytes_t RAND_bytes = nullptr;

#ifdef __linux__
#include <dlfcn.h>

/*! RAII helper to open/close OpenSSL.
*/
class RNGLib
{
public:
RNGLib()
{
handle = dlopen("libcrypto.so", RTLD_LAZY);

if (handle)
{
RAND_bytes = reinterpret_cast<RAND_bytes_t>(dlsym(handle, "RAND_bytes"));
}
}

~RNGLib()
{
RAND_bytes = nullptr;
if (handle)
{
dlclose(handle);
}
}

private:
void *handle = nullptr;
};
#endif

#ifdef __APPLE__
class RNGLib
{
};
#endif

#ifdef _WIN32
#include <windows.h>
/*! RAII helper to open/close OpenSSL.
*/
class RNGLib
{
public:
RNGLib()
{
handle = LoadLibraryA("libcrypto-1_1.dll");

if (handle)
{
RAND_bytes = reinterpret_cast<RAND_bytes_t>(GetProcAddress(handle, "RAND_bytes"));
}
}

~RNGLib()
{
RAND_bytes = nullptr;
if (handle)
{
FreeLibrary(handle);
}
}

private:
HMODULE handle = nullptr;
};
#endif

/*! Fallback to C++ random number generator if OpenSSL isn't available.
*/
void fallbackRandom(unsigned char *buf, unsigned int size)
Expand All @@ -103,7 +34,14 @@ void fallbackRandom(unsigned char *buf, unsigned int size)
*/
void CRYPTO_RandomBytes(unsigned char *buf, unsigned int size)
{
RNGLib lib;
if (!RAND_bytes)
{
void *libCrypto = U_library_open_ex("libcrypto");
if (libCrypto)
{
RAND_bytes = reinterpret_cast<RAND_bytes_t>(U_library_symbol(libCrypto, "RAND_bytes"));
}
}

if (RAND_bytes && RAND_bytes(buf, int(size)) == 1)
{
Expand Down
47 changes: 23 additions & 24 deletions crypto/scrypt.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021 dresden elektronik ingenieurtechnik gmbh.
* Copyright (c) 2021-2024 dresden elektronik ingenieurtechnik gmbh.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
Expand All @@ -17,9 +17,11 @@
#endif

#include <array>
#include <QLibrary>
#include <QByteArray>
#include <QString>
#include "random.h"
#include "scrypt.h"
#include "deconz/u_library_ex.h"


#ifdef HAS_OPENSSL
Expand Down Expand Up @@ -63,35 +65,32 @@ static int wrap_EVP_PKEY_CTX_set_scrypt_p(EVP_PKEY_CTX *ctx, uint64_t p)
*/
static int scryptDerive(const char *input, size_t inputLength, std::array<unsigned char, 64> &out, int N, int r, int p, const unsigned char *salt, size_t saltlen)
{
#ifdef Q_OS_WIN
QLibrary libCrypto(QLatin1String("libcrypto-1_1.dll"));
QLibrary libSsl(QLatin1String("libssl-1_1.dll"));
#elif defined (__APPLE__)
QLibrary libCrypto(QLatin1String("../Frameworks/libcrypto.3.dylib"));
QLibrary libSsl(QLatin1String("../Frameworks/libssl.3.dylib"));
#else
QLibrary libCrypto(QLatin1String("crypto"));
QLibrary libSsl(QLatin1String("ssl"));
#endif
void *libCrypto = U_library_open_ex("libcrypto");
void *libSsl = U_library_open_ex("libssl");

if (!libCrypto || !libSsl)
{
return -1;
}

unsigned long openSslVersion = 0;

auto _OpenSSL_version_num = reinterpret_cast<unsigned long (*)(void)>(libCrypto.resolve("OpenSSL_version_num"));
auto _OpenSSL_version_num = reinterpret_cast<unsigned long (*)(void)>(U_library_symbol(libCrypto, "OpenSSL_version_num"));

const auto lib_EVP_PKEY_CTX_new_id = reinterpret_cast<EVP_PKEY_CTX *(*)(int id, ENGINE *e)>(libCrypto.resolve("EVP_PKEY_CTX_new_id"));
const auto lib_EVP_PKEY_derive_init = reinterpret_cast<int (*)(EVP_PKEY_CTX *ctx)>(libCrypto.resolve("EVP_PKEY_derive_init"));
lib_EVP_PKEY_CTX_ctrl = reinterpret_cast<int (*)(EVP_PKEY_CTX *ctx, int keytype, int optype, int cmd, int p1, void *p2)>(libCrypto.resolve("EVP_PKEY_CTX_ctrl"));
lib_EVP_PKEY_CTX_ctrl_uint64 = reinterpret_cast<int (*)(EVP_PKEY_CTX *ctx, int keytype, int optype, int cmd, uint64_t value)>(libCrypto.resolve("EVP_PKEY_CTX_ctrl_uint64"));
const auto lib_EVP_PKEY_derive = reinterpret_cast<int (*)(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen)>(libCrypto.resolve("EVP_PKEY_derive"));
const auto lib_EVP_PKEY_CTX_free = reinterpret_cast<void (*)(EVP_PKEY_CTX *ctx)>(libCrypto.resolve("EVP_PKEY_CTX_free"));
const auto lib_EVP_PKEY_CTX_new_id = reinterpret_cast<EVP_PKEY_CTX *(*)(int id, ENGINE *e)>(U_library_symbol(libCrypto, "EVP_PKEY_CTX_new_id"));
const auto lib_EVP_PKEY_derive_init = reinterpret_cast<int (*)(EVP_PKEY_CTX *ctx)>(U_library_symbol(libCrypto, "EVP_PKEY_derive_init"));
lib_EVP_PKEY_CTX_ctrl = reinterpret_cast<int (*)(EVP_PKEY_CTX *ctx, int keytype, int optype, int cmd, int p1, void *p2)>(U_library_symbol(libCrypto, "EVP_PKEY_CTX_ctrl"));
lib_EVP_PKEY_CTX_ctrl_uint64 = reinterpret_cast<int (*)(EVP_PKEY_CTX *ctx, int keytype, int optype, int cmd, uint64_t value)>(U_library_symbol(libCrypto, "EVP_PKEY_CTX_ctrl_uint64"));
const auto lib_EVP_PKEY_derive = reinterpret_cast<int (*)(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen)>(U_library_symbol(libCrypto, "EVP_PKEY_derive"));
const auto lib_EVP_PKEY_CTX_free = reinterpret_cast<void (*)(EVP_PKEY_CTX *ctx)>(U_library_symbol(libCrypto, "EVP_PKEY_CTX_free"));

auto lib_EVP_PKEY_CTX_set1_pbe_pass = reinterpret_cast<int (*)(EVP_PKEY_CTX *ctx, const char *pass, int passlen)>(libCrypto.resolve("EVP_PKEY_CTX_set1_pbe_pass"));
auto lib_EVP_PKEY_CTX_set1_pbe_pass = reinterpret_cast<int (*)(EVP_PKEY_CTX *ctx, const char *pass, int passlen)>(U_library_symbol(libCrypto, "EVP_PKEY_CTX_set1_pbe_pass"));

auto lib_EVP_PKEY_CTX_set1_scrypt_salt = reinterpret_cast<int (*)(EVP_PKEY_CTX *ctx, const unsigned char *salt, int saltlen)>(libCrypto.resolve("EVP_PKEY_CTX_set1_scrypt_salt"));
auto lib_EVP_PKEY_CTX_set1_scrypt_salt = reinterpret_cast<int (*)(EVP_PKEY_CTX *ctx, const unsigned char *salt, int saltlen)>(U_library_symbol(libCrypto, "EVP_PKEY_CTX_set1_scrypt_salt"));

auto lib_EVP_PKEY_CTX_set_scrypt_N = reinterpret_cast<int (*)(EVP_PKEY_CTX *ctx, uint64_t n)>(libCrypto.resolve("EVP_PKEY_CTX_set_scrypt_N"));
auto lib_EVP_PKEY_CTX_set_scrypt_r = reinterpret_cast<int (*)(EVP_PKEY_CTX *ctx, uint64_t r)>(libCrypto.resolve("EVP_PKEY_CTX_set_scrypt_r"));
auto lib_EVP_PKEY_CTX_set_scrypt_p = reinterpret_cast<int (*)(EVP_PKEY_CTX *ctx, uint64_t p)>(libCrypto.resolve("EVP_PKEY_CTX_set_scrypt_p"));
auto lib_EVP_PKEY_CTX_set_scrypt_N = reinterpret_cast<int (*)(EVP_PKEY_CTX *ctx, uint64_t n)>(U_library_symbol(libCrypto, "EVP_PKEY_CTX_set_scrypt_N"));
auto lib_EVP_PKEY_CTX_set_scrypt_r = reinterpret_cast<int (*)(EVP_PKEY_CTX *ctx, uint64_t r)>(U_library_symbol(libCrypto, "EVP_PKEY_CTX_set_scrypt_r"));
auto lib_EVP_PKEY_CTX_set_scrypt_p = reinterpret_cast<int (*)(EVP_PKEY_CTX *ctx, uint64_t p)>(U_library_symbol(libCrypto, "EVP_PKEY_CTX_set_scrypt_p"));

if (_OpenSSL_version_num)
{
Expand Down
Loading

0 comments on commit acf9108

Please sign in to comment.