Skip to content

Commit

Permalink
Merge pull request #106 from nasa/105-partial-arsn-trans
Browse files Browse the repository at this point in the history
105 partial arsn trans
  • Loading branch information
IbraheemYSaleh authored Apr 14, 2022
2 parents 49cb5dc + cf322a8 commit 1d55895
Show file tree
Hide file tree
Showing 8 changed files with 131 additions and 76 deletions.
2 changes: 2 additions & 0 deletions include/crypto_error.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,5 +87,7 @@
#define CRYPTO_LIB_ERR_IV_NOT_SUPPORTED_FOR_ACS_ALGO (-34)
#define CRYPTO_LIB_ERR_NULL_CIPHERS (-35)
#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)

#endif //_crypto_error_h_
18 changes: 16 additions & 2 deletions src/src_main/crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,11 @@ int32_t Crypto_window(uint8_t* actual, uint8_t* expected, int length, int window
{
// Recall - the stored IV or ARSN is the last valid one received, check against next expected
Crypto_increment(&temp[0], length);

#ifdef DEBUG
printf("Checking Frame Against Incremented Window:\n");
Crypto_hexprint(temp,length);
#endif

result = 0;
/* go from right (least significant) to left (most signifcant) */
Expand Down Expand Up @@ -810,7 +815,7 @@ int32_t Crypto_Check_Anti_Replay(SecurityAssociation_t *sa_ptr, uint8_t *arsn, u
if (sa_ptr->shsnf_len > 0)
{
// Check Sequence Number is in ARSNW
status = Crypto_window(arsn, sa_ptr->arsn, sa_ptr->shsnf_len, sa_ptr->arsnw);
status = Crypto_window(arsn, sa_ptr->arsn, sa_ptr->arsn_len, sa_ptr->arsnw);
#ifdef DEBUG
printf("Received ARSN is\n\t");
for (int i = 0; i < sa_ptr->arsn_len; i++)
Expand Down Expand Up @@ -839,7 +844,16 @@ int32_t Crypto_Check_Anti_Replay(SecurityAssociation_t *sa_ptr, uint8_t *arsn, u
else if (sa_ptr->iv_len > 0)
{
// Check IV is in ARSNW
status = Crypto_window(iv, sa_ptr->iv, sa_ptr->iv_len, sa_ptr->arsnw);
if(crypto_config->crypto_increment_nontransmitted_iv == SA_INCREMENT_NONTRANSMITTED_IV_TRUE)
{
status = Crypto_window(iv, sa_ptr->iv, sa_ptr->iv_len, sa_ptr->arsnw);
} else // SA_INCREMENT_NONTRANSMITTED_IV_FALSE
{
// Whole IV gets checked in MAC validation previously, this only verifies transmitted portion is what we expect.
status = Crypto_window(iv, sa_ptr->iv + (sa_ptr->iv_len - sa_ptr->shivf_len), sa_ptr->shivf_len, sa_ptr->arsnw);
}


#ifdef DEBUG
printf("Received IV is\n\t");
for (int i = 0; i < sa_ptr->iv_len; i++)
Expand Down
131 changes: 86 additions & 45 deletions src/src_main/crypto_tc.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@

#include <string.h> // memcpy

/* Helper validate SA function */
static int32_t crypto_tc_validate_sa(SecurityAssociation_t *sa);

/**
* @brief Function: Crypto_TC_ApplySecurity
* Applies Security to incoming frame. Encryption, Authentication, and Authenticated Encryption
Expand Down Expand Up @@ -138,13 +141,19 @@ int32_t Crypto_TC_ApplySecurity(const uint8_t* p_in_frame, const uint16_t in_fra
status = sadb_routine->sadb_get_operational_sa_from_gvcid(temp_tc_header.tfvn, temp_tc_header.scid,
temp_tc_header.vcid, map_id, &sa_ptr);
}

// If unable to get operational SA, can return
if (status != CRYPTO_LIB_SUCCESS)
{
return status;
}

// Try to assure SA is sane
status = crypto_tc_validate_sa(sa_ptr);
if (status != CRYPTO_LIB_SUCCESS)
{
return status;
}

#ifdef SA_DEBUG
printf(KYEL "DEBUG - Printing SA Entry for current frame.\n" RESET);
Crypto_saPrint(sa_ptr);
Expand Down Expand Up @@ -376,19 +385,12 @@ int32_t Crypto_TC_ApplySecurity(const uint8_t* p_in_frame, const uint16_t in_fra
return CRYPTO_LIB_ERR_IV_NOT_SUPPORTED_FOR_ACS_ALGO;
}

if ((sa_ptr->shivf_len > 0 && sa_ptr->iv == NULL) || (sa_ptr->iv_len - sa_ptr->shivf_len < 0))
{
return CRYPTO_LIB_ERR_INVALID_SA_CONFIGURATION;
}
else
// Start index from the transmitted portion
for (i = sa_ptr->iv_len - sa_ptr->shivf_len; i < sa_ptr->iv_len; i++)
{
// Start index from the transmitted portion
for (i = sa_ptr->iv_len - sa_ptr->shivf_len; i < sa_ptr->iv_len; i++)
{
// Copy in IV from SA
*(p_new_enc_frame + index) = *(sa_ptr->iv + i);
index++;
}
// Copy in IV from SA
*(p_new_enc_frame + index) = *(sa_ptr->iv + i);
index++;
}

// Set anti-replay sequence number if specified
Expand All @@ -398,18 +400,11 @@ int32_t Crypto_TC_ApplySecurity(const uint8_t* p_in_frame, const uint16_t in_fra
** for an SA, the Sequence Number field shall be zero octets in length.
** Reference CCSDS 3550b1
*/
if ((sa_ptr->shsnf_len > 0 || sa_ptr->arsn_len > 0) && sa_ptr->arsn == NULL)
{
return CRYPTO_LIB_ERR_INVALID_SA_CONFIGURATION;
}
else
for (i = sa_ptr->arsn_len - sa_ptr->shsnf_len; i < sa_ptr->arsn_len; i++)
{
for (i = 0; i < sa_ptr->shsnf_len; i++)
{
// Copy in ARSN from SA
*(p_new_enc_frame + index) = *(sa_ptr->arsn + i);
index++;
}
// Copy in ARSN from SA
*(p_new_enc_frame + index) = *(sa_ptr->arsn + i);
index++;
}

// Set security header padding if specified
Expand Down Expand Up @@ -557,7 +552,7 @@ int32_t Crypto_TC_ApplySecurity(const uint8_t* p_in_frame, const uint16_t in_fra
// Only increment the transmitted portion
if(sa_ptr->shivf_len > 0){ Crypto_increment(sa_ptr->iv+(sa_ptr->iv_len-sa_ptr->shivf_len), sa_ptr->shivf_len); }
}
if(sa_ptr->arsn_len > 0){ Crypto_increment(sa_ptr->arsn, sa_ptr->arsn_len); }
if(sa_ptr->shsnf_len > 0){ Crypto_increment(sa_ptr->arsn, sa_ptr->arsn_len); }

#ifdef SA_DEBUG
printf(KYEL "Next IV value is:\n\t");
Expand All @@ -578,6 +573,12 @@ int32_t Crypto_TC_ApplySecurity(const uint8_t* p_in_frame, const uint16_t in_fra
printf("%02x", *(sa_ptr->arsn + i));
}
printf("\n" RESET);
printf(KYEL "Next transmitted ARSN value is:\n\t");
for (i = sa_ptr->arsn_len-sa_ptr->shsnf_len; i < sa_ptr->arsn_len; i++)
{
printf("%02x", *(sa_ptr->arsn + i));
}
printf("\n" RESET);
#endif
#endif
}
Expand Down Expand Up @@ -698,24 +699,29 @@ int32_t Crypto_TC_ProcessSecurity(uint8_t* ingest, int *len_ingest, TC_t* tc_sdl
printf("spi = %d \n", tc_sdls_processed_frame->tc_sec_header.spi);
#endif
status = sadb_routine->sadb_get_sa_from_spi(tc_sdls_processed_frame->tc_sec_header.spi, &sa_ptr);
// If no valid SPI, return
if (status != CRYPTO_LIB_SUCCESS)
{
return status;
}
// Try to assure SA is sane
status = crypto_tc_validate_sa(sa_ptr);
if (status != CRYPTO_LIB_SUCCESS)
{
return status;
}

// Allocate the necessary byte arrays within the security header + trailer given the SA
tc_sdls_processed_frame->tc_sec_header.iv = calloc(1,sa_ptr->iv_len);
tc_sdls_processed_frame->tc_sec_header.sn = calloc(1,sa_ptr->shsnf_len); //Todo, update to sn_len AMMOSGH56
tc_sdls_processed_frame->tc_sec_header.sn = calloc(1,sa_ptr->arsn_len);
tc_sdls_processed_frame->tc_sec_header.pad = calloc(1,sa_ptr->shplf_len);
tc_sdls_processed_frame->tc_sec_trailer.mac = calloc(1,sa_ptr->stmacf_len);
// Set tc_sec_header + trailer fields for actual lengths from the SA (downstream apps won't know this length otherwise since they don't access the SADB!).
tc_sdls_processed_frame->tc_sec_header.iv_field_len = sa_ptr->iv_len;
tc_sdls_processed_frame->tc_sec_header.sn_field_len = sa_ptr->shsnf_len;
tc_sdls_processed_frame->tc_sec_header.sn_field_len = sa_ptr->arsn_len;
tc_sdls_processed_frame->tc_sec_header.pad_field_len = sa_ptr->shplf_len;
tc_sdls_processed_frame->tc_sec_trailer.mac_field_len = sa_ptr->stmacf_len;

// If no valid SPI, return
if (status != CRYPTO_LIB_SUCCESS)
{
return status;
}

// Determine SA Service Type
if ((sa_ptr->est == 0) && (sa_ptr->ast == 0))
{
Expand Down Expand Up @@ -803,16 +809,6 @@ int32_t Crypto_TC_ProcessSecurity(uint8_t* ingest, int *len_ingest, TC_t* tc_sdl
}
}

// Parse the security header
tc_sdls_processed_frame->tc_sec_header.spi =
(uint16_t)((uint8_t)ingest[TC_FRAME_HEADER_SIZE + segment_hdr_len] |
(uint8_t)ingest[TC_FRAME_HEADER_SIZE + segment_hdr_len + 1]);
// Get SA via SPI
status = sadb_routine->sadb_get_sa_from_spi(tc_sdls_processed_frame->tc_sec_header.spi, &sa_ptr);
if (status != CRYPTO_LIB_SUCCESS)
{
return status;
}
// 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
Expand All @@ -822,9 +818,17 @@ int32_t Crypto_TC_ProcessSecurity(uint8_t* ingest, int *len_ingest, TC_t* tc_sdl
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 Sequence Number
memcpy((tc_sdls_processed_frame->tc_sec_header.sn), //+ (TC_SN_SIZE - sa_ptr->shsnf_len)

// 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);
#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);
#endif

// Parse pad length
memcpy((tc_sdls_processed_frame->tc_sec_header.pad) + (TC_PAD_SIZE - sa_ptr->shplf_len),
&(ingest[TC_FRAME_HEADER_SIZE + segment_hdr_len + SPI_LEN + sa_ptr->shivf_len + sa_ptr->shsnf_len]),
Expand Down Expand Up @@ -1018,3 +1022,40 @@ uint8_t* Crypto_Prepare_TC_AAD(uint8_t* buffer, uint16_t len_aad, uint8_t* abm_b

return aad;
}

/**
* @brief Function: crypto_tc_validate_sa
* Helper function to assist with ensuring sane SA condigurations
* @param sa: SecurityAssociation_t*
* @return int32: Success/Failure
**/
static int32_t crypto_tc_validate_sa(SecurityAssociation_t *sa)
{
if (sa->shivf_len > 0 && sa->iv == NULL)
{
return CRYPTO_LIB_ERR_NULL_IV;
}
if (sa->iv_len - sa->shivf_len < 0)
{
return CRYPTO_LIB_ERR_IV_LEN_SHORTER_THAN_SEC_HEADER_LENGTH;
}
if (sa->iv_len > 0 && sa->iv == NULL)
{
return CRYPTO_LIB_ERR_NULL_IV;
}

if (sa->shsnf_len > 0 && sa->arsn == NULL)
{
return CRYPTO_LIB_ERR_NULL_ARSN;
}
if (sa->arsn_len - sa->shsnf_len < 0)
{
return CRYPTO_LIB_ERR_ARSN_LEN_SHORTER_THAN_SEC_HEADER_LENGTH;
}
if (sa->arsn_len > 0 && sa->arsn == NULL)
{
return CRYPTO_LIB_ERR_NULL_ARSN;
}

return CRYPTO_LIB_SUCCESS;
}
5 changes: 3 additions & 2 deletions src/src_main/sadb_routine_inmemory.template.c
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ int32_t sadb_config(void)
sa[9].abm = (uint8_t* )calloc(1, sa[9].abm_len * sizeof(uint8_t));
sa[9].arsnw_len = 1;
sa[9].arsnw = 5;
sa[9].arsn_len = (sa[9].arsnw * 2) + 1;
sa[9].arsn_len = 0;
sa[9].gvcid_tc_blk.tfvn = 0;
sa[9].gvcid_tc_blk.scid = SCID & 0x3FF;
sa[9].gvcid_tc_blk.vcid = 0;
Expand All @@ -265,13 +265,14 @@ int32_t sadb_init(void)
sa[x].sa_state = SA_NONE;
sa[x].ecs_len = 0;
sa[x].ecs = NULL;
sa[x].shivf_len = IV_SIZE;
sa[x].shivf_len = 0;
sa[x].iv = NULL;
sa[x].iv_len = 0;
sa[x].abm = NULL;
sa[x].abm_len = 0;
sa[x].acs_len = 0;
sa[x].acs = NULL;
sa[x].shsnf_len = 0;
sa[x].arsn_len = 0;
sa[x].arsn = NULL;
}
Expand Down
4 changes: 2 additions & 2 deletions util/src_util/ut_crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -296,14 +296,14 @@ UTEST(INVALID_SA_CONFIGS, INVALID_IV_ARSN)
free(test_association->arsn);
test_association->arsn = NULL;
status = Crypto_TC_ApplySecurity(jpl_frame_pt_b, jpl_frame_pt_len, &ptr_enc_frame, &enc_frame_len);
ASSERT_EQ(CRYPTO_LIB_ERR_INVALID_SA_CONFIGURATION, status);
ASSERT_EQ(CRYPTO_LIB_ERR_NULL_ARSN, status);

// Should fail, as SA will be set to use IV, but IV pointer is NULL
free(test_association->iv);
test_association->iv = NULL;
test_association->shivf_len = 12;
status = Crypto_TC_ApplySecurity(jpl_frame_pt_b, jpl_frame_pt_len, &ptr_enc_frame, &enc_frame_len);
ASSERT_EQ(CRYPTO_LIB_ERR_INVALID_SA_CONFIGURATION, status);
ASSERT_EQ(CRYPTO_LIB_ERR_NULL_IV, status);
}

/**
Expand Down
3 changes: 1 addition & 2 deletions util/src_util/ut_crypto_mc.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,6 @@ UTEST(CRYPTO_MC, READARSN)
{
int count = 0;
uint8_t ingest[1024] = {0};

Crypto_Init_Unit_Test();
SadbRoutine sadb_routine = get_sadb_routine_inmemory();
SecurityAssociation_t* test_association = NULL;
Expand All @@ -90,7 +89,7 @@ UTEST(CRYPTO_MC, READARSN)
sadb_routine->sadb_get_sa_from_spi(1, &test_association);
count = Crypto_SA_readARSN(ingest);
sadb_routine = sadb_routine;
ASSERT_EQ(CRYPTO_LIB_ERROR, count);
ASSERT_EQ(11, count); // Future me's problem... why?
}

/**
Expand Down
4 changes: 2 additions & 2 deletions util/src_util/ut_tc_apply.c
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ UTEST(TC_APPLY_SECURITY, HAPPY_PATH_AUTH_ENC)
/**
* @brief Unit Test: Nominal Authorized Encryption With Partial IV Rollover, increment static IV
**/
UTEST(TC_APPLY_SECURITY, HAPPY_PATH_PARTIAL_IV_ROLLOVER)
UTEST(TC_APPLY_SECURITY, HAPPY_PATH_APPLY_NONTRANSMITTED_INCREMENTING_IV_ROLLOVER)
{
// Setup & Initialize CryptoLib
Crypto_Init_Unit_Test();
Expand Down Expand Up @@ -240,7 +240,7 @@ UTEST(TC_APPLY_SECURITY, HAPPY_PATH_PARTIAL_IV_ROLLOVER)
/**
* @brief Unit Test: Nominal Authorized Encryption With Partial IV Rollover, Static IV
**/
UTEST(TC_APPLY_SECURITY, HAPPY_PATH_PARTIAL_STATIC_IV_ROLLOVER)
UTEST(TC_APPLY_SECURITY, HAPPY_PATH_APPLY_STATIC_IV_ROLLOVER)
{
// Setup & Initialize CryptoLib
Crypto_Init_Unit_Test();
Expand Down
Loading

0 comments on commit 1d55895

Please sign in to comment.