diff --git a/src/core/libs/osnma_msg_receiver.cc b/src/core/libs/osnma_msg_receiver.cc index c515228ba..4a5e95ac9 100644 --- a/src/core/libs/osnma_msg_receiver.cc +++ b/src/core/libs/osnma_msg_receiver.cc @@ -21,15 +21,18 @@ #include "Galileo_OSNMA.h" #include "gnss_crypto.h" #include "gnss_satellite.h" -#include "osnma_dsm_reader.h" // for OSNMA_DSM_Reader +#include "osnma_dsm_reader.h" // for OSNMA_DSM_Reader #include "osnma_helper.h" #include // for gr::io_signature::make +#include #include #include #include #include #include #include // for typeid +#include + #if USE_GLOG_AND_GFLAGS #include // for DLOG @@ -95,16 +98,16 @@ void osnma_msg_receiver::msg_handler_osnma(const pmt::pmt_t& msg) if (msg_type_hash_code == typeid(std::shared_ptr).hash_code()) { const auto nma_msg = wht::any_cast>(pmt::any_ref(msg)); - const auto sat = Gnss_Satellite(std::string("Galileo"), nma_msg->PRN); // TODO remove if unneeded + const auto sat = Gnss_Satellite(std::string("Galileo"), nma_msg->PRN); // TODO remove if unneeded std::ostringstream output_message; output_message << "Galileo OSNMA: Subframe received starting at " - << "WN=" - << nma_msg->WN_sf0 - << ", TOW=" - << nma_msg->TOW_sf0 - << ", from satellite " - << sat; + << "WN=" + << nma_msg->WN_sf0 + << ", TOW=" + << nma_msg->TOW_sf0 + << ", from satellite " + << sat; LOG(WARNING) << output_message.str(); std::cout << output_message.str() << std::endl; @@ -113,28 +116,31 @@ void osnma_msg_receiver::msg_handler_osnma(const pmt::pmt_t& msg) else if (msg_type_hash_code == typeid(std::shared_ptr>).hash_code()) { // TODO - PRNa is a typo here, I think for d_satellite_nav_data, is PRN_d the name to use - const auto inav_data = wht::any_cast>>(pmt::any_ref(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);; + 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) + if (nav_data.size() == 549) { - LOG(INFO) << "Galileo OSNMA: received ADKD=0/12 navData, PRN_d (" << PRNa << ") " << "TOW_sf=" << TOW <(d_osnma_data); this->message_port_pub(pmt::mp("OSNMA_to_PVT"), pmt::make_any(osnma_data_ptr)); @@ -157,17 +163,17 @@ void osnma_msg_receiver::msg_handler_osnma(const pmt::pmt_t& msg) void osnma_msg_receiver::process_osnma_message(const std::shared_ptr& osnma_msg) { read_nma_header(osnma_msg->hkroot[0]); - if(d_osnma_data.d_nma_header.nmas == 0 || d_osnma_data.d_nma_header.nmas == 3 /*&& d_kroot_verified*/) + if (d_osnma_data.d_nma_header.nmas == 0 || d_osnma_data.d_nma_header.nmas == 3 /*&& d_kroot_verified*/) { - LOG(ERROR) << "Galileo OSNMA: NMAS invalid, skipping osnma message\n"; + LOG(WARNING) << "Galileo OSNMA: NMAS invalid, skipping osnma message"; return; } 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) + 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); - read_and_process_mack_block(osnma_msg); // only process them if at least 3 available. + read_and_process_mack_block(osnma_msg); // only process them if at least 3 available. } @@ -199,9 +205,8 @@ void osnma_msg_receiver::read_dsm_header(uint8_t 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 " << static_cast(d_osnma_data.d_dsm_header.dsm_block_id) - << " from DSM_ID " << static_cast(d_osnma_data.d_dsm_header.dsm_id) - << std::endl; + LOG(INFO) << "Galileo OSNMA: Received block " << static_cast(d_osnma_data.d_dsm_header.dsm_block_id) + << " from DSM_ID " << static_cast(d_osnma_data.d_dsm_header.dsm_id); } /* @@ -219,7 +224,6 @@ void osnma_msg_receiver::read_dsm_block(const std::shared_ptr& osnma_ // First block indicates number of blocks in DSM message if (d_osnma_data.d_dsm_header.dsm_block_id == 0) { - uint8_t nb = d_dsm_reader->get_number_blocks_index(d_dsm_message[d_osnma_data.d_dsm_header.dsm_id][0]); uint16_t number_of_blocks = 0; if (d_osnma_data.d_dsm_header.dsm_id < 12) @@ -255,7 +259,7 @@ void osnma_msg_receiver::read_dsm_block(const std::shared_ptr& osnma_ d_dsm_id_received[d_osnma_data.d_dsm_header.dsm_id][d_osnma_data.d_dsm_header.dsm_block_id] = 1; std::stringstream available_blocks; available_blocks << "Galileo OSNMA: Available blocks for DSM_ID " << static_cast(d_osnma_data.d_dsm_header.dsm_id) << ": [ "; - if (d_number_of_blocks[d_osnma_data.d_dsm_header.dsm_id] == 0) // block 0 not received yet + if (d_number_of_blocks[d_osnma_data.d_dsm_header.dsm_id] == 0) // block 0 not received yet { for (auto id_received : d_dsm_id_received[d_osnma_data.d_dsm_header.dsm_id]) { @@ -283,8 +287,8 @@ void osnma_msg_receiver::read_dsm_block(const std::shared_ptr& osnma_ } } } - available_blocks<< "]" << std::endl; - LOG(INFO) << available_blocks.str() << std::endl; + available_blocks << "]"; + LOG(INFO) << available_blocks.str(); } /** @@ -296,57 +300,53 @@ void osnma_msg_receiver::local_time_verification(const std::shared_ptrWN_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) + // 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; - + 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; + { // 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 = abs(d_receiver_time - d_GST_SIS); - if( delta_T <= d_T_L ) + 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 << "\n"; - LOG(INFO) << "Galileo OSNMA: d_receiver_time: " << d_receiver_time << " d_GST_SIS: " << d_GST_SIS << "\n"; - //std::cout << "( |local_t - GST_SIS| < T_L ) [ |" << static_cast(d_receiver_time - d_GST_SIS)<< " | < " << static_cast(d_T_L) << " ]" << std::endl; + d_tags_to_verify = {0, 4, 12}; + LOG(INFO) << "Galileo OSNMA: time constraint OK (" << delta_T; + 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* delta_T ) + else if (delta_T > d_T_L && delta_T <= 10 * delta_T) { 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\n"; - LOG(WARNING) << "Galileo OSNMA: d_receiver_time: " << d_receiver_time << " d_GST_SIS: " << d_GST_SIS << "\n"; - LOG(WARNING)<< "( |local_t - GST_SIS| < T_L ) [ |" << static_cast(d_receiver_time - d_GST_SIS) << " | < " << static_cast(d_T_L) << " ]" << std::endl; - + 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) << "( |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(ERROR) << "Galileo OSNMA: time constraint violation\n"; - LOG(ERROR) << "Galileo OSNMA: d_receiver_time: " << d_receiver_time << " d_GST_SIS: " << d_GST_SIS << "\n"; - LOG(ERROR) << "( |local_t - GST_SIS| < T_L ) [ |" << static_cast(d_receiver_time - d_GST_SIS) << " | < " << static_cast(d_T_L) << " ]" << std::endl; - + 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) << "( |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. * @@ -362,7 +362,8 @@ void osnma_msg_receiver::process_dsm_block(const std::shared_ptr& osn if ((d_number_of_blocks[d_osnma_data.d_dsm_header.dsm_id] != 0) && (d_number_of_blocks[d_osnma_data.d_dsm_header.dsm_id] == std::accumulate(d_dsm_id_received[d_osnma_data.d_dsm_header.dsm_id].cbegin(), d_dsm_id_received[d_osnma_data.d_dsm_header.dsm_id].cend(), 0))) { - std::vector dsm_msg(std::size_t(d_number_of_blocks[d_osnma_data.d_dsm_header.dsm_id]) * SIZE_DSM_BLOCKS_BYTES, 0); + size_t len = std::size_t(d_number_of_blocks[d_osnma_data.d_dsm_header.dsm_id]) * SIZE_DSM_BLOCKS_BYTES; + std::vector dsm_msg(len, 0); for (uint32_t i = 0; i < d_number_of_blocks[d_osnma_data.d_dsm_header.dsm_id]; i++) { for (size_t j = 0; j < SIZE_DSM_BLOCKS_BYTES; j++) @@ -376,6 +377,7 @@ void osnma_msg_receiver::process_dsm_block(const std::shared_ptr& osn } } + /* * case DSM-Kroot: * - computes the padding and compares with received message @@ -415,7 +417,7 @@ void osnma_msg_receiver::process_dsm_message(const std::vector& dsm_msg l_ds_bits = it->second; } const uint16_t l_ds_bytes = l_ds_bits / 8; - d_osnma_data.d_dsm_kroot_message.ds = std::vector(l_ds_bytes, 0); // C: this accounts for padding in case needed. + d_osnma_data.d_dsm_kroot_message.ds = std::vector(l_ds_bytes, 0); // C: this accounts for padding in case needed. for (uint16_t k = 0; k < l_ds_bytes; k++) { d_osnma_data.d_dsm_kroot_message.ds[k] = dsm_msg[13 + l_lk_bytes + k]; @@ -433,20 +435,20 @@ void osnma_msg_receiver::process_dsm_message(const std::vector& dsm_msg const uint16_t check_l_dk = 104 * std::ceil(1.0 + static_cast((l_lk_bytes * 8.0) + l_ds_bits) / 104.0); if (l_dk_bits != check_l_dk) { - LOG(ERROR) << "Galileo OSNMA: Failed length reading of DSM-KROOT message" << std::endl; + LOG(WARNING) << "Galileo OSNMA: Failed length reading of DSM-KROOT message"; } else { // validation of padding const uint16_t size_m = 13 + l_lk_bytes; std::vector MSG; - MSG.reserve(size_m + l_ds_bytes + 1); // C: message will get too many zeroes? ((12+1)+16) + 64 + 1? => in theory not, allocating is not assigning - MSG.push_back(osnma_msg->hkroot[0]); // C: NMA header + MSG.reserve(size_m + l_ds_bytes + 1); // C: message will get too many zeroes? ((12+1)+16) + 64 + 1? => in theory not, allocating is not assigning + MSG.push_back(osnma_msg->hkroot[0]); // C: NMA header for (uint16_t i = 1; i < size_m; i++) { MSG.push_back(dsm_msg[i]); } - std::vector message = MSG; // MSG = (M | DS) from ICD. Eq. 7 + std::vector message = MSG; // MSG = (M | DS) from ICD. Eq. 7 for (uint16_t k = 0; k < l_ds_bytes; k++) { MSG.push_back(d_osnma_data.d_dsm_kroot_message.ds[k]); @@ -479,27 +481,25 @@ void osnma_msg_receiver::process_dsm_message(const std::vector& dsm_msg LOG(INFO) << "Galileo OSNMA: KROOT with CID=" << static_cast(d_osnma_data.d_nma_header.cid) << ", PKID=" << static_cast(d_osnma_data.d_dsm_kroot_message.pkid) << ", 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 << std::endl; + << ", 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(message, d_osnma_data.d_dsm_kroot_message.ds); if (d_kroot_verified) { - LOG(WARNING) << "Galileo OSNMA: KROOT authentication successful !" << std::endl; - LOG(WARNING) << "Galileo OSNMA: KROOT authentication successful !" << std::endl; - LOG(WARNING) << "Galileo OSNMA: NMA Status is " << d_dsm_reader->get_nmas_status(d_osnma_data.d_nma_header.nmas) << ", " + std::cout << "Galileo OSNMA: KROOT authentication successful!" << std::endl; + LOG(INFO) << "Galileo OSNMA: KROOT authentication successful!"; + LOG(INFO) << "Galileo OSNMA: NMA Status is " << d_dsm_reader->get_nmas_status(d_osnma_data.d_nma_header.nmas) << ", " << "Chain in force is " << static_cast(d_osnma_data.d_nma_header.cid) << ", " - << "Chain and Public Key Status is " << d_dsm_reader->get_cpks_status(d_osnma_data.d_nma_header.cpks) << std::endl; + << "Chain and Public Key Status is " << d_dsm_reader->get_cpks_status(d_osnma_data.d_nma_header.cpks); } else { - LOG(ERROR) << "Galileo OSNMA: KROOT authentication failed. " << std::endl; - LOG(INFO) << "Galileo OSNMA: KROOT authentication failed. " << std::endl; + LOG(WARNING) << "Galileo OSNMA: KROOT authentication failed."; } - } else { - LOG(ERROR) << "Galileo OSNMA: Error computing padding bits." << std::endl; + LOG(WARNING) << "Galileo OSNMA: Error computing padding bits."; // TODO - here will have to decide if perform the verification or not. Since this step is not mandatory, one could as well have skipped it. } } @@ -544,7 +544,7 @@ void osnma_msg_receiver::process_dsm_message(const std::vector& dsm_msg uint32_t check_l_dp_bytes = 104 * std::ceil(static_cast(1040.0 + l_npk_bytes * 8.0) / 104.0) / 8; if (l_dp_bytes != check_l_dp_bytes) { - LOG(ERROR) << "Galileo OSNMA: Failed length reading of DSM-PKR message" << std::endl; + LOG(WARNING) << "Galileo OSNMA: Failed length reading of DSM-PKR message"; } else { @@ -559,7 +559,7 @@ void osnma_msg_receiver::process_dsm_message(const std::vector& dsm_msg << ", PKID=" << static_cast(d_osnma_data.d_dsm_pkr_message.npktid) /*<< ", 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*/ - << " received" << std::endl; + << " received"; // C: NPK verification against Merkle tree root. if (!d_public_key_verified) { @@ -570,7 +570,6 @@ void osnma_msg_receiver::process_dsm_message(const std::vector& dsm_msg d_crypto->set_public_key(d_osnma_data.d_dsm_pkr_message.npk); } } - } } else @@ -582,6 +581,7 @@ void osnma_msg_receiver::process_dsm_message(const std::vector& dsm_msg d_number_of_blocks[d_osnma_data.d_dsm_header.dsm_id] = 0; } + /** * @brief Reads the Mack message from the given OSNMA_msg object. * @@ -601,16 +601,16 @@ void osnma_msg_receiver::read_and_process_mack_block(const std::shared_ptrPRN,osnma_msg->TOW_sf0,d_osnma_data.d_nav_data); // TODO change place -// DEBUG PARSING MACK MESSAGES WHEN DSM-KROOT NOT YET AVAILABLE -// d_osnma_data.d_dsm_kroot_message.ts = 9; -// d_osnma_data.d_dsm_kroot_message.ks = 4; -// d_osnma_data.d_dsm_kroot_message.kroot = std::vector(16); - if (d_kroot_verified || d_tesla_key_verified || d_osnma_data.d_dsm_kroot_message.ts != 0 /*mack parser needs to know the tag size, otherwise cannot parse mack messages*/) // C: 4 ts < ts < 10 - { // TODO - correct? with this, MACK would not be processed unless a Kroot is available -- no, if TK available MACK sould go on, this has to change in future + d_osnma_data.d_nav_data.init(osnma_msg); // TODO refactor it + // add_satellite_data(osnma_msg->PRN,osnma_msg->TOW_sf0,d_osnma_data.d_nav_data); // TODO change place + // DEBUG PARSING MACK MESSAGES WHEN DSM-KROOT NOT YET AVAILABLE + // d_osnma_data.d_dsm_kroot_message.ts = 9; + // d_osnma_data.d_dsm_kroot_message.ks = 4; + // d_osnma_data.d_dsm_kroot_message.kroot = std::vector(16); + if (d_kroot_verified || d_tesla_key_verified || d_osnma_data.d_dsm_kroot_message.ts != 0 /*mack parser needs to know the tag size, otherwise cannot parse mack messages*/) // C: 4 ts < ts < 10 + { // TODO - correct? with this, MACK would not be processed unless a Kroot is available -- no, if TK available MACK sould go on, this has to change in future read_mack_header(); - d_osnma_data.d_mack_message.PRNa = osnma_msg->PRN; // FIXME this is ugly. + d_osnma_data.d_mack_message.PRNa = osnma_msg->PRN; // FIXME this is ugly. d_osnma_data.d_mack_message.TOW = osnma_msg->TOW_sf0; d_osnma_data.d_mack_message.WN = osnma_msg->WN_sf0; read_mack_body(); @@ -620,14 +620,15 @@ void osnma_msg_receiver::read_and_process_mack_block(const std::shared_ptr((d_mack_message[7/* bytes of MACK header */ + k * 7 /* offset of k-th tag */])) << 32); + tag += (static_cast((d_mack_message[7 /* bytes of MACK header */ + k * 7 /* offset of k-th tag */])) << 32); tag += (static_cast((d_mack_message[8 + k * 7])) << 24); tag += (static_cast((d_mack_message[9 + k * 7])) << 16); tag += (static_cast((d_mack_message[10 + k * 7])) << 8); @@ -847,7 +849,7 @@ void osnma_msg_receiver::read_mack_body() PRN_d += d_mack_message[12 + k * 7]; ADKD += ((d_mack_message[13 + k * 7] & 0xF0) >> 4); cop += (d_mack_message[13 + k * 7] & 0x0F); - if (k == (nt - 2)) // end of Tag&Info + if (k == (nt - 2)) // end of Tag&Info { d_osnma_data.d_mack_message.key = std::vector(d_osnma_data.d_dsm_kroot_message.kroot.size()); for (size_t j = 0; j < d_osnma_data.d_dsm_kroot_message.kroot.size(); j++) @@ -881,38 +883,43 @@ void osnma_msg_receiver::read_mack_body() */ void osnma_msg_receiver::process_mack_message() { - if(d_kroot_verified == false && d_tesla_key_verified == false) + if (d_kroot_verified == false && d_tesla_key_verified == false) { - LOG(WARNING) << "Galileo OSNMA: MACK cannot be processed. "<< ", " - << "No Kroot nor TESLA key available" << std::endl; - 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. + 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."; } // 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 + 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 { bool retV = verify_tesla_key(d_osnma_data.d_mack_message.key, d_osnma_data.d_nav_data.TOW_sf0); - if(retV){ - d_tesla_keys.insert(std::pair(d_osnma_data.d_nav_data.TOW_sf0, d_osnma_data.d_mack_message.key)); + if (retV) + { + d_tesla_keys.insert(std::pair>(d_osnma_data.d_nav_data.TOW_sf0, d_osnma_data.d_mack_message.key)); } } - // MACSEQ - verify current macks, then add current retrieved mack to the end. auto mack = d_macks_awaiting_MACSEQ_verification.begin(); - while (mack != d_macks_awaiting_MACSEQ_verification.end()){ - if(d_tesla_keys.find(mack->TOW + 30) != d_tesla_keys.end()){ + while (mack != d_macks_awaiting_MACSEQ_verification.end()) + { + if (d_tesla_keys.find(mack->TOW + 30) != d_tesla_keys.end()) + { bool ret = verify_macseq(*mack); - if (ret || d_flag_debug){ - for(std::size_t i = 0; i < mack->tag_and_info.size(); ++i) + if (ret || d_flag_debug) + { + for (std::size_t i = 0; i < mack->tag_and_info.size(); ++i) { // add tags of current mack to the verification queue auto& tag = mack->tag_and_info[i]; - Tag t(tag, mack->TOW, mack->WN, mack->PRNa, i + 2); // tag0 (mack header) has CTR1, so first tag of MTI has CTR = 2. - d_tags_awaiting_verify.insert(std::pair(mack->TOW, t)); + Tag t(tag, mack->TOW, mack->WN, mack->PRNa, i + 2); // tag0 (mack header) has CTR1, so first tag of MTI has CTR = 2. + d_tags_awaiting_verify.insert(std::pair(mack->TOW, t)); LOG(WARNING) << "Galileo OSNMA: MACSEQ verification :: SUCCESS for Mack at TOW=" << mack->TOW << ", PRN" << mack->PRNa; } std::cout << "Galileo OSNMA: d_tags_awaiting_verify :: size: " << d_tags_awaiting_verify.size() << std::endl; @@ -923,90 +930,91 @@ void osnma_msg_receiver::process_mack_message() 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 + else + { // key not yet available - keep in container until then -- might be deleted if container size exceeds max allowed ++mack; } } // add current received MACK to the container to be verified in the next iteration (on this one no key available) d_macks_awaiting_MACSEQ_verification.push_back(d_osnma_data.d_mack_message); - // Tag verification - for (auto & it : d_tags_awaiting_verify){ + for (auto& it : d_tags_awaiting_verify) + { bool ret; - if(tag_has_key_available(it.second) && tag_has_nav_data_available(it.second)){ + if (tag_has_key_available(it.second) && tag_has_nav_data_available(it.second)) + { ret = verify_tag(it.second); /* TODO - take into account: * - COP: if * - ADKD type * - NavData the tag verifies (min. number of bits verified to consider NavData OK) * */ - if(ret) + 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) - << std::endl; + << 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); } - /* TODO notify PVT via pmt - * have_new_data() true - * signal which one is verified - * communicate to PVT*/ + /* TODO notify PVT via pmt + * have_new_data() true + * signal which one is verified + * communicate to PVT*/ else - { - it.second.status = Tag::FAIL; - LOG(ERROR) << "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 - << ", TOW=" - << it.second.TOW - << ", ADKD=" - << static_cast(it.second.ADKD) - << ", PRNa=" - << static_cast(it.second.PRNa) - << ", PRNd=" - << static_cast(it.second.PRN_d) - << std::endl; - } + { + it.second.status = Tag::FAIL; + 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 + << ", TOW=" + << it.second.TOW + << ", ADKD=" + << static_cast(it.second.ADKD) + << ", PRNa=" + << static_cast(it.second.PRNa) + << ", PRNd=" + << static_cast(it.second.PRN_d); + } } - else if(it.second.TOW > d_osnma_data.d_nav_data.TOW_sf0){ + else if (it.second.TOW > d_osnma_data.d_nav_data.TOW_sf0) + { // case 1: adkd=12 and t.Tow + 300 < current TOW // case 2: adkd=0/4 and t.Tow + 30 < current TOW // case 3: any adkd and t.Tow > current TOW - it.second.skipped ++; - LOG(WARNING) << "Galileo OSNMA: Tag verification :: SKIPPED (x"<< it.second.skipped <<")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) - << ". Key available ("<< tag_has_key_available(it.second) <<"), navData ("<< tag_has_nav_data_available(it.second) <<"). " - << std::endl; + it.second.skipped++; + LOG(WARNING) << "Galileo OSNMA: Tag verification :: SKIPPED (x" << it.second.skipped << ")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) + << ". Key available (" << tag_has_key_available(it.second) << "), navData (" << tag_has_nav_data_available(it.second) << "). "; } } remove_verified_tags(); - control_tags_awaiting_verify_size(); // remove the oldest tags if size is too big. + control_tags_awaiting_verify_size(); // remove the oldest tags if size is too big. } + bool osnma_msg_receiver::verify_dsm_pkr(DSM_PKR_message message) { // TODO create function for recursively apply hash @@ -1021,30 +1029,33 @@ bool osnma_msg_receiver::verify_dsm_pkr(DSM_PKR_message message) } // compute intermediate leafs' values -// std::vector x_0,x_1,x_2,x_3,x_4; - LOG(INFO) << "Galileo OSNMA: DSM-PKR :: leaf provided: m_" << static_cast(message.mid) << std::endl; + // std::vector x_0,x_1,x_2,x_3,x_4; + LOG(INFO) << "Galileo OSNMA: DSM-PKR :: leaf provided: m_" << static_cast(message.mid); std::vector x_next, x_current = d_crypto->computeSHA256(m_i); - for (size_t i = 0 ; i < 4 ; i++) - { - x_next.clear(); - bool leaf_is_on_right = ((message.mid / (1 << (i))) % 2) == 1; + for (size_t i = 0; i < 4; i++) + { + x_next.clear(); + bool leaf_is_on_right = ((message.mid / (1 << (i))) % 2) == 1; - if (leaf_is_on_right) { - // Leaf is on the right -> first the itn, then concatenate the leaf - x_next.insert(x_next.end(), &message.itn[32*i], &message.itn[32*i + 32]); - x_next.insert(x_next.end(), x_current.begin(), x_current.end()); - } else { - // Leaf is on the left -> first the leaf, then concatenate the itn - x_next.insert(x_next.end(), x_current.begin(), x_current.end()); - x_next.insert(x_next.end(), &message.itn[32*i], &message.itn[32*i + 32]); - } + if (leaf_is_on_right) + { + // Leaf is on the right -> first the itn, then concatenate the leaf + x_next.insert(x_next.end(), &message.itn[32 * i], &message.itn[32 * i + 32]); + x_next.insert(x_next.end(), x_current.begin(), x_current.end()); + } + else + { + // Leaf is on the left -> first the leaf, then concatenate the itn + x_next.insert(x_next.end(), x_current.begin(), x_current.end()); + x_next.insert(x_next.end(), &message.itn[32 * i], &message.itn[32 * i + 32]); + } - // Compute the next node. - x_current = d_crypto->computeSHA256(x_next); - } + // Compute the next node. + x_current = d_crypto->computeSHA256(x_next); + } - if(x_current == d_crypto->getMerkleRoot()) + if (x_current == d_crypto->getMerkleRoot()) { LOG(INFO) << "Galileo OSNMA: DSM-PKR verified successfully! " << std::endl; return true; @@ -1055,6 +1066,8 @@ bool osnma_msg_receiver::verify_dsm_pkr(DSM_PKR_message message) return false; } } + + bool osnma_msg_receiver::verify_tag(Tag& tag) { // TODO case tag0, to be verified here?, PRNd not needed for it @@ -1065,20 +1078,20 @@ bool osnma_msg_receiver::verify_tag(Tag& tag) std::vector applicable_key; if (tag.ADKD == 0 || tag.ADKD == 4) applicable_key = d_tesla_keys[tag.TOW + 30]; - else // ADKD 12 + else // ADKD 12 applicable_key = d_tesla_keys[tag.TOW + 330]; - if (d_osnma_data.d_dsm_kroot_message.mf == 0) // C: HMAC-SHA-256 + if (d_osnma_data.d_dsm_kroot_message.mf == 0) // C: HMAC-SHA-256 { mac = d_crypto->computeHMAC_SHA_256(applicable_key, m); } - else if (d_osnma_data.d_dsm_kroot_message.mf == 1) // C: CMAC-AES + else if (d_osnma_data.d_dsm_kroot_message.mf == 1) // C: CMAC-AES { mac = d_crypto->computeCMAC_AES(applicable_key, m); } // truncate the computed mac: trunc(l_t, mac(K,m)) Eq. 23 ICD - uint8_t lt_bits = 0; // TODO - remove this duplication of code. + uint8_t lt_bits = 0; // TODO - remove this duplication of code. const auto it2 = OSNMA_TABLE_11.find(d_osnma_data.d_dsm_kroot_message.ts); if (it2 != OSNMA_TABLE_11.cend()) { @@ -1119,34 +1132,33 @@ bool osnma_msg_receiver::verify_tag(Tag& tag) if (tag.received_tag == computed_mac) { std::cout << "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 - << ", TOW=" - << tag.TOW - << ", ADKD=" - << static_cast(tag.ADKD) - << ", PRNa=" - << static_cast(tag.PRNa) - << ", PRNd=" - << static_cast(tag.PRN_d) - << std::endl; + << tag.tag_id + << ", value=0x" << std::setfill('0') << std::setw(10) << std::hex << std::uppercase + << tag.received_tag << std::dec + << ", TOW=" + << tag.TOW + << ", ADKD=" + << static_cast(tag.ADKD) + << ", PRNa=" + << static_cast(tag.PRNa) + << ", PRNd=" + << static_cast(tag.PRN_d); return true; } - - else - return false; + return false; } + + std::vector osnma_msg_receiver::build_message(const Tag& tag) { std::vector m; - if(tag.CTR != 1) + if (tag.CTR != 1) 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); + uint32_t GST = d_helper->compute_gst(tag.WN, tag.TOW); std::vector GST_uint8 = d_helper->gst_to_uint8(GST); - m.insert(m.end(),GST_uint8.begin(),GST_uint8.end()); + m.insert(m.end(), GST_uint8.begin(), GST_uint8.end()); m.push_back(tag.CTR); // Extracts only two bits from d_osnma_data.d_nma_header.nmas uint8_t two_bits_nmas = d_osnma_data.d_nma_header.nmas & 0b00000011; @@ -1156,7 +1168,7 @@ std::vector osnma_msg_receiver::build_message(const Tag& tag) // Add applicable NavData bits to message std::string applicable_nav_data; std::vector applicable_nav_data_bytes; - 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. + 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; } @@ -1165,76 +1177,91 @@ std::vector osnma_msg_receiver::build_message(const Tag& tag) applicable_nav_data = d_satellite_nav_data[tag.PRN_d][tag.TOW - 30].utc_vector_2; } else - LOG(ERROR) <<"Galileo OSNMA :: Tag verification :: unknown ADKD" <<"\n"; + LOG(WARNING) << "Galileo OSNMA :: Tag verification :: unknown ADKD"; // convert std::string to vector applicable_nav_data_bytes = d_helper->bytes(applicable_nav_data); // Convert and add NavData bytes into the message, taking care of that NMAS has only 2 bits - for (uint8_t byte : applicable_nav_data_bytes) { + for (uint8_t byte : applicable_nav_data_bytes) + { m.back() |= (byte >> 2); // First take the 6 MSB bits of byte and add to m - m.push_back(byte << 6); // Then take the last 2 bits of byte, shift them to MSB position and insert the new element into m + m.push_back(byte << 6); // Then take the last 2 bits of byte, shift them to MSB position and insert the new element into m } - if(m.back() == 0) { + if (m.back() == 0) + { m.pop_back(); // Remove the last element if its value is 0 (only padding was added) } - else { + else + { // Pad with zeros if the last element wasn't full - for (int bits = 2; bits < 8; bits += 2) { + for (int bits = 2; bits < 8; bits += 2) + { // Check if the last element in the vector has 2 '00' bits in its LSB position - if((m.back() & 0b00000011) == 0) { + if ((m.back() & 0b00000011) == 0) + { m.back() <<= 2; // Shift the existing bits to make room for new 2 bits } - else { + else + { break; // If it does not have 2 '00' bits in its LSB position, then the padding is complete } } } return m; } + + void osnma_msg_receiver::add_satellite_data(uint32_t SV_ID, uint32_t TOW, const NavData& data) { // control size of container - while (d_satellite_nav_data[SV_ID].size() >= 25) { + while (d_satellite_nav_data[SV_ID].size() >= 25) + { d_satellite_nav_data[SV_ID].erase(d_satellite_nav_data[SV_ID].begin()); } - //d_osnma_data[TOW] = crypto; // crypto - d_satellite_nav_data[SV_ID][TOW] = data; // nav - //std::cout << "Galileo OSNMA: added element, size is " << d_satellite_nav_data[SV_ID].size() << std::endl; + // d_osnma_data[TOW] = crypto; // crypto + d_satellite_nav_data[SV_ID][TOW] = data; // nav + // std::cout << "Galileo OSNMA: added element, size is " << d_satellite_nav_data[SV_ID].size() << std::endl; } + + void osnma_msg_receiver::display_data() { -// if(d_satellite_nav_data.empty()) -// return; -// -// for(const auto& satellite : d_satellite_nav_data) { -// std::cout << "SV_ID: " << satellite.first << std::endl; -// for(const auto& towData : satellite.second) { -// std::cout << "\tTOW: " << towData.first << " key: "; -// for(size_t i = 0; i < towData.second.d_mack_message.key.size(); i++) { -// std::cout << std::hex << std::setfill('0') << std::setw(2) -// << static_cast(towData.second.d_mack_message.key[i]) << " "; -// } -// } -// } + // if(d_satellite_nav_data.empty()) + // return; + // + // for(const auto& satellite : d_satellite_nav_data) { + // std::cout << "SV_ID: " << satellite.first << std::endl; + // for(const auto& towData : satellite.second) { + // std::cout << "\tTOW: " << towData.first << " key: "; + // for(size_t i = 0; i < towData.second.d_mack_message.key.size(); i++) { + // std::cout << std::hex << std::setfill('0') << std::setw(2) + // << static_cast(towData.second.d_mack_message.key[i]) << " "; + // } + // } + // } } + + 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_receiver_time - 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 + 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 d_validated_key = d_tesla_keys.rbegin()->second; - num_of_hashes_needed = (d_receiver_time - 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 " << std::endl; + num_of_hashes_needed = (d_receiver_time - 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); + hash = hash_chain(num_of_hashes_needed, key, GST_SFi, lk_bytes); } - else{// have to go until Kroot + else + { // have to go until Kroot d_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 - LOG(INFO) << "Galileo OSNMA: TESLA verification ("<< num_of_hashes_needed << " hashes) need to be performed up to Kroot " << std::endl; + num_of_hashes_needed = (d_receiver_time - 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); } @@ -1247,23 +1274,26 @@ 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! " << std::endl; - d_tesla_keys.insert(std::pair(TOW,key)); + LOG(WARNING) << "Galileo OSNMA:: TESLA key verification :: SUCCESS!"; + 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(ERROR) << "Galileo OSNMA:: TESLA key verification :: FAILED " << std::endl; - if(d_flag_debug){ - d_tesla_keys.insert(std::pair(TOW,key)); + else if (num_of_hashes_needed > 0) + { + LOG(WARNING) << "Galileo OSNMA:: TESLA key verification :: FAILED"; + 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. * @@ -1271,7 +1301,8 @@ bool osnma_msg_receiver::verify_tesla_key(std::vector& key, uint32_t TO */ void osnma_msg_receiver::remove_verified_tags() { - for (auto it = d_tags_awaiting_verify.begin(); it != d_tags_awaiting_verify.end() ; ){ + for (auto it = d_tags_awaiting_verify.begin(); it != d_tags_awaiting_verify.end();) + { if (it->second.status == Tag::SUCCESS || it->second.status == Tag::FAIL) { LOG(INFO) << "Galileo OSNMA: Tag verification :: DELETE tag Id=" @@ -1287,8 +1318,7 @@ void osnma_msg_receiver::remove_verified_tags() << ", PRNd=" << static_cast(it->second.PRN_d) << ", status= " - << d_helper->verification_status_str(it->second.status) - << std::endl; + << d_helper->verification_status_str(it->second.status); it = d_tags_awaiting_verify.erase(it); } else if (it->second.skipped >= 20) @@ -1306,8 +1336,7 @@ void osnma_msg_receiver::remove_verified_tags() << ", PRNd=" << static_cast(it->second.PRN_d) << ", status= " - << d_helper->verification_status_str(it->second.status) - << std::endl; + << d_helper->verification_status_str(it->second.status); it = d_tags_awaiting_verify.erase(it); } else @@ -1315,6 +1344,8 @@ void osnma_msg_receiver::remove_verified_tags() } std::cout << "Galileo OSNMA: d_tags_awaiting_verify :: size: " << d_tags_awaiting_verify.size() << std::endl; } + + /** * @brief Control the size of the tags awaiting verification multimap. * @@ -1325,19 +1356,19 @@ void osnma_msg_receiver::remove_verified_tags() */ void osnma_msg_receiver::control_tags_awaiting_verify_size() { - while(d_tags_awaiting_verify.size() > 500) + 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 - << std::endl; + << ", from satellite " << it->second.PRNa; d_tags_awaiting_verify.erase(it); } } + /** * @brief Verifies the MACSEQ of a received MACK_message. * @@ -1349,8 +1380,8 @@ 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.. - std::vector applicable_key = d_tesla_keys[mack.TOW + 30]; // current tesla key ie transmitted in the next subframe + 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.. + 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{}; std::vector applicable_sequence; @@ -1363,7 +1394,7 @@ bool osnma_msg_receiver::verify_macseq(const MACK_message& mack) } // Assign relevant sequence based on subframe time - if (mack.TOW % 60 < 30) // tried GST_Sf and it does not support the data present. + if (mack.TOW % 60 < 30) // tried GST_Sf and it does not support the data present. { applicable_sequence = sq1; } @@ -1373,55 +1404,56 @@ bool osnma_msg_receiver::verify_macseq(const MACK_message& mack) } else { - LOG(ERROR) << "Galileo OSNMA: Mismatch in the GST verification. " << std::endl; + LOG(WARNING) << "Galileo OSNMA: Mismatch in the GST verification."; } - if(mack.tag_and_info.size() != applicable_sequence.size() - 1) + if (mack.tag_and_info.size() != applicable_sequence.size() - 1) { - LOG(ERROR) << "Galileo OSNMA: Number of retrieved tags does not match MACLT sequence size!" << std::endl; + LOG(WARNING) << "Galileo OSNMA: Number of retrieved tags does not match MACLT sequence size!"; return false; } - std::vector flxTags {}; + std::vector flxTags{}; std::string tempADKD; // MACLT verification for (uint8_t i = 0; i < mack.tag_and_info.size(); i++) { - tempADKD = applicable_sequence[i+1]; - if(tempADKD == "FLX") + tempADKD = applicable_sequence[i + 1]; + if (tempADKD == "FLX") { - flxTags.push_back(i); // C: just need to save the index in the sequence + flxTags.push_back(i); // C: just need to save the index in the sequence } - else if(mack.tag_and_info[i].tag_info.ADKD != std::stoi(applicable_sequence[i+1])) + else if (mack.tag_and_info[i].tag_info.ADKD != std::stoi(applicable_sequence[i + 1])) { - LOG(WARNING) << "Galileo OSNMA: MACSEQ verification :: FAILURE :: ADKD mismatch against MAC Look-up table. " << std::endl; - return false; // C: suffices one incorrect to abort and not process the rest of the tags + LOG(WARNING) << "Galileo OSNMA: MACSEQ verification :: FAILURE :: ADKD mismatch against MAC Look-up table."; + return false; // C: suffices one incorrect to abort and not process the rest of the tags } } - if(flxTags.empty()){ - LOG(WARNING) << "Galileo OSNMA: MACSEQ verification :: SUCCESS :: ADKD matches MAC Look-up table. " << std::endl; + if (flxTags.empty()) + { + LOG(WARNING) << "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 - 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 + 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); // Case tags flexible - Eq. 21 ICD - for (uint8_t i = 0; i < flxTags.size() ; i++) + for (uint8_t i = 0; i < flxTags.size(); i++) { - m[2*i + 5] = mack.tag_and_info[flxTags[i]].tag_info.PRN_d; - m[2*i + 6] = mack.tag_and_info[flxTags[i]].tag_info.ADKD << 4 | + m[2 * i + 5] = mack.tag_and_info[flxTags[i]].tag_info.PRN_d; + m[2 * i + 6] = mack.tag_and_info[flxTags[i]].tag_info.ADKD << 4 | mack.tag_and_info[flxTags[i]].tag_info.cop; } // compute mac std::vector mac; - if (d_osnma_data.d_dsm_kroot_message.mf == 0) // C: HMAC-SHA-256 + if (d_osnma_data.d_dsm_kroot_message.mf == 0) // C: HMAC-SHA-256 { mac = d_crypto->computeHMAC_SHA_256(applicable_key, m); } - else if (d_osnma_data.d_dsm_kroot_message.mf == 1) // C: CMAC-AES + else if (d_osnma_data.d_dsm_kroot_message.mf == 1) // C: CMAC-AES { mac = d_crypto->computeCMAC_AES(applicable_key, m); } @@ -1432,39 +1464,51 @@ bool osnma_msg_receiver::verify_macseq(const MACK_message& mack) mac_msb = (mac[0] << 8) + mac[1]; } 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 " << std::endl; + if (computed_macseq == mack.header.macseq) + { + LOG(WARNING) << "Galileo OSNMA: MACSEQ verification :: SUCCESS :: FLX tags verification OK"; return true; } - else{ - LOG(ERROR) << "Galileo OSNMA: MACSEQ verification :: FAILURE :: FLX tags verification failed " << std::endl; + else + { + LOG(WARNING) << "Galileo OSNMA: MACSEQ verification :: FAILURE :: FLX tags verification failed"; return false; } - } + + bool osnma_msg_receiver::tag_has_nav_data_available(Tag& t) { auto prn_it = d_satellite_nav_data.find(t.PRN_d); - if (prn_it != d_satellite_nav_data.end()) { + if (prn_it != d_satellite_nav_data.end()) + { // PRN was found, check if TOW exists in inner map LOG(INFO) << "Galileo OSNMA: hasData = true " << std::endl; std::map& tow_map = prn_it->second; auto tow_it = tow_map.find(t.TOW - 30); - if (tow_it != tow_map.end()) { + if (tow_it != tow_map.end()) + { return true; - } else { + } + else + { // TOW not found return false; } - } else { + } + else + { // PRN was not found LOG(INFO) << "Galileo OSNMA: hasData = false " << std::endl; return false; } return false; } -bool osnma_msg_receiver::tag_has_key_available(Tag& t){ + + +bool osnma_msg_receiver::tag_has_key_available(Tag& t) +{ // check adkd of tag // if adkd = 0 or 4 => look for d_tesla_keys[t.TOW+30] // if adkd = 12 => look for d_tesla_keys[t.TOW+300] @@ -1484,36 +1528,38 @@ bool osnma_msg_receiver::tag_has_key_available(Tag& t){ auto it = d_tesla_keys.find(t.TOW + 330); if (it != d_tesla_keys.end()) { - LOG(INFO)<< "Galileo OSNMA: hasKey = true " << std::endl; + LOG(INFO) << "Galileo OSNMA: hasKey = true " << std::endl; return true; } } LOG(INFO) << "Galileo OSNMA: hasKey = false "; return false; } + + 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 K_I; // result of the recursive hash operations std::vector msg; // compute the tesla key for current SF (GST_SFi and K_II change in each iteration) - for (uint32_t i = 1; i <= num_of_hashes_needed ; i++) + for (uint32_t i = 1; i <= num_of_hashes_needed; i++) { // build message digest m = (K_I+1 || GST_SFi || alpha) msg.reserve(K_II.size() + sizeof(GST_SFi) + sizeof(d_osnma_data.d_dsm_kroot_message.alpha)); - std::copy(K_II.begin(),K_II.end(),std::back_inserter(msg)); + std::copy(K_II.begin(), K_II.end(), std::back_inserter(msg)); msg.push_back((GST_SFi & 0xFF000000) >> 24); msg.push_back((GST_SFi & 0x00FF0000) >> 16); msg.push_back((GST_SFi & 0x0000FF00) >> 8); msg.push_back(GST_SFi & 0x000000FF); - // extract alpha -// d_osnma_data.d_dsm_kroot_message.alpha = 0xa06221261ad9; - for (int k = 5; k >= 0;k--) + // extract alpha + // d_osnma_data.d_dsm_kroot_message.alpha = 0xa06221261ad9; + for (int k = 5; k >= 0; k--) { // TODO: static extracts the MSB in case from larger to shorter int? - msg.push_back(static_cast((d_osnma_data.d_dsm_kroot_message.alpha >> (k * 8)) & 0xFF)); // extract first 6 bytes of alpha. + msg.push_back(static_cast((d_osnma_data.d_dsm_kroot_message.alpha >> (k * 8)) & 0xFF)); // extract first 6 bytes of alpha. } // compute hash std::vector hash; @@ -1530,31 +1576,31 @@ std::vector osnma_msg_receiver::hash_chain(uint32_t num_of_hashes_neede hash = std::vector(32); } // truncate hash - K_I.reserve(lk_bytes); // TODO - case hash function has 512 bits + K_I.reserve(lk_bytes); // TODO - case hash function has 512 bits for (int k = 0; k < lk_bytes; k++) { K_I.push_back(hash[k]); } // set parameters for next iteration - GST_SFi -= 30; // next SF time is the actual minus 30 seconds - K_II = K_I; // next key is the actual one - K_I.clear(); // empty the actual one for a new computation + GST_SFi -= 30; // next SF time is the actual minus 30 seconds + K_II = K_I; // next key is the actual one + K_I.clear(); // empty the actual one for a new computation msg.clear(); } // check that the final time matches the Kroot time bool check; - if(!d_tesla_key_verified) + if (!d_tesla_key_verified) check = GST_SFi + 30 == d_GST_0 - 30; else check = GST_SFi + 30 == d_last_verified_key_GST; - if(!check) - LOG(ERROR) << "Galileo OSNMA: TESLA verification error. Kroot time mismatch! \n"; // ICD. Eq. 18 + if (!check) + LOG(WARNING) << "Galileo OSNMA: TESLA verification error. Kroot time mismatch!"; // ICD. Eq. 18 else - LOG(INFO) << "Galileo OSNMA: TESLA verification. Kroot time matches! \n"; // ICD. Eq. 18 + 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.\n"; + LOG(INFO) << "Galileo OSNMA: TESLA verification (" << num_of_hashes_needed << " hashes) took " << elapsed.count() << " seconds."; return K_II; } diff --git a/src/core/system_parameters/CMakeLists.txt b/src/core/system_parameters/CMakeLists.txt index 607c3702a..0ef4cf22e 100644 --- a/src/core/system_parameters/CMakeLists.txt +++ b/src/core/system_parameters/CMakeLists.txt @@ -163,6 +163,10 @@ if(OPENSSL_FOUND) target_compile_definitions(core_system_parameters PUBLIC -DUSE_OPENSSL_FALLBACK=1 -DUSE_OPENSSL_3=1) message("USE_OPENSSL_3: " ${DUSE_OPENSSL_3}) message("USE_OPENSSL_FALLBACK:" ${USE_OPENSSL_FALLBACK}) + else() + if(NOT OPENSSL_VERSION VERSION_LESS "1.1.1") + target_compile_definitions(core_system_parameters PRIVATE -DUSE_OPENSSL_FALLBACK=1 -DUSE_OPENSSL_111=1) + endif() endif() endif() diff --git a/src/core/system_parameters/gnss_crypto.cc b/src/core/system_parameters/gnss_crypto.cc index 947b8a436..0f1774271 100644 --- a/src/core/system_parameters/gnss_crypto.cc +++ b/src/core/system_parameters/gnss_crypto.cc @@ -60,6 +60,11 @@ Gnss_Crypto::Gnss_Crypto() { #if USE_OPENSSL_FALLBACK +#if !(USE_OPENSSL_3 || USE_OPENSSL_111) + LOG(WARNING) << "The OpenSSL library version you are linking against is too old for some OSNMA functions." + << " Please do not trust OSNMA ouputs or upgrade your system to a newer version of OpenSSL" + << " and rebuild GNSS-SDR against it."; +#endif #else // GnuTLS gnutls_global_init(); #endif @@ -69,6 +74,11 @@ Gnss_Crypto::Gnss_Crypto() Gnss_Crypto::Gnss_Crypto(const std::string& certFilePath, const std::string& merkleTreePath) { #if USE_OPENSSL_FALLBACK +#if !(USE_OPENSSL_3 || USE_OPENSSL_111) + LOG(WARNING) << "The OpenSSL library version you are linking against is too old for some OSNMA functions." + << " Please do not trust OSNMA ouputs or upgrade your system to a newer version of OpenSSL" + << " and rebuild GNSS-SDR against it."; +#endif #else // GnuTLS gnutls_global_init(); #endif @@ -296,7 +306,7 @@ std::vector Gnss_Crypto::computeSHA3_256(const std::vector& in { std::vector output(32); // SHA256 hash size #if USE_OPENSSL_FALLBACK -#if USE_OPENSSL_3 +#if USE_OPENSSL_3 || USE_OPENSSL_111 EVP_MD_CTX* mdctx = EVP_MD_CTX_new(); const EVP_MD* md = EVP_sha3_256(); @@ -305,7 +315,11 @@ std::vector Gnss_Crypto::computeSHA3_256(const std::vector& in EVP_DigestFinal_ex(mdctx, output.data(), nullptr); EVP_MD_CTX_free(mdctx); #else - // SHA3-256 not implemented in OpenSSL < 3.0 + // SHA3-256 not implemented in OpenSSL 1.0, it was introduced in OpenSSL 1.1.1 + if (!input.empty()) + { + // do nothing + } #endif #else // GnuTLS std::vector output_aux(32); @@ -380,24 +394,16 @@ std::vector Gnss_Crypto::computeHMAC_SHA_256(const std::vector hmac.resize(output_length); output = hmac; #else - std::vector hmac(32); - // Create HMAC context - HMAC_CTX* ctx = HMAC_CTX_new(); - HMAC_Init_ex(ctx, key.data(), key.size(), EVP_sha256(), nullptr); + unsigned int outputLength = EVP_MAX_MD_SIZE; + unsigned char* result = HMAC(EVP_sha256(), key.data(), key.size(), input.data(), input.size(), output.data(), &outputLength); + if (result == nullptr) + { + LOG(WARNING) << "OSNMA HMAC_SHA_256 computation failed to compute HMAC-SHA256"; + return output; + } - // Update HMAC context with the message - HMAC_Update(ctx, input.data(), input.size()); - - // Finalize HMAC computation - unsigned int hmacLen; - HMAC_Final(ctx, hmac.data(), &hmacLen); - - // Clean up HMAC context - HMAC_CTX_free(ctx); - - // Resize the HMAC vector to the actual length - hmac.resize(hmacLen); - output = hmac; + // Resize the output vector to the actual length of the HMAC-SHA256 output + output.resize(outputLength); #endif #else // GnuTLS std::vector output_aux(32); @@ -595,6 +601,7 @@ bool Gnss_Crypto::readPublicKeyFromCRT(const std::string& crtFilePath) // Read the public key from the certificate EVP_PKEY* pubkey = X509_get_pubkey(cert); +#if USE_OPENSSL_3 if (!pubkey) { std::cerr << "Failed to extract the public key" << std::endl; @@ -603,6 +610,18 @@ bool Gnss_Crypto::readPublicKeyFromCRT(const std::string& crtFilePath) } pubkey_copy(pubkey, &d_PublicKey); EVP_PKEY_free(pubkey); +#else + EC_KEY* ec_pubkey = EVP_PKEY_get1_EC_KEY(pubkey); + EVP_PKEY_free(pubkey); + if (!ec_pubkey) + { + std::cerr << "Failed to extract the public key" << std::endl; + X509_free(cert); + return false; + } + pubkey_copy(ec_pubkey, &d_PublicKey); + EC_KEY_free(ec_pubkey); +#endif BIO_free(bio); X509_free(cert); #else // GnuTLS @@ -735,7 +754,13 @@ bool Gnss_Crypto::verify_signature(const std::vector& message, const st LOG(WARNING) << "OpenSSL: OSNMA message authentication failed: " << err; } #else - int verification = ECDSA_verify(0, digest.data(), SHA256_DIGEST_LENGTH, signature.data(), static_cast(signature.size()), d_PublicKey); + std::vector der_sig; + if (!convert_raw_to_der_ecdsa(signature, der_sig)) + { + std::cerr << "Failed to convert raw ECDSA signature to DER format" << std::endl; + return false; + } + int verification = ECDSA_verify(0, digest.data(), SHA256_DIGEST_LENGTH, der_sig.data(), static_cast(der_sig.size()), d_PublicKey); if (verification == 1) { success = true; @@ -744,6 +769,7 @@ bool Gnss_Crypto::verify_signature(const std::vector& message, const st else if (verification == 0) { std::cerr << "OpenSSL: invalid signature found when verifying message" << std::endl; + LOG(WARNING) << "OpenSSL: invalid signature found when verifying message"; } else { @@ -838,12 +864,19 @@ void Gnss_Crypto::set_public_key(const std::vector& publicKey) LOG(INFO) << "OpenSSL: error setting the OSNMA public key."; return; } - +#if USE_OPENSSL_3 if (!pubkey_copy(pkey, &d_PublicKey)) { return; } - +#else + EC_KEY* ec_pkey = EVP_PKEY_get1_EC_KEY(pkey); + if (!pubkey_copy(ec_pkey, &d_PublicKey)) + { + return; + } + EC_KEY_free(ec_pkey); +#endif EVP_PKEY_free(pkey); #else // GnuTLS gnutls_pubkey_t pubkey; @@ -864,53 +897,6 @@ void Gnss_Crypto::set_public_key(const std::vector& publicKey) } -#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 == nullptr) - { - return false; - } - - // Export the public key from src into the memory buffer in PEM format - if (!PEM_write_bio_PUBKEY(mem_bio, src)) - { - BIO_free(mem_bio); - return false; - } - - // 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 == nullptr) - { - BIO_free(mem_bio); - return false; - } - - // Read the public key from the new memory buffer - *dest = PEM_read_bio_PUBKEY(mem_bio2, nullptr, nullptr, nullptr); - if (*dest == nullptr) - { - BIO_free(mem_bio); - BIO_free(mem_bio2); - return false; - } - - // Clean up - BIO_free(mem_bio); - BIO_free(mem_bio2); - - return true; -} - -#else // GnuTLS-specific functions - bool Gnss_Crypto::convert_raw_to_der_ecdsa(const std::vector& raw_signature, std::vector& der_signature) const { if (raw_signature.size() % 2 != 0) @@ -959,6 +945,102 @@ bool Gnss_Crypto::convert_raw_to_der_ecdsa(const std::vector& raw_signa } +#if USE_OPENSSL_FALLBACK +#if USE_OPENSSL_3 +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 == nullptr) + { + return false; + } + + // Export the public key from src into the memory buffer in PEM format + if (!PEM_write_bio_PUBKEY(mem_bio, src)) + { + BIO_free(mem_bio); + return false; + } + + // 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 == nullptr) + { + BIO_free(mem_bio); + return false; + } + + // Read the public key from the new memory buffer + *dest = PEM_read_bio_PUBKEY(mem_bio2, nullptr, nullptr, nullptr); + if (*dest == nullptr) + { + BIO_free(mem_bio); + BIO_free(mem_bio2); + return false; + } + + // Clean up + BIO_free(mem_bio); + BIO_free(mem_bio2); + + return true; +} + +#else // OpenSSL 1.x + +bool Gnss_Crypto::pubkey_copy(EC_KEY* src, EC_KEY** dest) +{ + // Open a memory buffer + BIO* mem_bio = BIO_new(BIO_s_mem()); + if (mem_bio == nullptr) + { + return false; + } + + // Export the public key from src into the memory buffer in PEM format + if (!PEM_write_bio_EC_PUBKEY(mem_bio, src)) + { + BIO_free(mem_bio); + return false; + } + + // 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 == nullptr) + { + BIO_free(mem_bio); + return false; + } + + // Read the public key from the new memory buffer + *dest = PEM_read_bio_EC_PUBKEY(mem_bio2, nullptr, nullptr, nullptr); + if (*dest == nullptr) + { + BIO_free(mem_bio); + BIO_free(mem_bio2); + return false; + } + + // Clean up + BIO_free(mem_bio); + BIO_free(mem_bio2); + + return true; +} + +#endif + +#else // GnuTLS-specific functions + bool Gnss_Crypto::pubkey_copy(gnutls_pubkey_t src, gnutls_pubkey_t* dest) { gnutls_datum_t key_datum; diff --git a/src/core/system_parameters/gnss_crypto.h b/src/core/system_parameters/gnss_crypto.h index 9d60c8a77..bbcac1afa 100644 --- a/src/core/system_parameters/gnss_crypto.h +++ b/src/core/system_parameters/gnss_crypto.h @@ -58,18 +58,19 @@ private: void read_merkle_xml(const std::string& merkleFilePath); void readPublicKeyFromPEM(const std::string& pemFilePath); bool readPublicKeyFromCRT(const std::string& crtFilePath); + bool convert_raw_to_der_ecdsa(const std::vector& raw_signature, std::vector& der_signature) const; std::vector convert_from_hex_str(const std::string& input) const; #if USE_OPENSSL_FALLBACK #if USE_OPENSSL_3 + bool pubkey_copy(EVP_PKEY* src, EVP_PKEY** dest); EVP_PKEY* d_PublicKey{}; -#else +#else // OpenSSL 1.x + bool pubkey_copy(EC_KEY* src, EC_KEY** dest); EC_KEY* d_PublicKey = nullptr; #endif - bool pubkey_copy(EVP_PKEY* src, EVP_PKEY** dest); #else // GnuTLS - gnutls_pubkey_t d_PublicKey{}; - 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); + gnutls_pubkey_t d_PublicKey{}; #endif std::vector d_x_4_0; std::vector d_x_3_1; diff --git a/src/core/system_parameters/osnma_dsm_reader.h b/src/core/system_parameters/osnma_dsm_reader.h index 3eeeb5bea..5031a140e 100644 --- a/src/core/system_parameters/osnma_dsm_reader.h +++ b/src/core/system_parameters/osnma_dsm_reader.h @@ -63,7 +63,6 @@ public: uint8_t get_npktid(const std::vector& dsm_msg) const; private: -#if __cplusplus == 201103L static constexpr std::uint8_t mask_nmas{0xC0}; static constexpr std::uint8_t mask_cid{0x30}; static constexpr std::uint8_t mask_cpks{0x07}; @@ -83,27 +82,6 @@ private: static constexpr std::uint8_t mask_dsm_mid{0x0F}; static constexpr std::uint8_t mask_dsm_npkt{0xF0}; static constexpr std::uint8_t mask_dsm_npktid{0x0F}; -#else - static constexpr std::uint8_t mask_nmas{0b1100'0000}; - static constexpr std::uint8_t mask_cid{0b0011'0000}; - static constexpr std::uint8_t mask_cpks{0b0000'1110}; - static constexpr std::uint8_t mask_nma_header_reserved{0b0000'0001}; - static constexpr std::uint8_t mask_dsm_id{0b1111'0000}; - static constexpr std::uint8_t mask_dsm_block_id{0b0000'1111}; - static constexpr std::uint8_t mask_dsm_number_blocks{0b1111'0000}; - static constexpr std::uint8_t mask_dsm_pkid{0b0000'1111}; - static constexpr std::uint8_t mask_dsm_cidkr{0b1100'0000}; - static constexpr std::uint8_t mask_dsm_reserved1{0b0011'0000}; - static constexpr std::uint8_t mask_dsm_hf{0b0000'1100}; - static constexpr std::uint8_t mask_dsm_mf{0b0000'0011}; - static constexpr std::uint8_t mask_dsm_ks{0b1111'0000}; - static constexpr std::uint8_t mask_dsm_ts{0b0000'1111}; - static constexpr std::uint8_t mask_dsm_reserved{0b1111'0000}; - static constexpr std::uint8_t mask_dsm_wk_k_msbyte{0b0000'1111}; - static constexpr std::uint8_t mask_dsm_mid{0b0000'1111}; - static constexpr std::uint8_t mask_dsm_npkt{0b1111'0000}; - static constexpr std::uint8_t mask_dsm_npktid{0b0000'1111}; -#endif }; /** \} */