Utils: Migration to OpenSSL3

This commit is contained in:
Grégory Soutadé 2022-08-10 21:37:43 +02:00
parent 57c3a58994
commit 600535d52c
5 changed files with 114 additions and 59 deletions

View File

@ -1,4 +1,3 @@
AR ?= $(CROSS)ar AR ?= $(CROSS)ar
CXX ?= $(CROSS)g++ CXX ?= $(CROSS)g++
@ -67,7 +66,7 @@ libgourou.so: $(OBJECTS) $(UPDFPARSERLIB)
$(CXX) obj/*.o $(LDFLAGS) -o $@ -shared $(CXX) obj/*.o $(LDFLAGS) -o $@ -shared
build_utils: build_utils:
make -C utils ROOT=$(PWD) CXX=$(CXX) AR=$(AR) DEBUG=$(DEBUG) STATIC_UTILS=$(STATIC_UTILS) OPENSSL3=$(OPENSSL3) make -C utils ROOT=$(PWD) CXX=$(CXX) AR=$(AR) DEBUG=$(DEBUG) STATIC_UTILS=$(STATIC_UTILS)
clean: clean:
rm -rf libgourou.a libgourou.so obj rm -rf libgourou.a libgourou.so obj

View File

@ -106,6 +106,7 @@ namespace gourou
CLIENT_INVALID_PKCS12, CLIENT_INVALID_PKCS12,
CLIENT_INVALID_CERTIFICATE, CLIENT_INVALID_CERTIFICATE,
CLIENT_NO_PRIV_KEY, CLIENT_NO_PRIV_KEY,
CLIENT_NO_PUB_KEY,
CLIENT_RSA_ERROR, CLIENT_RSA_ERROR,
CLIENT_BAD_CHAINING, CLIENT_BAD_CHAINING,
CLIENT_BAD_KEY_SIZE, CLIENT_BAD_KEY_SIZE,

View File

@ -3,16 +3,6 @@ TARGETS=acsmdownloader adept_activate adept_remove adept_loan_mgt
CXXFLAGS=-Wall -fPIC -I$(ROOT)/include -I$(ROOT)/lib/pugixml/src/ CXXFLAGS=-Wall -fPIC -I$(ROOT)/include -I$(ROOT)/lib/pugixml/src/
LDFLAGS=
ifneq ($(OPENSSL3),)
# OpenSSL 1.1.0 compat
CXXFLAGS += -DOPENSSL_API_COMPAT=0x10100000L
CXXFLAGS += -I/tmp/openssl3/usr/include/ -I/tmp/openssl3/usr/include/x86_64-linux-gnu
LDFLAGS += -L/tmp/openssl3/usr/lib/x86_64-linux-gnu -L/tmp/openssl3/usr/lib/x86_64-linux-gnu/ossl-modules
endif
STATIC_DEP= STATIC_DEP=
LDFLAGS += -L$(ROOT) -lcrypto -lzip -lz -lcurl LDFLAGS += -L$(ROOT) -lcrypto -lzip -lz -lcurl

View File

@ -31,6 +31,8 @@
#include <cctype> #include <cctype>
#include <locale> #include <locale>
#define OPENSSL_NO_DEPRECATED 1
#include <openssl/rand.h> #include <openssl/rand.h>
#include <openssl/pkcs12.h> #include <openssl/pkcs12.h>
#include <openssl/evp.h> #include <openssl/evp.h>
@ -302,40 +304,68 @@ std::string DRMProcessorClientImpl::sendHTTPRequest(const std::string& URL, cons
return std::string((char*)replyData.data(), replyData.length()); return std::string((char*)replyData.data(), replyData.length());
} }
void DRMProcessorClientImpl::padWithPKCS1(unsigned char* out, unsigned int outLength,
const unsigned char* in, unsigned int inLength)
{
if (outLength < (inLength + 3))
EXCEPTION(gourou::CLIENT_RSA_ERROR, "Not enough space for PKCS1 padding");
/*
PKCS1v5 Padding is :
0x00 0x01 0xff * n 0x00 dataIn
*/
memset(out, 0xFF, outLength);
out[0] = 0x0;
out[1] = 0x1;
out[outLength - inLength - 1] = 0x00;
memcpy(&out[outLength - inLength], in, inLength);
}
void DRMProcessorClientImpl::RSAPrivateEncrypt(const unsigned char* RSAKey, unsigned int RSAKeyLength, void DRMProcessorClientImpl::RSAPrivateEncrypt(const unsigned char* RSAKey, unsigned int RSAKeyLength,
const RSA_KEY_TYPE keyType, const std::string& password, const RSA_KEY_TYPE keyType, const std::string& password,
const unsigned char* data, unsigned dataLength, const unsigned char* data, unsigned dataLength,
unsigned char* res) unsigned char* res)
{ {
PKCS12 * pkcs12; PKCS12 * pkcs12;
EVP_PKEY* pkey; EVP_PKEY_CTX *ctx;
X509* cert; EVP_PKEY* pkey = NULL;
STACK_OF(X509)* ca; size_t outlen;
RSA * rsa; unsigned char* tmp;
int ret;
pkcs12 = d2i_PKCS12(NULL, &RSAKey, RSAKeyLength); pkcs12 = d2i_PKCS12(NULL, &RSAKey, RSAKeyLength);
if (!pkcs12) if (!pkcs12)
EXCEPTION(gourou::CLIENT_INVALID_PKCS12, ERR_error_string(ERR_get_error(), NULL)); EXCEPTION(gourou::CLIENT_INVALID_PKCS12, ERR_error_string(ERR_get_error(), NULL));
PKCS12_parse(pkcs12, password.c_str(), &pkey, &cert, &ca); if (PKCS12_parse(pkcs12, password.c_str(), &pkey, NULL, NULL) <= 0)
if (!pkey)
EXCEPTION(gourou::CLIENT_INVALID_PKCS12, ERR_error_string(ERR_get_error(), NULL)); EXCEPTION(gourou::CLIENT_INVALID_PKCS12, ERR_error_string(ERR_get_error(), NULL));
rsa = EVP_PKEY_get1_RSA(pkey); outlen = EVP_PKEY_get_size(pkey);
int ret = RSA_private_encrypt(dataLength, data, res, rsa, RSA_PKCS1_PADDING); ctx = EVP_PKEY_CTX_new(pkey, NULL);
if (ret < 0) /* Use RSA private key */
if (EVP_PKEY_decrypt_init(ctx) <= 0)
EXCEPTION(gourou::CLIENT_RSA_ERROR, ERR_error_string(ERR_get_error(), NULL)); EXCEPTION(gourou::CLIENT_RSA_ERROR, ERR_error_string(ERR_get_error(), NULL));
if (gourou::logLevel >= gourou::DEBUG) if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_NO_PADDING) <= 0)
{ EXCEPTION(gourou::CLIENT_RSA_ERROR, ERR_error_string(ERR_get_error(), NULL));
printf("Encrypted : ");
for(int i=0; i<ret; i++) tmp = (unsigned char*)malloc(outlen);
printf("%02x ", res[i]);
printf("\n"); /* PKCS1 functions are no more exported */
} padWithPKCS1(tmp, outlen, data, dataLength);
ret = EVP_PKEY_decrypt(ctx, res, &outlen, tmp, outlen);
EVP_PKEY_CTX_free(ctx);
free(tmp);
if (ret <= 0)
EXCEPTION(gourou::CLIENT_RSA_ERROR, ERR_error_string(ERR_get_error(), NULL));
} }
void DRMProcessorClientImpl::RSAPrivateDecrypt(const unsigned char* RSAKey, unsigned int RSAKeyLength, void DRMProcessorClientImpl::RSAPrivateDecrypt(const unsigned char* RSAKey, unsigned int RSAKeyLength,
@ -343,27 +373,41 @@ void DRMProcessorClientImpl::RSAPrivateDecrypt(const unsigned char* RSAKey, unsi
const unsigned char* data, unsigned dataLength, const unsigned char* data, unsigned dataLength,
unsigned char* res) unsigned char* res)
{ {
BIO* mem=BIO_new_mem_buf(RSAKey, RSAKeyLength); BIO* mem = BIO_new_mem_buf(RSAKey, RSAKeyLength);
PKCS8_PRIV_KEY_INFO* p8inf = d2i_PKCS8_PRIV_KEY_INFO_bio(mem, NULL); PKCS8_PRIV_KEY_INFO* p8inf = d2i_PKCS8_PRIV_KEY_INFO_bio(mem, NULL);
if (!p8inf) if (!p8inf)
EXCEPTION(gourou::CLIENT_INVALID_PKCS8, ERR_error_string(ERR_get_error(), NULL)); EXCEPTION(gourou::CLIENT_INVALID_PKCS8, ERR_error_string(ERR_get_error(), NULL));
EVP_PKEY_CTX *ctx;
EVP_PKEY* pkey = EVP_PKCS82PKEY(p8inf); EVP_PKEY* pkey = EVP_PKCS82PKEY(p8inf);
RSA * rsa; size_t outlen = dataLength;
int ret; int ret;
rsa = EVP_PKEY_get1_RSA(pkey); if (!pkey)
EXCEPTION(gourou::CLIENT_INVALID_PKCS8, ERR_error_string(ERR_get_error(), NULL));
ret = RSA_private_decrypt(dataLength, data, res, rsa, RSA_NO_PADDING); ctx = EVP_PKEY_CTX_new(pkey, NULL);
if (ret < 0) if (EVP_PKEY_decrypt_init(ctx) <= 0)
EXCEPTION(gourou::CLIENT_RSA_ERROR, ERR_error_string(ERR_get_error(), NULL));
if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_NO_PADDING) <= 0)
EXCEPTION(gourou::CLIENT_RSA_ERROR, ERR_error_string(ERR_get_error(), NULL));
ret = EVP_PKEY_decrypt(ctx, res, &outlen, data, dataLength);
PKCS8_PRIV_KEY_INFO_free(p8inf);
EVP_PKEY_CTX_free(ctx);
BIO_free(mem);
if (ret <= 0)
EXCEPTION(gourou::CLIENT_RSA_ERROR, ERR_error_string(ERR_get_error(), NULL)); EXCEPTION(gourou::CLIENT_RSA_ERROR, ERR_error_string(ERR_get_error(), NULL));
if (gourou::logLevel >= gourou::LG_LOG_DEBUG) if (gourou::logLevel >= gourou::LG_LOG_DEBUG)
{ {
printf("Decrypted : "); printf("Decrypted : ");
for(int i=0; i<ret; i++) for(int i=0; i<(int)outlen; i++)
printf("%02x ", res[i]); printf("%02x ", res[i]);
printf("\n"); printf("\n");
} }
@ -374,61 +418,79 @@ void DRMProcessorClientImpl::RSAPublicEncrypt(const unsigned char* RSAKey, unsig
const unsigned char* data, unsigned dataLength, const unsigned char* data, unsigned dataLength,
unsigned char* res) unsigned char* res)
{ {
size_t outlen;
X509 * x509 = d2i_X509(0, &RSAKey, RSAKeyLength); X509 * x509 = d2i_X509(0, &RSAKey, RSAKeyLength);
if (!x509) if (!x509)
EXCEPTION(gourou::CLIENT_INVALID_CERTIFICATE, "Invalid certificate"); EXCEPTION(gourou::CLIENT_INVALID_CERTIFICATE, "Invalid certificate");
EVP_PKEY_CTX *ctx;
EVP_PKEY * evpKey = X509_get_pubkey(x509); EVP_PKEY * evpKey = X509_get_pubkey(x509);
RSA* rsa = EVP_PKEY_get1_RSA(evpKey);
EVP_PKEY_free(evpKey);
if (!rsa) if (!evpKey)
EXCEPTION(gourou::CLIENT_NO_PRIV_KEY, "No private key in certificate"); EXCEPTION(gourou::CLIENT_NO_PUB_KEY, "No public key in certificate");
ctx = EVP_PKEY_CTX_new(evpKey, NULL);
if (EVP_PKEY_encrypt_init(ctx) <= 0)
EXCEPTION(gourou::CLIENT_RSA_ERROR, ERR_error_string(ERR_get_error(), NULL));
if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0)
EXCEPTION(gourou::CLIENT_RSA_ERROR, ERR_error_string(ERR_get_error(), NULL));
int ret = EVP_PKEY_encrypt(ctx, res, &outlen, data, dataLength);
EVP_PKEY_CTX_free(ctx);
int ret = RSA_public_encrypt(dataLength, data, res, rsa, RSA_PKCS1_PADDING);
if (ret < 0) if (ret < 0)
EXCEPTION(gourou::CLIENT_RSA_ERROR, ERR_error_string(ERR_get_error(), NULL)); EXCEPTION(gourou::CLIENT_RSA_ERROR, ERR_error_string(ERR_get_error(), NULL));
EVP_PKEY_free(evpKey);
} }
void* DRMProcessorClientImpl::generateRSAKey(int keyLengthBits) void* DRMProcessorClientImpl::generateRSAKey(int keyLengthBits)
{ {
BIGNUM * bn = BN_new(); BIGNUM * bn = BN_new();
RSA * rsa = RSA_new(); EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
EVP_PKEY *key = NULL;
BN_set_word(bn, 0x10001); BN_set_word(bn, 0x10001);
RSA_generate_key_ex(rsa, keyLengthBits, bn, 0);
EVP_PKEY_keygen_init(ctx);
EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, keyLengthBits);
EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING);
EVP_PKEY_CTX_set1_rsa_keygen_pubexp(ctx, bn);
EVP_PKEY_keygen(ctx, &key);
EVP_PKEY_CTX_free(ctx);
BN_free(bn); BN_free(bn);
return rsa; return key;
} }
void DRMProcessorClientImpl::destroyRSAHandler(void* handler) void DRMProcessorClientImpl::destroyRSAHandler(void* handler)
{ {
RSA_free((RSA*)handler); free(handler);
} }
void DRMProcessorClientImpl::extractRSAPublicKey(void* handler, unsigned char** keyOut, unsigned int* keyOutLength) void DRMProcessorClientImpl::extractRSAPublicKey(void* handler, unsigned char** keyOut, unsigned int* keyOutLength)
{ {
EVP_PKEY * evpKey = EVP_PKEY_new();
EVP_PKEY_set1_RSA(evpKey, (RSA*)handler);
X509_PUBKEY *x509_pubkey = 0; X509_PUBKEY *x509_pubkey = 0;
X509_PUBKEY_set(&x509_pubkey, evpKey); X509_PUBKEY_set(&x509_pubkey, (EVP_PKEY*)handler);
*keyOutLength = i2d_X509_PUBKEY(x509_pubkey, keyOut); *keyOutLength = i2d_X509_PUBKEY(x509_pubkey, keyOut);
X509_PUBKEY_free(x509_pubkey); X509_PUBKEY_free(x509_pubkey);
EVP_PKEY_free(evpKey);
} }
void DRMProcessorClientImpl::extractRSAPrivateKey(void* handler, unsigned char** keyOut, unsigned int* keyOutLength) void DRMProcessorClientImpl::extractRSAPrivateKey(void* handler, unsigned char** keyOut, unsigned int* keyOutLength)
{ {
EVP_PKEY * evpKey = EVP_PKEY_new(); PKCS8_PRIV_KEY_INFO * privKey = EVP_PKEY2PKCS8((EVP_PKEY*)handler);
EVP_PKEY_set1_RSA(evpKey, (RSA*)handler);
PKCS8_PRIV_KEY_INFO * privKey = EVP_PKEY2PKCS8(evpKey);
*keyOutLength = i2d_PKCS8_PRIV_KEY_INFO(privKey, keyOut); *keyOutLength = i2d_PKCS8_PRIV_KEY_INFO(privKey, keyOut);
PKCS8_PRIV_KEY_INFO_free(privKey); PKCS8_PRIV_KEY_INFO_free(privKey);
EVP_PKEY_free(evpKey);
} }
void DRMProcessorClientImpl::extractCertificate(const unsigned char* RSAKey, unsigned int RSAKeyLength, void DRMProcessorClientImpl::extractCertificate(const unsigned char* RSAKey, unsigned int RSAKeyLength,
@ -438,12 +500,11 @@ void DRMProcessorClientImpl::extractCertificate(const unsigned char* RSAKey, uns
PKCS12 * pkcs12; PKCS12 * pkcs12;
EVP_PKEY* pkey = 0; EVP_PKEY* pkey = 0;
X509* cert = 0; X509* cert = 0;
STACK_OF(X509)* ca;
pkcs12 = d2i_PKCS12(NULL, &RSAKey, RSAKeyLength); pkcs12 = d2i_PKCS12(NULL, &RSAKey, RSAKeyLength);
if (!pkcs12) if (!pkcs12)
EXCEPTION(gourou::CLIENT_INVALID_PKCS12, ERR_error_string(ERR_get_error(), NULL)); EXCEPTION(gourou::CLIENT_INVALID_PKCS12, ERR_error_string(ERR_get_error(), NULL));
PKCS12_parse(pkcs12, password.c_str(), &pkey, &cert, &ca); PKCS12_parse(pkcs12, password.c_str(), &pkey, &cert, NULL);
if (!cert) if (!cert)
EXCEPTION(gourou::CLIENT_INVALID_PKCS12, ERR_error_string(ERR_get_error(), NULL)); EXCEPTION(gourou::CLIENT_INVALID_PKCS12, ERR_error_string(ERR_get_error(), NULL));

View File

@ -127,6 +127,10 @@ public:
int wbits=-15, int compressionLevel=8); int wbits=-15, int compressionLevel=8);
private: private:
void padWithPKCS1(unsigned char* out, unsigned int outLength,
const unsigned char* in, unsigned int inLength);
#if OPENSSL_VERSION_MAJOR >= 3 #if OPENSSL_VERSION_MAJOR >= 3
OSSL_PROVIDER *legacy, *deflt; OSSL_PROVIDER *legacy, *deflt;
#else #else