1
0
mirror of https://github.com/gnss-sdr/gnss-sdr synced 2024-12-13 11:40:33 +00:00

[TAS-247][FEAT][Kroot] enable hotstart with last known Kroot

* Kroot is now saved into binary file if successfuly verified.
* on startup, file is checked first.
* This should enable a much quicker TTFAF
This commit is contained in:
cesaaargm 2024-07-26 18:03:21 +02:00
parent ffb456d058
commit 06e0c4b63a
7 changed files with 102 additions and 18 deletions

View File

@ -60,22 +60,26 @@ namespace wht = std;
#endif
osnma_msg_receiver_sptr osnma_msg_receiver_make(const std::string& pemFilePath, const std::string& merkleFilePath)
osnma_msg_receiver_sptr osnma_msg_receiver_make(const std::string& pemFilePath, const std::string& merkleFilePath, const std::string& rootKeyFilePath)
{
return osnma_msg_receiver_sptr(new osnma_msg_receiver(pemFilePath, merkleFilePath));
return osnma_msg_receiver_sptr(new osnma_msg_receiver(pemFilePath, merkleFilePath, rootKeyFilePath));
}
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, const std::string& rootKeyFilePath) : gr::block("osnma_msg_receiver",
gr::io_signature::make(0, 0, 0),
gr::io_signature::make(0, 0, 0))
{
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, rootKeyFilePath);
d_helper = std::make_unique<Osnma_Helper>();
d_nav_data_manager = std::make_unique<OSNMA_nav_data_Manager>();
if(d_crypto->have_root_key()){
d_kroot = d_crypto->get_root_key();
d_kroot_verified = true;
}
// register OSNMA input message port from telemetry blocks
this->message_port_register_in(pmt::mp("OSNMA_from_TLM"));
// register OSNMA output message port to PVT block
@ -126,7 +130,7 @@ void osnma_msg_receiver::msg_handler_osnma(const pmt::pmt_t& msg)
uint32_t PRNa = std::get<0>(*inav_data);
std::string nav_data = std::get<1>(*inav_data);
uint32_t TOW = std::get<2>(*inav_data);
d_nav_data_manager->add_navigation_data(nav_data, PRNa,TOW);
d_nav_data_manager->add_navigation_data(nav_data, PRNa, TOW);
}
else
{
@ -490,6 +494,10 @@ void osnma_msg_receiver::process_dsm_message(const std::vector<uint8_t>& dsm_msg
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<uint32_t>(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);
// Save Kroot into a permanent storage
d_crypto->store_root_key(ROOTKEYFILE_DEFAULT);
d_kroot = d_osnma_data.d_dsm_kroot_message.kroot;
d_crypto->set_root_key(d_kroot);
}
else
{

View File

@ -50,7 +50,7 @@ class osnma_msg_receiver;
using osnma_msg_receiver_sptr = gnss_shared_ptr<osnma_msg_receiver>;
osnma_msg_receiver_sptr osnma_msg_receiver_make(const std::string& pemFilePath, const std::string& merkleFilePath);
osnma_msg_receiver_sptr osnma_msg_receiver_make(const std::string& pemFilePath, const std::string& merkleFilePath, const std::string& rootKeyFilePath);
/*!
* \brief GNU Radio block that receives asynchronous OSNMA messages
@ -63,8 +63,8 @@ class osnma_msg_receiver : public gr::block
public:
~osnma_msg_receiver() = default; //!< Default destructor
private:
friend osnma_msg_receiver_sptr osnma_msg_receiver_make(const std::string& pemFilePath, const std::string& merkleFilePath);
osnma_msg_receiver(const std::string& crtFilePath, const std::string& merkleFilePath);
friend osnma_msg_receiver_sptr osnma_msg_receiver_make(const std::string& pemFilePath, const std::string& merkleFilePath, const std::string& rootKeyFilePath);
osnma_msg_receiver(const std::string& crtFilePath, const std::string& merkleFilePath, const std::string& rootKeyFilePath);
void msg_handler_osnma(const pmt::pmt_t& msg);
void process_osnma_message(const std::shared_ptr<OSNMA_msg>& osnma_msg);
@ -100,6 +100,7 @@ private:
std::map<uint32_t, std::vector<uint8_t>> d_tesla_keys; // tesla keys over time, sorted by TOW
std::multimap<uint32_t, Tag> d_tags_awaiting_verify; // container with tags to verify from arbitrary SVIDs, sorted by TOW
std::vector<uint8_t> d_kroot; // last available stored root key
std::vector<uint8_t> d_tags_to_verify{0, 4, 12};
std::vector<MACK_message> d_macks_awaiting_MACSEQ_verification;
@ -110,7 +111,7 @@ private:
std::unique_ptr<OSNMA_DSM_Reader> d_dsm_reader; // osnma parameters parser
std::unique_ptr<Gnss_Crypto> d_crypto; // access to cryptographic functions
std::unique_ptr<Osnma_Helper> d_helper;
std::unique_ptr<Osnma_Helper> d_helper; // helper class with auxiliary functions
std::unique_ptr<OSNMA_nav_data_Manager> d_nav_data_manager; // refactor for holding and processing navigation data
OSNMA_data d_osnma_data{};

View File

@ -126,7 +126,8 @@ void GNSSFlowgraph::init()
enable_osnma_rx_ = true;
const auto certFilePath = configuration_->property("GNSS-SDR.osnma_public_key", CRTFILE_DEFAULT);
const auto merKleTreePath = configuration_->property("GNSS-SDR.osnma_merkletree", MERKLEFILE_DEFAULT);
osnma_rx_ = osnma_msg_receiver_make(certFilePath, merKleTreePath);
const auto rootKeyPath = configuration_->property("GNSS-SDR.osnma_root_key", ROOTKEYFILE_DEFAULT);
osnma_rx_ = osnma_msg_receiver_make(certFilePath, merKleTreePath, rootKeyPath);
}
else
{

View File

@ -163,6 +163,7 @@ const std::unordered_map<std::string, uint16_t> OSNMA_TABLE_15 = {
const std::string PEMFILE_STORED("./OSNMA_PublicKey.pem");
const std::string CRTFILE_DEFAULT("../data/OSNMA_PublicKey_20240115100000_newPKID_1.crt");
const std::string MERKLEFILE_DEFAULT("../data/OSNMA_MerkleTree_20240115100000_newPKID_1.xml");
const std::string ROOTKEYFILE_DEFAULT("../data/OSNMA_RootKey.bin");
class Mack_lookup
{

View File

@ -75,7 +75,7 @@ Gnss_Crypto::Gnss_Crypto()
}
Gnss_Crypto::Gnss_Crypto(const std::string& certFilePath, const std::string& merkleTreePath)
Gnss_Crypto::Gnss_Crypto(const std::string& certFilePath, const std::string& merkleTreePath, const std::string& rootKeyFilePath)
{
#if USE_GNUTLS_FALLBACK
gnutls_global_init();
@ -100,6 +100,7 @@ Gnss_Crypto::Gnss_Crypto(const std::string& certFilePath, const std::string& mer
}
}
read_merkle_xml(merkleTreePath);
read_root_key(rootKeyFilePath);
}
@ -122,7 +123,10 @@ Gnss_Crypto::~Gnss_Crypto()
#endif
}
bool Gnss_Crypto::have_root_key() const
{
return !d_kroot.empty();
}
bool Gnss_Crypto::have_public_key() const
{
#if USE_GNUTLS_FALLBACK
@ -196,6 +200,22 @@ bool Gnss_Crypto::store_public_key(const std::string& pubKeyFilePath) const
return true;
}
bool Gnss_Crypto::store_root_key(const std::string& rootKeyFilePath) const
{
if (!have_root_key())
{
return false;
}
std::ofstream file(rootKeyFilePath, std::ios::binary | std::ios::out);
if (!file) {
return false;
}
file.write(reinterpret_cast<const char*>(d_kroot.data()), d_kroot.size());
return file.good();
}
bool Gnss_Crypto::verify_signature_ecdsa_p256(const std::vector<uint8_t>& message, const std::vector<uint8_t>& signature) const
{
@ -845,6 +865,10 @@ std::vector<uint8_t> Gnss_Crypto::get_merkle_root() const
return d_x_4_0;
}
std::vector<uint8_t> Gnss_Crypto::get_root_key() const
{
return d_kroot;
}
void Gnss_Crypto::set_public_key(const std::vector<uint8_t>& publicKey)
{
@ -899,12 +923,15 @@ void Gnss_Crypto::set_public_key(const std::vector<uint8_t>& publicKey)
DLOG(INFO) << "OSNMA Public Key successfully set up.";
}
void Gnss_Crypto::set_merkle_root(const std::vector<uint8_t>& v)
{
d_x_4_0 = v;
}
void Gnss_Crypto::set_root_key(const std::vector<uint8_t>& root_key)
{
d_kroot = root_key;
}
void Gnss_Crypto::read_merkle_xml(const std::string& merkleFilePath)
{
@ -1145,6 +1172,40 @@ bool Gnss_Crypto::readPublicKeyFromCRT(const std::string& crtFilePath)
return true;
}
/**
* \brief Reads the TESLA root key from a file and stores it.
* \param rootKeyFilePath The file path of the TESLA root key.
* \return True if the root key was successfully read and stored, false otherwise.
*/
bool Gnss_Crypto::read_root_key(const std::string& rootKeyFilePath)
{
std::ifstream file(rootKeyFilePath, std::ios::binary | std::ios::in);
if (!file) {
LOG(WARNING) << "Unable to open file: " << rootKeyFilePath;
return false;
}
// Determine file size
file.seekg(0, std::ios::end);
std::streamsize size = file.tellg();
file.seekg(0, std::ios::beg);
if (size == 0) {
LOG(WARNING) << "File is empty: " << rootKeyFilePath;
return false;
}
// Resize the vector and read file
d_kroot.resize(size);
if (!file.read(reinterpret_cast<char*>(d_kroot.data()), size)) {
LOG(WARNING) << "Failed to read the file: " << rootKeyFilePath;
return false;
}
std::cout << "OSNMA TESLA Root Key successfully read from file " << rootKeyFilePath << std::endl;
LOG(INFO) << "OSNMA TESLA Root Key successfully read from file " << rootKeyFilePath;
return true;
}
bool Gnss_Crypto::convert_raw_to_der_ecdsa(const std::vector<uint8_t>& raw_signature, std::vector<uint8_t>& der_signature) const
{

View File

@ -48,15 +48,22 @@ public:
* and a XML file for the Merkle Tree root.
* Files can be downloaded by registering at https://www.gsc-europa.eu/
*/
Gnss_Crypto(const std::string& certFilePath, const std::string& merkleTreePath);
Gnss_Crypto(const std::string& certFilePath, const std::string& merkleTreePath, const std::string& rootKeyFilePath);
~Gnss_Crypto(); //!< Default destructor
bool have_root_key() const; //!< Returns true if the TESLA root key is already loaded
bool have_public_key() const; //!< Returns true if the ECDSA Public Key is already loaded
/*!
* Stores the ECDSA Public Key in a .pem file, which is read in a following run if the .crt file is not found
*/
bool store_public_key(const std::string& pubKeyFilePath) const;
/*!
* Stores the TESLA root key in a plaintext file, which is read in a following run for a faster TTFAF.
* @param kroot TESLA root key
* @return true if successful
*/
bool store_root_key(const std::string& rootKeyFilePath) const;
bool verify_signature_ecdsa_p256(const std::vector<uint8_t>& message, const std::vector<uint8_t>& signature) const; //!< Verify ECDSA-P256 signature (message in plain hex, signature in raw format)
bool verify_signature_ecdsa_p521(const std::vector<uint8_t>& message, const std::vector<uint8_t>& signature) const; //!< Verify ECDSA-P521 signature (message in plain hex, signature in raw format)
@ -68,13 +75,15 @@ public:
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_root_key() const; //!< Gets the TESLA root key in binary format
void set_public_key(const std::vector<uint8_t>& publickey); //!< Sets the ECDSA Public Key (publickey in PEM 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_root_key(const std::vector<uint8_t>& root_key); //!< Sets the TESLA root key
private:
void read_merkle_xml(const std::string& merkleFilePath);
void readPublicKeyFromPEM(const std::string& pemFilePath);
bool read_root_key(const std::string& rootKeyFilePath);
bool readPublicKeyFromCRT(const std::string& crtFilePath);
bool convert_raw_to_der_ecdsa(const std::vector<uint8_t>& raw_signature, std::vector<uint8_t>& der_signature) const;
std::vector<uint8_t> convert_from_hex_str(const std::string& input) const;
@ -91,6 +100,7 @@ private:
#endif
#endif
std::vector<uint8_t> d_x_4_0;
std::vector<uint8_t> d_kroot;
};
/** \} */

View File

@ -24,6 +24,7 @@
#include <chrono>
#include <fstream>
#include <vector>
#include "Galileo_OSNMA.h"
#if USE_GLOG_AND_GFLAGS
#include <glog/logging.h> // for LOG
@ -76,7 +77,8 @@ protected:
// std::string merkleFilePath = "/home/cgm/CLionProjects/osnma/data/OSNMA_MerkleTree_20230803105953_newPKID_1.xml";
std::string crtFilePath = "/home/cgm/CLionProjects/osnma/data/OSNMA_PublicKey_20230720113300_newPKID_2.crt"; // conf. 2
std::string merkleFilePath = "/home/cgm/CLionProjects/osnma/data/OSNMA_MerkleTree_20230720113300_newPKID_2.xml";
osnma = osnma_msg_receiver_make(crtFilePath, merkleFilePath);
std::string rootKeyFilePath = ROOTKEYFILE_DEFAULT;
osnma = osnma_msg_receiver_make(crtFilePath, merkleFilePath, ROOTKEYFILE_DEFAULT);
}
};