mirror of
				https://github.com/gnss-sdr/gnss-sdr
				synced 2025-10-31 07:13:03 +00:00 
			
		
		
		
	Introducing the crypto bro
This commit is contained in:
		| @@ -102,45 +102,6 @@ target_link_libraries(core_libs | |||||||
|         Pugixml::pugixml |         Pugixml::pugixml | ||||||
| ) | ) | ||||||
|  |  | ||||||
| if(OPENSSL_FOUND) |  | ||||||
|     if(TARGET OpenSSL::SSL) |  | ||||||
|         target_link_libraries(core_libs |  | ||||||
|             PRIVATE |  | ||||||
|                 OpenSSL::SSL |  | ||||||
|         ) |  | ||||||
|     else() |  | ||||||
|         target_link_libraries(core_libs |  | ||||||
|             PRIVATE |  | ||||||
|                 ${OPENSSL_LIBRARIES} |  | ||||||
|         ) |  | ||||||
|         target_include_directories(core_libs |  | ||||||
|             PRIVATE |  | ||||||
|                 ${OPENSSL_INCLUDE_DIR} |  | ||||||
|         ) |  | ||||||
|     endif() |  | ||||||
|     if(OPENSSL_VERSION) |  | ||||||
|         if(OPENSSL_VERSION VERSION_GREATER "3.0.0") |  | ||||||
|             target_compile_definitions(core_libs PRIVATE -DUSE_OPENSSL_3=1) |  | ||||||
|         endif() |  | ||||||
|     endif() |  | ||||||
| else() |  | ||||||
|     target_link_libraries(core_libs |  | ||||||
|         PRIVATE |  | ||||||
|             ${GNUTLS_LIBRARIES} |  | ||||||
|             ${GNUTLS_OPENSSL_LIBRARY} |  | ||||||
|     ) |  | ||||||
|     target_include_directories(core_libs |  | ||||||
|         PRIVATE |  | ||||||
|         ${GNUTLS_INCLUDE_DIR} |  | ||||||
|     ) |  | ||||||
| endif() |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| if(OPENSSL_FOUND) |  | ||||||
|     target_compile_definitions(core_libs PRIVATE -DUSE_OPENSSL_FALLBACK=1) |  | ||||||
| endif() |  | ||||||
|  |  | ||||||
| if(USE_GENERIC_LAMBDAS AND NOT GNURADIO_USES_STD_POINTERS) | if(USE_GENERIC_LAMBDAS AND NOT GNURADIO_USES_STD_POINTERS) | ||||||
|     target_link_libraries(core_libs PUBLIC Boost::headers) |     target_link_libraries(core_libs PUBLIC Boost::headers) | ||||||
| else() | else() | ||||||
|   | |||||||
| @@ -19,18 +19,15 @@ | |||||||
|  |  | ||||||
| #include "osnma_msg_receiver.h" | #include "osnma_msg_receiver.h" | ||||||
| #include "Galileo_OSNMA.h" | #include "Galileo_OSNMA.h" | ||||||
|  | #include "gnss_crypto.h" | ||||||
| #include "osnma_dsm_reader.h"       // for OSNMA_DSM_Reader | #include "osnma_dsm_reader.h"       // for OSNMA_DSM_Reader | ||||||
| #include <glog/logging.h>           // for DLOG | #include <glog/logging.h>           // for DLOG | ||||||
| #include <gnuradio/io_signature.h>  // for gr::io_signature::make | #include <gnuradio/io_signature.h>  // for gr::io_signature::make | ||||||
| #include <bitset> |  | ||||||
| #include <cmath> | #include <cmath> | ||||||
| #include <cstddef> | #include <cstddef> | ||||||
| #include <cstdint> | #include <cstdint> | ||||||
| #include <fstream> |  | ||||||
| #include <iostream> | #include <iostream> | ||||||
| #include <iterator> |  | ||||||
| #include <numeric> | #include <numeric> | ||||||
| #include <string> |  | ||||||
| #include <typeinfo>  // for typeid | #include <typeinfo>  // for typeid | ||||||
|  |  | ||||||
| #if HAS_GENERIC_LAMBDA | #if HAS_GENERIC_LAMBDA | ||||||
| @@ -46,32 +43,20 @@ namespace wht = boost; | |||||||
| namespace wht = std; | namespace wht = std; | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #if USE_OPENSSL_FALLBACK |  | ||||||
| #include <openssl/cmac.h> |  | ||||||
| #include <openssl/hmac.h> |  | ||||||
| #if USE_OPENSSL_3 |  | ||||||
| #include <openssl/evp.h> |  | ||||||
| #define OPENSSL_ENGINE NULL |  | ||||||
| #else |  | ||||||
| #include <openssl/sha.h> |  | ||||||
| #endif |  | ||||||
| #else |  | ||||||
| #include <gnutls/crypto.h> |  | ||||||
| #include <gnutls/gnutls.h> |  | ||||||
| #include <gnutls/x509.h> |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| osnma_msg_receiver_sptr osnma_msg_receiver_make() | osnma_msg_receiver_sptr osnma_msg_receiver_make(const std::string& pemFilePath) | ||||||
| { | { | ||||||
|     return osnma_msg_receiver_sptr(new osnma_msg_receiver()); |     return osnma_msg_receiver_sptr(new osnma_msg_receiver(pemFilePath)); | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| osnma_msg_receiver::osnma_msg_receiver() : gr::block("osnma_msg_receiver", | osnma_msg_receiver::osnma_msg_receiver( | ||||||
|  |     const std::string& pemFilePath) : gr::block("osnma_msg_receiver", | ||||||
|                                           gr::io_signature::make(0, 0, 0), |                                           gr::io_signature::make(0, 0, 0), | ||||||
|                                           gr::io_signature::make(0, 0, 0)) |                                           gr::io_signature::make(0, 0, 0)) | ||||||
| { | { | ||||||
|     d_dsm_reader = std::make_unique<OSNMA_DSM_Reader>(); |     d_dsm_reader = std::make_unique<OSNMA_DSM_Reader>(); | ||||||
|  |     d_crypto = std::make_unique<Gnss_Crypto>(pemFilePath); | ||||||
|     //  register OSNMA input message port from telemetry blocks |     //  register OSNMA input message port from telemetry blocks | ||||||
|     this->message_port_register_in(pmt::mp("OSNMA_from_TLM")); |     this->message_port_register_in(pmt::mp("OSNMA_from_TLM")); | ||||||
|     // register OSNMA output message port to PVT block |     // register OSNMA output message port to PVT block | ||||||
| @@ -291,11 +276,11 @@ void osnma_msg_receiver::process_dsm_message(const std::vector<uint8_t>& dsm_msg | |||||||
|                     std::vector<uint8_t> hash; |                     std::vector<uint8_t> hash; | ||||||
|                     if (d_osnma_data.d_dsm_kroot_message.hf == 0)  // Table 8. |                     if (d_osnma_data.d_dsm_kroot_message.hf == 0)  // Table 8. | ||||||
|                         { |                         { | ||||||
|                             hash = computeSHA256(MSG); |                             hash = d_crypto->computeSHA256(MSG); | ||||||
|                         } |                         } | ||||||
|                     else if (d_osnma_data.d_dsm_kroot_message.hf == 2) |                     else if (d_osnma_data.d_dsm_kroot_message.hf == 2) | ||||||
|                         { |                         { | ||||||
|                             hash = computeSHA3_256(MSG); |                             hash = d_crypto->computeSHA3_256(MSG); | ||||||
|                         } |                         } | ||||||
|                     else |                     else | ||||||
|                         { |                         { | ||||||
| @@ -585,275 +570,3 @@ void osnma_msg_receiver::read_mack_key() | |||||||
| void osnma_msg_receiver::read_mack_padding() | void osnma_msg_receiver::read_mack_padding() | ||||||
| { | { | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| std::vector<uint8_t> osnma_msg_receiver::computeSHA256(const std::vector<uint8_t>& input) |  | ||||||
| { |  | ||||||
|     std::vector<uint8_t> output(32);  // SHA256 hash size |  | ||||||
| #if USE_OPENSSL_FALLBACK |  | ||||||
| #if USE_OPENSSL_3 |  | ||||||
|     // unsigned char mdVal[EVP_MAX_MD_SIZE]; |  | ||||||
|     // unsigned char* md; |  | ||||||
|     unsigned int mdLen; |  | ||||||
|     EVP_MD_CTX* mdCtx = EVP_MD_CTX_new(); |  | ||||||
|     if (!EVP_DigestInit_ex(mdCtx, EVP_sha256(), OPENSSL_ENGINE)) |  | ||||||
|         { |  | ||||||
|             LOG(WARNING) << "OSNMA SHA-256: Message digest initialization failed."; |  | ||||||
|             EVP_MD_CTX_free(mdCtx); |  | ||||||
|             return output; |  | ||||||
|         } |  | ||||||
|     if (!EVP_DigestUpdate(mdCtx, input.data(), input.size())) |  | ||||||
|         { |  | ||||||
|             LOG(WARNING) << "OSNMA SHA-256: Message digest update failed."; |  | ||||||
|             EVP_MD_CTX_free(mdCtx); |  | ||||||
|             return output; |  | ||||||
|         } |  | ||||||
|     if (!EVP_DigestFinal_ex(mdCtx, output.data(), &mdLen)) |  | ||||||
|         { |  | ||||||
|             LOG(WARNING) << "OSNMA SHA-256: Message digest finalization failed."; |  | ||||||
|             EVP_MD_CTX_free(mdCtx); |  | ||||||
|             return output; |  | ||||||
|         } |  | ||||||
|     EVP_MD_CTX_free(mdCtx); |  | ||||||
|     // md = mdVal; |  | ||||||
| #else |  | ||||||
|     SHA256_CTX sha256Context; |  | ||||||
|     SHA256_Init(&sha256Context); |  | ||||||
|     SHA256_Update(&sha256Context, input.data(), input.size()); |  | ||||||
|     SHA256_Final(output.data(), &sha256Context); |  | ||||||
| #endif |  | ||||||
| #else |  | ||||||
|     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; |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| std::vector<uint8_t> osnma_msg_receiver::computeSHA3_256(const std::vector<uint8_t>& input) |  | ||||||
| { |  | ||||||
|     std::vector<uint8_t> output(32);  // SHA256 hash size |  | ||||||
| #if USE_OPENSSL_FALLBACK |  | ||||||
| #if USE_OPENSSL_3 |  | ||||||
|     EVP_MD_CTX* mdctx = EVP_MD_CTX_new(); |  | ||||||
|     const EVP_MD* md = EVP_sha3_256(); |  | ||||||
|  |  | ||||||
|     EVP_DigestInit_ex(mdctx, md, nullptr); |  | ||||||
|     EVP_DigestUpdate(mdctx, input.data(), input.size()); |  | ||||||
|     EVP_DigestFinal_ex(mdctx, output.data(), nullptr); |  | ||||||
|     EVP_MD_CTX_free(mdctx); |  | ||||||
| #else |  | ||||||
|     // SHA3-256 not implemented in OpenSSL < 3.0 |  | ||||||
| #endif |  | ||||||
| #else |  | ||||||
|     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; |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| std::vector<uint8_t> osnma_msg_receiver::computeHMAC_SHA_256(const std::vector<uint8_t>& key, const std::vector<uint8_t>& input) |  | ||||||
| { |  | ||||||
|     std::vector<uint8_t> output(32); |  | ||||||
| #if USE_OPENSSL_FALLBACK |  | ||||||
| #if USE_OPENSSL_3 |  | ||||||
|     std::vector<uint8_t> hmac(EVP_MAX_MD_SIZE); |  | ||||||
|  |  | ||||||
|     // Create HMAC-SHA256 context |  | ||||||
|     EVP_MD_CTX* ctx = EVP_MD_CTX_new(); |  | ||||||
|     EVP_PKEY* pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, nullptr, key.data(), key.size()); |  | ||||||
|  |  | ||||||
|     // Initialize HMAC-SHA256 context |  | ||||||
|     EVP_DigestSignInit(ctx, nullptr, EVP_sha256(), nullptr, pkey); |  | ||||||
|  |  | ||||||
|     // Compute HMAC-SHA256 |  | ||||||
|     EVP_DigestSignUpdate(ctx, input.data(), input.size()); |  | ||||||
|     size_t macLength; |  | ||||||
|     EVP_DigestSignFinal(ctx, hmac.data(), &macLength); |  | ||||||
|  |  | ||||||
|     EVP_PKEY_free(pkey); |  | ||||||
|     EVP_MD_CTX_free(ctx); |  | ||||||
|  |  | ||||||
|     hmac.resize(macLength); |  | ||||||
|     output = hmac; |  | ||||||
| #else |  | ||||||
|     std::vector<uint8_t> hmac(32); |  | ||||||
|     // Create HMAC context |  | ||||||
|     HMAC_CTX* ctx = HMAC_CTX_new(); |  | ||||||
|     HMAC_Init_ex(ctx, key.data(), key.size(), EVP_sha256(), nullptr); |  | ||||||
|  |  | ||||||
|     // Update HMAC context with the message |  | ||||||
|     HMAC_Update(ctx, input.data(), input.size()); |  | ||||||
|  |  | ||||||
|     // Finalize HMAC computation |  | ||||||
|     unsigned int hmacLen; |  | ||||||
|     HMAC_Final(ctx, hmac.data(), &hmacLen); |  | ||||||
|  |  | ||||||
|     // Clean up HMAC context |  | ||||||
|     HMAC_CTX_free(ctx); |  | ||||||
|  |  | ||||||
|     // Resize the HMAC vector to the actual length |  | ||||||
|     hmac.resize(hmacLen); |  | ||||||
|  |  | ||||||
|     output = hmac; |  | ||||||
| #endif |  | ||||||
| #else |  | ||||||
|     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; |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| std::vector<uint8_t> osnma_msg_receiver::computeCMAC_AES(const std::vector<uint8_t>& key, const std::vector<uint8_t>& input) |  | ||||||
| { |  | ||||||
|     std::vector<uint8_t> output(16); |  | ||||||
| #if USE_OPENSSL_FALLBACK |  | ||||||
| #if USE_OPENSSL_3 |  | ||||||
|     std::vector<uint8_t> mac(EVP_MAX_MD_SIZE);  // CMAC-AES output size |  | ||||||
|  |  | ||||||
|     EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new(); |  | ||||||
|  |  | ||||||
|     // Initialize CMAC-AES context |  | ||||||
|     EVP_CIPHER_CTX* cmacCtx = EVP_CIPHER_CTX_new(); |  | ||||||
|     EVP_CMAC_CTX* cmac = EVP_CMAC_CTX_new(); |  | ||||||
|  |  | ||||||
|     EVP_CIPHER_CTX_reset(ctx); |  | ||||||
|     EVP_CMAC_CTX_reset(cmac); |  | ||||||
|  |  | ||||||
|     // Set AES-128 CMAC cipher and key |  | ||||||
|     EVP_CMAC_init(cmac, key.data(), key.size(), EVP_aes_128_cbc(), nullptr); |  | ||||||
|  |  | ||||||
|     // Compute CMAC-AES |  | ||||||
|     EVP_CMAC_update(cmac, input.data(), input.size()); |  | ||||||
|     size_t macLength; |  | ||||||
|     EVP_CMAC_final(cmac, mac.data(), &macLength); |  | ||||||
|  |  | ||||||
|     EVP_CIPHER_CTX_free(ctx); |  | ||||||
|     EVP_CMAC_CTX_free(cmac); |  | ||||||
|  |  | ||||||
|     mac.resize(macLength); |  | ||||||
|     output = mac; |  | ||||||
| #else |  | ||||||
|     std::vector<uint8_t> mac(CMAC_DIGEST_LENGTH);  // CMAC-AES output size |  | ||||||
|  |  | ||||||
|     // Create CMAC context |  | ||||||
|     CMAC_CTX* cmacCtx = CMAC_CTX_new(); |  | ||||||
|     CMAC_Init(cmacCtx, key.data(), key.size(), EVP_aes_128_cbc(), nullptr); |  | ||||||
|  |  | ||||||
|     // Compute CMAC-AES |  | ||||||
|     CMAC_Update(cmacCtx, input.data(), input.size()); |  | ||||||
|     CMAC_Final(cmacCtx, mac.data(), nullptr); |  | ||||||
|  |  | ||||||
|     // Clean up CMAC context |  | ||||||
|     CMAC_CTX_free(cmacCtx); |  | ||||||
|  |  | ||||||
|     output = mac; |  | ||||||
| #endif |  | ||||||
| #else |  | ||||||
|     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; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // bool signature(const std::vector<uint8_t>& publicKey, const std::vector<uint8_t>& digest, std::vector<uint8_t>& signature) |  | ||||||
| // { |  | ||||||
| //     bool success = false; |  | ||||||
| // #if USE_OPENSSL_FALLBACK |  | ||||||
| // #else |  | ||||||
| //     gnutls_global_init(); |  | ||||||
| //     int result = gnutls_pubkey_verify_data(publicKey.data(), GNUTLS_SIGN_ECDSA_SHA256, digest.data, digest.size(), signature.data(), signature.size()); |  | ||||||
| //     success = (result == GNUTLS_E_SUCCESS); |  | ||||||
| // gnutls_global_deinit(); |  | ||||||
| // #endif |  | ||||||
| //     return success; |  | ||||||
| // } |  | ||||||
| // bool verifyDigitalSignature(const unsigned char* signature, size_t signatureSize, const unsigned char* message, size_t messageSize, gnutls_pubkey_t publicKey) |  | ||||||
| // { |  | ||||||
| //     int verificationStatus = gnutls_pubkey_verify_data(publicKey, GNUTLS_DIG_SHA256, 0, message, messageSize, signature, signatureSize); |  | ||||||
| //     return verificationStatus == 0; |  | ||||||
|  |  | ||||||
| std::vector<uint8_t> osnma_msg_receiver::readPublicKeyFromPEM(const std::string& filePath) |  | ||||||
| { |  | ||||||
|     std::vector<uint8_t> publicKey; |  | ||||||
| #if USE_OPENSSL_FALLBACK |  | ||||||
| #if USE_OPENSSL_3 |  | ||||||
| #else |  | ||||||
| #endif |  | ||||||
| #else |  | ||||||
|     // Open the .pem file |  | ||||||
|     std::ifstream file(filePath); |  | ||||||
|     if (!file) |  | ||||||
|         { |  | ||||||
|             std::cerr << "Failed to open the file: " << filePath << std::endl; |  | ||||||
|             return publicKey; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|     // Read the contents of the .pem file into a string |  | ||||||
|     std::string pemContents((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>()); |  | ||||||
|  |  | ||||||
|     gnutls_x509_crt_t cert; |  | ||||||
|     gnutls_x509_crt_init(&cert); |  | ||||||
|  |  | ||||||
|     // Import the certificate from the PEM file |  | ||||||
|     gnutls_datum_t pemData; |  | ||||||
|     pemData.data = reinterpret_cast<unsigned char*>(const_cast<char*>(pemContents.data())); |  | ||||||
|     pemData.size = pemContents.size(); |  | ||||||
|     int ret = gnutls_x509_crt_import(cert, &pemData, GNUTLS_X509_FMT_PEM); |  | ||||||
|     if (ret < 0) |  | ||||||
|         { |  | ||||||
|             std::cerr << "Failed to import certificate from PEM file" << std::endl; |  | ||||||
|             gnutls_x509_crt_deinit(cert); |  | ||||||
|             return publicKey; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|     // Export the public key data |  | ||||||
|     size_t pubkey_data_size = 0; |  | ||||||
|     ret = gnutls_x509_crt_export(cert, GNUTLS_X509_FMT_DER, nullptr, &pubkey_data_size); |  | ||||||
|     if (ret < 0) |  | ||||||
|         { |  | ||||||
|             std::cerr << "Failed to export public key data" << std::endl; |  | ||||||
|             gnutls_x509_crt_deinit(cert); |  | ||||||
|             return publicKey; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|     publicKey.resize(pubkey_data_size); |  | ||||||
|     ret = gnutls_x509_crt_export(cert, GNUTLS_X509_FMT_DER, publicKey.data(), &pubkey_data_size); |  | ||||||
|     if (ret < 0) |  | ||||||
|         { |  | ||||||
|             std::cerr << "Failed to export public key data" << std::endl; |  | ||||||
|             gnutls_x509_crt_deinit(cert); |  | ||||||
|             return publicKey; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|     gnutls_x509_crt_deinit(cert); |  | ||||||
|  |  | ||||||
| #endif |  | ||||||
|     return publicKey; |  | ||||||
| } |  | ||||||
| @@ -27,6 +27,7 @@ | |||||||
| #include <pmt/pmt.h>               // for pmt::pmt_t | #include <pmt/pmt.h>               // for pmt::pmt_t | ||||||
| #include <array>                   // for std::array | #include <array>                   // for std::array | ||||||
| #include <memory>                  // for std::shared_ptr | #include <memory>                  // for std::shared_ptr | ||||||
|  | #include <string> | ||||||
| #include <vector> | #include <vector> | ||||||
|  |  | ||||||
| /** \addtogroup Core | /** \addtogroup Core | ||||||
| @@ -35,11 +36,12 @@ | |||||||
|  * \{ */ |  * \{ */ | ||||||
|  |  | ||||||
| class OSNMA_DSM_Reader; | class OSNMA_DSM_Reader; | ||||||
|  | class Gnss_Crypto; | ||||||
| class osnma_msg_receiver; | class osnma_msg_receiver; | ||||||
|  |  | ||||||
| using osnma_msg_receiver_sptr = gnss_shared_ptr<osnma_msg_receiver>; | using osnma_msg_receiver_sptr = gnss_shared_ptr<osnma_msg_receiver>; | ||||||
|  |  | ||||||
| osnma_msg_receiver_sptr osnma_msg_receiver_make(); | osnma_msg_receiver_sptr osnma_msg_receiver_make(const std::string& pemFilePath); | ||||||
|  |  | ||||||
| /*! | /*! | ||||||
|  * \brief GNU Radio block that receives asynchronous OSNMA messages |  * \brief GNU Radio block that receives asynchronous OSNMA messages | ||||||
| @@ -53,8 +55,8 @@ public: | |||||||
|     ~osnma_msg_receiver() = default;  //!< Default destructor |     ~osnma_msg_receiver() = default;  //!< Default destructor | ||||||
|  |  | ||||||
| private: | private: | ||||||
|     friend osnma_msg_receiver_sptr osnma_msg_receiver_make(); |     friend osnma_msg_receiver_sptr osnma_msg_receiver_make(const std::string& pemFilePath); | ||||||
|     osnma_msg_receiver(); |     osnma_msg_receiver(const std::string& pemFilePath); | ||||||
|  |  | ||||||
|     void msg_handler_osnma(const pmt::pmt_t& msg); |     void msg_handler_osnma(const pmt::pmt_t& msg); | ||||||
|     void process_osnma_message(const std::shared_ptr<OSNMA_msg>& osnma_msg); |     void process_osnma_message(const std::shared_ptr<OSNMA_msg>& osnma_msg); | ||||||
| @@ -69,13 +71,8 @@ private: | |||||||
|     void read_mack_key(); |     void read_mack_key(); | ||||||
|     void read_mack_padding(); |     void read_mack_padding(); | ||||||
|  |  | ||||||
|     std::vector<uint8_t> computeSHA256(const std::vector<uint8_t>& input); |  | ||||||
|     std::vector<uint8_t> computeSHA3_256(const std::vector<uint8_t>& input); |  | ||||||
|     std::vector<uint8_t> computeHMAC_SHA_256(const std::vector<uint8_t>& key, const std::vector<uint8_t>& input); |  | ||||||
|     std::vector<uint8_t> computeCMAC_AES(const std::vector<uint8_t>& key, const std::vector<uint8_t>& input); |  | ||||||
|     std::vector<uint8_t> readPublicKeyFromPEM(const std::string& filePath); |  | ||||||
|  |  | ||||||
|     std::unique_ptr<OSNMA_DSM_Reader> d_dsm_reader; |     std::unique_ptr<OSNMA_DSM_Reader> d_dsm_reader; | ||||||
|  |     std::unique_ptr<Gnss_Crypto> d_crypto; | ||||||
|  |  | ||||||
|     std::array<std::array<uint8_t, 256>, 16> d_dsm_message{}; |     std::array<std::array<uint8_t, 256>, 16> d_dsm_message{}; | ||||||
|     std::array<std::array<uint8_t, 16>, 16> d_dsm_id_received{}; |     std::array<std::array<uint8_t, 16>, 16> d_dsm_id_received{}; | ||||||
|   | |||||||
| @@ -118,7 +118,9 @@ void GNSSFlowgraph::init() | |||||||
|     if (configuration_->property("Channels_1B.count", 0) > 0) |     if (configuration_->property("Channels_1B.count", 0) > 0) | ||||||
|         { |         { | ||||||
|             enable_osnma_rx_ = true; |             enable_osnma_rx_ = true; | ||||||
|             osnma_rx_ = osnma_msg_receiver_make(); |             const std::string pemfile_default("./OSNMA_PublicKey_20210920133026.pem"); | ||||||
|  |             auto pemFilePath = configuration_->property("GNSS-SDR.OSNMA_pem", pemfile_default); | ||||||
|  |             osnma_rx_ = osnma_msg_receiver_make(pemFilePath); | ||||||
|         } |         } | ||||||
|     else |     else | ||||||
|         { |         { | ||||||
|   | |||||||
| @@ -7,6 +7,7 @@ | |||||||
|  |  | ||||||
| set(SYSTEM_PARAMETERS_SOURCES | set(SYSTEM_PARAMETERS_SOURCES | ||||||
|     gnss_almanac.cc |     gnss_almanac.cc | ||||||
|  |     gnss_crypto.cc | ||||||
|     gnss_ephemeris.cc |     gnss_ephemeris.cc | ||||||
|     gnss_satellite.cc |     gnss_satellite.cc | ||||||
|     gnss_signal.cc |     gnss_signal.cc | ||||||
| @@ -34,6 +35,7 @@ set(SYSTEM_PARAMETERS_SOURCES | |||||||
|  |  | ||||||
| set(SYSTEM_PARAMETERS_HEADERS | set(SYSTEM_PARAMETERS_HEADERS | ||||||
|     gnss_almanac.h |     gnss_almanac.h | ||||||
|  |     gnss_crypto.h | ||||||
|     gnss_ephemeris.h |     gnss_ephemeris.h | ||||||
|     gnss_satellite.h |     gnss_satellite.h | ||||||
|     gnss_signal.h |     gnss_signal.h | ||||||
| @@ -130,6 +132,42 @@ target_include_directories(core_system_parameters | |||||||
|         ${GNSSSDR_SOURCE_DIR}/src/algorithms/libs |         ${GNSSSDR_SOURCE_DIR}/src/algorithms/libs | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  | if(OPENSSL_FOUND) | ||||||
|  |     if(TARGET OpenSSL::SSL) | ||||||
|  |         target_link_libraries(core_system_parameters | ||||||
|  |             PRIVATE | ||||||
|  |                 OpenSSL::SSL | ||||||
|  |         ) | ||||||
|  |     else() | ||||||
|  |         target_link_libraries(core_system_parameters | ||||||
|  |             PRIVATE | ||||||
|  |                 ${OPENSSL_LIBRARIES} | ||||||
|  |         ) | ||||||
|  |         target_include_directories(core_system_parameters | ||||||
|  |             PRIVATE | ||||||
|  |                 ${OPENSSL_INCLUDE_DIR} | ||||||
|  |         ) | ||||||
|  |     endif() | ||||||
|  |     if(OPENSSL_VERSION) | ||||||
|  |         if(OPENSSL_VERSION VERSION_GREATER "3.0.0") | ||||||
|  |             target_compile_definitions(core_system_parameters PRIVATE -DUSE_OPENSSL_3=1) | ||||||
|  |         endif() | ||||||
|  |     endif() | ||||||
|  | else() | ||||||
|  |     target_link_libraries(core_system_parameters | ||||||
|  |         PRIVATE | ||||||
|  |             ${GNUTLS_LIBRARIES} | ||||||
|  |             ${GNUTLS_OPENSSL_LIBRARY} | ||||||
|  |     ) | ||||||
|  |     target_include_directories(core_system_parameters | ||||||
|  |         PRIVATE | ||||||
|  |         ${GNUTLS_INCLUDE_DIR} | ||||||
|  |     ) | ||||||
|  | endif() | ||||||
|  | if(OPENSSL_FOUND) | ||||||
|  |     target_compile_definitions(core_system_parameters PRIVATE -DUSE_OPENSSL_FALLBACK=1) | ||||||
|  | endif() | ||||||
|  |  | ||||||
| if(ENABLE_CLANG_TIDY) | if(ENABLE_CLANG_TIDY) | ||||||
|     if(CLANG_TIDY_EXE) |     if(CLANG_TIDY_EXE) | ||||||
|         set_target_properties(core_system_parameters |         set_target_properties(core_system_parameters | ||||||
|   | |||||||
							
								
								
									
										400
									
								
								src/core/system_parameters/gnss_crypto.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										400
									
								
								src/core/system_parameters/gnss_crypto.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,400 @@ | |||||||
|  | /*! | ||||||
|  |  * \file gnss_crypto.cc | ||||||
|  |  * \brief Class for computing cryptografic functions | ||||||
|  |  * \author Carles Fernandez, 2023. cfernandez(at)cttc.es | ||||||
|  |  * | ||||||
|  |  * | ||||||
|  |  * ----------------------------------------------------------------------------- | ||||||
|  |  * | ||||||
|  |  * GNSS-SDR is a Global Navigation Satellite System software-defined receiver. | ||||||
|  |  * This file is part of GNSS-SDR. | ||||||
|  |  * | ||||||
|  |  * Copyright (C) 2010-2023  (see AUTHORS file for a list of contributors) | ||||||
|  |  * SPDX-License-Identifier: GPL-3.0-or-later | ||||||
|  |  * | ||||||
|  |  * ----------------------------------------------------------------------------- | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #include "gnss_crypto.h" | ||||||
|  | #include <cstddef> | ||||||
|  | #include <fstream> | ||||||
|  | #include <iostream> | ||||||
|  | #include <iterator> | ||||||
|  |  | ||||||
|  | #if USE_OPENSSL_FALLBACK | ||||||
|  | #include <openssl/cmac.h> | ||||||
|  | #include <openssl/hmac.h> | ||||||
|  | #include <openssl/pem.h> | ||||||
|  | #if USE_OPENSSL_3 | ||||||
|  | #include <openssl/evp.h> | ||||||
|  | #define OPENSSL_ENGINE NULL | ||||||
|  | #else | ||||||
|  | #include <openssl/rsa.h> | ||||||
|  | #include <openssl/sha.h> | ||||||
|  | #endif | ||||||
|  | #else | ||||||
|  | #include <gnutls/crypto.h> | ||||||
|  | #include <gnutls/gnutls.h> | ||||||
|  | #include <gnutls/x509.h> | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | Gnss_Crypto::Gnss_Crypto(const std::string& filePath) | ||||||
|  | { | ||||||
|  |     d_PublicKey = readPublicKeyFromPEM(filePath); | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | std::vector<uint8_t> Gnss_Crypto::computeSHA256(const std::vector<uint8_t>& input) | ||||||
|  | { | ||||||
|  |     std::vector<uint8_t> output(32);  // SHA256 hash size | ||||||
|  | #if USE_OPENSSL_FALLBACK | ||||||
|  | #if USE_OPENSSL_3 | ||||||
|  |     unsigned int mdLen; | ||||||
|  |     EVP_MD_CTX* mdCtx = EVP_MD_CTX_new(); | ||||||
|  |     if (!EVP_DigestInit_ex(mdCtx, EVP_sha256(), OPENSSL_ENGINE)) | ||||||
|  |         { | ||||||
|  |             // LOG(WARNING) << "OSNMA SHA-256: Message digest initialization failed."; | ||||||
|  |             EVP_MD_CTX_free(mdCtx); | ||||||
|  |             return output; | ||||||
|  |         } | ||||||
|  |     if (!EVP_DigestUpdate(mdCtx, input.data(), input.size())) | ||||||
|  |         { | ||||||
|  |             // LOG(WARNING) << "OSNMA SHA-256: Message digest update failed."; | ||||||
|  |             EVP_MD_CTX_free(mdCtx); | ||||||
|  |             return output; | ||||||
|  |         } | ||||||
|  |     if (!EVP_DigestFinal_ex(mdCtx, output.data(), &mdLen)) | ||||||
|  |         { | ||||||
|  |             // LOG(WARNING) << "OSNMA SHA-256: Message digest finalization failed."; | ||||||
|  |             EVP_MD_CTX_free(mdCtx); | ||||||
|  |             return output; | ||||||
|  |         } | ||||||
|  |     EVP_MD_CTX_free(mdCtx); | ||||||
|  | #else | ||||||
|  |     SHA256_CTX sha256Context; | ||||||
|  |     SHA256_Init(&sha256Context); | ||||||
|  |     SHA256_Update(&sha256Context, input.data(), input.size()); | ||||||
|  |     SHA256_Final(output.data(), &sha256Context); | ||||||
|  | #endif | ||||||
|  | #else | ||||||
|  |     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; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | std::vector<uint8_t> Gnss_Crypto::computeSHA3_256(const std::vector<uint8_t>& input) | ||||||
|  | { | ||||||
|  |     std::vector<uint8_t> output(32);  // SHA256 hash size | ||||||
|  | #if USE_OPENSSL_FALLBACK | ||||||
|  | #if USE_OPENSSL_3 | ||||||
|  |     EVP_MD_CTX* mdctx = EVP_MD_CTX_new(); | ||||||
|  |     const EVP_MD* md = EVP_sha3_256(); | ||||||
|  |  | ||||||
|  |     EVP_DigestInit_ex(mdctx, md, nullptr); | ||||||
|  |     EVP_DigestUpdate(mdctx, input.data(), input.size()); | ||||||
|  |     EVP_DigestFinal_ex(mdctx, output.data(), nullptr); | ||||||
|  |     EVP_MD_CTX_free(mdctx); | ||||||
|  | #else | ||||||
|  |     // SHA3-256 not implemented in OpenSSL < 3.0 | ||||||
|  | #endif | ||||||
|  | #else | ||||||
|  |     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; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | std::vector<uint8_t> Gnss_Crypto::computeHMAC_SHA_256(const std::vector<uint8_t>& key, const std::vector<uint8_t>& input) | ||||||
|  | { | ||||||
|  |     std::vector<uint8_t> output(32); | ||||||
|  | #if USE_OPENSSL_FALLBACK | ||||||
|  | #if USE_OPENSSL_3 | ||||||
|  |     std::vector<uint8_t> hmac(EVP_MAX_MD_SIZE); | ||||||
|  |  | ||||||
|  |     // Create HMAC-SHA256 context | ||||||
|  |     EVP_MD_CTX* ctx = EVP_MD_CTX_new(); | ||||||
|  |     EVP_PKEY* pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, nullptr, key.data(), key.size()); | ||||||
|  |  | ||||||
|  |     // Initialize HMAC-SHA256 context | ||||||
|  |     EVP_DigestSignInit(ctx, nullptr, EVP_sha256(), nullptr, pkey); | ||||||
|  |  | ||||||
|  |     // Compute HMAC-SHA256 | ||||||
|  |     EVP_DigestSignUpdate(ctx, input.data(), input.size()); | ||||||
|  |     size_t macLength; | ||||||
|  |     EVP_DigestSignFinal(ctx, hmac.data(), &macLength); | ||||||
|  |  | ||||||
|  |     EVP_PKEY_free(pkey); | ||||||
|  |     EVP_MD_CTX_free(ctx); | ||||||
|  |  | ||||||
|  |     hmac.resize(macLength); | ||||||
|  |     output = hmac; | ||||||
|  | #else | ||||||
|  |     std::vector<uint8_t> hmac(32); | ||||||
|  |     // Create HMAC context | ||||||
|  |     HMAC_CTX* ctx = HMAC_CTX_new(); | ||||||
|  |     HMAC_Init_ex(ctx, key.data(), key.size(), EVP_sha256(), nullptr); | ||||||
|  |  | ||||||
|  |     // Update HMAC context with the message | ||||||
|  |     HMAC_Update(ctx, input.data(), input.size()); | ||||||
|  |  | ||||||
|  |     // Finalize HMAC computation | ||||||
|  |     unsigned int hmacLen; | ||||||
|  |     HMAC_Final(ctx, hmac.data(), &hmacLen); | ||||||
|  |  | ||||||
|  |     // Clean up HMAC context | ||||||
|  |     HMAC_CTX_free(ctx); | ||||||
|  |  | ||||||
|  |     // Resize the HMAC vector to the actual length | ||||||
|  |     hmac.resize(hmacLen); | ||||||
|  |  | ||||||
|  |     output = hmac; | ||||||
|  | #endif | ||||||
|  | #else | ||||||
|  |     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; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | std::vector<uint8_t> Gnss_Crypto::computeCMAC_AES(const std::vector<uint8_t>& key, const std::vector<uint8_t>& input) | ||||||
|  | { | ||||||
|  |     std::vector<uint8_t> output(16); | ||||||
|  | #if USE_OPENSSL_FALLBACK | ||||||
|  | #if USE_OPENSSL_3 | ||||||
|  |     std::vector<uint8_t> mac(EVP_MAX_MD_SIZE);  // CMAC-AES output size | ||||||
|  |  | ||||||
|  |     EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new(); | ||||||
|  |     EVP_MAC* cmac = EVP_MAC_fetch(NULL, "CMAC-AES", NULL); | ||||||
|  |  | ||||||
|  |     EVP_MAC_CTX* cmacCtx = EVP_MAC_CTX_new(cmac); | ||||||
|  |  | ||||||
|  |     OSSL_PARAM params[4]; | ||||||
|  |     params[0] = OSSL_PARAM_construct_utf8_string("key", (char*)key.data(), key.size()); | ||||||
|  |     params[1] = OSSL_PARAM_construct_octet_string("iv", NULL, 0);   // Set IV to NULL | ||||||
|  |     params[2] = OSSL_PARAM_construct_octet_string("aad", NULL, 0);  // Set AAD to NULL | ||||||
|  |     params[3] = OSSL_PARAM_construct_end(); | ||||||
|  |  | ||||||
|  |     // Set AES-128 CMAC cipher and key | ||||||
|  |     EVP_MAC_init(cmacCtx, nullptr, 0, params); | ||||||
|  |  | ||||||
|  |     // Compute CMAC-AES | ||||||
|  |     EVP_MAC_update(cmacCtx, input.data(), input.size()); | ||||||
|  |     size_t macLength = mac.size(); | ||||||
|  |     size_t outputLength = 16; | ||||||
|  |  | ||||||
|  |     EVP_MAC_final(cmacCtx, mac.data(), &macLength, outputLength); | ||||||
|  |  | ||||||
|  |     EVP_MAC_free(cmac); | ||||||
|  |     EVP_MAC_CTX_free(cmacCtx); | ||||||
|  |     EVP_CIPHER_CTX_free(ctx); | ||||||
|  |  | ||||||
|  |     mac.resize(macLength); | ||||||
|  |     output = mac; | ||||||
|  | #else | ||||||
|  |     std::vector<uint8_t> mac(16);  // CMAC-AES output size | ||||||
|  |  | ||||||
|  |     // Create CMAC context | ||||||
|  |     CMAC_CTX* cmacCtx = CMAC_CTX_new(); | ||||||
|  |     CMAC_Init(cmacCtx, key.data(), key.size(), EVP_aes_128_cbc(), nullptr); | ||||||
|  |  | ||||||
|  |     // Compute CMAC-AES | ||||||
|  |     CMAC_Update(cmacCtx, input.data(), input.size()); | ||||||
|  |     CMAC_Final(cmacCtx, mac.data(), nullptr); | ||||||
|  |  | ||||||
|  |     // Clean up CMAC context | ||||||
|  |     CMAC_CTX_free(cmacCtx); | ||||||
|  |  | ||||||
|  |     output = mac; | ||||||
|  | #endif | ||||||
|  | #else | ||||||
|  |     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; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | std::vector<uint8_t> Gnss_Crypto::readPublicKeyFromPEM(const std::string& filePath) | ||||||
|  | { | ||||||
|  |     std::vector<uint8_t> publicKey; | ||||||
|  |     // Open the .pem file | ||||||
|  |     std::ifstream pemFile(filePath); | ||||||
|  |     if (!pemFile) | ||||||
|  |         { | ||||||
|  |             std::cerr << "Failed to open the file: " << filePath << std::endl; | ||||||
|  |             return publicKey; | ||||||
|  |         } | ||||||
|  | #if USE_OPENSSL_FALLBACK | ||||||
|  | #if USE_OPENSSL_3 | ||||||
|  |     // Read the contents of the file into a string | ||||||
|  |     std::string pemContent((std::istreambuf_iterator<char>(pemFile)), std::istreambuf_iterator<char>()); | ||||||
|  |  | ||||||
|  |     // Create a BIO object from the string data | ||||||
|  |     BIO* bio = BIO_new_mem_buf(pemContent.c_str(), pemContent.length()); | ||||||
|  |     if (!bio) | ||||||
|  |         { | ||||||
|  |             // Handle BIO creation error | ||||||
|  |             pemFile.close(); | ||||||
|  |             // ... | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |     // Read the PEM data from the BIO | ||||||
|  |     EVP_PKEY* evpKey = PEM_read_bio_PUBKEY(bio, nullptr, nullptr, nullptr); | ||||||
|  |     if (!evpKey) | ||||||
|  |         { | ||||||
|  |             // Handle PEM reading error | ||||||
|  |             BIO_free(bio); | ||||||
|  |             pemFile.close(); | ||||||
|  |             // ... | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |     // Create a memory BIO to write the public key data | ||||||
|  |     BIO* memBio = BIO_new(BIO_s_mem()); | ||||||
|  |     if (!memBio) | ||||||
|  |         { | ||||||
|  |             // Handle memory BIO creation error | ||||||
|  |             EVP_PKEY_free(evpKey); | ||||||
|  |             BIO_free(bio); | ||||||
|  |             pemFile.close(); | ||||||
|  |             // ... | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |     // Write the public key to the memory BIO | ||||||
|  |     int result = PEM_write_bio_PUBKEY(memBio, evpKey); | ||||||
|  |     if (result != 1) | ||||||
|  |         { | ||||||
|  |             // Handle public key writing error | ||||||
|  |             BIO_free(memBio); | ||||||
|  |             EVP_PKEY_free(evpKey); | ||||||
|  |             BIO_free(bio); | ||||||
|  |             pemFile.close(); | ||||||
|  |             // ... | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |     // Get the pointer to the memory BIO data and its length | ||||||
|  |     char* bioData; | ||||||
|  |     long bioDataLength = BIO_get_mem_data(memBio, &bioData); | ||||||
|  |  | ||||||
|  |     // Copy the public key data to the vector | ||||||
|  |     publicKey.assign(bioData, bioData + bioDataLength); | ||||||
|  |  | ||||||
|  |     // Free resources | ||||||
|  |     BIO_free(memBio); | ||||||
|  |     EVP_PKEY_free(evpKey); | ||||||
|  |     BIO_free(bio); | ||||||
|  |     pemFile.close(); | ||||||
|  | #else | ||||||
|  |     // Read the PEM file contents into a string | ||||||
|  |     std::string pemContents((std::istreambuf_iterator<char>(pemFile)), std::istreambuf_iterator<char>()); | ||||||
|  |  | ||||||
|  |     // Create a BIO object to hold the PEM data | ||||||
|  |     BIO* bio = BIO_new_mem_buf(pemContents.c_str(), -1); | ||||||
|  |  | ||||||
|  |     // Load the public key from the BIO | ||||||
|  |     RSA* rsa = PEM_read_bio_RSA_PUBKEY(bio, nullptr, nullptr, nullptr); | ||||||
|  |     BIO_free(bio); | ||||||
|  |  | ||||||
|  |     if (rsa == nullptr) | ||||||
|  |         { | ||||||
|  |             // Handle error reading public key | ||||||
|  |             return {}; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |     // Get the RSA modulus and convert it to a vector of uint8_t | ||||||
|  |     const BIGNUM* rsaModulus = nullptr; | ||||||
|  |     RSA_get0_key(rsa, &rsaModulus, nullptr, nullptr); | ||||||
|  |  | ||||||
|  |     BN_bn2bin(rsaModulus, publicKey.data()); | ||||||
|  |  | ||||||
|  |     // Clean up the RSA object | ||||||
|  |     RSA_free(rsa); | ||||||
|  | #endif | ||||||
|  | #else | ||||||
|  |     // Read the contents of the .pem file into a string | ||||||
|  |     std::string pemContents((std::istreambuf_iterator<char>(pemFile)), std::istreambuf_iterator<char>()); | ||||||
|  |  | ||||||
|  |     gnutls_x509_crt_t cert; | ||||||
|  |     gnutls_x509_crt_init(&cert); | ||||||
|  |  | ||||||
|  |     // Import the certificate from the PEM file | ||||||
|  |     gnutls_datum_t pemData; | ||||||
|  |     pemData.data = reinterpret_cast<unsigned char*>(const_cast<char*>(pemContents.data())); | ||||||
|  |     pemData.size = pemContents.size(); | ||||||
|  |     int ret = gnutls_x509_crt_import(cert, &pemData, GNUTLS_X509_FMT_PEM); | ||||||
|  |     if (ret < 0) | ||||||
|  |         { | ||||||
|  |             std::cerr << "Failed to import certificate from PEM file" << std::endl; | ||||||
|  |             gnutls_x509_crt_deinit(cert); | ||||||
|  |             return publicKey; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |     // Export the public key data | ||||||
|  |     size_t pubkey_data_size = 0; | ||||||
|  |     ret = gnutls_x509_crt_export(cert, GNUTLS_X509_FMT_DER, nullptr, &pubkey_data_size); | ||||||
|  |     if (ret < 0) | ||||||
|  |         { | ||||||
|  |             std::cerr << "Failed to export public key data" << std::endl; | ||||||
|  |             gnutls_x509_crt_deinit(cert); | ||||||
|  |             return publicKey; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |     publicKey.resize(pubkey_data_size); | ||||||
|  |     ret = gnutls_x509_crt_export(cert, GNUTLS_X509_FMT_DER, publicKey.data(), &pubkey_data_size); | ||||||
|  |     if (ret < 0) | ||||||
|  |         { | ||||||
|  |             std::cerr << "Failed to export public key data" << std::endl; | ||||||
|  |             gnutls_x509_crt_deinit(cert); | ||||||
|  |             return publicKey; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |     gnutls_x509_crt_deinit(cert); | ||||||
|  | #endif | ||||||
|  |     return publicKey; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | // // bool signature(const std::vector<uint8_t>& publicKey, const std::vector<uint8_t>& digest, std::vector<uint8_t>& signature) | ||||||
|  | // // { | ||||||
|  | // //     bool success = false; | ||||||
|  | // // #if USE_OPENSSL_FALLBACK | ||||||
|  | // // #else | ||||||
|  | // //     gnutls_global_init(); | ||||||
|  | // //     int result = gnutls_pubkey_verify_data(publicKey.data(), GNUTLS_SIGN_ECDSA_SHA256, digest.data, digest.size(), signature.data(), signature.size()); | ||||||
|  | // //     success = (result == GNUTLS_E_SUCCESS); | ||||||
|  | // // gnutls_global_deinit(); | ||||||
|  | // // #endif | ||||||
|  | // //     return success; | ||||||
|  | // // } | ||||||
|  | // // bool verifyDigitalSignature(const unsigned char* signature, size_t signatureSize, const unsigned char* message, size_t messageSize, gnutls_pubkey_t publicKey) | ||||||
|  | // // { | ||||||
|  | // //     int verificationStatus = gnutls_pubkey_verify_data(publicKey, GNUTLS_DIG_SHA256, 0, message, messageSize, signature, signatureSize); | ||||||
|  | // //     return verificationStatus == 0; | ||||||
							
								
								
									
										49
									
								
								src/core/system_parameters/gnss_crypto.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								src/core/system_parameters/gnss_crypto.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | |||||||
|  | /*! | ||||||
|  |  * \file gnss_crypto.h | ||||||
|  |  * \brief Class for computing cryptografic functions | ||||||
|  |  * \author Carles Fernandez, 2023. cfernandez(at)cttc.es | ||||||
|  |  * | ||||||
|  |  * | ||||||
|  |  * ----------------------------------------------------------------------------- | ||||||
|  |  * | ||||||
|  |  * GNSS-SDR is a Global Navigation Satellite System software-defined receiver. | ||||||
|  |  * This file is part of GNSS-SDR. | ||||||
|  |  * | ||||||
|  |  * Copyright (C) 2010-2023  (see AUTHORS file for a list of contributors) | ||||||
|  |  * SPDX-License-Identifier: GPL-3.0-or-later | ||||||
|  |  * | ||||||
|  |  * ----------------------------------------------------------------------------- | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #ifndef GNSS_SDR_GNSS_CRYPTO_H | ||||||
|  | #define GNSS_SDR_GNSS_CRYPTO_H | ||||||
|  |  | ||||||
|  | #include <cstdint> | ||||||
|  | #include <string> | ||||||
|  | #include <vector> | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /** \addtogroup Core | ||||||
|  |  * \{ */ | ||||||
|  | /** \addtogroup System_Parameters | ||||||
|  |  * \{ */ | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class Gnss_Crypto | ||||||
|  | { | ||||||
|  | public: | ||||||
|  |     Gnss_Crypto() = default; | ||||||
|  |     Gnss_Crypto(const std::string& filePath); | ||||||
|  |     std::vector<uint8_t> computeSHA256(const std::vector<uint8_t>& input); | ||||||
|  |     std::vector<uint8_t> computeSHA3_256(const std::vector<uint8_t>& input); | ||||||
|  |     std::vector<uint8_t> computeHMAC_SHA_256(const std::vector<uint8_t>& key, const std::vector<uint8_t>& input); | ||||||
|  |     std::vector<uint8_t> computeCMAC_AES(const std::vector<uint8_t>& key, const std::vector<uint8_t>& input); | ||||||
|  |     std::vector<uint8_t> readPublicKeyFromPEM(const std::string& filePath); | ||||||
|  |  | ||||||
|  | private: | ||||||
|  |     std::vector<uint8_t> d_PublicKey; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /** \} */ | ||||||
|  | /** \} */ | ||||||
|  | #endif  // GNSS_SDR_GNSS_CRYPTO_H | ||||||
		Reference in New Issue
	
	Block a user
	 Carles Fernandez
					Carles Fernandez