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:
parent
d41efd2653
commit
bac36b2df5
@ -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
|
||||
{
|
||||
|
@ -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
|
||||
)
|
||||
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user