Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GH96: Add fix for incrementing non-transmitted portion logic for IV & #108

Merged
merged 2 commits into from
Apr 18, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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