From a9fa49c806cc47a0bca894ae26cb04a2c40006f8 Mon Sep 17 00:00:00 2001 From: caihy0414 Date: Fri, 8 Dec 2023 18:41:44 +0800 Subject: [PATCH] Support openssl V3.0.12 --- CMake/Dependencies/libopenssl-CMakeLists.txt | 8 +- CMake/Utilities.cmake | 1 + CMakeLists.txt | 7 +- src/source/Crypto/Crypto.c | 5 ++ src/source/Crypto/Crypto.h | 6 +- src/source/Crypto/Dtls.h | 1 + src/source/Crypto/Dtls_mbedtls.c | 9 ++ src/source/Crypto/Dtls_openssl.c | 88 +++++++++++++++++--- 8 files changed, 106 insertions(+), 19 deletions(-) mode change 100644 => 100755 CMake/Dependencies/libopenssl-CMakeLists.txt mode change 100644 => 100755 CMake/Utilities.cmake mode change 100644 => 100755 CMakeLists.txt mode change 100644 => 100755 src/source/Crypto/Crypto.c mode change 100644 => 100755 src/source/Crypto/Crypto.h mode change 100644 => 100755 src/source/Crypto/Dtls.h mode change 100644 => 100755 src/source/Crypto/Dtls_mbedtls.c mode change 100644 => 100755 src/source/Crypto/Dtls_openssl.c diff --git a/CMake/Dependencies/libopenssl-CMakeLists.txt b/CMake/Dependencies/libopenssl-CMakeLists.txt old mode 100644 new mode 100755 index 1180b72f9c..b02bc39566 --- a/CMake/Dependencies/libopenssl-CMakeLists.txt +++ b/CMake/Dependencies/libopenssl-CMakeLists.txt @@ -2,6 +2,12 @@ cmake_minimum_required(VERSION 3.6.3) project(libopenssl-download NONE) +if(BUILD_OLD_OPENSSL_VERSION) + SET(OPENSSL_GIT_TAG "OpenSSL_1_1_1t") +else() + SET(OPENSSL_GIT_TAG "openssl-3.0.12") +endif() + if (WIN32) find_program(MAKE_EXE NAMES nmake) SET(CONFIGURE_COMMAND perl ${CMAKE_CURRENT_BINARY_DIR}/build/src/project_libopenssl/Configure VC-WIN64A no-asm --prefix=${OPEN_SRC_INSTALL_PREFIX} --openssldir=${OPEN_SRC_INSTALL_PREFIX}) @@ -26,7 +32,7 @@ endif() include(ExternalProject) ExternalProject_Add(project_libopenssl GIT_REPOSITORY https://github.com/openssl/openssl.git - GIT_TAG OpenSSL_1_1_1t + GIT_TAG ${OPENSSL_GIT_TAG} PREFIX ${CMAKE_CURRENT_BINARY_DIR}/build CONFIGURE_COMMAND ${CONFIGURE_COMMAND} BUILD_COMMAND ${MAKE_EXE} diff --git a/CMake/Utilities.cmake b/CMake/Utilities.cmake old mode 100644 new mode 100755 index 35c9e82446..334dd27873 --- a/CMake/Utilities.cmake +++ b/CMake/Utilities.cmake @@ -32,6 +32,7 @@ function(build_dependency lib_name) library_found NAMES ${lib_file_name} PATHS ${OPEN_SRC_INSTALL_PREFIX}/lib + PATHS ${OPEN_SRC_INSTALL_PREFIX}/lib64 NO_DEFAULT_PATH) if(library_found) message(STATUS "${lib_name} already built") diff --git a/CMakeLists.txt b/CMakeLists.txt old mode 100644 new mode 100755 index 7a4943fd89..b4f6e09068 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,6 +20,7 @@ option(BUILD_SAMPLE "Build available samples" ON) option(ENABLE_DATA_CHANNEL "Enable support for data channel" ON) option(ENABLE_KVS_THREADPOOL "Enable support for KVS thread pool in signaling" ON) option(INSTRUMENTED_ALLOCATORS "Enable memory instrumentation" OFF) +option(BUILD_OLD_OPENSSL_VERSION "Builds openssl version 1.1.1t. Note this went EOL in Sept 2023" OFF) # Developer Flags option(BUILD_TEST "Build the testing tree." OFF) @@ -124,7 +125,7 @@ if(BUILD_DEPENDENCIES) file(MAKE_DIRECTORY ${OPEN_SRC_INSTALL_PREFIX}) endif() - set(ENV{PKG_CONFIG_PATH} "$ENV{PKG_CONFIG_PATH}:${OPEN_SRC_INSTALL_PREFIX}/lib/pkgconfig") + set(ENV{PKG_CONFIG_PATH} "$ENV{PKG_CONFIG_PATH}:${OPEN_SRC_INSTALL_PREFIX}/lib/pkgconfig:${OPEN_SRC_INSTALL_PREFIX}/lib64/pkgconfig") set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} ${OPEN_SRC_INSTALL_PREFIX}) message(STATUS "Begin building dependencies.") @@ -139,7 +140,8 @@ if(BUILD_DEPENDENCIES) if (USE_OPENSSL) set(BUILD_ARGS -DBUILD_STATIC_LIBS=${BUILD_STATIC_LIBS} -DBUILD_OPENSSL_PLATFORM=${BUILD_OPENSSL_PLATFORM} - -DOPENSSL_EXTRA=${OPENSSL_EXTRA}) + -DOPENSSL_EXTRA=${OPENSSL_EXTRA} + -DBUILD_OLD_OPENSSL_VERSION=${BUILD_OLD_OPENSSL_VERSION}) build_dependency(openssl ${BUILD_ARGS}) set(OPENSSL_ROOT_DIR ${OPEN_SRC_INSTALL_PREFIX}) elseif(USE_MBEDTLS) @@ -264,7 +266,6 @@ link_directories(${OPEN_SRC_INSTALL_PREFIX}/lib64) if("${CMAKE_C_COMPILER_ID}" MATCHES "GNU|Clang") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") - if(CODE_COVERAGE) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0 -g -fprofile-arcs -ftest-coverage") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --coverage") diff --git a/src/source/Crypto/Crypto.c b/src/source/Crypto/Crypto.c old mode 100644 new mode 100755 index c98ef648dc..ad91f5d5b0 --- a/src/source/Crypto/Crypto.c +++ b/src/source/Crypto/Crypto.c @@ -1,6 +1,11 @@ #define LOG_CLASS "Crypto" #include "../Include_i.h" +STATUS md5Digest(PBYTE inputStringBuff, UINT64 length, PBYTE outputBuff) +{ + return md5DigestCalculation(inputStringBuff, length, outputBuff); +} + STATUS createRtcCertificate(PRtcCertificate* ppRtcCertificate) { ENTERS(); diff --git a/src/source/Crypto/Crypto.h b/src/source/Crypto/Crypto.h old mode 100644 new mode 100755 index 81db2a51b6..d92530bfb6 --- a/src/source/Crypto/Crypto.h +++ b/src/source/Crypto/Crypto.h @@ -7,11 +7,13 @@ extern "C" { #endif +STATUS md5Digest(PBYTE, UINT64, PBYTE); + #ifdef KVS_USE_OPENSSL #define KVS_RSA_F4 RSA_F4 #define KVS_MD5_DIGEST_LENGTH MD5_DIGEST_LENGTH #define KVS_SHA1_DIGEST_LENGTH SHA_DIGEST_LENGTH -#define KVS_MD5_DIGEST(m, mlen, ob) MD5((m), (mlen), (ob)); +#define KVS_MD5_DIGEST(m, mlen, ob) md5Digest((m), (mlen), (ob)); #define KVS_SHA1_HMAC(k, klen, m, mlen, ob, plen) \ CHK(NULL != HMAC(EVP_sha1(), (k), (INT32) (klen), (m), (mlen), (ob), (plen)), STATUS_HMAC_GENERATION_ERROR); #define KVS_CRYPTO_INIT() \ @@ -35,7 +37,7 @@ typedef enum { #define KVS_RSA_F4 0x10001L #define KVS_MD5_DIGEST_LENGTH 16 #define KVS_SHA1_DIGEST_LENGTH 20 -#define KVS_MD5_DIGEST(m, mlen, ob) mbedtls_md5_ret((m), (mlen), (ob)); +#define KVS_MD5_DIGEST(m, mlen, ob) md5Digest((m), (mlen), (ob)); #define KVS_SHA1_HMAC(k, klen, m, mlen, ob, plen) \ CHK(0 == mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA1), (k), (klen), (m), (mlen), (ob)), STATUS_HMAC_GENERATION_ERROR); \ *(plen) = mbedtls_md_get_size(mbedtls_md_info_from_type(MBEDTLS_MD_SHA1)); diff --git a/src/source/Crypto/Dtls.h b/src/source/Crypto/Dtls.h old mode 100644 new mode 100755 index 7f0fbd9532..a2b9261010 --- a/src/source/Crypto/Dtls.h +++ b/src/source/Crypto/Dtls.h @@ -180,6 +180,7 @@ STATUS dtlsSessionShutdown(PDtlsSession); STATUS dtlsSessionOnOutBoundData(PDtlsSession, UINT64, DtlsSessionOutboundPacketFunc); STATUS dtlsSessionOnStateChange(PDtlsSession, UINT64, DtlsSessionOnStateChange); STATUS dtlsSessionHandshakeInThread(PDtlsSession, BOOL); +STATUS md5DigestCalculation(PBYTE, UINT64, PBYTE); /******** Internal Functions **********/ STATUS dtlsValidateRtcCertificates(PRtcCertificate, PUINT32); diff --git a/src/source/Crypto/Dtls_mbedtls.c b/src/source/Crypto/Dtls_mbedtls.c old mode 100644 new mode 100755 index 29dca1a8c6..88b4b18d3d --- a/src/source/Crypto/Dtls_mbedtls.c +++ b/src/source/Crypto/Dtls_mbedtls.c @@ -8,6 +8,15 @@ mbedtls_ssl_srtp_profile DTLS_SRTP_SUPPORTED_PROFILES[] = { MBEDTLS_TLS_SRTP_UNSET, }; +STATUS md5DigestCalculation(PBYTE inputStringBuff, UINT64 length, PBYTE outputBuff) +{ + STATUS retStatus = STATUS_SUCCESS; + CHK_ERR(inputStringBuff != NULL && outputBuff != NULL, STATUS_INVALID_ARG, "Invalid input or output buffer"); + CHK_ERR(!mbedtls_md5_ret(inputStringBuff, length, outputBuff), STATUS_INTERNAL_ERROR, "MD5 calculation failed"); +CleanUp: + return retStatus; +} + STATUS createDtlsSession(PDtlsSessionCallbacks pDtlsSessionCallbacks, TIMER_QUEUE_HANDLE timerQueueHandle, INT32 certificateBits, BOOL generateRSACertificate, PRtcCertificate pRtcCertificates, PDtlsSession* ppDtlsSession) { diff --git a/src/source/Crypto/Dtls_openssl.c b/src/source/Crypto/Dtls_openssl.c old mode 100644 new mode 100755 index 7b1ccf2b17..e839d1e256 --- a/src/source/Crypto/Dtls_openssl.c +++ b/src/source/Crypto/Dtls_openssl.c @@ -44,6 +44,38 @@ STATUS dtlsCertificateFingerprint(X509* pCertificate, PCHAR pBuff) return retStatus; } +STATUS md5DigestCalculation(PBYTE inputStringBuff, UINT64 length, PBYTE outputBuff) +{ + STATUS retStatus = STATUS_SUCCESS; +#if (OPENSSL_VERSION_NUMBER >= 0x30000000L) + EVP_MD_CTX* mdctx = NULL; + const EVP_MD* md = NULL; +#endif + + CHK_ERR(inputStringBuff != NULL && outputBuff != NULL, STATUS_INVALID_ARG, "Invalid input or output buffer"); + +#if (OPENSSL_VERSION_NUMBER >= 0x30000000L) + CHK_ERR(md = EVP_MD_fetch(NULL, "MD5", NULL), STATUS_INTERNAL_ERROR, "Failed to fetch MD5 provider"); + CHK_ERR(mdctx = EVP_MD_CTX_new(), STATUS_INTERNAL_ERROR, "Failed to create message digest context"); + CHK_ERR(EVP_DigestInit_ex(mdctx, md, NULL), STATUS_INTERNAL_ERROR, "Message digest initialization failed."); + CHK_ERR(EVP_DigestUpdate(mdctx, inputStringBuff, length), STATUS_INTERNAL_ERROR, "Message digest update failed"); + CHK_ERR(EVP_DigestFinal_ex(mdctx, outputBuff, NULL), STATUS_INTERNAL_ERROR, "Message digest finalization failed"); +#else + MD5(inputStringBuff, length, outputBuff); +#endif + +CleanUp: +#if (OPENSSL_VERSION_NUMBER >= 0x30000000L) + if (mdctx != NULL) { + EVP_MD_CTX_free(mdctx); + } + if (md != NULL) { + EVP_MD_free((EVP_MD*) md); + } +#endif + return retStatus; +} + STATUS dtlsTransmissionTimerCallback(UINT32 timerID, UINT64 currentTime, UINT64 customData) { UNUSED_PARAM(timerID); @@ -104,21 +136,42 @@ STATUS createCertificateAndKey(INT32 certificateBits, BOOL generateRSACertificat { ENTERS(); STATUS retStatus = STATUS_SUCCESS; + X509_NAME* pX509Name = NULL; + UINT64 certSn; +#if (OPENSSL_VERSION_NUMBER >= 0x30000000L) + EVP_PKEY_CTX* pctx = NULL; +#else BIGNUM* pBne = NULL; RSA* pRsa = NULL; - X509_NAME* pX509Name = NULL; UINT32 eccGroup = 0; EC_KEY* eccKey = NULL; - UINT64 certSn; - +#endif CHK(ppCert != NULL && ppPkey != NULL, STATUS_NULL_ARG); CHK((*ppPkey = EVP_PKEY_new()) != NULL, STATUS_CERTIFICATE_GENERATION_FAILED); CHK_STATUS(dtlsFillPseudoRandomBits((PBYTE) &certSn, SIZEOF(UINT64))); +#if (OPENSSL_VERSION_NUMBER >= 0x30000000L) + DLOGI("Detected openssl version greater than or equal to 3.0.0"); + if (generateRSACertificate) { + DLOGI("Using RSA"); + CHK_ERR(pctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL), STATUS_CERTIFICATE_GENERATION_FAILED, "Error creating EVP_PKEY_CTX for RSA"); + CHK_ERR(EVP_PKEY_keygen_init(pctx) > 0, STATUS_CERTIFICATE_GENERATION_FAILED, "Error initializing RSA keygen"); + CHK_ERR(EVP_PKEY_CTX_set_rsa_keygen_bits(pctx, certificateBits) > 0, STATUS_CERTIFICATE_GENERATION_FAILED, "Error setting RSA key size"); + CHK_ERR(EVP_PKEY_keygen(pctx, ppPkey) > 0, STATUS_CERTIFICATE_GENERATION_FAILED, "RSA Key generation errored"); + } else { + DLOGI("Using EC"); + CHK_ERR(pctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL), STATUS_CERTIFICATE_GENERATION_FAILED, "Error creating EVP_PKEY_CTX for EC"); + CHK_ERR(EVP_PKEY_keygen_init(pctx) > 0, STATUS_CERTIFICATE_GENERATION_FAILED, "Error initializing EC keygen"); + CHK_ERR(EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, OBJ_sn2nid("prime256v1")) > 0, STATUS_CERTIFICATE_GENERATION_FAILED, + "Error setting curve name"); + CHK_ERR(EVP_PKEY_keygen(pctx, ppPkey) > 0, STATUS_CERTIFICATE_GENERATION_FAILED, "EC Key generation errored"); + } + EVP_PKEY_CTX_free(pctx); +#else + DLOGI("Detected older version"); if (generateRSACertificate) { CHK((pBne = BN_new()) != NULL, STATUS_CERTIFICATE_GENERATION_FAILED); CHK(BN_set_word(pBne, KVS_RSA_F4) != 0, STATUS_CERTIFICATE_GENERATION_FAILED); - CHK((pRsa = RSA_new()) != NULL, STATUS_CERTIFICATE_GENERATION_FAILED); CHK(RSA_generate_key_ex(pRsa, certificateBits, pBne, NULL) != 0, STATUS_CERTIFICATE_GENERATION_FAILED); CHK((EVP_PKEY_assign_RSA(*ppPkey, pRsa)) != 0, STATUS_CERTIFICATE_GENERATION_FAILED); @@ -133,6 +186,7 @@ STATUS createCertificateAndKey(INT32 certificateBits, BOOL generateRSACertificat CHK(EC_KEY_generate_key(eccKey) != 0, STATUS_CERTIFICATE_GENERATION_FAILED); CHK(EVP_PKEY_assign_EC_KEY(*ppPkey, eccKey) != 0, STATUS_CERTIFICATE_GENERATION_FAILED); } +#endif CHK((*ppCert = X509_new()) != NULL, STATUS_CERTIFICATE_GENERATION_FAILED); X509_set_version(*ppCert, 2); @@ -149,14 +203,17 @@ STATUS createCertificateAndKey(INT32 certificateBits, BOOL generateRSACertificat CHK(X509_sign(*ppCert, *ppPkey, EVP_sha1()) != 0, STATUS_CERTIFICATE_GENERATION_FAILED); CleanUp: - if (pBne != NULL) { - BN_free(pBne); - } - +#if (OPENSSL_VERSION_NUMBER < 0x30000000L) + if (pBne != NULL) { + BN_free(pBne); + } +#endif if (STATUS_FAILED(retStatus)) { +#if (OPENSSL_VERSION_NUMBER < 0x30000000L) if (pRsa != NULL) { RSA_free(pRsa); } +#endif freeCertificateAndKey(ppCert, ppPkey); } @@ -169,7 +226,6 @@ STATUS createSslCtx(PDtlsSessionCertificateInfo pCertificates, UINT32 certCount, ENTERS(); STATUS retStatus = STATUS_SUCCESS; SSL_CTX* pSslCtx = NULL; - EC_KEY* pEcKey = NULL; UINT32 i; CHK(pCertificates != NULL && ppSslCtx != NULL, STATUS_NULL_ARG); @@ -194,12 +250,18 @@ STATUS createSslCtx(PDtlsSessionCertificateInfo pCertificates, UINT32 certCount, CHK(pSslCtx != NULL, STATUS_SSL_CTX_CREATION_FAILED); // Version greater than or equal to 1.0.2 +#if (OPENSSL_VERSION_NUMBER < 0x30000000L) #if (OPENSSL_VERSION_NUMBER >= 0x10002000L) SSL_CTX_set_ecdh_auto(pSslCtx, TRUE); #else CHK((ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1)) != NULL, STATUS_SSL_CTX_CREATION_FAILED); CHK(SSL_CTX_set_tmp_ecdh(pSslCtx, ecdh) == 1, STATUS_SSL_CTX_CREATION_FAILED); #endif +#else + // https://www.openssl.org/docs/man3.0/man3/EC_KEY_new_by_curve_name.html -- indicates that EC_KEY_new_by_curve_name and SSL_CTX_set_tmp_ecdh are + // deprecated https://www.openssl.org/docs/man1.1.1/man3/SSL_CTX_set1_groups.html + CHK(SSL_CTX_set1_groups_list(pSslCtx, "prime256v1") == 1, STATUS_SSL_CTX_CREATION_FAILED); +#endif SSL_CTX_set_verify(pSslCtx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, dtlsCertificateVerifyCallback); CHK(SSL_CTX_set_tlsext_use_srtp(pSslCtx, "SRTP_AES128_CM_SHA1_32:SRTP_AES128_CM_SHA1_80") == 0, STATUS_SSL_CTX_CREATION_FAILED); @@ -217,10 +279,6 @@ STATUS createSslCtx(PDtlsSessionCertificateInfo pCertificates, UINT32 certCount, SSL_CTX_free(pSslCtx); } - if (pEcKey != NULL) { - EC_KEY_free(pEcKey); - } - LEAVES(); return retStatus; } @@ -900,7 +958,11 @@ STATUS dtlsSessionVerifyRemoteCertificateFingerprint(PDtlsSession pDtlsSession, MUTEX_LOCK(pDtlsSession->sslLock); locked = TRUE; +#if (OPENSSL_VERSION_NUMBER >= 0x30000000L) + CHK((pRemoteCertificate = SSL_get1_peer_certificate(pDtlsSession->pSsl)) != NULL, STATUS_INTERNAL_ERROR); +#else CHK((pRemoteCertificate = SSL_get_peer_certificate(pDtlsSession->pSsl)) != NULL, STATUS_INTERNAL_ERROR); +#endif CHK_STATUS(dtlsCertificateFingerprint(pRemoteCertificate, actualFingerprint)); CHK(STRCMP(pExpectedFingerprint, actualFingerprint) == 0, STATUS_SSL_REMOTE_CERTIFICATE_VERIFICATION_FAILED);