diff --git a/src/core/system_parameters/gnss_crypto.cc b/src/core/system_parameters/gnss_crypto.cc index 06c9d6538..947b8a436 100644 --- a/src/core/system_parameters/gnss_crypto.cc +++ b/src/core/system_parameters/gnss_crypto.cc @@ -38,6 +38,7 @@ #include #include #include +#include #define OPENSSL_ENGINE nullptr #else #include @@ -416,35 +417,62 @@ std::vector Gnss_Crypto::computeCMAC_AES(const std::vector& ke std::vector output(16); #if USE_OPENSSL_FALLBACK #if USE_OPENSSL_3 - std::vector mac(EVP_MAX_MD_SIZE); // CMAC-AES output size + std::vector 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("AES-128-CBC"), 0), + OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY, const_cast(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 mac(16); // CMAC-AES output size 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 95137e21d..87f5afbfa 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 @@ -44,7 +44,7 @@ TEST(GnssCryptoTest, VerifySignature) // RG example - import crt certificate - result: FAIL std::vector 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 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 publicKey{ // PEM format - 1000 bits + std::vector 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, @@ -109,11 +109,11 @@ TEST(GnssCryptoTest, TestComputeHMACSHA256_m0) // key and message generated from RG A.6.5.1 std::unique_ptr d_crypto = std::make_unique(); - std::vector key = { // RG K4 @ 345690 + std::vector key = {// RG K4 @ 345690 0x69, 0xC0, 0x0A, 0xA7, 0x36, 0x42, 0x37, 0xA6, 0x5E, 0xBF, 0x00, 0x6A, 0xD8, 0xDD, 0xBC, 0x73}; - std::vector message{ // m0 + std::vector message{// m0 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, @@ -136,7 +136,7 @@ TEST(GnssCryptoTest, TestComputeHMACSHA256_adkd4) // key and message generated from RG A.6.5.2 std::unique_ptr d_crypto = std::make_unique(); - std::vector key = { // RG K4 @ 345690 + std::vector key = {// RG K4 @ 345690 0x69, 0xC0, 0x0A, 0xA7, 0x36, 0x42, 0x37, 0xA6, 0x5E, 0xBF, 0x00, 0x6A, 0xD8, 0xDD, 0xBC, 0x73}; @@ -155,4 +155,25 @@ TEST(GnssCryptoTest, TestComputeHMACSHA256_adkd4) ASSERT_EQ(expected_output, output); } -// TODO extend to HMAC-AES \ No newline at end of file + +TEST(GnssCryptoTest, TestComputeCMAC_AES) +{ + // Tests vectors from https://datatracker.ietf.org/doc/html/rfc4493#appendix-A + std::unique_ptr d_crypto = std::make_unique(); + + std::vector key = { + 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, + 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C}; + + std::vector message{ + 0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96, + 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A}; + + std::vector expected_output = { + 0x07, 0x0A, 0x16, 0xB4, 0x6B, 0x4D, 0x41, 0x44, + 0xF7, 0x9B, 0xDD, 0x9D, 0xD0, 0x4A, 0x28, 0x7C}; + + std::vector output = d_crypto->computeCMAC_AES(key, message); + + ASSERT_EQ(expected_output, output); +} \ No newline at end of file