diff --git a/src/core/system_parameters/gnss_crypto.cc b/src/core/system_parameters/gnss_crypto.cc index fd1403539..e664e4f50 100644 --- a/src/core/system_parameters/gnss_crypto.cc +++ b/src/core/system_parameters/gnss_crypto.cc @@ -794,13 +794,17 @@ std::vector Gnss_Crypto::get_merkle_root() const std::string Gnss_Crypto::get_public_key_type() const { + if (d_PublicKeyType.empty()) + { + return std::string("Unknown"); + } return d_PublicKeyType; } void Gnss_Crypto::set_public_key(const std::vector& publicKey) { - d_PublicKeyType = "Unknown"; + d_PublicKeyType = std::string("Unknown"); #if USE_GNUTLS_FALLBACK gnutls_pubkey_t pubkey{}; gnutls_ecc_curve_t curve; @@ -812,13 +816,13 @@ void Gnss_Crypto::set_public_key(const std::vector& publicKey) if (size_pk == 33) { curve = GNUTLS_ECC_CURVE_SECP256R1; - d_PublicKeyType = "ECDSA P-256"; + d_PublicKeyType = std::string("ECDSA P-256"); decompress_public_key_secp256r1(publicKey, x, y); } else if (size_pk == 67) { curve = GNUTLS_ECC_CURVE_SECP521R1; - d_PublicKeyType = "ECDSA P-521"; + d_PublicKeyType = std::string("ECDSA P-521"); decompress_public_key_secp521r1(publicKey, x, y); } else @@ -836,6 +840,7 @@ void Gnss_Crypto::set_public_key(const std::vector& publicKey) { gnutls_pubkey_deinit(pubkey); LOG(WARNING) << "GnuTLS: error setting the OSNMA public key: " << gnutls_strerror(ret); + d_PublicKeyType = std::string("Unknown"); return; } pubkey_copy(pubkey, &d_PublicKey); @@ -861,11 +866,11 @@ void Gnss_Crypto::set_public_key(const std::vector& publicKey) if (public_key_size == 33) { - d_PublicKeyType = "ECDSA P-256"; + d_PublicKeyType = std::string("ECDSA P-256"); } else if (public_key_size == 67) { - d_PublicKeyType = "ECDSA P-521"; + d_PublicKeyType = std::string("ECDSA P-521"); } ctx = EVP_PKEY_CTX_new_from_name(nullptr, "EC", nullptr); @@ -875,6 +880,7 @@ void Gnss_Crypto::set_public_key(const std::vector& publicKey) EVP_PKEY_CTX_free(ctx); OSSL_PARAM_free(params); OSSL_PARAM_BLD_free(param_bld); + d_PublicKeyType = std::string("Unknown"); return; } @@ -884,6 +890,7 @@ void Gnss_Crypto::set_public_key(const std::vector& publicKey) EVP_PKEY_CTX_free(ctx); OSSL_PARAM_free(params); OSSL_PARAM_BLD_free(param_bld); + d_PublicKeyType = std::string("Unknown"); return; } @@ -898,15 +905,16 @@ void Gnss_Crypto::set_public_key(const std::vector& publicKey) if (publicKey.size() == 33) // ECDSA-P-256 { group = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1); - d_PublicKeyType = "ECDSA P-256"; + d_PublicKeyType = std::string("ECDSA P-256"); } else // ECDSA-P-521 { group = EC_GROUP_new_by_curve_name(NID_secp521r1); - d_PublicKeyType = "ECDSA P-256"; + d_PublicKeyType = std::string("ECDSA P-521"); } if (!group) { + d_PublicKeyType = std::string("Unknown"); return; } @@ -914,6 +922,7 @@ void Gnss_Crypto::set_public_key(const std::vector& publicKey) if (!point) { EC_GROUP_free(group); + d_PublicKeyType = std::string("Unknown"); return; } @@ -921,6 +930,7 @@ void Gnss_Crypto::set_public_key(const std::vector& publicKey) { EC_GROUP_free(group); EC_POINT_free(point); + d_PublicKeyType = std::string("Unknown"); return; } @@ -936,18 +946,23 @@ void Gnss_Crypto::set_public_key(const std::vector& publicKey) { EC_GROUP_free(group); EC_POINT_free(point); + d_PublicKeyType = std::string("Unknown"); return; } - if (!EC_KEY_set_public_key(ec_key, point)) { EC_KEY_free(ec_key); EC_POINT_free(point); EC_GROUP_free(group); + d_PublicKeyType = std::string("Unknown"); return; } if (!pubkey_copy(ec_key, &d_PublicKey)) { + EC_KEY_free(ec_key); + EC_POINT_free(point); + EC_GROUP_free(group); + d_PublicKeyType = std::string("Unknown"); return; } EC_KEY_free(ec_key); @@ -1034,11 +1049,11 @@ void Gnss_Crypto::read_merkle_xml(const std::string& merkleFilePath) LOG(INFO) << "OSNMA Merkletree - PK Type: " << pkType; if (pkType == "ECDSA P-256/SHA-256") { - d_PublicKeyType = "ECDSA P-256"; + d_PublicKeyType = std::string("ECDSA P-256"); } else if (pkType == "ECDSA P-521/SHA-512") { - d_PublicKeyType = "ECDSA P-521"; + d_PublicKeyType = std::string("ECDSA P-521"); } } for (pugi::xml_node treeNode : merkleTree.children("TreeNode")) @@ -1075,7 +1090,7 @@ void Gnss_Crypto::readPublicKeyFromPEM(const std::string& pemFilePath) { return; } - d_PublicKeyType = "Unknown"; + d_PublicKeyType = std::string("Unknown"); std::string pemContent((std::istreambuf_iterator(pemFile)), std::istreambuf_iterator()); #if USE_GNUTLS_FALLBACK // Import the PEM data @@ -1108,8 +1123,7 @@ void Gnss_Crypto::readPublicKeyFromPEM(const std::string& pemFilePath) } pk_algorithm = static_cast(ret); - - if (pk_algorithm == GNUTLS_PK_ECDSA) + if (pk_algorithm == GNUTLS_PK_ECC) { gnutls_ecc_curve_t curve; ret = gnutls_pubkey_export_ecc_raw(pubkey, &curve, nullptr, nullptr); @@ -1122,11 +1136,11 @@ void Gnss_Crypto::readPublicKeyFromPEM(const std::string& pemFilePath) if (curve == GNUTLS_ECC_CURVE_SECP256R1) { - d_PublicKeyType = "ECDSA P-256"; + d_PublicKeyType = std::string("ECDSA P-256"); } else if (curve == GNUTLS_ECC_CURVE_SECP521R1) { - d_PublicKeyType = "ECDSA P-521"; + d_PublicKeyType = std::string("ECDSA P-521"); } else { @@ -1168,11 +1182,11 @@ void Gnss_Crypto::readPublicKeyFromPEM(const std::string& pemFilePath) { if (strcmp(curve_name, "prime256v1") == 0 || strcmp(curve_name, "P-256") == 0) { - d_PublicKeyType = "ECDSA P-256"; + d_PublicKeyType = std::string("ECDSA P-256"); } else if (strcmp(curve_name, "secp521r1") == 0 || strcmp(curve_name, "P-521") == 0) { - d_PublicKeyType = "ECDSA P-521"; + d_PublicKeyType = std::string("ECDSA P-521"); } else { @@ -1210,7 +1224,6 @@ void Gnss_Crypto::readPublicKeyFromPEM(const std::string& pemFilePath) } const EC_GROUP* group = EC_KEY_get0_group(pubkey); int nid = EC_GROUP_get_curve_name(group); - if (nid == 0) { BIGNUM* p = BN_new(); @@ -1220,11 +1233,11 @@ void Gnss_Crypto::readPublicKeyFromPEM(const std::string& pemFilePath) const std::string pcstr(p_str); if (pcstr.size() == 64) { - d_PublicKeyType = "ECDSA P-256"; + d_PublicKeyType = std::string("ECDSA P-256"); } else if (pcstr.size() == 132) { - d_PublicKeyType = "ECDSA P-521"; + d_PublicKeyType = std::string("ECDSA P-521"); } OPENSSL_free(p_str); } @@ -1236,11 +1249,11 @@ void Gnss_Crypto::readPublicKeyFromPEM(const std::string& pemFilePath) const std::string curve_str(curve_name); if (curve_str == "prime256v1") { - d_PublicKeyType = "ECDSA P-256"; + d_PublicKeyType = std::string("ECDSA P-256"); } else if (curve_str == "secp521r1") { - d_PublicKeyType = "ECDSA P-521"; + d_PublicKeyType = std::string("ECDSA P-521"); } } @@ -1262,8 +1275,7 @@ void Gnss_Crypto::readPublicKeyFromPEM(const std::string& pemFilePath) bool Gnss_Crypto::readPublicKeyFromCRT(const std::string& crtFilePath) { - d_PublicKeyType = "Unknown"; -#if USE_GNUTLS_FALLBACK + d_PublicKeyType = std::string("Unknown"); // Open the .crt file std::ifstream crtFile(crtFilePath, std::ios::binary); if (!crtFile.is_open()) @@ -1278,8 +1290,8 @@ bool Gnss_Crypto::readPublicKeyFromCRT(const std::string& crtFilePath) } const std::vector buffer((std::istreambuf_iterator(crtFile)), std::istreambuf_iterator()); +#if USE_GNUTLS_FALLBACK const gnutls_datum_t buffer_datum = {const_cast(buffer.data()), static_cast(buffer.size())}; - gnutls_x509_crt_t cert; gnutls_x509_crt_init(&cert); int ret = gnutls_x509_crt_import(cert, &buffer_datum, GNUTLS_X509_FMT_PEM); @@ -1316,8 +1328,7 @@ bool Gnss_Crypto::readPublicKeyFromCRT(const std::string& crtFilePath) } pk_algorithm = static_cast(ret); - - if (pk_algorithm == GNUTLS_PK_ECDSA) + if (pk_algorithm == GNUTLS_PK_ECC) { gnutls_ecc_curve_t curve; ret = gnutls_pubkey_export_ecc_raw(pubkey, &curve, nullptr, nullptr); @@ -1331,11 +1342,11 @@ bool Gnss_Crypto::readPublicKeyFromCRT(const std::string& crtFilePath) if (curve == GNUTLS_ECC_CURVE_SECP256R1) { - d_PublicKeyType = "ECDSA P-256"; + d_PublicKeyType = std::string("ECDSA P-256"); } else if (curve == GNUTLS_ECC_CURVE_SECP521R1) { - d_PublicKeyType = "ECDSA P-521"; + d_PublicKeyType = std::string("ECDSA P-521"); } else { @@ -1357,16 +1368,7 @@ bool Gnss_Crypto::readPublicKeyFromCRT(const std::string& crtFilePath) gnutls_x509_crt_deinit(cert); gnutls_pubkey_deinit(pubkey); #else // OpenSSL - // Open the .crt file - std::ifstream crtFile(crtFilePath, std::ios::binary); - if (!crtFile.is_open()) - { - LOG(WARNING) << "OpenSSL: Unable to open file: " << crtFilePath; - return false; - } - // Read certificate - std::vector buffer((std::istreambuf_iterator(crtFile)), std::istreambuf_iterator()); BIO* bio = BIO_new_mem_buf(buffer.data(), buffer.size()); if (!bio) { @@ -1387,6 +1389,7 @@ bool Gnss_Crypto::readPublicKeyFromCRT(const std::string& crtFilePath) { LOG(WARNING) << "OpenSSL: Failed to extract the public key"; X509_free(cert); + BIO_free(bio); return false; } #if USE_OPENSSL_3 @@ -1403,24 +1406,25 @@ bool Gnss_Crypto::readPublicKeyFromCRT(const std::string& crtFilePath) { if (strcmp(curve_name, "prime256v1") == 0 || strcmp(curve_name, "P-256") == 0) { - d_PublicKeyType = "ECDSA P-256"; + d_PublicKeyType = std::string("ECDSA P-256"); } else if (strcmp(curve_name, "secp521r1") == 0 || strcmp(curve_name, "P-521") == 0) { - d_PublicKeyType = "ECDSA P-521"; + d_PublicKeyType = std::string("ECDSA P-521"); } else { LOG(WARNING) << "OpenSSL: Trying to read an unknown EC curve"; X509_free(cert); + BIO_free(bio); return false; } } else { - d_PublicKeyType = "Unknown EC curve"; LOG(WARNING) << "OpenSSL: Trying to read an unknown EC curve"; X509_free(cert); + BIO_free(bio); return false; } } @@ -1428,6 +1432,7 @@ bool Gnss_Crypto::readPublicKeyFromCRT(const std::string& crtFilePath) { LOG(WARNING) << "OpenSSL: Trying to read an unknown key type"; X509_free(cert); + BIO_free(bio); return false; } pubkey_copy(pubkey, &d_PublicKey); @@ -1441,22 +1446,25 @@ bool Gnss_Crypto::readPublicKeyFromCRT(const std::string& crtFilePath) { X509_free(cert); EC_KEY_free(ec_key); + BIO_free(bio); return false; } const int nid = EC_GROUP_get_curve_name(group); if (nid == NID_X9_62_prime256v1) { - d_PublicKeyType = "ECDSA P-256"; + d_PublicKeyType = std::string("ECDSA P-256"); } else if (nid == NID_secp521r1) { - d_PublicKeyType = "ECDSA P-521"; + d_PublicKeyType = std::string("ECDSA P-521"); } + EC_KEY_free(ec_key); #else EC_KEY* ec_key = EVP_PKEY_get1_EC_KEY(pubkey); if (!ec_key) { X509_free(cert); + BIO_free(bio); return false; } @@ -1466,6 +1474,7 @@ bool Gnss_Crypto::readPublicKeyFromCRT(const std::string& crtFilePath) { X509_free(cert); EC_KEY_free(ec_key); + BIO_free(bio); return false; } const int nid = EC_GROUP_get_curve_name(group); @@ -1478,11 +1487,11 @@ bool Gnss_Crypto::readPublicKeyFromCRT(const std::string& crtFilePath) const std::string pcstr(p_str); if (pcstr.size() == 64) { - d_PublicKeyType = "ECDSA P-256"; + d_PublicKeyType = std::string("ECDSA P-256"); } else if (pcstr.size() == 132) { - d_PublicKeyType = "ECDSA P-521"; + d_PublicKeyType = std::string("ECDSA P-521"); } OPENSSL_free(p_str); } @@ -1494,13 +1503,14 @@ bool Gnss_Crypto::readPublicKeyFromCRT(const std::string& crtFilePath) const std::string curve_str(curve_name); if (curve_str == "prime256v1") { - d_PublicKeyType = "ECDSA P-256"; + d_PublicKeyType = std::string("ECDSA P-256"); } else if (curve_str == "secp521r1") { - d_PublicKeyType = "ECDSA P-521"; + d_PublicKeyType = std::string("ECDSA P-521"); } } + EC_KEY_free(ec_key); #endif EC_KEY* ec_pubkey = EVP_PKEY_get1_EC_KEY(pubkey); EVP_PKEY_free(pubkey); diff --git a/src/tests/unit-tests/signal-processing-blocks/osnma/gnss_crypto_test.cc b/src/tests/unit-tests/signal-processing-blocks/osnma/gnss_crypto_test.cc index 1904a16e9..2e536fb73 100644 --- a/src/tests/unit-tests/signal-processing-blocks/osnma/gnss_crypto_test.cc +++ b/src/tests/unit-tests/signal-processing-blocks/osnma/gnss_crypto_test.cc @@ -49,10 +49,9 @@ TEST(GnssCryptoTest, VerifyPubKeyImport) TEST(GnssCryptoTest, VerifyPublicKeyStorage) { - auto d_crypto = std::make_unique(); - const std::string f1("./osnma_test_file1.pem"); const std::string f2("./osnma_test_file2.pem"); + const std::string f3("./osnma_test_file3.pem"); // Input taken from RG 1.3 A7.1 // compressed ECDSA P-256 format @@ -62,15 +61,17 @@ TEST(GnssCryptoTest, VerifyPublicKeyStorage) 0x63, 0xFF, 0xA0, 0x91, 0x41, 0x0F, 0xC1, 0x58, 0xFB, 0xB7, 0x79, 0x80, 0xEA}; + auto d_crypto = std::make_unique(); + ASSERT_FALSE(d_crypto->have_public_key()); + ASSERT_TRUE(d_crypto->get_public_key_type() == "Unknown"); d_crypto->set_public_key(publicKey); - bool result = d_crypto->store_public_key(f1); - - ASSERT_TRUE(result); + ASSERT_TRUE(d_crypto->have_public_key()); + ASSERT_TRUE(d_crypto->store_public_key(f1)); auto d_crypto2 = std::make_unique(f1, ""); - bool result2 = d_crypto2->store_public_key(f2); - ASSERT_TRUE(result2); + ASSERT_TRUE(d_crypto2->have_public_key()); ASSERT_TRUE(d_crypto2->get_public_key_type() == "ECDSA P-256"); + ASSERT_TRUE(d_crypto2->store_public_key(f2)); std::ifstream t(f1); std::string content_file((std::istreambuf_iterator(t)), std::istreambuf_iterator()); @@ -80,9 +81,39 @@ TEST(GnssCryptoTest, VerifyPublicKeyStorage) ASSERT_EQ(content_file, content_file2); + // P-521 Public key in compressed X format + std::vector publicKey_P521 = { + 0x03, 0x00, 0x28, 0x35, 0xBB, 0xE9, 0x24, 0x59, 0x4E, 0xF0, + 0xE3, 0xA2, 0xDB, 0xC0, 0x49, 0x30, 0x60, 0x7C, 0x61, 0x90, + 0xE4, 0x03, 0xE0, 0xC7, 0xB8, 0xC2, 0x62, 0x37, 0xF7, 0x58, + 0x56, 0xBE, 0x63, 0x5C, 0x97, 0xF7, 0x53, 0x64, 0x7E, 0xE1, + 0x0C, 0x07, 0xD3, 0x97, 0x8D, 0x58, 0x46, 0xFD, 0x6E, 0x06, + 0x44, 0x01, 0xA7, 0xAA, 0xC4, 0x95, 0x13, 0x5D, 0xC9, 0x77, + 0x26, 0xE9, 0xF8, 0x72, 0x0C, 0xD3, 0x88}; + + d_crypto->set_public_key(publicKey_P521); + ASSERT_TRUE(d_crypto->have_public_key()); + ASSERT_TRUE(d_crypto->get_public_key_type() == "ECDSA P-521"); + ASSERT_TRUE(d_crypto->store_public_key(f3)); + + auto d_crypto3 = std::make_unique(f3, ""); + ASSERT_TRUE(d_crypto3->have_public_key()); + ASSERT_TRUE(d_crypto3->get_public_key_type() == "ECDSA P-521"); + + std::vector wrong_publicKey = { + 0x03, 0x03, 0xB2, 0xCE, 0x64, 0xBC, 0x20, 0x7B, 0xDD, 0x8B, + 0xC4, 0xDF, 0x85, 0x91, 0x87, 0xFC, 0xB6, 0x86, 0x32, 0x0D, + 0x63, 0xFF, 0xA0}; + + auto d_crypto4 = std::make_unique(); + d_crypto4->set_public_key(wrong_publicKey); + ASSERT_FALSE(d_crypto4->have_public_key()); + ASSERT_TRUE(d_crypto4->get_public_key_type() == "Unknown"); + errorlib::error_code ec; ASSERT_TRUE(fs::remove(fs::path(f1), ec)); ASSERT_TRUE(fs::remove(fs::path(f2), ec)); + ASSERT_TRUE(fs::remove(fs::path(f3), ec)); } @@ -263,13 +294,11 @@ TEST(GnssCryptoTest, VerifySignatureP256) 0x79, 0x80, 0xEA}; d_crypto->set_public_key(publicKey); - bool result = d_crypto->verify_signature_ecdsa_p256(message, signature); - ASSERT_TRUE(result); + ASSERT_TRUE(d_crypto->verify_signature_ecdsa_p256(message, signature)); std::vector wrong_signature = signature; wrong_signature[1] = 1; - bool result2 = d_crypto->verify_signature_ecdsa_p256(message, wrong_signature); - ASSERT_TRUE(!result2); + ASSERT_FALSE(d_crypto->verify_signature_ecdsa_p256(message, wrong_signature)); } @@ -309,11 +338,9 @@ TEST(GnssCryptoTest, VerifySignatureP521) 0x28, 0xEF}; d_crypto->set_public_key(publicKey); - bool result = d_crypto->verify_signature_ecdsa_p521(message, signature); - ASSERT_TRUE(result); + ASSERT_TRUE(d_crypto->verify_signature_ecdsa_p521(message, signature)); std::vector wrong_signature = signature; wrong_signature[1] = 1; - bool result2 = d_crypto->verify_signature_ecdsa_p521(message, wrong_signature); - ASSERT_TRUE(!result2); + ASSERT_FALSE(d_crypto->verify_signature_ecdsa_p521(message, wrong_signature)); }