1
0
mirror of https://github.com/gnss-sdr/gnss-sdr synced 2024-10-30 06:36:21 +00:00

Read .crt files instead of .pem files

Define the following global configuration parameters:
GNSS-SDR.osnma_public_key (string, by default pointing to ../data/OSNMA_PublicKey_20240115100000_newPKID_1.crt)
GNSS-SDR.osnma_merkletree (string, by default pointing to  ../data/OSNMA_MerkleTree_20240115100000_newPKID_1.xml)

Add logging of OSNMA events
Clean public API of Gnss_Crypto class
This commit is contained in:
Carles Fernandez 2024-06-23 09:49:14 +02:00
parent d41efd2653
commit bac36b2df5
No known key found for this signature in database
GPG Key ID: 4C583C52B0C3877D
5 changed files with 159 additions and 47 deletions

View File

@ -124,9 +124,9 @@ void GNSSFlowgraph::init()
if (configuration_->property("Channels_1B.count", 0) > 0)
{
enable_osnma_rx_ = true;
auto pemFilePath = configuration_->property("GNSS-SDR.OSNMA_pem", PEMFILE_DEFAULT);
auto merKleTreePath = configuration_->property("GNSS-SDR.OSNMA_MerkleTree", MERKLEFILE_DEFAULT);
osnma_rx_ = osnma_msg_receiver_make(pemFilePath, merKleTreePath);
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);
}
else
{

View File

@ -29,8 +29,9 @@ set(SYSTEM_PARAMETERS_SOURCES
glonass_gnav_utc_model.cc
glonass_gnav_navigation_message.cc
reed_solomon.cc
osnma_dsm_reader.cc
osnma_data.cc
osnma_dsm_reader.cc
osnma_helper.cc
)
set(SYSTEM_PARAMETERS_HEADERS
@ -96,7 +97,6 @@ set(SYSTEM_PARAMETERS_HEADERS
Galileo_OSNMA.h
osnma_data.h
osnma_dsm_reader.h
osnma_helper.cc
osnma_helper.h
)

View File

@ -161,7 +161,8 @@ const std::unordered_map<std::string, uint16_t> OSNMA_TABLE_15 = {
{std::string("SHA-512"), 1056}}; // key: ECDSA Curve and hash function, value: {l_ds_bits}
const std::string PEMFILE_DEFAULT("../data/OSNMA_PublicKey_20240115100000_newPKID_1.pem");
const std::string MERKLEFILE_DEFAULT("./OSNMA_MerkleTree_20210920133026.xml");
const std::string CRTFILE_DEFAULT("../data/OSNMA_PublicKey_20240115100000_newPKID_1.crt");
const std::string MERKLEFILE_DEFAULT("../data/OSNMA_MerkleTree_20240115100000_newPKID_1.xml");
class Mack_lookup
{

View File

@ -30,6 +30,7 @@
#include <openssl/ecdsa.h>
#include <openssl/hmac.h>
#include <openssl/pem.h>
#include <openssl/x509.h>
#if USE_OPENSSL_3
#include <openssl/bio.h>
#include <openssl/bn.h>
@ -47,13 +48,23 @@
#include <gnutls/x509.h>
#endif
Gnss_Crypto::Gnss_Crypto(const std::string& pemFilePath, const std::string& merkleTreePath)
#if USE_GLOG_AND_GFLAGS
#include <glog/logging.h> // for DLOG
#else
#include <absl/log/log.h>
#endif
Gnss_Crypto::Gnss_Crypto(const std::string& certFilePath, const std::string& merkleTreePath)
{
#if USE_OPENSSL_FALLBACK
#else // GnuTLS
gnutls_global_init();
#endif
readPublicKeyFromPEM(pemFilePath);
if (!readPublicKeyFromCRT(certFilePath))
{
readPublicKeyFromPEM(PEMFILE_DEFAULT);
}
read_merkle_xml(merkleTreePath);
}
@ -69,10 +80,10 @@ Gnss_Crypto::~Gnss_Crypto()
}
#endif
#else // GnuTLS
if (d_PublicKey != NULL)
if (d_PublicKey != nullptr)
{
gnutls_pubkey_deinit(d_PublicKey);
d_PublicKey = NULL;
d_PublicKey = nullptr;
}
gnutls_global_deinit();
#endif
@ -145,11 +156,11 @@ void Gnss_Crypto::read_merkle_xml(const std::string& merkleFilePath)
std::string signalVersion = galHeader.child("signalVersion").text().get();
std::string dataVersion = galHeader.child("dataVersion").text().get();
std::cout << " Source: " << source.child_value("mission") << " - " << source.child_value("segment") << " - " << source.child_value("element") << std::endl;
std::cout << " Destination: " << destination.child_value("mission") << " - " << destination.child_value("segment") << " - " << destination.child_value("element") << std::endl;
std::cout << " Issue Date: " << issueDate << std::endl;
std::cout << " Signal Version: " << signalVersion << std::endl;
std::cout << " Data Version: " << dataVersion << std::endl;
LOG(INFO) << "OSNMA Merkletree - Source: " << source.child_value("mission") << " - " << source.child_value("segment") << " - " << source.child_value("element");
LOG(INFO) << "OSNMA Merkletree - Destination: " << destination.child_value("mission") << " - " << destination.child_value("segment") << " - " << destination.child_value("element");
LOG(INFO) << "OSNMA Merkletree - Issue Date: " << issueDate;
LOG(INFO) << "OSNMA Merkletree - Signal Version: " << signalVersion;
LOG(INFO) << "OSNMA Merkletree - Data Version: " << dataVersion;
// Accessing data from the body
pugi::xml_node merkleTree = body.child("MerkleTree");
@ -157,8 +168,8 @@ void Gnss_Crypto::read_merkle_xml(const std::string& merkleFilePath)
int n = std::stoi(merkleTree.child_value("N"));
std::string hashFunction = merkleTree.child_value("HashFunction");
std::cout << " N: " << n << std::endl;
std::cout << " Hash Function: " << hashFunction << std::endl;
LOG(INFO) << "OSNMA Merkletree - N: " << n;
LOG(INFO) << "OSNMA Merkletree - Hash Function: " << hashFunction;
for (pugi::xml_node publicKey : merkleTree.children("PublicKey"))
{
@ -168,21 +179,21 @@ void Gnss_Crypto::read_merkle_xml(const std::string& merkleFilePath)
std::string point = publicKey.child_value("point");
std::string pkType = publicKey.child_value("PKType");
std::cout << " Public Key: " << i << std::endl;
std::cout << " PKID: " << pkid << std::endl;
std::cout << " Length in Bits: " << lengthInBits << std::endl;
std::cout << " Point: " << point << std::endl;
std::cout << " PK Type: " << pkType << std::endl;
LOG(INFO) << "OSNMA Merkletree - Public Key: " << i;
LOG(INFO) << "OSNMA Merkletree - PKID: " << pkid;
LOG(INFO) << "OSNMA Merkletree - Length in Bits: " << lengthInBits;
LOG(INFO) << "OSNMA Merkletree - Point: " << point;
LOG(INFO) << "OSNMA Merkletree - PK Type: " << pkType;
}
for (pugi::xml_node treeNode : merkleTree.children("TreeNode"))
{
int j = std::stoi(treeNode.child_value("j"));
int i = std::stoi(treeNode.child_value("i"));
int lengthInBits = std::stoi(treeNode.child_value("lengthInBits"));
std::cout << " Node length (bits): " << lengthInBits << std::endl;
LOG(INFO) << "OSNMA Merkletree - Node length (bits): " << lengthInBits;
std::string x_ji = treeNode.child_value("x_ji");
std::cout << " Size string (bytes): " << x_ji.size() << std::endl;
std::cout << " m_" << j << "_" << i << " = " << x_ji << std::endl;
LOG(INFO) << "OSNMA Merkletree - Size string (bytes): " << x_ji.size();
LOG(INFO) << "OSNMA Merkletree - m_" << j << "_" << i << " = " << x_ji;
if (j == 4 && i == 0)
{
d_x_4_0 = convert_from_hex_str(x_ji);
@ -220,7 +231,8 @@ void Gnss_Crypto::read_merkle_xml(const std::string& merkleFilePath)
d_x_0_1 = convert_from_hex_str("AA1A8B68E5DB293106B5BC8806F9790E8ACF8DC2D28A6EF6C1AC7233A9813D3F");
return;
}
std::cout << "Merkle Tree successfully read from file " << merkleFilePath << std::endl;
std::cout << "OSNMA Merkle Tree successfully read from file " << merkleFilePath << std::endl;
LOG(INFO) << "OSNMA Merkle Tree successfully read from file " << merkleFilePath;
}
@ -451,7 +463,8 @@ void Gnss_Crypto::readPublicKeyFromPEM(const std::string& pemFilePath)
BIO_free(bio);
if (d_PublicKey == nullptr)
{
std::cerr << "OpenSSL: error reading the Public Key from file " << pemFilePath << ". Aborting import" << std::endl;
std::cerr << "OpenSSL: error reading the OSNMA Public Key from file " << pemFilePath << ". Aborting import" << std::endl;
LOG(INFO) << "OpenSSL: error reading the OSNMA Public Key from file " << pemFilePath << ". Aborting import";
return;
}
#else // GnuTLS
@ -464,17 +477,105 @@ void Gnss_Crypto::readPublicKeyFromPEM(const std::string& pemFilePath)
if (ret != GNUTLS_E_SUCCESS)
{
gnutls_pubkey_deinit(pubkey);
std::cerr << "GnuTLS: error reading the Public Key from file "
std::cerr << "GnuTLS: error reading the OSNMA Public Key from file "
<< pemFilePath
<< ". Aborting import" << std::endl;
std::cerr << "GnuTLS error: " << gnutls_strerror(ret) << std::endl;
LOG(INFO) << "GnuTLS: error reading the OSNMA Public Key from file " << pemFilePath << ". Aborting import";
return;
}
pubkey_copy(pubkey, &d_PublicKey);
gnutls_pubkey_deinit(pubkey);
#endif
std::cout << "Public key successfully read from file " << pemFilePath << std::endl;
std::cout << "OSNMA Public key successfully read from file " << pemFilePath << std::endl;
LOG(INFO) << "OSNMA Public key successfully read from file " << pemFilePath;
}
bool Gnss_Crypto::readPublicKeyFromCRT(const std::string& crtFilePath)
{
#if USE_OPENSSL_FALLBACK
// Open the .crt file
std::ifstream crtFile(crtFilePath, std::ios::binary);
if (!crtFile.is_open())
{
std::cerr << "Unable to open file: " << crtFilePath << std::endl;
return false;
}
// Read certificate
std::vector<char> buffer((std::istreambuf_iterator<char>(crtFile)), std::istreambuf_iterator<char>());
BIO* bio = BIO_new_mem_buf(buffer.data(), buffer.size());
if (!bio)
{
std::cerr << "Unable to create BIO for file: " << crtFilePath << std::endl;
return false;
}
X509* cert = PEM_read_bio_X509(bio, nullptr, nullptr, nullptr);
if (!cert)
{
std::cerr << "Unable to read certificate from file: " << crtFilePath << std::endl;
BIO_free(bio);
return false;
}
// Read the public key from the certificate
EVP_PKEY* pubkey = X509_get_pubkey(cert);
if (!pubkey)
{
std::cerr << "Failed to extract the public key" << std::endl;
X509_free(cert);
return false;
}
pubkey_copy(pubkey, &d_PublicKey);
EVP_PKEY_free(pubkey);
BIO_free(bio);
X509_free(cert);
#else // GnuTLS
// Open the .crt file
std::ifstream crtFile(crtFilePath, std::ios::binary);
if (!crtFile.is_open())
{
// CRT file not found
// If it was not the default, maybe it is a configuration error
if (crtFilePath != CRTFILE_DEFAULT)
{
std::cerr << "File " << crtFilePath << " not found" << std::endl;
}
return false;
}
std::vector<char> buffer((std::istreambuf_iterator<char>(crtFile)), std::istreambuf_iterator<char>());
gnutls_x509_crt_t cert;
gnutls_x509_crt_init(&cert);
int ret = gnutls_x509_crt_import(cert, (const gnutls_datum_t*)&buffer, GNUTLS_X509_FMT_PEM);
if (ret < 0)
{
std::cerr << "Failed to import certificate: " << gnutls_strerror(ret) << std::endl;
gnutls_x509_crt_deinit(cert);
return false;
}
gnutls_pubkey_t pubkey;
gnutls_pubkey_init(&pubkey);
ret = gnutls_pubkey_import_x509(pubkey, cert, 0);
if (ret < 0)
{
std::cerr << "Failed to import public key: " << gnutls_strerror(ret) << std::endl;
gnutls_pubkey_deinit(pubkey);
gnutls_x509_crt_deinit(cert);
return false;
}
pubkey_copy(pubkey, &d_PublicKey);
gnutls_x509_crt_deinit(cert);
gnutls_pubkey_deinit(pubkey);
#endif
std::cout << "OSNMA Public key successfully read from file " << crtFilePath << std::endl;
LOG(INFO) << "OSNMA Public key successfully read from file " << crtFilePath;
return true;
}
@ -551,18 +652,21 @@ bool Gnss_Crypto::verify_signature(const std::vector<uint8_t>& message, const st
if (verification == 1)
{
success = true;
LOG(INFO) << "OpenSSL: OSNMA signature authenticated successfully";
}
else
{
unsigned long errCode = ERR_get_error();
char* err = ERR_error_string(errCode, NULL);
std::cerr << "OpenSSL: message authentication failed: " << err << std::endl;
char* err = ERR_error_string(errCode, nullptr);
std::cerr << "OpenSSL: OSNMA message authentication failed: " << err << std::endl;
LOG(WARNING) << "OpenSSL: OSNMA message authentication failed: " << err;
}
#else
int verification = ECDSA_verify(0, digest.data(), SHA256_DIGEST_LENGTH, signature.data(), static_cast<int>(signature.size()), d_PublicKey);
if (verification == 1)
{
success = true;
LOG(INFO) << "OpenSSL: OSNMA signature authenticated successfully";
}
else if (verification == 0)
{
@ -570,9 +674,9 @@ bool Gnss_Crypto::verify_signature(const std::vector<uint8_t>& message, const st
}
else
{
std::cerr << "OpenSSL: message authentication failed" << std::endl;
std::cerr << "OpenSSL: OSNMA message authentication failed" << std::endl;
LOG(WARNING) << "OpenSSL: OSNMA message authentication failed";
}
#endif
#else // GnuTLS
// Convert signature to DER format
@ -590,9 +694,14 @@ bool Gnss_Crypto::verify_signature(const std::vector<uint8_t>& message, const st
// Verify the DER-encoded signature
int ret = gnutls_pubkey_verify_hash2(d_PublicKey, GNUTLS_SIGN_ECDSA_SHA256, 0, &digest_data, &der_sig_data);
success = (ret >= 0);
if (!success)
if (success)
{
std::cerr << "GnuTLS: message authentication failed: " << gnutls_strerror(ret) << std::endl;
LOG(INFO) << "GnuTLS: OSNMA signature authenticated successfully";
}
else
{
std::cerr << "GnuTLS: OSNMA message authentication failed: " << gnutls_strerror(ret) << std::endl;
LOG(WARNING) << "GnuTLS: OSNMA message authentication failed: " << gnutls_strerror(ret);
}
#endif
return success;
@ -638,8 +747,8 @@ std::vector<uint8_t> Gnss_Crypto::getMerkleRoot(const std::vector<std::vector<ui
void Gnss_Crypto::set_public_key(const std::vector<uint8_t>& publicKey)
{
#if USE_OPENSSL_FALLBACK
BIO* bio = NULL;
EVP_PKEY* pkey = NULL;
BIO* bio = nullptr;
EVP_PKEY* pkey = nullptr;
bio = BIO_new_mem_buf(publicKey.data(), publicKey.size());
if (!bio)
{
@ -647,12 +756,13 @@ void Gnss_Crypto::set_public_key(const std::vector<uint8_t>& publicKey)
return;
}
pkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL);
pkey = PEM_read_bio_PUBKEY(bio, nullptr, nullptr, nullptr);
BIO_free(bio);
if (!pkey)
{
std::cerr << "OpenSSL: error setting the public key." << std::endl;
std::cerr << "OpenSSL: error setting the OSNMA public key." << std::endl;
LOG(INFO) << "OpenSSL: error setting the OSNMA public key.";
return;
}
@ -677,6 +787,7 @@ void Gnss_Crypto::set_public_key(const std::vector<uint8_t>& publicKey)
pubkey_copy(pubkey, &d_PublicKey);
gnutls_pubkey_deinit(pubkey);
#endif
LOG(INFO) << "OSNMA Public Key successfully set up.";
}
@ -685,7 +796,7 @@ 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 == NULL)
if (mem_bio == nullptr)
{
return false;
}
@ -703,15 +814,15 @@ bool Gnss_Crypto::pubkey_copy(EVP_PKEY* src, EVP_PKEY** dest)
// 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 == NULL)
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, NULL, NULL, NULL);
if (*dest == NULL)
*dest = PEM_read_bio_PUBKEY(mem_bio2, nullptr, nullptr, nullptr);
if (*dest == nullptr)
{
BIO_free(mem_bio);
BIO_free(mem_bio2);

View File

@ -36,12 +36,9 @@
class Gnss_Crypto
{
public:
Gnss_Crypto() = default;
Gnss_Crypto(const std::string& certFilePath, const std::string& merkleTreePath);
~Gnss_Crypto();
Gnss_Crypto(const std::string& pemFilePath, const std::string& merkleTreePath);
void readPublicKeyFromPEM(const std::string& pemFilePath);
void read_merkle_xml(const std::string& merkleFilePath);
void set_public_key(const std::vector<uint8_t>& publickey);
bool have_public_key() const;
bool verify_signature(const std::vector<uint8_t>& message, const std::vector<uint8_t>& signature) const;
@ -57,6 +54,9 @@ public:
}
private:
void read_merkle_xml(const std::string& merkleFilePath);
void readPublicKeyFromPEM(const std::string& pemFilePath);
bool readPublicKeyFromCRT(const std::string& crtFilePath);
std::vector<uint8_t> convert_from_hex_str(const std::string& input) const;
#if USE_OPENSSL_FALLBACK
#if USE_OPENSSL_3