1
0
mirror of https://github.com/gnss-sdr/gnss-sdr synced 2025-01-06 07:20:34 +00:00

Read type of public key (#16)

* Clang Tidy fixes

* Improve reading public key type

* Update osnma_nav_data_manager.cc

hotfix

---------

Co-authored-by: cesaaargm <cesare.martinez@proton.me>
This commit is contained in:
Carles Fernandez 2024-08-02 09:38:37 +02:00 committed by GitHub
parent 960e76e3a0
commit 6beb92278f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 307 additions and 146 deletions

View File

@ -29,6 +29,7 @@
#include <algorithm> #include <algorithm>
#include <cmath> #include <cmath>
#include <cstddef> #include <cstddef>
#include <fstream> // for std::ifstream and std::ofstream
#include <iomanip> // for std::setfill #include <iomanip> // for std::setfill
#include <ios> // for std::hex, std::uppercase #include <ios> // for std::hex, std::uppercase
#include <iostream> #include <iostream>
@ -37,7 +38,6 @@
#include <tuple> #include <tuple>
#include <typeinfo> // for typeid #include <typeinfo> // for typeid
#include <utility> #include <utility>
#include <fstream> // for std::ifstream and std::ofstream
#if USE_GLOG_AND_GFLAGS #if USE_GLOG_AND_GFLAGS
@ -68,21 +68,23 @@ osnma_msg_receiver_sptr osnma_msg_receiver_make(const std::string& pemFilePath,
osnma_msg_receiver::osnma_msg_receiver(const std::string& crtFilePath, const std::string& merkleFilePath) : gr::block("osnma_msg_receiver", osnma_msg_receiver::osnma_msg_receiver(const std::string& crtFilePath, const std::string& merkleFilePath) : gr::block("osnma_msg_receiver",
gr::io_signature::make(0, 0, 0), gr::io_signature::make(0, 0, 0),
gr::io_signature::make(0, 0, 0)) gr::io_signature::make(0, 0, 0))
{ {
d_dsm_reader = std::make_unique<OSNMA_DSM_Reader>(); d_dsm_reader = std::make_unique<OSNMA_DSM_Reader>();
d_crypto = std::make_unique<Gnss_Crypto>(crtFilePath, merkleFilePath); d_crypto = std::make_unique<Gnss_Crypto>(crtFilePath, merkleFilePath);
d_helper = std::make_unique<Osnma_Helper>(); d_helper = std::make_unique<Osnma_Helper>();
d_nav_data_manager = std::make_unique<OSNMA_nav_data_Manager>(); d_nav_data_manager = std::make_unique<OSNMA_nav_data_Manager>();
if(d_crypto->have_public_key()){ // Hot start is enabled if (d_crypto->have_public_key())
{ // Hot start is enabled
LOG(WARNING) << "OSNMA Public Key available, trying to find DSM-KROOT saved"; LOG(WARNING) << "OSNMA Public Key available, trying to find DSM-KROOT saved";
std::cout << "OSNMA Public Key available, trying to find DSM-KROOT saved" << std::endl; std::cout << "OSNMA Public Key available, trying to find DSM-KROOT saved" << std::endl;
d_public_key_verified = true; d_public_key_verified = true;
auto dsm_nmah = parse_dsm_kroot(); auto dsm_nmah = parse_dsm_kroot();
if (!dsm_nmah.first.empty()){ if (!dsm_nmah.first.empty())
{
LOG(WARNING) << "OSNMA DSM-KROOT and NMA Header successfully read from file " << KROOTFILE_DEFAULT; LOG(WARNING) << "OSNMA DSM-KROOT and NMA Header successfully read from file " << KROOTFILE_DEFAULT;
std::cout << "OSNMA DSM-KROOT and NMA Header successfully read from file " << KROOTFILE_DEFAULT << std::endl; std::cout << "OSNMA DSM-KROOT and NMA Header successfully read from file " << KROOTFILE_DEFAULT << std::endl;
d_flag_hot_start = true; d_flag_hot_start = true;
@ -113,20 +115,22 @@ osnma_msg_receiver::osnma_msg_receiver(const std::string& crtFilePath, const std
#endif #endif
#endif #endif
std::chrono::time_point<std::chrono::system_clock> now; std::chrono::time_point<std::chrono::system_clock> now;
if (d_flag_debug){ if (d_flag_debug)
{
// d_GST_Rx = d_helper->compute_gst(d_initial_debug_time); // d_GST_Rx = d_helper->compute_gst(d_initial_debug_time);
LOG(WARNING) << "Galileo OSNMA: Debug mode, time artificially set up."; LOG(WARNING) << "Galileo OSNMA: Debug mode, time artificially set up.";
std::cout << "Galileo OSNMA: Debug mode, time artificially set up." << std::endl; std::cout << "Galileo OSNMA: Debug mode, time artificially set up." << std::endl;
// TODO - need to synchronize time lapse with Gnss_Synchro? // TODO - need to synchronize time lapse with Gnss_Synchro?
} }
else{ else
{
d_GST_Rx = d_helper->compute_gst_now(); d_GST_Rx = d_helper->compute_gst_now();
} }
d_WN = d_helper->get_WN(d_GST_Rx); d_WN = d_helper->get_WN(d_GST_Rx);
d_TOW = d_helper->get_TOW(d_GST_Rx); d_TOW = d_helper->get_TOW(d_GST_Rx);
LOG(WARNING) << "Galileo OSNMA: initial receiver time GST=["<< d_WN << " " << d_TOW <<"]"; 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; std::cout << "Galileo OSNMA: initial receiver time GST=[" << d_WN << " " << d_TOW << "]" << std::endl;
} }
@ -155,16 +159,20 @@ void osnma_msg_receiver::msg_handler_osnma(const pmt::pmt_t& msg)
// Receiver time update // Receiver time update
d_GST_SIS = d_helper->compute_gst(nma_msg->WN_sf0, nma_msg->TOW_sf0); d_GST_SIS = d_helper->compute_gst(nma_msg->WN_sf0, nma_msg->TOW_sf0);
if (d_last_verified_key_GST == 0){ if (d_last_verified_key_GST == 0)
{
d_last_received_GST = d_GST_SIS; d_last_received_GST = d_GST_SIS;
} }
else if (d_GST_SIS > d_last_received_GST){ else if (d_GST_SIS > d_last_received_GST)
{
d_last_received_GST = d_GST_SIS; d_last_received_GST = d_GST_SIS;
} }
if (d_flag_debug){ if (d_flag_debug)
{
d_GST_Rx = d_last_received_GST; d_GST_Rx = d_last_received_GST;
} }
else{ else
{
d_GST_Rx = d_helper->compute_gst_now(); 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) << "]"; LOG(INFO) << "Galileo OSNMA: Receiver Time GST=[" << d_helper->get_WN(d_GST_Rx) << " " << d_helper->get_TOW(d_GST_Rx) << "]";
@ -198,7 +206,7 @@ void osnma_msg_receiver::msg_handler_osnma(const pmt::pmt_t& msg)
} }
process_osnma_message(nma_msg); process_osnma_message(nma_msg);
} // OSNMA frame received } // OSNMA frame received
else if (msg_type_hash_code == typeid(std::shared_ptr<std::tuple<uint32_t, std::string, uint32_t>>).hash_code()) // Navigation data bits for OSNMA received else if (msg_type_hash_code == typeid(std::shared_ptr<std::tuple<uint32_t, std::string, uint32_t>>).hash_code()) // Navigation data bits for OSNMA received
{ {
const auto inav_data = wht::any_cast<std::shared_ptr<std::tuple<uint32_t, std::string, uint32_t>>>(pmt::any_ref(msg)); const auto inav_data = wht::any_cast<std::shared_ptr<std::tuple<uint32_t, std::string, uint32_t>>>(pmt::any_ref(msg));
@ -231,26 +239,30 @@ 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>& osnma_msg) void osnma_msg_receiver::process_osnma_message(const std::shared_ptr<OSNMA_msg>& osnma_msg)
{ {
if (d_flag_alert_message && (d_public_key_verified || d_kroot_verified)){ if (d_flag_alert_message && (d_public_key_verified || d_kroot_verified))
{
return; return;
} }
read_nma_header(osnma_msg->hkroot[0]); read_nma_header(osnma_msg->hkroot[0]);
// Check for corner cases: renewal, revocation, alert message // Check for corner cases: renewal, revocation, alert message
if (d_osnma_data.d_nma_header.nmas == 0 /* RES */){ if (d_osnma_data.d_nma_header.nmas == 0 /* RES */)
{
LOG(WARNING) << "Galileo OSNMA: NMAS invalid (RES), skipping osnma message"; LOG(WARNING) << "Galileo OSNMA: NMAS invalid (RES), skipping osnma message";
return; return;
} }
// TODO - trusting the NMAS and CPKS shall be done upon PKR verification or Tag verification. // 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. // 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 // 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){ 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_flag_PK_renewal = true;
d_GST_PKR_PKREV_start = d_helper->compute_gst(osnma_msg->WN_sf0, osnma_msg->TOW_sf0); d_GST_PKR_PKREV_start = d_helper->compute_gst(osnma_msg->WN_sf0, osnma_msg->TOW_sf0);
LOG(INFO) << "Galileo OSNMA: Public Key Renewal :: Start at GST=[" << osnma_msg->WN_sf0 << " " << osnma_msg->TOW_sf0 << "]"; LOG(INFO) << "Galileo OSNMA: Public Key Renewal :: Start at GST=[" << osnma_msg->WN_sf0 << " " << osnma_msg->TOW_sf0 << "]";
std::cout << "Galileo OSNMA: Public Key Renewal :: Start at GST=[" << osnma_msg->WN_sf0 << " " << osnma_msg->TOW_sf0 << "]" << std::endl; std::cout << "Galileo OSNMA: Public Key Renewal :: Start at GST=[" << osnma_msg->WN_sf0 << " " << osnma_msg->TOW_sf0 << "]" << std::endl;
} }
if (d_flag_PK_renewal && d_osnma_data.d_nma_header.nmas == 2 /* OP */ && d_osnma_data.d_nma_header.cpks == 1 /* Nominal */ ){ if (d_flag_PK_renewal && d_osnma_data.d_nma_header.nmas == 2 /* OP */ && d_osnma_data.d_nma_header.cpks == 1 /* Nominal */)
{
d_flag_PK_renewal = false; d_flag_PK_renewal = false;
uint32_t final_GST = d_helper->compute_gst(osnma_msg->WN_sf0, osnma_msg->TOW_sf0); uint32_t final_GST = d_helper->compute_gst(osnma_msg->WN_sf0, osnma_msg->TOW_sf0);
double duration_hours = (final_GST - d_GST_PKR_PKREV_start) / 3600; double duration_hours = (final_GST - d_GST_PKR_PKREV_start) / 3600;
@ -258,7 +270,8 @@ void osnma_msg_receiver::process_osnma_message(const std::shared_ptr<OSNMA_msg>&
std::cout << "Galileo OSNMA: Public Key Renewal :: Finished at GST=" << duration_hours << ", Duration=" << duration_hours << " h" << std::endl; std::cout << "Galileo OSNMA: Public Key Renewal :: Finished at GST=" << duration_hours << ", Duration=" << duration_hours << " h" << std::endl;
} }
if (d_osnma_data.d_nma_header.nmas == 3 /* DU */ && d_osnma_data.d_nma_header.cpks == 5 /* PKREV */ && d_GST_PKR_PKREV_start == 0){ if (d_osnma_data.d_nma_header.nmas == 3 /* DU */ && d_osnma_data.d_nma_header.cpks == 5 /* PKREV */ && d_GST_PKR_PKREV_start == 0)
{
d_flag_PK_revocation = true; d_flag_PK_revocation = true;
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] = 0;
d_public_key_verified = false; d_public_key_verified = false;
@ -268,16 +281,20 @@ void osnma_msg_receiver::process_osnma_message(const std::shared_ptr<OSNMA_msg>&
LOG(INFO) << "Galileo OSNMA: Public Key Revocation :: Start at GST=[" << osnma_msg->WN_sf0 << " " << osnma_msg->TOW_sf0 << "]"; LOG(INFO) << "Galileo OSNMA: Public Key Revocation :: Start at GST=[" << osnma_msg->WN_sf0 << " " << osnma_msg->TOW_sf0 << "]";
std::cout << "Galileo OSNMA: Public Key Revocation :: Start at GST=[" << osnma_msg->WN_sf0 << " " << osnma_msg->TOW_sf0 << "]" << std::endl; std::cout << "Galileo OSNMA: Public Key Revocation :: Start at GST=[" << osnma_msg->WN_sf0 << " " << osnma_msg->TOW_sf0 << "]" << std::endl;
} }
if (d_flag_PK_revocation && d_osnma_data.d_nma_header.nmas == 2 /* OP */ && d_osnma_data.d_nma_header.cpks == 1 /* Nominal */ ){ if (d_flag_PK_revocation && d_osnma_data.d_nma_header.nmas == 2 /* OP */ && d_osnma_data.d_nma_header.cpks == 1 /* Nominal */)
{
// step 2 , start using new chain // step 2 , start using new chain
d_flag_PK_revocation = false; d_flag_PK_revocation = false;
uint32_t final_GST = d_helper->compute_gst(osnma_msg->WN_sf0, osnma_msg->TOW_sf0); uint32_t final_GST = d_helper->compute_gst(osnma_msg->WN_sf0, osnma_msg->TOW_sf0);
double duration_hours = (final_GST - d_GST_PKR_PKREV_start) / 3600; double duration_hours = (final_GST - d_GST_PKR_PKREV_start) / 3600;
LOG(INFO) << "Galileo OSNMA: Public Key Revocation :: Finished at GST=[" << osnma_msg->WN_sf0 << " " << osnma_msg->TOW_sf0 << "]" << ", Duration=" << duration_hours << "h"; LOG(INFO) << "Galileo OSNMA: Public Key Revocation :: Finished at GST=[" << osnma_msg->WN_sf0 << " " << osnma_msg->TOW_sf0 << "]"
std::cout << "Galileo OSNMA: Public Key Revocation :: Finished at GST=[" << osnma_msg->WN_sf0 << " " << osnma_msg->TOW_sf0 << "]" << ", Duration=" << duration_hours << "h" << std::endl; << ", Duration=" << duration_hours << "h";
std::cout << "Galileo OSNMA: Public Key Revocation :: Finished at GST=[" << osnma_msg->WN_sf0 << " " << osnma_msg->TOW_sf0 << "]"
<< ", Duration=" << duration_hours << "h" << std::endl;
} }
if (d_osnma_data.d_nma_header.nmas == 3 /* DU */ && d_osnma_data.d_nma_header.cpks == 7 /* AM */ && d_GST_PKR_AM_start == 0){ if (d_osnma_data.d_nma_header.nmas == 3 /* DU */ && d_osnma_data.d_nma_header.cpks == 7 /* AM */ && d_GST_PKR_AM_start == 0)
{
d_flag_alert_message = true; d_flag_alert_message = true;
d_GST_PKR_AM_start = d_helper->compute_gst(osnma_msg->WN_sf0, osnma_msg->TOW_sf0); d_GST_PKR_AM_start = d_helper->compute_gst(osnma_msg->WN_sf0, osnma_msg->TOW_sf0);
d_public_key_verified = false; d_public_key_verified = false;
@ -289,7 +306,8 @@ void osnma_msg_receiver::process_osnma_message(const std::shared_ptr<OSNMA_msg>&
read_dsm_header(osnma_msg->hkroot[1]); read_dsm_header(osnma_msg->hkroot[1]);
read_dsm_block(osnma_msg); 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 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){ 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_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. d_GST_Sf = d_GST_0 + 30 * std::floor((d_GST_SIS - d_GST_0) / 30); // Eq. 3 R.G.
} }
@ -474,7 +492,7 @@ void osnma_msg_receiver::process_dsm_message(const std::vector<uint8_t>& dsm_msg
d_osnma_data.d_dsm_kroot_message.kroot = d_dsm_reader->get_kroot(dsm_msg, l_lk_bytes); d_osnma_data.d_dsm_kroot_message.kroot = d_dsm_reader->get_kroot(dsm_msg, l_lk_bytes);
// DS field // DS field
uint16_t l_ds_bits = 0; uint16_t l_ds_bits = 0;
const auto it = OSNMA_TABLE_15.find(d_crypto->d_PublicKeyType); const auto it = OSNMA_TABLE_15.find(d_crypto->get_public_key_type());
if (it != OSNMA_TABLE_15.cend()) if (it != OSNMA_TABLE_15.cend())
{ {
l_ds_bits = it->second; l_ds_bits = it->second;
@ -507,12 +525,12 @@ void osnma_msg_receiver::process_dsm_message(const std::vector<uint8_t>& dsm_msg
const uint16_t size_m = 13 + l_lk_bytes; const uint16_t size_m = 13 + l_lk_bytes;
std::vector<uint8_t> MSG; std::vector<uint8_t> MSG;
MSG.reserve(size_m + l_ds_bytes + 1); MSG.reserve(size_m + l_ds_bytes + 1);
MSG.push_back(nma_header); // NMA header MSG.push_back(nma_header); // NMA header
for (uint16_t i = 1; i < size_m; i++) for (uint16_t i = 1; i < size_m; i++)
{ {
MSG.push_back(dsm_msg[i]); MSG.push_back(dsm_msg[i]);
} }
std::vector<uint8_t> message = MSG; // MSG = (M | DS) from ICD. Eq. 7 std::vector<uint8_t> message = MSG; // MSG = (M | DS) from ICD. Eq. 7
for (uint16_t k = 0; k < l_ds_bytes; k++) for (uint16_t k = 0; k < l_ds_bytes; k++)
{ {
MSG.push_back(d_osnma_data.d_dsm_kroot_message.ds[k]); MSG.push_back(d_osnma_data.d_dsm_kroot_message.ds[k]);
@ -549,7 +567,8 @@ void osnma_msg_receiver::process_dsm_message(const std::vector<uint8_t>& dsm_msg
// local_time_verification(osnma_msg); // FIXME TODO: real time verification needed // local_time_verification(osnma_msg); // FIXME TODO: real time verification needed
// If new PK verified and the new KROOT arrived, set the new PK before attempting verification // If new PK verified and the new KROOT arrived, set the new PK before attempting verification
if(d_flag_PK_renewal && d_osnma_data.d_dsm_kroot_message.pkid == d_new_public_key_id && d_flag_NPK_set == false){ if (d_flag_PK_renewal && d_osnma_data.d_dsm_kroot_message.pkid == d_new_public_key_id && d_flag_NPK_set == false)
{
d_crypto->set_public_key(d_new_public_key); d_crypto->set_public_key(d_new_public_key);
d_crypto->store_public_key(PEMFILE_DEFAULT); d_crypto->store_public_key(PEMFILE_DEFAULT);
d_flag_NPK_set = true; d_flag_NPK_set = true;
@ -566,7 +585,8 @@ void osnma_msg_receiver::process_dsm_message(const std::vector<uint8_t>& dsm_msg
{ {
std::cout << "Galileo OSNMA: DSM-KROOT authentication successful!" << std::endl; std::cout << "Galileo OSNMA: DSM-KROOT authentication successful!" << std::endl;
LOG(INFO) << "Galileo OSNMA: DSM-KROOT authentication successful!"; LOG(INFO) << "Galileo OSNMA: DSM-KROOT authentication successful!";
if (d_flag_alert_message){ if (d_flag_alert_message)
{
LOG(WARNING) << "Galileo OSNMA: DSM-KROOT :: Alert message verification :: SUCCESS. "; LOG(WARNING) << "Galileo OSNMA: DSM-KROOT :: Alert message verification :: SUCCESS. ";
} }
else else
@ -576,7 +596,8 @@ void osnma_msg_receiver::process_dsm_message(const std::vector<uint8_t>& dsm_msg
<< "Chain and Public Key Status is " << d_dsm_reader->get_cpks_status(d_osnma_data.d_nma_header.cpks); << "Chain and Public Key Status is " << d_dsm_reader->get_cpks_status(d_osnma_data.d_nma_header.cpks);
} }
// Save DSM-Kroot and NMA header into a permanent storage // Save DSM-Kroot and NMA header into a permanent storage
if (d_flag_hot_start){ if (d_flag_hot_start)
{
d_flag_hot_start = false; d_flag_hot_start = false;
return; return;
} }
@ -586,10 +607,11 @@ void osnma_msg_receiver::process_dsm_message(const std::vector<uint8_t>& dsm_msg
{ {
LOG(WARNING) << "Galileo OSNMA: DSM-KROOT authentication failed."; LOG(WARNING) << "Galileo OSNMA: DSM-KROOT authentication failed.";
std::cerr << "Galileo OSNMA: DSM-KROOT authentication failed." << std::endl; std::cerr << "Galileo OSNMA: DSM-KROOT authentication failed." << std::endl;
if (d_flag_alert_message){ if (d_flag_alert_message)
{
d_flag_alert_message = false; d_flag_alert_message = false;
} }
d_count_failed_Kroot ++; d_count_failed_Kroot++;
} }
} }
else else
@ -613,7 +635,8 @@ void osnma_msg_receiver::process_dsm_message(const std::vector<uint8_t>& dsm_msg
} }
d_osnma_data.d_dsm_pkr_message.npkt = d_dsm_reader->get_npkt(dsm_msg); d_osnma_data.d_dsm_pkr_message.npkt = d_dsm_reader->get_npkt(dsm_msg);
uint8_t npktid = d_dsm_reader->get_npktid(dsm_msg); uint8_t npktid = d_dsm_reader->get_npktid(dsm_msg);
if (d_flag_PK_renewal && npktid > d_osnma_data.d_dsm_pkr_message.npktid){ if (d_flag_PK_renewal && npktid > d_osnma_data.d_dsm_pkr_message.npktid)
{
d_new_public_key_id = npktid; d_new_public_key_id = npktid;
} }
d_osnma_data.d_dsm_pkr_message.npktid = npktid; d_osnma_data.d_dsm_pkr_message.npktid = npktid;
@ -668,15 +691,18 @@ void osnma_msg_receiver::process_dsm_message(const std::vector<uint8_t>& dsm_msg
{ {
LOG(INFO) << "Galileo OSNMA: DSM-PKR verification :: SUCCESS"; LOG(INFO) << "Galileo OSNMA: DSM-PKR verification :: SUCCESS";
d_public_key_verified = true; d_public_key_verified = true;
if (d_flag_PK_renewal){ if (d_flag_PK_renewal)
{
d_new_public_key = d_osnma_data.d_dsm_pkr_message.npk; d_new_public_key = d_osnma_data.d_dsm_pkr_message.npk;
} }
else if (d_flag_alert_message){ else if (d_flag_alert_message)
{
LOG(WARNING) << "Galileo OSNMA: DSM-PKR verification :: Alert message verification :: SUCCESS. OSNMA disabled. Contact Galileo Service Centre"; 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; std::cout << "Galileo OSNMA: DSM-PKR verification :: Alert message verification :: SUCCESS. OSNMA disabled. Contact Galileo Service Centre" << std::endl;
} }
else{ else
d_crypto->d_PublicKeyType = PKT; {
d_crypto->set_public_key_type(PKT);
d_crypto->set_public_key(d_osnma_data.d_dsm_pkr_message.npk); d_crypto->set_public_key(d_osnma_data.d_dsm_pkr_message.npk);
d_crypto->store_public_key(PEMFILE_DEFAULT); d_crypto->store_public_key(PEMFILE_DEFAULT);
} }
@ -685,8 +711,9 @@ void osnma_msg_receiver::process_dsm_message(const std::vector<uint8_t>& dsm_msg
{ {
LOG(ERROR) << "Galileo OSNMA: DSM-PKR verification :: FAILURE"; LOG(ERROR) << "Galileo OSNMA: DSM-PKR verification :: FAILURE";
d_public_key_verified = false; d_public_key_verified = false;
d_count_failed_pubKey ++; d_count_failed_pubKey++;
if (d_flag_alert_message){ if (d_flag_alert_message)
{
d_flag_alert_message = false; // disregard message as its authenticity could not be verified. d_flag_alert_message = false; // disregard message as its authenticity could not be verified.
} }
} }
@ -724,9 +751,10 @@ void osnma_msg_receiver::read_and_process_mack_block(const std::shared_ptr<OSNMA
d_osnma_data.d_nav_data.set_tow_sf0(osnma_msg->TOW_sf0); d_osnma_data.d_nav_data.set_tow_sf0(osnma_msg->TOW_sf0);
bool can_process_mack_block = (d_osnma_data.d_nma_header.nmas != 3 && d_kroot_verified) || // NMAS different than DU bool can_process_mack_block = (d_osnma_data.d_nma_header.nmas != 3 && d_kroot_verified) || // NMAS different than DU
(d_osnma_data.d_nma_header.nmas == 3 && !d_kroot_verified); // NMAS is DU, but must be disregarded (d_osnma_data.d_nma_header.nmas == 3 && !d_kroot_verified); // NMAS is DU, but must be disregarded
bool can_verify_tesla_key = d_kroot_verified || d_tesla_key_verified; // Either of those suffices for verifying the incoming TESLA key bool can_verify_tesla_key = d_kroot_verified || d_tesla_key_verified; // Either of those suffices for verifying the incoming TESLA key
bool can_parse_tag_fields = d_osnma_data.d_dsm_kroot_message.ts != 0; // calculating the number of tags is based on the TS of the DSM-KROOT. bool can_parse_tag_fields = d_osnma_data.d_dsm_kroot_message.ts != 0; // calculating the number of tags is based on the TS of the DSM-KROOT.
if (can_verify_tesla_key && can_parse_tag_fields && can_process_mack_block){ if (can_verify_tesla_key && can_parse_tag_fields && can_process_mack_block)
{
read_mack_header(); 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.TOW = osnma_msg->TOW_sf0;
@ -1617,8 +1645,8 @@ bool osnma_msg_receiver::verify_macseq(const MACK_message& mack)
return true; return true;
} }
// Fixed as well as FLX Tags share first part - Eq. 22 ICD // Fixed as well as FLX Tags share first part - Eq. 22 ICD
std::vector<uint8_t> m(5 + 2 * flxTags.size()); // each flx tag brings two bytes std::vector<uint8_t> m(5 + 2 * flxTags.size()); // each flx tag brings two bytes
m[0] = static_cast<uint8_t>(mack.PRNa); // PRN_A - SVID of the satellite transmiting the tag m[0] = static_cast<uint8_t>(mack.PRNa); // PRN_A - SVID of the satellite transmiting the tag
m[1] = static_cast<uint8_t>((GST_SFi & 0xFF000000) >> 24); m[1] = static_cast<uint8_t>((GST_SFi & 0xFF000000) >> 24);
m[2] = static_cast<uint8_t>((GST_SFi & 0x00FF0000) >> 16); m[2] = static_cast<uint8_t>((GST_SFi & 0x00FF0000) >> 16);
m[3] = static_cast<uint8_t>((GST_SFi & 0x0000FF00) >> 8); m[3] = static_cast<uint8_t>((GST_SFi & 0x0000FF00) >> 8);
@ -1863,7 +1891,7 @@ std::vector<MACK_tag_and_info> osnma_msg_receiver::verify_macseq_new(const MACK_
LOG(WARNING) << "Galileo OSNMA: MACSEQ verification :: FAILURE :: ADKD mismatch against MAC Look-up table for Tag=0x" 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 << std::setfill('0') << std::setw(10) << std::hex << std::uppercase
<< mack.tag_and_info[i].tag << std::dec; << mack.tag_and_info[i].tag << std::dec;
d_count_failed_macseq ++; d_count_failed_macseq++;
} }
} }
@ -1873,8 +1901,8 @@ std::vector<MACK_tag_and_info> osnma_msg_receiver::verify_macseq_new(const MACK_
return verified_tags; return verified_tags;
} }
// Fixed as well as FLX Tags share first part - Eq. 22 ICD // Fixed as well as FLX Tags share first part - Eq. 22 ICD
std::vector<uint8_t> m(5 + 2 * flxTags.size()); // each flx tag brings two bytes std::vector<uint8_t> m(5 + 2 * flxTags.size()); // each flx tag brings two bytes
m[0] = static_cast<uint8_t>(mack.PRNa); // PRN_A - SVID of the satellite transmiting the tag m[0] = static_cast<uint8_t>(mack.PRNa); // PRN_A - SVID of the satellite transmiting the tag
m[1] = static_cast<uint8_t>((GST_Sfi & 0xFF000000) >> 24); m[1] = static_cast<uint8_t>((GST_Sfi & 0xFF000000) >> 24);
m[2] = static_cast<uint8_t>((GST_Sfi & 0x00FF0000) >> 16); m[2] = static_cast<uint8_t>((GST_Sfi & 0x00FF0000) >> 16);
m[3] = static_cast<uint8_t>((GST_Sfi & 0x0000FF00) >> 8); m[3] = static_cast<uint8_t>((GST_Sfi & 0x0000FF00) >> 8);
@ -1924,7 +1952,7 @@ void osnma_msg_receiver::send_data_to_pvt(const std::vector<OSNMA_NavData>& data
{ {
if (!data.empty()) if (!data.empty())
{ {
for (auto & i : data) for (auto& i : data)
{ {
const auto tmp_obj = std::make_shared<OSNMA_NavData>(i); const auto tmp_obj = std::make_shared<OSNMA_NavData>(i);
this->message_port_pub(pmt::mp("OSNMA_to_PVT"), pmt::make_any(tmp_obj)); this->message_port_pub(pmt::mp("OSNMA_to_PVT"), pmt::make_any(tmp_obj));
@ -1936,7 +1964,8 @@ bool osnma_msg_receiver::store_dsm_kroot(const std::vector<uint8_t>& dsm, const
{ {
std::ofstream file(KROOTFILE_DEFAULT, std::ios::binary | std::ios::out); std::ofstream file(KROOTFILE_DEFAULT, std::ios::binary | std::ios::out);
if (!file.is_open()) { if (!file.is_open())
{
return false; return false;
} }
@ -1952,7 +1981,8 @@ bool osnma_msg_receiver::store_dsm_kroot(const std::vector<uint8_t>& dsm, const
std::pair<std::vector<uint8_t>, uint8_t> osnma_msg_receiver::parse_dsm_kroot() const std::pair<std::vector<uint8_t>, uint8_t> osnma_msg_receiver::parse_dsm_kroot() const
{ {
std::ifstream file(KROOTFILE_DEFAULT, std::ios::binary | std::ios::in); std::ifstream file(KROOTFILE_DEFAULT, std::ios::binary | std::ios::in);
if (!file) { if (!file)
{
return {std::vector<uint8_t>(), 0}; return {std::vector<uint8_t>(), 0};
} }
@ -1965,7 +1995,8 @@ std::pair<std::vector<uint8_t>, uint8_t> osnma_msg_receiver::parse_dsm_kroot() c
file.close(); file.close();
if (file.bad()) { if (file.bad())
{
return {std::vector<uint8_t>(), 0}; return {std::vector<uint8_t>(), 0};
} }

View File

@ -124,6 +124,7 @@ Gnss_Crypto::~Gnss_Crypto()
#endif #endif
} }
bool Gnss_Crypto::have_public_key() const bool Gnss_Crypto::have_public_key() const
{ {
#if USE_GNUTLS_FALLBACK #if USE_GNUTLS_FALLBACK
@ -133,6 +134,7 @@ bool Gnss_Crypto::have_public_key() const
#endif #endif
} }
bool Gnss_Crypto::store_public_key(const std::string& pubKeyFilePath) const bool Gnss_Crypto::store_public_key(const std::string& pubKeyFilePath) const
{ {
if (!have_public_key()) if (!have_public_key())
@ -782,63 +784,6 @@ std::vector<uint8_t> Gnss_Crypto::compute_CMAC_AES(const std::vector<uint8_t>& k
return output; return output;
} }
// TODO - deprecate: change return type to respective key type, PEM is not needed.
std::vector<uint8_t> Gnss_Crypto::get_public_key() const
{
if (!have_public_key())
{
return {};
}
#if USE_GNUTLS_FALLBACK
gnutls_datum_t pem_data = {nullptr, 0};
#if HAVE_GNUTLS_PUBKEY_EXPORT2
int ret = gnutls_pubkey_export2(d_PublicKey, GNUTLS_X509_FMT_PEM, &pem_data);
#else
size_t output_stata_size;
int ret = gnutls_pubkey_export(d_PublicKey, GNUTLS_X509_FMT_PEM, &pem_data, &output_stata_size);
#endif
if (ret != GNUTLS_E_SUCCESS)
{
LOG(WARNING) << "GnuTLS: Failed to export public key to PEM format.";
return {};
}
std::vector<uint8_t> output(pem_data.data, pem_data.data + pem_data.size);
// Free the allocated memory by gnutls_pubkey_export2
gnutls_free(pem_data.data);
#else // OpenSSL
// Create a BIO for the memory buffer
BIO* mem = BIO_new(BIO_s_mem());
if (!mem)
{
LOG(WARNING) << "OpenSSL: Failed to create BIO.";
return {};
}
#if USE_OPENSSL_3
if (!PEM_write_bio_PUBKEY(mem, d_PublicKey))
#else // OpenSSL 1.x
if (!PEM_write_bio_EC_PUBKEY(mem, d_PublicKey))
#endif
{
BIO_free(mem);
LOG(WARNING) << "OpenSSL: Failed to write public key to PEM format.";
return {};
}
// Get the length of the data in the BIO
BUF_MEM* mem_ptr;
BIO_get_mem_ptr(mem, &mem_ptr);
// Copy the data from the BIO to a std::vector<uint8_t>
std::vector<uint8_t> output(mem_ptr->length);
memcpy(output.data(), mem_ptr->data, mem_ptr->length);
// Clean up the BIO
BIO_free(mem);
#endif
return output;
}
std::vector<uint8_t> Gnss_Crypto::get_merkle_root() const std::vector<uint8_t> Gnss_Crypto::get_merkle_root() const
{ {
@ -846,8 +791,15 @@ std::vector<uint8_t> Gnss_Crypto::get_merkle_root() const
} }
std::string Gnss_Crypto::get_public_key_type() const
{
return d_PublicKeyType;
}
void Gnss_Crypto::set_public_key(const std::vector<uint8_t>& publicKey) void Gnss_Crypto::set_public_key(const std::vector<uint8_t>& publicKey)
{ {
d_PublicKeyType = "Unknown";
#if USE_GNUTLS_FALLBACK #if USE_GNUTLS_FALLBACK
gnutls_pubkey_t pubkey{}; gnutls_pubkey_t pubkey{};
gnutls_ecc_curve_t curve; gnutls_ecc_curve_t curve;
@ -859,16 +811,19 @@ void Gnss_Crypto::set_public_key(const std::vector<uint8_t>& publicKey)
if (size_pk == 33) if (size_pk == 33)
{ {
curve = GNUTLS_ECC_CURVE_SECP256R1; curve = GNUTLS_ECC_CURVE_SECP256R1;
d_PublicKeyType = "ECDSA P-256";
decompress_public_key_secp256r1(publicKey, x, y); decompress_public_key_secp256r1(publicKey, x, y);
} }
else if (size_pk == 67) else if (size_pk == 67)
{ {
curve = GNUTLS_ECC_CURVE_SECP521R1; curve = GNUTLS_ECC_CURVE_SECP521R1;
d_PublicKeyType = "ECDSA P-521";
decompress_public_key_secp521r1(publicKey, x, y); decompress_public_key_secp521r1(publicKey, x, y);
} }
else else
{ {
LOG(WARNING) << "GnuTLS: Invalid public key size"; LOG(WARNING) << "GnuTLS: Invalid public key size";
gnutls_pubkey_deinit(pubkey);
return; return;
} }
@ -893,22 +848,41 @@ void Gnss_Crypto::set_public_key(const std::vector<uint8_t>& publicKey)
EVP_PKEY_CTX* ctx = nullptr; EVP_PKEY_CTX* ctx = nullptr;
OSSL_PARAM_BLD* param_bld; OSSL_PARAM_BLD* param_bld;
OSSL_PARAM* params = nullptr; OSSL_PARAM* params = nullptr;
const size_t public_key_size = publicKey.size();
param_bld = OSSL_PARAM_BLD_new(); param_bld = OSSL_PARAM_BLD_new();
if (param_bld != nullptr && if (param_bld != nullptr &&
OSSL_PARAM_BLD_push_utf8_string(param_bld, "group", (publicKey.size() == 33) ? "prime256v1" : "secp521r1", 0) && OSSL_PARAM_BLD_push_utf8_string(param_bld, "group", (public_key_size == 33) ? "prime256v1" : "secp521r1", 0) &&
OSSL_PARAM_BLD_push_octet_string(param_bld, "pub", publicKey.data(), publicKey.size())) { OSSL_PARAM_BLD_push_octet_string(param_bld, "pub", publicKey.data(), public_key_size))
params = OSSL_PARAM_BLD_to_param(param_bld); {
params = OSSL_PARAM_BLD_to_param(param_bld);
}
if (public_key_size == 33)
{
d_PublicKeyType = "ECDSA P-256";
}
else if (public_key_size == 67)
{
d_PublicKeyType = "ECDSA P-521";
} }
ctx = EVP_PKEY_CTX_new_from_name(nullptr, "EC", nullptr); ctx = EVP_PKEY_CTX_new_from_name(nullptr, "EC", nullptr);
if (ctx == nullptr || params == nullptr || EVP_PKEY_fromdata_init(ctx) <= 0 || EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_PUBLIC_KEY, params) <= 0) if (ctx == nullptr || params == nullptr || EVP_PKEY_fromdata_init(ctx) <= 0 || EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_PUBLIC_KEY, params) <= 0)
{ {
EVP_PKEY_free(pkey);
EVP_PKEY_CTX_free(ctx);
OSSL_PARAM_free(params);
OSSL_PARAM_BLD_free(param_bld);
return; return;
} }
if (!pubkey_copy(pkey, &d_PublicKey)) if (!pubkey_copy(pkey, &d_PublicKey))
{ {
EVP_PKEY_free(pkey);
EVP_PKEY_CTX_free(ctx);
OSSL_PARAM_free(params);
OSSL_PARAM_BLD_free(param_bld);
return; return;
} }
@ -923,10 +897,12 @@ void Gnss_Crypto::set_public_key(const std::vector<uint8_t>& publicKey)
if (publicKey.size() == 33) // ECDSA-P-256 if (publicKey.size() == 33) // ECDSA-P-256
{ {
group = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1); group = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1);
d_PublicKeyType = "ECDSA P-256";
} }
else // ECDSA-P-521 else // ECDSA-P-521
{ {
group = EC_GROUP_new_by_curve_name(NID_secp521r1); group = EC_GROUP_new_by_curve_name(NID_secp521r1);
d_PublicKeyType = "ECDSA P-256";
} }
if (!group) if (!group)
{ {
@ -974,6 +950,15 @@ void Gnss_Crypto::set_public_key(const std::vector<uint8_t>& publicKey)
} }
void Gnss_Crypto::set_public_key_type(const std::string& public_key_type)
{
if (public_key_type == "ECDSA P-256" || public_key_type == "ECDSA P-521")
{
d_PublicKeyType = public_key_type;
}
}
void Gnss_Crypto::set_merkle_root(const std::vector<uint8_t>& v) void Gnss_Crypto::set_merkle_root(const std::vector<uint8_t>& v)
{ {
d_x_4_0 = v; d_x_4_0 = v;
@ -1038,6 +1023,14 @@ void Gnss_Crypto::read_merkle_xml(const std::string& merkleFilePath)
LOG(INFO) << "OSNMA Merkletree - Length in Bits: " << lengthInBits; LOG(INFO) << "OSNMA Merkletree - Length in Bits: " << lengthInBits;
LOG(INFO) << "OSNMA Merkletree - Point: " << point; LOG(INFO) << "OSNMA Merkletree - Point: " << point;
LOG(INFO) << "OSNMA Merkletree - PK Type: " << pkType; LOG(INFO) << "OSNMA Merkletree - PK Type: " << pkType;
if (pkType == "ECDSA P-256/SHA-256")
{
d_PublicKeyType = "ECDSA P-256";
}
else if (pkType == "ECDSA P-521/SHA-512")
{
d_PublicKeyType = "ECDSA P-521";
}
} }
for (pugi::xml_node treeNode : merkleTree.children("TreeNode")) for (pugi::xml_node treeNode : merkleTree.children("TreeNode"))
{ {
@ -1122,6 +1115,7 @@ void Gnss_Crypto::readPublicKeyFromPEM(const std::string& pemFilePath)
bool Gnss_Crypto::readPublicKeyFromCRT(const std::string& crtFilePath) bool Gnss_Crypto::readPublicKeyFromCRT(const std::string& crtFilePath)
{ {
d_PublicKeyType = "Unknown";
#if USE_GNUTLS_FALLBACK #if USE_GNUTLS_FALLBACK
// Open the .crt file // Open the .crt file
std::ifstream crtFile(crtFilePath, std::ios::binary); std::ifstream crtFile(crtFilePath, std::ios::binary);
@ -1160,6 +1154,72 @@ bool Gnss_Crypto::readPublicKeyFromCRT(const std::string& crtFilePath)
gnutls_x509_crt_deinit(cert); gnutls_x509_crt_deinit(cert);
return false; return false;
} }
// store the key type - needed for the Kroot in case no DSM-PKR available
gnutls_pk_algorithm_t pk_algorithm;
unsigned int bits;
ret = gnutls_pubkey_get_pk_algorithm(pubkey, &bits);
if (ret < 0)
{
LOG(WARNING) << "GnuTLS: Failed to get public key algorithm: " << gnutls_strerror(ret);
gnutls_pubkey_deinit(pubkey);
gnutls_x509_crt_deinit(cert);
return false;
}
pk_algorithm = static_cast<gnutls_pk_algorithm_t>(ret);
if (pk_algorithm == GNUTLS_PK_ECDSA)
{
gnutls_datum_t params;
ret = gnutls_pubkey_export_ecc_raw(pubkey, nullptr, &params, nullptr);
if (ret < 0)
{
LOG(WARNING) << "GnuTLS: Failed to export EC parameters: " << gnutls_strerror(ret);
gnutls_pubkey_deinit(pubkey);
gnutls_x509_crt_deinit(cert);
return false;
}
gnutls_ecc_curve_t curve;
ret = gnutls_ecc_curve_get_id(reinterpret_cast<const char*>(params.data));
gnutls_free(params.data);
if (ret < 0)
{
LOG(WARNING) << "GnuTLS: Failed to get EC curve: " << gnutls_strerror(ret);
gnutls_pubkey_deinit(pubkey);
gnutls_x509_crt_deinit(cert);
return false;
}
curve = static_cast<gnutls_ecc_curve_t>(ret);
if (curve == GNUTLS_ECC_CURVE_SECP256R1)
{
d_PublicKeyType = "ECDSA P-256";
}
else if (curve == GNUTLS_ECC_CURVE_SECP521R1)
{
d_PublicKeyType = "ECDSA P-521";
}
else
{
LOG(WARNING) << "GnuTLS: Trying to read unknown EC curve";
gnutls_x509_crt_deinit(cert);
gnutls_pubkey_deinit(pubkey);
return false;
}
}
else
{
LOG(WARNING) << "GnuTLS: Trying to read unknown key type";
gnutls_x509_crt_deinit(cert);
gnutls_pubkey_deinit(pubkey);
return false;
}
pubkey_copy(pubkey, &d_PublicKey); pubkey_copy(pubkey, &d_PublicKey);
gnutls_x509_crt_deinit(cert); gnutls_x509_crt_deinit(cert);
gnutls_pubkey_deinit(pubkey); gnutls_pubkey_deinit(pubkey);
@ -1190,27 +1250,69 @@ bool Gnss_Crypto::readPublicKeyFromCRT(const std::string& crtFilePath)
// Read the public key from the certificate // Read the public key from the certificate
EVP_PKEY* pubkey = X509_get_pubkey(cert); EVP_PKEY* pubkey = X509_get_pubkey(cert);
// store the key type - needed for the Kroot in case no DSM-PKR available
// TODO - only way I have found to find the curve type
const auto *const ec_key = EVP_PKEY_get0_EC_KEY(pubkey);
const EC_GROUP *group = EC_KEY_get0_group(ec_key);
int nid = EC_GROUP_get_curve_name(group);
if (nid == NID_X9_62_prime256v1) {
d_PublicKeyType = "ECDSA P-256";
} else if (nid == NID_secp521r1) {
d_PublicKeyType = "ECDSA P-521";
}
#if USE_OPENSSL_3
if (!pubkey) if (!pubkey)
{ {
LOG(WARNING) << "OpenSSL: Failed to extract the public key"; LOG(WARNING) << "OpenSSL: Failed to extract the public key";
X509_free(cert); X509_free(cert);
return false; return false;
} }
#if USE_OPENSSL_3
// store the key type - needed for the Kroot in case no DSM-PKR available
// Get the key type
int key_type = EVP_PKEY_base_id(pubkey);
if (key_type == EVP_PKEY_EC)
{
// It's an EC key, now we need to determine the curve
char curve_name[256];
size_t curve_name_len = sizeof(curve_name);
if (EVP_PKEY_get_utf8_string_param(pubkey, OSSL_PKEY_PARAM_GROUP_NAME, curve_name, curve_name_len, &curve_name_len) == 1)
{
if (strcmp(curve_name, "prime256v1") == 0 || strcmp(curve_name, "P-256") == 0)
{
d_PublicKeyType = "ECDSA P-256";
}
else if (strcmp(curve_name, "secp521r1") == 0 || strcmp(curve_name, "P-521") == 0)
{
d_PublicKeyType = "ECDSA P-521";
}
else
{
LOG(WARNING) << "OpenSSL: Trying to read an unknown EC curve";
X509_free(cert);
return false;
}
}
else
{
d_PublicKeyType = "Unknown EC curve";
LOG(WARNING) << "OpenSSL: Trying to read an unknown EC curve";
X509_free(cert);
return false;
}
}
else
{
LOG(WARNING) << "OpenSSL: Trying to read an unknown key type";
X509_free(cert);
return false;
}
pubkey_copy(pubkey, &d_PublicKey); pubkey_copy(pubkey, &d_PublicKey);
EVP_PKEY_free(pubkey); EVP_PKEY_free(pubkey);
#else // OpenSSL 1.x #else // OpenSSL 1.x
// store the key type - needed for the Kroot in case no DSM-PKR available
const auto ec_key = EVP_PKEY_get0_EC_KEY(pubkey);
const EC_GROUP* group = EC_KEY_get0_group(ec_key);
const int nid = EC_GROUP_get_curve_name(group);
if (nid == NID_X9_62_prime256v1)
{
d_PublicKeyType = "ECDSA P-256";
}
else if (nid == NID_secp521r1)
{
d_PublicKeyType = "ECDSA P-521";
}
EC_KEY* ec_pubkey = EVP_PKEY_get1_EC_KEY(pubkey); EC_KEY* ec_pubkey = EVP_PKEY_get1_EC_KEY(pubkey);
EVP_PKEY_free(pubkey); EVP_PKEY_free(pubkey);
if (!ec_pubkey) if (!ec_pubkey)
@ -1299,6 +1401,7 @@ std::vector<uint8_t> Gnss_Crypto::convert_from_hex_str(const std::string& input)
return result; return result;
} }
#if USE_GNUTLS_FALLBACK // GnuTLS-specific functions #if USE_GNUTLS_FALLBACK // GnuTLS-specific functions
bool Gnss_Crypto::pubkey_copy(gnutls_pubkey_t src, gnutls_pubkey_t* dest) bool Gnss_Crypto::pubkey_copy(gnutls_pubkey_t src, gnutls_pubkey_t* dest)
{ {

View File

@ -66,13 +66,13 @@ public:
std::vector<uint8_t> compute_HMAC_SHA_256(const std::vector<uint8_t>& key, const std::vector<uint8_t>& input) const; //!< Computes HMAC-SHA-256 message authentication code std::vector<uint8_t> compute_HMAC_SHA_256(const std::vector<uint8_t>& key, const std::vector<uint8_t>& input) const; //!< Computes HMAC-SHA-256 message authentication code
std::vector<uint8_t> compute_CMAC_AES(const std::vector<uint8_t>& key, const std::vector<uint8_t>& input) const; //!< Computes CMAC-AES message authentication code std::vector<uint8_t> compute_CMAC_AES(const std::vector<uint8_t>& key, const std::vector<uint8_t>& input) const; //!< Computes CMAC-AES message authentication code
std::vector<uint8_t> get_public_key() const; //!< Gets the ECDSA Public Key in PEM format
std::vector<uint8_t> get_merkle_root() const; //!< Gets the Merkle Tree root node (\f$ x_{4,0} \f$) std::vector<uint8_t> get_merkle_root() const; //!< Gets the Merkle Tree root node (\f$ x_{4,0} \f$)
std::string get_public_key_type() const; //!< Gets the ECDSA Public Key type (ECDSA P-256 / ECDSA P-521 / Unknown)
void set_public_key(const std::vector<uint8_t>& publickey); //!< Sets the ECDSA Public Key (publickey compressed format) void set_public_key(const std::vector<uint8_t>& publickey); //!< Sets the ECDSA Public Key (publickey compressed format)
void set_merkle_root(const std::vector<uint8_t>& v); //!< Sets the Merkle Tree root node x(\f$ x_{4,0} \f$) void set_public_key_type(const std::string& public_key_type); //!< Sets the ECDSA Public Key type (ECDSA P-256 / ECDSA P-521)
void read_merkle_xml(const std::string& merkleFilePath); void set_merkle_root(const std::vector<uint8_t>& v); //!< Sets the Merkle Tree root node x(\f$ x_{4,0} \f$)
std::string d_PublicKeyType; void read_merkle_xml(const std::string& merkleFilePath); //!> Reads the XML file provided from the GSC OSNMA server
private: private:
void readPublicKeyFromPEM(const std::string& pemFilePath); void readPublicKeyFromPEM(const std::string& pemFilePath);
@ -94,6 +94,7 @@ private:
#endif #endif
#endif #endif
std::vector<uint8_t> d_x_4_0; std::vector<uint8_t> d_x_4_0;
std::string d_PublicKeyType;
}; };
/** \} */ /** \} */

View File

@ -38,6 +38,8 @@ void OSNMA_nav_data_Manager::add_navigation_data(const std::string& nav_bits, ui
_satellite_nav_data[PRNd][TOW].set_tow_sf0(TOW); _satellite_nav_data[PRNd][TOW].set_tow_sf0(TOW);
} }
} }
/** /**
* @brief loops over the verified tags and updates the navigation data tag length * @brief loops over the verified tags and updates the navigation data tag length
*/ */
@ -55,7 +57,8 @@ void OSNMA_nav_data_Manager::update_nav_data(const std::multimap<uint32_t, Tag>&
for (auto & tow_it : tow_map) // note: starts with smallest (i.e. oldest) navigation dataset for (auto & tow_it : tow_map) // note: starts with smallest (i.e. oldest) navigation dataset
{ {
std::string nav_data; std::string nav_data;
if (tag.second.ADKD == 0 || tag.second.ADKD == 12){ if (tag.second.ADKD == 0 || tag.second.ADKD == 12)
{
nav_data = tow_it.second.get_ephemeris_data(); nav_data = tow_it.second.get_ephemeris_data();
} }
else if (tag.second.ADKD == 4){ else if (tag.second.ADKD == 4){
@ -70,11 +73,15 @@ void OSNMA_nav_data_Manager::update_nav_data(const std::multimap<uint32_t, Tag>&
} }
} }
} }
bool OSNMA_nav_data_Manager::have_PRNd_nav_data(uint32_t PRNd) bool OSNMA_nav_data_Manager::have_PRNd_nav_data(uint32_t PRNd)
{ {
// check if have data from PRNd in _satellite_nav_data // check if have data from PRNd in _satellite_nav_data
return _satellite_nav_data.find(PRNd) != _satellite_nav_data.end(); return _satellite_nav_data.find(PRNd) != _satellite_nav_data.end();
} }
std::vector<OSNMA_NavData> OSNMA_nav_data_Manager::get_verified_data() std::vector<OSNMA_NavData> OSNMA_nav_data_Manager::get_verified_data()
{ {
std::vector<OSNMA_NavData> result; std::vector<OSNMA_NavData> result;
@ -91,6 +98,8 @@ std::vector<OSNMA_NavData> OSNMA_nav_data_Manager::get_verified_data()
} }
return result; return result;
} }
bool OSNMA_nav_data_Manager::have_nav_data(uint32_t PRNd, uint32_t TOW, uint8_t ADKD) bool OSNMA_nav_data_Manager::have_nav_data(uint32_t PRNd, uint32_t TOW, uint8_t ADKD)
{ {
if (ADKD == 0 || ADKD == 12) if (ADKD == 0 || ADKD == 12)
@ -119,6 +128,8 @@ bool OSNMA_nav_data_Manager::have_nav_data(uint32_t PRNd, uint32_t TOW, uint8_t
} }
return false; return false;
} }
/** /**
* @brief returns OSNMA_NavData object. * @brief returns OSNMA_NavData object.
* @remarks assumes it exists (called have_nav_data before), otherwise undefined behavior * @remarks assumes it exists (called have_nav_data before), otherwise undefined behavior
@ -140,13 +151,16 @@ std::string OSNMA_nav_data_Manager::get_navigation_data(const Tag& tag)
{ {
if (tag.ADKD == 0 || tag.ADKD == 12) if (tag.ADKD == 0 || tag.ADKD == 12)
{ {
if (!tow_it.second.get_ephemeris_data().empty()){ if (!tow_it.second.get_ephemeris_data().empty())
{
return tow_it.second.get_ephemeris_data(); return tow_it.second.get_ephemeris_data();
} }
} }
else if(tag.ADKD == 4) else if(tag.ADKD == 4)
{ {
if (!tow_it.second.get_utc_data().empty()){
if (!tow_it.second.get_utc_data().empty())
{
return tow_it.second.get_utc_data(); return tow_it.second.get_utc_data();
} }
} }
@ -154,6 +168,8 @@ std::string OSNMA_nav_data_Manager::get_navigation_data(const Tag& tag)
} }
return ""; return "";
} }
/** /**
* @brief Checks if the OSNMA_NavData bits are already present. In case affirmative, it updates the OSNMA_NavData 'last received' timestamp * @brief Checks if the OSNMA_NavData bits are already present. In case affirmative, it updates the OSNMA_NavData 'last received' timestamp
* @remarks e.g.: a SV may repeat the bits over several subframes. In that case, need to save them only once. * @remarks e.g.: a SV may repeat the bits over several subframes. In that case, need to save them only once.
@ -182,6 +198,8 @@ bool OSNMA_nav_data_Manager::have_nav_data(const std::string& nav_bits, uint32_t
} }
return false; return false;
} }
/** /**
* @brief Checks if there is a OSNMA_NavData element within the COP time interval for a Tag t * @brief Checks if there is a OSNMA_NavData element within the COP time interval for a Tag t
* @param t Tag object * @param t Tag object
@ -202,13 +220,15 @@ bool OSNMA_nav_data_Manager::have_nav_data(const Tag& t) const
{ {
if (t.ADKD == 0 || t.ADKD == 12) if (t.ADKD == 0 || t.ADKD == 12)
{ {
if (!tow_it.second.get_ephemeris_data().empty()){ if (!tow_it.second.get_ephemeris_data().empty())
{
return true; return true;
} }
} }
else if (t.ADKD == 4) else if (t.ADKD == 4)
{ {
if (!tow_it.second.get_utc_data().empty()){ if (!tow_it.second.get_utc_data().empty())
{
return true; return true;
} }
} }
@ -216,6 +236,8 @@ bool OSNMA_nav_data_Manager::have_nav_data(const Tag& t) const
} }
return false; return false;
} }
void OSNMA_nav_data_Manager::print_status() void OSNMA_nav_data_Manager::print_status()
{ {
for (const auto& satellite : _satellite_nav_data){ for (const auto& satellite : _satellite_nav_data){

View File

@ -34,8 +34,10 @@ TEST(GnssCryptoTest, VerifyPubKeyImport)
// Input taken from RG 1.3 A7.1 // Input taken from RG 1.3 A7.1
// compressed ECDSA P-256 format // compressed ECDSA P-256 format
std::vector<uint8_t> publicKey = { std::vector<uint8_t> publicKey = {
0x03, 0x03, 0xB2, 0xCE, 0x64, 0xBC, 0x20, 0x7B, 0xDD, 0x8B, 0xC4, 0xDF, 0x85, 0x91, 0x87, 0xFC, 0xB6, 0x86, 0x03, 0x03, 0xB2, 0xCE, 0x64, 0xBC, 0x20, 0x7B, 0xDD, 0x8B,
0x32, 0x0D, 0x63, 0xFF, 0xA0, 0x91, 0x41, 0x0F, 0xC1, 0x58, 0xFB, 0xB7, 0x79, 0x80, 0xEA}; 0xC4, 0xDF, 0x85, 0x91, 0x87, 0xFC, 0xB6, 0x86, 0x32, 0x0D,
0x63, 0xFF, 0xA0, 0x91, 0x41, 0x0F, 0xC1, 0x58, 0xFB, 0xB7,
0x79, 0x80, 0xEA};
ASSERT_FALSE(d_crypto->have_public_key()); ASSERT_FALSE(d_crypto->have_public_key());
@ -55,8 +57,10 @@ TEST(GnssCryptoTest, VerifyPublicKeyStorage)
// Input taken from RG 1.3 A7.1 // Input taken from RG 1.3 A7.1
// compressed ECDSA P-256 format // compressed ECDSA P-256 format
std::vector<uint8_t> publicKey = { std::vector<uint8_t> publicKey = {
0x03, 0x03, 0xB2, 0xCE, 0x64, 0xBC, 0x20, 0x7B, 0xDD, 0x8B, 0xC4, 0xDF, 0x85, 0x91, 0x87, 0xFC, 0xB6, 0x86, 0x03, 0x03, 0xB2, 0xCE, 0x64, 0xBC, 0x20, 0x7B, 0xDD, 0x8B,
0x32, 0x0D, 0x63, 0xFF, 0xA0, 0x91, 0x41, 0x0F, 0xC1, 0x58, 0xFB, 0xB7, 0x79, 0x80, 0xEA}; 0xC4, 0xDF, 0x85, 0x91, 0x87, 0xFC, 0xB6, 0x86, 0x32, 0x0D,
0x63, 0xFF, 0xA0, 0x91, 0x41, 0x0F, 0xC1, 0x58, 0xFB, 0xB7,
0x79, 0x80, 0xEA};
d_crypto->set_public_key(publicKey); d_crypto->set_public_key(publicKey);
bool result = d_crypto->store_public_key(f1); bool result = d_crypto->store_public_key(f1);
@ -75,10 +79,6 @@ TEST(GnssCryptoTest, VerifyPublicKeyStorage)
ASSERT_EQ(content_file, content_file2); ASSERT_EQ(content_file, content_file2);
// TODO - this cannot be tested right now
// std::vector<uint8_t> readkey = d_crypto2->get_public_key();
// ASSERT_EQ(publicKey, readkey);
errorlib::error_code ec; errorlib::error_code ec;
ASSERT_TRUE(fs::remove(fs::path(f1), ec)); ASSERT_TRUE(fs::remove(fs::path(f1), ec));
ASSERT_TRUE(fs::remove(fs::path(f2), ec)); ASSERT_TRUE(fs::remove(fs::path(f2), ec));
@ -93,8 +93,9 @@ TEST(GnssCryptoTest, TestComputeSHA_256)
std::vector<uint8_t> expected_output = { std::vector<uint8_t> expected_output = {
0x18, 0x94, 0xA1, 0x9C, 0x85, 0xBA, 0x15, 0x3A, 0xCB, 0xF7, 0x18, 0x94, 0xA1, 0x9C, 0x85, 0xBA, 0x15, 0x3A, 0xCB, 0xF7,
0x43, 0xAC, 0x4E, 0x43, 0xFC, 0x00, 0x4C, 0x89, 0x16, 0x04, 0xB2, 0x43, 0xAC, 0x4E, 0x43, 0xFC, 0x00, 0x4C, 0x89, 0x16, 0x04,
0x6F, 0x8C, 0x69, 0xE1, 0xE8, 0x3E, 0xA2, 0xAF, 0xC7, 0xC4, 0x8F}; 0xB2, 0x6F, 0x8C, 0x69, 0xE1, 0xE8, 0x3E, 0xA2, 0xAF, 0xC7,
0xC4, 0x8F};
std::vector<uint8_t> output = d_crypto->compute_SHA_256(message); std::vector<uint8_t> output = d_crypto->compute_SHA_256(message);
@ -111,7 +112,8 @@ TEST(GnssCryptoTest, TestComputeSHA3_256)
std::vector<uint8_t> expected_output = { std::vector<uint8_t> expected_output = {
0xCC, 0xB8, 0xF9, 0x23, 0x5F, 0x4A, 0x93, 0x2C, 0xA0, 0xAB, 0xCC, 0xB8, 0xF9, 0x23, 0x5F, 0x4A, 0x93, 0x2C, 0xA0, 0xAB,
0xBB, 0x2C, 0x24, 0x36, 0x72, 0x5E, 0x2E, 0x8D, 0xC7, 0x5B, 0xBB, 0x2C, 0x24, 0x36, 0x72, 0x5E, 0x2E, 0x8D, 0xC7, 0x5B,
0x99, 0xE7, 0xF6, 0xC4, 0x50, 0x5B, 0x2A, 0x93, 0x6E, 0xB6, 0x3B, 0x3F}; 0x99, 0xE7, 0xF6, 0xC4, 0x50, 0x5B, 0x2A, 0x93, 0x6E, 0xB6,
0x3B, 0x3F};
std::vector<uint8_t> output = d_crypto->compute_SHA3_256(message); std::vector<uint8_t> output = d_crypto->compute_SHA3_256(message);
@ -254,8 +256,10 @@ TEST(GnssCryptoTest, VerifySignatureP256)
// Input taken from RG 1.3 A7.1 // Input taken from RG 1.3 A7.1
// compressed ECDSA P-256 format // compressed ECDSA P-256 format
std::vector<uint8_t> publicKey = { std::vector<uint8_t> publicKey = {
0x03, 0x03, 0xB2, 0xCE, 0x64, 0xBC, 0x20, 0x7B, 0xDD, 0x8B, 0xC4, 0xDF, 0x85, 0x91, 0x87, 0xFC, 0xB6, 0x86, 0x03, 0x03, 0xB2, 0xCE, 0x64, 0xBC, 0x20, 0x7B, 0xDD, 0x8B,
0x32, 0x0D, 0x63, 0xFF, 0xA0, 0x91, 0x41, 0x0F, 0xC1, 0x58, 0xFB, 0xB7, 0x79, 0x80, 0xEA}; 0xC4, 0xDF, 0x85, 0x91, 0x87, 0xFC, 0xB6, 0x86, 0x32, 0x0D,
0x63, 0xFF, 0xA0, 0x91, 0x41, 0x0F, 0xC1, 0x58, 0xFB, 0xB7,
0x79, 0x80, 0xEA};
d_crypto->set_public_key(publicKey); d_crypto->set_public_key(publicKey);
bool result = d_crypto->verify_signature_ecdsa_p256(message, signature); bool result = d_crypto->verify_signature_ecdsa_p256(message, signature);