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

AMMOSGH-91: Add sanity frame length checks against provided input frames #116

Merged
merged 2 commits into from
May 11, 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
2 changes: 2 additions & 0 deletions include/crypto_error.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,5 +90,7 @@
#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)
#define CRYPTO_LIB_ERR_INPUT_FRAME_TOO_SHORT_FOR_TC_STANDARD (-40)
#define CRYPTO_LIB_ERR_INPUT_FRAME_LENGTH_SHORTER_THAN_FRAME_HEADERS_LENGTH (-41)

#endif //_crypto_error_h_
24 changes: 24 additions & 0 deletions src/src_main/crypto_tc.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,12 @@ int32_t Crypto_TC_ApplySecurity(const uint8_t* p_in_frame, const uint16_t in_fra
return status; // return immediately so a NULL crypto_config is not dereferenced later
}

if (in_frame_length < 5) // Frame length doesn't have enough bytes for TC TF header -- error out.
{
status = CRYPTO_LIB_ERR_INPUT_FRAME_TOO_SHORT_FOR_TC_STANDARD;
return status;
}

// Primary Header
temp_tc_header.tfvn = ((uint8_t)p_in_frame[0] & 0xC0) >> 6;
temp_tc_header.bypass = ((uint8_t)p_in_frame[0] & 0x20) >> 5;
Expand All @@ -98,6 +104,12 @@ int32_t Crypto_TC_ApplySecurity(const uint8_t* p_in_frame, const uint16_t in_fra
temp_tc_header.fl = temp_tc_header.fl | (uint8_t)p_in_frame[3];
temp_tc_header.fsn = (uint8_t)p_in_frame[4];

if (in_frame_length < temp_tc_header.fl+1) // Specified frame length larger than provided frame!
{
status = CRYPTO_LIB_ERR_INPUT_FRAME_LENGTH_SHORTER_THAN_FRAME_HEADERS_LENGTH;
return status;
}

// Lookup-retrieve managed parameters for frame via gvcid:
status = Crypto_Get_Managed_Parameters_For_Gvcid(temp_tc_header.tfvn, temp_tc_header.scid, temp_tc_header.vcid,
gvcid_managed_parameters, &current_managed_parameters);
Expand Down Expand Up @@ -659,6 +671,12 @@ int32_t Crypto_TC_ProcessSecurity(uint8_t* ingest, int *len_ingest, TC_t* tc_sdl
printf(KYEL "\n----- Crypto_TC_ProcessSecurity START -----\n" RESET);
#endif

if (*len_ingest < 5) // Frame length doesn't even have enough bytes for header -- error out.
{
status = CRYPTO_LIB_ERR_INPUT_FRAME_TOO_SHORT_FOR_TC_STANDARD;
return status;
}

int byte_idx = 0;
// Primary Header
tc_sdls_processed_frame->tc_header.tfvn = ((uint8_t)ingest[byte_idx] & 0xC0) >> 6;
Expand All @@ -677,6 +695,12 @@ int32_t Crypto_TC_ProcessSecurity(uint8_t* ingest, int *len_ingest, TC_t* tc_sdl
tc_sdls_processed_frame->tc_header.fsn = (uint8_t)ingest[byte_idx];
byte_idx++;

if (*len_ingest < tc_sdls_processed_frame->tc_header.fl + 1) // Specified frame length larger than provided frame!
{
status = CRYPTO_LIB_ERR_INPUT_FRAME_LENGTH_SHORTER_THAN_FRAME_HEADERS_LENGTH;
return status;
}

// Lookup-retrieve managed parameters for frame via gvcid:
status = Crypto_Get_Managed_Parameters_For_Gvcid(
tc_sdls_processed_frame->tc_header.tfvn, tc_sdls_processed_frame->tc_header.scid,
Expand Down
68 changes: 68 additions & 0 deletions util/src_util/ut_tc_apply.c
Original file line number Diff line number Diff line change
Expand Up @@ -520,4 +520,72 @@ UTEST(TC_APPLY_SECURITY, INVALID_FRAME_SIZE)
ASSERT_EQ(CRYPTO_LIB_ERR_TC_FRAME_SIZE_EXCEEDS_SPEC_LIMIT, status);
}

UTEST(TC_APPLY_SECURITY, ERROR_TC_INPUT_FRAME_TOO_SHORT_FOR_SPEC)
{
int32_t status = CRYPTO_LIB_SUCCESS;
uint8_t* ptr_enc_frame = NULL;
uint16_t enc_frame_len = 0;
// Setup & Initialize CryptoLib
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_TRUE, TC_UNIQUE_SA_PER_MAP_ID_FALSE,
TC_CHECK_FECF_TRUE, 0x3F, SA_INCREMENT_NONTRANSMITTED_IV_TRUE);
Crypto_Config_Add_Gvcid_Managed_Parameter(0, 0x0003, 0, TC_HAS_FECF, TC_HAS_SEGMENT_HDRS, 4);
status = Crypto_Init();
ASSERT_EQ(CRYPTO_LIB_SUCCESS, status);


char* test_frame_pt_h = "2003001c";
uint8_t *test_frame_pt_b = NULL;
int test_frame_pt_len = 0;

// Expose/setup SAs for testing
SecurityAssociation_t* test_association = NULL;
test_association = malloc(sizeof(SecurityAssociation_t) * sizeof(uint8_t));
sadb_routine->sadb_get_sa_from_spi(1, &test_association);
test_association->arsn_len = 0;
test_association->shsnf_len = 0;

// Convert input test frame
hex_conversion(test_frame_pt_h, (char**) &test_frame_pt_b, &test_frame_pt_len);
// Should fail, as frame length violates the managed parameter
status = Crypto_TC_ApplySecurity(test_frame_pt_b, test_frame_pt_len, &ptr_enc_frame, &enc_frame_len);
ASSERT_EQ(CRYPTO_LIB_ERR_INPUT_FRAME_TOO_SHORT_FOR_TC_STANDARD, status);

Crypto_Shutdown();
}

UTEST(TC_APPLY_SECURITY, ERROR_TC_INPUT_FRAME_TOO_SHORT_FOR_SPECIFIED_FRAME_LENGTH_HEADER)
{
int32_t status = CRYPTO_LIB_SUCCESS;
uint8_t* ptr_enc_frame = NULL;
uint16_t enc_frame_len = 0;
// Setup & Initialize CryptoLib
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_TRUE, TC_UNIQUE_SA_PER_MAP_ID_FALSE,
TC_CHECK_FECF_TRUE, 0x3F, SA_INCREMENT_NONTRANSMITTED_IV_TRUE);
Crypto_Config_Add_Gvcid_Managed_Parameter(0, 0x0003, 0, TC_HAS_FECF, TC_HAS_SEGMENT_HDRS, 4);
status = Crypto_Init();
ASSERT_EQ(CRYPTO_LIB_SUCCESS, status);


char* test_frame_pt_h = "2003001c00000002ff";
uint8_t *test_frame_pt_b = NULL;
int test_frame_pt_len = 0;

// Expose/setup SAs for testing
SecurityAssociation_t* test_association = NULL;
test_association = malloc(sizeof(SecurityAssociation_t) * sizeof(uint8_t));
sadb_routine->sadb_get_sa_from_spi(1, &test_association);
test_association->arsn_len = 0;
test_association->shsnf_len = 0;

// Convert input test frame
hex_conversion(test_frame_pt_h, (char**) &test_frame_pt_b, &test_frame_pt_len);
// Should fail, as frame length violates the managed parameter
status = Crypto_TC_ApplySecurity(test_frame_pt_b, test_frame_pt_len, &ptr_enc_frame, &enc_frame_len);
ASSERT_EQ(CRYPTO_LIB_ERR_INPUT_FRAME_LENGTH_SHORTER_THAN_FRAME_HEADERS_LENGTH, status);

Crypto_Shutdown();
}

UTEST_MAIN();
70 changes: 70 additions & 0 deletions util/src_util/ut_tc_process.c
Original file line number Diff line number Diff line change
Expand Up @@ -517,5 +517,75 @@ UTEST(TC_PROCESS, HAPPY_PATH_PROCESS_NONTRANSMITTED_INCREMENTING_ARSN_ROLLOVER)
// sadb_routine->sadb_close();
}

UTEST(TC_PROCESS, ERROR_TC_INPUT_FRAME_TOO_SHORT_FOR_SPEC)
{
int32_t status = CRYPTO_LIB_SUCCESS;
// Setup & Initialize CryptoLib
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_TRUE, TC_UNIQUE_SA_PER_MAP_ID_FALSE,
TC_CHECK_FECF_TRUE, 0x3F, SA_INCREMENT_NONTRANSMITTED_IV_TRUE);
Crypto_Config_Add_Gvcid_Managed_Parameter(0, 0x0003, 0, TC_HAS_FECF, TC_HAS_SEGMENT_HDRS, 4);
status = Crypto_Init();
ASSERT_EQ(CRYPTO_LIB_SUCCESS, status);

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));


char* test_frame_pt_h = "2003001c";
uint8_t *test_frame_pt_b = NULL;
int test_frame_pt_len = 0;

// Expose/setup SAs for testing
SecurityAssociation_t* test_association = NULL;
test_association = malloc(sizeof(SecurityAssociation_t) * sizeof(uint8_t));
sadb_routine->sadb_get_sa_from_spi(1, &test_association);
test_association->arsn_len = 0;
test_association->shsnf_len = 0;

// Convert input test frame
hex_conversion(test_frame_pt_h, (char**) &test_frame_pt_b, &test_frame_pt_len);
// Should fail, as frame length violates the managed parameter
status = Crypto_TC_ProcessSecurity(test_frame_pt_b, &test_frame_pt_len, tc_sdls_processed_frame);
ASSERT_EQ(CRYPTO_LIB_ERR_INPUT_FRAME_TOO_SHORT_FOR_TC_STANDARD, status);

Crypto_Shutdown();
}

UTEST(TC_PROCESS, ERROR_TC_INPUT_FRAME_TOO_SHORT_FOR_SPECIFIED_FRAME_LENGTH_HEADER)
{
int32_t status = CRYPTO_LIB_SUCCESS;
// Setup & Initialize CryptoLib
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_TRUE, TC_UNIQUE_SA_PER_MAP_ID_FALSE,
TC_CHECK_FECF_TRUE, 0x3F, SA_INCREMENT_NONTRANSMITTED_IV_TRUE);
Crypto_Config_Add_Gvcid_Managed_Parameter(0, 0x0003, 0, TC_HAS_FECF, TC_HAS_SEGMENT_HDRS, 4);
status = Crypto_Init();
ASSERT_EQ(CRYPTO_LIB_SUCCESS, status);

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));

char* test_frame_pt_h = "200304260000020000000000000000000000309e09deeaa375487983a89f3ed7519a230baf22";
uint8_t *test_frame_pt_b = NULL;
int test_frame_pt_len = 0;

// Expose/setup SAs for testing
SecurityAssociation_t* test_association = NULL;
test_association = malloc(sizeof(SecurityAssociation_t) * sizeof(uint8_t));
sadb_routine->sadb_get_sa_from_spi(1, &test_association);
test_association->arsn_len = 0;
test_association->shsnf_len = 0;

// Convert input test frame
hex_conversion(test_frame_pt_h, (char**) &test_frame_pt_b, &test_frame_pt_len);
// Should fail, as frame length violates the managed parameter
status = Crypto_TC_ProcessSecurity(test_frame_pt_b, &test_frame_pt_len, tc_sdls_processed_frame);
ASSERT_EQ(CRYPTO_LIB_ERR_INPUT_FRAME_LENGTH_SHORTER_THAN_FRAME_HEADERS_LENGTH, status);

Crypto_Shutdown();
}

UTEST_MAIN();