Skip to content

Commit

Permalink
Merge pull request #108 from nasa/GH96
Browse files Browse the repository at this point in the history
GH96: Add fix for incrementing non-transmitted portion logic for IV &
  • Loading branch information
IbraheemYSaleh committed Apr 18, 2022
2 parents 1d55895 + 0acb9c6 commit 7c1f5f5
Show file tree
Hide file tree
Showing 5 changed files with 290 additions and 21 deletions.
1 change: 1 addition & 0 deletions include/crypto_error.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,5 +89,6 @@
#define CRYPTO_LIB_ERR_NO_ECS_SET_FOR_ENCRYPTION_MODE (-36)
#define CRYPTO_LIB_ERR_IV_LEN_SHORTER_THAN_SEC_HEADER_LENGTH (-37)
#define CRYPTO_LIB_ERR_ARSN_LEN_SHORTER_THAN_SEC_HEADER_LENGTH (-38)
#define CRYPTO_LIB_ERR_FRAME_COUNTER_DOESNT_MATCH_SA (-39)

#endif //_crypto_error_h_
106 changes: 100 additions & 6 deletions src/src_main/crypto_tc.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@

#include <string.h> // memcpy

/* Helper validate SA function */
/* Helper functions */
static int32_t crypto_tc_validate_sa(SecurityAssociation_t *sa);
static int32_t crypto_handle_incrementing_nontransmitted_counter(uint8_t* dest, uint8_t* src, int src_full_len,int transmitted_len, int window);

/**
* @brief Function: Crypto_TC_ApplySecurity
Expand Down Expand Up @@ -809,21 +810,53 @@ int32_t Crypto_TC_ProcessSecurity(uint8_t* ingest, int *len_ingest, TC_t* tc_sdl
}
}

// Retrieve non-transmitted portion of IV from SA (if applicable)
memcpy(tc_sdls_processed_frame->tc_sec_header.iv, sa_ptr->iv, sa_ptr->iv_len-sa_ptr->shivf_len);
// Parse transmitted portion of IV
// Parse transmitted portion of IV from received frame (Will be Whole IV if iv_len==shivf_len)
memcpy((tc_sdls_processed_frame->tc_sec_header.iv+(sa_ptr->iv_len-sa_ptr->shivf_len)), &(ingest[TC_FRAME_HEADER_SIZE + segment_hdr_len + SPI_LEN]),
sa_ptr->shivf_len);

// Handle non-transmitted IV increment case (transmitted-portion roll-over)
if(sa_ptr->shivf_len < sa_ptr->iv_len &&
crypto_config->ignore_anti_replay==TC_IGNORE_ANTI_REPLAY_FALSE &&
crypto_config->crypto_increment_nontransmitted_iv==SA_INCREMENT_NONTRANSMITTED_IV_TRUE)
{
status = crypto_handle_incrementing_nontransmitted_counter(tc_sdls_processed_frame->tc_sec_header.iv,sa_ptr->iv,sa_ptr->iv_len,sa_ptr->shivf_len,sa_ptr->arsnw);
if (status != CRYPTO_LIB_SUCCESS)
{
return status;
}
}
else // Not checking IV ARSNW or only non-transmitted portion is static; Note, non-transmitted IV in SA must match frame or will fail MAC check.
{
// Retrieve non-transmitted portion of IV from SA (if applicable)
memcpy(tc_sdls_processed_frame->tc_sec_header.iv, sa_ptr->iv, sa_ptr->iv_len-sa_ptr->shivf_len);
}

#ifdef DEBUG
printf("Full IV Value from Frame and SADB (if applicable):\n");
Crypto_hexprint(tc_sdls_processed_frame->tc_sec_header.iv,sa_ptr->iv_len);
#endif

// Parse non-transmitted portion of ARSN from SA
memcpy(tc_sdls_processed_frame->tc_sec_header.sn, sa_ptr->arsn, sa_ptr->arsn_len-sa_ptr->shsnf_len);
// Parse transmitted portion of ARSN
memcpy((tc_sdls_processed_frame->tc_sec_header.sn + (sa_ptr->arsn_len-sa_ptr->shsnf_len)),
&(ingest[TC_FRAME_HEADER_SIZE + segment_hdr_len + SPI_LEN + sa_ptr->shivf_len]), sa_ptr->shsnf_len);

// Handle non-transmitted SN increment case (transmitted-portion roll-over)
if(sa_ptr->shsnf_len < sa_ptr->arsn_len &&
crypto_config->ignore_anti_replay==TC_IGNORE_ANTI_REPLAY_FALSE)
{
status = crypto_handle_incrementing_nontransmitted_counter(tc_sdls_processed_frame->tc_sec_header.sn,sa_ptr->arsn,sa_ptr->arsn_len,sa_ptr->shsnf_len,sa_ptr->arsnw);
if (status != CRYPTO_LIB_SUCCESS)
{
return status;
}
}
else // Not checking ARSN in ARSNW
{
// Parse non-transmitted portion of ARSN from SA
memcpy(tc_sdls_processed_frame->tc_sec_header.sn, sa_ptr->arsn, sa_ptr->arsn_len-sa_ptr->shsnf_len);

}

#ifdef DEBUG
printf("Full ARSN Value from Frame and SADB (if applicable):\n");
Crypto_hexprint(tc_sdls_processed_frame->tc_sec_header.sn,sa_ptr->arsn_len);
Expand Down Expand Up @@ -939,6 +972,18 @@ int32_t Crypto_TC_ProcessSecurity(uint8_t* ingest, int *len_ingest, TC_t* tc_sdl
if (crypto_config->ignore_anti_replay == TC_IGNORE_ANTI_REPLAY_FALSE && status == CRYPTO_LIB_SUCCESS)
{
status = Crypto_Check_Anti_Replay(sa_ptr, tc_sdls_processed_frame->tc_sec_header.sn, tc_sdls_processed_frame->tc_sec_header.iv);

if(status != CRYPTO_LIB_SUCCESS)
{
return status;
}

// Only save the SA (IV/ARSN) if checking the anti-replay counter; Otherwise we don't update.
status = sadb_routine->sadb_save_sa(sa_ptr);
if(status != CRYPTO_LIB_SUCCESS)
{
return status;
}
}

// Extended PDU processing, if applicable
Expand Down Expand Up @@ -1058,4 +1103,53 @@ static int32_t crypto_tc_validate_sa(SecurityAssociation_t *sa)
}

return CRYPTO_LIB_SUCCESS;
}

static int32_t crypto_handle_incrementing_nontransmitted_counter(uint8_t* dest, uint8_t* src, int src_full_len,int transmitted_len, int window)
{
int32_t status = CRYPTO_LIB_SUCCESS;
// Copy IV to temp
uint8_t* temp_counter = malloc(src_full_len);
memcpy(temp_counter,src,src_full_len);

// Increment temp_counter Until Transmitted Portion Matches Frame.
uint8_t counter_matches = CRYPTO_TRUE;
for(int i = 0; i < window; i++)
{
Crypto_increment(temp_counter,src_full_len);
for(int x = (src_full_len - transmitted_len); x < src_full_len; x++)
{
//This increment doesn't match the frame!
if(temp_counter[x] != dest[x])
{
counter_matches = CRYPTO_FALSE;
break;
}
}
if(counter_matches == CRYPTO_TRUE)
{
break;
}
else if (i < window - 1) // Only reset flag if there are more windows to check.
{
counter_matches = CRYPTO_TRUE; // reset the flag, and continue the for loop for the next
continue;
}

}

if(counter_matches == CRYPTO_TRUE)
{
// Retrieve non-transmitted portion of incremented counter that matches (and may have rolled over/incremented)
memcpy(dest, temp_counter, src_full_len - transmitted_len);
#ifdef DEBUG
printf("Incremented IV is:\n");
Crypto_hexprint(temp_counter,src_full_len);
#endif
}
else
{
status = CRYPTO_LIB_ERR_FRAME_COUNTER_DOESNT_MATCH_SA;
}
return status;
}
2 changes: 1 addition & 1 deletion src/src_main/sadb_routine_inmemory.template.c
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ int32_t sadb_config(void)
sa[4].abm = (uint8_t* )calloc(1, sa[4].abm_len * sizeof(uint8_t));
sa[4].arsnw_len = 1;
sa[4].arsnw = 5;
sa[4].arsn_len = (sa[4].arsnw * 2) + 1;
sa[4].arsn_len = 0;
sa[4].gvcid_tc_blk.tfvn = 0;
sa[4].gvcid_tc_blk.scid = SCID & 0x3FF;
sa[4].gvcid_tc_blk.vcid = 0;
Expand Down
86 changes: 86 additions & 0 deletions util/src_util/ut_tc_apply.c
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,92 @@ UTEST(TC_APPLY_SECURITY, HAPPY_PATH_APPLY_STATIC_IV_ROLLOVER)
free(ptr_enc_frame);
ASSERT_EQ(CRYPTO_LIB_SUCCESS, return_val);
}

/**
* @brief Unit Test: Nominal Authorized Encryption With Partial ARSN Rollover, increment static ARSN
**/
UTEST(TC_APPLY_SECURITY, HAPPY_PATH_APPLY_NONTRANSMITTED_INCREMENTING_ARSN_ROLLOVER)
{
// Setup & Initialize CryptoLib
Crypto_Init_Unit_Test();
char* raw_tc_sdls_ping_h = "20030015000080d2c70008197f0b00310000b1fe3128";
char* raw_tc_sdls_ping_b = NULL;

char* new_arsn_h = "05FFFC";
char* new_arsn_b = NULL;

char* expected_arsn_h = "060001";
char* expected_arsn_b = NULL;

int raw_tc_sdls_ping_len = 0;
int new_arsn_len = 0;
int expected_arsn_len = 0;

SadbRoutine sadb_routine = get_sadb_routine_inmemory();

hex_conversion(raw_tc_sdls_ping_h, &raw_tc_sdls_ping_b, &raw_tc_sdls_ping_len);
hex_conversion(new_arsn_h, &new_arsn_b, &new_arsn_len);
hex_conversion(expected_arsn_h, &expected_arsn_b, &expected_arsn_len);
uint8_t* ptr_enc_frame = NULL;
uint16_t enc_frame_len = 0;

int32_t return_val = CRYPTO_LIB_ERROR;

SecurityAssociation_t* test_association = malloc(sizeof(SecurityAssociation_t) * sizeof(uint8_t));
// Expose the SADB Security Association for test edits.
sadb_routine->sadb_get_sa_from_spi(1, &test_association);
test_association->sa_state = SA_NONE;
sadb_routine->sadb_get_sa_from_spi(4, &test_association);
test_association->sa_state = SA_OPERATIONAL;
test_association->shivf_len = 0;
test_association->iv_len = 0;
test_association->est=0;
test_association->ast=1;
test_association->ecs_len=1;
test_association->ecs = calloc(1, test_association->ecs_len * sizeof(uint8_t));
*test_association->ecs = CRYPTO_CIPHER_NONE;
test_association->acs_len=1;
test_association->acs = calloc(1, test_association->acs_len * sizeof(uint8_t));
*test_association->acs = CRYPTO_MAC_CMAC_AES256;
test_association->arsn_len = 3;
test_association->shsnf_len = 2;
test_association->arsn = calloc(1,test_association->arsn_len);
memcpy(test_association->arsn, (uint8_t *)new_arsn_b, new_arsn_len);

return_val =
Crypto_TC_ApplySecurity((uint8_t* )raw_tc_sdls_ping_b, raw_tc_sdls_ping_len, &ptr_enc_frame, &enc_frame_len);
ASSERT_EQ(CRYPTO_LIB_SUCCESS,return_val);
return_val =
Crypto_TC_ApplySecurity((uint8_t* )raw_tc_sdls_ping_b, raw_tc_sdls_ping_len, &ptr_enc_frame, &enc_frame_len);
ASSERT_EQ(CRYPTO_LIB_SUCCESS,return_val);
return_val =
Crypto_TC_ApplySecurity((uint8_t* )raw_tc_sdls_ping_b, raw_tc_sdls_ping_len, &ptr_enc_frame, &enc_frame_len);
ASSERT_EQ(CRYPTO_LIB_SUCCESS,return_val);
return_val =
Crypto_TC_ApplySecurity((uint8_t* )raw_tc_sdls_ping_b, raw_tc_sdls_ping_len, &ptr_enc_frame, &enc_frame_len);
ASSERT_EQ(CRYPTO_LIB_SUCCESS,return_val);
return_val =
Crypto_TC_ApplySecurity((uint8_t* )raw_tc_sdls_ping_b, raw_tc_sdls_ping_len, &ptr_enc_frame, &enc_frame_len);
ASSERT_EQ(CRYPTO_LIB_SUCCESS,return_val);

printf("Expected ARSN:\n");
Crypto_hexprint(expected_arsn_b,expected_arsn_len);
printf("Actual SA ARSN:\n");
Crypto_hexprint(test_association->arsn,test_association->arsn_len);

for (int i = 0; i < test_association->arsn_len; i++)
{
printf("[%d] Truth: %02x, Actual: %02x\n", i, expected_arsn_b[i], *(test_association->arsn + i));
ASSERT_EQ(expected_arsn_b[i], *(test_association->arsn + i));
}

//Must shutdown after checking test_association ARSN since that will get freed!
Crypto_Shutdown();
free(raw_tc_sdls_ping_b);
free(ptr_enc_frame);
ASSERT_EQ(CRYPTO_LIB_SUCCESS, return_val);
}

/**
* @brief Unit Test: Bad Spacecraft ID
* This should pass the flawed hex string, and return CRYPTO_LIB_ERR_INVALID_SCID
Expand Down
116 changes: 102 additions & 14 deletions util/src_util/ut_tc_process.c
Original file line number Diff line number Diff line change
Expand Up @@ -399,20 +399,108 @@ UTEST(TC_PROCESS, HAPPY_PATH_PROCESS_NONTRANSMITTED_INCREMENTING_IV_ROLLOVER)
ASSERT_EQ(test_association->iv[11],0xFF);
// test_association->iv[5] = 0x01;
return_val = Crypto_TC_ProcessSecurity(dec_test_00_b, &dec_test_00_len, tc_sdls_processed_frame);
//Tc_ProcessSecurity Rollover bug ( https://github.jpl.nasa.gov/ASEC/AMMOS-CryptoLib/issues/57 ), cannot assert this!
// ASSERT_EQ(CRYPTO_LIB_SUCCESS, return_val);
// ASSERT_EQ(test_association->iv[0] ,0x00);
// ASSERT_EQ(test_association->iv[1] ,0x00);
// ASSERT_EQ(test_association->iv[2] ,0x00);
// ASSERT_EQ(test_association->iv[3] ,0x00);
// ASSERT_EQ(test_association->iv[4] ,0x00);
// ASSERT_EQ(test_association->iv[5] ,0x01);
// ASSERT_EQ(test_association->iv[6] ,0x00);
// ASSERT_EQ(test_association->iv[7] ,0x00);
// ASSERT_EQ(test_association->iv[8] ,0x00);
// ASSERT_EQ(test_association->iv[9] ,0x00);
// ASSERT_EQ(test_association->iv[10],0x00);
// ASSERT_EQ(test_association->iv[11],0x00);
ASSERT_EQ(CRYPTO_LIB_SUCCESS, return_val);
ASSERT_EQ(test_association->iv[0] ,0x00);
ASSERT_EQ(test_association->iv[1] ,0x00);
ASSERT_EQ(test_association->iv[2] ,0x00);
ASSERT_EQ(test_association->iv[3] ,0x00);
ASSERT_EQ(test_association->iv[4] ,0x00);
ASSERT_EQ(test_association->iv[5] ,0x01);
ASSERT_EQ(test_association->iv[6] ,0x00);
ASSERT_EQ(test_association->iv[7] ,0x00);
ASSERT_EQ(test_association->iv[8] ,0x00);
ASSERT_EQ(test_association->iv[9] ,0x00);
ASSERT_EQ(test_association->iv[10],0x00);
ASSERT_EQ(test_association->iv[11],0x00);

Crypto_saPrint(test_association);

Crypto_Shutdown();

free(dec_test_fe_b);
free(dec_test_ff_b);
free(dec_test_00_b);
// free(test_association->ecs);
free(tc_sdls_processed_frame);
// sadb_routine->sadb_close();
}

UTEST(TC_PROCESS, HAPPY_PATH_PROCESS_NONTRANSMITTED_INCREMENTING_ARSN_ROLLOVER)
{
// Setup & Initialize CryptoLib
Crypto_Init_Unit_Test();
Crypto_Config_CryptoLib(SADB_TYPE_INMEMORY, CRYPTOGRAPHY_TYPE_LIBGCRYPT, CRYPTO_TC_CREATE_FECF_TRUE, TC_PROCESS_SDLS_PDUS_TRUE, TC_HAS_PUS_HDR,
TC_IGNORE_SA_STATE_FALSE, TC_IGNORE_ANTI_REPLAY_FALSE, TC_UNIQUE_SA_PER_MAP_ID_FALSE,
TC_CHECK_FECF_TRUE, 0x3F, SA_INCREMENT_NONTRANSMITTED_IV_TRUE);

SadbRoutine sadb_routine = get_sadb_routine_inmemory();

char* dec_test_fe_h =
"2003002900000004FFFE80D2C70008197F0B00310000B1FE1C9119D059698FFE5AAE811572FA678D0741";
char* dec_test_ff_h =
"2003002900000004FFFF80D2C70008197F0B00310000B1FE1C9119D059698FFE5AAE811572FA678D8968";
char* dec_test_00_h =
"2003002900000004000080D2C70008197F0B00310000B1FE1C9119D059698FFE5AAE811572FA678D7824";

uint8_t *dec_test_fe_b, *dec_test_ff_b, *dec_test_00_b = NULL;
int dec_test_fe_len, dec_test_ff_len, dec_test_00_len = 0;

hex_conversion(dec_test_fe_h, (char**) &dec_test_fe_b, &dec_test_fe_len);
hex_conversion(dec_test_ff_h, (char**) &dec_test_ff_b, &dec_test_ff_len);
hex_conversion(dec_test_00_h, (char**) &dec_test_00_b, &dec_test_00_len);

SecurityAssociation_t* test_association = NULL;
test_association = malloc(sizeof(SecurityAssociation_t) * sizeof(uint8_t));

int32_t return_val = -1;

TC_t* tc_sdls_processed_frame;
tc_sdls_processed_frame = malloc(sizeof(uint8_t) * TC_SIZE);
memset(tc_sdls_processed_frame, 0, (sizeof(uint8_t) * TC_SIZE));

// Default SA
// Expose SA 1 for testing
sadb_routine->sadb_get_sa_from_spi(1, &test_association);
test_association->ecs = calloc(1, test_association->ecs_len * sizeof(uint8_t));
*test_association->ecs = CRYPTO_CIPHER_NONE;

// Deactive SA 1
test_association->sa_state = SA_NONE;

// Expose SA 4 for testing
sadb_routine->sadb_get_sa_from_spi(4, &test_association);
test_association->sa_state = SA_OPERATIONAL;
test_association->shivf_len = 0;
test_association->iv_len = 0;
test_association->est=0;
test_association->ast=1;
test_association->ecs_len=1;
test_association->ecs = calloc(1, test_association->ecs_len * sizeof(uint8_t));
*test_association->ecs = CRYPTO_CIPHER_NONE;
test_association->acs_len=1;
test_association->acs = calloc(1, test_association->acs_len * sizeof(uint8_t));
*test_association->acs = CRYPTO_MAC_CMAC_AES256;
test_association->arsn_len = 3;
test_association->shsnf_len = 2;
test_association->arsn = calloc(1,test_association->arsn_len);
// ARSN = "05FFFD"
test_association->arsn[0] = 0x05;
test_association->arsn[1] = 0xFF;
test_association->arsn[2] = 0xFD;

Crypto_saPrint(test_association);
return_val = Crypto_TC_ProcessSecurity(dec_test_fe_b, &dec_test_fe_len, tc_sdls_processed_frame);
ASSERT_EQ(CRYPTO_LIB_SUCCESS, return_val);
ASSERT_EQ(test_association->arsn[2],0xFE);
return_val = Crypto_TC_ProcessSecurity(dec_test_ff_b, &dec_test_ff_len, tc_sdls_processed_frame);
ASSERT_EQ(CRYPTO_LIB_SUCCESS, return_val);
ASSERT_EQ(test_association->arsn[2],0xFF);
// test_association->iv[5] = 0x01;
return_val = Crypto_TC_ProcessSecurity(dec_test_00_b, &dec_test_00_len, tc_sdls_processed_frame);
ASSERT_EQ(CRYPTO_LIB_SUCCESS, return_val);
ASSERT_EQ(test_association->arsn[0] ,0x06);
ASSERT_EQ(test_association->arsn[1] ,0x00);
ASSERT_EQ(test_association->arsn[2] ,0x00);

Crypto_saPrint(test_association);

Expand Down

0 comments on commit 7c1f5f5

Please sign in to comment.