From 1a2cbe45067c0d84db68f9dac3d9118c19f9c2fd Mon Sep 17 00:00:00 2001 From: Carles Fernandez Date: Sat, 20 Jul 2024 21:25:53 +0200 Subject: [PATCH] Code cleaning --- src/core/libs/osnma_msg_receiver.cc | 272 +++++++++++------- src/core/libs/osnma_msg_receiver.h | 108 ++++--- src/core/system_parameters/osnma_data.h | 2 +- .../osnma/osnma_msg_receiver_test.cc | 4 +- 4 files changed, 227 insertions(+), 159 deletions(-) diff --git a/src/core/libs/osnma_msg_receiver.cc b/src/core/libs/osnma_msg_receiver.cc index 293058b26..e73f74ad4 100644 --- a/src/core/libs/osnma_msg_receiver.cc +++ b/src/core/libs/osnma_msg_receiver.cc @@ -3,14 +3,15 @@ * \brief GNU Radio block that processes Galileo OSNMA data received from * Galileo E1B telemetry blocks. After successful decoding, sends the content to * the PVT block. - * \author Carles Fernandez-Prades, 2023. cfernandez(at)cttc.es + * \author Carles Fernandez-Prades, 2023-2024. cfernandez(at)cttc.es + * Cesare Ghionoiu Martinez, 2023-2024. c.ghionoiu-martinez@tu-braunschweig.de * * ----------------------------------------------------------------------------- * * 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 * * ----------------------------------------------------------------------------- @@ -24,12 +25,13 @@ #include "osnma_dsm_reader.h" // for OSNMA_DSM_Reader #include "osnma_helper.h" #include // for gr::io_signature::make -#include #include #include -#include +#include // for std::setfill +#include // for std::hex, std::uppercase #include -#include +#include // for std::accumulate +#include // std::stringstream #include // for typeid #include @@ -101,14 +103,14 @@ void osnma_msg_receiver::msg_handler_osnma(const pmt::pmt_t& msg) const auto sat = Gnss_Satellite(std::string("Galileo"), nma_msg->PRN); // TODO remove if unneeded std::ostringstream output_message; - output_message << "Galileo OSNMA: complete OSNMA message received starting at " + output_message << "Galileo OSNMA: data received starting at " << "WN=" << nma_msg->WN_sf0 << ", TOW=" << nma_msg->TOW_sf0 << ", from satellite " << sat; - LOG(WARNING) << output_message.str(); + LOG(INFO) << output_message.str(); std::cout << output_message.str() << std::endl; process_osnma_message(nma_msg); @@ -119,33 +121,32 @@ void osnma_msg_receiver::msg_handler_osnma(const pmt::pmt_t& msg) const auto inav_data = wht::any_cast>>(pmt::any_ref(msg)); uint32_t PRNa = std::get<0>(*inav_data); std::string nav_data = std::get<1>(*inav_data); - ; uint32_t TOW = std::get<2>(*inav_data); // iono data => 549 bits, utc data, 141 bits. if (nav_data.size() == 549) { -// LOG(INFO) << "Galileo OSNMA: received ADKD=0/12 navData, PRN_d (" << PRNa << ") " -// << "TOW_sf=" << TOW; + // LOG(INFO) << "Galileo OSNMA: received ADKD=0/12 navData, PRN_d (" << PRNa << ") " + // << "TOW_sf=" << TOW; d_satellite_nav_data[PRNa][TOW].ephemeris_iono_vector_2 = nav_data; } else if (nav_data.size() == 141) { -// LOG(INFO) << "Galileo OSNMA: received ADKD=4 navData, PRN_d (" << PRNa << ") " -// << "TOW_sf=" << TOW; + // LOG(INFO) << "Galileo OSNMA: received ADKD=4 navData, PRN_d (" << PRNa << ") " + // << "TOW_sf=" << TOW; d_satellite_nav_data[PRNa][TOW].utc_vector_2 = nav_data; } else - LOG(WARNING) << "osnma_msg_receiver incorrect navData parsing!"; + LOG(WARNING) << "Galileo OSNMA: osnma_msg_receiver incorrect navData parsing!"; } else { - LOG(WARNING) << "osnma_msg_receiver received an unknown object type!"; + LOG(WARNING) << "Galileo OSNMA: osnma_msg_receiver received an unknown object type!"; } } catch (const wht::bad_any_cast& e) { - LOG(WARNING) << "osnma_msg_receiver Bad any_cast: " << e.what(); + LOG(WARNING) << "Galileo OSNMA: osnma_msg_receiver Bad any_cast: " << e.what(); } // Send the resulting decoded NMA data (if available) to PVT @@ -155,7 +156,7 @@ void osnma_msg_receiver::msg_handler_osnma(const pmt::pmt_t& msg) this->message_port_pub(pmt::mp("OSNMA_to_PVT"), pmt::make_any(osnma_data_ptr)); d_new_data = false; // d_osnma_data = OSNMA_data(); - DLOG(INFO) << "NMA info sent to the PVT block through the OSNMA_to_PVT async message port"; + DLOG(INFO) << "Galileo OSNMA: NMA info sent to the PVT block through the OSNMA_to_PVT async message port"; } } @@ -172,7 +173,9 @@ void osnma_msg_receiver::process_osnma_message(const std::shared_ptr& read_dsm_block(osnma_msg); process_dsm_block(osnma_msg); // will process dsm block if received a complete one, then will call mack processing upon re-setting the dsm block to 0 if (d_osnma_data.d_dsm_kroot_message.towh_k != 0) - local_time_verification(osnma_msg); + { + local_time_verification(osnma_msg); + } read_and_process_mack_block(osnma_msg); // only process them if at least 3 available. } @@ -203,8 +206,6 @@ void osnma_msg_receiver::read_dsm_header(uint8_t dsm_header) { d_osnma_data.d_dsm_header.dsm_id = d_dsm_reader->get_dsm_id(dsm_header); d_osnma_data.d_dsm_header.dsm_block_id = d_dsm_reader->get_dsm_block_id(dsm_header); // BID -// LOG(INFO) << "OSNMA: DSM_ID=" << static_cast(d_osnma_data.d_dsm_header.dsm_id); -// LOG(INFO) << "OSNMA: DSM_BID=" << static_cast(d_osnma_data.d_dsm_header.dsm_block_id); LOG(INFO) << "Galileo OSNMA: Received block DSM_BID=" << static_cast(d_osnma_data.d_dsm_header.dsm_block_id) << " with DSM_ID " << static_cast(d_osnma_data.d_dsm_header.dsm_id); } @@ -246,7 +247,7 @@ void osnma_msg_receiver::read_dsm_block(const std::shared_ptr& osnma_ } d_number_of_blocks[d_osnma_data.d_dsm_header.dsm_id] = number_of_blocks; - LOG(INFO) << "OSNMA: number_of_blocks=" << static_cast(number_of_blocks); + LOG(INFO) << "Galileo OSNMA: number of blocks in this message: " << static_cast(number_of_blocks); if (number_of_blocks == 0) { // Something is wrong, start over @@ -289,8 +290,10 @@ void osnma_msg_receiver::read_dsm_block(const std::shared_ptr& osnma_ } available_blocks << "]"; LOG(INFO) << available_blocks.str(); + std::cout << available_blocks.str() << std::endl; } + /** * @brief Function to verify the local time based on GST_SIS and GST_0 * @@ -323,7 +326,7 @@ void osnma_msg_receiver::local_time_verification(const std::shared_ptr(d_receiver_time - d_GST_SIS)<< " | < " << static_cast(d_T_L) << " ]" << std::endl; // TODO set flag to false to avoid processing dsm and MACK messages @@ -334,7 +337,7 @@ void osnma_msg_receiver::local_time_verification(const std::shared_ptr(d_receiver_time - d_GST_SIS) << " | < " << static_cast(d_T_L) << " ]"; + LOG(WARNING) << "Galileo OSNMA: ( |local_t - GST_SIS| < T_L ) [ |" << static_cast(d_receiver_time - d_GST_SIS) << " | < " << static_cast(d_T_L) << " ]"; } else { @@ -342,7 +345,7 @@ void osnma_msg_receiver::local_time_verification(const std::shared_ptr(d_receiver_time - d_GST_SIS) << " | < " << static_cast(d_T_L) << " ]"; + LOG(WARNING) << "Galileo OSNMA: ( |local_t - GST_SIS| < T_L ) [ |" << static_cast(d_receiver_time - d_GST_SIS) << " | < " << static_cast(d_T_L) << " ]"; } } @@ -391,7 +394,7 @@ void osnma_msg_receiver::process_dsm_message(const std::vector& dsm_msg if (d_osnma_data.d_dsm_header.dsm_id < 12) { // Parse Kroot message - LOG(INFO) << "OSNMA: DSM-KROOT message received."; + LOG(INFO) << "Galileo OSNMA: DSM-KROOT message received."; d_osnma_data.d_dsm_kroot_message.nb_dk = d_dsm_reader->get_number_blocks_index(dsm_msg[0]); d_osnma_data.d_dsm_kroot_message.pkid = d_dsm_reader->get_pkid(dsm_msg); d_osnma_data.d_dsm_kroot_message.cidkr = d_dsm_reader->get_cidkr(dsm_msg); @@ -483,7 +486,14 @@ void osnma_msg_receiver::process_dsm_message(const std::vector& dsm_msg << ", WN=" << static_cast(d_osnma_data.d_dsm_kroot_message.wn_k) << ", TOW=" << static_cast(d_osnma_data.d_dsm_kroot_message.towh_k) * 3600; local_time_verification(osnma_msg); - d_kroot_verified = d_crypto->verify_signature_ecdsa_p256(message, d_osnma_data.d_dsm_kroot_message.ds); + if(l_ds_bits == 512) + { + d_kroot_verified = d_crypto->verify_signature_ecdsa_p256(message, d_osnma_data.d_dsm_kroot_message.ds); + } + else if(l_ds_bits == 1056) + { + d_kroot_verified = d_crypto->verify_signature_ecdsa_p521(message, d_osnma_data.d_dsm_kroot_message.ds); + } if (d_kroot_verified) { std::cout << "Galileo OSNMA: KROOT authentication successful!" << std::endl; @@ -495,6 +505,7 @@ void osnma_msg_receiver::process_dsm_message(const std::vector& dsm_msg else { LOG(WARNING) << "Galileo OSNMA: KROOT authentication failed."; + std::cerr << "Galileo OSNMA: KROOT authentication failed." << std::endl; } } else @@ -506,7 +517,7 @@ void osnma_msg_receiver::process_dsm_message(const std::vector& dsm_msg } else if (d_osnma_data.d_dsm_header.dsm_id >= 12 && d_osnma_data.d_dsm_header.dsm_id < 16) { - LOG(WARNING) << "Galileo OSNMA: DSM-PKR message received."; + LOG(INFO) << "Galileo OSNMA: DSM-PKR message received."; // Save DSM-PKR message d_osnma_data.d_dsm_pkr_message.nb_dp = d_dsm_reader->get_number_blocks_index(dsm_msg[0]); d_osnma_data.d_dsm_pkr_message.mid = d_dsm_reader->get_mid(dsm_msg); @@ -530,7 +541,7 @@ void osnma_msg_receiver::process_dsm_message(const std::vector& dsm_msg uint32_t l_dp_bytes = dsm_msg.size(); if (d_osnma_data.d_dsm_pkr_message.npkt == 4) { - LOG(WARNING) << "OSNMA: OAM received"; + LOG(WARNING) << "Galileo OSNMA: OAM received"; l_npk_bytes = l_dp_bytes - 130; // bytes } @@ -576,8 +587,8 @@ void osnma_msg_receiver::process_dsm_message(const std::vector& dsm_msg else { // Reserved message? - LOG(WARNING) << "OSNMA Reserved message received"; - // d_osnma_data = OSNMA_data(); + LOG(WARNING) << "Galileo OSNMA: Reserved message received"; + std::cerr << "Galileo OSNMA: Reserved message received" << std::endl; } d_number_of_blocks[d_osnma_data.d_dsm_header.dsm_id] = 0; } @@ -883,15 +894,16 @@ void osnma_msg_receiver::process_mack_message() { if (d_kroot_verified == false && d_tesla_key_verified == false) { - LOG(WARNING) << "Galileo OSNMA: MACK cannot be processed. " - << ", " - << "No Kroot nor TESLA key available"; + LOG(WARNING) << "Galileo OSNMA: MACK cannot be processed, " + << "no Kroot nor TESLA key available."; if (!d_flag_debug) { return; // early return, cannot proceed further without one of the two verified. this equals to having Kroot but no TESLa key yet. } else - LOG(WARNING) << "But it will be processed for debugging purposes."; + { + LOG(WARNING) << "Galileo OSNMA: But it will be processed for debugging purposes."; + } } // verify tesla key and add it to the container of verified keys if successful if (d_tesla_keys.find(d_osnma_data.d_nav_data.TOW_sf0) == d_tesla_keys.end()) // check if already available => no need to verify @@ -933,12 +945,13 @@ void osnma_msg_receiver::process_mack_message() << ", PRNd=" << static_cast(t.PRN_d); } - std::cout << "Galileo OSNMA: d_tags_awaiting_verify :: size: " << d_tags_awaiting_verify.size() << std::endl; + LOG(INFO) << "Galileo OSNMA: d_tags_awaiting_verify :: size: " << d_tags_awaiting_verify.size(); mack = d_macks_awaiting_MACSEQ_verification.erase(mack); } else - { // key not yet available - keep in container until then -- might be deleted if container size exceeds max allowed + { + // key not yet available - keep in container until then -- might be deleted if container size exceeds max allowed ++mack; } } @@ -960,18 +973,24 @@ void osnma_msg_receiver::process_mack_message() if (ret) { it.second.status = Tag::SUCCESS; - LOG(WARNING) << "Galileo OSNMA: Tag verification :: SUCCESS for tag Id= " - << it.second.tag_id - << ", value=0x" << std::setfill('0') << std::setw(10) << std::hex << std::uppercase - << it.second.received_tag << std::dec - << ", TOW=" - << it.second.TOW - << ", ADKD=" - << static_cast(it.second.ADKD) - << ", PRNa=" - << static_cast(it.second.PRNa) - << ", PRNd=" - << static_cast(it.second.PRN_d); + LOG(INFO) << "Galileo OSNMA: Tag verification :: SUCCESS for tag Id=" + << it.second.tag_id + << ", value=0x" << std::setfill('0') << std::setw(10) << std::hex << std::uppercase + << it.second.received_tag << std::dec + << ", TOW=" + << it.second.TOW + << ", ADKD=" + << static_cast(it.second.ADKD) + << ", PRNa=" + << static_cast(it.second.PRNa) + << ", PRNd=" + << static_cast(it.second.PRN_d); + std::cout << "Galileo OSNMA: Tag verification :: SUCCESS for tag ADKD=" + << static_cast(it.second.ADKD) + << ", PRNa=" + << static_cast(it.second.PRNa) + << ", PRNd=" + << static_cast(it.second.PRN_d) << std::endl; } /* TODO notify PVT via pmt * have_new_data() true @@ -980,7 +999,7 @@ void osnma_msg_receiver::process_mack_message() else { it.second.status = Tag::FAIL; - LOG(WARNING) << "Galileo OSNMA: Tag verification :: FAILURE for tag Id=" + LOG(WARNING) << "Galileo OSNMA: Tag verification :: FAILURE for tag Id=" << it.second.tag_id << ", value=0x" << std::setfill('0') << std::setw(10) << std::hex << std::uppercase << it.second.received_tag << std::dec @@ -992,6 +1011,12 @@ void osnma_msg_receiver::process_mack_message() << static_cast(it.second.PRNa) << ", PRNd=" << static_cast(it.second.PRN_d); + std::cerr << "Galileo OSNMA: Tag verification :: FAILURE for tag ADKD=" + << static_cast(it.second.ADKD) + << ", PRNa=" + << static_cast(it.second.PRNa) + << ", PRNd=" + << static_cast(it.second.PRN_d) << std::endl; } } else if (it.second.TOW > d_osnma_data.d_nav_data.TOW_sf0) @@ -1031,27 +1056,29 @@ void osnma_msg_receiver::process_mack_message() * \pre DSM_PKR_message correctly filled in especially the 1024 intermediate tree nodes * \returns true if computed merkle root matches received one, false otherwise */ -bool osnma_msg_receiver::verify_dsm_pkr(DSM_PKR_message message) +bool osnma_msg_receiver::verify_dsm_pkr(const DSM_PKR_message& message) const { - std::vector computed_merkle_root; // x_4_0 - std::vector base_leaf = compute_base_leaf(message); // m_i - - LOG(INFO) << "Galileo OSNMA: DSM-PKR :: leaf provided: m_" << static_cast(message.mid); - - computed_merkle_root = compute_merke_root(message, base_leaf); + const auto base_leaf = get_merkle_tree_leaves(message); // m_i + const auto computed_merkle_root = compute_merkle_root(message, base_leaf); // x_4_0 + const auto msg_id = static_cast(message.mid); + LOG(INFO) << "Galileo OSNMA: DSM-PKR verification :: leaf provided for Message ID " << msg_id; if (computed_merkle_root == d_crypto->get_merkle_root()) { - LOG(INFO) << "Galileo OSNMA: DSM-PKR verification :: SUCCESS!." << std::endl; + LOG(INFO) << "Galileo OSNMA: DSM-PKR verification for Message ID " << msg_id << " :: SUCCESS."; + std::cout << "Galileo OSNMA: DSM-PKR verification for Message ID " << msg_id << " :: SUCCESS." << std::endl; return true; } else { - LOG(INFO) << "Galileo OSNMA: DSM-PKR verification :: FAILURE." << std::endl; + LOG(WARNING) << "Galileo OSNMA: DSM-PKR verification for Message ID " << msg_id << " :: FAILURE."; + std::cerr << "Galileo OSNMA: DSM-PKR verification for Message ID " << msg_id << " :: FAILURE." << std::endl; return false; } } -std::vector osnma_msg_receiver::compute_merke_root(const DSM_PKR_message& dsm_pkr_message, const std::vector& m_i) const + + +std::vector osnma_msg_receiver::compute_merkle_root(const DSM_PKR_message& dsm_pkr_message, const std::vector& m_i) const { std::vector x_next, x_current = d_crypto->compute_SHA_256(m_i); for (size_t i = 0; i < 4; i++) @@ -1077,12 +1104,16 @@ std::vector osnma_msg_receiver::compute_merke_root(const DSM_PKR_messag } return x_current; } -std::vector osnma_msg_receiver::compute_base_leaf(const DSM_PKR_message& dsm_pkr_message) const -{ // build base leaf m_i + + +std::vector osnma_msg_receiver::get_merkle_tree_leaves(const DSM_PKR_message& dsm_pkr_message) const +{ + // build base leaf m_i according to OSNMA SIS ICD v1.1, section 6.2 DSM-PKR Verification std::vector m_i; - m_i.reserve(2 + dsm_pkr_message.npk.size()); + const size_t size_npk = dsm_pkr_message.npk.size(); + m_i.reserve(1 + size_npk); m_i.push_back((dsm_pkr_message.npkt << 4) + dsm_pkr_message.npktid); - for (uint8_t i = 0; i < dsm_pkr_message.npk.size(); i++) + for (size_t i = 0; i < size_npk; i++) { m_i.push_back(dsm_pkr_message.npk[i]); } @@ -1090,13 +1121,13 @@ std::vector osnma_msg_receiver::compute_base_leaf(const DSM_PKR_message } -bool osnma_msg_receiver::verify_tag(Tag& tag) +bool osnma_msg_receiver::verify_tag(const Tag& tag) { // Debug -// LOG(INFO) << "Galileo OSNMA: Tag verification :: Start for tag Id= " -// << tag.tag_id -// << ", value=0x" << std::setfill('0') << std::setw(10) << std::hex << std::uppercase -// << tag.received_tag << std::dec; + // LOG(INFO) << "Galileo OSNMA: Tag verification :: Start for tag Id= " + // << tag.tag_id + // << ", value=0x" << std::setfill('0') << std::setw(10) << std::hex << std::uppercase + // << tag.received_tag << std::dec; // build message std::vector m = build_message(tag); @@ -1105,14 +1136,13 @@ bool osnma_msg_receiver::verify_tag(Tag& tag) if (tag.ADKD == 0 || tag.ADKD == 4) { applicable_key = d_tesla_keys[tag.TOW + 30]; -// LOG(INFO) << "|---> Galileo OSNMA :: applicable key: 0x" << d_helper->convert_to_hex_string(applicable_key) << "TOW="<(tag.TOW + 30); + // LOG(INFO) << "|---> Galileo OSNMA :: applicable key: 0x" << d_helper->convert_to_hex_string(applicable_key) << "TOW="<(tag.TOW + 30); + } + else // ADKD 12 + { + applicable_key = d_tesla_keys[tag.TOW + 330]; + // LOG(INFO) << "|---> Galileo OSNMA :: applicable key: 0x" << d_helper->convert_to_hex_string(applicable_key) << "TOW="<(tag.TOW + 330); } - else // ADKD 12 - { - applicable_key = d_tesla_keys[tag.TOW + 330]; -// LOG(INFO) << "|---> Galileo OSNMA :: applicable key: 0x" << d_helper->convert_to_hex_string(applicable_key) << "TOW="<(tag.TOW + 330); - } - if (d_osnma_data.d_dsm_kroot_message.mf == 0) // C: HMAC-SHA-256 { @@ -1164,7 +1194,7 @@ bool osnma_msg_receiver::verify_tag(Tag& tag) // Compare computed tag with received one truncated if (tag.received_tag == computed_mac) { - std::cout << "Galileo OSNMA: Tag verification :: SUCCESS for tag Id= " + LOG(INFO) << "Galileo OSNMA: Tag verification :: SUCCESS for tag Id=" << tag.tag_id << ", value=0x" << std::setfill('0') << std::setw(10) << std::hex << std::uppercase << tag.received_tag << std::dec @@ -1175,6 +1205,14 @@ bool osnma_msg_receiver::verify_tag(Tag& tag) << ", PRNa=" << static_cast(tag.PRNa) << ", PRNd=" + << static_cast(tag.PRN_d); + std::cout << "Galileo OSNMA: Tag verification :: SUCCESS for tag Id=" + << tag.tag_id + << ", ADKD=" + << static_cast(tag.ADKD) + << ", PRNa=" + << static_cast(tag.PRNa) + << ", PRNd=" << static_cast(tag.PRN_d) << std::endl; return true; } @@ -1186,7 +1224,9 @@ std::vector osnma_msg_receiver::build_message(const Tag& tag) { std::vector m; if (tag.CTR != 1) - m.push_back(static_cast(tag.PRN_d)); + { + m.push_back(static_cast(tag.PRN_d)); + } m.push_back(static_cast(tag.PRNa)); // TODO: maybe here I have to use d_receiver_time instead of d_GST_SIS which is what I am computing uint32_t GST = d_helper->compute_gst(tag.WN, tag.TOW); @@ -1204,15 +1244,17 @@ std::vector osnma_msg_receiver::build_message(const Tag& tag) if (tag.ADKD == 0 || tag.ADKD == 12) // note: for ADKD=12 still the same logic applies. Only the Key selection is shifted 10 Subframes into the future. { applicable_nav_data = d_satellite_nav_data[tag.PRN_d][tag.TOW - 30].ephemeris_iono_vector_2; -// LOG(INFO) << "|---> Galileo OSNMA :: applicable NavData (PRN_d="<< static_cast(tag.PRN_d) << ", TOW=" << tag.TOW - 30 <<"): 0b" << applicable_nav_data; + // LOG(INFO) << "|---> Galileo OSNMA :: applicable NavData (PRN_d="<< static_cast(tag.PRN_d) << ", TOW=" << tag.TOW - 30 <<"): 0b" << applicable_nav_data; } else if (tag.ADKD == 4) { applicable_nav_data = d_satellite_nav_data[tag.PRN_d][tag.TOW - 30].utc_vector_2; -// LOG(INFO) << "|---> Galileo OSNMA :: applicable NavData (PRN_d="<< static_cast(tag.PRN_d) << ", TOW=" << tag.TOW - 30 <<"): 0b" << applicable_nav_data; + // LOG(INFO) << "|---> Galileo OSNMA :: applicable NavData (PRN_d="<< static_cast(tag.PRN_d) << ", TOW=" << tag.TOW - 30 <<"): 0b" << applicable_nav_data; } else - LOG(WARNING) << "Galileo OSNMA :: Tag verification :: unknown ADKD"; + { + LOG(WARNING) << "Galileo OSNMA: Tag verification :: unknown ADKD"; + } // convert std::string to vector applicable_nav_data_bytes = d_helper->bytes(applicable_nav_data); @@ -1309,14 +1351,16 @@ bool osnma_msg_receiver::verify_tesla_key(std::vector& key, uint32_t TO } if (computed_key == d_validated_key && num_of_hashes_needed > 0) { - LOG(WARNING) << "Galileo OSNMA:: TESLA key verification :: SUCCESS!"; + LOG(INFO) << "Galileo OSNMA: TESLA key verification :: SUCCESS!"; + std::cout << "Galileo OSNMA: TESLA key verification :: SUCCESS!" << std::endl; d_tesla_keys.insert(std::pair>(TOW, key)); d_tesla_key_verified = true; d_last_verified_key_GST = d_receiver_time; } else if (num_of_hashes_needed > 0) { - LOG(WARNING) << "Galileo OSNMA:: TESLA key verification :: FAILED"; + LOG(WARNING) << "Galileo OSNMA: TESLA key verification :: FAILED"; + std::cerr << "Galileo OSNMA: TESLA key verification :: FAILED" << std::endl; if (d_flag_debug) { d_tesla_keys.insert(std::pair>(TOW, key)); @@ -1375,9 +1419,11 @@ void osnma_msg_receiver::remove_verified_tags() it = d_tags_awaiting_verify.erase(it); } else - ++it; + { + ++it; + } } - std::cout << "Galileo OSNMA: d_tags_awaiting_verify :: size: " << d_tags_awaiting_verify.size() << std::endl; + LOG(INFO) << "Galileo OSNMA: d_tags_awaiting_verify :: size: " << d_tags_awaiting_verify.size(); } @@ -1394,11 +1440,11 @@ void osnma_msg_receiver::control_tags_awaiting_verify_size() while (d_tags_awaiting_verify.size() > 500) { auto it = d_tags_awaiting_verify.begin(); - LOG(WARNING) << "Galileo OSNMA: Tag verification :: DELETED tag due to exceeding buffer size. " - << "Tag Id= " << it->second.tag_id - << ", TOW=" << it->first - << ", ADKD=" << static_cast(it->second.ADKD) - << ", from satellite " << it->second.PRNa; + LOG(INFO) << "Galileo OSNMA: Tag verification :: DELETED tag due to exceeding buffer size. " + << "Tag Id= " << it->second.tag_id + << ", TOW=" << it->first + << ", ADKD=" << static_cast(it->second.ADKD) + << ", from satellite " << it->second.PRNa; d_tags_awaiting_verify.erase(it); } } @@ -1463,7 +1509,7 @@ bool osnma_msg_receiver::verify_macseq(const MACK_message& mack) if (flxTags.empty()) { - LOG(WARNING) << "Galileo OSNMA: MACSEQ verification :: SUCCESS :: ADKD matches MAC Look-up table."; + LOG(INFO) << "Galileo OSNMA: MACSEQ verification :: SUCCESS :: ADKD matches MAC Look-up table."; return true; } // Fixed as well as FLX Tags share first part - Eq. 22 ICD @@ -1499,7 +1545,7 @@ bool osnma_msg_receiver::verify_macseq(const MACK_message& mack) uint16_t computed_macseq = (mac_msb & 0xFFF0) >> 4; if (computed_macseq == mack.header.macseq) { - LOG(WARNING) << "Galileo OSNMA: MACSEQ verification :: SUCCESS :: FLX tags verification OK"; + LOG(INFO) << "Galileo OSNMA: MACSEQ verification :: SUCCESS :: FLX tags verification OK"; return true; } @@ -1511,7 +1557,7 @@ bool osnma_msg_receiver::verify_macseq(const MACK_message& mack) } -bool osnma_msg_receiver::tag_has_nav_data_available(Tag& t) +bool osnma_msg_receiver::tag_has_nav_data_available(const Tag& t) { auto prn_it = d_satellite_nav_data.find(t.PRN_d); if (prn_it != d_satellite_nav_data.end()) @@ -1540,7 +1586,7 @@ bool osnma_msg_receiver::tag_has_nav_data_available(Tag& t) } -bool osnma_msg_receiver::tag_has_key_available(Tag& t) +bool osnma_msg_receiver::tag_has_key_available(const Tag& t) { // check adkd of tag // if adkd = 0 or 4 => look for d_tesla_keys[t.TOW+30] @@ -1572,7 +1618,6 @@ bool osnma_msg_receiver::tag_has_key_available(Tag& t) std::vector osnma_msg_receiver::hash_chain(uint32_t num_of_hashes_needed, std::vector key, uint32_t GST_SFi, const uint8_t lk_bytes) { - auto start = std::chrono::high_resolution_clock::now(); std::vector K_II = key; std::vector K_I; // result of the recursive hash operations std::vector msg; @@ -1624,20 +1669,26 @@ std::vector osnma_msg_receiver::hash_chain(uint32_t num_of_hashes_neede // check that the final time matches the Kroot time bool check; if (!d_tesla_key_verified) - check = GST_SFi + 30 == d_GST_0 - 30; + { + check = GST_SFi + 30 == d_GST_0 - 30; + } else - check = GST_SFi + 30 == d_last_verified_key_GST; + { + check = GST_SFi + 30 == d_last_verified_key_GST; + } if (!check) - LOG(WARNING) << "Galileo OSNMA: TESLA verification error. Kroot time mismatch!"; // ICD. Eq. 18 + { + LOG(WARNING) << "Galileo OSNMA: TESLA key chain verification error: KROOT time mismatch!"; // ICD. Eq. 18 + std::cerr << "Galileo OSNMA: TESLA key chain verification error: KROOT time mismatch!" << std::endl; + } else - LOG(INFO) << "Galileo OSNMA: TESLA verification. Kroot time matches!"; // ICD. Eq. 18 - // compare computed current key against received key - auto end = std::chrono::high_resolution_clock::now(); - std::chrono::duration elapsed = end - start; -// LOG(INFO) << "Galileo OSNMA: TESLA verification (" << num_of_hashes_needed << " hashes) took " << elapsed.count() << " seconds."; + { + LOG(INFO) << "Galileo OSNMA: TESLA key chain verification: KROOT time matches."; // ICD. Eq. 18 + } return K_II; } + /** * @brief Verifies the MAC sequence of a received MACK message. * @@ -1650,7 +1701,7 @@ std::vector osnma_msg_receiver::hash_chain(uint32_t num_of_hashes_neede */ std::vector osnma_msg_receiver::verify_macseq_new(const MACK_message& mack) { - std::vector verified_tags {}; + std::vector verified_tags{}; // MACSEQ verification d_GST_Sf = d_receiver_time - 30; // time of the start of SF containing MACSEQ // TODO buffer with times? since out of debug not every 30 s a Sf is necessarily received.. @@ -1692,23 +1743,23 @@ std::vector osnma_msg_receiver::verify_macseq_new(const MACK_ else if (mack.tag_and_info[i].tag_info.ADKD == std::stoi(applicable_sequence[i + 1])) { // fill index of tags failed - LOG(WARNING) << "Galileo OSNMA: MACSEQ verification :: SUCCESS :: ADKD match against MAC Look-up table for " - "Tag=0x" << std::setfill('0') << std::setw(10) << std::hex << std::uppercase - << mack.tag_and_info[i].tag << std::dec; + LOG(INFO) << "Galileo OSNMA: MACSEQ verification :: SUCCESS :: ADKD match against MAC Look-up table for Tag=0x" + << std::setfill('0') << std::setw(10) << std::hex << std::uppercase + << mack.tag_and_info[i].tag << std::dec; verified_tags.push_back(mack.tag_and_info[i]); } else { // discard tag - LOG(WARNING) << "Galileo OSNMA: MACSEQ verification :: FAILURE :: ADKD mismatch against MAC Look-up table for " - "Tag=0x" << std::setfill('0') << std::setw(10) << std::hex << std::uppercase - << mack.tag_and_info[i].tag << std::dec; + LOG(WARNING) << "Galileo OSNMA: MACSEQ verification :: FAILURE :: ADKD mismatch against MAC Look-up table for Tag=0x" + << std::setfill('0') << std::setw(10) << std::hex << std::uppercase + << mack.tag_and_info[i].tag << std::dec; } } if (flxTags.empty() /*TODO add check d_flag_check_mackseq_fixed_tags*/) { - LOG(WARNING) << "Galileo OSNMA: MACSEQ verification :: No FLX tags to verify."; + LOG(INFO) << "Galileo OSNMA: MACSEQ verification :: No FLX tags to verify."; return verified_tags; } // Fixed as well as FLX Tags share first part - Eq. 22 ICD @@ -1744,7 +1795,7 @@ std::vector osnma_msg_receiver::verify_macseq_new(const MACK_ uint16_t computed_macseq = (mac_msb & 0xFFF0) >> 4; if (computed_macseq == mack.header.macseq) { - LOG(WARNING) << "Galileo OSNMA: MACSEQ verification :: SUCCESS :: FLX tags verification OK"; + LOG(INFO) << "Galileo OSNMA: MACSEQ verification :: SUCCESS :: FLX tags verification OK"; for (uint8_t i = 0; i < flxTags.size(); i++) { verified_tags.push_back(mack.tag_and_info[flxTags[i]]); @@ -1757,5 +1808,4 @@ std::vector osnma_msg_receiver::verify_macseq_new(const MACK_ LOG(WARNING) << "Galileo OSNMA: MACSEQ verification :: FAILURE :: FLX tags verification failed"; return verified_tags; } - } diff --git a/src/core/libs/osnma_msg_receiver.h b/src/core/libs/osnma_msg_receiver.h index ad397cc2f..148b1266e 100644 --- a/src/core/libs/osnma_msg_receiver.h +++ b/src/core/libs/osnma_msg_receiver.h @@ -3,14 +3,15 @@ * \brief GNU Radio block that processes Galileo OSNMA data received from * Galileo E1B telemetry blocks. After successful decoding, sends the content to * the PVT block. - * \author Carles Fernandez-Prades, 2023. cfernandez(at)cttc.es + * \author Carles Fernandez-Prades, 2023-2024. cfernandez(at)cttc.es + * Cesare Ghionoiu Martinez, 2023-2024. c.ghionoiu-martinez@tu-braunschweig.de * * ----------------------------------------------------------------------------- * * 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 * * ----------------------------------------------------------------------------- @@ -18,20 +19,23 @@ #ifndef GNSS_SDR_OSNMA_MSG_RECEIVER_H #define GNSS_SDR_OSNMA_MSG_RECEIVER_H -#define FRIEND_TEST(test_case_name, test_name)\ -friend class test_case_name##_##test_name##_Test + +#define FRIEND_TEST(test_case_name, test_name) \ + friend class test_case_name##_##test_name##_Test #include "galileo_inav_message.h" // for OSNMA_msg #include "gnss_block_interface.h" // for gnss_shared_ptr #include "gnss_sdr_make_unique.h" // for std::make:unique in C++11 -#include "osnma_data.h" // for OSNMA_data -#include -#include // for gr::block -#include // for pmt::pmt_t -#include // for std::array -#include // for std::shared_ptr -#include -#include +#include "osnma_data.h" // for OSNMA_data structures +#include // for gr::block +#include // for pmt::pmt_t +#include // for std::array +#include // for uint8_t +#include // for std::time_t +#include // for std::map, std::multimap +#include // for std::shared_ptr +#include // for std::string +#include // for std::vector /** \addtogroup Core * \{ */ @@ -73,58 +77,72 @@ private: void read_mack_header(); void read_mack_body(); void process_mack_message(); - void add_satellite_data(uint32_t SV_ID, uint32_t TOW, const NavData &data); + void add_satellite_data(uint32_t SV_ID, uint32_t TOW, const NavData& data); void remove_verified_tags(); void control_tags_awaiting_verify_size(); - std::vector build_message(const Tag& tag); - std::vector hash_chain(uint32_t num_of_hashes_needed, std::vector key, uint32_t GST_SFi, const uint8_t lk_bytes); - std::vector compute_base_leaf(const DSM_PKR_message& dsm_pkr_message) const; - std::vector compute_merke_root(const DSM_PKR_message& dsm_pkr_message, const std::vector& m_i) const; - std::vector verify_macseq_new(const MACK_message& mack); void display_data(); + bool verify_tag(MACK_tag_and_info tag_and_info, OSNMA_data applicable_OSNMA, uint8_t tag_position, const std::vector& applicable_key, NavData applicable_NavData); bool verify_tesla_key(std::vector& key, uint32_t TOW); - bool verify_tag(Tag& tag); + bool verify_tag(const Tag& tag); bool is_next_subframe(); - bool tag_has_nav_data_available(Tag& t); - bool tag_has_key_available(Tag& t); + bool tag_has_nav_data_available(const Tag& t); + bool tag_has_key_available(const Tag& t); bool verify_macseq(const MACK_message& mack); - bool verify_dsm_pkr(DSM_PKR_message message); + bool verify_dsm_pkr(const DSM_PKR_message& message) const; - enum tags_to_verify{all,utc,slow_eph, eph, none}; - tags_to_verify d_tags_allowed{tags_to_verify::all}; - std::map> d_satellite_nav_data; // map holding NavData sorted by SVID (first key) and TOW (second key). - std::map> d_tesla_keys; // tesla keys over time, sorted by TOW + std::vector get_merkle_tree_leaves(const DSM_PKR_message& dsm_pkr_message) const; + std::vector compute_merkle_root(const DSM_PKR_message& dsm_pkr_message, const std::vector& m_i) const; + std::vector build_message(const Tag& tag); + std::vector hash_chain(uint32_t num_of_hashes_needed, std::vector key, uint32_t GST_SFi, const uint8_t lk_bytes); + std::vector verify_macseq_new(const MACK_message& mack); + + std::map> d_satellite_nav_data; // map holding NavData sorted by SVID (first key) and TOW (second key). + std::map> d_tesla_keys; // tesla keys over time, sorted by TOW + std::multimap d_tags_awaiting_verify; // container with tags to verify from arbitrary SVIDs, sorted by TOW + + std::vector d_tags_to_verify{0, 4, 12}; + std::vector d_validated_key{}; std::vector d_macks_awaiting_MACSEQ_verification; - std::multimap d_tags_awaiting_verify; // container with tags to verify from arbitrary SVIDs, sorted by TOW - std::unique_ptr d_dsm_reader; // osnma parameters parser - std::unique_ptr d_crypto; // access to cryptographic functions - std::unique_ptr d_helper; - std::array, 16> d_dsm_message{}; // structure for recording DSM blocks, when filled it sends them to parse and resets itself. + std::array, 16> d_dsm_message{}; // structure for recording DSM blocks, when filled it sends them to parse and resets itself. std::array, 16> d_dsm_id_received{}; std::array d_number_of_blocks{}; - std::array d_mack_message{}; // C: 480 b + std::array d_mack_message{}; // C: 480 b + + std::unique_ptr d_dsm_reader; // osnma parameters parser + std::unique_ptr d_crypto; // access to cryptographic functions + std::unique_ptr d_helper; OSNMA_data d_osnma_data{}; + + enum tags_to_verify + { + all, + utc, + slow_eph, + eph, + none + }; + tags_to_verify d_tags_allowed{tags_to_verify::all}; + std::time_t d_receiver_time{0}; + + uint32_t d_GST_Sf{}; // C: used for MACSEQ and Tesla Key verification TODO need really to be global var? + uint32_t d_last_verified_key_GST{0}; + uint32_t d_GST_0{}; + uint32_t d_GST_SIS{}; + + uint8_t d_Lt_min{}; // minimum equivalent tag length + uint8_t d_Lt_verified_eph{0}; // verified tag bits - ephemeris + uint8_t d_Lt_verified_utc{0}; // verified tag bits - timing + uint8_t const d_T_L{30}; // s RG Section 2.1 + uint8_t const d_delta_COP{30}; // s SIS ICD Table 14 + bool d_new_data{false}; bool d_public_key_verified{false}; bool d_kroot_verified{false}; bool d_tesla_key_verified{false}; bool d_flag_debug{false}; - uint32_t d_GST_Sf {}; // C: used for MACSEQ and Tesla Key verification TODO need really to be global var? - uint32_t d_last_verified_key_GST{0}; - uint32_t d_GST_0 {}; - uint32_t d_GST_SIS {}; - std::time_t d_receiver_time {0}; - uint8_t d_Lt_min {}; // minimum equivalent tag length - uint8_t d_Lt_verified_eph {0}; // verified tag bits - ephemeris - uint8_t d_Lt_verified_utc {0}; // verified tag bits - timing - uint8_t const d_T_L{30}; // s RG Section 2.1 - uint8_t const d_delta_COP{30}; // s SIS ICD Table 14 - - std::vector d_tags_to_verify{0,4,12}; - std::vector d_validated_key{}; // Provide access to inner functions to Gtest FRIEND_TEST(OsnmaMsgReceiverTest, TeslaKeyVerification); diff --git a/src/core/system_parameters/osnma_data.h b/src/core/system_parameters/osnma_data.h index 105c4cbc2..484fa0162 100644 --- a/src/core/system_parameters/osnma_data.h +++ b/src/core/system_parameters/osnma_data.h @@ -82,7 +82,7 @@ class DSM_PKR_message public: DSM_PKR_message() = default; - std::array itn; // bitset<1024> + std::array itn{}; // bitset<1024> std::vector npk; std::vector p_dp; uint8_t nb_dp{}; 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 7daa43fb4..d0df27a3b 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 @@ -83,7 +83,7 @@ TEST_F(OsnmaMsgReceiverTest, ComputeMerkleRoot) // Act // ---------- - computed_merkle_root = osnma->compute_merke_root(dsm_pkr_message,base_leaf); + computed_merkle_root = osnma->compute_merkle_root(dsm_pkr_message, base_leaf); // Assert // ---------- @@ -102,7 +102,7 @@ TEST_F(OsnmaMsgReceiverTest, ComputeBaseLeaf) // Act // ---------- - std::vector computed_base_leaf = osnma->compute_base_leaf(dsm_pkr_message); + std::vector computed_base_leaf = osnma->get_merkle_tree_leaves(dsm_pkr_message); // Assert // ----------