2024-07-23 09:16:45 +00:00
/*!
2024-07-26 16:09:25 +00:00
* \ file osmna_msg_receiver_test . cc
2024-07-23 09:16:45 +00:00
* \ brief Tests for the osnma_msg_receiver class .
* \ author Carles Fernandez , 2023 - 2024. cfernandez ( at ) cttc . es
* Cesare Ghionoiu Martinez , 2023 - 2024. c . ghionoiu - martinez @ tu - braunschweig . de
*
*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*
* GNSS - SDR is a Global Navigation Satellite System software - defined receiver .
* This file is part of GNSS - SDR .
*
* Copyright ( C ) 2010 - 2024 ( see AUTHORS file for a list of contributors )
* SPDX - License - Identifier : GPL - 3.0 - or - later
*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
2024-08-11 10:44:18 +00:00
# include "Galileo_OSNMA.h"
# include "gnss_crypto.h"
# include "osnma_helper.h"
# include "osnma_msg_receiver.h"
2024-04-18 22:47:31 +00:00
# include <gtest/gtest.h>
2024-05-06 15:58:56 +00:00
# include <bitset>
2024-06-30 08:10:03 +00:00
# include <chrono>
2024-04-18 22:47:31 +00:00
# include <fstream>
# include <vector>
2024-06-29 09:10:35 +00:00
# if USE_GLOG_AND_GFLAGS
# include <glog/logging.h> // for LOG
# else
# include <absl/log/log.h>
# endif
2024-04-18 22:47:31 +00:00
class OsnmaMsgReceiverTest : public : : testing : : Test
{
protected :
2024-07-09 15:13:40 +00:00
Osnma_Helper helper ;
2024-04-18 22:47:31 +00:00
osnma_msg_receiver_sptr osnma ;
OSNMA_msg osnma_msg { } ;
std : : array < int8_t , 15 > nma_position_filled ;
2024-06-26 13:01:05 +00:00
uint32_t d_GST_SIS { } ;
2024-04-18 22:47:31 +00:00
uint32_t TOW { } ;
uint32_t WN { } ;
2024-07-27 17:14:13 +00:00
std : : tm GST_START_EPOCH = { 0 , 0 , 0 , 22 , 8 - 1 , 1999 - 1900 , 0 , 0 , 0 , 0 , 0 } ; // months start with 0 and years since 1900 in std::tm
2024-08-11 10:44:18 +00:00
const uint32_t LEAP_SECONDS = 0 ; // tried with 13 + 5, which is the official count, but won't parse correctly
2024-04-18 22:47:31 +00:00
void set_time ( std : : tm & input ) ;
void SetUp ( ) override
{
2024-07-27 17:14:13 +00:00
// std::tm input_time = {0, 0, 5, 16, 8 - 1, 2023 - 1900, 0, 0, 0, 0, 0}; // conf. 1
std : : tm input_time = { 0 , 0 , 0 , 27 , 7 - 1 , 2023 - 1900 , 0 , 0 , 0 , 0 , 0 } ; // conf. 2
2024-04-18 22:47:31 +00:00
set_time ( input_time ) ;
2024-07-27 16:25:20 +00:00
osnma = osnma_msg_receiver_make ( CRTFILE_DEFAULT , MERKLEFILE_DEFAULT ) ;
2024-04-18 22:47:31 +00:00
}
} ;
2024-07-23 09:16:45 +00:00
2024-07-09 15:13:40 +00:00
TEST_F ( OsnmaMsgReceiverTest , ComputeMerkleRoot )
{
2024-07-23 18:53:05 +00:00
// input data taken from Receiver Guidelines v1.3, A.7
2024-07-09 15:13:40 +00:00
// Arrange
std : : vector < uint8_t > computed_merkle_root ;
std : : vector < uint8_t > expected_merkle_root = helper . convert_from_hex_string ( " A10C440F3AA62453526DB4AF76DF8D9410D35D8277397D7053C700D192702B0D " ) ;
DSM_PKR_message dsm_pkr_message ;
dsm_pkr_message . npkt = 0x01 ;
dsm_pkr_message . npktid = 0x2 ;
dsm_pkr_message . mid = 0x01 ;
std : : vector < uint8_t > base_leaf = helper . convert_from_hex_string ( " 120303B2CE64BC207BDD8BC4DF859187FCB686320D63FFA091410FC158FBB77980EA " ) ;
2024-07-23 18:53:05 +00:00
// ITN
2024-07-23 09:16:45 +00:00
std : : vector < uint8_t > vec = helper . convert_from_hex_string (
" 7CBE05D9970CFC9E22D0A43A340EF557624453A2E821AADEAC989C405D78BA06 "
2024-07-09 15:13:40 +00:00
" 956380BAB0D2C939EC6208151040CCFFCF1FB7156178FD1255BA0AECAAA253F7 "
" 407B6C5DD4DF059FF8789474061301E1C34881DB7A367A913A3674300E21EAB1 "
" 24EF508389B7D446C3E2ECE8D459FBBD3239A794906F5B1F92469C640164FD87 " ) ;
std : : copy ( vec . begin ( ) , vec . end ( ) , dsm_pkr_message . itn . begin ( ) ) ;
dsm_pkr_message . npk = helper . convert_from_hex_string ( " 0303B2CE64BC207BDD8BC4DF859187FCB686320D63FFA091410FC158FBB77980EA " ) ;
// Act
2024-07-20 19:25:53 +00:00
computed_merkle_root = osnma - > compute_merkle_root ( dsm_pkr_message , base_leaf ) ;
2024-07-09 15:13:40 +00:00
// Assert
ASSERT_EQ ( computed_merkle_root , expected_merkle_root ) ;
}
2024-07-23 09:16:45 +00:00
2024-07-09 15:13:40 +00:00
TEST_F ( OsnmaMsgReceiverTest , ComputeBaseLeaf )
{
2024-07-23 18:53:05 +00:00
// input data taken from Receiver Guidelines v1.3, A.7
2024-07-09 15:13:40 +00:00
// Arrange
std : : vector < uint8_t > expected_base_leaf = helper . convert_from_hex_string ( " 120303B2CE64BC207BDD8BC4DF859187FCB686320D63FFA091410FC158FBB77980EA " ) ;
DSM_PKR_message dsm_pkr_message ;
dsm_pkr_message . npkt = 0x01 ;
dsm_pkr_message . npktid = 0x2 ;
dsm_pkr_message . npk = helper . convert_from_hex_string ( " 0303B2CE64BC207BDD8BC4DF859187FCB686320D63FFA091410FC158FBB77980EA " ) ;
// Act
2024-07-20 19:25:53 +00:00
std : : vector < uint8_t > computed_base_leaf = osnma - > get_merkle_tree_leaves ( dsm_pkr_message ) ;
2024-07-09 15:13:40 +00:00
// Assert
2024-07-23 09:16:45 +00:00
ASSERT_EQ ( computed_base_leaf , expected_base_leaf ) ;
2024-07-09 15:13:40 +00:00
}
2024-07-23 18:53:05 +00:00
2024-07-23 09:16:45 +00:00
TEST_F ( OsnmaMsgReceiverTest , VerifyPublicKey )
2024-07-25 12:48:29 +00:00
{
// Input data taken from Receiver Guidelines v1.3, A.7
2024-07-09 15:13:40 +00:00
// Arrange
2024-07-18 08:49:52 +00:00
osnma - > d_crypto - > set_merkle_root ( helper . convert_from_hex_string ( " A10C440F3AA62453526DB4AF76DF8D9410D35D8277397D7053C700D192702B0D " ) ) ;
2024-07-09 15:13:40 +00:00
DSM_PKR_message dsm_pkr_message ;
dsm_pkr_message . npkt = 0x01 ;
dsm_pkr_message . npktid = 0x2 ;
dsm_pkr_message . mid = 0x01 ;
2024-07-23 09:16:45 +00:00
std : : vector < uint8_t > vec = helper . convert_from_hex_string (
" 7CBE05D9970CFC9E22D0A43A340EF557624453A2E821AADEAC989C405D78BA06 "
" 956380BAB0D2C939EC6208151040CCFFCF1FB7156178FD1255BA0AECAAA253F7 "
" 407B6C5DD4DF059FF8789474061301E1C34881DB7A367A913A3674300E21EAB1 "
" 24EF508389B7D446C3E2ECE8D459FBBD3239A794906F5B1F92469C640164FD87 " ) ;
2024-07-09 15:13:40 +00:00
std : : copy ( vec . begin ( ) , vec . end ( ) , dsm_pkr_message . itn . begin ( ) ) ;
dsm_pkr_message . npk = helper . convert_from_hex_string ( " 0303B2CE64BC207BDD8BC4DF859187FCB686320D63FFA091410FC158FBB77980EA " ) ;
// Act
2024-07-25 12:48:29 +00:00
bool result = osnma - > verify_dsm_pkr ( dsm_pkr_message ) ; // TODO - refactor method so that output is more than a boolean.
2024-07-09 15:13:40 +00:00
// Assert
ASSERT_TRUE ( result ) ;
}
2024-04-18 22:47:31 +00:00
2024-07-23 09:16:45 +00:00
2024-06-26 13:01:05 +00:00
TEST_F ( OsnmaMsgReceiverTest , BuildTagMessageM0 )
2024-06-23 09:10:40 +00:00
{
2024-07-23 18:53:05 +00:00
// input data taken from Receiver Guidelines v1.3, A.6.5.1
2024-06-26 13:01:05 +00:00
// Arrange
2024-07-23 09:16:45 +00:00
std : : vector < uint8_t > expected_message = {
2024-06-26 13:01:05 +00:00
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 ,
2024-07-23 09:16:45 +00:00
0x02 , 0x68 , 0x05 , 0x4A , 0x02 , 0xC2 , 0x26 , 0x07 , 0xF7 , 0xFC , 0x00 } ;
2024-06-26 13:01:05 +00:00
uint32_t TOW_Tag0 = 345660 ;
uint32_t TOW_NavData = TOW_Tag0 - 30 ;
2024-07-23 09:16:45 +00:00
uint32_t TOW_Key_Tag0 = TOW_Tag0 + 30 ;
2024-06-26 13:01:05 +00:00
uint32_t WN = 1248 ;
uint32_t PRNa = 2 ;
uint8_t CTR = 1 ;
2024-07-23 09:16:45 +00:00
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
2024-06-26 13:01:05 +00:00
osnma - > d_osnma_data . d_dsm_kroot_message . mf = 0 ;
2024-07-25 14:00:43 +00:00
osnma - > d_nav_data_manager - > add_navigation_data (
2024-07-23 09:16:45 +00:00
" 000011101001011001000100000101000111010110100100100101100000000000 "
" 011101101011001111101110101010000001010000011011111100000011101011 "
" 011100101101011010101011011011001001110111101011110110111111001111 "
" 001000011111101110011000111111110111111010000011101011111111110000 "
" 110111000000100000001110110000110110001110000100001110101100010100 "
" 110100010001000110001110011010110000111010000010000000000001101000 "
" 000000000011100101100100010000000000000110110100110001111100000000 "
" 000000100110100000000101010010100000001011000010001001100000011111 "
2024-07-25 14:00:43 +00:00
" 110111111111000000000 " ,
PRNa , TOW_NavData ) ;
2024-06-26 13:01:05 +00:00
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 ) ;
}
2024-07-23 09:16:45 +00:00
TEST_F ( OsnmaMsgReceiverTest , TagVerification )
{
2024-07-23 18:53:05 +00:00
// input data taken from Receiver Guidelines v1.3, A.6.5.1
2024-06-26 13:01:05 +00:00
// Arrange
// Tag0
uint32_t TOW_Tag0 = 345660 ;
uint32_t TOW_NavData = TOW_Tag0 - 30 ;
2024-07-23 09:16:45 +00:00
uint32_t TOW_Key_Tag0 = TOW_Tag0 + 30 ;
2024-06-26 13:01:05 +00:00
uint32_t WN = 1248 ;
uint32_t PRNa = 2 ;
uint8_t CTR = 1 ;
2024-07-23 09:16:45 +00:00
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
2024-06-26 13:01:05 +00:00
osnma - > d_osnma_data . d_dsm_kroot_message . mf = 0 ;
2024-07-25 14:00:43 +00:00
osnma - > d_nav_data_manager - > add_navigation_data (
2024-07-26 16:09:25 +00:00
" 000011101001011001000100000101000111010110100100100101100000000000 "
" 011101101011001111101110101010000001010000011011111100000011101011 "
" 011100101101011010101011011011001001110111101011110110111111001111 "
" 001000011111101110011000111111110111111010000011101011111111110000 "
" 110111000000100000001110110000110110001110000100001110101100010100 "
" 110100010001000110001110011010110000111010000010000000000001101000 "
" 000000000011100101100100010000000000000110110100110001111100000000 "
" 000000100110100000000101010010100000001011000010001001100000011111 "
" 110111111111000000000 " ,
PRNa , TOW_NavData ) ;
2024-06-26 13:01:05 +00:00
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
// Tag3
2024-07-23 09:16:45 +00:00
uint32_t TOW_Key_Tag3 = TOW_Tag0 + 30 ;
2024-06-26 13:01:05 +00:00
WN = 1248 ;
PRNa = 2 ;
CTR = 3 ;
2024-07-23 09:16:45 +00:00
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
2024-06-26 13:01:05 +00:00
osnma - > d_osnma_data . d_dsm_kroot_message . mf = 0 ;
2024-07-25 14:00:43 +00:00
osnma - > d_nav_data_manager - > add_navigation_data (
2024-06-26 13:01:05 +00:00
" 111111111111111111111111111111110000000000000000000000010001001001001000 "
2024-07-26 16:09:25 +00:00
" 111000001000100111100010010111111111011110111111111001001100000100000 " ,
PRNa , TOW_NavData ) ;
2024-06-26 13:01:05 +00:00
osnma - > d_osnma_data . d_nma_header . nmas = 0b10 ;
MTI . tag = static_cast < uint64_t > ( 0x7BB238C883 ) ;
MTI . tag_info . PRN_d = 0x02 ;
MTI . tag_info . ADKD = 0x04 ;
MTI . tag_info . cop = 0x0F ;
Tag t3 ( MTI , TOW_Tag0 , WN , PRNa , CTR ) ;
bool result_tag3 = osnma - > verify_tag ( t3 ) ;
ASSERT_TRUE ( result_tag0 & & result_tag3 ) ;
}
2024-07-23 09:16:45 +00:00
TEST_F ( OsnmaMsgReceiverTest , TeslaKeyVerification )
{
2024-07-23 18:53:05 +00:00
// input data taken from Receiver Guidelines v1.3, A.5.2
2024-04-18 22:47:31 +00:00
// Arrange
osnma - > d_tesla_key_verified = false ;
2024-07-23 09:16:45 +00:00
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
2024-05-06 15:58:56 +00:00
osnma - > d_osnma_data . d_dsm_kroot_message . alpha = 0x610BDF26D77B ;
osnma - > d_GST_SIS = ( 1248 & 0x00000FFF ) < < 20 | ( 345630 & 0x000FFFFF ) ;
2024-08-11 10:44:18 +00:00
osnma - > d_GST_0 = ( ( 1248 & 0x00000FFF ) < < 20 | ( 345600 & 0x000FFFFF ) ) ; // applicable time (GST_Kroot + 30)
2024-08-01 09:52:28 +00:00
osnma - > d_GST_Sf = osnma - > d_GST_0 + 30 * std : : floor ( ( osnma - > d_GST_SIS - osnma - > d_GST_0 ) / 30 ) ; // Eq. 3 R.G.
2024-05-06 15:58:56 +00:00
2024-07-23 09:16:45 +00:00
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
2024-04-18 22:47:31 +00:00
uint32_t TOW = 345630 ;
// Act
2024-07-25 12:48:29 +00:00
bool result = osnma - > verify_tesla_key ( key , TOW ) ; // TODO - refactor so that output is not a boolean. Or use last_verified_tesla_key?
2024-06-26 13:01:05 +00:00
2024-04-18 22:47:31 +00:00
// Assert
2024-05-14 14:15:17 +00:00
ASSERT_TRUE ( result ) ;
2024-06-26 13:01:05 +00:00
}
2024-06-23 09:10:40 +00:00
2024-07-23 09:16:45 +00:00
2024-05-06 15:58:56 +00:00
/**
* @ brief Sets the time based on the given input .
*
* This function calculates the week number ( WN ) and time of week ( TOW )
* based on the input time and the GST_START_EPOCH . It then stores the
* calculated values in the WN and TOW member variables . Finally , it
* combines the WN and TOW into a single 32 - bit value and stores it in
* the d_GST_SIS member variable .
*
* @ param input The input time as a tm struct .
*/
2024-04-18 22:47:31 +00:00
void OsnmaMsgReceiverTest : : set_time ( std : : tm & input )
{
2024-05-06 15:58:56 +00:00
auto epoch_time_point = std : : chrono : : system_clock : : from_time_t ( mktime ( & GST_START_EPOCH ) ) ;
2024-04-18 22:47:31 +00:00
auto input_time_point = std : : chrono : : system_clock : : from_time_t ( mktime ( & input ) ) ;
// Get the duration from epoch in seconds
auto duration_sec = std : : chrono : : duration_cast < std : : chrono : : seconds > ( input_time_point - epoch_time_point ) ;
// Calculate the week number (WN) and time of week (TOW)
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 ;
2024-07-23 09:16:45 +00:00
this - > WN = week_number ;
this - > TOW = time_of_week + LEAP_SECONDS ;
2024-04-18 22:47:31 +00:00
// Return the week number and time of week as a pair
2024-06-11 16:33:58 +00:00
// 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
2024-07-23 09:16:45 +00:00
this - > d_GST_SIS = ( this - > WN & 0x00000FFF ) < < 20 | ( this - > TOW & 0x000FFFFF ) ;
}