diff --git a/src/core/receiver/gnss_flowgraph.cc b/src/core/receiver/gnss_flowgraph.cc index 4b5f71012..acdea9df2 100644 --- a/src/core/receiver/gnss_flowgraph.cc +++ b/src/core/receiver/gnss_flowgraph.cc @@ -124,9 +124,9 @@ void GNSSFlowgraph::init() if (configuration_->property("Channels_1B.count", 0) > 0) { enable_osnma_rx_ = true; - auto pemFilePath = configuration_->property("GNSS-SDR.OSNMA_pem", PEMFILE_DEFAULT); - auto merKleTreePath = configuration_->property("GNSS-SDR.OSNMA_MerkleTree", MERKLEFILE_DEFAULT); - osnma_rx_ = osnma_msg_receiver_make(pemFilePath, merKleTreePath); + const auto certFilePath = configuration_->property("GNSS-SDR.osnma_public_key", CRTFILE_DEFAULT); + const auto merKleTreePath = configuration_->property("GNSS-SDR.osnma_merkletree", MERKLEFILE_DEFAULT); + osnma_rx_ = osnma_msg_receiver_make(certFilePath, merKleTreePath); } else { diff --git a/src/core/system_parameters/CMakeLists.txt b/src/core/system_parameters/CMakeLists.txt index 518e64264..607c3702a 100644 --- a/src/core/system_parameters/CMakeLists.txt +++ b/src/core/system_parameters/CMakeLists.txt @@ -29,8 +29,9 @@ set(SYSTEM_PARAMETERS_SOURCES glonass_gnav_utc_model.cc glonass_gnav_navigation_message.cc reed_solomon.cc - osnma_dsm_reader.cc osnma_data.cc + osnma_dsm_reader.cc + osnma_helper.cc ) set(SYSTEM_PARAMETERS_HEADERS @@ -96,7 +97,6 @@ set(SYSTEM_PARAMETERS_HEADERS Galileo_OSNMA.h osnma_data.h osnma_dsm_reader.h - osnma_helper.cc osnma_helper.h ) diff --git a/src/core/system_parameters/Galileo_OSNMA.h b/src/core/system_parameters/Galileo_OSNMA.h index e6530b610..bc919c4b3 100644 --- a/src/core/system_parameters/Galileo_OSNMA.h +++ b/src/core/system_parameters/Galileo_OSNMA.h @@ -161,7 +161,8 @@ const std::unordered_map OSNMA_TABLE_15 = { {std::string("SHA-512"), 1056}}; // key: ECDSA Curve and hash function, value: {l_ds_bits} const std::string PEMFILE_DEFAULT("../data/OSNMA_PublicKey_20240115100000_newPKID_1.pem"); -const std::string MERKLEFILE_DEFAULT("./OSNMA_MerkleTree_20210920133026.xml"); +const std::string CRTFILE_DEFAULT("../data/OSNMA_PublicKey_20240115100000_newPKID_1.crt"); +const std::string MERKLEFILE_DEFAULT("../data/OSNMA_MerkleTree_20240115100000_newPKID_1.xml"); class Mack_lookup { diff --git a/src/core/system_parameters/gnss_crypto.cc b/src/core/system_parameters/gnss_crypto.cc index d3cd11380..947b8a436 100644 --- a/src/core/system_parameters/gnss_crypto.cc +++ b/src/core/system_parameters/gnss_crypto.cc @@ -1,7 +1,8 @@ /*! * \file gnss_crypto.cc - * \brief Class for computing cryptografic functions - * \author Carles Fernandez, 2023. cfernandez(at)cttc.es + * \brief Class for computing cryptographic functions + * \author Carles Fernandez, 2023-2024. cfernandez(at)cttc.es + * Cesare Ghionoiu Martinez, 2023-2024. c.ghionoiu-martinez@tu-braunschweig.de * * * ----------------------------------------------------------------------------- @@ -9,7 +10,7 @@ * 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) + * Copyright (C) 2010-2024 (see AUTHORS file for a list of contributors) * SPDX-License-Identifier: GPL-3.0-or-later * * ----------------------------------------------------------------------------- @@ -20,41 +21,61 @@ #include #include #include +#include #include #include -#include #if USE_OPENSSL_FALLBACK #include #include #include #include +#include #if USE_OPENSSL_3 -#include #include +#include +#include #include #include -#include #include -#include +#include #define OPENSSL_ENGINE nullptr #else #include #endif -#else +#else // GnuTLS +#include #include #include #include -#include #endif -Gnss_Crypto::Gnss_Crypto(const std::string& pemFilePath, const std::string& merkleTreePath) +#if USE_GLOG_AND_GFLAGS +#include // for DLOG +#else +#include +#endif + + +Gnss_Crypto::Gnss_Crypto() { #if USE_OPENSSL_FALLBACK -#else - // gnutls_global_init(); +#else // GnuTLS + gnutls_global_init(); #endif - readPublicKeyFromPEM(pemFilePath); +} + + +Gnss_Crypto::Gnss_Crypto(const std::string& certFilePath, const std::string& merkleTreePath) +{ +#if USE_OPENSSL_FALLBACK +#else // GnuTLS + gnutls_global_init(); +#endif + if (!readPublicKeyFromCRT(certFilePath)) + { + readPublicKeyFromPEM(PEMFILE_DEFAULT); + } read_merkle_xml(merkleTreePath); } @@ -69,11 +90,13 @@ Gnss_Crypto::~Gnss_Crypto() EC_KEY_free(d_PublicKey); } #endif -#else // GNU-TLS - if (d_PublicKey != NULL) { +#else // GnuTLS + if (d_PublicKey != nullptr) + { gnutls_pubkey_deinit(d_PublicKey); - d_PublicKey = NULL; + d_PublicKey = nullptr; } + gnutls_global_deinit(); #endif } @@ -82,25 +105,12 @@ bool Gnss_Crypto::have_public_key() const { #if USE_OPENSSL_FALLBACK return (d_PublicKey != nullptr); -#else +#else // GnuTLS return (d_PublicKey != gnutls_pubkey_t{}); #endif } -std::string Gnss_Crypto::convert_to_utf8_str(const std::vector& input) const -{ - const char hex[] = "0123456789ABCDEF"; - std::string str(input.size() * 2, '0'); - for (size_t i = 0; i < input.size(); i++) - { - str[(i * 2) + 0] = hex[((input[i] & 0xF0) >> 4)]; - str[(i * 2) + 1] = hex[((input[i] & 0x0F))]; - } - return str; -} - - std::vector Gnss_Crypto::convert_from_hex_str(const std::string& input) const { std::vector result; @@ -157,11 +167,11 @@ void Gnss_Crypto::read_merkle_xml(const std::string& merkleFilePath) std::string signalVersion = galHeader.child("signalVersion").text().get(); std::string dataVersion = galHeader.child("dataVersion").text().get(); - std::cout << " Source: " << source.child_value("mission") << " - " << source.child_value("segment") << " - " << source.child_value("element") << std::endl; - std::cout << " Destination: " << destination.child_value("mission") << " - " << destination.child_value("segment") << " - " << destination.child_value("element") << std::endl; - std::cout << " Issue Date: " << issueDate << std::endl; - std::cout << " Signal Version: " << signalVersion << std::endl; - std::cout << " Data Version: " << dataVersion << std::endl; + LOG(INFO) << "OSNMA Merkletree - Source: " << source.child_value("mission") << " - " << source.child_value("segment") << " - " << source.child_value("element"); + LOG(INFO) << "OSNMA Merkletree - Destination: " << destination.child_value("mission") << " - " << destination.child_value("segment") << " - " << destination.child_value("element"); + LOG(INFO) << "OSNMA Merkletree - Issue Date: " << issueDate; + LOG(INFO) << "OSNMA Merkletree - Signal Version: " << signalVersion; + LOG(INFO) << "OSNMA Merkletree - Data Version: " << dataVersion; // Accessing data from the body pugi::xml_node merkleTree = body.child("MerkleTree"); @@ -169,8 +179,8 @@ void Gnss_Crypto::read_merkle_xml(const std::string& merkleFilePath) int n = std::stoi(merkleTree.child_value("N")); std::string hashFunction = merkleTree.child_value("HashFunction"); - std::cout << " N: " << n << std::endl; - std::cout << " Hash Function: " << hashFunction << std::endl; + LOG(INFO) << "OSNMA Merkletree - N: " << n; + LOG(INFO) << "OSNMA Merkletree - Hash Function: " << hashFunction; for (pugi::xml_node publicKey : merkleTree.children("PublicKey")) { @@ -180,21 +190,21 @@ void Gnss_Crypto::read_merkle_xml(const std::string& merkleFilePath) std::string point = publicKey.child_value("point"); std::string pkType = publicKey.child_value("PKType"); - std::cout << " Public Key: " << i << std::endl; - std::cout << " PKID: " << pkid << std::endl; - std::cout << " Length in Bits: " << lengthInBits << std::endl; - std::cout << " Point: " << point << std::endl; - std::cout << " PK Type: " << pkType << std::endl; + LOG(INFO) << "OSNMA Merkletree - Public Key: " << i; + LOG(INFO) << "OSNMA Merkletree - PKID: " << pkid; + LOG(INFO) << "OSNMA Merkletree - Length in Bits: " << lengthInBits; + LOG(INFO) << "OSNMA Merkletree - Point: " << point; + LOG(INFO) << "OSNMA Merkletree - PK Type: " << pkType; } for (pugi::xml_node treeNode : merkleTree.children("TreeNode")) { int j = std::stoi(treeNode.child_value("j")); int i = std::stoi(treeNode.child_value("i")); int lengthInBits = std::stoi(treeNode.child_value("lengthInBits")); - std::cout << " Node length (bits): " << lengthInBits << std::endl; + LOG(INFO) << "OSNMA Merkletree - Node length (bits): " << lengthInBits; std::string x_ji = treeNode.child_value("x_ji"); - std::cout << " Size string (bytes): " << x_ji.size() << std::endl; - std::cout << " m_" << j << "_" << i << " = " << x_ji << std::endl; + LOG(INFO) << "OSNMA Merkletree - Size string (bytes): " << x_ji.size(); + LOG(INFO) << "OSNMA Merkletree - m_" << j << "_" << i << " = " << x_ji; if (j == 4 && i == 0) { d_x_4_0 = convert_from_hex_str(x_ji); @@ -232,15 +242,11 @@ void Gnss_Crypto::read_merkle_xml(const std::string& merkleFilePath) d_x_0_1 = convert_from_hex_str("AA1A8B68E5DB293106B5BC8806F9790E8ACF8DC2D28A6EF6C1AC7233A9813D3F"); return; } - std::cout << "Merkle Tree successfully read from file " << merkleFilePath << std::endl; + std::cout << "OSNMA Merkle Tree successfully read from file " << merkleFilePath << std::endl; + LOG(INFO) << "OSNMA Merkle Tree successfully read from file " << merkleFilePath; } -// void Gnss_Crypto::set_public_key(const std::vector& publickey) -// { -// } - - std::vector Gnss_Crypto::computeSHA256(const std::vector& input) const { std::vector output(32); // SHA256 hash size @@ -273,7 +279,7 @@ std::vector Gnss_Crypto::computeSHA256(const std::vector& inpu SHA256_Update(&sha256Context, input.data(), input.size()); SHA256_Final(output.data(), &sha256Context); #endif -#else +#else // GnuTLS std::vector output_aux(32); gnutls_hash_hd_t hashHandle; gnutls_hash_init(&hashHandle, GNUTLS_DIG_SHA256); @@ -301,7 +307,7 @@ std::vector Gnss_Crypto::computeSHA3_256(const std::vector& in #else // SHA3-256 not implemented in OpenSSL < 3.0 #endif -#else +#else // GnuTLS std::vector output_aux(32); gnutls_hash_hd_t hashHandle; gnutls_hash_init(&hashHandle, GNUTLS_DIG_SHA3_256); @@ -320,23 +326,58 @@ std::vector Gnss_Crypto::computeHMAC_SHA_256(const std::vector #if USE_OPENSSL_FALLBACK #if USE_OPENSSL_3 std::vector hmac(EVP_MAX_MD_SIZE); + size_t output_length = 0; + // Create the context for the HMAC operation + EVP_MAC* mac = EVP_MAC_fetch(nullptr, "HMAC", nullptr); + if (!mac) + { + LOG(WARNING) << "OSNMA HMAC_SHA_256 computation failed to fetch HMAC"; + return output; + } - // 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()); + EVP_MAC_CTX* ctx = EVP_MAC_CTX_new(mac); + if (!ctx) + { + EVP_MAC_free(mac); + LOG(WARNING) << "OSNMA HMAC_SHA_256 computation failed to create HMAC context"; + return output; + } - // Initialize HMAC-SHA256 context - EVP_DigestSignInit(ctx, nullptr, EVP_sha256(), nullptr, pkey); + // Initialize the HMAC context with the key and the SHA-256 algorithm + OSSL_PARAM params[] = { + OSSL_PARAM_construct_utf8_string(OSSL_ALG_PARAM_DIGEST, const_cast("SHA256"), 0), + OSSL_PARAM_construct_end()}; - // Compute HMAC-SHA256 - EVP_DigestSignUpdate(ctx, input.data(), input.size()); - size_t macLength; - EVP_DigestSignFinal(ctx, hmac.data(), &macLength); + if (EVP_MAC_init(ctx, key.data(), key.size(), params) <= 0) + { + EVP_MAC_CTX_free(ctx); + EVP_MAC_free(mac); + LOG(WARNING) << "OSNMA HMAC_SHA_256 computation failed to initialize HMAC context"; + return output; + } - EVP_PKEY_free(pkey); - EVP_MD_CTX_free(ctx); + // Update the HMAC context with the input data + if (EVP_MAC_update(ctx, input.data(), input.size()) <= 0) + { + EVP_MAC_CTX_free(ctx); + EVP_MAC_free(mac); + LOG(WARNING) << "OSNMA HMAC_SHA_256 computation failed to update HMAC context"; + return output; + } - hmac.resize(macLength); + // Finalize the HMAC and retrieve the output + if (EVP_MAC_final(ctx, hmac.data(), &output_length, hmac.size()) <= 0) + { + EVP_MAC_CTX_free(ctx); + EVP_MAC_free(mac); + LOG(WARNING) << "OSNMA HMAC_SHA_256 computation failed to finalize HMAC"; + return output; + } + + // Clean up the HMAC context + EVP_MAC_CTX_free(ctx); + EVP_MAC_free(mac); + hmac.resize(output_length); output = hmac; #else std::vector hmac(32); @@ -358,7 +399,7 @@ std::vector Gnss_Crypto::computeHMAC_SHA_256(const std::vector hmac.resize(hmacLen); output = hmac; #endif -#else +#else // GnuTLS std::vector output_aux(32); gnutls_hmac_hd_t hmac; gnutls_hmac_init(&hmac, GNUTLS_MAC_SHA256, key.data(), key.size()); @@ -376,35 +417,62 @@ std::vector Gnss_Crypto::computeCMAC_AES(const std::vector& ke std::vector output(16); #if USE_OPENSSL_FALLBACK #if USE_OPENSSL_3 - std::vector mac(EVP_MAX_MD_SIZE); // CMAC-AES output size + std::vector aux(EVP_MAX_MD_SIZE); // CMAC-AES output size + size_t output_length = 0; - EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new(); - EVP_MAC* cmac = EVP_MAC_fetch(nullptr, "CMAC-AES", nullptr); + // Create the context for the CMAC operation + EVP_MAC* mac = EVP_MAC_fetch(nullptr, "CMAC", nullptr); + if (!mac) + { + LOG(INFO) << "OSNMA CMAC-AES: Failed to fetch CMAC"; + return output; + } - EVP_MAC_CTX* cmacCtx = EVP_MAC_CTX_new(cmac); + EVP_MAC_CTX* ctx = EVP_MAC_CTX_new(mac); + if (!ctx) + { + LOG(INFO) << "OSNMA CMAC-AES: Failed to create CMAC context"; + return output; + } - 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", nullptr, 0); // Set IV to nullptr - params[2] = OSSL_PARAM_construct_octet_string("aad", nullptr, 0); // Set AAD to nullptr - params[3] = OSSL_PARAM_construct_end(); + // Initialize the CMAC context with the key and the AES algorithm + OSSL_PARAM params[] = { + OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_CIPHER, const_cast("AES-128-CBC"), 0), + OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY, const_cast(key.data()), key.size()), + OSSL_PARAM_construct_end()}; - // Set AES-128 CMAC cipher and key - EVP_MAC_init(cmacCtx, nullptr, 0, params); + if (EVP_MAC_init(ctx, nullptr, 0, params) <= 0) + { + EVP_MAC_CTX_free(ctx); + EVP_MAC_free(mac); + LOG(INFO) << "OSNMA CMAC-AES: Failed to initialize CMAC context"; + return output; + } - // Compute CMAC-AES - EVP_MAC_update(cmacCtx, input.data(), input.size()); - size_t macLength = mac.size(); - size_t outputLength = 16; + // Update the CMAC context with the input data + if (EVP_MAC_update(ctx, input.data(), input.size()) <= 0) + { + EVP_MAC_CTX_free(ctx); + EVP_MAC_free(mac); + LOG(INFO) << "OSNMA CMAC-AES: Failed to update CMAC context"; + return output; + } - EVP_MAC_final(cmacCtx, mac.data(), &macLength, outputLength); + // Finalize the CMAC and retrieve the output + if (EVP_MAC_final(ctx, aux.data(), &output_length, aux.size()) <= 0) + { + EVP_MAC_CTX_free(ctx); + EVP_MAC_free(mac); + LOG(INFO) << "OSNMA CMAC-AES: Failed to finalize CMAC"; + return output; + } - EVP_MAC_free(cmac); - EVP_MAC_CTX_free(cmacCtx); - EVP_CIPHER_CTX_free(ctx); + // Clean up the CMAC context + EVP_MAC_CTX_free(ctx); + EVP_MAC_free(mac); - mac.resize(macLength); - output = mac; + aux.resize(output_length); + output = aux; #else std::vector mac(16); // CMAC-AES output size @@ -421,7 +489,7 @@ std::vector Gnss_Crypto::computeCMAC_AES(const std::vector& ke output = mac; #endif -#else +#else // GnuTLS gnutls_cipher_hd_t cipher; std::vector mac(16); std::vector message = input; @@ -468,11 +536,11 @@ void Gnss_Crypto::readPublicKeyFromPEM(const std::string& pemFilePath) BIO_free(bio); if (d_PublicKey == nullptr) { - std::cerr << "OpenSSL: error reading the Public Key from file " << pemFilePath << ". Aborting import" << std::endl; + 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 +#else // GnuTLS // Import the PEM data gnutls_datum_t pemDatum = {const_cast(reinterpret_cast(pemContent.data())), static_cast(pemContent.size())}; gnutls_pubkey_t pubkey; @@ -482,73 +550,120 @@ void Gnss_Crypto::readPublicKeyFromPEM(const std::string& pemFilePath) if (ret != GNUTLS_E_SUCCESS) { gnutls_pubkey_deinit(pubkey); - std::cerr << "GnuTLS: error reading the Public Key from file " + std::cerr << "GnuTLS: error reading the OSNMA Public Key from file " << pemFilePath << ". Aborting import" << std::endl; std::cerr << "GnuTLS error: " << gnutls_strerror(ret) << std::endl; + LOG(INFO) << "GnuTLS: error reading the OSNMA Public Key from file " << pemFilePath << ". Aborting import"; return; } pubkey_copy(pubkey, &d_PublicKey); gnutls_pubkey_deinit(pubkey); #endif - std::cout << "Public key successfully read from file " << pemFilePath << std::endl; - //print_pubkey_hex(d_PublicKey); + std::cout << "OSNMA Public key successfully read from file " << pemFilePath << std::endl; + LOG(INFO) << "OSNMA Public key successfully read from file " << pemFilePath; } -bool Gnss_Crypto::verify_signature(const std::vector& message, const std::vector& signature) +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 buffer((std::istreambuf_iterator(crtFile)), std::istreambuf_iterator()); + 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 (!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); + BIO_free(bio); + X509_free(cert); +#else // GnuTLS + // Open the .crt file + std::ifstream crtFile(crtFilePath, std::ios::binary); + if (!crtFile.is_open()) + { + // CRT file not found + // If it was not the default, maybe it is a configuration error + if (crtFilePath != CRTFILE_DEFAULT) + { + std::cerr << "File " << crtFilePath << " not found" << std::endl; + } + return false; + } + + std::vector buffer((std::istreambuf_iterator(crtFile)), std::istreambuf_iterator()); + + gnutls_x509_crt_t cert; + gnutls_x509_crt_init(&cert); + int ret = gnutls_x509_crt_import(cert, (const gnutls_datum_t*)&buffer, GNUTLS_X509_FMT_PEM); + if (ret < 0) + { + std::cerr << "Failed to import certificate: " << gnutls_strerror(ret) << std::endl; + gnutls_x509_crt_deinit(cert); + return false; + } + + gnutls_pubkey_t pubkey; + gnutls_pubkey_init(&pubkey); + + ret = gnutls_pubkey_import_x509(pubkey, cert, 0); + if (ret < 0) + { + std::cerr << "Failed to import public key: " << gnutls_strerror(ret) << std::endl; + gnutls_pubkey_deinit(pubkey); + gnutls_x509_crt_deinit(cert); + return false; + } + pubkey_copy(pubkey, &d_PublicKey); + gnutls_x509_crt_deinit(cert); + gnutls_pubkey_deinit(pubkey); +#endif + std::cout << "OSNMA Public key successfully read from file " << crtFilePath << std::endl; + LOG(INFO) << "OSNMA Public key successfully read from file " << crtFilePath; + return true; +} + + +bool Gnss_Crypto::verify_signature(const std::vector& message, const std::vector& signature) const { std::vector digest = this->computeSHA256(message); if (!have_public_key()) { - std::cerr << "Galileo OSNMA::Kroot verification error::Public key not available"<< std::endl; + std::cerr << "Galileo OSNMA KROOT verification error: Public key is not available" << std::endl; return false; } bool success = false; #if USE_OPENSSL_FALLBACK -// using low-level API to test function -- it works in unit tests, not in real bytes. -// EVP_MD_CTX *mdctx = NULL; // verification context; a struct that wraps the message to be verified. -// int ret = 0; // error -// -// /* Create the Message Digest Context */ -// if(!(mdctx = EVP_MD_CTX_new())) goto err; // Allocates and returns a digest context. -// -// /* Initialize `key` with a public key */ -// // hashes cnt bytes of data at d into the verification context ctx -// if(1 != EVP_DigestVerifyInit(mdctx, NULL /*TODO null?*/, EVP_sha256(), NULL, d_PublicKey)) goto err; -// -// /* Initialize `key` with a public key */ -// if(1 != EVP_DigestVerifyUpdate(mdctx, message.data(), message.size())) goto err; -// -// -// if( 1 == EVP_DigestVerifyFinal(mdctx, signature.data(), signature.size())) -// { -// return true; -// } -// else -// { -// unsigned long errCode = ERR_get_error(); -// int lib_code = ERR_GET_LIB(errCode); -// char* err = ERR_error_string(errCode, NULL); -// const char* error_string = ERR_error_string(errCode, NULL); -// std::cerr << "OpenSSL: message authentication failed: " << err /*<< -// "from library with code " << lib_code << -// " error string: " << error_string */<< std::endl; -// } -//err: -// if(ret != 1) -// { -// /* Do some error handling */ -// // notify other blocks -// std::cout << "ECDSA_Verify_OSSL()::error " << ret << std::endl; -// -// } - - #if USE_OPENSSL_3 EVP_PKEY_CTX* ctx; - //print_pubkey_hex(d_PublicKey); ctx = EVP_PKEY_CTX_new(d_PublicKey, nullptr); bool do_operation = true; @@ -556,7 +671,7 @@ bool Gnss_Crypto::verify_signature(const std::vector& message, const st { do_operation = false; } - // convert raw signature into DER format, needed for verify_signature + // convert raw signature into DER format size_t half_size = signature.size() / 2; std::vector raw_r(signature.begin(), signature.begin() + half_size); std::vector raw_s(signature.begin() + half_size, signature.end()); @@ -575,12 +690,12 @@ bool Gnss_Crypto::verify_signature(const std::vector& message, const st if (ECDSA_SIG_set0(sig, r, s) != 1) { std::cerr << "Failed to set R and S values in ECDSA_SIG" << std::endl; - ECDSA_SIG_free(sig); // Free the ECDSA_SIG struct as it's no longer needed + ECDSA_SIG_free(sig); // Free the ECDSA_SIG struct as it is no longer needed return false; } std::vector derSignature; - unsigned char *derSig = nullptr; + unsigned char* derSig = nullptr; int derSigLength = i2d_ECDSA_SIG(sig, &derSig); if (derSigLength <= 0) @@ -591,7 +706,6 @@ bool Gnss_Crypto::verify_signature(const std::vector& message, const st derSignature.assign(derSig, derSig + derSigLength); - if (EVP_PKEY_verify_init(ctx) <= 0) { do_operation = false; @@ -611,19 +725,21 @@ bool Gnss_Crypto::verify_signature(const std::vector& message, const st if (verification == 1) { success = true; + LOG(INFO) << "OpenSSL: OSNMA signature authenticated successfully"; } else { unsigned long errCode = ERR_get_error(); - char* err = ERR_error_string(errCode, NULL); - std::cerr << "OpenSSL: message authentication failed: " << err << std::endl; + char* err = ERR_error_string(errCode, nullptr); + std::cerr << "OpenSSL: OSNMA message authentication failed: " << err << std::endl; + LOG(WARNING) << "OpenSSL: OSNMA message authentication failed: " << err; } #else - auto digest = this->computeSHA256(message); int verification = ECDSA_verify(0, digest.data(), SHA256_DIGEST_LENGTH, signature.data(), static_cast(signature.size()), d_PublicKey); if (verification == 1) { success = true; + LOG(INFO) << "OpenSSL: OSNMA signature authenticated successfully"; } else if (verification == 0) { @@ -631,38 +747,35 @@ bool Gnss_Crypto::verify_signature(const std::vector& message, const st } else { - std::cerr << "OpenSSL: message authentication failed" << std::endl; + std::cerr << "OpenSSL: OSNMA message authentication failed" << std::endl; + LOG(WARNING) << "OpenSSL: OSNMA message authentication failed"; } - #endif -#else - // GNU-TLS - gnutls_global_init(); - // debug info gnu-tls remove when not needed anymore! - gnutls_global_set_log_level(9); - gnutls_global_set_log_function(Gnss_Crypto::my_log_func); - - unsigned int bit_size; - if (gnutls_pubkey_get_pk_algorithm(d_PublicKey, &bit_size) != GNUTLS_PK_ECDSA) +#else // GnuTLS + // Convert signature to DER format + std::vector der_sig; + if (!convert_raw_to_der_ecdsa(signature, der_sig)) { - std::cerr << "GnuTLS: the Public Key does not contain a ECDSA key. Aborting signature verification" << std::endl; + std::cerr << "Failed to convert raw ECDSA signature to DER format" << std::endl; + return false; } - gnutls_datum_t signature_{}; - signature_.data = const_cast(signature.data()); - signature_.size = signature.size(); - gnutls_datum_t data_{}; - data_.data = const_cast(message.data()); - data_.size = message.size(); - int ret = gnutls_pubkey_verify_data2(d_PublicKey, GNUTLS_SIGN_ECDSA_SHA256, 0, &data_, &signature_); - if (ret >= 0) + + // Prepare the digest datum + gnutls_datum_t digest_data = {const_cast(digest.data()), static_cast(digest.size())}; + gnutls_datum_t der_sig_data = {der_sig.data(), static_cast(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) { - success = true; + LOG(INFO) << "GnuTLS: OSNMA signature authenticated successfully"; } else { - std::cerr << "GnuTLS error: " << gnutls_strerror(ret) << std::endl; + std::cerr << "GnuTLS: OSNMA message authentication failed: " << gnutls_strerror(ret) << std::endl; + LOG(WARNING) << "GnuTLS: OSNMA message authentication failed: " << gnutls_strerror(ret); } - gnutls_global_deinit(); #endif return success; } @@ -707,82 +820,56 @@ std::vector Gnss_Crypto::getMerkleRoot(const std::vector& publicKey) { #if USE_OPENSSL_FALLBACK - BIO *bio = NULL; - EVP_PKEY *pkey = NULL; + BIO* bio = nullptr; + EVP_PKEY* pkey = nullptr; bio = BIO_new_mem_buf(publicKey.data(), publicKey.size()); - if (!bio) { + if (!bio) + { std::cerr << "Failed to create BIO for key \n"; return; } - pkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL); - BIO_free(bio); + pkey = PEM_read_bio_PUBKEY(bio, nullptr, nullptr, nullptr); + BIO_free(bio); - if (!pkey) { - std::cerr << "OpenSSL: error setting the public key " - << ". Aborting import" << std::endl; + if (!pkey) + { + std::cerr << "OpenSSL: error setting the OSNMA public key." << std::endl; + LOG(INFO) << "OpenSSL: error setting the OSNMA public key."; return; } - //print_pubkey_hex(pkey); - - if(!pubkey_copy(pkey, &d_PublicKey)) - return - - EVP_PKEY_free(pkey); -#else -// // GNU-TLS -// gnutls_global_init(); -// -// // debug info gnu-tls remove when not needed anymore! -// gnutls_global_set_log_level(9); -// gnutls_global_set_log_function(Gnss_Crypto::my_log_func); + if (!pubkey_copy(pkey, &d_PublicKey)) + { + return; + } + EVP_PKEY_free(pkey); +#else // GnuTLS gnutls_pubkey_t pubkey; gnutls_datum_t pemDatum = {const_cast(publicKey.data()), static_cast(publicKey.size())}; gnutls_pubkey_init(&pubkey); int ret = gnutls_pubkey_import(pubkey, &pemDatum, GNUTLS_X509_FMT_PEM); - //ret = gnutls_pubkey_import_x509_raw(pubkey, &pemDatum,GNUTLS_X509_FMT_PEM,0); if (ret != GNUTLS_E_SUCCESS) { gnutls_pubkey_deinit(pubkey); - std::cerr << "GnuTLS: error setting the public key " - << ". Aborting import" << std::endl; + std::cerr << "GnuTLS: error setting the public key" << std::endl; std::cerr << "GnuTLS error: " << gnutls_strerror(ret) << std::endl; return; } - // d_PublicKey = pubkey; pubkey_copy(pubkey, &d_PublicKey); -// std::cout << "pubkey: " << std::endl; -// print_pubkey_hex(pubkey); -// std::cout << "d_PublicKey before : " << std::endl; -// print_pubkey_hex(d_PublicKey); gnutls_pubkey_deinit(pubkey); -// std::cout << "d_PublicKey after: " << std::endl; -// print_pubkey_hex(d_PublicKey); - -// gnutls_global_deinit(); #endif - + LOG(INFO) << "OSNMA Public Key successfully set up."; } -std::vector Gnss_Crypto::get_public_key() -{ -#if USE_OPENSSL_FALLBACK - // TODO -#else -// GNU-TLS - // TODO -#endif - return {}; -} #if USE_OPENSSL_FALLBACK bool Gnss_Crypto::pubkey_copy(EVP_PKEY* src, EVP_PKEY** dest) { // Open a memory buffer BIO* mem_bio = BIO_new(BIO_s_mem()); - if (mem_bio == NULL) + if (mem_bio == nullptr) { return false; } @@ -794,24 +881,21 @@ bool Gnss_Crypto::pubkey_copy(EVP_PKEY* src, EVP_PKEY** dest) return false; } - // Add a null-terminator to the data in the memory buffer - //BIO_write(mem_bio, "\0", 1); - // Read the data from the memory buffer char* bio_data; long data_len = BIO_get_mem_data(mem_bio, &bio_data); // Create a new memory buffer and load the data into it BIO* mem_bio2 = BIO_new_mem_buf(bio_data, data_len); - if (mem_bio2 == NULL) + if (mem_bio2 == nullptr) { BIO_free(mem_bio); return false; } // Read the public key from the new memory buffer - *dest = PEM_read_bio_PUBKEY(mem_bio2, NULL, NULL, NULL); - if (*dest == NULL) + *dest = PEM_read_bio_PUBKEY(mem_bio2, nullptr, nullptr, nullptr); + if (*dest == nullptr) { BIO_free(mem_bio); BIO_free(mem_bio2); @@ -824,95 +908,87 @@ bool Gnss_Crypto::pubkey_copy(EVP_PKEY* src, EVP_PKEY** dest) return true; } -void Gnss_Crypto::print_pubkey_hex(EVP_PKEY* pubkey) + +#else // GnuTLS-specific functions + +bool Gnss_Crypto::convert_raw_to_der_ecdsa(const std::vector& raw_signature, std::vector& der_signature) const { - BIO* mem_bio = BIO_new(BIO_s_mem()); - if (!mem_bio) { - std::cerr << "Failed to create new memory BIO\n"; - return; + if (raw_signature.size() % 2 != 0) + { + std::cerr << "Invalid raw ECDSA signature size" << std::endl; + return false; } - if (!PEM_write_bio_PUBKEY(mem_bio, pubkey)){ - std::cerr << "Failed to write public key to BIO\n"; - BIO_free(mem_bio); - return; + size_t half_size = raw_signature.size() / 2; + std::vector raw_r(raw_signature.begin(), raw_signature.begin() + half_size); + std::vector raw_s(raw_signature.begin() + half_size, raw_signature.end()); + + auto encode_asn1_integer = [](const std::vector& value) -> std::vector { + std::vector result; + result.push_back(0x02); // INTEGER tag + + if (value[0] & 0x80) + { + result.push_back(value.size() + 1); // Length byte + result.push_back(0x00); // Add leading zero byte to ensure positive integer + } + else + { + result.push_back(value.size()); // Length byte + } + + result.insert(result.end(), value.begin(), value.end()); + return result; + }; + + std::vector der_r = encode_asn1_integer(raw_r); + std::vector der_s = encode_asn1_integer(raw_s); + + size_t total_length = der_r.size() + der_s.size(); + der_signature.push_back(0x30); // SEQUENCE tag + if (total_length > 127) + { + der_signature.push_back(0x81); // Long form length } + der_signature.push_back(static_cast(total_length)); - BUF_MEM* mem_ptr; - BIO_get_mem_ptr(mem_bio, &mem_ptr); // Fetch the underlying BUF_MEM structure from the BIO. + der_signature.insert(der_signature.end(), der_r.begin(), der_r.end()); + der_signature.insert(der_signature.end(), der_s.begin(), der_s.end()); - std::stringstream ss; - - // Iterate through each byte in mem_ptr->data and print its hex value. - for (size_t i = 0; i < mem_ptr->length; i++) { - ss << std::hex << std::setw(2) << std::setfill('0') << - static_cast(static_cast(mem_ptr->data[i])); - } - - //std::cout << "Public key in hex format: 0x" << ss.str() << std::endl; - - BIO_free(mem_bio); + return true; } -#else // gnutls-specific functions - void Gnss_Crypto::my_log_func(int level, const char *msg){ - fprintf(stderr, " %s", level, msg);} - bool Gnss_Crypto::pubkey_copy(gnutls_pubkey_t src, gnutls_pubkey_t* dest) - { - gnutls_datum_t key_datum; - int ret; - // Export the public key from src to memory - ret = gnutls_pubkey_export2(src, GNUTLS_X509_FMT_PEM, &key_datum); - if (ret < 0) - { - gnutls_free(key_datum.data); - return false; - } +bool Gnss_Crypto::pubkey_copy(gnutls_pubkey_t src, gnutls_pubkey_t* dest) +{ + gnutls_datum_t key_datum; - // Initialize dest - ret = gnutls_pubkey_init(dest); - if (ret < 0) - { - gnutls_free(key_datum.data); - return false; - } + // 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; + } - // 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); + // Initialize dest + ret = gnutls_pubkey_init(dest); + if (ret < 0) + { + gnutls_free(key_datum.data); + return false; + } - if (ret < 0) - { - gnutls_pubkey_deinit(*dest); - 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); - return true; - } + if (ret < 0) + { + gnutls_pubkey_deinit(*dest); + return false; + } - void Gnss_Crypto::print_pubkey_hex(gnutls_pubkey_t pubkey) - { - gnutls_datum_t key_datum; - int ret; - - // Export the public key from pubkey to memory in DER format - ret = gnutls_pubkey_export2(pubkey, GNUTLS_X509_FMT_PEM, &key_datum); - if (ret < 0) { - std::cerr << "Failed to export public key: " << gnutls_strerror(ret) << std::endl; - return; - } - - std::stringstream ss; - - // Iterate through each byte in key_datum.data and print its hex value - for (unsigned int i = 0; i < key_datum.size; ++i) { - ss << std::hex << std::setw(2) << std::setfill('0') << static_cast(key_datum.data[i]); - } - - std::cout << "Public key in hex format: 0x" << ss.str() << std::endl; - - // Free the memory allocated to key_datum.data - gnutls_free(key_datum.data); - } + return true; +} #endif diff --git a/src/core/system_parameters/gnss_crypto.h b/src/core/system_parameters/gnss_crypto.h index 1191a7ed5..9d60c8a77 100644 --- a/src/core/system_parameters/gnss_crypto.h +++ b/src/core/system_parameters/gnss_crypto.h @@ -1,7 +1,8 @@ /*! * \file gnss_crypto.h - * \brief Class for computing cryptografic functions - * \author Carles Fernandez, 2023. cfernandez(at)cttc.es + * \brief Class for computing cryptographic functions + * \author Carles Fernandez, 2023-2024. cfernandez(at)cttc.es + * Cesare Ghionoiu Martinez, 2023-2024. c.ghionoiu-martinez@tu-braunschweig.de * * * ----------------------------------------------------------------------------- @@ -9,7 +10,7 @@ * 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) + * Copyright (C) 2010-2024 (see AUTHORS file for a list of contributors) * SPDX-License-Identifier: GPL-3.0-or-later * * ----------------------------------------------------------------------------- @@ -35,43 +36,39 @@ class Gnss_Crypto { public: - Gnss_Crypto() = default; + Gnss_Crypto(); + Gnss_Crypto(const std::string& certFilePath, const std::string& merkleTreePath); ~Gnss_Crypto(); - Gnss_Crypto(const std::string& pemFilePath, const std::string& merkleTreePath); + + void set_public_key(const std::vector& publickey); bool have_public_key() const; - std::string convert_to_utf8_str(const std::vector& input) const; - std::vector convert_from_hex_str(const std::string& input) const; + bool verify_signature(const std::vector& message, const std::vector& signature) const; std::vector computeSHA256(const std::vector& input) const; std::vector computeSHA3_256(const std::vector& input) const; std::vector computeHMAC_SHA_256(const std::vector& key, const std::vector& input) const; std::vector computeCMAC_AES(const std::vector& key, const std::vector& input) const; - - bool verify_signature(const std::vector& message, const std::vector& signature); - void readPublicKeyFromPEM(const std::string& pemFilePath); - void read_merkle_xml(const std::string& merkleFilePath); std::vector getMerkleRoot(const std::vector>& merkle) const; - std::vector getMerkleRoot() const + + inline std::vector getMerkleRoot() const { return d_x_4_0; } - void set_public_key(const std::vector& publickey); - static std::vector get_public_key(); - private: + void read_merkle_xml(const std::string& merkleFilePath); + void readPublicKeyFromPEM(const std::string& pemFilePath); + bool readPublicKeyFromCRT(const std::string& crtFilePath); + std::vector convert_from_hex_str(const std::string& input) const; #if USE_OPENSSL_FALLBACK - bool pubkey_copy(EVP_PKEY* src, EVP_PKEY** dest); - void print_pubkey_hex(EVP_PKEY* pubkey); #if USE_OPENSSL_3 EVP_PKEY* d_PublicKey{}; #else EC_KEY* d_PublicKey = nullptr; #endif -#else + bool pubkey_copy(EVP_PKEY* src, EVP_PKEY** dest); +#else // GnuTLS gnutls_pubkey_t d_PublicKey{}; - void set_ecc_key(const std::vector& pK, const std::vector ecP); - static void my_log_func(int level, const char* msg); - void print_pubkey_hex(gnutls_pubkey_t); + bool convert_raw_to_der_ecdsa(const std::vector& raw_signature, std::vector& der_signature) const; bool pubkey_copy(gnutls_pubkey_t src, gnutls_pubkey_t* dest); #endif std::vector d_x_4_0; diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt index 97bbac838..8de611f5f 100644 --- a/src/tests/CMakeLists.txt +++ b/src/tests/CMakeLists.txt @@ -1344,52 +1344,14 @@ else() endif() endif() -######################################################### gnss_crypto_test - -if(NOT ENABLE_PACKAGING AND NOT ENABLE_FPGA) - set(GNSS_CRYPTO_TEST_SOURCES - ${CMAKE_CURRENT_SOURCE_DIR}/single_test_main.cc - ${CMAKE_CURRENT_SOURCE_DIR}/unit-tests/signal-processing-blocks/osnma/gnss_crypto_test.cc) - - if(USE_CMAKE_TARGET_SOURCES) - add_executable(gnss_crypto_test) - target_sources(gnss_crypto_test PRIVATE ${GNSS_CRYPTO_TEST_SOURCES}) - else() - add_executable(gnss_crypto_test ${GNSS_CRYPTO_TEST_SOURCES}) - endif() - - target_link_libraries(gnss_crypto_test - PRIVATE - Boost::thread - GTest::GTest - GTest::Main - core_system_parameters - Pugixml::pugixml - ) - if(ENABLE_GLOG_AND_GFLAGS) - target_link_libraries(gnss_crypto_test PRIVATE Gflags::gflags Glog::glog) - target_compile_definitions(gnss_crypto_test PRIVATE -DUSE_GLOG_AND_GFLAGS=1) - else() - target_link_libraries(gnss_crypto_test PRIVATE absl::flags absl::flags_parse absl::log $ absl::log_initialize) - endif() - - target_include_directories(gnss_crypto_test - PRIVATE - ${GNSSSDR_SOURCE_DIR}/src/core/system_parameters) - - xcode_remove_warning_duplicates(gnss_crypto_test) # TODO - unsure if needed - - add_test(gnss_crypto_test gnss_crypto_test) - - set_property(TEST gnss_crypto_test PROPERTY TIMEOUT 1) -endif() ######################################################### osnma_msg_receiver_test if(NOT ENABLE_PACKAGING AND NOT ENABLE_FPGA) set(OSNMA_MSG_RECEIVER_TEST_SOURCES - ${CMAKE_CURRENT_SOURCE_DIR}/single_test_main.cc - ${CMAKE_CURRENT_SOURCE_DIR}/unit-tests/signal-processing-blocks/osnma/osnma_msg_receiver_test.cc) + ${CMAKE_CURRENT_SOURCE_DIR}/single_test_main.cc + ${CMAKE_CURRENT_SOURCE_DIR}/unit-tests/signal-processing-blocks/osnma/osnma_msg_receiver_test.cc + ) if(USE_CMAKE_TARGET_SOURCES) add_executable(osnma_msg_receiver_test) @@ -1399,7 +1361,8 @@ if(NOT ENABLE_PACKAGING AND NOT ENABLE_FPGA) endif() target_link_libraries(osnma_msg_receiver_test - PRIVATE + PRIVATE + gnss_sdr_flags Boost::thread GTest::GTest GTest::Main @@ -1416,11 +1379,12 @@ if(NOT ENABLE_PACKAGING AND NOT ENABLE_FPGA) add_test(osnma_msg_receiver_test osnma_msg_receiver_test) - set_property(TEST osnma_msg_receiver_test PROPERTY TIMEOUT 1) + set_property(TEST osnma_msg_receiver_test PROPERTY TIMEOUT 30) target_include_directories(osnma_msg_receiver_test - PRIVATE - ${GNSSSDR_SOURCE_DIR}/src/core/system_parameters) + PRIVATE + ${GNSSSDR_SOURCE_DIR}/src/core/system_parameters + ) endif() if(ENABLE_BENCHMARKS) diff --git a/src/tests/single_test_main.cc b/src/tests/single_test_main.cc index beece7581..c0a6e1dee 100644 --- a/src/tests/single_test_main.cc +++ b/src/tests/single_test_main.cc @@ -19,6 +19,7 @@ #include "concurrent_map.h" #include "concurrent_queue.h" #include "gps_acq_assist.h" +#include "gnss_sdr_flags.h" #include #include #include @@ -36,7 +37,6 @@ using namespace google; DECLARE_string(log_dir); #endif #else -#include "gnss_sdr_flags.h" #include #include #include @@ -44,7 +44,6 @@ DECLARE_string(log_dir); #include #include #include - class TestLogSink : public absl::LogSink { public: diff --git a/src/tests/test_main.cc b/src/tests/test_main.cc index 8611d44b8..7990ca258 100644 --- a/src/tests/test_main.cc +++ b/src/tests/test_main.cc @@ -113,7 +113,7 @@ private: #include "unit-tests/signal-processing-blocks/adapter/pass_through_test.cc" #include "unit-tests/signal-processing-blocks/libs/item_type_helpers_test.cc" #include "unit-tests/signal-processing-blocks/osnma/gnss_crypto_test.cc" -#include "unit-tests/signal-processing-blocks/osnma/osnma_msg_receiver_test.cc" +// #include "unit-tests/signal-processing-blocks/osnma/osnma_msg_receiver_test.cc" #include "unit-tests/signal-processing-blocks/pvt/geohash_test.cc" #include "unit-tests/signal-processing-blocks/pvt/nmea_printer_test.cc" #include "unit-tests/signal-processing-blocks/pvt/rinex_printer_test.cc" diff --git a/src/tests/unit-tests/signal-processing-blocks/osnma/gnss_crypto_test.cc b/src/tests/unit-tests/signal-processing-blocks/osnma/gnss_crypto_test.cc index a72d86998..87f5afbfa 100644 --- a/src/tests/unit-tests/signal-processing-blocks/osnma/gnss_crypto_test.cc +++ b/src/tests/unit-tests/signal-processing-blocks/osnma/gnss_crypto_test.cc @@ -1,192 +1,115 @@ -#include #include "gnss_crypto.h" +#include class GnssCryptoTest : public ::testing::Test { - }; -TEST(GnssCryptoTest, VerifySignature) { - // "../data/OSNMA_PublicKey_20240115100000_newPKID_1.pem" - std::unique_ptr d_crypto = std::make_unique(); - -// RG example - import crt certificate - result: FAIL -std::vector message = {0x82, 0x10, 0x49, 0x22, 0x04, 0xE0, 0x60, 0x61, 0x0B, 0xDF, 0x26, 0xD7, 0x7B, 0x5B, 0xF8, 0xC9, 0xCB, 0xFC, 0xF7, 0x04, 0x22, 0x08, 0x14, 0x75, 0xFD, 0x44, 0x5D, 0xF0, 0xFF}; -std::vector signature = {0xF8, 0xCD, 0x88, 0x29, 0x9F, 0xA4, 0x60, 0x58, 0x00, 0x20, 0x7B, 0xFE, 0xBE, 0xAC, 0x55, 0x02, 0x40, 0x53, 0xF3, 0x0F, 0x7C, 0x69, 0xB3, 0x5C, 0x15, 0xE6, 0x08, 0x00, 0xAC, 0x3B, 0x6F, 0xE3, 0xED, 0x06, 0x39, 0x95, 0x2F, 0x7B, 0x02, 0x8D, 0x86, 0x86, 0x74, 0x45, 0x96, 0x1F, 0xFE, 0x94, 0xFB, 0x22, 0x6B, 0xFF, 0x70, 0x06, 0xE0, 0xC4, 0x51, 0xEE, 0x3F, 0x87, 0x28, 0xC1, 0x77, 0xFB}; -std::vector publicKey { // PEM format - 1000 bits - 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x50, 0x55, 0x42, 0x4C, 0x49, 0x43, 0x20, 0x4B, 0x45, 0x59, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, - - 0x4D, 0x46, 0x6B, 0x77, 0x45, 0x77, 0x59, 0x48, 0x4B, 0x6F, 0x5A, 0x49, 0x7A, 0x6A, 0x30, 0x43, 0x41, 0x51, 0x59, 0x49, 0x4B, 0x6F, 0x5A, 0x49, - 0x7A, 0x6A, 0x30, 0x44, 0x41, 0x51, 0x63, 0x44, 0x51, 0x67, 0x41, 0x45, 0x41, 0x37, 0x4C, 0x4F, 0x5A, 0x4C, 0x77, 0x67, 0x65, 0x39, 0x32, 0x4C, 0x78, 0x4E, 0x2B, 0x46, 0x6B, 0x59, 0x66, 0x38, 0x74, 0x6F, 0x59, 0x79, 0x44, 0x57, 0x50, 0x2F, 0x0A, 0x6F, 0x4A, 0x46, 0x42, 0x44, 0x38, 0x46, 0x59, 0x2B, 0x37, - 0x64, 0x35, 0x67, 0x4F, 0x71, 0x49, 0x61, 0x45, 0x32, 0x52, 0x6A, 0x50, 0x41, 0x6E, 0x4B, 0x49, 0x36, 0x38, 0x73, 0x2F, 0x4F, 0x4B, 0x2F, 0x48, 0x50, 0x67, 0x6F, 0x4C, 0x6B, 0x4F, 0x32, 0x69, 0x6A, 0x51, 0x38, 0x78, 0x41, 0x5A, 0x79, 0x44, 0x64, 0x50, 0x42, 0x31, 0x64, 0x48, 0x53, 0x51, 0x3D, 0x3D, - - 0x0A, - 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x50, 0x55, 0x42, 0x4C, 0x49, 0x43, 0x20, 0x4B, 0x45, 0x59, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A } ; - - // own ECDSA-P256 key and message generated and signed and verified successfully with openssl -// std::vector message{0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x77, 0x6F, 0x72, 0x6C, 0x64, 0x0A }; // Hello world con 0x0A al final. Raw message (unhashed) -// std::vector signature{0x30, 0x45, 0x02, 0x21, 0x00, 0xFB, 0xE6, 0x09, 0x74, 0x5C, 0x12, 0xE8, 0x2C, 0x0C, 0xC9, 0x7A, 0x8E, 0x13, 0x88, 0x87, 0xDA, 0xBF, 0x08, 0x43, 0xF8, 0xC8, 0x93, 0x16, 0x5A, -// 0x0F, 0x7A, 0xA4, 0xBF, 0x4A, 0xE1, 0xE1, 0xDB, 0x02, 0x20, 0x6B, 0xCB, 0x2F, 0x80, 0x69, 0xBB, 0xDE, 0xC9, 0x11, 0x1D, 0x51, 0x2B, 0x9F, 0x61, 0xA0, 0xC1, 0x29, 0xD1, 0x0B, -// 0x58, 0x09, 0x82, 0x58, 0xFC, 0x9E, 0x00, 0xC7, 0xEE, 0xA5, 0xB9, 0xB2, 0x56}; // Hello world hashed and then encrypted with PrK - // raw r and s values -// std::vector signature = { -// 0x00, 0xFB, 0xE6, 0x09, 0x74, 0x5C, 0x12, 0xE8, 0x2C, 0x0C, 0xC9, 0x7A, 0x8E, 0x13, 0x88, 0x87, 0xDA, 0xBF, 0x08, 0x43, 0xF8, -// 0xC8, 0x93, 0x16, 0x5A, 0x0F, 0x7A, 0xA4, 0xBF, 0x4A, 0xE1, 0xE1, 0xDB, 0x02, 0x20, 0x6B, 0xCB, 0x2F, 0x80, 0x69, 0xBB, 0xDE, -// 0xC9, 0x11, 0x1D, 0x51, 0x2B, 0x9F, 0x61, 0xA0, 0xC1, 0x29, 0xD1, 0x0B, 0x58, 0x09, 0x82, 0x58, 0xFC, 0x9E, 0x00, 0xC7, 0xEE, -// 0xA5, 0xB9, 0xB2, 0x56 }; - - // std::vector publicKey{// PK associated to the PrK, in der format ---test -// 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x4A, 0xF3, -// 0xEE, 0x3A, 0x94, 0x25, 0x25, 0x3D, 0x55, 0xC2, 0x5A, 0xC2, 0x2D, 0xCF, 0x14, 0x4D, 0x39, 0x0D, 0xB1, 0xFC, 0x7F, 0x31, 0x5A, 0x2A, 0x19, 0xAE, 0x4E, 0xD6, 0xCB, 0xA6, 0x59, -// 0xD6, 0x99, 0x7C, 0xE8, 0xBD, 0x1F, 0x43, 0x34, 0x1C, 0x59, 0xD9, 0xD9, 0xCA, 0xC3, 0xEE, 0x58, 0xE5, 0xEA, 0xD3, 0x55, 0x44, 0xEA, 0x89, 0x71, 0x65, 0xD0, 0x92, 0x72, 0xA2, -// 0xC8, 0x3C, 0x87, 0x5D }; -// std::vector publicKey{ // PK associated to the PrK, in pem format -// 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x50, 0x55, 0x42, 0x4C, 0x49, 0x43, 0x20, 0x4B, 0x45, 0x59, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, -// -// 0x4D, 0x46, -// 0x6B, 0x77, 0x45, 0x77, 0x59, 0x48, 0x4B, 0x6F, 0x5A, 0x49, 0x7A, 0x6A, 0x30, 0x43, 0x41, 0x51, 0x59, 0x49, 0x4B, 0x6F, 0x5A, 0x49, 0x7A, 0x6A, 0x30, 0x44, 0x41, 0x51, 0x63, -// 0x44, 0x51, 0x67, 0x41, 0x45, 0x53, 0x76, 0x50, 0x75, 0x4F, 0x70, 0x51, 0x6C, 0x4A, 0x54, 0x31, 0x56, 0x77, 0x6C, 0x72, 0x43, 0x4C, 0x63, 0x38, 0x55, 0x54, 0x54, 0x6B, 0x4E, -// 0x73, 0x66, 0x78, 0x2F, 0x0A, 0x4D, 0x56, 0x6F, 0x71, 0x47, 0x61, 0x35, 0x4F, 0x31, 0x73, 0x75, 0x6D, 0x57, 0x64, 0x61, 0x5A, 0x66, 0x4F, 0x69, 0x39, 0x48, 0x30, 0x4D, 0x30, -// 0x48, 0x46, 0x6E, 0x5A, 0x32, 0x63, 0x72, 0x44, 0x37, 0x6C, 0x6A, 0x6C, 0x36, 0x74, 0x4E, 0x56, 0x52, 0x4F, 0x71, 0x4A, 0x63, 0x57, 0x58, 0x51, 0x6B, 0x6E, 0x4B, 0x69, 0x79, -// 0x44, 0x79, 0x48, 0x58, 0x51, 0x3D, 0x3D, 0x0A, -// -// 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x50, 0x55, 0x42, 0x4C, 0x49, 0x43, 0x20, 0x4B, 0x45, 0x59, 0x2D, 0x2D, -// 0x2D, 0x2D, 0x2D, 0x0A }; - - // own key - GnuTLS error: The curve is unsupported... x192 EC unsupported?? - // std::vector message = {0x68, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x77, 0x6F, 0x72, 0x6C, 0x64 }; // hello world - // std::vector signature = {0x30, 0x34, 0x02, 0x18, 0x4F, 0xAC, 0x9C, 0x5A, 0x44, 0xCF, 0xFD, 0x42, 0x6A, 0x58, 0x97, 0xA4, 0x94, 0x53, 0x2C, 0x79, 0xD1, 0x7B, 0x8B, 0xF9, 0x93, 0x03, 0xA2, 0xAF, 0x02, 0x18, 0x46, 0xF2, 0xF3, 0xCF, 0x9A, 0x23, 0x39, 0xB4, 0x25, 0x11, 0x89, 0x9A, 0x44, 0x7E, 0x2F, 0xB1, 0xE1, 0x58, 0xAF, 0xCE, 0xC1,0xB4, 0xA1, 0x38 }; - // std::vector publicKey = { - // 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x50, 0x55, 0x42, 0x4C, 0x49, 0x43, 0x20, 0x4B, 0x45, 0x59, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x45, 0x6B, 0x77, 0x45, 0x77, 0x59, 0x48, 0x4B, 0x6F, 0x5A, 0x49, 0x7A, 0x6A, 0x30, 0x43, 0x41, 0x51, 0x59, 0x49, 0x4B, 0x6F, 0x5A, 0x49, - // 0x7A, 0x6A, 0x30, 0x44, 0x41, 0x51, 0x49, 0x44, 0x4D, 0x67, 0x41, 0x45, 0x51, 0x55, 0x61, 0x30, 0x6C, 0x38, 0x4D, 0x35, 0x76, 0x50, 0x58, 0x2B, 0x74, 0x4A, 0x76, 0x63, 0x4C, 0x2B, 0x45, 0x45, 0x4C, 0x34, 0x6E, 0x71, 0x79, 0x75, 0x53, 0x43, 0x0A, 0x4D, 0x4E, 0x46, 0x4A, 0x64, 0x43, 0x5A, 0x62, 0x62, 0x58, - // 0x35, 0x70, 0x4D, 0x36, 0x69, 0x4C, 0x52, 0x53, 0x30, 0x43, 0x51, 0x59, 0x45, 0x67, 0x56, 0x47, 0x51, 0x6B, 0x65, 0x75, 0x74, 0x74, 0x35, 0x78, 0x2F, 0x45, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x50, 0x55, 0x42, 0x4C, 0x49, 0x43, 0x20, 0x4B, 0x45, 0x59, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, - // 0x0A }; - // std::vector ecparam = { - // 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x45, 0x43, 0x20, 0x50, 0x41, 0x52, 0x41, 0x4D, 0x45, 0x54, 0x45, 0x52, 0x53, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x42, 0x67, 0x67, 0x71, 0x68, 0x6B, 0x6A, 0x4F, 0x50, 0x51, 0x4D, 0x42, 0x41, 0x67, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, - // 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x45, 0x43, 0x20, 0x50, 0x41, 0x52, 0x41, 0x4D, 0x45, 0x54, 0x45, 0x52, 0x53, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A }; - - d_crypto->set_public_key(publicKey); - bool result = d_crypto->verify_signature(message, signature); - - ASSERT_TRUE(result); - -//TEST(GnssCryptoTest, sha256Test) -//{ -// std::unique_ptr d_crypto; -// -// auto str = "Hello World!"; -// std::vector input (str, str + strlen(str)); -// -// auto expectedOutputStr = "86933b0b147ac4c010266b99004158fa17937db89a03dd7bb2ca5ef7f43c325a"; -// std::vector expectedOutput(expectedOutputStr, expectedOutputStr + strlen(expectedOutputStr)); -// -// std::vector computedOutput = d_crypto->computeSHA256(input); -// -// ASSERT_TRUE(computedOutput == expectedOutput - } - - -TEST(GnssCryptoTest,VerifyPubKeyImport) +TEST(GnssCryptoTest, TestComputeSHA_256) +{ + std::unique_ptr d_crypto = std::make_unique(); + std::vector message{0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x77, 0x6F, 0x72, 0x6C, 0x64, 0x0A}; // Hello world + + std::vector expected_output = { + 0x18, 0x94, 0xA1, 0x9C, 0x85, 0xBA, 0x15, 0x3A, 0xCB, 0xF7, + 0x43, 0xAC, 0x4E, 0x43, 0xFC, 0x00, 0x4C, 0x89, 0x16, 0x04, 0xB2, + 0x6F, 0x8C, 0x69, 0xE1, 0xE8, 0x3E, 0xA2, 0xAF, 0xC7, 0xC4, 0x8F}; + + std::vector output = d_crypto->computeSHA256(message); + + ASSERT_EQ(expected_output, output); +} + + +TEST(GnssCryptoTest, TestComputeSHA3_256) +{ + std::unique_ptr d_crypto = std::make_unique(); + std::vector message{0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x77, 0x6F, 0x72, 0x6C, 0x64, 0x0A}; // Hello world + + std::vector expected_output = { + 0xCC, 0xB8, 0xF9, 0x23, 0x5F, 0x4A, 0x93, 0x2C, 0xA0, 0xAB, + 0xBB, 0x2C, 0x24, 0x36, 0x72, 0x5E, 0x2E, 0x8D, 0xC7, 0x5B, + 0x99, 0xE7, 0xF6, 0xC4, 0x50, 0x5B, 0x2A, 0x93, 0x6E, 0xB6, 0x3B, 0x3F}; + + std::vector output = d_crypto->computeSHA3_256(message); + + ASSERT_EQ(expected_output, output); +} + + +TEST(GnssCryptoTest, VerifySignature) { - // "../data/OSNMA_PublicKey_20240115100000_newPKID_1.pem" std::unique_ptr d_crypto = std::make_unique(); - // RG example - key is raw 520 bits example shown - // std::vector publicKey = { // base64 decoding error - // 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x50, 0x55, 0x42, 0x4C, 0x49, 0x43, 0x20, 0x4B, 0x45, 0x59, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, - // - // 0x04, 0x03, 0xB2, 0xCE, 0x64, 0xBC, 0x20, 0x7B, 0xDD, 0x8B, 0xC4, 0xDF, 0x85, 0x91, 0x87, 0xFC, - // 0xB6, 0x86, 0x32, 0x0D, 0x63, 0xFF, 0xA0, 0x91, 0x41, 0x0F, 0xC1, 0x58, 0xFB, 0xB7, 0x79, 0x80, - // 0xEA, 0x88, 0x68, 0x4D, 0x91, 0x8C, 0xF0, 0x27, 0x28, 0x8E, 0xBC, 0xB3, 0xF3, 0x8A, 0xFC, 0x73, - // 0xE0, 0xA0, 0xB9, 0x0E, 0xDA, 0x28, 0xD0, 0xF3, 0x10, 0x19, 0xC8, 0x37, 0x4F, 0x07, 0x57, 0x47, 0x49, - // - // 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x50, 0x55, 0x42, 0x4C, 0x49, 0x43, 0x20, 0x4B, 0x45, 0x59, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A - // - // }; - - // RG example crt exported and convert PK.pem - key is raw 1000 bits ,..., why mismatch!? does key get truncated? - // std::vector publicKey { - // 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x50, 0x55, 0x42, 0x4C, 0x49, 0x43, 0x20, 0x4B, 0x45, 0x59, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x46, 0x6B, 0x77, 0x45, 0x77, 0x59, 0x48, 0x4B, 0x6F, 0x5A, 0x49, 0x7A, 0x6A, 0x30, 0x43, 0x41, 0x51, 0x59, 0x49, 0x4B, 0x6F, 0x5A, 0x49, - // 0x7A, 0x6A, 0x30, 0x44, 0x41, 0x51, 0x63, 0x44, 0x51, 0x67, 0x41, 0x45, 0x41, 0x37, 0x4C, 0x4F, 0x5A, 0x4C, 0x77, 0x67, 0x65, 0x39, 0x32, 0x4C, 0x78, 0x4E, 0x2B, 0x46, 0x6B, 0x59, 0x66, 0x38, 0x74, 0x6F, 0x59, 0x79, 0x44, 0x57, 0x50, 0x2F, 0x0A, 0x6F, 0x4A, 0x46, 0x42, 0x44, 0x38, 0x46, 0x59, 0x2B, 0x37, - // 0x64, 0x35, 0x67, 0x4F, 0x71, 0x49, 0x61, 0x45, 0x32, 0x52, 0x6A, 0x50, 0x41, 0x6E, 0x4B, 0x49, 0x36, 0x38, 0x73, 0x2F, 0x4F, 0x4B, 0x2F, 0x48, 0x50, 0x67, 0x6F, 0x4C, 0x6B, 0x4F, 0x32, 0x69, 0x6A, 0x51, 0x38, 0x78, 0x41, 0x5A, 0x79, 0x44, 0x64, 0x50, 0x42, 0x31, 0x64, 0x48, 0x53, 0x51, 0x3D, 0x3D, 0x0A, - // 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x50, 0x55, 0x42, 0x4C, 0x49, 0x43, 0x20, 0x4B, 0x45, 0x59, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A } ; - // own ECDSA P 256 public key and own message generated (2024-02-19-Own-Key-ECDSA-openssl) - std::vector publicKey{ // PEM + // RG example - import crt certificate - result: FAIL + std::vector message = {0x82, 0x10, 0x49, 0x22, 0x04, 0xE0, 0x60, 0x61, 0x0B, 0xDF, 0x26, 0xD7, 0x7B, 0x5B, 0xF8, 0xC9, 0xCB, 0xFC, 0xF7, 0x04, 0x22, 0x08, 0x14, 0x75, 0xFD, 0x44, 0x5D, 0xF0, 0xFF}; + std::vector signature = {0xF8, 0xCD, 0x88, 0x29, 0x9F, 0xA4, 0x60, 0x58, 0x00, 0x20, 0x7B, 0xFE, 0xBE, 0xAC, 0x55, 0x02, 0x40, 0x53, 0xF3, 0x0F, 0x7C, 0x69, 0xB3, 0x5C, 0x15, 0xE6, 0x08, 0x00, 0xAC, 0x3B, 0x6F, 0xE3, 0xED, 0x06, 0x39, 0x95, 0x2F, 0x7B, 0x02, 0x8D, 0x86, 0x86, 0x74, 0x45, 0x96, 0x1F, 0xFE, 0x94, 0xFB, 0x22, 0x6B, 0xFF, 0x70, 0x06, 0xE0, 0xC4, 0x51, 0xEE, 0x3F, 0x87, 0x28, 0xC1, 0x77, 0xFB}; + std::vector publicKey{// PEM format - 1000 bits 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x50, 0x55, 0x42, 0x4C, 0x49, 0x43, 0x20, 0x4B, 0x45, 0x59, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, + 0x4D, 0x46, 0x6B, 0x77, 0x45, 0x77, 0x59, 0x48, 0x4B, 0x6F, 0x5A, 0x49, 0x7A, 0x6A, 0x30, 0x43, 0x41, 0x51, 0x59, 0x49, 0x4B, 0x6F, 0x5A, 0x49, + 0x7A, 0x6A, 0x30, 0x44, 0x41, 0x51, 0x63, 0x44, 0x51, 0x67, 0x41, 0x45, 0x41, 0x37, 0x4C, 0x4F, 0x5A, 0x4C, 0x77, 0x67, 0x65, 0x39, 0x32, 0x4C, 0x78, 0x4E, 0x2B, 0x46, 0x6B, 0x59, 0x66, 0x38, 0x74, 0x6F, 0x59, 0x79, 0x44, 0x57, 0x50, 0x2F, 0x0A, 0x6F, 0x4A, 0x46, 0x42, 0x44, 0x38, 0x46, 0x59, 0x2B, 0x37, + 0x64, 0x35, 0x67, 0x4F, 0x71, 0x49, 0x61, 0x45, 0x32, 0x52, 0x6A, 0x50, 0x41, 0x6E, 0x4B, 0x49, 0x36, 0x38, 0x73, 0x2F, 0x4F, 0x4B, 0x2F, 0x48, 0x50, 0x67, 0x6F, 0x4C, 0x6B, 0x4F, 0x32, 0x69, 0x6A, 0x51, 0x38, 0x78, 0x41, 0x5A, 0x79, 0x44, 0x64, 0x50, 0x42, 0x31, 0x64, 0x48, 0x53, 0x51, 0x3D, 0x3D, + 0x0A, + 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x50, 0x55, 0x42, 0x4C, 0x49, 0x43, 0x20, 0x4B, 0x45, 0x59, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A}; + d_crypto->set_public_key(publicKey); + bool result = d_crypto->verify_signature(message, signature); + + ASSERT_TRUE(result); +} + + +TEST(GnssCryptoTest, VerifyPubKeyImport) +{ + std::unique_ptr d_crypto = std::make_unique(); + + std::vector publicKey{// PEM + 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x50, 0x55, 0x42, 0x4C, 0x49, 0x43, 0x20, 0x4B, 0x45, 0x59, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x46, 0x6B, 0x77, 0x45, 0x77, 0x59, 0x48, 0x4B, 0x6F, 0x5A, 0x49, 0x7A, 0x6A, 0x30, 0x43, 0x41, 0x51, 0x59, 0x49, 0x4B, 0x6F, 0x5A, 0x49, 0x7A, 0x6A, 0x30, 0x44, 0x41, 0x51, 0x63, 0x44, 0x51, 0x67, 0x41, 0x45, 0x53, 0x76, 0x50, 0x75, 0x4F, 0x70, 0x51, 0x6C, 0x4A, 0x54, 0x31, 0x56, 0x77, 0x6C, 0x72, 0x43, 0x4C, 0x63, 0x38, 0x55, 0x54, 0x54, 0x6B, 0x4E, 0x73, 0x66, 0x78, 0x2F, 0x0A, 0x4D, 0x56, 0x6F, 0x71, 0x47, 0x61, 0x35, 0x4F, 0x31, 0x73, 0x75, 0x6D, 0x57, 0x64, 0x61, 0x5A, 0x66, 0x4F, 0x69, 0x39, 0x48, 0x30, 0x4D, 0x30, 0x48, 0x46, 0x6E, 0x5A, 0x32, 0x63, 0x72, 0x44, 0x37, 0x6C, 0x6A, 0x6C, 0x36, 0x74, 0x4E, 0x56, 0x52, 0x4F, 0x71, 0x4A, 0x63, 0x57, 0x58, 0x51, 0x6B, 0x6E, 0x4B, 0x69, 0x79, 0x44, 0x79, 0x48, 0x58, 0x51, 0x3D, 0x3D, 0x0A, - 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x50, 0x55, 0x42, 0x4C, 0x49, 0x43, 0x20, 0x4B, 0x45, 0x59, 0x2D, 0x2D, - 0x2D, 0x2D, 0x2D, 0x0A }; + 0x2D, 0x2D, 0x2D, 0x0A}; d_crypto->set_public_key(publicKey); ASSERT_TRUE(d_crypto->have_public_key()); - - - - - - - - // std::vector publicKey = { // DER format -// 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x50, 0x55, 0x42, 0x4C, 0x49, 0x43, 0x20, 0x4B, 0x45, 0x59, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x46, 0x6B, 0x77, 0x45, 0x77, 0x59, 0x48, 0x4B, 0x6F, 0x5A, 0x49, 0x7A, 0x6A, 0x30, 0x43, 0x41, 0x51, 0x59, 0x49, 0x4B, 0x6F, 0x5A, 0x49, -// 0x7A, 0x6A, 0x30, 0x44, 0x41, 0x51, 0x63, 0x44, 0x51, 0x67, 0x41, 0x45, 0x41, 0x37, 0x4C, 0x4F, 0x5A, 0x4C, 0x77, 0x67, 0x65, 0x39, 0x32, 0x4C, 0x78, 0x4E, 0x2B, 0x46, 0x6B, 0x59, 0x66, 0x38, 0x74, 0x6F, 0x59, 0x79, 0x44, 0x57, 0x50, 0x2F, 0x0A, 0x6F, 0x4A, 0x46, 0x42, 0x44, 0x38, 0x46, 0x59, 0x2B, 0x37, -// 0x64, 0x35, 0x67, 0x4F, 0x71, 0x49, 0x61, 0x45, 0x32, 0x52, 0x6A, 0x50, 0x41, 0x6E, 0x4B, 0x49, 0x36, 0x38, 0x73, 0x2F, 0x4F, 0x4B, 0x2F, 0x48, 0x50, 0x67, 0x6F, 0x4C, 0x6B, 0x4F, 0x32, 0x69, 0x6A, 0x51, 0x38, 0x78, 0x41, 0x5A, 0x79, 0x44, 0x64, 0x50, 0x42, 0x31, 0x64, 0x48, 0x53, 0x51, 0x3D, 0x3D, 0x0A, -// 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x50, 0x55, 0x42, 0x4C, 0x49, 0x43, 0x20, 0x4B, 0x45, 0x59, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x30, 0x82, 0x02, 0x6C, 0x30, 0x82, 0x02, 0x12, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x47, 0xC4, 0xF1, 0x43, 0xC3, 0xFA, 0x61, 0xA5, 0x29, 0x4E, 0x63, -// 0xD5, 0x57, 0x2B, 0x01, 0x62, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x37, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x45, 0x53, 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x05, 0x45, 0x55, 0x53, 0x50, 0x41, 0x31, 0x18, 0x30, -// 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0F, 0x45, 0x55, 0x53, 0x50, 0x41, 0x20, 0x4F, 0x53, 0x4E, 0x4D, 0x41, 0x20, 0x49, 0x43, 0x41, 0x30, 0x1E, 0x17, 0x0D, 0x32, 0x33, 0x30, 0x37, 0x32, 0x30, 0x31, 0x31, 0x32, 0x32, 0x33, 0x30, 0x5A, 0x17, 0x0D, 0x32, 0x35, 0x30, 0x38, 0x30, 0x38, 0x31, 0x31, 0x33, -// 0x33, 0x30, 0x30, 0x5A, 0x30, 0x3A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x45, 0x53, 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x05, 0x45, 0x55, 0x53, 0x50, 0x41, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x12, 0x45, 0x55, 0x53, 0x50, 0x41, -// 0x20, 0x4F, 0x53, 0x4E, 0x4D, 0x41, 0x20, 0x45, 0x45, 0x20, 0x50, 0x4B, 0x52, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x03, 0xB2, 0xCE, 0x64, 0xBC, 0x20, 0x7B, 0xDD, 0x8B, 0xC4, 0xDF, -// 0x85, 0x91, 0x87, 0xFC, 0xB6, 0x86, 0x32, 0x0D, 0x63, 0xFF, 0xA0, 0x91, 0x41, 0x0F, 0xC1, 0x58, 0xFB, 0xB7, 0x79, 0x80, 0xEA, 0x88, 0x68, 0x4D, 0x91, 0x8C, 0xF0, 0x27, 0x28, 0x8E, 0xBC, 0xB3, 0xF3, 0x8A, 0xFC, 0x73, 0xE0, 0xA0, 0xB9, 0x0E, 0xDA, 0x28, 0xD0, 0xF3, 0x10, 0x19, 0xC8, 0x37, 0x4F, 0x07, 0x57, -// 0x47, 0x49, 0xA3, 0x81, 0xFC, 0x30, 0x81, 0xF9, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0x6A, 0x22, 0x16, 0x58, 0x9B, 0x23, 0xC9, 0x43, 0x41, 0x3C, 0xB6, 0xF8, 0x9D, 0x93, 0x0F, 0xE0, 0xFE, 0x6A, 0x3C, 0x54, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, -// 0x14, 0x20, 0xC0, 0x54, 0x85, 0xAF, 0x82, 0xAE, 0x96, 0x3C, 0xBC, 0xDF, 0xC1, 0xB9, 0x05, 0xDE, 0xD7, 0x46, 0x72, 0x32, 0xA3, 0x30, 0x63, 0x06, 0x03, 0x55, 0x1D, 0x20, 0x04, 0x5C, 0x30, 0x5A, 0x30, 0x4E, 0x06, 0x0B, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0xD5, 0x11, 0x01, 0x01, 0x01, 0x30, 0x3F, 0x30, 0x3D, -// 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x01, 0x16, 0x31, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3A, 0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E, 0x67, 0x73, 0x63, 0x2D, 0x65, 0x75, 0x72, 0x6F, 0x70, 0x61, 0x2E, 0x65, 0x75, 0x2F, 0x67, 0x73, 0x63, 0x2D, 0x70, 0x72, 0x6F, 0x64, 0x75, 0x63, 0x74, 0x73, 0x2F, -// 0x4F, 0x53, 0x4E, 0x4D, 0x41, 0x2F, 0x50, 0x4B, 0x49, 0x2F, 0x30, 0x08, 0x06, 0x06, 0x04, 0x00, 0x8F, 0x7A, 0x01, 0x02, 0x30, 0x42, 0x06, 0x03, 0x55, 0x1D, 0x1F, 0x04, 0x3B, 0x30, 0x39, 0x30, 0x37, 0xA0, 0x35, 0xA0, 0x33, 0x86, 0x31, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3A, 0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E, -// 0x67, 0x73, 0x63, 0x2D, 0x65, 0x75, 0x72, 0x6F, 0x70, 0x61, 0x2E, 0x65, 0x75, 0x2F, 0x67, 0x73, 0x63, 0x2D, 0x70, 0x72, 0x6F, 0x64, 0x75, 0x63, 0x74, 0x73, 0x2F, 0x4F, 0x53, 0x4E, 0x4D, 0x41, 0x2F, 0x50, 0x4B, 0x49, 0x2F, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x01, 0x01, 0xFF, 0x04, 0x04, 0x03, 0x02, -// 0x07, 0x80, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x21, 0x00, 0xE9, 0xBB, 0x90, 0x8E, 0xE5, 0x0C, 0xF3, 0xDA, 0x57, 0x71, 0xE3, 0xD0, 0xD2, 0xEA, 0xAC, 0x1B, 0x00, 0xF3, 0x51, 0xE9, 0xD8, 0xBB, 0x0A, 0xB2, 0x4C, 0x8A, 0x65, 0x52, 0x79, -// 0x9F, 0x43, 0xF6, 0x02, 0x20, 0x10, 0x65, 0x2F, 0x6A, 0xF8, 0x26, 0x20, 0x42, 0xFF, 0x09, 0x6B, 0xD0, 0x8D, 0x0B, 0x75, 0x15, 0x24, 0xBF, 0xE4, 0xFE, 0x60, 0xC3, 0x6E, 0x2D, 0x31, 0x32, 0xED, 0x65, 0x6C, 0x5C, 0x8B, 0x14 }; - -// std::vector publicKey= { // PEM format -// 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x50, 0x55, 0x42, 0x4C, 0x49, 0x43, 0x20, 0x4B, 0x45, 0x59, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x46, 0x6B, 0x77, 0x45, 0x77, 0x59, 0x48, 0x4B, 0x6F, 0x5A, 0x49, 0x7A, 0x6A, 0x30, 0x43, 0x41, 0x51, 0x59, 0x49, 0x4B, 0x6F, 0x5A, 0x49, -// 0x7A, 0x6A, 0x30, 0x44, 0x41, 0x51, 0x63, 0x44, 0x51, 0x67, 0x41, 0x45, 0x41, 0x37, 0x4C, 0x4F, 0x5A, 0x4C, 0x77, 0x67, 0x65, 0x39, 0x32, 0x4C, 0x78, 0x4E, 0x2B, 0x46, 0x6B, 0x59, 0x66, 0x38, 0x74, 0x6F, 0x59, 0x79, 0x44, 0x57, 0x50, 0x2F, 0x0A, 0x6F, 0x4A, 0x46, 0x42, 0x44, 0x38, 0x46, 0x59, 0x2B, 0x37, -// 0x64, 0x35, 0x67, 0x4F, 0x71, 0x49, 0x61, 0x45, 0x32, 0x52, 0x6A, 0x50, 0x41, 0x6E, 0x4B, 0x49, 0x36, 0x38, 0x73, 0x2F, 0x4F, 0x4B, 0x2F, 0x48, 0x50, 0x67, 0x6F, 0x4C, 0x6B, 0x4F, 0x32, 0x69, 0x6A, 0x51, 0x38, 0x78, 0x41, 0x5A, 0x79, 0x44, 0x64, 0x50, 0x42, 0x31, 0x64, 0x48, 0x53, 0x51, 0x3D, 0x3D, 0x0A, -// 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x50, 0x55, 0x42, 0x4C, 0x49, 0x43, 0x20, 0x4B, 0x45, 0x59, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A }; - } + // Unit test for computeHMAC_SHA_256 function. -TEST(GnssCryptoTest, TestComputeHMACSHA256) { // key and message generated with openssl +TEST(GnssCryptoTest, TestComputeHMACSHA256) +{ std::unique_ptr d_crypto = std::make_unique(); + std::vector key = { - 0x24, 0x24, 0x3B, 0x76, 0xF9, 0x14, 0xB1, 0xA7, - 0x7D, 0x48, 0xE7, 0xF1, 0x48, 0x0C, 0xC2, 0x98, - 0xEB, 0x62, 0x3E, 0x95, 0x6B, 0x2B, 0xCE, 0xA3, - 0xB4, 0xD4, 0xDB, 0x31, 0xEE, 0x96, 0xAB, 0xFA }; + 0x24, 0x24, 0x3B, 0x76, 0xF9, 0x14, 0xB1, 0xA7, + 0x7D, 0x48, 0xE7, 0xF1, 0x48, 0x0C, 0xC2, 0x98, + 0xEB, 0x62, 0x3E, 0x95, 0x6B, 0x2B, 0xCE, 0xA3, + 0xB4, 0xD4, 0xDB, 0x31, 0xEE, 0x96, 0xAB, 0xFA}; - std::vector message{0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x77, 0x6F, 0x72, 0x6C, 0x64, 0x0A }; // Hello world con 0x0A + std::vector message{0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x77, 0x6F, 0x72, 0x6C, 0x64, 0x0A}; // Hello world con 0x0A std::vector expected_output = { - 0xC3, 0x51, 0xF6, 0xFD, 0xDD, 0xC9, 0x8B, 0x41, - 0xD6, 0xF4, 0x77, 0x6D, 0xAC, 0xE8, 0xE0, 0x14, - 0xB2, 0x7A, 0xCC, 0x22, 0x00, 0xAA, 0xD2, 0x37, - 0xD0, 0x79, 0x06, 0x12, 0x83, 0x40, 0xB7, 0xA6 }; - + 0xC3, 0x51, 0xF6, 0xFD, 0xDD, 0xC9, 0x8B, 0x41, + 0xD6, 0xF4, 0x77, 0x6D, 0xAC, 0xE8, 0xE0, 0x14, + 0xB2, 0x7A, 0xCC, 0x22, 0x00, 0xAA, 0xD2, 0x37, + 0xD0, 0x79, 0x06, 0x12, 0x83, 0x40, 0xB7, 0xA6}; std::vector output = d_crypto->computeHMAC_SHA_256(key, message); ASSERT_EQ(expected_output, output); - - } -TEST(GnssCryptoTest, TestComputeHMACSHA256_m0) { // key and message generated from RG A.6.5.1 + +TEST(GnssCryptoTest, TestComputeHMACSHA256_m0) +{ + // key and message generated from RG A.6.5.1 std::unique_ptr d_crypto = std::make_unique(); - std::vector key = { // RG K4 @ 345690 + + std::vector key = {// RG K4 @ 345690 0x69, 0xC0, 0x0A, 0xA7, 0x36, 0x42, 0x37, 0xA6, 0x5E, 0xBF, 0x00, 0x6A, 0xD8, 0xDD, 0xBC, 0x73}; @@ -207,15 +130,19 @@ TEST(GnssCryptoTest, TestComputeHMACSHA256_m0) { // key and message generated fr ASSERT_EQ(expected_output, output); } -TEST(GnssCryptoTest, TestComputeHMACSHA256_adkd4) { // key and message generated from RG A.6.5.2 + +TEST(GnssCryptoTest, TestComputeHMACSHA256_adkd4) +{ + // key and message generated from RG A.6.5.2 std::unique_ptr d_crypto = std::make_unique(); - std::vector key = { // RG K4 @ 345690 + + std::vector key = {// RG K4 @ 345690 0x69, 0xC0, 0x0A, 0xA7, 0x36, 0x42, 0x37, 0xA6, 0x5E, 0xBF, 0x00, 0x6A, 0xD8, 0xDD, 0xBC, 0x73}; std::vector message{ 0x02, 0x02, 0x4E, 0x05, 0x46, 0x3C, 0x03, 0xBF, - 0xFF, 0xFF, 0xFF, 0xC0, 0x00,0x00, 0x44, 0x92, 0x38, + 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x44, 0x92, 0x38, 0x22, 0x78, 0x97, 0xFD, 0xEF, 0xF9, 0x30, 0x40}; std::vector expected_output = { @@ -223,10 +150,30 @@ TEST(GnssCryptoTest, TestComputeHMACSHA256_adkd4) { // key and message generated 0xE6, 0x3F, 0xB7, 0xF4, 0xF5, 0x4D, 0x44, 0xAB, 0xEE, 0x4D, 0xCE, 0xB9, 0x3D, 0xCF, 0x65, 0xCB, 0x3A, 0x5B, 0x81, 0x4A, 0x34, 0xE9}; - std::vector output = d_crypto->computeHMAC_SHA_256(key, message); ASSERT_EQ(expected_output, output); } -// TODO extend to HMAC-AES \ No newline at end of file + +TEST(GnssCryptoTest, TestComputeCMAC_AES) +{ + // Tests vectors from https://datatracker.ietf.org/doc/html/rfc4493#appendix-A + std::unique_ptr d_crypto = std::make_unique(); + + std::vector key = { + 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, + 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C}; + + std::vector message{ + 0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96, + 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A}; + + std::vector expected_output = { + 0x07, 0x0A, 0x16, 0xB4, 0x6B, 0x4D, 0x41, 0x44, + 0xF7, 0x9B, 0xDD, 0x9D, 0xD0, 0x4A, 0x28, 0x7C}; + + std::vector output = d_crypto->computeCMAC_AES(key, message); + + ASSERT_EQ(expected_output, output); +} \ No newline at end of file diff --git a/src/tests/unit-tests/signal-processing-blocks/osnma/osnma_msg_receiver_test.cc b/src/tests/unit-tests/signal-processing-blocks/osnma/osnma_msg_receiver_test.cc index ec89911ce..35cb9fd45 100644 --- a/src/tests/unit-tests/signal-processing-blocks/osnma/osnma_msg_receiver_test.cc +++ b/src/tests/unit-tests/signal-processing-blocks/osnma/osnma_msg_receiver_test.cc @@ -2,7 +2,6 @@ #include #include #include -#include #include #include @@ -25,26 +24,26 @@ protected: std::string page_even; OSNMA_msg osnma_msg{}; std::array nma_position_filled; - uint32_t d_GST_SIS{}; // 16 AUG 2023 05 00 01 + uint32_t d_GST_SIS{}; // 16 AUG 2023 05 00 01 uint32_t TOW{}; uint32_t WN{}; - std::tm GST_START_EPOCH = {0, 0, 0, 22, 8 - 1, 1999 - 1900, 0}; // months start with 0 and years since 1900 in std::tm - const uint32_t LEAP_SECONDS = 0;//13 + 5; + std::tm GST_START_EPOCH = {0, 0, 0, 22, 8 - 1, 1999 - 1900, 0}; // months start with 0 and years since 1900 in std::tm + const uint32_t LEAP_SECONDS = 0; // 13 + 5; void set_time(std::tm& input); -// std::string log_name {"CONFIG1-2023-08-23-PKID1-OSNMA"}; - std::string log_name {"CONFIG2-2023-07-27-PKID2-MT2-OSNMA"}; - void initializeGoogleLog(); + // std::string log_name {"CONFIG1-2023-08-23-PKID1-OSNMA"}; + std::string log_name{"CONFIG2-2023-07-27-PKID2-MT2-OSNMA"}; + // void initializeGoogleLog(); void SetUp() override { - flag_CRC_test = false; // TODO what for? + flag_CRC_test = false; // TODO what for? page_even = ""; -// std::tm input_time = {0, 0, 5, 16, 8 - 1, 2023 - 1900, 0}; + // std::tm input_time = {0, 0, 5, 16, 8 - 1, 2023 - 1900, 0}; std::tm input_time = {0, 0, 0, 27, 7 - 1, 2023 - 1900, 0}; set_time(input_time); -// std::string pemFilePath = "/home/cgm/CLionProjects/osnma/data/OSNMA_PublicKey_20230803105952_newPKID_1.pem"; -// std::string merkleFilePath = "/home/cgm/CLionProjects/osnma/data/OSNMA_MerkleTree_20230803105953_newPKID_1.xml"; + // std::string pemFilePath = "/home/cgm/CLionProjects/osnma/data/OSNMA_PublicKey_20230803105952_newPKID_1.pem"; + // std::string merkleFilePath = "/home/cgm/CLionProjects/osnma/data/OSNMA_MerkleTree_20230803105953_newPKID_1.xml"; std::string pemFilePath = "/home/cgm/CLionProjects/osnma/data/OSNMA_PublicKey_20230720113300_newPKID_2.pem"; std::string merkleFilePath = "/home/cgm/CLionProjects/osnma/data/OSNMA_MerkleTree_20230720113300_newPKID_2.xml"; osnma = osnma_msg_receiver_make(pemFilePath, merkleFilePath); @@ -58,121 +57,120 @@ public: }; -TEST_F(OsnmaMsgReceiverTest, TeslaKeyVerification) { +TEST_F(OsnmaMsgReceiverTest, TeslaKeyVerification) +{ // Arrange // ---------- osnma->d_tesla_key_verified = false; - osnma->d_osnma_data.d_dsm_kroot_message.kroot = {0x5B, 0xF8, 0xC9, 0xCB, 0xFC, 0xF7, 0x04, 0x22, 0x08, 0x14, 0x75, 0xFD, 0x44, 0x5D, 0xF0, 0xFF}; // Kroot, TOW 345570 GST_0 - 30 - osnma->d_osnma_data.d_dsm_kroot_message.ks = 4; // TABLE 10 --> 128 bits + osnma->d_osnma_data.d_dsm_kroot_message.kroot = {0x5B, 0xF8, 0xC9, 0xCB, 0xFC, 0xF7, 0x04, 0x22, 0x08, 0x14, 0x75, 0xFD, 0x44, 0x5D, 0xF0, 0xFF}; // Kroot, TOW 345570 GST_0 - 30 + osnma->d_osnma_data.d_dsm_kroot_message.ks = 4; // TABLE 10 --> 128 bits osnma->d_osnma_data.d_dsm_kroot_message.alpha = 0x610BDF26D77B; // local_time_verification would do this operation. TODO - eliminate duplication. osnma->d_GST_SIS = (1248 & 0x00000FFF) << 20 | (345630 & 0x000FFFFF); - osnma->d_GST_0 = ((1248 & 0x00000FFF) << 20 | (345600 & 0x000FFFFF)); // applicable time (GST_Kroot + 30) - osnma->d_receiver_time = osnma->d_GST_0 + 30 * std::floor((osnma->d_GST_SIS - osnma->d_GST_0) / 30); // Eq. 3 R.G.//345630; + osnma->d_GST_0 = ((1248 & 0x00000FFF) << 20 | (345600 & 0x000FFFFF)); // applicable time (GST_Kroot + 30) + osnma->d_receiver_time = osnma->d_GST_0 + 30 * std::floor((osnma->d_GST_SIS - osnma->d_GST_0) / 30); // Eq. 3 R.G.//345630; - osnma->d_tesla_keys.insert((std::pair>(345600,{0xEF, 0xF9, 0x99, 0x04, 0x0E, 0x19, 0xB5, 0x70, 0x83, 0x50, 0x60, 0xBE, 0xBD, 0x23, 0xED, 0x92}))); // K1, not needed, just for reference. - std::vector key = {0x2D, 0xC3, 0xA3, 0xCD, 0xB1, 0x17, 0xFA, 0xAD, 0xB8, 0x3B, 0x5F, 0x0B, 0x6F, 0xEA, 0x88, 0xEB}; // K2 + osnma->d_tesla_keys.insert((std::pair>(345600, {0xEF, 0xF9, 0x99, 0x04, 0x0E, 0x19, 0xB5, 0x70, 0x83, 0x50, 0x60, 0xBE, 0xBD, 0x23, 0xED, 0x92}))); // K1, not needed, just for reference. + std::vector key = {0x2D, 0xC3, 0xA3, 0xCD, 0xB1, 0x17, 0xFA, 0xAD, 0xB8, 0x3B, 0x5F, 0x0B, 0x6F, 0xEA, 0x88, 0xEB}; // K2 uint32_t TOW = 345630; - - - // Act // ---------- bool result = osnma->verify_tesla_key(key, TOW); - - - - // Assert // ---------- ASSERT_TRUE(result); - } + TEST_F(OsnmaMsgReceiverTest, OsnmaTestVectorsSimulation) { - initializeGoogleLog(); + // initializeGoogleLog(); // Arrange // ---------- -// std::vector testVectors = readTestVectorsFromFile("/home/cgm/CLionProjects/osnma/data/16_AUG_2023_GST_05_00_01.csv"); + // std::vector testVectors = readTestVectorsFromFile("/home/cgm/CLionProjects/osnma/data/16_AUG_2023_GST_05_00_01.csv"); std::vector testVectors = readTestVectorsFromFile("/home/cgm/CLionProjects/osnma/data/27_JUL_2023_GST_00_00_01.csv"); - if (testVectors.empty()){ + if (testVectors.empty()) + { ASSERT_TRUE(false); } bool end_of_hex_stream{false}; int offset_byte{0}; - int byte_index{0}; // index containing the last byte position of the hex stream that was retrieved. Takes advantage that all TVs have same size - const int SIZE_PAGE_BYTES{240/8}; // total bytes of a page - const int SIZE_SUBFRAME_PAGES{15}; // number of pages of a subframe - const int SIZE_SUBFRAME_BYTES{SIZE_PAGE_BYTES*SIZE_SUBFRAME_PAGES}; // total bytes of a subframe - const int DURATION_SUBFRAME{30}; // duration of a subframe, in seconds + int byte_index{0}; // index containing the last byte position of the hex stream that was retrieved. Takes advantage that all TVs have same size + const int SIZE_PAGE_BYTES{240 / 8}; // total bytes of a page + const int SIZE_SUBFRAME_PAGES{15}; // number of pages of a subframe + const int SIZE_SUBFRAME_BYTES{SIZE_PAGE_BYTES * SIZE_SUBFRAME_PAGES}; // total bytes of a subframe + const int DURATION_SUBFRAME{30}; // duration of a subframe, in seconds const int DUMMY_PAGE{63}; bool flag_dummy_page{false}; - std::cout << "OsnmaTestVectorsSimulation:" << " d_GST_SIS= " << d_GST_SIS - << ", TOW=" << TOW - << ", WN=" << WN << std::endl; - - - + std::cout << "OsnmaTestVectorsSimulation:" + << " d_GST_SIS= " << d_GST_SIS + << ", TOW=" << TOW + << ", WN=" << WN << std::endl; // Act // ---------- // loop over all bytes of data. Note: all TestVectors have same amount of data. - while (end_of_hex_stream == false){ + while (end_of_hex_stream == false) + { // loop over all SVs, extract a subframe - for(const TestVector& tv : testVectors) { // loop over all SVs, extract a subframe - std::cout << "OsnmaTestVectorsSimulation: SVID (PRN_a) "<< tv.svId << std::endl; + for (const TestVector& tv : testVectors) + { // loop over all SVs, extract a subframe + std::cout << "OsnmaTestVectorsSimulation: SVID (PRN_a) " << tv.svId << std::endl; auto osnmaMsg_sptr = std::make_shared(); std::array hkroot{}; std::array mack{}; - byte_index = offset_byte; // reset byte_index to the offset position for the next test vector. Offset is updated at the end of each Subframe (every 30 s or 450 Bytes) - std::map> words; // structure containing and + byte_index = offset_byte; // reset byte_index to the offset position for the next test vector. Offset is updated at the end of each Subframe (every 30 s or 450 Bytes) + std::map> words; // structure containing and - for (int idx = 0; idx < SIZE_SUBFRAME_PAGES; ++idx) // extract all pages of a subframe + for (int idx = 0; idx < SIZE_SUBFRAME_PAGES; ++idx) // extract all pages of a subframe { // extract bytes of complete page (odd+even) -- extract SIZE_PAGE from tv.navBits, starting from byte_index - std::vector page_bytes = extract_page_bytes(tv,byte_index,SIZE_PAGE_BYTES); - if(page_bytes.empty()){ - std::cout<< "OsnmaTestVectorsSimulation: end of TestVectors \n" << "byte_index="< data_k(even_page.substr(2,112)); - std::bitset<16> data_j(odd_page.substr(2,16)); + std::bitset<112> data_k(even_page.substr(2, 112)); + std::bitset<16> data_j(odd_page.substr(2, 16)); std::bitset<112> shifted_data_k = data_k; -// uint8_t word_type = 0; -// for(int i = 0; i < 6; ++i) { -// word_type |= (data_k[104 + i] << i); -// } - uint8_t word_type = static_cast((shifted_data_k >>= 106).to_ulong()); // word type is the first 6 bits of the word - std::cout<< "OsnmaTestVectorsSimulation: received Word "<< static_cast(word_type) << std::endl; - if( (word_type >= 1 && word_type <=5) || word_type == 6 || word_type == 10) + // uint8_t word_type = 0; + // for(int i = 0; i < 6; ++i) { + // word_type |= (data_k[104 + i] << i); + // } + uint8_t word_type = static_cast((shifted_data_k >>= 106).to_ulong()); // word type is the first 6 bits of the word + std::cout << "OsnmaTestVectorsSimulation: received Word " << static_cast(word_type) << std::endl; + if ((word_type >= 1 && word_type <= 5) || word_type == 6 || word_type == 10) { // store raw word std::bitset<128> data_combined(data_k.to_string() + data_j.to_string()); words[word_type] = data_combined; } - if(word_type == DUMMY_PAGE) + if (word_type == DUMMY_PAGE) flag_dummy_page = true; // place it into osnma object. std::bitset<40> osnmaBits(odd_page.substr(18, 40)); @@ -185,12 +183,13 @@ TEST_F(OsnmaMsgReceiverTest, OsnmaTestVectorsSimulation) byte_index += SIZE_PAGE_BYTES; } - std::cout<< "----------" << std::endl; - if(end_of_hex_stream) + std::cout << "----------" << std::endl; + if (end_of_hex_stream) break; - if(flag_dummy_page){ + if (flag_dummy_page) + { flag_dummy_page = false; - continue; // skip this SV + continue; // skip this SV } // Fill osnma object @@ -198,8 +197,8 @@ TEST_F(OsnmaMsgReceiverTest, OsnmaTestVectorsSimulation) osnmaMsg_sptr->mack = mack; osnmaMsg_sptr->TOW_sf0 = d_GST_SIS & 0x000FFFFF; - osnmaMsg_sptr->WN_sf0 = (d_GST_SIS & 0xFFF00000) >> 20 ; - osnmaMsg_sptr->PRN = tv.svId; // PRNa + osnmaMsg_sptr->WN_sf0 = (d_GST_SIS & 0xFFF00000) >> 20; + osnmaMsg_sptr->PRN = tv.svId; // PRNa // TODO - refactor this logic, currently it is split @@ -210,14 +209,14 @@ TEST_F(OsnmaMsgReceiverTest, OsnmaTestVectorsSimulation) if (words.find(i) == words.end()) { ephClockStatusWordsReceived = false; - std::cerr<< "OsnmaTestVectorsSimulation: error parsing words 1->5. " - "Word "<< i << " should be received for each subframe but was not." << std::endl; + std::cerr << "OsnmaTestVectorsSimulation: error parsing words 1->5. " + "Word " + << i << " should be received for each subframe but was not." << std::endl; } } // extract bits as needed by osnma block - if(ephClockStatusWordsReceived) + if (ephClockStatusWordsReceived) { - // Define the starting position and length of bits to extract for each word std::map> extractionParams = { {1, {6, 120}}, @@ -227,29 +226,28 @@ TEST_F(OsnmaMsgReceiverTest, OsnmaTestVectorsSimulation) {5, {6, 67}}, }; - // Fill NavData bits -- Iterate over the extraction parameters + // Fill NavData bits -- Iterate over the extraction parameters // Fill NavData bits -- Iterate over the extraction parameters std::string nav_data_ADKD_0_12 = ""; - for (const auto& param : extractionParams) { + for (const auto& param : extractionParams) + { uint8_t wordKey = param.first; uint8_t start = param.second.first; uint8_t length = param.second.second; // Extract the required bits and fill osnma block - nav_data_ADKD_0_12 += words[wordKey]. - to_string().substr( - start, length); + nav_data_ADKD_0_12 += words[wordKey].to_string().substr(start, length); } // send to osnma block bool check_size_is_ok = nav_data_ADKD_0_12.size() == 549; - if(check_size_is_ok) + if (check_size_is_ok) { - std::cout << "Galileo OSNMA: sending ADKD=0/12 navData, PRN_d (" << tv.svId << ") " << "TOW_sf=" << osnmaMsg_sptr->TOW_sf0 <>( // < PRNd , navDataBits, TOW_Sosf> + std::cout << "Galileo OSNMA: sending ADKD=0/12 navData, PRN_d (" << tv.svId << ") " + << "TOW_sf=" << osnmaMsg_sptr->TOW_sf0 << std::endl; + const auto tmp_obj_osnma = std::make_shared>( // < PRNd , navDataBits, TOW_Sosf> tv.svId, nav_data_ADKD_0_12, osnmaMsg_sptr->TOW_sf0); osnma->msg_handler_osnma(pmt::make_any(tmp_obj_osnma)); - } } @@ -257,12 +255,12 @@ TEST_F(OsnmaMsgReceiverTest, OsnmaTestVectorsSimulation) bool timingWordsReceived = words.find(6) != words.end() && words.find(10) != words.end(); // extract bits as needed by osnma block - if(timingWordsReceived){ + if (timingWordsReceived) + { // Define the starting position and length of bits to extract for each word std::map> extractionParams = { {6, {6, 99}}, - {10, {86, 42}} - }; + {10, {86, 42}}}; std::string nav_data_ADKD_4 = ""; // Fill NavData bits -- Iterate over the extraction parameters @@ -276,39 +274,39 @@ TEST_F(OsnmaMsgReceiverTest, OsnmaTestVectorsSimulation) nav_data_ADKD_4 += words[wordKey].to_string().substr( start, length); } + // send to osnma block bool check_size_is_ok = nav_data_ADKD_4.size() == 141; - if(check_size_is_ok) + if (check_size_is_ok) { - std::cout << "Galileo OSNMA: sending ADKD=04 navData, PRN_d (" << tv.svId << ") " << "TOW_sf=" << osnmaMsg_sptr->TOW_sf0 <>( // < PRNd , navDataBits, TOW_Sosf> + std::cout << "Galileo OSNMA: sending ADKD=04 navData, PRN_d (" << tv.svId << ") " + << "TOW_sf=" << osnmaMsg_sptr->TOW_sf0 << std::endl; + const auto tmp_obj_osnma = std::make_shared>( // < PRNd , navDataBits, TOW_Sosf> tv.svId, nav_data_ADKD_4, osnmaMsg_sptr->TOW_sf0); osnma->msg_handler_osnma(pmt::make_any(tmp_obj_osnma)); - } - } // Call the handler, as if it came from telemetry decoder block auto temp_obj = pmt::make_any(osnmaMsg_sptr); - osnma->msg_handler_osnma(temp_obj); // osnma entry point + osnma->msg_handler_osnma(temp_obj); // osnma entry point } - if(!end_of_hex_stream){ - offset_byte = byte_index; // update offset for the next subframe + if (!end_of_hex_stream) + { + offset_byte = byte_index; // update offset for the next subframe d_GST_SIS += DURATION_SUBFRAME; TOW = d_GST_SIS & 0x000FFFFF; - WN = (d_GST_SIS & 0xFFF00000) >> 20 ; - std::cout << "OsnmaTestVectorsSimulation:" << " d_GST_SIS= " << d_GST_SIS + WN = (d_GST_SIS & 0xFFF00000) >> 20; + std::cout << "OsnmaTestVectorsSimulation:" + << " d_GST_SIS= " << d_GST_SIS << ", TOW=" << TOW << ", WN=" << WN << std::endl; } - - } @@ -318,20 +316,24 @@ TEST_F(OsnmaMsgReceiverTest, OsnmaTestVectorsSimulation) // TODO - create global vars with failed tags and compare to total tags (Tag Id for example) } + std::vector OsnmaMsgReceiverTest::readTestVectorsFromFile(const std::string& filename) { std::ifstream file(filename); std::vector testVectors; - if (!file.is_open()) { - std::cerr<<"Error reading the file \"" << filename <<"\" \n"; + if (!file.is_open()) + { + std::cerr << "Error reading the file \"" << filename << "\" \n"; return testVectors; } std::string line; std::getline(file, line); - if (line != "SVID,NumNavBits,NavBitsHEX\r" ){ - std::cerr<<"Error parsing first line" <<"\n"; - } + if (line != "SVID,NumNavBits,NavBitsHEX\r") + { + std::cerr << "Error parsing first line" + << "\n"; + } while (std::getline(file, line)) { @@ -354,23 +356,27 @@ std::vector OsnmaMsgReceiverTest::readTestVectorsFromFile(const std: return testVectors; } + + std::vector OsnmaMsgReceiverTest::parseNavBits(const std::string& hex) { std::vector bytes; - for (unsigned int i = 0; i < hex.length()-1; i += 2) + for (unsigned int i = 0; i < hex.length() - 1; i += 2) { std::string byteString = hex.substr(i, 2); - uint8_t byte = (uint8_t) strtol(byteString.c_str(), NULL, 16); + uint8_t byte = (uint8_t)strtol(byteString.c_str(), NULL, 16); bytes.push_back(byte); } return bytes; } + + std::string OsnmaMsgReceiverTest::bytes_to_str(const std::vector& bytes) { std::string bit_string; bit_string.reserve(bytes.size() * 8); - for(const auto& byte : bytes) + for (const auto& byte : bytes) { std::bitset<8> bits(byte); bit_string += bits.to_string(); @@ -378,6 +384,7 @@ std::string OsnmaMsgReceiverTest::bytes_to_str(const std::vector& bytes return bit_string; } + /** * @brief Extracts a range of bytes from a TestVector's navBits vector. * @@ -406,6 +413,8 @@ std::vector OsnmaMsgReceiverTest::extract_page_bytes(const TestVector& return extracted_bytes; } + + /** * @brief Sets the time based on the given input. * @@ -429,118 +438,37 @@ void OsnmaMsgReceiverTest::set_time(std::tm& input) uint32_t sec_in_week = 7 * 24 * 60 * 60; uint32_t week_number = duration_sec.count() / sec_in_week; uint32_t time_of_week = duration_sec.count() % sec_in_week; - this->WN = week_number; - this->TOW = time_of_week + LEAP_SECONDS; + this->WN = week_number; + this->TOW = time_of_week + LEAP_SECONDS; // Return the week number and time of week as a pair // TODO: d_GST_SIS or d_receiver_time? doubt // I am assuming that local realisation of receiver is identical to SIS GST time coming from W5 or W0 - this->d_GST_SIS = (this->WN & 0x00000FFF) << 20 | (this->TOW & 0x000FFFFF); - - -} -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; - } - } + this->d_GST_SIS = (this->WN & 0x00000FFF) << 20 | (this->TOW & 0x000FFFFF); } TEST_F(OsnmaMsgReceiverTest, BuildTagMessageM0) { - // Arrange - // ---------- - // m0 - std::vector expected_message = { - 0x02, 0x4E, 0x05, 0x46, 0x3C, 0x01, 0x83, 0xA5, 0x91, 0x05, 0x1D, 0x69, 0x25, 0x80, 0x07, 0x6B, - 0x3E, 0xEA, 0x81, 0x41, 0xBF, 0x03, 0xAD, 0xCB, 0x5A, 0xAD, 0xB2, 0x77, 0xAF, 0x6F, 0xCF, 0x21, - 0xFB, 0x98, 0xFF, 0x7E, 0x83, 0xAF, 0xFC, 0x37, 0x02, 0x03, 0xB0, 0xD8, 0xE1, 0x0E, 0xB1, 0x4D, - 0x11, 0x18, 0xE6, 0xB0, 0xE8, 0x20, 0x01, 0xA0, 0x00, 0xE5, 0x91, 0x00, 0x06, 0xD3, 0x1F, 0x00, - 0x02, 0x68, 0x05, 0x4A, 0x02, 0xC2, 0x26, 0x07, 0xF7, 0xFC, 0x00 - }; - - uint32_t TOW_Tag0 = 345660; - uint32_t TOW_NavData = TOW_Tag0 - 30; - uint32_t TOW_Key_Tag0 = TOW_Tag0 + 30 ; - uint32_t WN = 1248; - uint32_t PRNa = 2; - uint8_t CTR = 1; - - osnma->d_osnma_data.d_dsm_kroot_message.ts = 9; // 40 bit - osnma->d_tesla_keys[TOW_Key_Tag0] = {0x69, 0xC0, 0x0A, 0xA7, 0x36, 0x42, 0x37, 0xA6, 0x5E, 0xBF, 0x00, 0x6A, 0xD8, 0xDB, 0xBC, 0x73}; // K4 - osnma->d_osnma_data.d_dsm_kroot_message.mf = 0; - osnma->d_satellite_nav_data[PRNa][TOW_NavData].ephemeris_iono_vector_2 = "000011101001011001000100000101000111010110100100100101100000000000011101101011001111101110101010000001010000011011111100000011101011011100101101011010101011011011001001110111101011110110111111001111001000011111101110011000111111110111111010000011101011111111110000110111000000100000001110110000110110001110000100001110101100010100110100010001000110001110011010110000111010000010000000000001101000000000000011100101100100010000000000000110110100110001111100000000000000100110100000000101010010100000001011000010001001100000011111110111111111000000000"; - osnma->d_osnma_data.d_nma_header.nmas = 0b10; - - MACK_tag_and_info MTI; - MTI.tag = static_cast(0xE37BC4F858); - MTI.tag_info.PRN_d = 0x02; - MTI.tag_info.ADKD = 0x00; - MTI.tag_info.cop = 0x0F; - Tag t0(MTI, TOW_Tag0, WN, PRNa, CTR); - - - - // Act - // ---------- - auto computed_message = osnma->build_message(t0); - - - // Assert - // ---------- - ASSERT_TRUE(computed_message == expected_message); - -} -TEST_F(OsnmaMsgReceiverTest, TagVerification) { // Arrange // ---------- - // Tag0 + // m0 + std::vector expected_message = { + 0x02, 0x4E, 0x05, 0x46, 0x3C, 0x01, 0x83, 0xA5, 0x91, 0x05, 0x1D, 0x69, 0x25, 0x80, 0x07, 0x6B, + 0x3E, 0xEA, 0x81, 0x41, 0xBF, 0x03, 0xAD, 0xCB, 0x5A, 0xAD, 0xB2, 0x77, 0xAF, 0x6F, 0xCF, 0x21, + 0xFB, 0x98, 0xFF, 0x7E, 0x83, 0xAF, 0xFC, 0x37, 0x02, 0x03, 0xB0, 0xD8, 0xE1, 0x0E, 0xB1, 0x4D, + 0x11, 0x18, 0xE6, 0xB0, 0xE8, 0x20, 0x01, 0xA0, 0x00, 0xE5, 0x91, 0x00, 0x06, 0xD3, 0x1F, 0x00, + 0x02, 0x68, 0x05, 0x4A, 0x02, 0xC2, 0x26, 0x07, 0xF7, 0xFC, 0x00}; + uint32_t TOW_Tag0 = 345660; uint32_t TOW_NavData = TOW_Tag0 - 30; - uint32_t TOW_Key_Tag0 = TOW_Tag0 + 30 ; + uint32_t TOW_Key_Tag0 = TOW_Tag0 + 30; uint32_t WN = 1248; uint32_t PRNa = 2; uint8_t CTR = 1; - osnma->d_osnma_data.d_dsm_kroot_message.ts = 9; // 40 bit - osnma->d_tesla_keys[TOW_Key_Tag0] = {0x69, 0xC0, 0x0A, 0xA7, 0x36, 0x42, 0x37, 0xA6, 0x5E, 0xBF, 0x00, 0x6A, 0xD8, 0xDD, 0xBC, 0x73}; // K4 + osnma->d_osnma_data.d_dsm_kroot_message.ts = 9; // 40 bit + osnma->d_tesla_keys[TOW_Key_Tag0] = {0x69, 0xC0, 0x0A, 0xA7, 0x36, 0x42, 0x37, 0xA6, 0x5E, 0xBF, 0x00, 0x6A, 0xD8, 0xDB, 0xBC, 0x73}; // K4 osnma->d_osnma_data.d_dsm_kroot_message.mf = 0; osnma->d_satellite_nav_data[PRNa][TOW_NavData].ephemeris_iono_vector_2 = "000011101001011001000100000101000111010110100100100101100000000000011101101011001111101110101010000001010000011011111100000011101011011100101101011010101011011011001001110111101011110110111111001111001000011111101110011000111111110111111010000011101011111111110000110111000000100000001110110000110110001110000100001110101100010100110100010001000110001110011010110000111010000010000000000001101000000000000011100101100100010000000000000110110100110001111100000000000000100110100000000101010010100000001011000010001001100000011111110111111111000000000"; osnma->d_osnma_data.d_nma_header.nmas = 0b10; @@ -553,29 +481,62 @@ TEST_F(OsnmaMsgReceiverTest, TagVerification) { Tag t0(MTI, TOW_Tag0, WN, PRNa, CTR); + // Act + // ---------- + auto computed_message = osnma->build_message(t0); + + + // Assert + // ---------- + ASSERT_TRUE(computed_message == expected_message); +} + + +TEST_F(OsnmaMsgReceiverTest, TagVerification) +{ + // Arrange + // ---------- + // Tag0 + uint32_t TOW_Tag0 = 345660; + uint32_t TOW_NavData = TOW_Tag0 - 30; + uint32_t TOW_Key_Tag0 = TOW_Tag0 + 30; + uint32_t WN = 1248; + uint32_t PRNa = 2; + uint8_t CTR = 1; + + osnma->d_osnma_data.d_dsm_kroot_message.ts = 9; // 40 bit + osnma->d_tesla_keys[TOW_Key_Tag0] = {0x69, 0xC0, 0x0A, 0xA7, 0x36, 0x42, 0x37, 0xA6, 0x5E, 0xBF, 0x00, 0x6A, 0xD8, 0xDD, 0xBC, 0x73}; // K4 + osnma->d_osnma_data.d_dsm_kroot_message.mf = 0; + osnma->d_satellite_nav_data[PRNa][TOW_NavData].ephemeris_iono_vector_2 = "000011101001011001000100000101000111010110100100100101100000000000011101101011001111101110101010000001010000011011111100000011101011011100101101011010101011011011001001110111101011110110111111001111001000011111101110011000111111110111111010000011101011111111110000110111000000100000001110110000110110001110000100001110101100010100110100010001000110001110011010110000111010000010000000000001101000000000000011100101100100010000000000000110110100110001111100000000000000100110100000000101010010100000001011000010001001100000011111110111111111000000000"; + osnma->d_osnma_data.d_nma_header.nmas = 0b10; + + MACK_tag_and_info MTI; + MTI.tag = static_cast(0xE37BC4F858); + MTI.tag_info.PRN_d = 0x02; + MTI.tag_info.ADKD = 0x00; + MTI.tag_info.cop = 0x0F; + Tag t0(MTI, TOW_Tag0, WN, PRNa, CTR); + // Act // ---------- bool result_tag0 = osnma->verify_tag(t0); - - - // Assert // ---------- - //ASSERT_TRUE(result_tag0); + // ASSERT_TRUE(result_tag0); // Tag3 uint32_t TOW_Tag3 = 345660; uint32_t TOW_NavData_Tag3 = TOW_Tag3 - 30; - uint32_t TOW_Key_Tag3 = TOW_Tag0 + 30 ; + uint32_t TOW_Key_Tag3 = TOW_Tag0 + 30; WN = 1248; PRNa = 2; CTR = 3; - osnma->d_osnma_data.d_dsm_kroot_message.ts = 9; // 40 bit - osnma->d_tesla_keys[TOW_Key_Tag3] = {0x69, 0xC0, 0x0A, 0xA7, 0x36, 0x42, 0x37, 0xA6, 0x5E, 0xBF, 0x00, 0x6A, 0xD8, 0xDD, 0xBC, 0x73}; // K4 + osnma->d_osnma_data.d_dsm_kroot_message.ts = 9; // 40 bit + osnma->d_tesla_keys[TOW_Key_Tag3] = {0x69, 0xC0, 0x0A, 0xA7, 0x36, 0x42, 0x37, 0xA6, 0x5E, 0xBF, 0x00, 0x6A, 0xD8, 0xDD, 0xBC, 0x73}; // K4 osnma->d_osnma_data.d_dsm_kroot_message.mf = 0; osnma->d_satellite_nav_data[PRNa][TOW_NavData].utc_vector_2 = "111111111111111111111111111111110000000000000000000000010001001001001000" @@ -591,5 +552,4 @@ TEST_F(OsnmaMsgReceiverTest, TagVerification) { bool result_tag3 = osnma->verify_tag(t3); ASSERT_TRUE(result_tag0 && result_tag3); - }