blob: 4bc6015adc14f6f961ecba5705693a2091d4ade3 [file] [log] [blame]
/*
*
* Copyright 2018-2020 NXP
* SPDX-License-Identifier: Apache-2.0
*/
/** @file */
#include <fsl_sss_se05x_apis.h>
#include <nxLog_sss.h>
#include <string.h>
#if SSS_HAVE_APPLET_SE05X_IOT
#include <fsl_sss_se05x_policy.h>
/*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 */