/* * * Copyright 2018-2020 NXP * SPDX-License-Identifier: Apache-2.0 */ /** @file */ #include #include #include #if SSS_HAVE_APPLET_SE05X_IOT #include /*Update header bit of policy based on the access rights sets in the policy Input:policy object of type sss_policy_sym_key_u Output:pbuffer pointing to policy header offset*/ static void sss_se05x_update_header_sym_key_policy(sss_policy_sym_key_u key_pol, uint8_t *pbuffer); /*Update header bit of policy based on the access rights sets in the policy Input:policy object of type sss_policy_asym_key_u Output:pbuffer pointing to policy header offset*/ static void sss_se05x_update_header_asym_key_policy(sss_policy_asym_key_u key_pol, uint8_t *pbuffer); /*Update header bit of policy based on the access rights sets in the policy Input:policy object of type sss_policy_common_u Output:pbuffer pointing to policy header offset*/ static void sss_se05x_update_header_common_policy(sss_policy_common_u common_pol, uint8_t *pbuffer); /*Update header bit of policy based on the access rights sets in the policy Input:policy object of type sss_policy_userid_u Output:pbuffer pointing to policy header offset*/ static void sss_se05x_update_header_pin_policy(sss_policy_userid_u pin_pol, uint8_t *pbuffer); /*Update header bit of policy based on the access rights sets in the policy Input:policy object of type sss_policy_file_u Output:pbuffer pointing to policy header offset*/ static void sss_se05x_update_header_file_policy(sss_policy_file_u file_pol, uint8_t *pbuffer); /*Update header bit of policy based on the access rights sets in the policy Input:policy object of type sss_policy_counter_u Output:pbuffer pointing to policy header offset*/ static void sss_se05x_update_header_counter_policy(sss_policy_counter_u counter_pol, uint8_t *pbuffer); /*Update header bit of policy based on the access rights sets in the policy Input:policy object of type sss_policy_pcr_u Output:pbuffer pointing to policy header offset */ static void sss_se05x_update_header_pcr_policy(sss_policy_pcr_u pcr_pol, uint8_t *pbuffer); /*Update header bit of policy based on the access rights sets in the policy Input:policy object of type sss_policy_common_pcr_value_u Output:pbuffer pointing to policy header offset */ static void sss_se05x_update_header_pcr_value_policy(sss_policy_common_pcr_value_u pcr_value_pol, uint8_t *pbuffer); static void sss_se05x_update_ext_pcr_value_policy( sss_policy_common_pcr_value_u pcr_value_pol, uint8_t *pbuffer, uint32_t *ext_offset); /* finds indices of all same auth Ids in a group of polices and returns the count of same auth ids with in a group of Ids, it laso copies indices in to an array passed by user Input: authId to be searched policies: array of all policies with diversified auth ids Output: pindices " array contains index of all input authid retuns :count of same auth ids with in a group of Ids */ static int sss_se05x_find_authId_instances(uint32_t authId, uint8_t *pindices, sss_policy_t *policies); static void sss_se05x_copy_uint32_to_u8_array(uint32_t u32, uint8_t *pbuffer); static void sss_se05x_copy_uint16_to_u8_array(uint16_t u16, uint8_t *pbuffer); static void sss_se05x_update_header_sym_key_policy(sss_policy_sym_key_u key_pol, uint8_t *pbuffer) { uint32_t header = 0; if (key_pol.can_Sign) { header |= POLICY_OBJ_ALLOW_SIGN; } if (key_pol.can_Verify) { header |= POLICY_OBJ_ALLOW_VERIFY; } if (key_pol.can_Encrypt) { header |= POLICY_OBJ_ALLOW_ENC; } if (key_pol.can_Decrypt) { header |= POLICY_OBJ_ALLOW_DEC; } if (key_pol.can_KD) { header |= POLICY_OBJ_ALLOW_KDF; } if (key_pol.can_Wrap) { header |= POLICY_OBJ_ALLOW_WRAP; } if (key_pol.can_Write) { header |= POLICY_OBJ_ALLOW_WRITE; } if (key_pol.can_Gen) { header |= POLICY_OBJ_ALLOW_GEN; } if (key_pol.can_Desfire_Auth) { header |= POLICY_OBJ_ALLOW_DESFIRE_AUTHENTICATION; } if (key_pol.can_Desfire_Dump) { header |= POLICY_OBJ_ALLOW_DESFIRE_DUMP_SESSION_KEYS; } if (key_pol.can_Import_Export) { header |= POLICY_OBJ_ALLOW_IMPORT_EXPORT; } #if SSS_HAVE_SE05X_VER_GTE_06_00 if (key_pol.forbid_Derived_Output) { header |= POLICY_OBJ_FORBID_DERIVED_OUTPUT; } #endif #if SSS_HAVE_SE05X_VER_GTE_06_00 if (key_pol.allow_kdf_ext_rnd) { header |= POLICY_OBJ_ALLOW_KDF_EXT_RANDOM; } #endif sss_se05x_copy_uint32_to_u8_array(header, pbuffer); } static void sss_se05x_update_header_asym_key_policy(sss_policy_asym_key_u key_pol, uint8_t *pbuffer) { uint32_t header = 0; if (key_pol.can_Sign) { header |= POLICY_OBJ_ALLOW_SIGN; } if (key_pol.can_Verify) { header |= POLICY_OBJ_ALLOW_VERIFY; } if (key_pol.can_Encrypt) { header |= POLICY_OBJ_ALLOW_ENC; } if (key_pol.can_Decrypt) { header |= POLICY_OBJ_ALLOW_DEC; } if (key_pol.can_KD) { header |= POLICY_OBJ_ALLOW_KDF; } if (key_pol.can_Wrap) { header |= POLICY_OBJ_ALLOW_WRAP; } if (key_pol.can_Write) { header |= POLICY_OBJ_ALLOW_WRITE; } if (key_pol.can_Gen) { header |= POLICY_OBJ_ALLOW_GEN; } if (key_pol.can_Import_Export) { header |= POLICY_OBJ_ALLOW_IMPORT_EXPORT; } if (key_pol.can_KA) { header |= POLICY_OBJ_ALLOW_KA; } if (key_pol.can_Read) { header |= POLICY_OBJ_ALLOW_READ; } if (key_pol.can_Attest) { header |= POLICY_OBJ_ALLOW_ATTESTATION; } #if SSS_HAVE_SE05X_VER_GTE_06_00 if (key_pol.forbid_Derived_Output) { header |= POLICY_OBJ_FORBID_DERIVED_OUTPUT; } #endif sss_se05x_copy_uint32_to_u8_array(header, pbuffer); } static void sss_se05x_update_header_common_policy(sss_policy_common_u common_pol, uint8_t *pbuffer) { uint32_t header = 0; if (common_pol.can_Delete) { header |= POLICY_OBJ_ALLOW_DELETE; } if (common_pol.forbid_All) { header |= POLICY_OBJ_FORBID_ALL; } if (common_pol.req_Sm) { header |= POLICY_OBJ_REQUIRE_SM; } sss_se05x_copy_uint32_to_u8_array(header, pbuffer); } static void sss_se05x_update_header_pin_policy(sss_policy_userid_u pin_pol, uint8_t *pbuffer) { uint32_t header = 0; if (pin_pol.can_Write) { header |= POLICY_OBJ_ALLOW_WRITE; } sss_se05x_copy_uint32_to_u8_array(header, pbuffer); } static void sss_se05x_update_header_file_policy(sss_policy_file_u file_pol, uint8_t *pbuffer) { uint32_t header = 0; if (file_pol.can_Read) { header |= POLICY_OBJ_ALLOW_READ; } if (file_pol.can_Write) { header |= POLICY_OBJ_ALLOW_WRITE; } sss_se05x_copy_uint32_to_u8_array(header, pbuffer); } static void sss_se05x_update_header_counter_policy(sss_policy_counter_u counter_pol, uint8_t *pbuffer) { uint32_t header = 0; if (counter_pol.can_Read) { header |= POLICY_OBJ_ALLOW_READ; } if (counter_pol.can_Write) { header |= POLICY_OBJ_ALLOW_WRITE; } sss_se05x_copy_uint32_to_u8_array(header, pbuffer); } static void sss_se05x_update_header_pcr_policy(sss_policy_pcr_u pcr_pol, uint8_t *pbuffer) { uint32_t header = 0; if (pcr_pol.can_Read) { header |= POLICY_OBJ_ALLOW_READ; } if (pcr_pol.can_Write) { header |= POLICY_OBJ_ALLOW_WRITE; } sss_se05x_copy_uint32_to_u8_array(header, pbuffer); } static void sss_se05x_update_header_pcr_value_policy(sss_policy_common_pcr_value_u pcr_pol, uint8_t *pbuffer) { uint32_t header = 0; header |= POLICY_OBJ_REQUIRE_PCR_VALUE; sss_se05x_copy_uint32_to_u8_array(header, pbuffer); } static void sss_se05x_update_ext_pcr_value_policy( sss_policy_common_pcr_value_u pcr_pol, uint8_t *pbuffer, uint32_t *ext_offset) { /*copy 4 bytes PCR Object ID*/ sss_se05x_copy_uint32_to_u8_array(pcr_pol.pcrObjId, pbuffer + *ext_offset); *ext_offset += sizeof(pcr_pol.pcrObjId); /*copy 32 bytes PCR value*/ memcpy(pbuffer + *ext_offset, pcr_pol.pcrExpectedValue, sizeof(pcr_pol.pcrExpectedValue)); *ext_offset += sizeof(pcr_pol.pcrExpectedValue); } static void sss_se05x_copy_uint32_to_u8_array(uint32_t u32, uint8_t *pbuffer) { pbuffer[0] |= (uint8_t)((u32 >> 3 * 8) & 0xFF); pbuffer[1] |= (uint8_t)((u32 >> 2 * 8) & 0xFF); pbuffer[2] |= (uint8_t)((u32 >> 1 * 8) & 0xFF); pbuffer[3] |= (uint8_t)((u32 >> 0 * 8) & 0xFF); } static void sss_se05x_copy_uint16_to_u8_array(uint16_t u16, uint8_t *pbuffer) { pbuffer[0] |= (uint8_t)((u16 >> 8) & 0xFF); pbuffer[1] |= (uint8_t)((u16)&0xFF); } static int sss_se05x_find_authId_instances(uint32_t authId, uint8_t *pindices, sss_policy_t *policies) { int count = 0; for (uint32_t i = 0; i <= policies->nPolicies - 1; i++) { if (policies->policies[i] != NULL && policies->policies[i]->auth_obj_id == authId) { *pindices++ = i; count++; } } return count; } sss_status_t sss_se05x_create_object_policy_buffer(sss_policy_t *policies, uint8_t *pbuff, size_t *buf_len) { uint8_t temp_buffer[MAX_OBJ_POLICY_SIZE] = {0}; uint8_t indexArray[MAX_OBJ_POLICY_TYPES] = {0}; uint8_t auth_id_count = 0; uint8_t policiesCopied = 0; uint32_t ext_offset = 0; uint32_t offset = 0; if ((policies == NULL) || (pbuff == NULL) || (buf_len == NULL)) return kStatus_SSS_InvalidArgument; if (policies->nPolicies > SSS_POLICY_COUNT_MAX) { return kStatus_SSS_InvalidArgument; } *buf_len = 0; /*Reinitialize policy buffer for every Secure object*/ memset(pbuff, 0x00, MAX_POLICY_BUFFER_SIZE); for (uint32_t i = 0; i < policies->nPolicies && policiesCopied < policies->nPolicies; i++) { if (policies->policies[i] != NULL) { auth_id_count = sss_se05x_find_authId_instances(policies->policies[i]->auth_obj_id, &indexArray[0], policies); /*length is initialized with default length will be updated when extensions are copied*/ temp_buffer[OBJ_POLICY_LENGTH_OFFSET] = DEFAULT_OBJECT_POLICY_SIZE; /* Copy Auth Id*/ sss_se05x_copy_uint32_to_u8_array( policies->policies[i]->auth_obj_id, &temp_buffer[OBJ_POLICY_AUTHID_OFFSET]); for (int j = 0; j < auth_id_count; j++) { /* Update AR Header as per object type*/ switch (policies->policies[indexArray[j]]->type) { case KPolicy_Sym_Key: sss_se05x_update_header_sym_key_policy( (policies->policies[indexArray[j]])->policy.symmkey, &temp_buffer[OBJ_POLICY_HEADER_OFFSET]); break; case KPolicy_Asym_Key: sss_se05x_update_header_asym_key_policy( (policies->policies[indexArray[j]])->policy.asymmkey, &temp_buffer[OBJ_POLICY_HEADER_OFFSET]); break; case KPolicy_Common: sss_se05x_update_header_common_policy( (policies->policies[indexArray[j]])->policy.common, &temp_buffer[OBJ_POLICY_HEADER_OFFSET]); break; case KPolicy_Common_PCR_Value: sss_se05x_update_header_pcr_value_policy( (policies->policies[indexArray[j]])->policy.common_pcr_value, &temp_buffer[OBJ_POLICY_HEADER_OFFSET]); sss_se05x_update_ext_pcr_value_policy((policies->policies[indexArray[j]])->policy.common_pcr_value, &temp_buffer[OBJ_POLICY_EXT_OFFSET], &ext_offset); temp_buffer[OBJ_POLICY_LENGTH_OFFSET] += OBJ_POLICY_PCR_DATA_SIZE; break; case KPolicy_File: sss_se05x_update_header_file_policy( (policies->policies[indexArray[j]])->policy.file, &temp_buffer[OBJ_POLICY_HEADER_OFFSET]); break; case KPolicy_Counter: sss_se05x_update_header_counter_policy( (policies->policies[indexArray[j]])->policy.counter, &temp_buffer[OBJ_POLICY_HEADER_OFFSET]); break; case KPolicy_PCR: sss_se05x_update_header_pcr_policy( (policies->policies[indexArray[j]])->policy.pcr, &temp_buffer[OBJ_POLICY_HEADER_OFFSET]); break; case KPolicy_UserID: sss_se05x_update_header_pin_policy( (policies->policies[indexArray[j]])->policy.pin, &temp_buffer[OBJ_POLICY_HEADER_OFFSET]); break; default: break; } policies->policies[indexArray[j]] = NULL; } memcpy(pbuff + offset, temp_buffer, (temp_buffer[0] + 1)); *buf_len += (temp_buffer[0] + 1); policiesCopied = policiesCopied + auth_id_count; offset += (temp_buffer[0] + 1); /* reinitialize temp buffer for a new policy*/ memset(&temp_buffer[0], 0x00, sizeof(temp_buffer)); ext_offset = 0; } } return kStatus_SSS_Success; } sss_status_t sss_se05x_create_session_policy_buffer( sss_policy_session_u *session_policy, uint8_t *session_pol_buff, size_t *buf_len) { uint16_t session_header = 0; /*Reinitialize policy buffer for every Secure object*/ memset(session_pol_buff, 0x00, MAX_POLICY_BUFFER_SIZE); if ((session_policy == NULL) || (session_pol_buff == NULL) || (buf_len == NULL)) return kStatus_SSS_InvalidArgument; *buf_len = DEFAULT_SESSION_POLICY_SIZE; /*set default length*/ session_pol_buff[SESSION_POLICY_LENGTH_OFFSET] = DEFAULT_SESSION_POLICY_SIZE; if (session_policy->has_MaxOperationsInSession) { session_header |= POLICY_SESSION_MAX_APDU; sss_se05x_copy_uint16_to_u8_array(session_header, &session_pol_buff[SESSION_POLICY_AR_HEADER_OFFSET]); sss_se05x_copy_uint16_to_u8_array(session_policy->maxOperationsInSession, &session_pol_buff[*buf_len]); *buf_len += sizeof(session_policy->maxOperationsInSession); } if (session_policy->has_MaxDurationOfSession_sec) { session_header |= POLICY_SESSION_MAX_TIME; sss_se05x_copy_uint16_to_u8_array(session_header, &session_pol_buff[SESSION_POLICY_AR_HEADER_OFFSET]); sss_se05x_copy_uint16_to_u8_array(session_policy->maxDurationOfSession_sec, &session_pol_buff[*buf_len]); *buf_len += sizeof(session_policy->maxDurationOfSession_sec); } if (session_policy->allowRefresh) { session_header |= POLICY_SESSION_ALLOW_REFRESH; sss_se05x_copy_uint16_to_u8_array(session_header, &session_pol_buff[SESSION_POLICY_AR_HEADER_OFFSET]); } session_pol_buff[0] = (uint8_t)(*buf_len - 1); //Exclude Length of Policy field. return kStatus_SSS_Success; } #endif /* SSS_HAVE_APPLET_SE05X_IOT */