From a47cf1187c1983729ca627b1de63c52fccb0a468 Mon Sep 17 00:00:00 2001 From: cesaaargm Date: Thu, 1 Aug 2024 11:52:28 +0200 Subject: [PATCH] [TAS-255] [BUG] Assure time synch. is properly done if d_flag_debug=false, now system clock is used to for the receiver synchronisation. It uses the UTC time and the GST epoch start time (adjusted for local time zone difference) to create a local estimation of GST, then compares with GST_SIS (coming from NavData Words 5 and 6) --- src/core/libs/osnma_msg_receiver.cc | 185 ++++++++---------- src/core/libs/osnma_msg_receiver.h | 30 +-- src/core/system_parameters/osnma_helper.cc | 41 +++- src/core/system_parameters/osnma_helper.h | 8 + .../osnma/osnma_msg_receiver_test.cc | 5 +- 5 files changed, 141 insertions(+), 128 deletions(-) diff --git a/src/core/libs/osnma_msg_receiver.cc b/src/core/libs/osnma_msg_receiver.cc index 1e85e3a89..7035a9e08 100644 --- a/src/core/libs/osnma_msg_receiver.cc +++ b/src/core/libs/osnma_msg_receiver.cc @@ -112,6 +112,21 @@ osnma_msg_receiver::osnma_msg_receiver(const std::string& crtFilePath, const std boost::bind(&osnma_msg_receiver::msg_handler_osnma, this, _1)); #endif #endif + std::chrono::time_point now; + if (d_flag_debug){ + // d_GST_Rx = d_helper->compute_gst(d_initial_debug_time); + LOG(WARNING) << "Galileo OSNMA: Debug mode, time artificially set up."; + std::cout << "Galileo OSNMA: Debug mode, time artificially set up." << std::endl; + // TODO - need to synchronize time lapse with Gnss_Synchro? + } + else{ + d_GST_Rx = d_helper->compute_gst_now(); + } + + d_WN = d_helper->get_WN(d_GST_Rx); + d_TOW = d_helper->get_TOW(d_GST_Rx); + LOG(WARNING) << "Galileo OSNMA: initial receiver time GST=["<< d_WN << " " << d_TOW <<"]"; + std::cout << "Galileo OSNMA: initial receiver time GST=["<< d_WN << " " << d_TOW <<"]" << std::endl; } @@ -138,6 +153,50 @@ void osnma_msg_receiver::msg_handler_osnma(const pmt::pmt_t& msg) LOG(INFO) << output_message.str(); std::cout << output_message.str() << std::endl; + // Receiver time update + d_GST_SIS = d_helper->compute_gst(nma_msg->WN_sf0, nma_msg->TOW_sf0); + if (d_last_verified_key_GST == 0){ + d_last_received_GST = d_GST_SIS; + } + else if (d_GST_SIS > d_last_received_GST){ + d_last_received_GST = d_GST_SIS; + } + if (d_flag_debug){ + d_GST_Rx = d_last_received_GST; + } + else{ + d_GST_Rx = d_helper->compute_gst_now(); + } + LOG(INFO) << "Galileo OSNMA: Receiver Time GST=[" << d_helper->get_WN(d_GST_Rx) << " " << d_helper->get_TOW(d_GST_Rx) << "]"; + std::cout << "Galileo OSNMA: Receiver Time GST=[" << d_helper->get_WN(d_GST_Rx) << " " << d_helper->get_TOW(d_GST_Rx) << "]" << std::endl; + + // time constraint verification + std::time_t delta_T = std::abs(static_cast(d_GST_Rx - d_GST_SIS)); + if (delta_T <= d_T_L) + { + d_tags_to_verify = {0, 4, 12}; + LOG(INFO) << "Galileo OSNMA: time constraint OK ( delta_T=" << delta_T << " s)"; + std::cout << "Galileo OSNMA: time constraint OK ( delta_T=" << delta_T << " s)" << std::endl; + } + else if (delta_T > d_T_L && delta_T <= 10 * d_T_L) + { + d_tags_to_verify = {12}; + LOG(WARNING) << "Galileo OSNMA: time constraint allows only slow MACs to be verified"; + std::cout << "Galileo OSNMA: |local_t - GST_SIS| < T_L [ |" << static_cast(d_GST_Rx - d_GST_SIS) << " | < " << static_cast(d_T_L) << " ]" << std::endl; + LOG(WARNING) << "Galileo OSNMA: d_receiver_time: " << d_GST_Rx << " d_GST_SIS: " << d_GST_SIS; + LOG(WARNING) << "Galileo OSNMA: |local_t - GST_SIS| < T_L [ |" << static_cast(d_GST_Rx - d_GST_SIS) << " | < " << static_cast(d_T_L) << " ]"; + } + else + { + d_tags_to_verify = {}; + LOG(WARNING) << "Galileo OSNMA: time constraint violation"; + std::cerr << "Galileo OSNMA: time constraint violation" << std::endl; + std::cerr << "Galileo OSNMA: | local_t - GST_SIS | < T_L [ | " << static_cast(d_GST_Rx - d_GST_SIS) << " | < " << static_cast(d_T_L) << " ]" << std::endl; + LOG(WARNING) << "Galileo OSNMA: d_receiver_time: " << d_GST_Rx << " d_GST_SIS: " << d_GST_SIS; + LOG(WARNING) << "Galileo OSNMA: | local_t - GST_SIS | < T_L [ | " << static_cast(d_GST_Rx - d_GST_SIS) << " | < " << static_cast(d_T_L) << " ]"; + return; + } + process_osnma_message(nma_msg); } // OSNMA frame received else if (msg_type_hash_code == typeid(std::shared_ptr>).hash_code()) // Navigation data bits for OSNMA received @@ -159,7 +218,7 @@ void osnma_msg_receiver::msg_handler_osnma(const pmt::pmt_t& msg) } // Send the resulting decoded NMA data (if available) to PVT - if (d_new_data) // TODO where is it set to true? + if (d_new_data) { auto osnma_data_ptr = std::make_shared(d_osnma_data); this->message_port_pub(pmt::mp("OSNMA_to_PVT"), pmt::make_any(osnma_data_ptr)); @@ -177,13 +236,14 @@ void osnma_msg_receiver::process_osnma_message(const std::shared_ptr& } read_nma_header(osnma_msg->hkroot[0]); - // Check for corner cases: renewal, revocation + // Check for corner cases: renewal, revocation, alert message if (d_osnma_data.d_nma_header.nmas == 0 /* RES */){ LOG(WARNING) << "Galileo OSNMA: NMAS invalid (RES), skipping osnma message"; return; } // TODO - trusting the NMAS and CPKS shall be done upon PKR verification or Tag verification. // It's ok to activate the flags, but the final decision should happen after verifying it. + // For OAM is solved, but NPK and PKREV I think not yet if (d_osnma_data.d_nma_header.nmas == 2 /* OP */ && d_osnma_data.d_nma_header.cpks == 4 /* NPK */ && d_GST_PKR_PKREV_start == 0){ d_flag_PK_renewal = true; d_GST_PKR_PKREV_start = d_helper->compute_gst(osnma_msg->WN_sf0, osnma_msg->TOW_sf0); @@ -229,9 +289,9 @@ void osnma_msg_receiver::process_osnma_message(const std::shared_ptr& read_dsm_header(osnma_msg->hkroot[1]); 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); + if (d_osnma_data.d_dsm_kroot_message.towh_k != 0){ + d_GST_0 = d_helper->compute_gst(d_osnma_data.d_dsm_kroot_message.wn_k, d_osnma_data.d_dsm_kroot_message.towh_k * 3600); + d_GST_Sf = d_GST_0 + 30 * std::floor((d_GST_SIS - d_GST_0) / 30); // Eq. 3 R.G. } read_and_process_mack_block(osnma_msg); // only process them if at least 3 available. } @@ -350,63 +410,6 @@ void osnma_msg_receiver::read_dsm_block(const std::shared_ptr& osnma_ std::cout << available_blocks.str() << std::endl; } - -/** - * @brief Function to verify the local time based on GST_SIS and GST_0 - * - * @param osnma_msg Shared pointer to OSNMA message structure - */ -void osnma_msg_receiver::local_time_verification(const std::shared_ptr& osnma_msg) -{ - // compute local time based on GST_SIS and GST_0 - d_GST_SIS = (osnma_msg->WN_sf0 & 0x00000FFF) << 20 | (osnma_msg->TOW_sf0 & 0x000FFFFF); - // std::cout << "Galileo OSNMA: d_GST_SIS: " << d_GST_SIS << std::endl; - // d_GST_0 = d_osnma_data.d_dsm_kroot_message.towh_k + 604800 * d_osnma_data.d_dsm_kroot_message.wn_k + 30; - d_GST_0 = ((d_osnma_data.d_dsm_kroot_message.wn_k & 0x00000FFF) << 20 | (d_osnma_data.d_dsm_kroot_message.towh_k * 3600 & 0x000FFFFF)); // applicable time (GST_Kroot + 30) - // d_GST_0 = d_osnma_data.d_dsm_kroot_message.towh_k + 604800 * d_osnma_data.d_dsm_kroot_message.wn_k + 30; - // TODO store list of SVs sending OSNMA and if received ID matches one stored, then just increment time 30s for that ID. - if (d_receiver_time != 0) - { - d_receiver_time = d_GST_0 + 30 * std::floor((d_GST_SIS - d_GST_0) / 30); // Eq. 3 R.G. - // d_receiver_time += 30; - // std::cout << "Galileo OSNMA: d_receiver_time: " << d_receiver_time << std::endl; - } - else - { // local time not initialised -> compute it. - d_receiver_time = d_GST_0 + 30 * std::floor((d_GST_SIS - d_GST_0) / 30); // Eq. 3 R.G. - // std::cout << "Galileo OSNMA: d_receiver_time: " << d_receiver_time << std::endl; - } - // verify time constraint - std::time_t delta_T = std::abs(static_cast(d_receiver_time - d_GST_SIS)); - if (delta_T <= d_T_L) - { - d_tags_allowed = tags_to_verify::all; - d_tags_to_verify = {0, 4, 12}; - LOG(INFO) << "Galileo OSNMA: time constraint OK ( delta_T=" << delta_T << " s)"; - // LOG(INFO) << "Galileo OSNMA: d_receiver_time: " << d_receiver_time << " d_GST_SIS: " << d_GST_SIS; - // std::cout << "( |local_t - GST_SIS| < T_L ) [ |" << static_cast(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 - } - else if (delta_T > d_T_L && delta_T <= 10 * d_T_L) - { - d_tags_allowed = tags_to_verify::slow_eph; - d_tags_to_verify = {12}; - LOG(WARNING) << "Galileo OSNMA: time constraint allows only slow MACs to be verified"; - LOG(WARNING) << "Galileo OSNMA: d_receiver_time: " << d_receiver_time << " d_GST_SIS: " << d_GST_SIS; - LOG(WARNING) << "Galileo OSNMA: ( |local_t - GST_SIS| < T_L ) [ |" << static_cast(d_receiver_time - d_GST_SIS) << " | < " << static_cast(d_T_L) << " ]"; - } - else - { - d_tags_allowed = tags_to_verify::none; - d_tags_to_verify = {}; - LOG(WARNING) << "Galileo OSNMA: time constraint violation"; - LOG(WARNING) << "Galileo OSNMA: d_receiver_time: " << d_receiver_time << " d_GST_SIS: " << d_GST_SIS; - LOG(WARNING) << "Galileo OSNMA: ( |local_t - GST_SIS| < T_L ) [ |" << static_cast(d_receiver_time - d_GST_SIS) << " | < " << static_cast(d_T_L) << " ]"; - } -} - - /** * @brief Process DSM block of an OSNMA message. * @@ -671,7 +674,6 @@ void osnma_msg_receiver::process_dsm_message(const std::vector& dsm_msg else if (d_flag_alert_message){ LOG(WARNING) << "Galileo OSNMA: DSM-PKR verification :: Alert message verification :: SUCCESS. OSNMA disabled. Contact Galileo Service Centre"; std::cout << "Galileo OSNMA: DSM-PKR verification :: Alert message verification :: SUCCESS. OSNMA disabled. Contact Galileo Service Centre" << std::endl; - } else{ d_crypto->d_PublicKeyType = PKT; @@ -686,7 +688,6 @@ void osnma_msg_receiver::process_dsm_message(const std::vector& dsm_msg d_count_failed_pubKey ++; if (d_flag_alert_message){ d_flag_alert_message = false; // disregard message as its authenticity could not be verified. - } } } @@ -697,7 +698,7 @@ void osnma_msg_receiver::process_dsm_message(const std::vector& dsm_msg 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; // TODO - reset during header parsing in PKREV? + d_number_of_blocks[d_osnma_data.d_dsm_header.dsm_id] = 0; // TODO - reset during header parsing in PKREV? } @@ -725,8 +726,7 @@ void osnma_msg_receiver::read_and_process_mack_block(const std::shared_ptrPRN; // FIXME this is ugly. d_osnma_data.d_mack_message.TOW = osnma_msg->TOW_sf0; @@ -1012,14 +1012,8 @@ void osnma_msg_receiver::process_mack_message() { 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) << "Galileo OSNMA: But it will be processed for debugging purposes."; - } + return; // early return, cannot proceed further without one of the two verified. this equals to having Kroot but no TESLa key yet. + } // 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.get_tow_sf0()) == d_tesla_keys.end()) // check if already available => no need to verify @@ -1425,14 +1419,14 @@ void osnma_msg_receiver::display_data() bool osnma_msg_receiver::verify_tesla_key(std::vector& key, uint32_t TOW) { uint32_t num_of_hashes_needed; - uint32_t GST_SFi = d_receiver_time - 30; // GST of target key is to be used. + uint32_t GST_SFi = d_GST_Sf - 30; // GST of target key is to be used. std::vector hash; const uint8_t lk_bytes = d_dsm_reader->get_lk_bits(d_osnma_data.d_dsm_kroot_message.ks) / 8; std::vector validated_key; if (d_tesla_key_verified) { // have to go up to last verified key validated_key = d_tesla_keys.rbegin()->second; - num_of_hashes_needed = (d_receiver_time - d_last_verified_key_GST) / 30; // Eq. 19 ICD modified + num_of_hashes_needed = (d_GST_Sf - d_last_verified_key_GST) / 30; // Eq. 19 ICD modified LOG(INFO) << "Galileo OSNMA: TESLA verification (" << num_of_hashes_needed << " hashes) need to be performed up to closest verified TESLA key"; hash = hash_chain(num_of_hashes_needed, key, GST_SFi, lk_bytes); @@ -1440,7 +1434,7 @@ bool osnma_msg_receiver::verify_tesla_key(std::vector& key, uint32_t TO else { // have to go until Kroot validated_key = d_osnma_data.d_dsm_kroot_message.kroot; - num_of_hashes_needed = (d_receiver_time - d_GST_0) / 30 + 1; // Eq. 19 IC + num_of_hashes_needed = (d_GST_Sf - d_GST_0) / 30 + 1; // Eq. 19 IC LOG(INFO) << "Galileo OSNMA: TESLA verification (" << num_of_hashes_needed << " hashes) need to be performed up to Kroot"; hash = hash_chain(num_of_hashes_needed, key, GST_SFi, lk_bytes); @@ -1458,24 +1452,16 @@ bool osnma_msg_receiver::verify_tesla_key(std::vector& key, uint32_t TO 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; + d_last_verified_key_GST = d_GST_Sf; } else if (num_of_hashes_needed > 0) { 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)); - d_last_verified_key_GST = d_receiver_time; - d_tesla_key_verified = true; - // TODO - if intermediate verification fails, can one still use the former verified tesla key or should go to Kroot or even retrieve new Kroot? - } } return d_tesla_key_verified; } - /** * @brief Removes the tags that have been verified from the multimap d_tags_awaiting_verify. * @@ -1582,7 +1568,7 @@ void osnma_msg_receiver::control_tags_awaiting_verify_size() bool osnma_msg_receiver::verify_macseq(const MACK_message& mack) { // 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.. + uint32_t GST_SFi = d_GST_Sf - 30; // time of the start of SF containing MACSEQ std::vector applicable_key = d_tesla_keys[mack.TOW + 30]; // current tesla key ie transmitted in the next subframe std::vector sq1{}; std::vector sq2{}; @@ -1594,7 +1580,6 @@ bool osnma_msg_receiver::verify_macseq(const MACK_message& mack) sq1 = it->second.sequence1; sq2 = it->second.sequence2; } - // Assign relevant sequence based on subframe time if (mack.TOW % 60 < 30) // tried GST_Sf and it does not support the data present. { @@ -1633,12 +1618,12 @@ bool osnma_msg_receiver::verify_macseq(const MACK_message& mack) return true; } // Fixed as well as FLX Tags share first part - Eq. 22 ICD - std::vector m(5 + 2 * flxTags.size()); // each flx tag brings two bytes + std::vector m(5 + 2 * flxTags.size()); // each flx tag brings two bytes m[0] = static_cast(mack.PRNa); // PRN_A - SVID of the satellite transmiting the tag - m[1] = static_cast((d_GST_Sf & 0xFF000000) >> 24); // TODO d_GST_Sf left useless - m[2] = static_cast((d_GST_Sf & 0x00FF0000) >> 16); - m[3] = static_cast((d_GST_Sf & 0x0000FF00) >> 8); - m[4] = static_cast(d_GST_Sf & 0x000000FF); + m[1] = static_cast((GST_SFi & 0xFF000000) >> 24); + m[2] = static_cast((GST_SFi & 0x00FF0000) >> 16); + m[3] = static_cast((GST_SFi & 0x0000FF00) >> 8); + m[4] = static_cast(GST_SFi & 0x000000FF); // Case tags flexible - Eq. 21 ICD for (size_t i = 0; i < flxTags.size(); i++) { @@ -1823,7 +1808,7 @@ std::vector osnma_msg_receiver::verify_macseq_new(const MACK_ 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. + uint32_t GST_Sfi = d_GST_Sf - 30; // time of the start of SF containing MACSEQ std::vector applicable_key; const auto key_it = d_tesla_keys.find(mack.TOW + 30); // current tesla key ie transmitted in the next subframe if (key_it != d_tesla_keys.cend()) @@ -1889,12 +1874,12 @@ std::vector osnma_msg_receiver::verify_macseq_new(const MACK_ return verified_tags; } // Fixed as well as FLX Tags share first part - Eq. 22 ICD - std::vector m(5 + 2 * flxTags.size()); // each flx tag brings two bytes + std::vector m(5 + 2 * flxTags.size()); // each flx tag brings two bytes m[0] = static_cast(mack.PRNa); // PRN_A - SVID of the satellite transmiting the tag - m[1] = static_cast((d_GST_Sf & 0xFF000000) >> 24); // TODO d_GST_Sf left useless - m[2] = static_cast((d_GST_Sf & 0x00FF0000) >> 16); - m[3] = static_cast((d_GST_Sf & 0x0000FF00) >> 8); - m[4] = static_cast(d_GST_Sf & 0x000000FF); + m[1] = static_cast((GST_Sfi & 0xFF000000) >> 24); + m[2] = static_cast((GST_Sfi & 0x00FF0000) >> 16); + m[3] = static_cast((GST_Sfi & 0x0000FF00) >> 8); + m[4] = static_cast(GST_Sfi & 0x000000FF); // Case tags flexible - Eq. 21 ICD for (size_t i = 0; i < flxTags.size(); i++) { diff --git a/src/core/libs/osnma_msg_receiver.h b/src/core/libs/osnma_msg_receiver.h index 59158ab4c..fb83f2b8c 100644 --- a/src/core/libs/osnma_msg_receiver.h +++ b/src/core/libs/osnma_msg_receiver.h @@ -73,7 +73,6 @@ private: void read_nma_header(uint8_t nma_header); void read_dsm_header(uint8_t dsm_header); void read_dsm_block(const std::shared_ptr& osnma_msg); - void local_time_verification(const std::shared_ptr& osnma_msg); void process_dsm_block(const std::shared_ptr& osnma_msg); void process_dsm_message(const std::vector& dsm_msg, const uint8_t& nma_header); void read_and_process_mack_block(const std::shared_ptr& osnma_msg); @@ -118,35 +117,24 @@ private: 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{}; + uint32_t d_last_received_GST{0}; // latest GST received + uint32_t d_GST_Sf{}; // Scaled GST time for cryptographic computations + uint32_t d_GST_Rx{0}; // local GST receiver time + uint32_t d_last_verified_key_GST{0}; // GST for the latest verified TESLA key + uint32_t d_GST_0{}; // Time of applicability GST (KROOT + 30 s) + uint32_t d_GST_SIS{}; // GST coming from W6 and W5 of SIS uint32_t d_GST_PKR_PKREV_start{}; uint32_t d_GST_PKR_AM_start{}; + uint32_t d_WN{}; + uint32_t d_TOW{}; - 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}; + bool d_flag_debug{true}; bool d_flag_hot_start{false}; bool d_flag_PK_renewal{false}; bool d_flag_PK_revocation{false}; diff --git a/src/core/system_parameters/osnma_helper.cc b/src/core/system_parameters/osnma_helper.cc index f8650ed3f..3ce589302 100644 --- a/src/core/system_parameters/osnma_helper.cc +++ b/src/core/system_parameters/osnma_helper.cc @@ -19,13 +19,37 @@ #include #include #include +#include // timezone -uint32_t Osnma_Helper::compute_gst(uint32_t WN, uint32_t TOW) const -{ - uint32_t GST = (WN & 0x00000FFF) << 20 | (TOW & 0x000FFFFF); - return GST; +uint32_t Osnma_Helper::compute_gst(uint32_t WN, uint32_t TOW) const{ + return (WN & 0x00000FFF) << 20 | (TOW & 0x000FFFFF); } +uint32_t Osnma_Helper::compute_gst(tm& input) +{ + auto epoch_time_point = std::chrono::system_clock::from_time_t(mktime(&GST_START_EPOCH)); + auto input_time_point = std::chrono::system_clock::from_time_t(mktime(&input)); + + // Get the duration from epoch in seconds + auto duration_sec = std::chrono::duration_cast(input_time_point - epoch_time_point); + + // Calculate the week number (WN) and time of week (TOW) + 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; + return compute_gst(week_number, time_of_week); +} + +uint32_t Osnma_Helper::compute_gst_now() +{ + std::chrono::time_point epoch_time_point = std::chrono::system_clock::from_time_t(mktime(&GST_START_EPOCH) - timezone); +// auto time_utc = std::chrono::time_point_cast(time).time_since_epoch(); + auto duration_sec = std::chrono::duration_cast(std::chrono::system_clock::now() - epoch_time_point); + 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; + return compute_gst(week_number, time_of_week); +} std::vector Osnma_Helper::gst_to_uint8(uint32_t GST) const { @@ -121,3 +145,12 @@ std::vector Osnma_Helper::convert_from_hex_string(const std::string& he return result; } +uint32_t Osnma_Helper::get_WN(uint32_t GST) +{ + return (GST & 0xFFF00000) >> 20; +} +uint32_t Osnma_Helper::get_TOW(uint32_t GST) +{ + return GST & 0x000FFFFF; +} + diff --git a/src/core/system_parameters/osnma_helper.h b/src/core/system_parameters/osnma_helper.h index 1e0eae235..ea4e81313 100644 --- a/src/core/system_parameters/osnma_helper.h +++ b/src/core/system_parameters/osnma_helper.h @@ -18,6 +18,7 @@ #define GNSS_SDR_OSNMA_HELPER_H +#include #include #include #include @@ -27,11 +28,18 @@ public: Osnma_Helper() = default; ~Osnma_Helper() = default; uint32_t compute_gst(uint32_t WN, uint32_t TOW) const; + uint32_t compute_gst(std::tm& input); + uint32_t compute_gst_now(); + uint32_t get_WN(uint32_t GST); + uint32_t get_TOW(uint32_t GST); std::vector gst_to_uint8(uint32_t GST) const; std::vector bytes(const std::string& binaryString) const; std::string verification_status_str(int status) const; std::string convert_to_hex_string(const std::vector& vector) const; std::vector convert_from_hex_string(const std::string& hex_string) const; // TODO remove similar function in gnss_crypto + + std::tm GST_START_EPOCH = {0, 0, 0, 22, 8 - 1, 1999 - 1900, 0, 0, 0, 0, 0}; + }; #endif // GNSS_SDR_OSNMA_HELPER_H 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 7dd2e7a8d..5d5e3819f 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 @@ -252,10 +252,9 @@ TEST_F(OsnmaMsgReceiverTest, TeslaKeyVerification) 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_GST_Sf = osnma->d_GST_0 + 30 * std::floor((osnma->d_GST_SIS - osnma->d_GST_0) / 30); // Eq. 3 R.G. 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