1
0
mirror of https://github.com/gnss-sdr/gnss-sdr synced 2024-12-13 19:50:34 +00:00

Bugfix for Gnss_Crypto::verify_signature

The commit introduces conversion from raw signature (r, s values) into DER format for the ossl3 region, after realising that that was making the verification fail.
This commit is contained in:
cesaaargm 2024-05-06 17:52:07 +02:00
parent 359631b534
commit b687d4cafe

View File

@ -34,6 +34,9 @@
#include <openssl/bio.h> #include <openssl/bio.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/bn.h>
#define OPENSSL_ENGINE nullptr #define OPENSSL_ENGINE nullptr
#else #else
#include <openssl/sha.h> #include <openssl/sha.h>
@ -490,7 +493,7 @@ 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); //print_pubkey_hex(d_PublicKey);
} }
@ -545,7 +548,7 @@ bool Gnss_Crypto::verify_signature(const std::vector<uint8_t>& message, const st
#if USE_OPENSSL_3 #if USE_OPENSSL_3
EVP_PKEY_CTX* ctx; EVP_PKEY_CTX* ctx;
print_pubkey_hex(d_PublicKey); //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;
@ -553,6 +556,42 @@ 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
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());
// Convert raw R and S to BIGNUMs
BIGNUM* r = BN_bin2bn(raw_r.data(), raw_r.size(), nullptr);
BIGNUM* s = BN_bin2bn(raw_s.data(), raw_s.size(), nullptr);
ECDSA_SIG* sig = ECDSA_SIG_new();
if (r == nullptr || s == nullptr || sig == nullptr)
{
std::cerr << "Failed to allocate memory for BIGNUMs or ECDSA_SIG" << std::endl;
return false;
}
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
return false;
}
std::vector<uint8_t> derSignature;
unsigned char *derSig = nullptr;
int derSigLength = i2d_ECDSA_SIG(sig, &derSig);
if (derSigLength <= 0)
{
std::cerr << "Failed to convert ECDSA_SIG to DER format" << std::endl;
return false;
}
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;
@ -564,9 +603,11 @@ bool Gnss_Crypto::verify_signature(const std::vector<uint8_t>& message, const st
int verification = 0; int verification = 0;
if (do_operation) if (do_operation)
{ {
verification = EVP_PKEY_verify(ctx, signature.data(), signature.size(), digest.data(), digest.size()); verification = EVP_PKEY_verify(ctx, derSignature.data(), derSignature.size(), digest.data(), digest.size());
} }
EVP_PKEY_CTX_free(ctx); EVP_PKEY_CTX_free(ctx);
OPENSSL_free(derSig);
ECDSA_SIG_free(sig);
if (verification == 1) if (verification == 1)
{ {
success = true; success = true;
@ -682,7 +723,7 @@ void Gnss_Crypto::set_public_key(const std::vector<uint8_t>& publicKey)
<< ". Aborting import" << std::endl; << ". Aborting import" << std::endl;
return; return;
} }
print_pubkey_hex(pkey); //print_pubkey_hex(pkey);
if(!pubkey_copy(pkey, &d_PublicKey)) if(!pubkey_copy(pkey, &d_PublicKey))
return return
@ -736,7 +777,6 @@ std::vector<uint8_t> Gnss_Crypto::get_public_key()
return {}; 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)
{ {
@ -809,7 +849,7 @@ void Gnss_Crypto::print_pubkey_hex(EVP_PKEY* pubkey)
static_cast<int>(static_cast<unsigned char>(mem_ptr->data[i])); static_cast<int>(static_cast<unsigned char>(mem_ptr->data[i]));
} }
std::cout << "Public key in hex format: 0x" << ss.str() << std::endl; //std::cout << "Public key in hex format: 0x" << ss.str() << std::endl;
BIO_free(mem_bio); BIO_free(mem_bio);
} }