1
0
mirror of https://github.com/gnss-sdr/gnss-sdr synced 2025-07-17 09:22:56 +00:00

Really fix signature verification with GnuTLS

This commit is contained in:
Carles Fernandez 2024-06-21 10:29:20 +02:00
parent 11e84e751b
commit d41efd2653
No known key found for this signature in database
GPG Key ID: 4C583C52B0C3877D
2 changed files with 143 additions and 255 deletions

View File

@ -1,7 +1,8 @@
/*! /*!
* \file gnss_crypto.cc * \file gnss_crypto.cc
* \brief Class for computing cryptografic functions * \brief Class for computing cryptographic functions
* \author Carles Fernandez, 2023. cfernandez(at)cttc.es * \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. * GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
* This file is part of GNSS-SDR. * 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 * SPDX-License-Identifier: GPL-3.0-or-later
* *
* ----------------------------------------------------------------------------- * -----------------------------------------------------------------------------
@ -20,9 +21,9 @@
#include <pugixml.hpp> #include <pugixml.hpp>
#include <cstddef> #include <cstddef>
#include <fstream> #include <fstream>
#include <iomanip>
#include <iostream> #include <iostream>
#include <iterator> #include <iterator>
#include <sstream>
#if USE_OPENSSL_FALLBACK #if USE_OPENSSL_FALLBACK
#include <openssl/cmac.h> #include <openssl/cmac.h>
@ -30,29 +31,27 @@
#include <openssl/hmac.h> #include <openssl/hmac.h>
#include <openssl/pem.h> #include <openssl/pem.h>
#if USE_OPENSSL_3 #if USE_OPENSSL_3
#include <iomanip>
#include <openssl/bio.h> #include <openssl/bio.h>
#include <openssl/bn.h>
#include <openssl/err.h> #include <openssl/err.h>
#include <openssl/evp.h> #include <openssl/evp.h>
#include <openssl/ec.h>
#include <openssl/param_build.h> #include <openssl/param_build.h>
#include <openssl/bn.h>
#define OPENSSL_ENGINE nullptr #define OPENSSL_ENGINE nullptr
#else #else
#include <openssl/sha.h> #include <openssl/sha.h>
#endif #endif
#else #else // GnuTLS
#include <cstring>
#include <gnutls/abstract.h> #include <gnutls/abstract.h>
#include <gnutls/crypto.h> #include <gnutls/crypto.h>
#include <gnutls/x509.h> #include <gnutls/x509.h>
#include <iomanip>
#endif #endif
Gnss_Crypto::Gnss_Crypto(const std::string& pemFilePath, const std::string& merkleTreePath) Gnss_Crypto::Gnss_Crypto(const std::string& pemFilePath, const std::string& merkleTreePath)
{ {
#if USE_OPENSSL_FALLBACK #if USE_OPENSSL_FALLBACK
#else #else // GnuTLS
// gnutls_global_init(); gnutls_global_init();
#endif #endif
readPublicKeyFromPEM(pemFilePath); readPublicKeyFromPEM(pemFilePath);
read_merkle_xml(merkleTreePath); read_merkle_xml(merkleTreePath);
@ -69,11 +68,13 @@ Gnss_Crypto::~Gnss_Crypto()
EC_KEY_free(d_PublicKey); EC_KEY_free(d_PublicKey);
} }
#endif #endif
#else // GNU-TLS #else // GnuTLS
if (d_PublicKey != NULL) { if (d_PublicKey != NULL)
{
gnutls_pubkey_deinit(d_PublicKey); gnutls_pubkey_deinit(d_PublicKey);
d_PublicKey = NULL; d_PublicKey = NULL;
} }
gnutls_global_deinit();
#endif #endif
} }
@ -82,25 +83,12 @@ bool Gnss_Crypto::have_public_key() const
{ {
#if USE_OPENSSL_FALLBACK #if USE_OPENSSL_FALLBACK
return (d_PublicKey != nullptr); return (d_PublicKey != nullptr);
#else #else // GnuTLS
return (d_PublicKey != gnutls_pubkey_t{}); return (d_PublicKey != gnutls_pubkey_t{});
#endif #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> Gnss_Crypto::convert_from_hex_str(const std::string& input) const
{ {
std::vector<uint8_t> result; std::vector<uint8_t> result;
@ -236,11 +224,6 @@ void Gnss_Crypto::read_merkle_xml(const std::string& 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> Gnss_Crypto::computeSHA256(const std::vector<uint8_t>& input) const
{ {
std::vector<uint8_t> output(32); // SHA256 hash size std::vector<uint8_t> output(32); // SHA256 hash size
@ -273,7 +256,7 @@ std::vector<uint8_t> Gnss_Crypto::computeSHA256(const std::vector<uint8_t>& inpu
SHA256_Update(&sha256Context, input.data(), input.size()); SHA256_Update(&sha256Context, input.data(), input.size());
SHA256_Final(output.data(), &sha256Context); SHA256_Final(output.data(), &sha256Context);
#endif #endif
#else #else // GnuTLS
std::vector<uint8_t> output_aux(32); std::vector<uint8_t> output_aux(32);
gnutls_hash_hd_t hashHandle; gnutls_hash_hd_t hashHandle;
gnutls_hash_init(&hashHandle, GNUTLS_DIG_SHA256); gnutls_hash_init(&hashHandle, GNUTLS_DIG_SHA256);
@ -301,7 +284,7 @@ std::vector<uint8_t> Gnss_Crypto::computeSHA3_256(const std::vector<uint8_t>& in
#else #else
// SHA3-256 not implemented in OpenSSL < 3.0 // SHA3-256 not implemented in OpenSSL < 3.0
#endif #endif
#else #else // GnuTLS
std::vector<uint8_t> output_aux(32); std::vector<uint8_t> output_aux(32);
gnutls_hash_hd_t hashHandle; gnutls_hash_hd_t hashHandle;
gnutls_hash_init(&hashHandle, GNUTLS_DIG_SHA3_256); gnutls_hash_init(&hashHandle, GNUTLS_DIG_SHA3_256);
@ -358,7 +341,7 @@ std::vector<uint8_t> Gnss_Crypto::computeHMAC_SHA_256(const std::vector<uint8_t>
hmac.resize(hmacLen); hmac.resize(hmacLen);
output = hmac; output = hmac;
#endif #endif
#else #else // GnuTLS
std::vector<uint8_t> output_aux(32); std::vector<uint8_t> output_aux(32);
gnutls_hmac_hd_t hmac; gnutls_hmac_hd_t hmac;
gnutls_hmac_init(&hmac, GNUTLS_MAC_SHA256, key.data(), key.size()); gnutls_hmac_init(&hmac, GNUTLS_MAC_SHA256, key.data(), key.size());
@ -421,7 +404,7 @@ std::vector<uint8_t> Gnss_Crypto::computeCMAC_AES(const std::vector<uint8_t>& ke
output = mac; output = mac;
#endif #endif
#else #else // GnuTLS
gnutls_cipher_hd_t cipher; gnutls_cipher_hd_t cipher;
std::vector<uint8_t> mac(16); std::vector<uint8_t> mac(16);
std::vector<uint8_t> message = input; std::vector<uint8_t> message = input;
@ -471,8 +454,7 @@ void Gnss_Crypto::readPublicKeyFromPEM(const std::string& pemFilePath)
std::cerr << "OpenSSL: error reading the Public Key from file " << pemFilePath << ". Aborting import" << std::endl; std::cerr << "OpenSSL: error reading the Public Key from file " << pemFilePath << ". Aborting import" << std::endl;
return; return;
} }
#else // GnuTLS
#else
// Import the PEM data // 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_datum_t pemDatum = {const_cast<unsigned char*>(reinterpret_cast<unsigned char*>(pemContent.data())), static_cast<unsigned int>(pemContent.size())};
gnutls_pubkey_t pubkey; gnutls_pubkey_t pubkey;
@ -493,62 +475,21 @@ void Gnss_Crypto::readPublicKeyFromPEM(const std::string& pemFilePath)
gnutls_pubkey_deinit(pubkey); gnutls_pubkey_deinit(pubkey);
#endif #endif
std::cout << "Public key successfully read from file " << pemFilePath << std::endl; std::cout << "Public key successfully read from file " << pemFilePath << std::endl;
//print_pubkey_hex(d_PublicKey);
} }
bool Gnss_Crypto::verify_signature(const std::vector<uint8_t>& message, const std::vector<uint8_t>& signature) 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); std::vector<uint8_t> digest = this->computeSHA256(message);
if (!have_public_key()) 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; return false;
} }
bool success = false; bool success = false;
#if USE_OPENSSL_FALLBACK #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 #if USE_OPENSSL_3
EVP_PKEY_CTX* ctx; EVP_PKEY_CTX* ctx;
//print_pubkey_hex(d_PublicKey);
ctx = EVP_PKEY_CTX_new(d_PublicKey, nullptr); ctx = EVP_PKEY_CTX_new(d_PublicKey, nullptr);
bool do_operation = true; bool do_operation = true;
@ -556,7 +497,7 @@ bool Gnss_Crypto::verify_signature(const std::vector<uint8_t>& message, const st
{ {
do_operation = false; 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; size_t half_size = signature.size() / 2;
std::vector<uint8_t> raw_r(signature.begin(), signature.begin() + half_size); std::vector<uint8_t> raw_r(signature.begin(), signature.begin() + half_size);
std::vector<uint8_t> raw_s(signature.begin() + half_size, signature.end()); std::vector<uint8_t> raw_s(signature.begin() + half_size, signature.end());
@ -575,12 +516,12 @@ bool Gnss_Crypto::verify_signature(const std::vector<uint8_t>& message, const st
if (ECDSA_SIG_set0(sig, r, s) != 1) if (ECDSA_SIG_set0(sig, r, s) != 1)
{ {
std::cerr << "Failed to set R and S values in ECDSA_SIG" << std::endl; 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; return false;
} }
std::vector<uint8_t> derSignature; std::vector<uint8_t> derSignature;
unsigned char *derSig = nullptr; unsigned char* derSig = nullptr;
int derSigLength = i2d_ECDSA_SIG(sig, &derSig); int derSigLength = i2d_ECDSA_SIG(sig, &derSig);
if (derSigLength <= 0) if (derSigLength <= 0)
@ -591,7 +532,6 @@ bool Gnss_Crypto::verify_signature(const std::vector<uint8_t>& message, const st
derSignature.assign(derSig, derSig + derSigLength); derSignature.assign(derSig, derSig + derSigLength);
if (EVP_PKEY_verify_init(ctx) <= 0) if (EVP_PKEY_verify_init(ctx) <= 0)
{ {
do_operation = false; do_operation = false;
@ -616,10 +556,9 @@ bool Gnss_Crypto::verify_signature(const std::vector<uint8_t>& message, const st
{ {
unsigned long errCode = ERR_get_error(); unsigned long errCode = ERR_get_error();
char* err = ERR_error_string(errCode, NULL); char* err = ERR_error_string(errCode, NULL);
std::cerr << "OpenSSL: message authentication failed: " << err << std::endl; std::cerr << "OpenSSL: message authentication failed: " << err << std::endl;
} }
#else #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); int verification = ECDSA_verify(0, digest.data(), SHA256_DIGEST_LENGTH, signature.data(), static_cast<int>(signature.size()), d_PublicKey);
if (verification == 1) if (verification == 1)
{ {
@ -635,34 +574,26 @@ bool Gnss_Crypto::verify_signature(const std::vector<uint8_t>& message, const st
} }
#endif #endif
#else #else // GnuTLS
// GNU-TLS // Convert signature to DER format
gnutls_global_init(); std::vector<uint8_t> der_sig;
// debug info gnu-tls remove when not needed anymore! if (!convert_raw_to_der_ecdsa(signature, der_sig))
gnutls_global_set_log_level(9); {
gnutls_global_set_log_function(Gnss_Crypto::my_log_func); std::cerr << "Failed to convert raw ECDSA signature to DER format" << std::endl;
return false;
}
unsigned int bit_size; // Prepare the digest datum
if (gnutls_pubkey_get_pk_algorithm(d_PublicKey, &bit_size) != GNUTLS_PK_ECDSA) 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)
{ {
std::cerr << "GnuTLS: the Public Key does not contain a ECDSA key. Aborting signature verification" << std::endl; std::cerr << "GnuTLS: message authentication failed: " << gnutls_strerror(ret) << std::endl;
} }
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)
{
success = true;
}
else
{
std::cerr << "GnuTLS error: " << gnutls_strerror(ret) << std::endl;
}
gnutls_global_deinit();
#endif #endif
return success; return success;
} }
@ -707,75 +638,47 @@ 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) void Gnss_Crypto::set_public_key(const std::vector<uint8_t>& publicKey)
{ {
#if USE_OPENSSL_FALLBACK #if USE_OPENSSL_FALLBACK
BIO *bio = NULL; BIO* bio = NULL;
EVP_PKEY *pkey = NULL; EVP_PKEY* pkey = NULL;
bio = BIO_new_mem_buf(publicKey.data(), publicKey.size()); bio = BIO_new_mem_buf(publicKey.data(), publicKey.size());
if (!bio) { if (!bio)
{
std::cerr << "Failed to create BIO for key \n"; std::cerr << "Failed to create BIO for key \n";
return; return;
} }
pkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL); pkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL);
BIO_free(bio); BIO_free(bio);
if (!pkey) { if (!pkey)
std::cerr << "OpenSSL: error setting the public key " {
<< ". Aborting import" << std::endl; std::cerr << "OpenSSL: error setting the public key." << std::endl;
return; 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_pubkey_t pubkey;
gnutls_datum_t pemDatum = {const_cast<unsigned char*>(publicKey.data()), static_cast<unsigned int>(publicKey.size())}; gnutls_datum_t pemDatum = {const_cast<unsigned char*>(publicKey.data()), static_cast<unsigned int>(publicKey.size())};
gnutls_pubkey_init(&pubkey); gnutls_pubkey_init(&pubkey);
int ret = gnutls_pubkey_import(pubkey, &pemDatum, GNUTLS_X509_FMT_PEM); 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) if (ret != GNUTLS_E_SUCCESS)
{ {
gnutls_pubkey_deinit(pubkey); gnutls_pubkey_deinit(pubkey);
std::cerr << "GnuTLS: error setting the public key " std::cerr << "GnuTLS: error setting the public key" << std::endl;
<< ". Aborting import" << std::endl;
std::cerr << "GnuTLS error: " << gnutls_strerror(ret) << std::endl; std::cerr << "GnuTLS error: " << gnutls_strerror(ret) << std::endl;
return; return;
} }
// d_PublicKey = pubkey;
pubkey_copy(pubkey, &d_PublicKey); 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); gnutls_pubkey_deinit(pubkey);
// std::cout << "d_PublicKey after: " << std::endl;
// print_pubkey_hex(d_PublicKey);
// gnutls_global_deinit();
#endif #endif
} }
std::vector<uint8_t> Gnss_Crypto::get_public_key()
{
#if USE_OPENSSL_FALLBACK
// TODO
#else
// GNU-TLS
// TODO
#endif
return {};
}
#if USE_OPENSSL_FALLBACK #if USE_OPENSSL_FALLBACK
bool Gnss_Crypto::pubkey_copy(EVP_PKEY* src, EVP_PKEY** dest) bool Gnss_Crypto::pubkey_copy(EVP_PKEY* src, EVP_PKEY** dest)
@ -794,9 +697,6 @@ bool Gnss_Crypto::pubkey_copy(EVP_PKEY* src, EVP_PKEY** dest)
return false; 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 // Read the data from the memory buffer
char* bio_data; char* bio_data;
long data_len = BIO_get_mem_data(mem_bio, &bio_data); long data_len = BIO_get_mem_data(mem_bio, &bio_data);
@ -824,95 +724,87 @@ bool Gnss_Crypto::pubkey_copy(EVP_PKEY* src, EVP_PKEY** dest)
return true; 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 (raw_signature.size() % 2 != 0)
if (!mem_bio) { {
std::cerr << "Failed to create new memory BIO\n"; std::cerr << "Invalid raw ECDSA signature size" << std::endl;
return; return false;
} }
if (!PEM_write_bio_PUBKEY(mem_bio, pubkey)){ size_t half_size = raw_signature.size() / 2;
std::cerr << "Failed to write public key to BIO\n"; std::vector<uint8_t> raw_r(raw_signature.begin(), raw_signature.begin() + half_size);
BIO_free(mem_bio); std::vector<uint8_t> raw_s(raw_signature.begin() + half_size, raw_signature.end());
return;
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; der_signature.insert(der_signature.end(), der_r.begin(), der_r.end());
BIO_get_mem_ptr(mem_bio, &mem_ptr); // Fetch the underlying BUF_MEM structure from the BIO. der_signature.insert(der_signature.end(), der_s.begin(), der_s.end());
std::stringstream ss; return true;
// 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);
} }
#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 bool Gnss_Crypto::pubkey_copy(gnutls_pubkey_t src, gnutls_pubkey_t* dest)
ret = gnutls_pubkey_export2(src, GNUTLS_X509_FMT_PEM, &key_datum); {
if (ret < 0) gnutls_datum_t key_datum;
{
gnutls_free(key_datum.data);
return false;
}
// Initialize dest // Export the public key from src to memory
ret = gnutls_pubkey_init(dest); int ret = gnutls_pubkey_export2(src, GNUTLS_X509_FMT_PEM, &key_datum);
if (ret < 0) if (ret < 0)
{ {
gnutls_free(key_datum.data); gnutls_free(key_datum.data);
return false; return false;
} }
// Import the public key data from key_datum to dest // Initialize dest
ret = gnutls_pubkey_import(*dest, &key_datum, GNUTLS_X509_FMT_PEM); ret = gnutls_pubkey_init(dest);
gnutls_free(key_datum.data); if (ret < 0)
{
gnutls_free(key_datum.data);
return false;
}
if (ret < 0) // Import the public key data from key_datum to dest
{ ret = gnutls_pubkey_import(*dest, &key_datum, GNUTLS_X509_FMT_PEM);
gnutls_pubkey_deinit(*dest); gnutls_free(key_datum.data);
return false;
}
return true; if (ret < 0)
} {
gnutls_pubkey_deinit(*dest);
return false;
}
void Gnss_Crypto::print_pubkey_hex(gnutls_pubkey_t pubkey) return true;
{ }
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);
}
#endif #endif

View File

@ -1,7 +1,8 @@
/*! /*!
* \file gnss_crypto.h * \file gnss_crypto.h
* \brief Class for computing cryptografic functions * \brief Class for computing cryptographic functions
* \author Carles Fernandez, 2023. cfernandez(at)cttc.es * \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. * GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
* This file is part of GNSS-SDR. * 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 * SPDX-License-Identifier: GPL-3.0-or-later
* *
* ----------------------------------------------------------------------------- * -----------------------------------------------------------------------------
@ -38,40 +39,35 @@ public:
Gnss_Crypto() = default; Gnss_Crypto() = default;
~Gnss_Crypto(); ~Gnss_Crypto();
Gnss_Crypto(const std::string& pemFilePath, const std::string& merkleTreePath); 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 have_public_key() const;
std::string convert_to_utf8_str(const std::vector<uint8_t>& input) const; bool verify_signature(const std::vector<uint8_t>& message, const std::vector<uint8_t>& signature) const;
std::vector<uint8_t> convert_from_hex_str(const std::string& input) const;
std::vector<uint8_t> computeSHA256(const std::vector<uint8_t>& input) 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> 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> 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; 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 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; return d_x_4_0;
} }
void set_public_key(const std::vector<uint8_t>& publickey);
static std::vector<uint8_t> get_public_key();
private: private:
std::vector<uint8_t> convert_from_hex_str(const std::string& input) const;
#if USE_OPENSSL_FALLBACK #if USE_OPENSSL_FALLBACK
bool pubkey_copy(EVP_PKEY* src, EVP_PKEY** dest);
void print_pubkey_hex(EVP_PKEY* pubkey);
#if USE_OPENSSL_3 #if USE_OPENSSL_3
EVP_PKEY* d_PublicKey{}; EVP_PKEY* d_PublicKey{};
#else #else
EC_KEY* d_PublicKey = nullptr; EC_KEY* d_PublicKey = nullptr;
#endif #endif
#else bool pubkey_copy(EVP_PKEY* src, EVP_PKEY** dest);
#else // GnuTLS
gnutls_pubkey_t d_PublicKey{}; gnutls_pubkey_t d_PublicKey{};
void set_ecc_key(const std::vector<uint8_t>& pK, const std::vector<uint8_t> ecP); bool convert_raw_to_der_ecdsa(const std::vector<uint8_t>& raw_signature, std::vector<uint8_t>& der_signature) const;
static void my_log_func(int level, const char* msg);
void print_pubkey_hex(gnutls_pubkey_t);
bool pubkey_copy(gnutls_pubkey_t src, gnutls_pubkey_t* dest); bool pubkey_copy(gnutls_pubkey_t src, gnutls_pubkey_t* dest);
#endif #endif
std::vector<uint8_t> d_x_4_0; std::vector<uint8_t> d_x_4_0;