1
0
mirror of https://github.com/gnss-sdr/gnss-sdr synced 2024-10-29 22:26:22 +00:00

Look for OpenSSL in the first place, fallback to GnuTLS if not found

Fix test building in some environments
This commit is contained in:
Carles Fernandez 2024-06-29 11:10:35 +02:00
parent 359693c0e8
commit db5466832c
No known key found for this signature in database
GPG Key ID: 4C583C52B0C3877D
10 changed files with 410 additions and 429 deletions

View File

@ -2196,99 +2196,9 @@ endif()
################################################################################
# GnuTLS - https://www.gnutls.org/
# OpenSSL https://www.openssl.org/ or GnuTLS - https://www.gnutls.org/
################################################################################
find_package(GnuTLS)
set_package_properties(GnuTLS PROPERTIES
URL "https://www.gnutls.org/"
PURPOSE "Used for the SUPL protocol implementation."
TYPE REQUIRED
)
if(GnuTLS_FOUND AND GNUTLS_VERSION_STRING)
set_package_properties(GnuTLS PROPERTIES
DESCRIPTION "Transport Layer Security Library (found: v${GNUTLS_VERSION_STRING})"
)
else()
set_package_properties(GnuTLS PROPERTIES
DESCRIPTION "Transport Layer Security Library"
)
endif()
find_library(GNUTLS_OPENSSL_LIBRARY
NAMES gnutls-openssl libgnutls-openssl.so.27
PATHS
/usr/lib
/usr/lib64
/usr/lib/x86_64-linux-gnu
/usr/lib/aarch64-linux-gnu
/usr/lib/arm-linux-gnueabihf
/usr/lib/arm-linux-gnueabi
/usr/lib/i386-linux-gnu
/usr/lib/alpha-linux-gnu
/usr/lib/hppa-linux-gnu
/usr/lib/i386-gnu
/usr/lib/i686-gnu
/usr/lib/i686-linux-gnu
/usr/lib/x86_64-kfreebsd-gnu
/usr/lib/i686-kfreebsd-gnu
/usr/lib/m68k-linux-gnu
/usr/lib/mips-linux-gnu
/usr/lib/mips64el-linux-gnuabi64
/usr/lib/mipsel-linux-gnu
/usr/lib/powerpc-linux-gnu
/usr/lib/powerpc-linux-gnuspe
/usr/lib/powerpc64-linux-gnu
/usr/lib/powerpc64le-linux-gnu
/usr/lib/s390x-linux-gnu
/usr/lib/riscv64-linux-gnu
/usr/lib/sparc64-linux-gnu
/usr/lib/x86_64-linux-gnux32
/usr/lib/sh4-linux-gnu
/usr/lib/loongarch64-linux-gnu
/usr/local/lib
/usr/local/lib64
/opt/local/lib
)
#if(NOT GNUTLS_OPENSSL_LIBRARY)
if(GNUTLS_OPENSSL_LIBRARY)
if(GnuTLS_FOUND)
message(STATUS " But it was not built with openssl compatibility.")
endif()
message(STATUS " Looking for OpenSSL instead...")
if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
set(OPENSSL_ROOT_DIR /usr/local/opt/openssl) # Trick for Homebrew
endif()
find_package(OpenSSL)
set_package_properties(OpenSSL PROPERTIES
URL "https://www.openssl.org"
DESCRIPTION "Cryptography and SSL/TLS Toolkit (found: v${OPENSSL_VERSION})"
PURPOSE "Used for the SUPL protocol implementation."
TYPE REQUIRED
)
message("OPENSSL_FOUND: " ${OPENSSL_FOUND})
if(OPENSSL_FOUND)
set_package_properties(GnuTLS PROPERTIES
PURPOSE "Not found, but OpenSSL can replace it."
)
set(GNUTLS_INCLUDE_DIR ${OPENSSL_INCLUDE_DIR})
set(GNUTLS_LIBRARIES "")
set(GNUTLS_OPENSSL_LIBRARY ${OPENSSL_SSL_LIBRARY})
else()
message(" The GnuTLS library with openssl compatibility enabled has not been found.")
message(" You can try to install the required libraries by typing:")
if(${CMAKE_SYSTEM_NAME} MATCHES "Linux|kFreeBSD|GNU")
if(${LINUX_DISTRIBUTION} MATCHES "Fedora" OR ${LINUX_DISTRIBUTION} MATCHES "Red Hat")
message(" sudo yum install openssl-devel")
else()
message(" sudo apt-get install libgnutls28-dev")
endif()
endif()
if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
message(" 'sudo port install gnutls', if you are using Macports, or")
message(" 'brew install openssl', if you are using Homebrew.")
endif()
message(FATAL_ERROR "GnuTLS libraries with openssl compatibility are required to build gnss-sdr")
endif()
endif()
include(GnssSdrCrypto)

View File

@ -0,0 +1,152 @@
# GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
# This file is part of GNSS-SDR.
#
# SPDX-FileCopyrightText: 2024 C. Fernandez-Prades cfernandez(at)cttc.es
# SPDX-License-Identifier: BSD-3-Clause
################################################################################
# OpenSSL https://www.openssl.org/
################################################################################
if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
set(OPENSSL_ROOT_DIR /usr/local/opt/openssl) # Trick for Homebrew
endif()
find_package(OpenSSL)
set_package_properties(OpenSSL
PROPERTIES
URL "https://www.openssl.org"
PURPOSE "Used for the OSNMA and SUPL protocol implementations."
TYPE REQUIRED
)
if(OPENSSL_FOUND)
set_package_properties(OpenSSL
PROPERTIES
DESCRIPTION "Cryptography and SSL/TLS Toolkit (found: v${OPENSSL_VERSION})"
)
else()
set_package_properties(OpenSSL
PROPERTIES
DESCRIPTION "OpenSSL has not been found, but GnuTLS with openssl compatibility can replace it"
)
################################################################################
# GnuTLS - https://www.gnutls.org/
################################################################################
find_package(GnuTLS)
set_package_properties(GnuTLS PROPERTIES
URL "https://www.gnutls.org/"
PURPOSE "Used for the OSNMA and SUPL protocol implementations."
TYPE REQUIRED
)
if(GnuTLS_FOUND AND GNUTLS_VERSION_STRING)
set_package_properties(GnuTLS PROPERTIES
DESCRIPTION "Transport Layer Security Library (found: v${GNUTLS_VERSION_STRING})"
)
else()
set_package_properties(GnuTLS PROPERTIES
DESCRIPTION "Transport Layer Security Library"
)
endif()
find_library(GNUTLS_OPENSSL_LIBRARY
NAMES gnutls-openssl libgnutls-openssl.so.27
PATHS
/usr/lib
/usr/lib64
/usr/lib/x86_64-linux-gnu
/usr/lib/aarch64-linux-gnu
/usr/lib/arm-linux-gnueabihf
/usr/lib/arm-linux-gnueabi
/usr/lib/i386-linux-gnu
/usr/lib/alpha-linux-gnu
/usr/lib/hppa-linux-gnu
/usr/lib/i386-gnu
/usr/lib/i686-gnu
/usr/lib/i686-linux-gnu
/usr/lib/x86_64-kfreebsd-gnu
/usr/lib/i686-kfreebsd-gnu
/usr/lib/m68k-linux-gnu
/usr/lib/mips-linux-gnu
/usr/lib/mips64el-linux-gnuabi64
/usr/lib/mipsel-linux-gnu
/usr/lib/powerpc-linux-gnu
/usr/lib/powerpc-linux-gnuspe
/usr/lib/powerpc64-linux-gnu
/usr/lib/powerpc64le-linux-gnu
/usr/lib/s390x-linux-gnu
/usr/lib/riscv64-linux-gnu
/usr/lib/sparc64-linux-gnu
/usr/lib/x86_64-linux-gnux32
/usr/lib/sh4-linux-gnu
/usr/lib/loongarch64-linux-gnu
/usr/local/lib
/usr/local/lib64
/opt/local/lib
)
if(NOT GNUTLS_OPENSSL_LIBRARY)
message(" The GnuTLS library with openssl compatibility enabled has not been found.")
message(" You can try to install the required libraries by typing:")
if(${CMAKE_SYSTEM_NAME} MATCHES "Linux|kFreeBSD|GNU")
if(${LINUX_DISTRIBUTION} MATCHES "Fedora" OR ${LINUX_DISTRIBUTION} MATCHES "Red Hat")
message(" sudo yum install openssl-devel")
else()
message(" sudo apt-get install libgnutls28-dev")
endif()
endif()
if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
message(" 'sudo port install gnutls', if you are using Macports, or")
message(" 'brew install openssl', if you are using Homebrew.")
endif()
message(FATAL_ERROR "OpenSSL or the GnuTLS libraries with openssl compatibility are required to build gnss-sdr")
endif()
endif()
################################################################################
function(link_to_crypto_dependencies target)
if(OPENSSL_FOUND)
if(TARGET OpenSSL::SSL)
target_link_libraries(core_system_parameters
PUBLIC
OpenSSL::SSL
)
if(TARGET OpenSSL::Crypto)
target_link_libraries(core_system_parameters
PUBLIC
OpenSSL::Crypto
)
endif()
else()
target_link_libraries(core_system_parameters
PUBLIC
${OPENSSL_LIBRARIES}
"${OPENSSL_CRYPTO_LIBRARIES}"
)
target_include_directories(core_system_parameters
PUBLIC
${OPENSSL_INCLUDE_DIR}
)
endif()
if(OPENSSL_VERSION)
if(OPENSSL_VERSION VERSION_GREATER "3.0.0")
target_compile_definitions(${target} PUBLIC -DUSE_OPENSSL_3=1)
else()
if(NOT OPENSSL_VERSION VERSION_LESS "1.1.1")
target_compile_definitions(${target} PUBLIC -DUSE_OPENSSL_111=1)
else()
endif()
endif()
else()
endif()
else() # GnuTLS
target_link_libraries(core_system_parameters
PUBLIC
${GNUTLS_LIBRARIES}
${GNUTLS_OPENSSL_LIBRARY}
)
target_include_directories(core_system_parameters
PUBLIC
${GNUTLS_INCLUDE_DIR}
)
target_compile_definitions(${target} PUBLIC -DUSE_GNUTLS_FALLBACK=1)
endif()
endfunction()

View File

@ -55,6 +55,15 @@ All notable changes to GNSS-SDR will be documented in this file.
This change has a downside in maintainability, since the source code becomes
plagued with preprocessor directives required to maintain compatibility both
with gflags and glog, and with Abseil.
- Historically, GNSS-SDR linked against the GnuTLS library for cryptographic
functions. If GnuTLS was not found, then the building system looked for and
linked against OpenSSL as a fallback. This was due to the OpenSSL 1.x dual
license scheme, which was incompatible with GPL v3.0 license, preventing it
from being a mandatory dependency for GNSS-SDR in most GNU/Linux
distributions. This issue was solved with the release of OpenSSL 3.0.0, which
transitioned to the Apache License 2.0, fully compatible with GPL v3.0.
Accordingly, the GNSS-SDR building system now looks for OpenSSL in the first
place and, if not found, then it looks for GnuTLS as a fallback.
### Improvements in Usability:

View File

@ -46,16 +46,9 @@ if(CMAKE_C_COMPILER_ID MATCHES "Clang|GNU" AND (CMAKE_VERSION VERSION_GREATER "3
target_compile_options(core_libs_supl PUBLIC $<$<COMPILE_LANGUAGE:C>:${MY_C_FLAGS}>)
endif()
if(OPENSSL_FOUND)
target_compile_definitions(core_libs_supl PUBLIC -DUSE_OPENSSL_FALLBACK=1)
endif()
message("OPENSSL_FOUND: " ${OPENSSL_FOUND})
message("USE_OPENSSL_FALLBACK:" ${USE_OPENSSL_FALLBACK})
target_link_libraries(core_libs_supl
PUBLIC
${GNUTLS_LIBRARIES}
${GNUTLS_OPENSSL_LIBRARY}
)
# links to the appropriate library and defines
# USE_GNUTLS_FALLBACK, USE_OPENSSL_3, or USE_OPENSSL_111 accordingly.
link_to_crypto_dependencies(core_libs_supl)
target_include_directories(core_libs_supl
PUBLIC

View File

@ -24,18 +24,18 @@
#define EXPORT
#endif
// clang-format off
#if USE_OPENSSL_FALLBACK
#include <openssl/crypto.h>
#include <openssl/x509.h>
#include <openssl/pem.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#else
#if USE_GNUTLS_FALLBACK
#include <gnutls/gnutls.h>
#include <gnutls/compat.h>
#include <gnutls/crypto.h>
#include <gnutls/openssl.h>
#include <gnutls/x509.h>
#else
#include <openssl/crypto.h>
#include <openssl/x509.h>
#include <openssl/pem.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#endif
// clang-format on
#include <PDU.h>

View File

@ -124,7 +124,7 @@ target_link_libraries(core_system_parameters
Boost::date_time
Boost::serialization
PRIVATE
Pugixml::pugixml
Pugixml::pugixml
)
if(ENABLE_GLOG_AND_GFLAGS)
@ -140,50 +140,9 @@ target_include_directories(core_system_parameters
${GNSSSDR_SOURCE_DIR}/src/algorithms/libs
)
if(OPENSSL_FOUND)
message("OPENSSL_FOUND: " ${OPENSSL_FOUND})
if(TARGET OpenSSL::SSL)
target_link_libraries(core_system_parameters
PUBLIC
OpenSSL::SSL
)
else()
target_link_libraries(core_system_parameters
PUBLIC
${OPENSSL_LIBRARIES}
)
target_include_directories(core_system_parameters
PUBLIC
${OPENSSL_INCLUDE_DIR}
)
endif()
if(OPENSSL_VERSION)
message("OPENSSL_VERSION: " ${OPENSSL_VERSION})
if(OPENSSL_VERSION VERSION_GREATER "3.0.0")
target_compile_definitions(core_system_parameters PUBLIC -DUSE_OPENSSL_FALLBACK=1 -DUSE_OPENSSL_3=1)
message("USE_OPENSSL_3: " ${DUSE_OPENSSL_3})
message("USE_OPENSSL_FALLBACK:" ${USE_OPENSSL_FALLBACK})
else()
if(NOT OPENSSL_VERSION VERSION_LESS "1.1.1")
target_compile_definitions(core_system_parameters PRIVATE -DUSE_OPENSSL_FALLBACK=1 -DUSE_OPENSSL_111=1)
endif()
endif()
endif()
else()
target_link_libraries(core_system_parameters
PUBLIC
${GNUTLS_LIBRARIES}
${GNUTLS_OPENSSL_LIBRARY}
)
target_include_directories(core_system_parameters
PUBLIC
${GNUTLS_INCLUDE_DIR}
)
endif()
if(OPENSSL_FOUND)
target_compile_definitions(core_system_parameters PUBLIC -DUSE_OPENSSL_FALLBACK=1)
endif()
# links to the appropriate library and defines
# USE_GNUTLS_FALLBACK, USE_OPENSSL_3, or USE_OPENSSL_111 accordingly.
link_to_crypto_dependencies(core_system_parameters)
if(ENABLE_CLANG_TIDY)
if(CLANG_TIDY_EXE)

View File

@ -25,7 +25,12 @@
#include <iostream>
#include <iterator>
#if USE_OPENSSL_FALLBACK
#if USE_GNUTLS_FALLBACK
#include <cstring>
#include <gnutls/abstract.h>
#include <gnutls/crypto.h>
#include <gnutls/x509.h>
#else // OpenSSL
#include <openssl/cmac.h>
#include <openssl/ecdsa.h>
#include <openssl/hmac.h>
@ -40,14 +45,9 @@
#include <openssl/param_build.h>
#include <openssl/params.h>
#define OPENSSL_ENGINE nullptr
#else
#else // OpenSSL 1.x
#include <openssl/sha.h>
#endif
#else // GnuTLS
#include <cstring>
#include <gnutls/abstract.h>
#include <gnutls/crypto.h>
#include <gnutls/x509.h>
#endif
#if USE_GLOG_AND_GFLAGS
@ -59,28 +59,28 @@
Gnss_Crypto::Gnss_Crypto()
{
#if USE_OPENSSL_FALLBACK
#if USE_GNUTLS_FALLBACK
gnutls_global_init();
#else // OpenSSL
#if !(USE_OPENSSL_3 || USE_OPENSSL_111)
LOG(WARNING) << "The OpenSSL library version you are linking against is too old for some OSNMA functions."
<< " Please do not trust OSNMA ouputs or upgrade your system to a newer version of OpenSSL"
<< " and rebuild GNSS-SDR against it.";
#endif
#else // GnuTLS
gnutls_global_init();
#endif
}
Gnss_Crypto::Gnss_Crypto(const std::string& certFilePath, const std::string& merkleTreePath)
{
#if USE_OPENSSL_FALLBACK
#if USE_GNUTLS_FALLBACK
gnutls_global_init();
#else // OpenSSL
#if !(USE_OPENSSL_3 || USE_OPENSSL_111)
LOG(WARNING) << "The OpenSSL library version you are linking against is too old for some OSNMA functions."
<< " Please do not trust OSNMA ouputs or upgrade your system to a newer version of OpenSSL"
<< " and rebuild GNSS-SDR against it.";
#endif
#else // GnuTLS
gnutls_global_init();
#endif
if (!readPublicKeyFromCRT(certFilePath))
{
@ -92,31 +92,30 @@ Gnss_Crypto::Gnss_Crypto(const std::string& certFilePath, const std::string& mer
Gnss_Crypto::~Gnss_Crypto()
{
#if USE_OPENSSL_FALLBACK
#if USE_OPENSSL_3
#else
if (d_PublicKey != nullptr)
{
EC_KEY_free(d_PublicKey);
}
#endif
#else // GnuTLS
#if USE_GNUTLS_FALLBACK
if (d_PublicKey != nullptr)
{
gnutls_pubkey_deinit(d_PublicKey);
d_PublicKey = nullptr;
}
gnutls_global_deinit();
#else // OpenSSL
#if !USE_OPENSSL_3
if (d_PublicKey != nullptr)
{
EC_KEY_free(d_PublicKey);
}
#endif
#endif
}
bool Gnss_Crypto::have_public_key() const
{
#if USE_OPENSSL_FALLBACK
return (d_PublicKey != nullptr);
#else // GnuTLS
#if USE_GNUTLS_FALLBACK
return (d_PublicKey != gnutls_pubkey_t{});
#else // OpenSSL
return (d_PublicKey != nullptr);
#endif
}
@ -260,7 +259,15 @@ void Gnss_Crypto::read_merkle_xml(const std::string& merkleFilePath)
std::vector<uint8_t> Gnss_Crypto::computeSHA256(const std::vector<uint8_t>& input) const
{
std::vector<uint8_t> output(32); // SHA256 hash size
#if USE_OPENSSL_FALLBACK
#if USE_GNUTLS_FALLBACK
std::vector<uint8_t> output_aux(32);
gnutls_hash_hd_t hashHandle;
gnutls_hash_init(&hashHandle, GNUTLS_DIG_SHA256);
gnutls_hash(hashHandle, input.data(), input.size());
gnutls_hash_output(hashHandle, output_aux.data());
output = output_aux;
gnutls_hash_deinit(hashHandle, output_aux.data());
#else // OpenSSL
#if USE_OPENSSL_3
unsigned int mdLen;
EVP_MD_CTX* mdCtx = EVP_MD_CTX_new();
@ -283,20 +290,12 @@ std::vector<uint8_t> Gnss_Crypto::computeSHA256(const std::vector<uint8_t>& inpu
return output;
}
EVP_MD_CTX_free(mdCtx);
#else
#else // OpenSSL 1.x
SHA256_CTX sha256Context;
SHA256_Init(&sha256Context);
SHA256_Update(&sha256Context, input.data(), input.size());
SHA256_Final(output.data(), &sha256Context);
#endif
#else // GnuTLS
std::vector<uint8_t> output_aux(32);
gnutls_hash_hd_t hashHandle;
gnutls_hash_init(&hashHandle, GNUTLS_DIG_SHA256);
gnutls_hash(hashHandle, input.data(), input.size());
gnutls_hash_output(hashHandle, output_aux.data());
output = output_aux;
gnutls_hash_deinit(hashHandle, output_aux.data());
#endif
return output;
}
@ -305,7 +304,15 @@ std::vector<uint8_t> Gnss_Crypto::computeSHA256(const std::vector<uint8_t>& inpu
std::vector<uint8_t> Gnss_Crypto::computeSHA3_256(const std::vector<uint8_t>& input) const
{
std::vector<uint8_t> output(32); // SHA256 hash size
#if USE_OPENSSL_FALLBACK
#if USE_GNUTLS_FALLBACK
std::vector<uint8_t> output_aux(32);
gnutls_hash_hd_t hashHandle;
gnutls_hash_init(&hashHandle, GNUTLS_DIG_SHA3_256);
gnutls_hash(hashHandle, input.data(), input.size());
gnutls_hash_output(hashHandle, output_aux.data());
output = output_aux;
gnutls_hash_deinit(hashHandle, output_aux.data());
#else // OpenSSL
#if USE_OPENSSL_3 || USE_OPENSSL_111
EVP_MD_CTX* mdctx = EVP_MD_CTX_new();
const EVP_MD* md = EVP_sha3_256();
@ -314,21 +321,13 @@ std::vector<uint8_t> Gnss_Crypto::computeSHA3_256(const std::vector<uint8_t>& in
EVP_DigestUpdate(mdctx, input.data(), input.size());
EVP_DigestFinal_ex(mdctx, output.data(), nullptr);
EVP_MD_CTX_free(mdctx);
#else
#else // OpenSSL 1.x
// SHA3-256 not implemented in OpenSSL 1.0, it was introduced in OpenSSL 1.1.1
if (!input.empty())
{
// do nothing
}
#endif
#else // GnuTLS
std::vector<uint8_t> output_aux(32);
gnutls_hash_hd_t hashHandle;
gnutls_hash_init(&hashHandle, GNUTLS_DIG_SHA3_256);
gnutls_hash(hashHandle, input.data(), input.size());
gnutls_hash_output(hashHandle, output_aux.data());
output = output_aux;
gnutls_hash_deinit(hashHandle, output_aux.data());
#endif
return output;
}
@ -337,7 +336,15 @@ std::vector<uint8_t> Gnss_Crypto::computeSHA3_256(const std::vector<uint8_t>& in
std::vector<uint8_t> Gnss_Crypto::computeHMAC_SHA_256(const std::vector<uint8_t>& key, const std::vector<uint8_t>& input) const
{
std::vector<uint8_t> output(32);
#if USE_OPENSSL_FALLBACK
#if USE_GNUTLS_FALLBACK
std::vector<uint8_t> output_aux(32);
gnutls_hmac_hd_t hmac;
gnutls_hmac_init(&hmac, GNUTLS_MAC_SHA256, key.data(), key.size());
gnutls_hmac(hmac, input.data(), input.size());
gnutls_hmac_output(hmac, output_aux.data());
output = output_aux;
gnutls_hmac_deinit(hmac, output_aux.data());
#else // OpenSSL
#if USE_OPENSSL_3
std::vector<uint8_t> hmac(EVP_MAX_MD_SIZE);
size_t output_length = 0;
@ -393,7 +400,7 @@ std::vector<uint8_t> Gnss_Crypto::computeHMAC_SHA_256(const std::vector<uint8_t>
EVP_MAC_free(mac);
hmac.resize(output_length);
output = hmac;
#else
#else // OpenSSL 1.x
unsigned int outputLength = EVP_MAX_MD_SIZE;
unsigned char* result = HMAC(EVP_sha256(), key.data(), key.size(), input.data(), input.size(), output.data(), &outputLength);
if (result == nullptr)
@ -405,14 +412,6 @@ std::vector<uint8_t> Gnss_Crypto::computeHMAC_SHA_256(const std::vector<uint8_t>
// Resize the output vector to the actual length of the HMAC-SHA256 output
output.resize(outputLength);
#endif
#else // GnuTLS
std::vector<uint8_t> output_aux(32);
gnutls_hmac_hd_t hmac;
gnutls_hmac_init(&hmac, GNUTLS_MAC_SHA256, key.data(), key.size());
gnutls_hmac(hmac, input.data(), input.size());
gnutls_hmac_output(hmac, output_aux.data());
output = output_aux;
gnutls_hmac_deinit(hmac, output_aux.data());
#endif
return output;
}
@ -421,7 +420,18 @@ std::vector<uint8_t> Gnss_Crypto::computeHMAC_SHA_256(const std::vector<uint8_t>
std::vector<uint8_t> Gnss_Crypto::computeCMAC_AES(const std::vector<uint8_t>& key, const std::vector<uint8_t>& input) const
{
std::vector<uint8_t> output(16);
#if USE_OPENSSL_FALLBACK
#if USE_GNUTLS_FALLBACK
gnutls_cipher_hd_t cipher;
std::vector<uint8_t> mac(16);
std::vector<uint8_t> message = input;
gnutls_datum_t key_data = {const_cast<uint8_t*>(key.data()), static_cast<unsigned int>(key.size())};
gnutls_cipher_init(&cipher, GNUTLS_CIPHER_AES_128_CBC, &key_data, nullptr);
gnutls_cipher_set_iv(cipher, nullptr, 16); // Set IV to zero
gnutls_cipher_encrypt(cipher, message.data(), message.size()); // Encrypt the message with AES-128
gnutls_cipher_tag(cipher, mac.data(), mac.size()); // Get the CMAC-AES tag
output = mac;
gnutls_cipher_deinit(cipher);
#else // OpenSSL
#if USE_OPENSSL_3
std::vector<uint8_t> aux(EVP_MAX_MD_SIZE); // CMAC-AES output size
size_t output_length = 0;
@ -479,7 +489,7 @@ std::vector<uint8_t> Gnss_Crypto::computeCMAC_AES(const std::vector<uint8_t>& ke
aux.resize(output_length);
output = aux;
#else
#else // OpenSSL 1.x
std::vector<uint8_t> mac(16); // CMAC-AES output size
// Create CMAC context
@ -495,17 +505,6 @@ std::vector<uint8_t> Gnss_Crypto::computeCMAC_AES(const std::vector<uint8_t>& ke
output = mac;
#endif
#else // GnuTLS
gnutls_cipher_hd_t cipher;
std::vector<uint8_t> mac(16);
std::vector<uint8_t> message = input;
gnutls_datum_t key_data = {const_cast<uint8_t*>(key.data()), static_cast<unsigned int>(key.size())};
gnutls_cipher_init(&cipher, GNUTLS_CIPHER_AES_128_CBC, &key_data, nullptr);
gnutls_cipher_set_iv(cipher, nullptr, 16); // Set IV to zero
gnutls_cipher_encrypt(cipher, message.data(), message.size()); // Encrypt the message with AES-128
gnutls_cipher_tag(cipher, mac.data(), mac.size()); // Get the CMAC-AES tag
output = mac;
gnutls_cipher_deinit(cipher);
#endif
return output;
}
@ -526,27 +525,7 @@ void Gnss_Crypto::readPublicKeyFromPEM(const std::string& pemFilePath)
return;
}
std::string pemContent((std::istreambuf_iterator<char>(pemFile)), std::istreambuf_iterator<char>());
#if USE_OPENSSL_FALLBACK
// Create a BIO object from the string data
BIO* bio = BIO_new_mem_buf(pemContent.c_str(), pemContent.length());
if (!bio)
{
std::cerr << "OpenSSL: error creating a BIO object with data read from file " << pemFilePath << ". Aborting import" << std::endl;
return;
}
#if USE_OPENSSL_3
d_PublicKey = PEM_read_bio_PUBKEY(bio, nullptr, nullptr, nullptr);
#else
d_PublicKey = PEM_read_bio_EC_PUBKEY(bio, nullptr, nullptr, nullptr);
#endif
BIO_free(bio);
if (d_PublicKey == nullptr)
{
std::cerr << "OpenSSL: error reading the OSNMA Public Key from file " << pemFilePath << ". Aborting import" << std::endl;
LOG(INFO) << "OpenSSL: error reading the OSNMA Public Key from file " << pemFilePath << ". Aborting import";
return;
}
#else // GnuTLS
#if USE_GNUTLS_FALLBACK
// Import the PEM data
gnutls_datum_t pemDatum = {const_cast<unsigned char*>(reinterpret_cast<unsigned char*>(pemContent.data())), static_cast<unsigned int>(pemContent.size())};
gnutls_pubkey_t pubkey;
@ -566,6 +545,26 @@ void Gnss_Crypto::readPublicKeyFromPEM(const std::string& pemFilePath)
pubkey_copy(pubkey, &d_PublicKey);
gnutls_pubkey_deinit(pubkey);
#else // OpenSSL
// Create a BIO object from the string data
BIO* bio = BIO_new_mem_buf(pemContent.c_str(), pemContent.length());
if (!bio)
{
std::cerr << "OpenSSL: error creating a BIO object with data read from file " << pemFilePath << ". Aborting import" << std::endl;
return;
}
#if USE_OPENSSL_3
d_PublicKey = PEM_read_bio_PUBKEY(bio, nullptr, nullptr, nullptr);
#else // OpenSSL 1.x
d_PublicKey = PEM_read_bio_EC_PUBKEY(bio, nullptr, nullptr, nullptr);
#endif
BIO_free(bio);
if (d_PublicKey == nullptr)
{
std::cerr << "OpenSSL: error reading the OSNMA Public Key from file " << pemFilePath << ". Aborting import" << std::endl;
LOG(INFO) << "OpenSSL: error reading the OSNMA Public Key from file " << pemFilePath << ". Aborting import";
return;
}
#endif
std::cout << "OSNMA Public key successfully read from file " << pemFilePath << std::endl;
LOG(INFO) << "OSNMA Public key successfully read from file " << pemFilePath;
@ -574,57 +573,7 @@ void Gnss_Crypto::readPublicKeyFromPEM(const std::string& pemFilePath)
bool Gnss_Crypto::readPublicKeyFromCRT(const std::string& crtFilePath)
{
#if USE_OPENSSL_FALLBACK
// Open the .crt file
std::ifstream crtFile(crtFilePath, std::ios::binary);
if (!crtFile.is_open())
{
std::cerr << "Unable to open file: " << crtFilePath << std::endl;
return false;
}
// Read certificate
std::vector<char> buffer((std::istreambuf_iterator<char>(crtFile)), std::istreambuf_iterator<char>());
BIO* bio = BIO_new_mem_buf(buffer.data(), buffer.size());
if (!bio)
{
std::cerr << "Unable to create BIO for file: " << crtFilePath << std::endl;
return false;
}
X509* cert = PEM_read_bio_X509(bio, nullptr, nullptr, nullptr);
if (!cert)
{
std::cerr << "Unable to read certificate from file: " << crtFilePath << std::endl;
BIO_free(bio);
return false;
}
// Read the public key from the certificate
EVP_PKEY* pubkey = X509_get_pubkey(cert);
#if USE_OPENSSL_3
if (!pubkey)
{
std::cerr << "Failed to extract the public key" << std::endl;
X509_free(cert);
return false;
}
pubkey_copy(pubkey, &d_PublicKey);
EVP_PKEY_free(pubkey);
#else
EC_KEY* ec_pubkey = EVP_PKEY_get1_EC_KEY(pubkey);
EVP_PKEY_free(pubkey);
if (!ec_pubkey)
{
std::cerr << "Failed to extract the public key" << std::endl;
X509_free(cert);
return false;
}
pubkey_copy(ec_pubkey, &d_PublicKey);
EC_KEY_free(ec_pubkey);
#endif
BIO_free(bio);
X509_free(cert);
#else // GnuTLS
#if USE_GNUTLS_FALLBACK
// Open the .crt file
std::ifstream crtFile(crtFilePath, std::ios::binary);
if (!crtFile.is_open())
@ -664,6 +613,56 @@ bool Gnss_Crypto::readPublicKeyFromCRT(const std::string& crtFilePath)
pubkey_copy(pubkey, &d_PublicKey);
gnutls_x509_crt_deinit(cert);
gnutls_pubkey_deinit(pubkey);
#else // OpenSSL
// Open the .crt file
std::ifstream crtFile(crtFilePath, std::ios::binary);
if (!crtFile.is_open())
{
std::cerr << "Unable to open file: " << crtFilePath << std::endl;
return false;
}
// Read certificate
std::vector<char> buffer((std::istreambuf_iterator<char>(crtFile)), std::istreambuf_iterator<char>());
BIO* bio = BIO_new_mem_buf(buffer.data(), buffer.size());
if (!bio)
{
std::cerr << "Unable to create BIO for file: " << crtFilePath << std::endl;
return false;
}
X509* cert = PEM_read_bio_X509(bio, nullptr, nullptr, nullptr);
if (!cert)
{
std::cerr << "Unable to read certificate from file: " << crtFilePath << std::endl;
BIO_free(bio);
return false;
}
// Read the public key from the certificate
EVP_PKEY* pubkey = X509_get_pubkey(cert);
#if USE_OPENSSL_3
if (!pubkey)
{
std::cerr << "Failed to extract the public key" << std::endl;
X509_free(cert);
return false;
}
pubkey_copy(pubkey, &d_PublicKey);
EVP_PKEY_free(pubkey);
#else // OpenSSL 1.x
EC_KEY* ec_pubkey = EVP_PKEY_get1_EC_KEY(pubkey);
EVP_PKEY_free(pubkey);
if (!ec_pubkey)
{
std::cerr << "Failed to extract the public key" << std::endl;
X509_free(cert);
return false;
}
pubkey_copy(ec_pubkey, &d_PublicKey);
EC_KEY_free(ec_pubkey);
#endif
BIO_free(bio);
X509_free(cert);
#endif
std::cout << "OSNMA Public key successfully read from file " << crtFilePath << std::endl;
LOG(INFO) << "OSNMA Public key successfully read from file " << crtFilePath;
@ -680,7 +679,32 @@ bool Gnss_Crypto::verify_signature(const std::vector<uint8_t>& message, const st
return false;
}
bool success = false;
#if USE_OPENSSL_FALLBACK
#if USE_GNUTLS_FALLBACK
// Convert signature to DER format
std::vector<uint8_t> der_sig;
if (!convert_raw_to_der_ecdsa(signature, der_sig))
{
std::cerr << "Failed to convert raw ECDSA signature to DER format" << std::endl;
return false;
}
// Prepare the digest datum
gnutls_datum_t digest_data = {const_cast<unsigned char*>(digest.data()), static_cast<unsigned int>(digest.size())};
gnutls_datum_t der_sig_data = {der_sig.data(), static_cast<unsigned int>(der_sig.size())};
// Verify the DER-encoded signature
int ret = gnutls_pubkey_verify_hash2(d_PublicKey, GNUTLS_SIGN_ECDSA_SHA256, 0, &digest_data, &der_sig_data);
success = (ret >= 0);
if (success)
{
LOG(INFO) << "GnuTLS: OSNMA signature authenticated successfully";
}
else
{
std::cerr << "GnuTLS: OSNMA message authentication failed: " << gnutls_strerror(ret) << std::endl;
LOG(WARNING) << "GnuTLS: OSNMA message authentication failed: " << gnutls_strerror(ret);
}
#else // OpenSSL
#if USE_OPENSSL_3
EVP_PKEY_CTX* ctx;
ctx = EVP_PKEY_CTX_new(d_PublicKey, nullptr);
@ -753,7 +777,7 @@ bool Gnss_Crypto::verify_signature(const std::vector<uint8_t>& message, const st
std::cerr << "OpenSSL: OSNMA message authentication failed: " << err << std::endl;
LOG(WARNING) << "OpenSSL: OSNMA message authentication failed: " << err;
}
#else
#else // OpenSSL 1.x
std::vector<uint8_t> der_sig;
if (!convert_raw_to_der_ecdsa(signature, der_sig))
{
@ -777,31 +801,6 @@ bool Gnss_Crypto::verify_signature(const std::vector<uint8_t>& message, const st
LOG(WARNING) << "OpenSSL: OSNMA message authentication failed";
}
#endif
#else // GnuTLS
// Convert signature to DER format
std::vector<uint8_t> der_sig;
if (!convert_raw_to_der_ecdsa(signature, der_sig))
{
std::cerr << "Failed to convert raw ECDSA signature to DER format" << std::endl;
return false;
}
// Prepare the digest datum
gnutls_datum_t digest_data = {const_cast<unsigned char*>(digest.data()), static_cast<unsigned int>(digest.size())};
gnutls_datum_t der_sig_data = {der_sig.data(), static_cast<unsigned int>(der_sig.size())};
// Verify the DER-encoded signature
int ret = gnutls_pubkey_verify_hash2(d_PublicKey, GNUTLS_SIGN_ECDSA_SHA256, 0, &digest_data, &der_sig_data);
success = (ret >= 0);
if (success)
{
LOG(INFO) << "GnuTLS: OSNMA signature authenticated successfully";
}
else
{
std::cerr << "GnuTLS: OSNMA message authentication failed: " << gnutls_strerror(ret) << std::endl;
LOG(WARNING) << "GnuTLS: OSNMA message authentication failed: " << gnutls_strerror(ret);
}
#endif
return success;
}
@ -845,7 +844,21 @@ std::vector<uint8_t> Gnss_Crypto::getMerkleRoot(const std::vector<std::vector<ui
void Gnss_Crypto::set_public_key(const std::vector<uint8_t>& publicKey)
{
#if USE_OPENSSL_FALLBACK
#if USE_GNUTLS_FALLBACK
gnutls_pubkey_t pubkey;
gnutls_datum_t pemDatum = {const_cast<unsigned char*>(publicKey.data()), static_cast<unsigned int>(publicKey.size())};
gnutls_pubkey_init(&pubkey);
int ret = gnutls_pubkey_import(pubkey, &pemDatum, GNUTLS_X509_FMT_PEM);
if (ret != GNUTLS_E_SUCCESS)
{
gnutls_pubkey_deinit(pubkey);
std::cerr << "GnuTLS: error setting the public key" << std::endl;
std::cerr << "GnuTLS error: " << gnutls_strerror(ret) << std::endl;
return;
}
pubkey_copy(pubkey, &d_PublicKey);
gnutls_pubkey_deinit(pubkey);
#else // OpenSSL
BIO* bio = nullptr;
EVP_PKEY* pkey = nullptr;
bio = BIO_new_mem_buf(publicKey.data(), publicKey.size());
@ -876,22 +889,8 @@ void Gnss_Crypto::set_public_key(const std::vector<uint8_t>& publicKey)
return;
}
EC_KEY_free(ec_pkey);
#endif
#endif // OpenSSL 1.x
EVP_PKEY_free(pkey);
#else // GnuTLS
gnutls_pubkey_t pubkey;
gnutls_datum_t pemDatum = {const_cast<unsigned char*>(publicKey.data()), static_cast<unsigned int>(publicKey.size())};
gnutls_pubkey_init(&pubkey);
int ret = gnutls_pubkey_import(pubkey, &pemDatum, GNUTLS_X509_FMT_PEM);
if (ret != GNUTLS_E_SUCCESS)
{
gnutls_pubkey_deinit(pubkey);
std::cerr << "GnuTLS: error setting the public key" << std::endl;
std::cerr << "GnuTLS error: " << gnutls_strerror(ret) << std::endl;
return;
}
pubkey_copy(pubkey, &d_PublicKey);
gnutls_pubkey_deinit(pubkey);
#endif
LOG(INFO) << "OSNMA Public Key successfully set up.";
}
@ -945,7 +944,40 @@ bool Gnss_Crypto::convert_raw_to_der_ecdsa(const std::vector<uint8_t>& raw_signa
}
#if USE_OPENSSL_FALLBACK
#if USE_GNUTLS_FALLBACK // GnuTLS-specific functions
bool Gnss_Crypto::pubkey_copy(gnutls_pubkey_t src, gnutls_pubkey_t* dest)
{
gnutls_datum_t key_datum;
// Export the public key from src to memory
int ret = gnutls_pubkey_export2(src, GNUTLS_X509_FMT_PEM, &key_datum);
if (ret < 0)
{
gnutls_free(key_datum.data);
return false;
}
// Initialize dest
ret = gnutls_pubkey_init(dest);
if (ret < 0)
{
gnutls_free(key_datum.data);
return false;
}
// Import the public key data from key_datum to dest
ret = gnutls_pubkey_import(*dest, &key_datum, GNUTLS_X509_FMT_PEM);
gnutls_free(key_datum.data);
if (ret < 0)
{
gnutls_pubkey_deinit(*dest);
return false;
}
return true;
}
#else // OpenSSL
#if USE_OPENSSL_3
bool Gnss_Crypto::pubkey_copy(EVP_PKEY* src, EVP_PKEY** dest)
{
@ -1036,41 +1068,5 @@ bool Gnss_Crypto::pubkey_copy(EC_KEY* src, EC_KEY** dest)
return true;
}
#endif
#else // GnuTLS-specific functions
bool Gnss_Crypto::pubkey_copy(gnutls_pubkey_t src, gnutls_pubkey_t* dest)
{
gnutls_datum_t key_datum;
// Export the public key from src to memory
int ret = gnutls_pubkey_export2(src, GNUTLS_X509_FMT_PEM, &key_datum);
if (ret < 0)
{
gnutls_free(key_datum.data);
return false;
}
// Initialize dest
ret = gnutls_pubkey_init(dest);
if (ret < 0)
{
gnutls_free(key_datum.data);
return false;
}
// Import the public key data from key_datum to dest
ret = gnutls_pubkey_import(*dest, &key_datum, GNUTLS_X509_FMT_PEM);
gnutls_free(key_datum.data);
if (ret < 0)
{
gnutls_pubkey_deinit(*dest);
return false;
}
return true;
}
#endif

View File

@ -22,10 +22,10 @@
#include <cstdint>
#include <string>
#include <vector>
#if USE_OPENSSL_FALLBACK
#include <openssl/ec.h>
#else
#if USE_GNUTLS_FALLBACK
#include <gnutls/gnutls.h>
#else // OpenSSL
#include <openssl/ec.h>
#endif
/** \addtogroup Core
@ -60,7 +60,10 @@ private:
bool readPublicKeyFromCRT(const std::string& crtFilePath);
bool convert_raw_to_der_ecdsa(const std::vector<uint8_t>& raw_signature, std::vector<uint8_t>& der_signature) const;
std::vector<uint8_t> convert_from_hex_str(const std::string& input) const;
#if USE_OPENSSL_FALLBACK
#if USE_GNUTLS_FALLBACK
bool pubkey_copy(gnutls_pubkey_t src, gnutls_pubkey_t* dest);
gnutls_pubkey_t d_PublicKey{};
#else // OpenSSL
#if USE_OPENSSL_3
bool pubkey_copy(EVP_PKEY* src, EVP_PKEY** dest);
EVP_PKEY* d_PublicKey{};
@ -68,9 +71,6 @@ private:
bool pubkey_copy(EC_KEY* src, EC_KEY** dest);
EC_KEY* d_PublicKey = nullptr;
#endif
#else // GnuTLS
bool pubkey_copy(gnutls_pubkey_t src, gnutls_pubkey_t* dest);
gnutls_pubkey_t d_PublicKey{};
#endif
std::vector<uint8_t> d_x_4_0;
std::vector<uint8_t> d_x_3_1;
@ -82,4 +82,5 @@ private:
/** \} */
/** \} */
#endif // GNSS_SDR_GNSS_CRYPTO_H

View File

@ -1367,6 +1367,9 @@ if(NOT ENABLE_PACKAGING AND NOT ENABLE_FPGA)
GTest::GTest
GTest::Main
core_libs
Gnuradio::blocks
Gnuradio::runtime
Gnuradio::filter # workaround for old systems
)
if(ENABLE_GLOG_AND_GFLAGS)
target_link_libraries(osnma_msg_receiver_test PRIVATE Gflags::gflags Glog::glog)

View File

@ -1,11 +1,14 @@
#include <gtest/gtest.h>
#include <bitset>
#include <filesystem>
#include <fstream>
#include <logging.h>
#include <osnma_msg_receiver.h>
#include <vector>
#include "osnma_msg_receiver.h"
#if USE_GLOG_AND_GFLAGS
#include <glog/logging.h> // for LOG
#else
#include <absl/log/log.h>
#endif
struct TestVector
{
@ -31,11 +34,9 @@ protected:
void set_time(std::tm& input);
// std::string log_name {"CONFIG1-2023-08-16-PKID1-OSNMA"};
std::string log_name {"CONFIG2-2023-07-27-PKID2-MT2-OSNMA"};
void initializeGoogleLog();
void SetUp() override
{
initializeGoogleLog();
// std::tm input_time = {0, 0, 5, 16, 8 - 1, 2023 - 1900, 0}; // conf. 1
std::tm input_time = {0, 0, 0, 27, 7 - 1, 2023 - 1900, 0}; // conf. 2
set_time(input_time);
@ -545,46 +546,3 @@ void OsnmaMsgReceiverTest::set_time(std::tm& input)
}
void OsnmaMsgReceiverTest::initializeGoogleLog()
{
google::InitGoogleLogging(log_name.c_str());
FLAGS_minloglevel = 0; // INFO
FLAGS_logtostderr = 0; // add this line
FLAGS_log_dir = "/home/cgm/CLionProjects/osnma/build/src/tests/logs";
if (FLAGS_log_dir.empty())
{
std::cout << "Logging will be written at "
<< std::filesystem::temp_directory_path()
<< '\n'
<< "Use gnss-sdr --log_dir=/path/to/log to change that.\n";
}
else
{
try
{
const std::filesystem::path p(FLAGS_log_dir);
if (!std::filesystem::exists(p))
{
std::cout << "The path "
<< FLAGS_log_dir
<< " does not exist, attempting to create it.\n";
std::error_code ec;
if (!std::filesystem::create_directory(p, ec))
{
std::cout << "Could not create the " << FLAGS_log_dir << " folder.\n";
gflags::ShutDownCommandLineFlags();
throw std::runtime_error("Could not create folder for logs");
}
}
std::cout << "Logging will be written at " << FLAGS_log_dir << '\n';
}
catch (const std::exception& e)
{
std::cerr << e.what() << '\n';
std::cerr << "Could not create the " << FLAGS_log_dir << " folder.\n";
gflags::ShutDownCommandLineFlags();
throw;
}
}
}