1
0
mirror of https://github.com/gnss-sdr/gnss-sdr synced 2025-04-06 02:37:20 +00:00

Merge pull request #4 from carlesfernandez/osnma-cesare-fix3

Really fix signature verification with GnuTLS
This commit is contained in:
cesaaargm 2024-06-24 15:33:20 +02:00 committed by GitHub
commit c1c58eab06
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 681 additions and 737 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

@ -1,7 +1,8 @@
/*!
* \file gnss_crypto.cc
* \brief Class for computing cryptografic functions
* \author Carles Fernandez, 2023. cfernandez(at)cttc.es
* \brief Class for computing cryptographic functions
* \author Carles Fernandez, 2023-2024. cfernandez(at)cttc.es
* Cesare Ghionoiu Martinez, 2023-2024. c.ghionoiu-martinez@tu-braunschweig.de
*
*
* -----------------------------------------------------------------------------
@ -9,7 +10,7 @@
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
* This file is part of GNSS-SDR.
*
* Copyright (C) 2010-2023 (see AUTHORS file for a list of contributors)
* Copyright (C) 2010-2024 (see AUTHORS file for a list of contributors)
* SPDX-License-Identifier: GPL-3.0-or-later
*
* -----------------------------------------------------------------------------
@ -20,41 +21,61 @@
#include <pugixml.hpp>
#include <cstddef>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <sstream>
#if USE_OPENSSL_FALLBACK
#include <openssl/cmac.h>
#include <openssl/ecdsa.h>
#include <openssl/hmac.h>
#include <openssl/pem.h>
#include <openssl/x509.h>
#if USE_OPENSSL_3
#include <iomanip>
#include <openssl/bio.h>
#include <openssl/bn.h>
#include <openssl/core_names.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/ec.h>
#include <openssl/param_build.h>
#include <openssl/bn.h>
#include <openssl/params.h>
#define OPENSSL_ENGINE nullptr
#else
#include <openssl/sha.h>
#endif
#else
#else // GnuTLS
#include <cstring>
#include <gnutls/abstract.h>
#include <gnutls/crypto.h>
#include <gnutls/x509.h>
#include <iomanip>
#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()
{
#if USE_OPENSSL_FALLBACK
#else
// gnutls_global_init();
#else // GnuTLS
gnutls_global_init();
#endif
readPublicKeyFromPEM(pemFilePath);
}
Gnss_Crypto::Gnss_Crypto(const std::string& certFilePath, const std::string& merkleTreePath)
{
#if USE_OPENSSL_FALLBACK
#else // GnuTLS
gnutls_global_init();
#endif
if (!readPublicKeyFromCRT(certFilePath))
{
readPublicKeyFromPEM(PEMFILE_DEFAULT);
}
read_merkle_xml(merkleTreePath);
}
@ -69,11 +90,13 @@ Gnss_Crypto::~Gnss_Crypto()
EC_KEY_free(d_PublicKey);
}
#endif
#else // GNU-TLS
if (d_PublicKey != NULL) {
#else // GnuTLS
if (d_PublicKey != nullptr)
{
gnutls_pubkey_deinit(d_PublicKey);
d_PublicKey = NULL;
d_PublicKey = nullptr;
}
gnutls_global_deinit();
#endif
}
@ -82,25 +105,12 @@ bool Gnss_Crypto::have_public_key() const
{
#if USE_OPENSSL_FALLBACK
return (d_PublicKey != nullptr);
#else
#else // GnuTLS
return (d_PublicKey != gnutls_pubkey_t{});
#endif
}
std::string Gnss_Crypto::convert_to_utf8_str(const std::vector<uint8_t>& input) const
{
const char hex[] = "0123456789ABCDEF";
std::string str(input.size() * 2, '0');
for (size_t i = 0; i < input.size(); i++)
{
str[(i * 2) + 0] = hex[((input[i] & 0xF0) >> 4)];
str[(i * 2) + 1] = hex[((input[i] & 0x0F))];
}
return str;
}
std::vector<uint8_t> Gnss_Crypto::convert_from_hex_str(const std::string& input) const
{
std::vector<uint8_t> result;
@ -157,11 +167,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");
@ -169,8 +179,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"))
{
@ -180,21 +190,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);
@ -232,15 +242,11 @@ 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;
}
// void Gnss_Crypto::set_public_key(const std::vector<uint8_t>& publickey)
// {
// }
std::vector<uint8_t> Gnss_Crypto::computeSHA256(const std::vector<uint8_t>& input) const
{
std::vector<uint8_t> output(32); // SHA256 hash size
@ -273,7 +279,7 @@ std::vector<uint8_t> Gnss_Crypto::computeSHA256(const std::vector<uint8_t>& inpu
SHA256_Update(&sha256Context, input.data(), input.size());
SHA256_Final(output.data(), &sha256Context);
#endif
#else
#else // GnuTLS
std::vector<uint8_t> output_aux(32);
gnutls_hash_hd_t hashHandle;
gnutls_hash_init(&hashHandle, GNUTLS_DIG_SHA256);
@ -301,7 +307,7 @@ std::vector<uint8_t> Gnss_Crypto::computeSHA3_256(const std::vector<uint8_t>& in
#else
// SHA3-256 not implemented in OpenSSL < 3.0
#endif
#else
#else // GnuTLS
std::vector<uint8_t> output_aux(32);
gnutls_hash_hd_t hashHandle;
gnutls_hash_init(&hashHandle, GNUTLS_DIG_SHA3_256);
@ -320,23 +326,58 @@ std::vector<uint8_t> Gnss_Crypto::computeHMAC_SHA_256(const std::vector<uint8_t>
#if USE_OPENSSL_FALLBACK
#if USE_OPENSSL_3
std::vector<uint8_t> hmac(EVP_MAX_MD_SIZE);
size_t output_length = 0;
// Create the context for the HMAC operation
EVP_MAC* mac = EVP_MAC_fetch(nullptr, "HMAC", nullptr);
if (!mac)
{
LOG(WARNING) << "OSNMA HMAC_SHA_256 computation failed to fetch HMAC";
return output;
}
// Create HMAC-SHA256 context
EVP_MD_CTX* ctx = EVP_MD_CTX_new();
EVP_PKEY* pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, nullptr, key.data(), key.size());
EVP_MAC_CTX* ctx = EVP_MAC_CTX_new(mac);
if (!ctx)
{
EVP_MAC_free(mac);
LOG(WARNING) << "OSNMA HMAC_SHA_256 computation failed to create HMAC context";
return output;
}
// Initialize HMAC-SHA256 context
EVP_DigestSignInit(ctx, nullptr, EVP_sha256(), nullptr, pkey);
// Initialize the HMAC context with the key and the SHA-256 algorithm
OSSL_PARAM params[] = {
OSSL_PARAM_construct_utf8_string(OSSL_ALG_PARAM_DIGEST, const_cast<char*>("SHA256"), 0),
OSSL_PARAM_construct_end()};
// Compute HMAC-SHA256
EVP_DigestSignUpdate(ctx, input.data(), input.size());
size_t macLength;
EVP_DigestSignFinal(ctx, hmac.data(), &macLength);
if (EVP_MAC_init(ctx, key.data(), key.size(), params) <= 0)
{
EVP_MAC_CTX_free(ctx);
EVP_MAC_free(mac);
LOG(WARNING) << "OSNMA HMAC_SHA_256 computation failed to initialize HMAC context";
return output;
}
EVP_PKEY_free(pkey);
EVP_MD_CTX_free(ctx);
// Update the HMAC context with the input data
if (EVP_MAC_update(ctx, input.data(), input.size()) <= 0)
{
EVP_MAC_CTX_free(ctx);
EVP_MAC_free(mac);
LOG(WARNING) << "OSNMA HMAC_SHA_256 computation failed to update HMAC context";
return output;
}
hmac.resize(macLength);
// Finalize the HMAC and retrieve the output
if (EVP_MAC_final(ctx, hmac.data(), &output_length, hmac.size()) <= 0)
{
EVP_MAC_CTX_free(ctx);
EVP_MAC_free(mac);
LOG(WARNING) << "OSNMA HMAC_SHA_256 computation failed to finalize HMAC";
return output;
}
// Clean up the HMAC context
EVP_MAC_CTX_free(ctx);
EVP_MAC_free(mac);
hmac.resize(output_length);
output = hmac;
#else
std::vector<uint8_t> hmac(32);
@ -358,7 +399,7 @@ std::vector<uint8_t> Gnss_Crypto::computeHMAC_SHA_256(const std::vector<uint8_t>
hmac.resize(hmacLen);
output = hmac;
#endif
#else
#else // GnuTLS
std::vector<uint8_t> output_aux(32);
gnutls_hmac_hd_t hmac;
gnutls_hmac_init(&hmac, GNUTLS_MAC_SHA256, key.data(), key.size());
@ -376,35 +417,62 @@ std::vector<uint8_t> Gnss_Crypto::computeCMAC_AES(const std::vector<uint8_t>& ke
std::vector<uint8_t> output(16);
#if USE_OPENSSL_FALLBACK
#if USE_OPENSSL_3
std::vector<uint8_t> mac(EVP_MAX_MD_SIZE); // CMAC-AES output size
std::vector<uint8_t> aux(EVP_MAX_MD_SIZE); // CMAC-AES output size
size_t output_length = 0;
EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
EVP_MAC* cmac = EVP_MAC_fetch(nullptr, "CMAC-AES", nullptr);
// Create the context for the CMAC operation
EVP_MAC* mac = EVP_MAC_fetch(nullptr, "CMAC", nullptr);
if (!mac)
{
LOG(INFO) << "OSNMA CMAC-AES: Failed to fetch CMAC";
return output;
}
EVP_MAC_CTX* cmacCtx = EVP_MAC_CTX_new(cmac);
EVP_MAC_CTX* ctx = EVP_MAC_CTX_new(mac);
if (!ctx)
{
LOG(INFO) << "OSNMA CMAC-AES: Failed to create CMAC context";
return output;
}
OSSL_PARAM params[4];
params[0] = OSSL_PARAM_construct_utf8_string("key", (char*)key.data(), key.size());
params[1] = OSSL_PARAM_construct_octet_string("iv", nullptr, 0); // Set IV to nullptr
params[2] = OSSL_PARAM_construct_octet_string("aad", nullptr, 0); // Set AAD to nullptr
params[3] = OSSL_PARAM_construct_end();
// Initialize the CMAC context with the key and the AES algorithm
OSSL_PARAM params[] = {
OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_CIPHER, const_cast<char*>("AES-128-CBC"), 0),
OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY, const_cast<unsigned char*>(key.data()), key.size()),
OSSL_PARAM_construct_end()};
// Set AES-128 CMAC cipher and key
EVP_MAC_init(cmacCtx, nullptr, 0, params);
if (EVP_MAC_init(ctx, nullptr, 0, params) <= 0)
{
EVP_MAC_CTX_free(ctx);
EVP_MAC_free(mac);
LOG(INFO) << "OSNMA CMAC-AES: Failed to initialize CMAC context";
return output;
}
// Compute CMAC-AES
EVP_MAC_update(cmacCtx, input.data(), input.size());
size_t macLength = mac.size();
size_t outputLength = 16;
// Update the CMAC context with the input data
if (EVP_MAC_update(ctx, input.data(), input.size()) <= 0)
{
EVP_MAC_CTX_free(ctx);
EVP_MAC_free(mac);
LOG(INFO) << "OSNMA CMAC-AES: Failed to update CMAC context";
return output;
}
EVP_MAC_final(cmacCtx, mac.data(), &macLength, outputLength);
// Finalize the CMAC and retrieve the output
if (EVP_MAC_final(ctx, aux.data(), &output_length, aux.size()) <= 0)
{
EVP_MAC_CTX_free(ctx);
EVP_MAC_free(mac);
LOG(INFO) << "OSNMA CMAC-AES: Failed to finalize CMAC";
return output;
}
EVP_MAC_free(cmac);
EVP_MAC_CTX_free(cmacCtx);
EVP_CIPHER_CTX_free(ctx);
// Clean up the CMAC context
EVP_MAC_CTX_free(ctx);
EVP_MAC_free(mac);
mac.resize(macLength);
output = mac;
aux.resize(output_length);
output = aux;
#else
std::vector<uint8_t> mac(16); // CMAC-AES output size
@ -421,7 +489,7 @@ std::vector<uint8_t> Gnss_Crypto::computeCMAC_AES(const std::vector<uint8_t>& ke
output = mac;
#endif
#else
#else // GnuTLS
gnutls_cipher_hd_t cipher;
std::vector<uint8_t> mac(16);
std::vector<uint8_t> message = input;
@ -468,11 +536,11 @@ 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
#else // GnuTLS
// Import the PEM data
gnutls_datum_t pemDatum = {const_cast<unsigned char*>(reinterpret_cast<unsigned char*>(pemContent.data())), static_cast<unsigned int>(pemContent.size())};
gnutls_pubkey_t pubkey;
@ -482,73 +550,120 @@ 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;
//print_pubkey_hex(d_PublicKey);
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::verify_signature(const std::vector<uint8_t>& message, const std::vector<uint8_t>& signature)
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;
}
bool Gnss_Crypto::verify_signature(const std::vector<uint8_t>& message, const std::vector<uint8_t>& signature) const
{
std::vector<uint8_t> digest = this->computeSHA256(message);
if (!have_public_key())
{
std::cerr << "Galileo OSNMA::Kroot verification error::Public key not available"<< std::endl;
std::cerr << "Galileo OSNMA KROOT verification error: Public key is not available" << std::endl;
return false;
}
bool success = false;
#if USE_OPENSSL_FALLBACK
// using low-level API to test function -- it works in unit tests, not in real bytes.
// EVP_MD_CTX *mdctx = NULL; // verification context; a struct that wraps the message to be verified.
// int ret = 0; // error
//
// /* Create the Message Digest Context */
// if(!(mdctx = EVP_MD_CTX_new())) goto err; // Allocates and returns a digest context.
//
// /* Initialize `key` with a public key */
// // hashes cnt bytes of data at d into the verification context ctx
// if(1 != EVP_DigestVerifyInit(mdctx, NULL /*TODO null?*/, EVP_sha256(), NULL, d_PublicKey)) goto err;
//
// /* Initialize `key` with a public key */
// if(1 != EVP_DigestVerifyUpdate(mdctx, message.data(), message.size())) goto err;
//
//
// if( 1 == EVP_DigestVerifyFinal(mdctx, signature.data(), signature.size()))
// {
// return true;
// }
// else
// {
// unsigned long errCode = ERR_get_error();
// int lib_code = ERR_GET_LIB(errCode);
// char* err = ERR_error_string(errCode, NULL);
// const char* error_string = ERR_error_string(errCode, NULL);
// std::cerr << "OpenSSL: message authentication failed: " << err /*<<
// "from library with code " << lib_code <<
// " error string: " << error_string */<< std::endl;
// }
//err:
// if(ret != 1)
// {
// /* Do some error handling */
// // notify other blocks
// std::cout << "ECDSA_Verify_OSSL()::error " << ret << std::endl;
//
// }
#if USE_OPENSSL_3
EVP_PKEY_CTX* ctx;
//print_pubkey_hex(d_PublicKey);
ctx = EVP_PKEY_CTX_new(d_PublicKey, nullptr);
bool do_operation = true;
@ -556,7 +671,7 @@ bool Gnss_Crypto::verify_signature(const std::vector<uint8_t>& message, const st
{
do_operation = false;
}
// convert raw signature into DER format, needed for verify_signature
// convert raw signature into DER format
size_t half_size = signature.size() / 2;
std::vector<uint8_t> raw_r(signature.begin(), signature.begin() + half_size);
std::vector<uint8_t> raw_s(signature.begin() + half_size, signature.end());
@ -575,12 +690,12 @@ bool Gnss_Crypto::verify_signature(const std::vector<uint8_t>& message, const st
if (ECDSA_SIG_set0(sig, r, s) != 1)
{
std::cerr << "Failed to set R and S values in ECDSA_SIG" << std::endl;
ECDSA_SIG_free(sig); // Free the ECDSA_SIG struct as it's no longer needed
ECDSA_SIG_free(sig); // Free the ECDSA_SIG struct as it is no longer needed
return false;
}
std::vector<uint8_t> derSignature;
unsigned char *derSig = nullptr;
unsigned char* derSig = nullptr;
int derSigLength = i2d_ECDSA_SIG(sig, &derSig);
if (derSigLength <= 0)
@ -591,7 +706,6 @@ bool Gnss_Crypto::verify_signature(const std::vector<uint8_t>& message, const st
derSignature.assign(derSig, derSig + derSigLength);
if (EVP_PKEY_verify_init(ctx) <= 0)
{
do_operation = false;
@ -611,19 +725,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
auto digest = this->computeSHA256(message);
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)
{
@ -631,38 +747,35 @@ 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
// GNU-TLS
gnutls_global_init();
// debug info gnu-tls remove when not needed anymore!
gnutls_global_set_log_level(9);
gnutls_global_set_log_function(Gnss_Crypto::my_log_func);
unsigned int bit_size;
if (gnutls_pubkey_get_pk_algorithm(d_PublicKey, &bit_size) != GNUTLS_PK_ECDSA)
#else // GnuTLS
// Convert signature to DER format
std::vector<uint8_t> der_sig;
if (!convert_raw_to_der_ecdsa(signature, der_sig))
{
std::cerr << "GnuTLS: the Public Key does not contain a ECDSA key. Aborting signature verification" << std::endl;
std::cerr << "Failed to convert raw ECDSA signature to DER format" << std::endl;
return false;
}
gnutls_datum_t signature_{};
signature_.data = const_cast<uint8_t*>(signature.data());
signature_.size = signature.size();
gnutls_datum_t data_{};
data_.data = const_cast<uint8_t*>(message.data());
data_.size = message.size();
int ret = gnutls_pubkey_verify_data2(d_PublicKey, GNUTLS_SIGN_ECDSA_SHA256, 0, &data_, &signature_);
if (ret >= 0)
// Prepare the digest datum
gnutls_datum_t digest_data = {const_cast<unsigned char*>(digest.data()), static_cast<unsigned int>(digest.size())};
gnutls_datum_t der_sig_data = {der_sig.data(), static_cast<unsigned int>(der_sig.size())};
// 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)
{
success = true;
LOG(INFO) << "GnuTLS: OSNMA signature authenticated successfully";
}
else
{
std::cerr << "GnuTLS error: " << gnutls_strerror(ret) << std::endl;
std::cerr << "GnuTLS: OSNMA message authentication failed: " << gnutls_strerror(ret) << std::endl;
LOG(WARNING) << "GnuTLS: OSNMA message authentication failed: " << gnutls_strerror(ret);
}
gnutls_global_deinit();
#endif
return success;
}
@ -707,82 +820,56 @@ 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) {
if (!bio)
{
std::cerr << "Failed to create BIO for key \n";
return;
}
pkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL);
BIO_free(bio);
pkey = PEM_read_bio_PUBKEY(bio, nullptr, nullptr, nullptr);
BIO_free(bio);
if (!pkey) {
std::cerr << "OpenSSL: error setting the public key "
<< ". Aborting import" << std::endl;
if (!pkey)
{
std::cerr << "OpenSSL: error setting the OSNMA public key." << std::endl;
LOG(INFO) << "OpenSSL: error setting the OSNMA public key.";
return;
}
//print_pubkey_hex(pkey);
if(!pubkey_copy(pkey, &d_PublicKey))
return
EVP_PKEY_free(pkey);
#else
// // GNU-TLS
// gnutls_global_init();
//
// // debug info gnu-tls remove when not needed anymore!
// gnutls_global_set_log_level(9);
// gnutls_global_set_log_function(Gnss_Crypto::my_log_func);
if (!pubkey_copy(pkey, &d_PublicKey))
{
return;
}
EVP_PKEY_free(pkey);
#else // GnuTLS
gnutls_pubkey_t pubkey;
gnutls_datum_t pemDatum = {const_cast<unsigned char*>(publicKey.data()), static_cast<unsigned int>(publicKey.size())};
gnutls_pubkey_init(&pubkey);
int ret = gnutls_pubkey_import(pubkey, &pemDatum, GNUTLS_X509_FMT_PEM);
//ret = gnutls_pubkey_import_x509_raw(pubkey, &pemDatum,GNUTLS_X509_FMT_PEM,0);
if (ret != GNUTLS_E_SUCCESS)
{
gnutls_pubkey_deinit(pubkey);
std::cerr << "GnuTLS: error setting the public key "
<< ". Aborting import" << std::endl;
std::cerr << "GnuTLS: error setting the public key" << std::endl;
std::cerr << "GnuTLS error: " << gnutls_strerror(ret) << std::endl;
return;
}
// d_PublicKey = pubkey;
pubkey_copy(pubkey, &d_PublicKey);
// std::cout << "pubkey: " << std::endl;
// print_pubkey_hex(pubkey);
// std::cout << "d_PublicKey before : " << std::endl;
// print_pubkey_hex(d_PublicKey);
gnutls_pubkey_deinit(pubkey);
// std::cout << "d_PublicKey after: " << std::endl;
// print_pubkey_hex(d_PublicKey);
// gnutls_global_deinit();
#endif
LOG(INFO) << "OSNMA Public Key successfully set up.";
}
std::vector<uint8_t> Gnss_Crypto::get_public_key()
{
#if USE_OPENSSL_FALLBACK
// TODO
#else
// GNU-TLS
// TODO
#endif
return {};
}
#if USE_OPENSSL_FALLBACK
bool Gnss_Crypto::pubkey_copy(EVP_PKEY* src, EVP_PKEY** dest)
{
// Open a memory buffer
BIO* mem_bio = BIO_new(BIO_s_mem());
if (mem_bio == NULL)
if (mem_bio == nullptr)
{
return false;
}
@ -794,24 +881,21 @@ bool Gnss_Crypto::pubkey_copy(EVP_PKEY* src, EVP_PKEY** dest)
return false;
}
// Add a null-terminator to the data in the memory buffer
//BIO_write(mem_bio, "\0", 1);
// Read the data from the memory buffer
char* bio_data;
long data_len = BIO_get_mem_data(mem_bio, &bio_data);
// Create a new memory buffer and load the data into it
BIO* mem_bio2 = BIO_new_mem_buf(bio_data, data_len);
if (mem_bio2 == 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);
@ -824,95 +908,87 @@ bool Gnss_Crypto::pubkey_copy(EVP_PKEY* src, EVP_PKEY** dest)
return true;
}
void Gnss_Crypto::print_pubkey_hex(EVP_PKEY* pubkey)
#else // GnuTLS-specific functions
bool Gnss_Crypto::convert_raw_to_der_ecdsa(const std::vector<uint8_t>& raw_signature, std::vector<uint8_t>& der_signature) const
{
BIO* mem_bio = BIO_new(BIO_s_mem());
if (!mem_bio) {
std::cerr << "Failed to create new memory BIO\n";
return;
if (raw_signature.size() % 2 != 0)
{
std::cerr << "Invalid raw ECDSA signature size" << std::endl;
return false;
}
if (!PEM_write_bio_PUBKEY(mem_bio, pubkey)){
std::cerr << "Failed to write public key to BIO\n";
BIO_free(mem_bio);
return;
size_t half_size = raw_signature.size() / 2;
std::vector<uint8_t> raw_r(raw_signature.begin(), raw_signature.begin() + half_size);
std::vector<uint8_t> raw_s(raw_signature.begin() + half_size, raw_signature.end());
auto encode_asn1_integer = [](const std::vector<uint8_t>& value) -> std::vector<uint8_t> {
std::vector<uint8_t> result;
result.push_back(0x02); // INTEGER tag
if (value[0] & 0x80)
{
result.push_back(value.size() + 1); // Length byte
result.push_back(0x00); // Add leading zero byte to ensure positive integer
}
else
{
result.push_back(value.size()); // Length byte
}
result.insert(result.end(), value.begin(), value.end());
return result;
};
std::vector<uint8_t> der_r = encode_asn1_integer(raw_r);
std::vector<uint8_t> der_s = encode_asn1_integer(raw_s);
size_t total_length = der_r.size() + der_s.size();
der_signature.push_back(0x30); // SEQUENCE tag
if (total_length > 127)
{
der_signature.push_back(0x81); // Long form length
}
der_signature.push_back(static_cast<uint8_t>(total_length));
BUF_MEM* mem_ptr;
BIO_get_mem_ptr(mem_bio, &mem_ptr); // Fetch the underlying BUF_MEM structure from the BIO.
der_signature.insert(der_signature.end(), der_r.begin(), der_r.end());
der_signature.insert(der_signature.end(), der_s.begin(), der_s.end());
std::stringstream ss;
// Iterate through each byte in mem_ptr->data and print its hex value.
for (size_t i = 0; i < mem_ptr->length; i++) {
ss << std::hex << std::setw(2) << std::setfill('0') <<
static_cast<int>(static_cast<unsigned char>(mem_ptr->data[i]));
}
//std::cout << "Public key in hex format: 0x" << ss.str() << std::endl;
BIO_free(mem_bio);
return true;
}
#else // gnutls-specific functions
void Gnss_Crypto::my_log_func(int level, const char *msg){
fprintf(stderr, "<GnuTLS %d> %s", level, msg);}
bool Gnss_Crypto::pubkey_copy(gnutls_pubkey_t src, gnutls_pubkey_t* dest)
{
gnutls_datum_t key_datum;
int ret;
// Export the public key from src to memory
ret = gnutls_pubkey_export2(src, GNUTLS_X509_FMT_PEM, &key_datum);
if (ret < 0)
{
gnutls_free(key_datum.data);
return false;
}
bool Gnss_Crypto::pubkey_copy(gnutls_pubkey_t src, gnutls_pubkey_t* dest)
{
gnutls_datum_t key_datum;
// Initialize dest
ret = gnutls_pubkey_init(dest);
if (ret < 0)
{
gnutls_free(key_datum.data);
return false;
}
// Export the public key from src to memory
int ret = gnutls_pubkey_export2(src, GNUTLS_X509_FMT_PEM, &key_datum);
if (ret < 0)
{
gnutls_free(key_datum.data);
return false;
}
// Import the public key data from key_datum to dest
ret = gnutls_pubkey_import(*dest, &key_datum, GNUTLS_X509_FMT_PEM);
gnutls_free(key_datum.data);
// Initialize dest
ret = gnutls_pubkey_init(dest);
if (ret < 0)
{
gnutls_free(key_datum.data);
return false;
}
if (ret < 0)
{
gnutls_pubkey_deinit(*dest);
return false;
}
// Import the public key data from key_datum to dest
ret = gnutls_pubkey_import(*dest, &key_datum, GNUTLS_X509_FMT_PEM);
gnutls_free(key_datum.data);
return true;
}
if (ret < 0)
{
gnutls_pubkey_deinit(*dest);
return false;
}
void Gnss_Crypto::print_pubkey_hex(gnutls_pubkey_t pubkey)
{
gnutls_datum_t key_datum;
int ret;
// Export the public key from pubkey to memory in DER format
ret = gnutls_pubkey_export2(pubkey, GNUTLS_X509_FMT_PEM, &key_datum);
if (ret < 0) {
std::cerr << "Failed to export public key: " << gnutls_strerror(ret) << std::endl;
return;
}
std::stringstream ss;
// Iterate through each byte in key_datum.data and print its hex value
for (unsigned int i = 0; i < key_datum.size; ++i) {
ss << std::hex << std::setw(2) << std::setfill('0') << static_cast<std::uint32_t>(key_datum.data[i]);
}
std::cout << "Public key in hex format: 0x" << ss.str() << std::endl;
// Free the memory allocated to key_datum.data
gnutls_free(key_datum.data);
}
return true;
}
#endif

View File

@ -1,7 +1,8 @@
/*!
* \file gnss_crypto.h
* \brief Class for computing cryptografic functions
* \author Carles Fernandez, 2023. cfernandez(at)cttc.es
* \brief Class for computing cryptographic functions
* \author Carles Fernandez, 2023-2024. cfernandez(at)cttc.es
* Cesare Ghionoiu Martinez, 2023-2024. c.ghionoiu-martinez@tu-braunschweig.de
*
*
* -----------------------------------------------------------------------------
@ -9,7 +10,7 @@
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
* This file is part of GNSS-SDR.
*
* Copyright (C) 2010-2023 (see AUTHORS file for a list of contributors)
* Copyright (C) 2010-2024 (see AUTHORS file for a list of contributors)
* SPDX-License-Identifier: GPL-3.0-or-later
*
* -----------------------------------------------------------------------------
@ -35,43 +36,39 @@
class Gnss_Crypto
{
public:
Gnss_Crypto() = default;
Gnss_Crypto();
Gnss_Crypto(const std::string& certFilePath, const std::string& merkleTreePath);
~Gnss_Crypto();
Gnss_Crypto(const std::string& pemFilePath, const std::string& merkleTreePath);
void set_public_key(const std::vector<uint8_t>& publickey);
bool have_public_key() const;
std::string convert_to_utf8_str(const std::vector<uint8_t>& input) const;
std::vector<uint8_t> convert_from_hex_str(const std::string& input) const;
bool verify_signature(const std::vector<uint8_t>& message, const std::vector<uint8_t>& signature) const;
std::vector<uint8_t> computeSHA256(const std::vector<uint8_t>& input) const;
std::vector<uint8_t> computeSHA3_256(const std::vector<uint8_t>& input) const;
std::vector<uint8_t> computeHMAC_SHA_256(const std::vector<uint8_t>& key, const std::vector<uint8_t>& input) const;
std::vector<uint8_t> computeCMAC_AES(const std::vector<uint8_t>& key, const std::vector<uint8_t>& input) const;
bool verify_signature(const std::vector<uint8_t>& message, const std::vector<uint8_t>& signature);
void readPublicKeyFromPEM(const std::string& pemFilePath);
void read_merkle_xml(const std::string& merkleFilePath);
std::vector<uint8_t> getMerkleRoot(const std::vector<std::vector<uint8_t>>& merkle) const;
std::vector<uint8_t> getMerkleRoot() const
inline std::vector<uint8_t> getMerkleRoot() const
{
return d_x_4_0;
}
void set_public_key(const std::vector<uint8_t>& publickey);
static std::vector<uint8_t> get_public_key();
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
bool pubkey_copy(EVP_PKEY* src, EVP_PKEY** dest);
void print_pubkey_hex(EVP_PKEY* pubkey);
#if USE_OPENSSL_3
EVP_PKEY* d_PublicKey{};
#else
EC_KEY* d_PublicKey = nullptr;
#endif
#else
bool pubkey_copy(EVP_PKEY* src, EVP_PKEY** dest);
#else // GnuTLS
gnutls_pubkey_t d_PublicKey{};
void set_ecc_key(const std::vector<uint8_t>& pK, const std::vector<uint8_t> ecP);
static void my_log_func(int level, const char* msg);
void print_pubkey_hex(gnutls_pubkey_t);
bool convert_raw_to_der_ecdsa(const std::vector<uint8_t>& raw_signature, std::vector<uint8_t>& der_signature) const;
bool pubkey_copy(gnutls_pubkey_t src, gnutls_pubkey_t* dest);
#endif
std::vector<uint8_t> d_x_4_0;

View File

@ -1344,52 +1344,14 @@ else()
endif()
endif()
######################################################### gnss_crypto_test
if(NOT ENABLE_PACKAGING AND NOT ENABLE_FPGA)
set(GNSS_CRYPTO_TEST_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/single_test_main.cc
${CMAKE_CURRENT_SOURCE_DIR}/unit-tests/signal-processing-blocks/osnma/gnss_crypto_test.cc)
if(USE_CMAKE_TARGET_SOURCES)
add_executable(gnss_crypto_test)
target_sources(gnss_crypto_test PRIVATE ${GNSS_CRYPTO_TEST_SOURCES})
else()
add_executable(gnss_crypto_test ${GNSS_CRYPTO_TEST_SOURCES})
endif()
target_link_libraries(gnss_crypto_test
PRIVATE
Boost::thread
GTest::GTest
GTest::Main
core_system_parameters
Pugixml::pugixml
)
if(ENABLE_GLOG_AND_GFLAGS)
target_link_libraries(gnss_crypto_test PRIVATE Gflags::gflags Glog::glog)
target_compile_definitions(gnss_crypto_test PRIVATE -DUSE_GLOG_AND_GFLAGS=1)
else()
target_link_libraries(gnss_crypto_test PRIVATE absl::flags absl::flags_parse absl::log $<LINK_LIBRARY:WHOLE_ARCHIVE,absl::log_flags> absl::log_initialize)
endif()
target_include_directories(gnss_crypto_test
PRIVATE
${GNSSSDR_SOURCE_DIR}/src/core/system_parameters)
xcode_remove_warning_duplicates(gnss_crypto_test) # TODO - unsure if needed
add_test(gnss_crypto_test gnss_crypto_test)
set_property(TEST gnss_crypto_test PROPERTY TIMEOUT 1)
endif()
######################################################### osnma_msg_receiver_test
if(NOT ENABLE_PACKAGING AND NOT ENABLE_FPGA)
set(OSNMA_MSG_RECEIVER_TEST_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/single_test_main.cc
${CMAKE_CURRENT_SOURCE_DIR}/unit-tests/signal-processing-blocks/osnma/osnma_msg_receiver_test.cc)
${CMAKE_CURRENT_SOURCE_DIR}/single_test_main.cc
${CMAKE_CURRENT_SOURCE_DIR}/unit-tests/signal-processing-blocks/osnma/osnma_msg_receiver_test.cc
)
if(USE_CMAKE_TARGET_SOURCES)
add_executable(osnma_msg_receiver_test)
@ -1399,7 +1361,8 @@ if(NOT ENABLE_PACKAGING AND NOT ENABLE_FPGA)
endif()
target_link_libraries(osnma_msg_receiver_test
PRIVATE
PRIVATE
gnss_sdr_flags
Boost::thread
GTest::GTest
GTest::Main
@ -1416,11 +1379,12 @@ if(NOT ENABLE_PACKAGING AND NOT ENABLE_FPGA)
add_test(osnma_msg_receiver_test osnma_msg_receiver_test)
set_property(TEST osnma_msg_receiver_test PROPERTY TIMEOUT 1)
set_property(TEST osnma_msg_receiver_test PROPERTY TIMEOUT 30)
target_include_directories(osnma_msg_receiver_test
PRIVATE
${GNSSSDR_SOURCE_DIR}/src/core/system_parameters)
PRIVATE
${GNSSSDR_SOURCE_DIR}/src/core/system_parameters
)
endif()
if(ENABLE_BENCHMARKS)

View File

@ -19,6 +19,7 @@
#include "concurrent_map.h"
#include "concurrent_queue.h"
#include "gps_acq_assist.h"
#include "gnss_sdr_flags.h"
#include <gtest/gtest.h>
#include <fstream>
#include <iostream>
@ -36,7 +37,6 @@ using namespace google;
DECLARE_string(log_dir);
#endif
#else
#include "gnss_sdr_flags.h"
#include <absl/flags/flag.h>
#include <absl/flags/parse.h>
#include <absl/log/flags.h>
@ -44,7 +44,6 @@ DECLARE_string(log_dir);
#include <absl/log/log.h>
#include <absl/log/log_sink.h>
#include <absl/log/log_sink_registry.h>
class TestLogSink : public absl::LogSink
{
public:

View File

@ -113,7 +113,7 @@ private:
#include "unit-tests/signal-processing-blocks/adapter/pass_through_test.cc"
#include "unit-tests/signal-processing-blocks/libs/item_type_helpers_test.cc"
#include "unit-tests/signal-processing-blocks/osnma/gnss_crypto_test.cc"
#include "unit-tests/signal-processing-blocks/osnma/osnma_msg_receiver_test.cc"
// #include "unit-tests/signal-processing-blocks/osnma/osnma_msg_receiver_test.cc"
#include "unit-tests/signal-processing-blocks/pvt/geohash_test.cc"
#include "unit-tests/signal-processing-blocks/pvt/nmea_printer_test.cc"
#include "unit-tests/signal-processing-blocks/pvt/rinex_printer_test.cc"

View File

@ -1,192 +1,115 @@
#include <gtest/gtest.h>
#include "gnss_crypto.h"
#include <gtest/gtest.h>
class GnssCryptoTest : public ::testing::Test
{
};
TEST(GnssCryptoTest, VerifySignature) {
// "../data/OSNMA_PublicKey_20240115100000_newPKID_1.pem"
std::unique_ptr<Gnss_Crypto> d_crypto = std::make_unique<Gnss_Crypto>();
// RG example - import crt certificate - result: FAIL
std::vector<uint8_t> message = {0x82, 0x10, 0x49, 0x22, 0x04, 0xE0, 0x60, 0x61, 0x0B, 0xDF, 0x26, 0xD7, 0x7B, 0x5B, 0xF8, 0xC9, 0xCB, 0xFC, 0xF7, 0x04, 0x22, 0x08, 0x14, 0x75, 0xFD, 0x44, 0x5D, 0xF0, 0xFF};
std::vector<uint8_t> signature = {0xF8, 0xCD, 0x88, 0x29, 0x9F, 0xA4, 0x60, 0x58, 0x00, 0x20, 0x7B, 0xFE, 0xBE, 0xAC, 0x55, 0x02, 0x40, 0x53, 0xF3, 0x0F, 0x7C, 0x69, 0xB3, 0x5C, 0x15, 0xE6, 0x08, 0x00, 0xAC, 0x3B, 0x6F, 0xE3, 0xED, 0x06, 0x39, 0x95, 0x2F, 0x7B, 0x02, 0x8D, 0x86, 0x86, 0x74, 0x45, 0x96, 0x1F, 0xFE, 0x94, 0xFB, 0x22, 0x6B, 0xFF, 0x70, 0x06, 0xE0, 0xC4, 0x51, 0xEE, 0x3F, 0x87, 0x28, 0xC1, 0x77, 0xFB};
std::vector<uint8_t> publicKey { // PEM format - 1000 bits
0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x50, 0x55, 0x42, 0x4C, 0x49, 0x43, 0x20, 0x4B, 0x45, 0x59, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A,
0x4D, 0x46, 0x6B, 0x77, 0x45, 0x77, 0x59, 0x48, 0x4B, 0x6F, 0x5A, 0x49, 0x7A, 0x6A, 0x30, 0x43, 0x41, 0x51, 0x59, 0x49, 0x4B, 0x6F, 0x5A, 0x49,
0x7A, 0x6A, 0x30, 0x44, 0x41, 0x51, 0x63, 0x44, 0x51, 0x67, 0x41, 0x45, 0x41, 0x37, 0x4C, 0x4F, 0x5A, 0x4C, 0x77, 0x67, 0x65, 0x39, 0x32, 0x4C, 0x78, 0x4E, 0x2B, 0x46, 0x6B, 0x59, 0x66, 0x38, 0x74, 0x6F, 0x59, 0x79, 0x44, 0x57, 0x50, 0x2F, 0x0A, 0x6F, 0x4A, 0x46, 0x42, 0x44, 0x38, 0x46, 0x59, 0x2B, 0x37,
0x64, 0x35, 0x67, 0x4F, 0x71, 0x49, 0x61, 0x45, 0x32, 0x52, 0x6A, 0x50, 0x41, 0x6E, 0x4B, 0x49, 0x36, 0x38, 0x73, 0x2F, 0x4F, 0x4B, 0x2F, 0x48, 0x50, 0x67, 0x6F, 0x4C, 0x6B, 0x4F, 0x32, 0x69, 0x6A, 0x51, 0x38, 0x78, 0x41, 0x5A, 0x79, 0x44, 0x64, 0x50, 0x42, 0x31, 0x64, 0x48, 0x53, 0x51, 0x3D, 0x3D,
0x0A,
0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x50, 0x55, 0x42, 0x4C, 0x49, 0x43, 0x20, 0x4B, 0x45, 0x59, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A } ;
// own ECDSA-P256 key and message generated and signed and verified successfully with openssl
// std::vector<uint8_t> message{0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x77, 0x6F, 0x72, 0x6C, 0x64, 0x0A }; // Hello world con 0x0A al final. Raw message (unhashed)
// std::vector<uint8_t> signature{0x30, 0x45, 0x02, 0x21, 0x00, 0xFB, 0xE6, 0x09, 0x74, 0x5C, 0x12, 0xE8, 0x2C, 0x0C, 0xC9, 0x7A, 0x8E, 0x13, 0x88, 0x87, 0xDA, 0xBF, 0x08, 0x43, 0xF8, 0xC8, 0x93, 0x16, 0x5A,
// 0x0F, 0x7A, 0xA4, 0xBF, 0x4A, 0xE1, 0xE1, 0xDB, 0x02, 0x20, 0x6B, 0xCB, 0x2F, 0x80, 0x69, 0xBB, 0xDE, 0xC9, 0x11, 0x1D, 0x51, 0x2B, 0x9F, 0x61, 0xA0, 0xC1, 0x29, 0xD1, 0x0B,
// 0x58, 0x09, 0x82, 0x58, 0xFC, 0x9E, 0x00, 0xC7, 0xEE, 0xA5, 0xB9, 0xB2, 0x56}; // Hello world hashed and then encrypted with PrK
// raw r and s values
// std::vector<uint8_t> signature = {
// 0x00, 0xFB, 0xE6, 0x09, 0x74, 0x5C, 0x12, 0xE8, 0x2C, 0x0C, 0xC9, 0x7A, 0x8E, 0x13, 0x88, 0x87, 0xDA, 0xBF, 0x08, 0x43, 0xF8,
// 0xC8, 0x93, 0x16, 0x5A, 0x0F, 0x7A, 0xA4, 0xBF, 0x4A, 0xE1, 0xE1, 0xDB, 0x02, 0x20, 0x6B, 0xCB, 0x2F, 0x80, 0x69, 0xBB, 0xDE,
// 0xC9, 0x11, 0x1D, 0x51, 0x2B, 0x9F, 0x61, 0xA0, 0xC1, 0x29, 0xD1, 0x0B, 0x58, 0x09, 0x82, 0x58, 0xFC, 0x9E, 0x00, 0xC7, 0xEE,
// 0xA5, 0xB9, 0xB2, 0x56 };
// std::vector<uint8_t> publicKey{// PK associated to the PrK, in der format ---test
// 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x4A, 0xF3,
// 0xEE, 0x3A, 0x94, 0x25, 0x25, 0x3D, 0x55, 0xC2, 0x5A, 0xC2, 0x2D, 0xCF, 0x14, 0x4D, 0x39, 0x0D, 0xB1, 0xFC, 0x7F, 0x31, 0x5A, 0x2A, 0x19, 0xAE, 0x4E, 0xD6, 0xCB, 0xA6, 0x59,
// 0xD6, 0x99, 0x7C, 0xE8, 0xBD, 0x1F, 0x43, 0x34, 0x1C, 0x59, 0xD9, 0xD9, 0xCA, 0xC3, 0xEE, 0x58, 0xE5, 0xEA, 0xD3, 0x55, 0x44, 0xEA, 0x89, 0x71, 0x65, 0xD0, 0x92, 0x72, 0xA2,
// 0xC8, 0x3C, 0x87, 0x5D };
// std::vector<uint8_t> publicKey{ // PK associated to the PrK, in pem format
// 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x50, 0x55, 0x42, 0x4C, 0x49, 0x43, 0x20, 0x4B, 0x45, 0x59, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A,
//
// 0x4D, 0x46,
// 0x6B, 0x77, 0x45, 0x77, 0x59, 0x48, 0x4B, 0x6F, 0x5A, 0x49, 0x7A, 0x6A, 0x30, 0x43, 0x41, 0x51, 0x59, 0x49, 0x4B, 0x6F, 0x5A, 0x49, 0x7A, 0x6A, 0x30, 0x44, 0x41, 0x51, 0x63,
// 0x44, 0x51, 0x67, 0x41, 0x45, 0x53, 0x76, 0x50, 0x75, 0x4F, 0x70, 0x51, 0x6C, 0x4A, 0x54, 0x31, 0x56, 0x77, 0x6C, 0x72, 0x43, 0x4C, 0x63, 0x38, 0x55, 0x54, 0x54, 0x6B, 0x4E,
// 0x73, 0x66, 0x78, 0x2F, 0x0A, 0x4D, 0x56, 0x6F, 0x71, 0x47, 0x61, 0x35, 0x4F, 0x31, 0x73, 0x75, 0x6D, 0x57, 0x64, 0x61, 0x5A, 0x66, 0x4F, 0x69, 0x39, 0x48, 0x30, 0x4D, 0x30,
// 0x48, 0x46, 0x6E, 0x5A, 0x32, 0x63, 0x72, 0x44, 0x37, 0x6C, 0x6A, 0x6C, 0x36, 0x74, 0x4E, 0x56, 0x52, 0x4F, 0x71, 0x4A, 0x63, 0x57, 0x58, 0x51, 0x6B, 0x6E, 0x4B, 0x69, 0x79,
// 0x44, 0x79, 0x48, 0x58, 0x51, 0x3D, 0x3D, 0x0A,
//
// 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x50, 0x55, 0x42, 0x4C, 0x49, 0x43, 0x20, 0x4B, 0x45, 0x59, 0x2D, 0x2D,
// 0x2D, 0x2D, 0x2D, 0x0A };
// own key - GnuTLS error: The curve is unsupported... x192 EC unsupported??
// std::vector<uint8_t> message = {0x68, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x77, 0x6F, 0x72, 0x6C, 0x64 }; // hello world
// std::vector<uint8_t> signature = {0x30, 0x34, 0x02, 0x18, 0x4F, 0xAC, 0x9C, 0x5A, 0x44, 0xCF, 0xFD, 0x42, 0x6A, 0x58, 0x97, 0xA4, 0x94, 0x53, 0x2C, 0x79, 0xD1, 0x7B, 0x8B, 0xF9, 0x93, 0x03, 0xA2, 0xAF, 0x02, 0x18, 0x46, 0xF2, 0xF3, 0xCF, 0x9A, 0x23, 0x39, 0xB4, 0x25, 0x11, 0x89, 0x9A, 0x44, 0x7E, 0x2F, 0xB1, 0xE1, 0x58, 0xAF, 0xCE, 0xC1,0xB4, 0xA1, 0x38 };
// std::vector<uint8_t> publicKey = {
// 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x50, 0x55, 0x42, 0x4C, 0x49, 0x43, 0x20, 0x4B, 0x45, 0x59, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x45, 0x6B, 0x77, 0x45, 0x77, 0x59, 0x48, 0x4B, 0x6F, 0x5A, 0x49, 0x7A, 0x6A, 0x30, 0x43, 0x41, 0x51, 0x59, 0x49, 0x4B, 0x6F, 0x5A, 0x49,
// 0x7A, 0x6A, 0x30, 0x44, 0x41, 0x51, 0x49, 0x44, 0x4D, 0x67, 0x41, 0x45, 0x51, 0x55, 0x61, 0x30, 0x6C, 0x38, 0x4D, 0x35, 0x76, 0x50, 0x58, 0x2B, 0x74, 0x4A, 0x76, 0x63, 0x4C, 0x2B, 0x45, 0x45, 0x4C, 0x34, 0x6E, 0x71, 0x79, 0x75, 0x53, 0x43, 0x0A, 0x4D, 0x4E, 0x46, 0x4A, 0x64, 0x43, 0x5A, 0x62, 0x62, 0x58,
// 0x35, 0x70, 0x4D, 0x36, 0x69, 0x4C, 0x52, 0x53, 0x30, 0x43, 0x51, 0x59, 0x45, 0x67, 0x56, 0x47, 0x51, 0x6B, 0x65, 0x75, 0x74, 0x74, 0x35, 0x78, 0x2F, 0x45, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x50, 0x55, 0x42, 0x4C, 0x49, 0x43, 0x20, 0x4B, 0x45, 0x59, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D,
// 0x0A };
// std::vector<uint8_t> ecparam = {
// 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x45, 0x43, 0x20, 0x50, 0x41, 0x52, 0x41, 0x4D, 0x45, 0x54, 0x45, 0x52, 0x53, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x42, 0x67, 0x67, 0x71, 0x68, 0x6B, 0x6A, 0x4F, 0x50, 0x51, 0x4D, 0x42, 0x41, 0x67, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D,
// 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x45, 0x43, 0x20, 0x50, 0x41, 0x52, 0x41, 0x4D, 0x45, 0x54, 0x45, 0x52, 0x53, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A };
d_crypto->set_public_key(publicKey);
bool result = d_crypto->verify_signature(message, signature);
ASSERT_TRUE(result);
//TEST(GnssCryptoTest, sha256Test)
//{
// std::unique_ptr<Gnss_Crypto> d_crypto;
//
// auto str = "Hello World!";
// std::vector<uint8_t> input (str, str + strlen(str));
//
// auto expectedOutputStr = "86933b0b147ac4c010266b99004158fa17937db89a03dd7bb2ca5ef7f43c325a";
// std::vector<uint8_t> expectedOutput(expectedOutputStr, expectedOutputStr + strlen(expectedOutputStr));
//
// std::vector<uint8_t> computedOutput = d_crypto->computeSHA256(input);
//
// ASSERT_TRUE(computedOutput == expectedOutput
}
TEST(GnssCryptoTest,VerifyPubKeyImport)
TEST(GnssCryptoTest, TestComputeSHA_256)
{
std::unique_ptr<Gnss_Crypto> d_crypto = std::make_unique<Gnss_Crypto>();
std::vector<uint8_t> message{0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x77, 0x6F, 0x72, 0x6C, 0x64, 0x0A}; // Hello world
std::vector<uint8_t> expected_output = {
0x18, 0x94, 0xA1, 0x9C, 0x85, 0xBA, 0x15, 0x3A, 0xCB, 0xF7,
0x43, 0xAC, 0x4E, 0x43, 0xFC, 0x00, 0x4C, 0x89, 0x16, 0x04, 0xB2,
0x6F, 0x8C, 0x69, 0xE1, 0xE8, 0x3E, 0xA2, 0xAF, 0xC7, 0xC4, 0x8F};
std::vector<uint8_t> output = d_crypto->computeSHA256(message);
ASSERT_EQ(expected_output, output);
}
TEST(GnssCryptoTest, TestComputeSHA3_256)
{
std::unique_ptr<Gnss_Crypto> d_crypto = std::make_unique<Gnss_Crypto>();
std::vector<uint8_t> message{0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x77, 0x6F, 0x72, 0x6C, 0x64, 0x0A}; // Hello world
std::vector<uint8_t> expected_output = {
0xCC, 0xB8, 0xF9, 0x23, 0x5F, 0x4A, 0x93, 0x2C, 0xA0, 0xAB,
0xBB, 0x2C, 0x24, 0x36, 0x72, 0x5E, 0x2E, 0x8D, 0xC7, 0x5B,
0x99, 0xE7, 0xF6, 0xC4, 0x50, 0x5B, 0x2A, 0x93, 0x6E, 0xB6, 0x3B, 0x3F};
std::vector<uint8_t> output = d_crypto->computeSHA3_256(message);
ASSERT_EQ(expected_output, output);
}
TEST(GnssCryptoTest, VerifySignature)
{
// "../data/OSNMA_PublicKey_20240115100000_newPKID_1.pem"
std::unique_ptr<Gnss_Crypto> d_crypto = std::make_unique<Gnss_Crypto>();
// RG example - key is raw 520 bits example shown
// std::vector<uint8_t> publicKey = { // base64 decoding error
// 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x50, 0x55, 0x42, 0x4C, 0x49, 0x43, 0x20, 0x4B, 0x45, 0x59, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A,
//
// 0x04, 0x03, 0xB2, 0xCE, 0x64, 0xBC, 0x20, 0x7B, 0xDD, 0x8B, 0xC4, 0xDF, 0x85, 0x91, 0x87, 0xFC,
// 0xB6, 0x86, 0x32, 0x0D, 0x63, 0xFF, 0xA0, 0x91, 0x41, 0x0F, 0xC1, 0x58, 0xFB, 0xB7, 0x79, 0x80,
// 0xEA, 0x88, 0x68, 0x4D, 0x91, 0x8C, 0xF0, 0x27, 0x28, 0x8E, 0xBC, 0xB3, 0xF3, 0x8A, 0xFC, 0x73,
// 0xE0, 0xA0, 0xB9, 0x0E, 0xDA, 0x28, 0xD0, 0xF3, 0x10, 0x19, 0xC8, 0x37, 0x4F, 0x07, 0x57, 0x47, 0x49,
//
// 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x50, 0x55, 0x42, 0x4C, 0x49, 0x43, 0x20, 0x4B, 0x45, 0x59, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A
//
// };
// RG example crt exported and convert PK.pem - key is raw 1000 bits ,..., why mismatch!? does key get truncated?
// std::vector<uint8_t> publicKey {
// 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x50, 0x55, 0x42, 0x4C, 0x49, 0x43, 0x20, 0x4B, 0x45, 0x59, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x46, 0x6B, 0x77, 0x45, 0x77, 0x59, 0x48, 0x4B, 0x6F, 0x5A, 0x49, 0x7A, 0x6A, 0x30, 0x43, 0x41, 0x51, 0x59, 0x49, 0x4B, 0x6F, 0x5A, 0x49,
// 0x7A, 0x6A, 0x30, 0x44, 0x41, 0x51, 0x63, 0x44, 0x51, 0x67, 0x41, 0x45, 0x41, 0x37, 0x4C, 0x4F, 0x5A, 0x4C, 0x77, 0x67, 0x65, 0x39, 0x32, 0x4C, 0x78, 0x4E, 0x2B, 0x46, 0x6B, 0x59, 0x66, 0x38, 0x74, 0x6F, 0x59, 0x79, 0x44, 0x57, 0x50, 0x2F, 0x0A, 0x6F, 0x4A, 0x46, 0x42, 0x44, 0x38, 0x46, 0x59, 0x2B, 0x37,
// 0x64, 0x35, 0x67, 0x4F, 0x71, 0x49, 0x61, 0x45, 0x32, 0x52, 0x6A, 0x50, 0x41, 0x6E, 0x4B, 0x49, 0x36, 0x38, 0x73, 0x2F, 0x4F, 0x4B, 0x2F, 0x48, 0x50, 0x67, 0x6F, 0x4C, 0x6B, 0x4F, 0x32, 0x69, 0x6A, 0x51, 0x38, 0x78, 0x41, 0x5A, 0x79, 0x44, 0x64, 0x50, 0x42, 0x31, 0x64, 0x48, 0x53, 0x51, 0x3D, 0x3D, 0x0A,
// 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x50, 0x55, 0x42, 0x4C, 0x49, 0x43, 0x20, 0x4B, 0x45, 0x59, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A } ;
// own ECDSA P 256 public key and own message generated (2024-02-19-Own-Key-ECDSA-openssl)
std::vector<uint8_t> publicKey{ // PEM
// RG example - import crt certificate - result: FAIL
std::vector<uint8_t> message = {0x82, 0x10, 0x49, 0x22, 0x04, 0xE0, 0x60, 0x61, 0x0B, 0xDF, 0x26, 0xD7, 0x7B, 0x5B, 0xF8, 0xC9, 0xCB, 0xFC, 0xF7, 0x04, 0x22, 0x08, 0x14, 0x75, 0xFD, 0x44, 0x5D, 0xF0, 0xFF};
std::vector<uint8_t> signature = {0xF8, 0xCD, 0x88, 0x29, 0x9F, 0xA4, 0x60, 0x58, 0x00, 0x20, 0x7B, 0xFE, 0xBE, 0xAC, 0x55, 0x02, 0x40, 0x53, 0xF3, 0x0F, 0x7C, 0x69, 0xB3, 0x5C, 0x15, 0xE6, 0x08, 0x00, 0xAC, 0x3B, 0x6F, 0xE3, 0xED, 0x06, 0x39, 0x95, 0x2F, 0x7B, 0x02, 0x8D, 0x86, 0x86, 0x74, 0x45, 0x96, 0x1F, 0xFE, 0x94, 0xFB, 0x22, 0x6B, 0xFF, 0x70, 0x06, 0xE0, 0xC4, 0x51, 0xEE, 0x3F, 0x87, 0x28, 0xC1, 0x77, 0xFB};
std::vector<uint8_t> publicKey{// PEM format - 1000 bits
0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x50, 0x55, 0x42, 0x4C, 0x49, 0x43, 0x20, 0x4B, 0x45, 0x59, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A,
0x4D, 0x46, 0x6B, 0x77, 0x45, 0x77, 0x59, 0x48, 0x4B, 0x6F, 0x5A, 0x49, 0x7A, 0x6A, 0x30, 0x43, 0x41, 0x51, 0x59, 0x49, 0x4B, 0x6F, 0x5A, 0x49,
0x7A, 0x6A, 0x30, 0x44, 0x41, 0x51, 0x63, 0x44, 0x51, 0x67, 0x41, 0x45, 0x41, 0x37, 0x4C, 0x4F, 0x5A, 0x4C, 0x77, 0x67, 0x65, 0x39, 0x32, 0x4C, 0x78, 0x4E, 0x2B, 0x46, 0x6B, 0x59, 0x66, 0x38, 0x74, 0x6F, 0x59, 0x79, 0x44, 0x57, 0x50, 0x2F, 0x0A, 0x6F, 0x4A, 0x46, 0x42, 0x44, 0x38, 0x46, 0x59, 0x2B, 0x37,
0x64, 0x35, 0x67, 0x4F, 0x71, 0x49, 0x61, 0x45, 0x32, 0x52, 0x6A, 0x50, 0x41, 0x6E, 0x4B, 0x49, 0x36, 0x38, 0x73, 0x2F, 0x4F, 0x4B, 0x2F, 0x48, 0x50, 0x67, 0x6F, 0x4C, 0x6B, 0x4F, 0x32, 0x69, 0x6A, 0x51, 0x38, 0x78, 0x41, 0x5A, 0x79, 0x44, 0x64, 0x50, 0x42, 0x31, 0x64, 0x48, 0x53, 0x51, 0x3D, 0x3D,
0x0A,
0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x50, 0x55, 0x42, 0x4C, 0x49, 0x43, 0x20, 0x4B, 0x45, 0x59, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A};
d_crypto->set_public_key(publicKey);
bool result = d_crypto->verify_signature(message, signature);
ASSERT_TRUE(result);
}
TEST(GnssCryptoTest, VerifyPubKeyImport)
{
std::unique_ptr<Gnss_Crypto> d_crypto = std::make_unique<Gnss_Crypto>();
std::vector<uint8_t> publicKey{// PEM
0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x50, 0x55, 0x42, 0x4C, 0x49, 0x43, 0x20, 0x4B, 0x45, 0x59, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A,
0x4D, 0x46,
0x6B, 0x77, 0x45, 0x77, 0x59, 0x48, 0x4B, 0x6F, 0x5A, 0x49, 0x7A, 0x6A, 0x30, 0x43, 0x41, 0x51, 0x59, 0x49, 0x4B, 0x6F, 0x5A, 0x49, 0x7A, 0x6A, 0x30, 0x44, 0x41, 0x51, 0x63,
0x44, 0x51, 0x67, 0x41, 0x45, 0x53, 0x76, 0x50, 0x75, 0x4F, 0x70, 0x51, 0x6C, 0x4A, 0x54, 0x31, 0x56, 0x77, 0x6C, 0x72, 0x43, 0x4C, 0x63, 0x38, 0x55, 0x54, 0x54, 0x6B, 0x4E,
0x73, 0x66, 0x78, 0x2F, 0x0A, 0x4D, 0x56, 0x6F, 0x71, 0x47, 0x61, 0x35, 0x4F, 0x31, 0x73, 0x75, 0x6D, 0x57, 0x64, 0x61, 0x5A, 0x66, 0x4F, 0x69, 0x39, 0x48, 0x30, 0x4D, 0x30,
0x48, 0x46, 0x6E, 0x5A, 0x32, 0x63, 0x72, 0x44, 0x37, 0x6C, 0x6A, 0x6C, 0x36, 0x74, 0x4E, 0x56, 0x52, 0x4F, 0x71, 0x4A, 0x63, 0x57, 0x58, 0x51, 0x6B, 0x6E, 0x4B, 0x69, 0x79,
0x44, 0x79, 0x48, 0x58, 0x51, 0x3D, 0x3D, 0x0A,
0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x50, 0x55, 0x42, 0x4C, 0x49, 0x43, 0x20, 0x4B, 0x45, 0x59, 0x2D, 0x2D,
0x2D, 0x2D, 0x2D, 0x0A };
0x2D, 0x2D, 0x2D, 0x0A};
d_crypto->set_public_key(publicKey);
ASSERT_TRUE(d_crypto->have_public_key());
// std::vector<uint8_t> publicKey = { // DER format
// 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x50, 0x55, 0x42, 0x4C, 0x49, 0x43, 0x20, 0x4B, 0x45, 0x59, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x46, 0x6B, 0x77, 0x45, 0x77, 0x59, 0x48, 0x4B, 0x6F, 0x5A, 0x49, 0x7A, 0x6A, 0x30, 0x43, 0x41, 0x51, 0x59, 0x49, 0x4B, 0x6F, 0x5A, 0x49,
// 0x7A, 0x6A, 0x30, 0x44, 0x41, 0x51, 0x63, 0x44, 0x51, 0x67, 0x41, 0x45, 0x41, 0x37, 0x4C, 0x4F, 0x5A, 0x4C, 0x77, 0x67, 0x65, 0x39, 0x32, 0x4C, 0x78, 0x4E, 0x2B, 0x46, 0x6B, 0x59, 0x66, 0x38, 0x74, 0x6F, 0x59, 0x79, 0x44, 0x57, 0x50, 0x2F, 0x0A, 0x6F, 0x4A, 0x46, 0x42, 0x44, 0x38, 0x46, 0x59, 0x2B, 0x37,
// 0x64, 0x35, 0x67, 0x4F, 0x71, 0x49, 0x61, 0x45, 0x32, 0x52, 0x6A, 0x50, 0x41, 0x6E, 0x4B, 0x49, 0x36, 0x38, 0x73, 0x2F, 0x4F, 0x4B, 0x2F, 0x48, 0x50, 0x67, 0x6F, 0x4C, 0x6B, 0x4F, 0x32, 0x69, 0x6A, 0x51, 0x38, 0x78, 0x41, 0x5A, 0x79, 0x44, 0x64, 0x50, 0x42, 0x31, 0x64, 0x48, 0x53, 0x51, 0x3D, 0x3D, 0x0A,
// 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x50, 0x55, 0x42, 0x4C, 0x49, 0x43, 0x20, 0x4B, 0x45, 0x59, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x30, 0x82, 0x02, 0x6C, 0x30, 0x82, 0x02, 0x12, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x47, 0xC4, 0xF1, 0x43, 0xC3, 0xFA, 0x61, 0xA5, 0x29, 0x4E, 0x63,
// 0xD5, 0x57, 0x2B, 0x01, 0x62, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x37, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x45, 0x53, 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x05, 0x45, 0x55, 0x53, 0x50, 0x41, 0x31, 0x18, 0x30,
// 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0F, 0x45, 0x55, 0x53, 0x50, 0x41, 0x20, 0x4F, 0x53, 0x4E, 0x4D, 0x41, 0x20, 0x49, 0x43, 0x41, 0x30, 0x1E, 0x17, 0x0D, 0x32, 0x33, 0x30, 0x37, 0x32, 0x30, 0x31, 0x31, 0x32, 0x32, 0x33, 0x30, 0x5A, 0x17, 0x0D, 0x32, 0x35, 0x30, 0x38, 0x30, 0x38, 0x31, 0x31, 0x33,
// 0x33, 0x30, 0x30, 0x5A, 0x30, 0x3A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x45, 0x53, 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x05, 0x45, 0x55, 0x53, 0x50, 0x41, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x12, 0x45, 0x55, 0x53, 0x50, 0x41,
// 0x20, 0x4F, 0x53, 0x4E, 0x4D, 0x41, 0x20, 0x45, 0x45, 0x20, 0x50, 0x4B, 0x52, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x03, 0xB2, 0xCE, 0x64, 0xBC, 0x20, 0x7B, 0xDD, 0x8B, 0xC4, 0xDF,
// 0x85, 0x91, 0x87, 0xFC, 0xB6, 0x86, 0x32, 0x0D, 0x63, 0xFF, 0xA0, 0x91, 0x41, 0x0F, 0xC1, 0x58, 0xFB, 0xB7, 0x79, 0x80, 0xEA, 0x88, 0x68, 0x4D, 0x91, 0x8C, 0xF0, 0x27, 0x28, 0x8E, 0xBC, 0xB3, 0xF3, 0x8A, 0xFC, 0x73, 0xE0, 0xA0, 0xB9, 0x0E, 0xDA, 0x28, 0xD0, 0xF3, 0x10, 0x19, 0xC8, 0x37, 0x4F, 0x07, 0x57,
// 0x47, 0x49, 0xA3, 0x81, 0xFC, 0x30, 0x81, 0xF9, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0x6A, 0x22, 0x16, 0x58, 0x9B, 0x23, 0xC9, 0x43, 0x41, 0x3C, 0xB6, 0xF8, 0x9D, 0x93, 0x0F, 0xE0, 0xFE, 0x6A, 0x3C, 0x54, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80,
// 0x14, 0x20, 0xC0, 0x54, 0x85, 0xAF, 0x82, 0xAE, 0x96, 0x3C, 0xBC, 0xDF, 0xC1, 0xB9, 0x05, 0xDE, 0xD7, 0x46, 0x72, 0x32, 0xA3, 0x30, 0x63, 0x06, 0x03, 0x55, 0x1D, 0x20, 0x04, 0x5C, 0x30, 0x5A, 0x30, 0x4E, 0x06, 0x0B, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0xD5, 0x11, 0x01, 0x01, 0x01, 0x30, 0x3F, 0x30, 0x3D,
// 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x01, 0x16, 0x31, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3A, 0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E, 0x67, 0x73, 0x63, 0x2D, 0x65, 0x75, 0x72, 0x6F, 0x70, 0x61, 0x2E, 0x65, 0x75, 0x2F, 0x67, 0x73, 0x63, 0x2D, 0x70, 0x72, 0x6F, 0x64, 0x75, 0x63, 0x74, 0x73, 0x2F,
// 0x4F, 0x53, 0x4E, 0x4D, 0x41, 0x2F, 0x50, 0x4B, 0x49, 0x2F, 0x30, 0x08, 0x06, 0x06, 0x04, 0x00, 0x8F, 0x7A, 0x01, 0x02, 0x30, 0x42, 0x06, 0x03, 0x55, 0x1D, 0x1F, 0x04, 0x3B, 0x30, 0x39, 0x30, 0x37, 0xA0, 0x35, 0xA0, 0x33, 0x86, 0x31, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3A, 0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E,
// 0x67, 0x73, 0x63, 0x2D, 0x65, 0x75, 0x72, 0x6F, 0x70, 0x61, 0x2E, 0x65, 0x75, 0x2F, 0x67, 0x73, 0x63, 0x2D, 0x70, 0x72, 0x6F, 0x64, 0x75, 0x63, 0x74, 0x73, 0x2F, 0x4F, 0x53, 0x4E, 0x4D, 0x41, 0x2F, 0x50, 0x4B, 0x49, 0x2F, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x01, 0x01, 0xFF, 0x04, 0x04, 0x03, 0x02,
// 0x07, 0x80, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x21, 0x00, 0xE9, 0xBB, 0x90, 0x8E, 0xE5, 0x0C, 0xF3, 0xDA, 0x57, 0x71, 0xE3, 0xD0, 0xD2, 0xEA, 0xAC, 0x1B, 0x00, 0xF3, 0x51, 0xE9, 0xD8, 0xBB, 0x0A, 0xB2, 0x4C, 0x8A, 0x65, 0x52, 0x79,
// 0x9F, 0x43, 0xF6, 0x02, 0x20, 0x10, 0x65, 0x2F, 0x6A, 0xF8, 0x26, 0x20, 0x42, 0xFF, 0x09, 0x6B, 0xD0, 0x8D, 0x0B, 0x75, 0x15, 0x24, 0xBF, 0xE4, 0xFE, 0x60, 0xC3, 0x6E, 0x2D, 0x31, 0x32, 0xED, 0x65, 0x6C, 0x5C, 0x8B, 0x14 };
// std::vector<uint8_t> publicKey= { // PEM format
// 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x50, 0x55, 0x42, 0x4C, 0x49, 0x43, 0x20, 0x4B, 0x45, 0x59, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x46, 0x6B, 0x77, 0x45, 0x77, 0x59, 0x48, 0x4B, 0x6F, 0x5A, 0x49, 0x7A, 0x6A, 0x30, 0x43, 0x41, 0x51, 0x59, 0x49, 0x4B, 0x6F, 0x5A, 0x49,
// 0x7A, 0x6A, 0x30, 0x44, 0x41, 0x51, 0x63, 0x44, 0x51, 0x67, 0x41, 0x45, 0x41, 0x37, 0x4C, 0x4F, 0x5A, 0x4C, 0x77, 0x67, 0x65, 0x39, 0x32, 0x4C, 0x78, 0x4E, 0x2B, 0x46, 0x6B, 0x59, 0x66, 0x38, 0x74, 0x6F, 0x59, 0x79, 0x44, 0x57, 0x50, 0x2F, 0x0A, 0x6F, 0x4A, 0x46, 0x42, 0x44, 0x38, 0x46, 0x59, 0x2B, 0x37,
// 0x64, 0x35, 0x67, 0x4F, 0x71, 0x49, 0x61, 0x45, 0x32, 0x52, 0x6A, 0x50, 0x41, 0x6E, 0x4B, 0x49, 0x36, 0x38, 0x73, 0x2F, 0x4F, 0x4B, 0x2F, 0x48, 0x50, 0x67, 0x6F, 0x4C, 0x6B, 0x4F, 0x32, 0x69, 0x6A, 0x51, 0x38, 0x78, 0x41, 0x5A, 0x79, 0x44, 0x64, 0x50, 0x42, 0x31, 0x64, 0x48, 0x53, 0x51, 0x3D, 0x3D, 0x0A,
// 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x50, 0x55, 0x42, 0x4C, 0x49, 0x43, 0x20, 0x4B, 0x45, 0x59, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A };
}
// Unit test for computeHMAC_SHA_256 function.
TEST(GnssCryptoTest, TestComputeHMACSHA256) { // key and message generated with openssl
TEST(GnssCryptoTest, TestComputeHMACSHA256)
{
std::unique_ptr<Gnss_Crypto> d_crypto = std::make_unique<Gnss_Crypto>();
std::vector<uint8_t> key = {
0x24, 0x24, 0x3B, 0x76, 0xF9, 0x14, 0xB1, 0xA7,
0x7D, 0x48, 0xE7, 0xF1, 0x48, 0x0C, 0xC2, 0x98,
0xEB, 0x62, 0x3E, 0x95, 0x6B, 0x2B, 0xCE, 0xA3,
0xB4, 0xD4, 0xDB, 0x31, 0xEE, 0x96, 0xAB, 0xFA };
0x24, 0x24, 0x3B, 0x76, 0xF9, 0x14, 0xB1, 0xA7,
0x7D, 0x48, 0xE7, 0xF1, 0x48, 0x0C, 0xC2, 0x98,
0xEB, 0x62, 0x3E, 0x95, 0x6B, 0x2B, 0xCE, 0xA3,
0xB4, 0xD4, 0xDB, 0x31, 0xEE, 0x96, 0xAB, 0xFA};
std::vector<uint8_t> message{0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x77, 0x6F, 0x72, 0x6C, 0x64, 0x0A }; // Hello world con 0x0A
std::vector<uint8_t> message{0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x77, 0x6F, 0x72, 0x6C, 0x64, 0x0A}; // Hello world con 0x0A
std::vector<uint8_t> expected_output = {
0xC3, 0x51, 0xF6, 0xFD, 0xDD, 0xC9, 0x8B, 0x41,
0xD6, 0xF4, 0x77, 0x6D, 0xAC, 0xE8, 0xE0, 0x14,
0xB2, 0x7A, 0xCC, 0x22, 0x00, 0xAA, 0xD2, 0x37,
0xD0, 0x79, 0x06, 0x12, 0x83, 0x40, 0xB7, 0xA6 };
0xC3, 0x51, 0xF6, 0xFD, 0xDD, 0xC9, 0x8B, 0x41,
0xD6, 0xF4, 0x77, 0x6D, 0xAC, 0xE8, 0xE0, 0x14,
0xB2, 0x7A, 0xCC, 0x22, 0x00, 0xAA, 0xD2, 0x37,
0xD0, 0x79, 0x06, 0x12, 0x83, 0x40, 0xB7, 0xA6};
std::vector<uint8_t> output = d_crypto->computeHMAC_SHA_256(key, message);
ASSERT_EQ(expected_output, output);
}
TEST(GnssCryptoTest, TestComputeHMACSHA256_m0) { // key and message generated from RG A.6.5.1
TEST(GnssCryptoTest, TestComputeHMACSHA256_m0)
{
// key and message generated from RG A.6.5.1
std::unique_ptr<Gnss_Crypto> d_crypto = std::make_unique<Gnss_Crypto>();
std::vector<uint8_t> key = { // RG K4 @ 345690
std::vector<uint8_t> key = {// RG K4 @ 345690
0x69, 0xC0, 0x0A, 0xA7, 0x36, 0x42, 0x37, 0xA6,
0x5E, 0xBF, 0x00, 0x6A, 0xD8, 0xDD, 0xBC, 0x73};
@ -207,15 +130,19 @@ TEST(GnssCryptoTest, TestComputeHMACSHA256_m0) { // key and message generated fr
ASSERT_EQ(expected_output, output);
}
TEST(GnssCryptoTest, TestComputeHMACSHA256_adkd4) { // key and message generated from RG A.6.5.2
TEST(GnssCryptoTest, TestComputeHMACSHA256_adkd4)
{
// key and message generated from RG A.6.5.2
std::unique_ptr<Gnss_Crypto> d_crypto = std::make_unique<Gnss_Crypto>();
std::vector<uint8_t> key = { // RG K4 @ 345690
std::vector<uint8_t> key = {// RG K4 @ 345690
0x69, 0xC0, 0x0A, 0xA7, 0x36, 0x42, 0x37, 0xA6,
0x5E, 0xBF, 0x00, 0x6A, 0xD8, 0xDD, 0xBC, 0x73};
std::vector<uint8_t> message{
0x02, 0x02, 0x4E, 0x05, 0x46, 0x3C, 0x03, 0xBF,
0xFF, 0xFF, 0xFF, 0xC0, 0x00,0x00, 0x44, 0x92, 0x38,
0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x44, 0x92, 0x38,
0x22, 0x78, 0x97, 0xFD, 0xEF, 0xF9, 0x30, 0x40};
std::vector<uint8_t> expected_output = {
@ -223,10 +150,30 @@ TEST(GnssCryptoTest, TestComputeHMACSHA256_adkd4) { // key and message generated
0xE6, 0x3F, 0xB7, 0xF4, 0xF5, 0x4D, 0x44, 0xAB, 0xEE, 0x4D,
0xCE, 0xB9, 0x3D, 0xCF, 0x65, 0xCB, 0x3A, 0x5B, 0x81, 0x4A, 0x34, 0xE9};
std::vector<uint8_t> output = d_crypto->computeHMAC_SHA_256(key, message);
ASSERT_EQ(expected_output, output);
}
// TODO extend to HMAC-AES
TEST(GnssCryptoTest, TestComputeCMAC_AES)
{
// Tests vectors from https://datatracker.ietf.org/doc/html/rfc4493#appendix-A
std::unique_ptr<Gnss_Crypto> d_crypto = std::make_unique<Gnss_Crypto>();
std::vector<uint8_t> key = {
0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C};
std::vector<uint8_t> message{
0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96,
0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A};
std::vector<uint8_t> expected_output = {
0x07, 0x0A, 0x16, 0xB4, 0x6B, 0x4D, 0x41, 0x44,
0xF7, 0x9B, 0xDD, 0x9D, 0xD0, 0x4A, 0x28, 0x7C};
std::vector<uint8_t> output = d_crypto->computeCMAC_AES(key, message);
ASSERT_EQ(expected_output, output);
}

View File

@ -2,7 +2,6 @@
#include <bitset>
#include <filesystem>
#include <fstream>
#include <logging.h>
#include <osnma_msg_receiver.h>
#include <vector>
@ -25,26 +24,26 @@ protected:
std::string page_even;
OSNMA_msg osnma_msg{};
std::array<int8_t, 15> nma_position_filled;
uint32_t d_GST_SIS{}; // 16 AUG 2023 05 00 01
uint32_t d_GST_SIS{}; // 16 AUG 2023 05 00 01
uint32_t TOW{};
uint32_t WN{};
std::tm GST_START_EPOCH = {0, 0, 0, 22, 8 - 1, 1999 - 1900, 0}; // months start with 0 and years since 1900 in std::tm
const uint32_t LEAP_SECONDS = 0;//13 + 5;
std::tm GST_START_EPOCH = {0, 0, 0, 22, 8 - 1, 1999 - 1900, 0}; // months start with 0 and years since 1900 in std::tm
const uint32_t LEAP_SECONDS = 0; // 13 + 5;
void set_time(std::tm& input);
// std::string log_name {"CONFIG1-2023-08-23-PKID1-OSNMA"};
std::string log_name {"CONFIG2-2023-07-27-PKID2-MT2-OSNMA"};
void initializeGoogleLog();
// std::string log_name {"CONFIG1-2023-08-23-PKID1-OSNMA"};
std::string log_name{"CONFIG2-2023-07-27-PKID2-MT2-OSNMA"};
// void initializeGoogleLog();
void SetUp() override
{
flag_CRC_test = false; // TODO what for?
flag_CRC_test = false; // TODO what for?
page_even = "";
// std::tm input_time = {0, 0, 5, 16, 8 - 1, 2023 - 1900, 0};
// std::tm input_time = {0, 0, 5, 16, 8 - 1, 2023 - 1900, 0};
std::tm input_time = {0, 0, 0, 27, 7 - 1, 2023 - 1900, 0};
set_time(input_time);
// std::string pemFilePath = "/home/cgm/CLionProjects/osnma/data/OSNMA_PublicKey_20230803105952_newPKID_1.pem";
// std::string merkleFilePath = "/home/cgm/CLionProjects/osnma/data/OSNMA_MerkleTree_20230803105953_newPKID_1.xml";
// std::string pemFilePath = "/home/cgm/CLionProjects/osnma/data/OSNMA_PublicKey_20230803105952_newPKID_1.pem";
// std::string merkleFilePath = "/home/cgm/CLionProjects/osnma/data/OSNMA_MerkleTree_20230803105953_newPKID_1.xml";
std::string pemFilePath = "/home/cgm/CLionProjects/osnma/data/OSNMA_PublicKey_20230720113300_newPKID_2.pem";
std::string merkleFilePath = "/home/cgm/CLionProjects/osnma/data/OSNMA_MerkleTree_20230720113300_newPKID_2.xml";
osnma = osnma_msg_receiver_make(pemFilePath, merkleFilePath);
@ -58,121 +57,120 @@ public:
};
TEST_F(OsnmaMsgReceiverTest, TeslaKeyVerification) {
TEST_F(OsnmaMsgReceiverTest, TeslaKeyVerification)
{
// Arrange
// ----------
osnma->d_tesla_key_verified = false;
osnma->d_osnma_data.d_dsm_kroot_message.kroot = {0x5B, 0xF8, 0xC9, 0xCB, 0xFC, 0xF7, 0x04, 0x22, 0x08, 0x14, 0x75, 0xFD, 0x44, 0x5D, 0xF0, 0xFF}; // Kroot, TOW 345570 GST_0 - 30
osnma->d_osnma_data.d_dsm_kroot_message.ks = 4; // TABLE 10 --> 128 bits
osnma->d_osnma_data.d_dsm_kroot_message.kroot = {0x5B, 0xF8, 0xC9, 0xCB, 0xFC, 0xF7, 0x04, 0x22, 0x08, 0x14, 0x75, 0xFD, 0x44, 0x5D, 0xF0, 0xFF}; // Kroot, TOW 345570 GST_0 - 30
osnma->d_osnma_data.d_dsm_kroot_message.ks = 4; // TABLE 10 --> 128 bits
osnma->d_osnma_data.d_dsm_kroot_message.alpha = 0x610BDF26D77B;
// local_time_verification would do this operation. TODO - eliminate duplication.
osnma->d_GST_SIS = (1248 & 0x00000FFF) << 20 | (345630 & 0x000FFFFF);
osnma->d_GST_0 = ((1248 & 0x00000FFF) << 20 | (345600 & 0x000FFFFF)); // applicable time (GST_Kroot + 30)
osnma->d_receiver_time = osnma->d_GST_0 + 30 * std::floor((osnma->d_GST_SIS - osnma->d_GST_0) / 30); // Eq. 3 R.G.//345630;
osnma->d_GST_0 = ((1248 & 0x00000FFF) << 20 | (345600 & 0x000FFFFF)); // applicable time (GST_Kroot + 30)
osnma->d_receiver_time = osnma->d_GST_0 + 30 * std::floor((osnma->d_GST_SIS - osnma->d_GST_0) / 30); // Eq. 3 R.G.//345630;
osnma->d_tesla_keys.insert((std::pair<uint32_t, std::vector<uint8_t>>(345600,{0xEF, 0xF9, 0x99, 0x04, 0x0E, 0x19, 0xB5, 0x70, 0x83, 0x50, 0x60, 0xBE, 0xBD, 0x23, 0xED, 0x92}))); // K1, not needed, just for reference.
std::vector<uint8_t> key = {0x2D, 0xC3, 0xA3, 0xCD, 0xB1, 0x17, 0xFA, 0xAD, 0xB8, 0x3B, 0x5F, 0x0B, 0x6F, 0xEA, 0x88, 0xEB}; // K2
osnma->d_tesla_keys.insert((std::pair<uint32_t, std::vector<uint8_t>>(345600, {0xEF, 0xF9, 0x99, 0x04, 0x0E, 0x19, 0xB5, 0x70, 0x83, 0x50, 0x60, 0xBE, 0xBD, 0x23, 0xED, 0x92}))); // K1, not needed, just for reference.
std::vector<uint8_t> key = {0x2D, 0xC3, 0xA3, 0xCD, 0xB1, 0x17, 0xFA, 0xAD, 0xB8, 0x3B, 0x5F, 0x0B, 0x6F, 0xEA, 0x88, 0xEB}; // K2
uint32_t TOW = 345630;
// Act
// ----------
bool result = osnma->verify_tesla_key(key, TOW);
// Assert
// ----------
ASSERT_TRUE(result);
}
TEST_F(OsnmaMsgReceiverTest, OsnmaTestVectorsSimulation)
{
initializeGoogleLog();
// initializeGoogleLog();
// Arrange
// ----------
// std::vector<TestVector> testVectors = readTestVectorsFromFile("/home/cgm/CLionProjects/osnma/data/16_AUG_2023_GST_05_00_01.csv");
// std::vector<TestVector> testVectors = readTestVectorsFromFile("/home/cgm/CLionProjects/osnma/data/16_AUG_2023_GST_05_00_01.csv");
std::vector<TestVector> testVectors = readTestVectorsFromFile("/home/cgm/CLionProjects/osnma/data/27_JUL_2023_GST_00_00_01.csv");
if (testVectors.empty()){
if (testVectors.empty())
{
ASSERT_TRUE(false);
}
bool end_of_hex_stream{false};
int offset_byte{0};
int byte_index{0}; // index containing the last byte position of the hex stream that was retrieved. Takes advantage that all TVs have same size
const int SIZE_PAGE_BYTES{240/8}; // total bytes of a page
const int SIZE_SUBFRAME_PAGES{15}; // number of pages of a subframe
const int SIZE_SUBFRAME_BYTES{SIZE_PAGE_BYTES*SIZE_SUBFRAME_PAGES}; // total bytes of a subframe
const int DURATION_SUBFRAME{30}; // duration of a subframe, in seconds
int byte_index{0}; // index containing the last byte position of the hex stream that was retrieved. Takes advantage that all TVs have same size
const int SIZE_PAGE_BYTES{240 / 8}; // total bytes of a page
const int SIZE_SUBFRAME_PAGES{15}; // number of pages of a subframe
const int SIZE_SUBFRAME_BYTES{SIZE_PAGE_BYTES * SIZE_SUBFRAME_PAGES}; // total bytes of a subframe
const int DURATION_SUBFRAME{30}; // duration of a subframe, in seconds
const int DUMMY_PAGE{63};
bool flag_dummy_page{false};
std::cout << "OsnmaTestVectorsSimulation:" << " d_GST_SIS= " << d_GST_SIS
<< ", TOW=" << TOW
<< ", WN=" << WN << std::endl;
std::cout << "OsnmaTestVectorsSimulation:"
<< " d_GST_SIS= " << d_GST_SIS
<< ", TOW=" << TOW
<< ", WN=" << WN << std::endl;
// Act
// ----------
// loop over all bytes of data. Note: all TestVectors have same amount of data.
while (end_of_hex_stream == false){
while (end_of_hex_stream == false)
{
// loop over all SVs, extract a subframe
for(const TestVector& tv : testVectors) { // loop over all SVs, extract a subframe
std::cout << "OsnmaTestVectorsSimulation: SVID (PRN_a) "<< tv.svId << std::endl;
for (const TestVector& tv : testVectors)
{ // loop over all SVs, extract a subframe
std::cout << "OsnmaTestVectorsSimulation: SVID (PRN_a) " << tv.svId << std::endl;
auto osnmaMsg_sptr = std::make_shared<OSNMA_msg>();
std::array<uint8_t, 15> hkroot{};
std::array<uint32_t, 15> mack{};
byte_index = offset_byte; // reset byte_index to the offset position for the next test vector. Offset is updated at the end of each Subframe (every 30 s or 450 Bytes)
std::map<uint8_t, std::bitset<128>> words; // structure containing <WORD_NUMBER> and <EXTRACTED_BITS>
byte_index = offset_byte; // reset byte_index to the offset position for the next test vector. Offset is updated at the end of each Subframe (every 30 s or 450 Bytes)
std::map<uint8_t, std::bitset<128>> words; // structure containing <WORD_NUMBER> and <EXTRACTED_BITS>
for (int idx = 0; idx < SIZE_SUBFRAME_PAGES; ++idx) // extract all pages of a subframe
for (int idx = 0; idx < SIZE_SUBFRAME_PAGES; ++idx) // extract all pages of a subframe
{
// extract bytes of complete page (odd+even) -- extract SIZE_PAGE from tv.navBits, starting from byte_index
std::vector<uint8_t> page_bytes = extract_page_bytes(tv,byte_index,SIZE_PAGE_BYTES);
if(page_bytes.empty()){
std::cout<< "OsnmaTestVectorsSimulation: end of TestVectors \n" << "byte_index="<<byte_index<< " expected= " << 432000/8 << std::endl;
std::vector<uint8_t> page_bytes = extract_page_bytes(tv, byte_index, SIZE_PAGE_BYTES);
if (page_bytes.empty())
{
std::cout << "OsnmaTestVectorsSimulation: end of TestVectors \n"
<< "byte_index=" << byte_index << " expected= " << 432000 / 8 << std::endl;
end_of_hex_stream = true;
break;
}
// convert them to bitset representation using bytes_to_string
std::string page_bits = bytes_to_str(page_bytes);
// Extract the 40 OSNMA bits starting from the 18th bit
std::string even_page = page_bits.substr(0, page_bits.size() / 2);;
std::string odd_page = page_bits.substr( page_bits.size() / 2);
if(even_page.size() < 120 || odd_page.size() < 120 ){
std::cout<< "OsnmaTestVectorsSimulation: error parsing pages" << std::endl;
std::string even_page = page_bits.substr(0, page_bits.size() / 2);
;
std::string odd_page = page_bits.substr(page_bits.size() / 2);
if (even_page.size() < 120 || odd_page.size() < 120)
{
std::cout << "OsnmaTestVectorsSimulation: error parsing pages" << std::endl;
}
bool even_odd_OK = even_page[0] == '0' && odd_page[0] == '1';
bool page_type_OK = even_page[1] == '0' && odd_page[1] == '0';
bool tail_bits_OK = even_page.substr(even_page.size() - 6) == "000000" && odd_page.substr(odd_page.size() - 6) == "000000";
if(!even_odd_OK || !page_type_OK || !tail_bits_OK)
std::cerr<< "OsnmaTestVectorsSimulation: error parsing pages." << std::endl;
if (!even_odd_OK || !page_type_OK || !tail_bits_OK)
std::cerr << "OsnmaTestVectorsSimulation: error parsing pages." << std::endl;
std::bitset<112> data_k(even_page.substr(2,112));
std::bitset<16> data_j(odd_page.substr(2,16));
std::bitset<112> data_k(even_page.substr(2, 112));
std::bitset<16> data_j(odd_page.substr(2, 16));
std::bitset<112> shifted_data_k = data_k;
// uint8_t word_type = 0;
// for(int i = 0; i < 6; ++i) {
// word_type |= (data_k[104 + i] << i);
// }
uint8_t word_type = static_cast<uint8_t>((shifted_data_k >>= 106).to_ulong()); // word type is the first 6 bits of the word
std::cout<< "OsnmaTestVectorsSimulation: received Word "<< static_cast<int>(word_type) << std::endl;
if( (word_type >= 1 && word_type <=5) || word_type == 6 || word_type == 10)
// uint8_t word_type = 0;
// for(int i = 0; i < 6; ++i) {
// word_type |= (data_k[104 + i] << i);
// }
uint8_t word_type = static_cast<uint8_t>((shifted_data_k >>= 106).to_ulong()); // word type is the first 6 bits of the word
std::cout << "OsnmaTestVectorsSimulation: received Word " << static_cast<int>(word_type) << std::endl;
if ((word_type >= 1 && word_type <= 5) || word_type == 6 || word_type == 10)
{
// store raw word
std::bitset<128> data_combined(data_k.to_string() + data_j.to_string());
words[word_type] = data_combined;
}
if(word_type == DUMMY_PAGE)
if (word_type == DUMMY_PAGE)
flag_dummy_page = true;
// place it into osnma object.
std::bitset<40> osnmaBits(odd_page.substr(18, 40));
@ -185,12 +183,13 @@ TEST_F(OsnmaMsgReceiverTest, OsnmaTestVectorsSimulation)
byte_index += SIZE_PAGE_BYTES;
}
std::cout<< "----------" << std::endl;
if(end_of_hex_stream)
std::cout << "----------" << std::endl;
if (end_of_hex_stream)
break;
if(flag_dummy_page){
if (flag_dummy_page)
{
flag_dummy_page = false;
continue; // skip this SV
continue; // skip this SV
}
// Fill osnma object
@ -198,8 +197,8 @@ TEST_F(OsnmaMsgReceiverTest, OsnmaTestVectorsSimulation)
osnmaMsg_sptr->mack = mack;
osnmaMsg_sptr->TOW_sf0 = d_GST_SIS & 0x000FFFFF;
osnmaMsg_sptr->WN_sf0 = (d_GST_SIS & 0xFFF00000) >> 20 ;
osnmaMsg_sptr->PRN = tv.svId; // PRNa
osnmaMsg_sptr->WN_sf0 = (d_GST_SIS & 0xFFF00000) >> 20;
osnmaMsg_sptr->PRN = tv.svId; // PRNa
// TODO - refactor this logic, currently it is split
@ -210,14 +209,14 @@ TEST_F(OsnmaMsgReceiverTest, OsnmaTestVectorsSimulation)
if (words.find(i) == words.end())
{
ephClockStatusWordsReceived = false;
std::cerr<< "OsnmaTestVectorsSimulation: error parsing words 1->5. "
"Word "<< i << " should be received for each subframe but was not." << std::endl;
std::cerr << "OsnmaTestVectorsSimulation: error parsing words 1->5. "
"Word "
<< i << " should be received for each subframe but was not." << std::endl;
}
}
// extract bits as needed by osnma block
if(ephClockStatusWordsReceived)
if (ephClockStatusWordsReceived)
{
// Define the starting position and length of bits to extract for each word
std::map<uint8_t, std::pair<uint8_t, uint8_t>> extractionParams = {
{1, {6, 120}},
@ -227,29 +226,28 @@ TEST_F(OsnmaMsgReceiverTest, OsnmaTestVectorsSimulation)
{5, {6, 67}},
};
// Fill NavData bits -- Iterate over the extraction parameters
// Fill NavData bits -- Iterate over the extraction parameters // Fill NavData bits -- Iterate over the extraction parameters
std::string nav_data_ADKD_0_12 = "";
for (const auto& param : extractionParams) {
for (const auto& param : extractionParams)
{
uint8_t wordKey = param.first;
uint8_t start = param.second.first;
uint8_t length = param.second.second;
// Extract the required bits and fill osnma block
nav_data_ADKD_0_12 += words[wordKey].
to_string().substr(
start, length);
nav_data_ADKD_0_12 += words[wordKey].to_string().substr(start, length);
}
// send to osnma block
bool check_size_is_ok = nav_data_ADKD_0_12.size() == 549;
if(check_size_is_ok)
if (check_size_is_ok)
{
std::cout << "Galileo OSNMA: sending ADKD=0/12 navData, PRN_d (" << tv.svId << ") " << "TOW_sf=" << osnmaMsg_sptr->TOW_sf0 <<std::endl;
const auto tmp_obj_osnma = std::make_shared<std::tuple<uint32_t, std::string,uint32_t>>( // < PRNd , navDataBits, TOW_Sosf>
std::cout << "Galileo OSNMA: sending ADKD=0/12 navData, PRN_d (" << tv.svId << ") "
<< "TOW_sf=" << osnmaMsg_sptr->TOW_sf0 << std::endl;
const auto tmp_obj_osnma = std::make_shared<std::tuple<uint32_t, std::string, uint32_t>>( // < PRNd , navDataBits, TOW_Sosf>
tv.svId,
nav_data_ADKD_0_12,
osnmaMsg_sptr->TOW_sf0);
osnma->msg_handler_osnma(pmt::make_any(tmp_obj_osnma));
}
}
@ -257,12 +255,12 @@ TEST_F(OsnmaMsgReceiverTest, OsnmaTestVectorsSimulation)
bool timingWordsReceived = words.find(6) != words.end() &&
words.find(10) != words.end();
// extract bits as needed by osnma block
if(timingWordsReceived){
if (timingWordsReceived)
{
// Define the starting position and length of bits to extract for each word
std::map<uint8_t, std::pair<uint8_t, uint8_t>> extractionParams = {
{6, {6, 99}},
{10, {86, 42}}
};
{10, {86, 42}}};
std::string nav_data_ADKD_4 = "";
// Fill NavData bits -- Iterate over the extraction parameters
@ -276,39 +274,39 @@ TEST_F(OsnmaMsgReceiverTest, OsnmaTestVectorsSimulation)
nav_data_ADKD_4 += words[wordKey].to_string().substr(
start, length);
}
// send to osnma block
bool check_size_is_ok = nav_data_ADKD_4.size() == 141;
if(check_size_is_ok)
if (check_size_is_ok)
{
std::cout << "Galileo OSNMA: sending ADKD=04 navData, PRN_d (" << tv.svId << ") " << "TOW_sf=" << osnmaMsg_sptr->TOW_sf0 <<std::endl;
const auto tmp_obj_osnma = std::make_shared<std::tuple<uint32_t, std::string,uint32_t>>( // < PRNd , navDataBits, TOW_Sosf>
std::cout << "Galileo OSNMA: sending ADKD=04 navData, PRN_d (" << tv.svId << ") "
<< "TOW_sf=" << osnmaMsg_sptr->TOW_sf0 << std::endl;
const auto tmp_obj_osnma = std::make_shared<std::tuple<uint32_t, std::string, uint32_t>>( // < PRNd , navDataBits, TOW_Sosf>
tv.svId,
nav_data_ADKD_4,
osnmaMsg_sptr->TOW_sf0);
osnma->msg_handler_osnma(pmt::make_any(tmp_obj_osnma));
}
}
// Call the handler, as if it came from telemetry decoder block
auto temp_obj = pmt::make_any(osnmaMsg_sptr);
osnma->msg_handler_osnma(temp_obj); // osnma entry point
osnma->msg_handler_osnma(temp_obj); // osnma entry point
}
if(!end_of_hex_stream){
offset_byte = byte_index; // update offset for the next subframe
if (!end_of_hex_stream)
{
offset_byte = byte_index; // update offset for the next subframe
d_GST_SIS += DURATION_SUBFRAME;
TOW = d_GST_SIS & 0x000FFFFF;
WN = (d_GST_SIS & 0xFFF00000) >> 20 ;
std::cout << "OsnmaTestVectorsSimulation:" << " d_GST_SIS= " << d_GST_SIS
WN = (d_GST_SIS & 0xFFF00000) >> 20;
std::cout << "OsnmaTestVectorsSimulation:"
<< " d_GST_SIS= " << d_GST_SIS
<< ", TOW=" << TOW
<< ", WN=" << WN << std::endl;
}
}
@ -318,20 +316,24 @@ TEST_F(OsnmaMsgReceiverTest, OsnmaTestVectorsSimulation)
// TODO - create global vars with failed tags and compare to total tags (Tag Id for example)
}
std::vector<TestVector> OsnmaMsgReceiverTest::readTestVectorsFromFile(const std::string& filename)
{
std::ifstream file(filename);
std::vector<TestVector> testVectors;
if (!file.is_open()) {
std::cerr<<"Error reading the file \"" << filename <<"\" \n";
if (!file.is_open())
{
std::cerr << "Error reading the file \"" << filename << "\" \n";
return testVectors;
}
std::string line;
std::getline(file, line);
if (line != "SVID,NumNavBits,NavBitsHEX\r" ){
std::cerr<<"Error parsing first line" <<"\n";
}
if (line != "SVID,NumNavBits,NavBitsHEX\r")
{
std::cerr << "Error parsing first line"
<< "\n";
}
while (std::getline(file, line))
{
@ -354,23 +356,27 @@ std::vector<TestVector> OsnmaMsgReceiverTest::readTestVectorsFromFile(const std:
return testVectors;
}
std::vector<uint8_t> OsnmaMsgReceiverTest::parseNavBits(const std::string& hex)
{
std::vector<uint8_t> bytes;
for (unsigned int i = 0; i < hex.length()-1; i += 2)
for (unsigned int i = 0; i < hex.length() - 1; i += 2)
{
std::string byteString = hex.substr(i, 2);
uint8_t byte = (uint8_t) strtol(byteString.c_str(), NULL, 16);
uint8_t byte = (uint8_t)strtol(byteString.c_str(), NULL, 16);
bytes.push_back(byte);
}
return bytes;
}
std::string OsnmaMsgReceiverTest::bytes_to_str(const std::vector<uint8_t>& bytes)
{
std::string bit_string;
bit_string.reserve(bytes.size() * 8);
for(const auto& byte : bytes)
for (const auto& byte : bytes)
{
std::bitset<8> bits(byte);
bit_string += bits.to_string();
@ -378,6 +384,7 @@ std::string OsnmaMsgReceiverTest::bytes_to_str(const std::vector<uint8_t>& bytes
return bit_string;
}
/**
* @brief Extracts a range of bytes from a TestVector's navBits vector.
*
@ -406,6 +413,8 @@ std::vector<uint8_t> OsnmaMsgReceiverTest::extract_page_bytes(const TestVector&
return extracted_bytes;
}
/**
* @brief Sets the time based on the given input.
*
@ -429,118 +438,37 @@ void OsnmaMsgReceiverTest::set_time(std::tm& input)
uint32_t sec_in_week = 7 * 24 * 60 * 60;
uint32_t week_number = duration_sec.count() / sec_in_week;
uint32_t time_of_week = duration_sec.count() % sec_in_week;
this->WN = week_number;
this->TOW = time_of_week + LEAP_SECONDS;
this->WN = week_number;
this->TOW = time_of_week + LEAP_SECONDS;
// Return the week number and time of week as a pair
// TODO: d_GST_SIS or d_receiver_time? doubt
// I am assuming that local realisation of receiver is identical to SIS GST time coming from W5 or W0
this->d_GST_SIS = (this->WN & 0x00000FFF) << 20 | (this->TOW & 0x000FFFFF);
}
void OsnmaMsgReceiverTest::initializeGoogleLog()
{
google::InitGoogleLogging(log_name.c_str());
FLAGS_minloglevel = 0; // INFO
FLAGS_logtostderr = 0; // add this line
FLAGS_log_dir = "/home/cgm/CLionProjects/osnma/build/src/tests/logs";
if (FLAGS_log_dir.empty())
{
std::cout << "Logging will be written at "
<< std::filesystem::temp_directory_path()
<< '\n'
<< "Use gnss-sdr --log_dir=/path/to/log to change that.\n";
}
else
{
try
{
const std::filesystem::path p(FLAGS_log_dir);
if (!std::filesystem::exists(p))
{
std::cout << "The path "
<< FLAGS_log_dir
<< " does not exist, attempting to create it.\n";
std::error_code ec;
if (!std::filesystem::create_directory(p, ec))
{
std::cout << "Could not create the " << FLAGS_log_dir << " folder.\n";
gflags::ShutDownCommandLineFlags();
throw std::runtime_error("Could not create folder for logs");
}
}
std::cout << "Logging will be written at " << FLAGS_log_dir << '\n';
}
catch (const std::exception& e)
{
std::cerr << e.what() << '\n';
std::cerr << "Could not create the " << FLAGS_log_dir << " folder.\n";
gflags::ShutDownCommandLineFlags();
throw;
}
}
this->d_GST_SIS = (this->WN & 0x00000FFF) << 20 | (this->TOW & 0x000FFFFF);
}
TEST_F(OsnmaMsgReceiverTest, BuildTagMessageM0)
{
// Arrange
// ----------
// m0
std::vector<uint8_t> expected_message = {
0x02, 0x4E, 0x05, 0x46, 0x3C, 0x01, 0x83, 0xA5, 0x91, 0x05, 0x1D, 0x69, 0x25, 0x80, 0x07, 0x6B,
0x3E, 0xEA, 0x81, 0x41, 0xBF, 0x03, 0xAD, 0xCB, 0x5A, 0xAD, 0xB2, 0x77, 0xAF, 0x6F, 0xCF, 0x21,
0xFB, 0x98, 0xFF, 0x7E, 0x83, 0xAF, 0xFC, 0x37, 0x02, 0x03, 0xB0, 0xD8, 0xE1, 0x0E, 0xB1, 0x4D,
0x11, 0x18, 0xE6, 0xB0, 0xE8, 0x20, 0x01, 0xA0, 0x00, 0xE5, 0x91, 0x00, 0x06, 0xD3, 0x1F, 0x00,
0x02, 0x68, 0x05, 0x4A, 0x02, 0xC2, 0x26, 0x07, 0xF7, 0xFC, 0x00
};
uint32_t TOW_Tag0 = 345660;
uint32_t TOW_NavData = TOW_Tag0 - 30;
uint32_t TOW_Key_Tag0 = TOW_Tag0 + 30 ;
uint32_t WN = 1248;
uint32_t PRNa = 2;
uint8_t CTR = 1;
osnma->d_osnma_data.d_dsm_kroot_message.ts = 9; // 40 bit
osnma->d_tesla_keys[TOW_Key_Tag0] = {0x69, 0xC0, 0x0A, 0xA7, 0x36, 0x42, 0x37, 0xA6, 0x5E, 0xBF, 0x00, 0x6A, 0xD8, 0xDB, 0xBC, 0x73}; // K4
osnma->d_osnma_data.d_dsm_kroot_message.mf = 0;
osnma->d_satellite_nav_data[PRNa][TOW_NavData].ephemeris_iono_vector_2 = "000011101001011001000100000101000111010110100100100101100000000000011101101011001111101110101010000001010000011011111100000011101011011100101101011010101011011011001001110111101011110110111111001111001000011111101110011000111111110111111010000011101011111111110000110111000000100000001110110000110110001110000100001110101100010100110100010001000110001110011010110000111010000010000000000001101000000000000011100101100100010000000000000110110100110001111100000000000000100110100000000101010010100000001011000010001001100000011111110111111111000000000";
osnma->d_osnma_data.d_nma_header.nmas = 0b10;
MACK_tag_and_info MTI;
MTI.tag = static_cast<uint64_t>(0xE37BC4F858);
MTI.tag_info.PRN_d = 0x02;
MTI.tag_info.ADKD = 0x00;
MTI.tag_info.cop = 0x0F;
Tag t0(MTI, TOW_Tag0, WN, PRNa, CTR);
// Act
// ----------
auto computed_message = osnma->build_message(t0);
// Assert
// ----------
ASSERT_TRUE(computed_message == expected_message);
}
TEST_F(OsnmaMsgReceiverTest, TagVerification) {
// Arrange
// ----------
// Tag0
// m0
std::vector<uint8_t> expected_message = {
0x02, 0x4E, 0x05, 0x46, 0x3C, 0x01, 0x83, 0xA5, 0x91, 0x05, 0x1D, 0x69, 0x25, 0x80, 0x07, 0x6B,
0x3E, 0xEA, 0x81, 0x41, 0xBF, 0x03, 0xAD, 0xCB, 0x5A, 0xAD, 0xB2, 0x77, 0xAF, 0x6F, 0xCF, 0x21,
0xFB, 0x98, 0xFF, 0x7E, 0x83, 0xAF, 0xFC, 0x37, 0x02, 0x03, 0xB0, 0xD8, 0xE1, 0x0E, 0xB1, 0x4D,
0x11, 0x18, 0xE6, 0xB0, 0xE8, 0x20, 0x01, 0xA0, 0x00, 0xE5, 0x91, 0x00, 0x06, 0xD3, 0x1F, 0x00,
0x02, 0x68, 0x05, 0x4A, 0x02, 0xC2, 0x26, 0x07, 0xF7, 0xFC, 0x00};
uint32_t TOW_Tag0 = 345660;
uint32_t TOW_NavData = TOW_Tag0 - 30;
uint32_t TOW_Key_Tag0 = TOW_Tag0 + 30 ;
uint32_t TOW_Key_Tag0 = TOW_Tag0 + 30;
uint32_t WN = 1248;
uint32_t PRNa = 2;
uint8_t CTR = 1;
osnma->d_osnma_data.d_dsm_kroot_message.ts = 9; // 40 bit
osnma->d_tesla_keys[TOW_Key_Tag0] = {0x69, 0xC0, 0x0A, 0xA7, 0x36, 0x42, 0x37, 0xA6, 0x5E, 0xBF, 0x00, 0x6A, 0xD8, 0xDD, 0xBC, 0x73}; // K4
osnma->d_osnma_data.d_dsm_kroot_message.ts = 9; // 40 bit
osnma->d_tesla_keys[TOW_Key_Tag0] = {0x69, 0xC0, 0x0A, 0xA7, 0x36, 0x42, 0x37, 0xA6, 0x5E, 0xBF, 0x00, 0x6A, 0xD8, 0xDB, 0xBC, 0x73}; // K4
osnma->d_osnma_data.d_dsm_kroot_message.mf = 0;
osnma->d_satellite_nav_data[PRNa][TOW_NavData].ephemeris_iono_vector_2 = "000011101001011001000100000101000111010110100100100101100000000000011101101011001111101110101010000001010000011011111100000011101011011100101101011010101011011011001001110111101011110110111111001111001000011111101110011000111111110111111010000011101011111111110000110111000000100000001110110000110110001110000100001110101100010100110100010001000110001110011010110000111010000010000000000001101000000000000011100101100100010000000000000110110100110001111100000000000000100110100000000101010010100000001011000010001001100000011111110111111111000000000";
osnma->d_osnma_data.d_nma_header.nmas = 0b10;
@ -553,29 +481,62 @@ TEST_F(OsnmaMsgReceiverTest, TagVerification) {
Tag t0(MTI, TOW_Tag0, WN, PRNa, CTR);
// Act
// ----------
auto computed_message = osnma->build_message(t0);
// Assert
// ----------
ASSERT_TRUE(computed_message == expected_message);
}
TEST_F(OsnmaMsgReceiverTest, TagVerification)
{
// Arrange
// ----------
// Tag0
uint32_t TOW_Tag0 = 345660;
uint32_t TOW_NavData = TOW_Tag0 - 30;
uint32_t TOW_Key_Tag0 = TOW_Tag0 + 30;
uint32_t WN = 1248;
uint32_t PRNa = 2;
uint8_t CTR = 1;
osnma->d_osnma_data.d_dsm_kroot_message.ts = 9; // 40 bit
osnma->d_tesla_keys[TOW_Key_Tag0] = {0x69, 0xC0, 0x0A, 0xA7, 0x36, 0x42, 0x37, 0xA6, 0x5E, 0xBF, 0x00, 0x6A, 0xD8, 0xDD, 0xBC, 0x73}; // K4
osnma->d_osnma_data.d_dsm_kroot_message.mf = 0;
osnma->d_satellite_nav_data[PRNa][TOW_NavData].ephemeris_iono_vector_2 = "000011101001011001000100000101000111010110100100100101100000000000011101101011001111101110101010000001010000011011111100000011101011011100101101011010101011011011001001110111101011110110111111001111001000011111101110011000111111110111111010000011101011111111110000110111000000100000001110110000110110001110000100001110101100010100110100010001000110001110011010110000111010000010000000000001101000000000000011100101100100010000000000000110110100110001111100000000000000100110100000000101010010100000001011000010001001100000011111110111111111000000000";
osnma->d_osnma_data.d_nma_header.nmas = 0b10;
MACK_tag_and_info MTI;
MTI.tag = static_cast<uint64_t>(0xE37BC4F858);
MTI.tag_info.PRN_d = 0x02;
MTI.tag_info.ADKD = 0x00;
MTI.tag_info.cop = 0x0F;
Tag t0(MTI, TOW_Tag0, WN, PRNa, CTR);
// Act
// ----------
bool result_tag0 = osnma->verify_tag(t0);
// Assert
// ----------
//ASSERT_TRUE(result_tag0);
// ASSERT_TRUE(result_tag0);
// Tag3
uint32_t TOW_Tag3 = 345660;
uint32_t TOW_NavData_Tag3 = TOW_Tag3 - 30;
uint32_t TOW_Key_Tag3 = TOW_Tag0 + 30 ;
uint32_t TOW_Key_Tag3 = TOW_Tag0 + 30;
WN = 1248;
PRNa = 2;
CTR = 3;
osnma->d_osnma_data.d_dsm_kroot_message.ts = 9; // 40 bit
osnma->d_tesla_keys[TOW_Key_Tag3] = {0x69, 0xC0, 0x0A, 0xA7, 0x36, 0x42, 0x37, 0xA6, 0x5E, 0xBF, 0x00, 0x6A, 0xD8, 0xDD, 0xBC, 0x73}; // K4
osnma->d_osnma_data.d_dsm_kroot_message.ts = 9; // 40 bit
osnma->d_tesla_keys[TOW_Key_Tag3] = {0x69, 0xC0, 0x0A, 0xA7, 0x36, 0x42, 0x37, 0xA6, 0x5E, 0xBF, 0x00, 0x6A, 0xD8, 0xDD, 0xBC, 0x73}; // K4
osnma->d_osnma_data.d_dsm_kroot_message.mf = 0;
osnma->d_satellite_nav_data[PRNa][TOW_NavData].utc_vector_2 =
"111111111111111111111111111111110000000000000000000000010001001001001000"
@ -591,5 +552,4 @@ TEST_F(OsnmaMsgReceiverTest, TagVerification) {
bool result_tag3 = osnma->verify_tag(t3);
ASSERT_TRUE(result_tag0 && result_tag3);
}