/** | |
* @file ex_hlse_cert.c | |
* @author NXP Semiconductors | |
* @version 1.0 | |
* @par License | |
* | |
* Copyright 2018 NXP | |
* SPDX-License-Identifier: Apache-2.0 | |
* | |
* @par Description | |
* Example using Certificate objects | |
* | |
*/ | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <assert.h> | |
#include "sm_printf.h" | |
#include "HLSEAPI.h" | |
#include "sm_types.h" | |
#include "sm_apdu.h" | |
#include "tst_sm_util.h" | |
#include "a71ch_util.h" | |
#include "HLSEAPI.h" | |
#include "tst_a71ch_util.h" | |
#include "tst_hlse_a71ch_util.h" | |
static U8 exDataObjUsage(U8 initMode); | |
static U8 exMixedCertsAndDataObj(U8 initMode, U16 nBaseSize, U16 nObj); | |
static U8 exCertUsageBasic(U8 initMode); | |
static U8 exCertUsageEnlarge(U8 initMode); | |
static U8 exCertUsageGpTableLengthUnknown(U8 initMode); | |
static U8 exCertUsageReadOnly(U8 initMode); | |
static U8 exCertEnumerate(void); | |
static U8 exCertGetAttr(void); | |
static U8 exCertSetAttr(void); | |
// internal utilities | |
static HLSE_RET_CODE patchCertificateInitialTL(U8 *clientCertDer, U16 clientCertDerLen); | |
static HLSE_RET_CODE getObject(HLSE_OBJECT_HANDLE handle, U8 *data, U16 *len); | |
static HLSE_RET_CODE setObject(HLSE_OBJECT_HANDLE handle, U8 *data, U16 len); | |
/** | |
* Demonstrate usage of certificate objects | |
*/ | |
U8 exHlseCert() | |
{ | |
U8 result = 1; | |
PRINTF("\r\n-----------\r\nStart exHlseCert()\r\n------------\r\n"); | |
DEV_ClearChannelState(); | |
// Example of Data object usage | |
result &= exDataObjUsage(INIT_MODE_RESET); | |
#if AX_EMBEDDED | |
result &= exMixedCertsAndDataObj(INIT_MODE_RESET, 40 /* size */, 8 /* num of objects */); | |
#else | |
result &= exMixedCertsAndDataObj(INIT_MODE_RESET, 300 /* size */, 8 /* num of objects */); | |
#endif | |
// Example certificate usage with enhanced validations | |
result &= exCertUsageBasic(INIT_MODE_RESET); | |
// Example certificate usage enlarging and updating a certificate | |
result &= exCertUsageEnlarge(INIT_MODE_RESET); | |
// Example of Certificate creation / enumeration / Get / Set / Delete - when Read Only attribute used | |
result &= exCertUsageReadOnly(INIT_MODE_RESET); | |
// Example certificate usage when map contains indirect length (to be obtained from TLV of actual object) | |
result &= exCertUsageGpTableLengthUnknown(INIT_MODE_RESET); | |
// overall result | |
PRINTF("\r\n-----------\r\nEnd exHlseCert(), result = %s\r\n------------\r\n", ((result == 1) ? "OK" : "FAILED")); | |
return result; | |
} | |
/** | |
* Demonstrate usage of certificate object: | |
* | |
* Simulate the following scenario and aim to verify it works correctly: | |
* | |
* - Create Certificate | |
* - Read certificate data and verify correctness | |
* - Index ok | |
* - Value was correctly set | |
* - Update Certificate contents | |
* - Verify Certificate updated correctly | |
* - Delete certificate | |
* - Verify deletion | |
* | |
* @param[in] initMode Visit the documentation of ::a71chInitModule for more information on this parameter | |
*/ | |
static U8 exCertUsageBasic(U8 initMode) | |
{ | |
U8 result = 1; | |
HLSE_RET_CODE hlseRc; | |
HLSE_OBJECT_HANDLE certHandles[5]; | |
U16 certHandlesNum = sizeof(certHandles) / sizeof(HLSE_OBJECT_HANDLE); | |
HLSE_OBJECT_INDEX index = 0; | |
HLSE_OBJECT_TYPE objType = HLSE_CERTIFICATE; | |
// Cert for this test is 50 bytes which occupies 2 chunks of 32 bytes on the GP Storage | |
U8 certData[50]; | |
HLSE_ATTRIBUTE attr[3]; | |
unsigned short templateSize = 3; | |
U8 data[50]; // to hold data to update certificate | |
memset(certHandles, 0x00, sizeof(certHandles)); | |
memset(certData, 0xAA, sizeof(certData)); | |
PRINTF("\r\n-----------\r\nStart exCertUsageBasic(%s)\r\n------------\r\n", getInitModeAsString(initMode)); | |
// Initialize the A71CH (Debug mode restrictions may apply) | |
result &= hlse_a71chInitModule(initMode); | |
assert(result); | |
// start with clean GP table to avoid cached data from previous test | |
hlseRc = Debug_ForceReadGPDataTable(); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
attr[0].type = HLSE_ATTR_OBJECT_TYPE; | |
attr[0].value = &objType; | |
attr[0].valueLen = sizeof(objType); | |
attr[1].type = HLSE_ATTR_OBJECT_INDEX; | |
attr[1].value = &index; | |
attr[1].valueLen = sizeof(index); | |
attr[2].type = HLSE_ATTR_OBJECT_VALUE; | |
attr[2].value = certData; | |
attr[2].valueLen = sizeof(certData); | |
// Create certificate object index = 0 | |
PRINTF("\r\nHLSE_CreateObject() - Create certificate object...\r\n------------\r\n"); | |
hlseRc = HLSE_CreateObject(attr, templateSize, &certHandles[0]); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
// assumption : correct slot in GP Table data was occupied | |
// TODO: consider additional low level test for it | |
// Now read certificate data and verify correctness | |
// Find certificate where index=0 | |
// enumerate objects - we should have one certificate by now with index 0 | |
PRINTF("\r\nHLSE_EnumerateObjects()...\r\n"); | |
certHandlesNum = sizeof(certHandles) / sizeof(HLSE_OBJECT_HANDLE); | |
hlseRc = HLSE_EnumerateObjects(HLSE_CERTIFICATE, certHandles, &certHandlesNum); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
result &= AX_CHECK_U16(certHandlesNum, 1, "err"); | |
// Get the attributes of the single certificate we have created | |
// - Object Index | |
// - Certificate data | |
PRINTF("\r\nHLSE_GetObjectAttribute()...\r\n"); | |
{ | |
U32 certIndex = 0xFFFFFFFF; | |
HLSE_ATTRIBUTE attrL; | |
attrL.type = HLSE_ATTR_OBJECT_INDEX; | |
attrL.value = &certIndex; | |
attrL.valueLen = sizeof(certIndex); | |
hlseRc = HLSE_GetObjectAttribute(certHandles[certHandlesNum - 1], &attrL); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
PRINTF("\tcert index = 0x%lx\r\n", certIndex); | |
result &= AX_CHECK_U16((U16)certIndex, 0x00, "err"); | |
} | |
PRINTF("Verify Certificate contents...\r\n"); | |
{ | |
U8 readCertData[50]; | |
HLSE_ATTRIBUTE attrL; | |
attrL.type = HLSE_ATTR_OBJECT_VALUE; | |
attrL.value = readCertData; | |
attrL.valueLen = sizeof(readCertData); | |
hlseRc = HLSE_GetObjectAttribute(certHandles[certHandlesNum - 1], &attrL); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
result &= AX_COMPARE_BYTE_ARRAY("certOnA71CH", readCertData, sizeof(certData), | |
"expected cert data", certData, sizeof(certData), AX_COLON_32); | |
} | |
PRINTF("Update Certificate contents...\r\n"); | |
{ | |
HLSE_ATTRIBUTE attrL; | |
memset(data, 0xAB, sizeof(data)); | |
attrL.type = HLSE_ATTR_OBJECT_VALUE; | |
attrL.value = data; | |
attrL.valueLen = sizeof(data); | |
hlseRc = HLSE_SetObjectAttribute(certHandles[certHandlesNum - 1], &attrL); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
} | |
PRINTF("Verify Certificate Updated correctly...\r\n"); | |
{ | |
U8 readCertData[50]; | |
HLSE_ATTRIBUTE attrL; | |
memset(readCertData, 0x00, sizeof(readCertData)); | |
attrL.type = HLSE_ATTR_OBJECT_VALUE; | |
attrL.value = readCertData; | |
attrL.valueLen = sizeof(readCertData); | |
hlseRc = HLSE_GetObjectAttribute(certHandles[certHandlesNum - 1], &attrL); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
result &= AX_COMPARE_BYTE_ARRAY("read data", readCertData, sizeof(certData), | |
"expected cert data", data, sizeof(data), AX_COLON_32); | |
} | |
// Delete the certificate | |
PRINTF("\r\nHLSE_EraseObject()...\r\n"); | |
hlseRc = HLSE_EraseObject(certHandles[certHandlesNum - 1]); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
// Verify it was actually deleted | |
// enumerate objects - we should have no certificates by now | |
PRINTF("\r\nVerify object was erased...\r\n"); | |
certHandlesNum = sizeof(certHandles) / sizeof(HLSE_OBJECT_HANDLE); | |
hlseRc = HLSE_EnumerateObjects(HLSE_CERTIFICATE, certHandles, &certHandlesNum); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
result &= AX_CHECK_U16(certHandlesNum, 0, "err"); | |
PRINTF("\r\n-----------\r\nEnd exCertUsageBasic(), result = %s\r\n------------\r\n", ((result == 1) ? "OK" : "FAILED")); | |
return result; | |
} | |
/** | |
* Demonstrate usage of a data object: | |
* | |
* Simulate the following scenario and aim to verify it works correctly: | |
* | |
* - Create Data Object | |
* - Shows how to obtain the object GP offset | |
* - Read Data object and verify correctness | |
* - Index ok | |
* - Value was correctly set | |
* - Update Data Object contents | |
* - Verify Data Object updated correctly | |
* | |
* - Show direct update of partial block in Data Object | |
* - Show direct read of partial block in Data Object | |
* - Show direct Read / Write with offset that exceeds object boundaries is not allowed | |
* - Show direct Read / Write with length that exceeds object boundaries is not allowed | |
* | |
* - Delete Data Object | |
* - Verify deletion | |
* | |
* @param[in] initMode Visit the documentation of ::a71chInitModule for more information on this parameter | |
*/ | |
static U8 exDataObjUsage(U8 initMode) | |
{ | |
U8 result = 1; | |
HLSE_RET_CODE hlseRc; | |
HLSE_OBJECT_HANDLE handles[5]; | |
U16 handlesNum = sizeof(handles) / sizeof(HLSE_OBJECT_HANDLE); | |
HLSE_OBJECT_INDEX index = 0; | |
HLSE_OBJECT_TYPE objType = HLSE_DATA; | |
// data for this test is 100 bytes which occupies 2 chunks of 32 bytes on the GP Storage | |
U8 data[50]; | |
HLSE_ATTRIBUTE attr[3]; | |
unsigned short templateSize = 3; | |
//U8 updateData[50]; // to hold data to update data object | |
memset(handles, 0x00, sizeof(handles)); | |
memset(data, 0xAA, sizeof(data)); | |
PRINTF("\r\n-----------\r\nStart exDataObjUsage(%s)\r\n------------\r\n", getInitModeAsString(initMode)); | |
// Initialize the A71CH (Debug mode restrictions may apply) | |
result &= hlse_a71chInitModule(initMode); | |
assert(result); | |
// start with clean GP table to avoid cached data from previous test | |
hlseRc = Debug_ForceReadGPDataTable(); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
attr[0].type = HLSE_ATTR_OBJECT_TYPE; | |
attr[0].value = &objType; | |
attr[0].valueLen = sizeof(objType); | |
attr[1].type = HLSE_ATTR_OBJECT_INDEX; | |
attr[1].value = &index; | |
attr[1].valueLen = sizeof(index); | |
attr[2].type = HLSE_ATTR_OBJECT_VALUE; | |
attr[2].value = data; | |
attr[2].valueLen = sizeof(data); | |
// Create data object index = 0 | |
PRINTF("\r\nHLSE_CreateObject() - Create Data object...\r\n------------\r\n"); | |
hlseRc = HLSE_CreateObject(attr, templateSize, &handles[0]); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
// assumption : correct slot in GP Table data was occupied | |
// TODO: consider additional low level test for it | |
// Now read data object and verify correctness | |
// Find data object where index=0 | |
// enumerate objects - we should have one certificate by now with index 0 | |
PRINTF("\r\nHLSE_EnumerateObjects()...\r\n"); | |
handlesNum = sizeof(handles) / sizeof(HLSE_OBJECT_HANDLE); | |
hlseRc = HLSE_EnumerateObjects(HLSE_DATA, handles, &handlesNum); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
result &= AX_CHECK_U16(handlesNum, 1, "err"); | |
// show how to get the object's GP offset | |
PRINTF("\r\nGet object GP offset...\r\n"); | |
{ | |
U16 offset; | |
HLSE_ATTRIBUTE attrL; | |
attrL.type = HLSE_ATTR_OBJECT_OFFSET; | |
attrL.value = &offset; | |
attrL.valueLen = sizeof(offset); | |
hlseRc = HLSE_GetObjectAttribute(handles[handlesNum - 1], &attrL); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
PRINTF("\tdata object offset = 0x%u\r\n", offset); | |
} | |
// make sure our data object is the one we previously created | |
// Get the attributes of the single data object we have | |
PRINTF("\r\nHLSE_GetObjectAttribute()...\r\n"); | |
{ | |
U32 dataIndex = 0xFFFFFFFF; | |
HLSE_ATTRIBUTE attrL; | |
attrL.type = HLSE_ATTR_OBJECT_INDEX; | |
attrL.value = &dataIndex; | |
attrL.valueLen = sizeof(dataIndex); | |
hlseRc = HLSE_GetObjectAttribute(handles[handlesNum - 1], &attrL); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
PRINTF("\tdata object index = 0x%lx\r\n", dataIndex); | |
result &= AX_CHECK_U16((U16)dataIndex, 0x00, "err"); | |
} | |
PRINTF("Verify Data object contents...\r\n"); | |
{ | |
U8 readData[50]; | |
HLSE_ATTRIBUTE attrL; | |
attrL.type = HLSE_ATTR_OBJECT_VALUE; | |
attrL.value = readData; | |
attrL.valueLen = sizeof(readData); | |
hlseRc = HLSE_GetObjectAttribute(handles[handlesNum - 1], &attrL); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
result &= AX_COMPARE_BYTE_ARRAY("dataOnA71CH", readData, sizeof(data), | |
"expected data", data, sizeof(data), AX_COLON_32); | |
} | |
PRINTF("Update Data object contents...\r\n"); | |
{ | |
HLSE_ATTRIBUTE attrL; | |
memset(data, 0xAB, sizeof(data)); | |
attrL.type = HLSE_ATTR_OBJECT_VALUE; | |
attrL.value = data; | |
attrL.valueLen = sizeof(data); | |
hlseRc = HLSE_SetObjectAttribute(handles[handlesNum - 1], &attrL); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
} | |
PRINTF("Verify Data object Updated correctly...\r\n"); | |
{ | |
U8 readData[50]; | |
HLSE_ATTRIBUTE attrL; | |
memset(readData, 0x00, sizeof(readData)); | |
attrL.type = HLSE_ATTR_OBJECT_VALUE; | |
attrL.value = readData; | |
attrL.valueLen = sizeof(readData); | |
hlseRc = HLSE_GetObjectAttribute(handles[handlesNum - 1], &attrL); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
result &= AX_COMPARE_BYTE_ARRAY("read data", readData, sizeof(readData), | |
"expected data", data, sizeof(data), AX_COLON_32); | |
} | |
PRINTF("Show usage of direct read / Update access to Data Object...\r\n"); | |
{ | |
HLSE_ATTRIBUTE attrL; | |
HLSE_DIRECT_ACCESS_ATTRIBUTE_VALUE theValue; | |
U8 buffer[50]; // a buffer to hold the read data | |
U8 refBuffer2[50]; | |
memset(buffer, 0x00, sizeof(buffer)); | |
attrL.type = HLSE_ATTR_DIRECT_ACCESS_OBJECT_VALUE; | |
PRINTF(" Verify Direct Read of Data Object...\r\n"); | |
theValue.offset = 0; | |
theValue.bytes = 32; | |
theValue.buffer = buffer; | |
theValue.bufferLen = sizeof(buffer); | |
attrL.value = &theValue; | |
attrL.valueLen = sizeof(theValue); | |
hlseRc = HLSE_GetObjectAttribute(handles[handlesNum - 1], &attrL); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
result &= AX_COMPARE_BYTE_ARRAY("dataOnA71CH", buffer, theValue.bytes, | |
"expected data", data, theValue.bytes, AX_COLON_32); | |
// Now show usage of direct update to data object - update 10 bytes at offset 0 to 0x11 | |
memset(buffer, 0x11, 10); | |
theValue.bytes = 10; | |
theValue.buffer = buffer; | |
hlseRc = HLSE_SetObjectAttribute(handles[handlesNum - 1], &attrL); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
PRINTF(" Verify Direct Update of Data Object...\r\n"); | |
memcpy(refBuffer2, buffer, 50); | |
memset(buffer, 0x00, sizeof(buffer)); | |
theValue.bytes = 32; | |
theValue.buffer = buffer; | |
theValue.bufferLen = sizeof(buffer); | |
hlseRc = HLSE_GetObjectAttribute(handles[handlesNum - 1], &attrL); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
result &= AX_COMPARE_BYTE_ARRAY("dataOnA71CH", buffer, theValue.bytes, | |
"expected data", refBuffer2, theValue.bytes, AX_COLON_32); | |
PRINTF(" Test Direct Read / Write with offset that exceeds object boundaries...\r\n"); | |
{ | |
// Note : data object 0 is at offset 0 , size 50 bytes | |
memset(buffer, 0x00, sizeof(buffer)); | |
theValue.offset = 100; | |
theValue.bytes = 50; | |
theValue.buffer = buffer; | |
theValue.bufferLen = sizeof(buffer); | |
// Read with offset exceeding object boundary - not allowed | |
hlseRc = HLSE_GetObjectAttribute(handles[handlesNum - 1], &attrL); | |
result &= AX_CHECK_SW(hlseRc, HLSE_ERR_MEMORY, "err"); | |
// Write with offset exceeding object boundary - not allowed | |
hlseRc = HLSE_SetObjectAttribute(handles[handlesNum - 1], &attrL); | |
result &= AX_CHECK_SW(hlseRc, HLSE_ERR_MEMORY, "err"); | |
} | |
PRINTF(" Test Direct Read / Write with length that exceeds object boundaries...\r\n"); | |
{ | |
// Note : data object 0 is at offset 0 , size 50 bytes | |
memset(buffer, 0x00, sizeof(buffer)); | |
theValue.offset = 30; | |
theValue.bytes = 50; | |
theValue.buffer = buffer; | |
theValue.bufferLen = sizeof(buffer); | |
// Read exceeding object boundary - not allowed | |
hlseRc = HLSE_GetObjectAttribute(handles[handlesNum - 1], &attrL); | |
result &= AX_CHECK_SW(hlseRc, HLSE_ERR_MEMORY, "err"); | |
// Write exceeding object boundary - not allowed | |
hlseRc = HLSE_SetObjectAttribute(handles[handlesNum - 1], &attrL); | |
result &= AX_CHECK_SW(hlseRc, HLSE_ERR_MEMORY, "err"); | |
} | |
} | |
// Delete the Data object | |
PRINTF("\r\nHLSE_EraseObject()...\r\n"); | |
hlseRc = HLSE_EraseObject(handles[handlesNum - 1]); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
// Verify it was actually deleted | |
// enumerate objects - we should have no certificates by now | |
PRINTF("\r\nVerify object was erased...\r\n"); | |
handlesNum = sizeof(handles) / sizeof(HLSE_OBJECT_HANDLE); | |
hlseRc = HLSE_EnumerateObjects(HLSE_DATA, handles, &handlesNum); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
result &= AX_CHECK_U16(handlesNum, 0, "err"); | |
PRINTF("\r\n-----------\r\nEnd exDataObjUsage(), result = %s\r\n------------\r\n", ((result == 1) ? "OK" : "FAILED")); | |
return result; | |
} | |
#define N_ADV_CERT 255 | |
#define MAX_ADV_CERT_SIZE (4096 - 32) | |
#define LEN_SHORT_FORM_MAX 127 | |
#define LEN_LONG_FORM_ONE_BYTE_MAX 255 | |
#define LEN_LONG_FORM_TWO_BYTE_MAX 65536 | |
#define ERR_GP_NO_CERT 0x2000 | |
/** | |
* An Example to show usage of mixed certificates and data objects | |
* | |
* Scenario: | |
* - Create certificates and data objects | |
* - Read back the certificate and data objects | |
* - verify objects exists | |
* - verify object's length matches | |
* - verify objects's data matches | |
* - Delete a random number of objects | |
* - Read back the remaining certificate and data objects | |
* - verify objects exists | |
* - verify object's length matches | |
* - verify objects's data matches | |
* - Update an objects with new data | |
* - Read back the remaining certificate and data objects | |
* - verify objects exists | |
* - verify object's length matches | |
* - verify objects's data matches | |
* - Delete all objects | |
* | |
* @param[in] initMode Visit the documentation of ::a71chInitModule for more information on this parameter | |
* @param[in] nBaseSize base size of Cert/Data object to create | |
* @param[in] nObj number of total objects to create | |
*/ | |
static U8 exMixedCertsAndDataObj(U8 initMode, U16 nBaseSize, U16 nObj) | |
{ | |
U8 result = 1; | |
HLSE_RET_CODE hlseRc; | |
HLSE_OBJECT_HANDLE mixedHandles[N_ADV_CERT]; // to hold handles of objects created | |
HLSE_OBJECT_INDEX index = 0; | |
HLSE_OBJECT_TYPE objType = HLSE_CERTIFICATE; | |
U8 *refData[N_ADV_CERT]; | |
U16 effectiveSize[N_ADV_CERT]; | |
U8 *refDataU[N_ADV_CERT]; | |
U16 effectiveSizeU[N_ADV_CERT]; | |
HLSE_ATTRIBUTE attr[3]; | |
unsigned short templateSize = 3; | |
U8 data[MAX_ADV_CERT_SIZE]; // to hold data to read certificate | |
U8 nObjCreated = 0; // certs and data objects | |
U8 nObjToDelete = 0; | |
U8 handleIndDeleted[N_ADV_CERT]; // to hold array ind of handle deleted | |
U8 handleAlreadySelected = 0; | |
int i, j; | |
PRINTF("\r\n-----------\r\nStart exMixedCertsAndDataObjUsage(%s)\r\n------------\r\n", getInitModeAsString(initMode)); | |
// Initialize the A71CH (Debug mode restrictions may apply) | |
result &= hlse_a71chInitModule(initMode); | |
assert(result); | |
// start with clean GP table to avoid cached data from previous test | |
hlseRc = Debug_ForceReadGPDataTable(); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
memset(mixedHandles, 0x00, sizeof(mixedHandles)); | |
memset(handleIndDeleted, 0x00, sizeof(handleIndDeleted)); | |
// Create reference arrays containing random values which could serve as certificates or data objects | |
srand(0); | |
for (i = 0; i < nObj; i++) | |
{ | |
effectiveSize[i] = (U16)(nBaseSize - (i % 24)); | |
refData[i] = (U8 *)malloc(effectiveSize[i]); | |
for (j = 0; j < effectiveSize[i]; j++) | |
{ | |
refData[i][j] = (U8)rand(); | |
} | |
} | |
// Create reference arrays containing random values which could serve as certificates or data objects, for updating the objects later | |
for (i = 0; i < nObj; i++) | |
{ | |
effectiveSizeU[i] = (U16)(nBaseSize - (i % 24)); | |
refDataU[i] = (U8 *)malloc(effectiveSizeU[i]); | |
for (j = 0; j < effectiveSizeU[i]; j++) | |
{ | |
refDataU[i][j] = (U8)rand(); | |
} | |
} | |
// Since the reference data arrays can be used as certificate we have to patch it to make sure it begins with a TLV of the certificate size, | |
// as this determines the certificate value returned when we retrieve it | |
for (i = 0; i < nObj; i++) | |
{ | |
hlseRc = patchCertificateInitialTL(refData[i], effectiveSize[i]); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "Failed to patch initial TL of certificate"); | |
hlseRc = patchCertificateInitialTL(refDataU[i], effectiveSizeU[i]); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "Failed to patch initial TL of certificate"); | |
} | |
PRINTF("\r\n-----------\r\nStart intMixedCertsAndDataObjUsage()\r\n------------\r\n"); | |
for (i = 0; i < nObj; i++) | |
{ | |
index = (HLSE_OBJECT_INDEX)i; | |
// create mixed data objects and certficiates objects | |
objType = (i % 2 == 0) ? HLSE_CERTIFICATE : HLSE_DATA; | |
attr[0].type = HLSE_ATTR_OBJECT_TYPE; | |
attr[0].value = &objType; | |
attr[0].valueLen = sizeof(objType); | |
attr[1].type = HLSE_ATTR_OBJECT_INDEX; | |
attr[1].value = &index; | |
attr[1].valueLen = sizeof(index); | |
attr[2].type = HLSE_ATTR_OBJECT_VALUE; | |
attr[2].value = refData[i]; | |
attr[2].valueLen = effectiveSize[i]; | |
// Create certificate object @ index | |
PRINTF("\r\nHLSE_CreateObject(index=%lu, size=%d) - Create %s object...\r\n------------\r\n", | |
index, attr[2].valueLen, (objType == HLSE_CERTIFICATE ? "Certificate" : "Data")); | |
hlseRc = HLSE_CreateObject(attr, templateSize, &mixedHandles[i]); | |
if ((hlseRc == HLSE_ERR_MEMORY) && (index > 4)) { | |
// this is acceptable since we managed to create at least 5 certificates | |
PRINTF("\r\nGp Memory filled up"); | |
break; | |
} | |
else if (hlseRc == HLSE_SW_OK) | |
{ | |
nObjCreated++; | |
} | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
} | |
PRINTF("\r\nCreated %02d total objects ( mixed data and certificates objects )...", nObjCreated); | |
PRINTF("\r\nNow read back certificates and data objects..."); | |
for (i = 0; i < nObjCreated; i++) | |
{ | |
U16 dataLen = MAX_ADV_CERT_SIZE; | |
U8 localScore = 1; | |
hlseRc = getObject(mixedHandles[i], data, &dataLen); | |
localScore &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
// Does the length match? | |
localScore &= AX_CHECK_U16(dataLen, effectiveSize[i], "dataLen"); | |
// Does the data match? | |
localScore &= AX_COMPARE_BYTE_ARRAY("data", data, dataLen, "refData", refData[i], effectiveSize[i], AX_COLON_16); | |
if (localScore != 1) { PRINTF("\r\nFailed to retrieve certificate at index %d (expected size=%d)\r\n", i, effectiveSize[i]); } | |
result &= localScore; | |
} | |
// Delete a random number of objects | |
do { | |
nObjToDelete = (U8)(rand() % (nObjCreated / 2)); | |
} while (nObjToDelete == 0); | |
PRINTF("\r\nAbout to delete %d objects...", nObjToDelete); | |
for (i = 0; i < nObjToDelete; i++) | |
{ | |
handleAlreadySelected = 0; | |
// find an index to delete | |
do { | |
// index in mixedHandles array of handle to delete | |
index = (U8)(rand() % nObjCreated); | |
// verify this index was not already deleted | |
if (handleIndDeleted[index] == 1) { | |
// need to select another handle | |
handleAlreadySelected = 1; | |
} | |
else { | |
handleAlreadySelected = 0; | |
} | |
} while (handleAlreadySelected == 1); | |
// set this index as a handle which was deleted | |
handleIndDeleted[index] = 1; | |
// Delete the object | |
PRINTF("\r\nHLSE_EraseObject(), handle=0x%lX...\r\n", mixedHandles[index]); | |
hlseRc = HLSE_EraseObject(mixedHandles[index]); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
} | |
// Verify the remaining objects are still ok | |
PRINTF("\r\nNow read back remaining certificates and data objects...\r\n"); | |
for (i = 0; i < nObjCreated; i++) | |
{ | |
U16 dataLen = MAX_ADV_CERT_SIZE; | |
U8 localScore = 1; | |
// ignore this handle if was deleted | |
if (handleIndDeleted[i] != 0) | |
{ | |
// skip this deleted object; | |
continue; | |
} | |
hlseRc = getObject(mixedHandles[i], data, &dataLen); | |
localScore &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
// Does the length match? | |
localScore &= AX_CHECK_U16(dataLen, effectiveSize[i], "dataLen"); | |
// Does the certificate match? | |
localScore &= AX_COMPARE_BYTE_ARRAY("data", data, dataLen, "refData", refData[i], effectiveSize[i], AX_COLON_16); | |
if (localScore != 1) { PRINTF("\r\nFailed to retrieve certificate at index %d (expected size=%d)\r\n", i, effectiveSize[i]); } | |
result &= localScore; | |
} | |
// Update remaining objects with the alternate reference data, and verify updated data succesfull | |
PRINTF("\r\nNow update remaining certificates and data objects...\r\n"); | |
for (i = 0; i < nObjCreated; i++) | |
{ | |
U16 dataLen; | |
U8 localScore = 1; | |
// ignore this handle if was deleted | |
if (handleIndDeleted[i] != 0) | |
{ | |
// skip this deleted object; | |
continue; | |
} | |
// Set object with new data | |
memcpy(data, refDataU[i], effectiveSizeU[i]); | |
dataLen = effectiveSizeU[i]; | |
hlseRc = setObject(mixedHandles[i], data, dataLen); | |
localScore &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
// Get updated data | |
memset(data, 0, sizeof(data)); | |
dataLen = MAX_ADV_CERT_SIZE; | |
hlseRc = getObject(mixedHandles[i], data, &dataLen); | |
localScore &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
// Does the length match? | |
localScore &= AX_CHECK_U16(dataLen, effectiveSizeU[i], "dataLen"); | |
// Does the data match? | |
localScore &= AX_COMPARE_BYTE_ARRAY("data", data, dataLen, "refData", refDataU[i], effectiveSizeU[i], AX_COLON_16); | |
if (localScore != 1) { PRINTF("\r\nFailed to retrieve certificate at index %d (expected size=%d)\r\n", i, effectiveSize[i]); } | |
result &= localScore; | |
} | |
/* | |
* Delete all objects | |
*/ | |
PRINTF("\r\nNow Delete all objects...\r\n"); | |
for (i = 0; i < nObjCreated; i++) | |
{ | |
// ignore this handle if was deleted | |
if (handleIndDeleted[i] != 0) | |
{ | |
// skip this deleted object; | |
continue; | |
} | |
// set this index as a handle which was deleted | |
handleIndDeleted[i] = 1; | |
// Delete the object | |
PRINTF("\r\nHLSE_EraseObject(), handle=0x%lX...\r\n", mixedHandles[i]); | |
hlseRc = HLSE_EraseObject(mixedHandles[i]); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
} | |
for (i = 0; i < nObjCreated; i++) | |
{ | |
free(refData[i]); | |
free(refDataU[i]); | |
} | |
PRINTF("\r\n-----------\r\nEnd exMixedCertsAndDataObjUsage(), result = %s\r\n------------\r\n", ((result == 1) ? "OK" : "FAILED")); | |
return result; | |
} | |
/** | |
* Demonstrate usage of certificate objects: | |
* | |
* Simulate the following scenario and aim to verify it works correctly: | |
* | |
* - Create certificates | |
* - Verify cannot create additional certificate | |
* - Verify allows to enlarge a certificate with size within allocated boundary | |
* - Verify cannot enlarge beyond the allocated boundary | |
* - Delete the certificate | |
* - Recreate it with bigger size | |
* - Verify last certificate created still exists | |
* | |
* @param[in] initMode Visit the documentation of ::a71chInitModule for more information on this parameter | |
*/ | |
static U8 exCertUsageEnlarge(U8 initMode) | |
{ | |
U8 result = 1; | |
HLSE_RET_CODE hlseRc; | |
// num of certificates to try to create ( actually created depends on GP memory availability ) | |
U8 nCertsToCreate = 50; | |
// Note at max of 254 objects could be stored in the Gp table | |
// we allocate here space for one more in case we want to check that more that that is not possible | |
HLSE_OBJECT_HANDLE certHandles[255 + 1]; | |
U8 nCertsCreated = 0; | |
// to hold actual handles created | |
//HLSE_OBJECT_HANDLE certHandle0; | |
//HLSE_OBJECT_HANDLE certHandle1; | |
HLSE_OBJECT_HANDLE certHandle2; | |
HLSE_OBJECT_HANDLE certHandle3; | |
//HLSE_OBJECT_HANDLE certHandle4; | |
HLSE_OBJECT_HANDLE lastCertHandle; | |
HLSE_OBJECT_INDEX index = 0; | |
HLSE_OBJECT_TYPE objType = HLSE_CERTIFICATE; | |
U8 indexCert; | |
U16 certHandlesNum; | |
// Cert for this test is 32 bytes which occupies 2 chunks of 32 bytes on the GP Storage | |
U8 certData[50]; | |
HLSE_ATTRIBUTE attr[3]; | |
unsigned short templateSize = 3; | |
U8 dataIn2Chunks[60]; // to hold data to update certificate - within 2 chunks boundary | |
U8 dataIn3Chunks[90]; // to hold data to update certificate - within 3 chunks boundary | |
memset(certHandles, 0x00, sizeof(certHandles)); | |
memset(certData, 0xAA, sizeof(certData)); | |
PRINTF("\r\n-----------\r\nStart exCertUsageEnlarge(%s)\r\n------------\r\n", getInitModeAsString(initMode)); | |
// Initialize the A71CH (Debug mode restrictions may apply) | |
result &= hlse_a71chInitModule(initMode); | |
assert(result); | |
// start with clean GP table to avoid cached data from previous test | |
hlseRc = Debug_ForceReadGPDataTable(); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
attr[0].type = HLSE_ATTR_OBJECT_TYPE; | |
attr[0].value = &objType; | |
attr[0].valueLen = sizeof(objType); | |
attr[1].type = HLSE_ATTR_OBJECT_INDEX; | |
attr[1].value = &index; | |
attr[1].valueLen = sizeof(index); | |
attr[2].type = HLSE_ATTR_OBJECT_VALUE; | |
attr[2].value = certData; | |
attr[2].valueLen = sizeof(certData); | |
PRINTF("\r\nAbout to create up to %02d certificates...", nCertsToCreate); | |
for (indexCert = 0; indexCert < nCertsToCreate; indexCert++) | |
{ | |
index = indexCert; | |
memset(certData, (0xAA+index), sizeof(certData)); | |
PRINTF("\r\nHLSE_CreateObject() - Create certificate object(0x%02lx)", index); | |
hlseRc = HLSE_CreateObject(attr, templateSize, &certHandles[indexCert]); | |
if ((hlseRc != HLSE_SW_OK) && (indexCert > 4)) { | |
// this is acceptable since we managed to create 5 certificates | |
break; | |
} | |
else if (hlseRc == HLSE_SW_OK ) | |
{ | |
nCertsCreated++; | |
} | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
} | |
PRINTF("\r\nCreated %02d certificates...", nCertsCreated); | |
// save the handles as the values in the array might be changed . not reflecting the actual handles , after deletion | |
//certHandle0 = certHandles[0]; | |
//certHandle1 = certHandles[1]; | |
certHandle2 = certHandles[2]; | |
certHandle3 = certHandles[3]; | |
//certHandle4 = certHandles[4]; | |
lastCertHandle = certHandles[nCertsCreated - 1]; | |
// Enlarge certificate at index=2 within boundary | |
PRINTF("Try to Enlarge Certificate contents within 2 chunks...\r\n"); | |
{ | |
HLSE_ATTRIBUTE attrL; | |
memset(dataIn2Chunks, 0xBB, sizeof(dataIn2Chunks)); | |
attrL.type = HLSE_ATTR_OBJECT_VALUE; | |
attrL.value = dataIn2Chunks; | |
attrL.valueLen = sizeof(dataIn2Chunks); | |
hlseRc = HLSE_SetObjectAttribute(certHandle2, &attrL); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
} | |
PRINTF("Verify Certificate Updated correctly...\r\n"); | |
{ | |
U8 readCertData[60]; | |
HLSE_ATTRIBUTE attrL; | |
memset(readCertData, 0x00, sizeof(readCertData)); | |
attrL.type = HLSE_ATTR_OBJECT_VALUE; | |
attrL.value = readCertData; | |
attrL.valueLen = sizeof(readCertData); | |
hlseRc = HLSE_GetObjectAttribute(certHandle2, &attrL); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
result &= AX_COMPARE_BYTE_ARRAY("read data", readCertData, sizeof(readCertData), | |
"expected cert data", dataIn2Chunks, sizeof(dataIn2Chunks), AX_COLON_32); | |
} | |
// Enlarge certificate at index=2, over the boundary - not allowed - need to delete it and recreate it | |
PRINTF("Try to Enlarge Certificate with 3 chunks data over the allocated size - not allowed...\r\n"); | |
{ | |
HLSE_ATTRIBUTE attrL; | |
memset(dataIn3Chunks, 0xCC, sizeof(dataIn3Chunks)); | |
attrL.type = HLSE_ATTR_OBJECT_VALUE; | |
attrL.value = dataIn3Chunks; | |
attrL.valueLen = sizeof(dataIn3Chunks); | |
hlseRc = HLSE_SetObjectAttribute(certHandle2, &attrL); | |
result &= AX_CHECK_SW(hlseRc, HLSE_ERR_MEMORY, "err"); | |
} | |
PRINTF("Verify Certificate contents has not changed...\r\n"); | |
{ | |
U8 readCertData[60]; | |
HLSE_ATTRIBUTE attrL; | |
memset(readCertData, 0x00, sizeof(readCertData)); | |
attrL.type = HLSE_ATTR_OBJECT_VALUE; | |
attrL.value = readCertData; | |
attrL.valueLen = sizeof(readCertData); | |
hlseRc = HLSE_GetObjectAttribute(certHandle2, &attrL); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
result &= AX_COMPARE_BYTE_ARRAY("read data", readCertData, sizeof(readCertData), | |
"expected cert data", dataIn2Chunks, sizeof(dataIn2Chunks), AX_COLON_32); | |
} | |
// enumerate objects - we should have nCertsCreated objects | |
memset(certHandles, 0, sizeof(certHandles)); | |
PRINTF("\r\nHLSE_EnumerateObjects()...\r\n"); | |
certHandlesNum = sizeof(certHandles) / sizeof(HLSE_OBJECT_HANDLE); | |
hlseRc = HLSE_EnumerateObjects(HLSE_CERTIFICATE, certHandles, &certHandlesNum); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
result &= AX_CHECK_U16(certHandlesNum, nCertsCreated, "err"); | |
// Need to delete the object and recreate it | |
PRINTF("\r\nHLSE_EraseObject()...\r\n"); | |
hlseRc = HLSE_EraseObject(certHandle2); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
nCertsCreated--; | |
// enumerate objects - we should have nCertsCreated objects | |
memset(certHandles, 0, sizeof(certHandles)); | |
PRINTF("\r\nHLSE_EnumerateObjects()...\r\n"); | |
certHandlesNum = sizeof(certHandles) / sizeof(HLSE_OBJECT_HANDLE); | |
hlseRc = HLSE_EnumerateObjects(HLSE_CERTIFICATE, certHandles, &certHandlesNum); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
result &= AX_CHECK_U16(certHandlesNum, nCertsCreated, "err"); | |
// | |
// recreate it - should now succeed | |
index = 2; | |
// set the reference data that in cert 3 that is expected not to change | |
memset(dataIn2Chunks, (0xBB + index), sizeof(certData)); | |
{ | |
attr[0].type = HLSE_ATTR_OBJECT_TYPE; | |
attr[0].value = &objType; | |
attr[0].valueLen = sizeof(objType); | |
attr[1].type = HLSE_ATTR_OBJECT_INDEX; | |
attr[1].value = &index; | |
attr[1].valueLen = sizeof(index); | |
attr[2].type = HLSE_ATTR_OBJECT_VALUE; | |
attr[2].value = dataIn2Chunks; | |
attr[2].valueLen = sizeof(dataIn2Chunks); | |
PRINTF("\r\nHLSE_CreateObject() - Create certificate object(0x%02lx)\r\n", index); | |
hlseRc = HLSE_CreateObject(attr, templateSize, &certHandle2); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
nCertsCreated++; | |
} | |
PRINTF("Verify Certificate Updated correctly...\r\n"); | |
{ | |
U8 readCertData[60]; | |
HLSE_ATTRIBUTE attrL; | |
memset(readCertData, 0x00, sizeof(readCertData)); | |
attrL.type = HLSE_ATTR_OBJECT_VALUE; | |
attrL.value = readCertData; | |
attrL.valueLen = sizeof(readCertData); | |
hlseRc = HLSE_GetObjectAttribute(certHandle2, &attrL); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
result &= AX_COMPARE_BYTE_ARRAY("read data", readCertData, sizeof(readCertData), | |
"expected cert data", dataIn2Chunks, sizeof(dataIn2Chunks), AX_COLON_32); | |
} | |
PRINTF("Verify Cert 4 still exists\r\n"); | |
{ | |
U8 readCertData[90]; | |
HLSE_ATTRIBUTE attrL; | |
index = 3; | |
memset(readCertData, 0x00, sizeof(readCertData)); | |
attrL.type = HLSE_ATTR_OBJECT_VALUE; | |
attrL.value = readCertData; | |
attrL.valueLen = sizeof(readCertData); | |
hlseRc = HLSE_GetObjectAttribute(certHandle3 /*certHandles[index]*/, &attrL); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
// set the reference data that in cert 3 that is expected not to change | |
memset(certData, (0xAA + index), sizeof(certData)); | |
result &= AX_COMPARE_BYTE_ARRAY("read data", readCertData, sizeof(certData), | |
"expected cert data", certData, sizeof(certData), AX_COLON_32); | |
} | |
// | |
// note : last certificate depends on max certifcate which are allowed at Gp table | |
PRINTF("Verify last Certificate created in table still exists\r\n"); | |
{ | |
U8 readCertData[90]; | |
HLSE_ATTRIBUTE attrL; | |
index = nCertsCreated - 1; | |
memset(readCertData, 0x00, sizeof(readCertData)); | |
attrL.type = HLSE_ATTR_OBJECT_VALUE; | |
attrL.value = readCertData; | |
attrL.valueLen = sizeof(readCertData); | |
hlseRc = HLSE_GetObjectAttribute(lastCertHandle , &attrL); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
// set the reference data that in lasr cert that is expected not to change | |
memset(certData, (0xAA + index), sizeof(certData)); | |
result &= AX_COMPARE_BYTE_ARRAY("read data", readCertData, sizeof(certData), | |
"expected cert data", certData, sizeof(certData), AX_COLON_32); | |
} | |
// enumerate objects - we should have certHandlesNum objects | |
memset(certHandles, 0, sizeof(certHandles)); | |
PRINTF("\r\nHLSE_EnumerateObjects()...\r\n"); | |
certHandlesNum = sizeof(certHandles) / sizeof(HLSE_OBJECT_HANDLE); | |
hlseRc = HLSE_EnumerateObjects(HLSE_CERTIFICATE, certHandles, &certHandlesNum); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
result &= AX_CHECK_U16(certHandlesNum, nCertsCreated, "err"); | |
// delete all certs | |
for (indexCert = 0; indexCert < certHandlesNum; indexCert++) | |
{ | |
index = indexCert; | |
PRINTF("\r\nHLSE_EraseObject() - index 0x%02lx", index); | |
hlseRc = HLSE_EraseObject(certHandles[index]); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
} | |
PRINTF("\r\n-----------\r\nEnd exCertUsageEnlarge(), result = %s\r\n------------\r\n", ((result == 1) ? "OK" : "FAILED")); | |
return result; | |
} | |
/** | |
* Demonstrate usage of certificate objects: | |
* | |
* this example Verifies correct operation in case when length of certificate object was Unknown at the | |
* time the mapping table was created | |
* | |
* Detailed explanation : | |
* | |
* - The abstraction for various objects that reside in the GP Storage area is achieved by maintaining a | |
* lookup table (mapping) at the end of the GP Storage area to holds information about the logical objects that exist | |
* in the GP Storage | |
* | |
* - The gp table is rewritten(whole) each time an object is inserted or deleted | |
* - Each object is aligned to occupy at least the amount of memory on the boundary of the GP storage, that is 32 bytes. | |
* E.g. an object of 17 bytes will occupy 32 bytes | |
* | |
* In cases where the length of an object is not known at the time the table entry is set, the MSBit (0x8000) will be set | |
* in the length as an indicator for the host library to know that the data is in TLV format and that the actual length | |
* can be obtained by reading the first bytes of the object's data. | |
* | |
* Example pre setup required: | |
* | |
* - We want to have a single certificate at offset 0 in the GP storage | |
* - we want to have a mapping table with one entry in which the length of the certificate object is unknown. | |
* | |
* Simulate the following scenario to verify it works correctly: | |
* | |
* - Create A Mapping table with one entry with length unknown as follows: | |
* | |
* \verbatim | |
* | |
* Notes: | |
* X+1 is the address of the last byte of the GP Storage. | |
* N is the object number from 1 to N | |
* | |
* Address Value | |
* ------- ---------------------- | |
* X-1*6+0 First Object Class - 1 byte value : 0 | |
* X-1*6+1 First Object Index - 1 byte value : 0 | |
* X-1*6+2 First Object Length MSB - 1 byte value : 0x80 ( 0x8000 the MSBit Indicates Indirect length) | |
* X-1*6+3 First Object Length LSB - 1 byte value : 0x00 | |
* X-1*6+4 First Object Offset MSB - 1 byte value : 0 | |
* X-1*6+5 First Object Offset LSB - 1 byte value : 0 | |
* X Update Counter - 1 byte value : 1 | |
* X+1 Number of table entries - 1 byte value : 1 | |
* End of GP Storage | |
* | |
* \endverbatim | |
* | |
* - Write simulated certificate object at offset 0 of gp storage | |
* use TLV length encoded length: | |
* - 2 bytes 0x81, 0x.. | |
* - 3 bytes 0x82, 0x00, 0x.. | |
* | |
* - Read certificate data and verify correctness | |
* - index ok | |
* - value was correctly set | |
* - Update Certificate contents | |
* - Verify Certificate Updated correctly | |
* - Delete certificate | |
* - Verify deletion | |
* | |
* @param[in] initMode Visit the documentation of ::a71chInitModule for more information on this parameter | |
*/ | |
static U8 exCertUsageGpTableLengthUnknown(U8 initMode) | |
{ | |
U8 result = 1; | |
HLSE_RET_CODE hlseRc; | |
HLSE_OBJECT_HANDLE certHandles[5]; | |
U16 certHandlesNum = sizeof(certHandles) / sizeof(HLSE_OBJECT_HANDLE); | |
HLSE_OBJECT_INDEX index = 0; | |
HLSE_OBJECT_TYPE objType = HLSE_CERTIFICATE; | |
// Cert for this test is 50 bytes which occupies 2 chunks of 32 bytes on the GP Storage | |
U8 certData[50]; | |
HLSE_ATTRIBUTE attr[3]; | |
unsigned short templateSize = 3; | |
U8 data[50]; // to hold data to update certificate | |
memset(certHandles, 0x00, sizeof(certHandles)); | |
memset(certData, 0xAA, sizeof(certData)); | |
// Set header data - to be able to simulate length is unknown in the GP table at time Gp table was created - | |
// so it will be retrieved from this header | |
certData[0] = 0x30; // tag | |
certData[1] = 0x81; // length in next byte | |
certData[2] = 0x2F; // length is 47 bytes | |
PRINTF("\r\n-----------\r\nStart exCertUsageGpTableLengthUnknown(%s)\r\n------------\r\n", getInitModeAsString(initMode)); | |
// Initialize the A71CH (Debug mode restrictions may apply) | |
result &= hlse_a71chInitModule(initMode); | |
assert(result); | |
// start with clean GP table to avoid cached data from previous test | |
hlseRc = Debug_ForceReadGPDataTable(); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
attr[0].type = HLSE_ATTR_OBJECT_TYPE; | |
attr[0].value = &objType; | |
attr[0].valueLen = sizeof(objType); | |
attr[1].type = HLSE_ATTR_OBJECT_INDEX; | |
attr[1].value = &index; | |
attr[1].valueLen = sizeof(index); | |
attr[2].type = HLSE_ATTR_OBJECT_VALUE; | |
attr[2].value = certData; | |
attr[2].valueLen = sizeof(certData); | |
// Create certificate object index = 0 | |
PRINTF("\r\nHLSE_CreateObject() - Create certificate object, use 2 bytes encoded length in header...\r\n------------\r\n"); | |
hlseRc = HLSE_CreateObject(attr, templateSize, &certHandles[0]); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
// We now have a mapping table, starting at the beginning of the last chunk of the GP storage (order is backward) which consists of 32 bytes composed of: | |
// | |
// Start of last chunk of GP storage : | |
// Address Offset Value | |
// ------- ------------------ ---------------------- | |
// ... (note invalid entries are filled with 0xff) | |
// ... ... ... | |
// 4088 [0x00000018] 0x09 class certificate 1 | |
// 4089 [0x00000019] 0x00 index | |
// 4090 [0x0000001a] 0x00 Length MSB Byte | |
// 4091 [0x0000001b] 0x32 Length LSB Byte means size is 50 bytes = sizeof(certData) | |
// 4092 [0x0000001c] 0x00 Offset MSB Byte offset 0 | |
// 4093 [0x0000001d] 0x00 Offset LSB Byte | |
// 4094 [0x0000001e] 0x01 update counter | |
// 4095 [0x0000001f] 0x01 number of entries (Note it is in the last byte of the GP storage) | |
// End of Gp Storage | |
// We'll now overrun this map to contain 0x8000 in the length to indicate indirect length | |
PRINTF("\r\noverwrite gp table map to have indirect length indication...\r\n"); | |
{ | |
U16 gpSize; | |
//HLSE_RET_CODE lReturn = HLSE_SW_OK; | |
U8 dataL[32]; | |
U8 dataSize = sizeof(dataL); | |
hlseRc = hlse_GetGPDataSize(&gpSize); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
// Read the entire table - consists of one chunk 5 entries | |
hlseRc = A71_GetGpData(gpSize - 32, dataL, 32); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
// Now overwrite Gp Table with indirect length | |
dataL[dataSize - 2 - 1*6 + 2] = 0x80; | |
dataL[dataSize - 2 - 1*6 + 3] = 0x00; | |
// dataL[2] = 0x80; | |
// dataL[3] = 0x00; | |
#if 0 // just for debug !! | |
// data format to check | |
U8 altData[32] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // invalid entry | |
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // invalid entry | |
0x09, 0x02, 0x80, 0x00, 0x06, 0x00, // third certificate | |
0x09, 0x01, 0x80, 0x00, 0x02, 0x00, // second certificate | |
0x09, 0x00, 0x80, 0x00, 0x00, 0x00, // first certificate | |
0x00, 0x03 // update counter + num of entries | |
}; | |
memcpy(dataL, altData, 32); | |
#endif | |
hlseRc = A71_SetGpData(gpSize - 32, dataL, 32); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
hlseRc = Debug_ForceReadGPDataTable(); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
} | |
// enumerate objects - we should have one certificate by now with index 0 | |
PRINTF("\r\nHLSE_EnumerateObjects()...\r\n"); | |
certHandlesNum = sizeof(certHandles) / sizeof(HLSE_OBJECT_HANDLE); | |
hlseRc = HLSE_EnumerateObjects(HLSE_CERTIFICATE, certHandles, &certHandlesNum); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
result &= AX_CHECK_U16(certHandlesNum, 1, "err"); | |
// make sure our certificate is the one we previously created | |
// Get the attributes of the single certificate we have | |
PRINTF("\r\nHLSE_GetObjectAttribute()...\r\n"); | |
{ | |
U32 certIndex = 0xFFFFFFFF; | |
HLSE_ATTRIBUTE attrL; | |
attrL.type = HLSE_ATTR_OBJECT_INDEX; | |
attrL.value = &certIndex; | |
attrL.valueLen = sizeof(certIndex); | |
hlseRc = HLSE_GetObjectAttribute(certHandles[certHandlesNum - 1], &attrL); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
PRINTF("\tcert index = 0x%lx\r\n", certIndex); | |
result &= AX_CHECK_U16((U16)certIndex, 0x00, "err"); | |
} | |
PRINTF("Verify Certificate contents...\r\n"); | |
{ | |
U8 readCertData[50]; | |
HLSE_ATTRIBUTE attrL; | |
attrL.type = HLSE_ATTR_OBJECT_VALUE; | |
attrL.value = readCertData; | |
attrL.valueLen = sizeof(readCertData); | |
hlseRc = HLSE_GetObjectAttribute(certHandles[certHandlesNum - 1], &attrL); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
result &= AX_COMPARE_BYTE_ARRAY("certOnA71CH", readCertData, sizeof(certData), | |
"expected cert data", certData, sizeof(certData), AX_COLON_32); | |
} | |
PRINTF("Update Certificate contents , use 3 bytes encoded length in header...\r\n"); | |
{ | |
HLSE_ATTRIBUTE attrL; | |
memset(data, 0xAB, sizeof(data)); | |
// Now use 3 bytes indirect length | |
// Set header data - to be able to simulate length is unknown in the GP table at time Gp table was created - | |
// so it will be retrieved from this header | |
data[0] = 0x06; // tag | |
data[1] = 0x82; // length in next 2 bytes | |
data[2] = 0x00; // MSB 0 | |
data[3] = 0x2E; // length is 46 bytes | |
attrL.type = HLSE_ATTR_OBJECT_VALUE; | |
attrL.value = data; | |
attrL.valueLen = sizeof(data); | |
hlseRc = HLSE_SetObjectAttribute(certHandles[certHandlesNum - 1], &attrL); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
} | |
// We'll now overrun this map to contain 0x8000 in the length to indicate indirect length | |
{ | |
U16 gpSize; | |
//HLSE_RET_CODE lReturn = HLSE_SW_OK; | |
U8 dataL[32]; | |
hlseRc = hlse_GetGPDataSize(&gpSize); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
// Read the entire table - consists of one chunk 5 entries | |
hlseRc = A71_GetGpData(gpSize - 32, dataL, 32); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
// Now overrite with indirect length | |
dataL[2] = 0x80; | |
dataL[3] = 0x00; | |
hlseRc = A71_SetGpData(gpSize - 32, dataL, 32); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
hlseRc = Debug_ForceReadGPDataTable(); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
} | |
PRINTF("Verify Certificate Updated correctly...\r\n"); | |
{ | |
U8 readCertData[50]; | |
HLSE_ATTRIBUTE attrL; | |
memset(readCertData, 0x00, sizeof(readCertData)); | |
attrL.type = HLSE_ATTR_OBJECT_VALUE; | |
attrL.value = readCertData; | |
attrL.valueLen = sizeof(readCertData); | |
hlseRc = HLSE_GetObjectAttribute(certHandles[certHandlesNum - 1], &attrL); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
result &= AX_COMPARE_BYTE_ARRAY("read data", readCertData, sizeof(certData), | |
"expected cert data", data, sizeof(data), AX_COLON_32); | |
} | |
// Delete the certificate | |
PRINTF("\r\nHLSE_EraseObject()...\r\n"); | |
hlseRc = HLSE_EraseObject(certHandles[certHandlesNum - 1]); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
// Verify it was actually deleted | |
// enumerate objects - we should have no certificates by now | |
PRINTF("\r\nVerify object was erased...\r\n"); | |
certHandlesNum = sizeof(certHandles) / sizeof(HLSE_OBJECT_HANDLE); | |
hlseRc = HLSE_EnumerateObjects(HLSE_CERTIFICATE, certHandles, &certHandlesNum); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
result &= AX_CHECK_U16(certHandlesNum, 0, "err"); | |
PRINTF("\r\n-----------\r\nEnd exCertUsageGpTableLengthUnknown(), result = %s\r\n------------\r\n", ((result == 1) ? "OK" : "FAILED")); | |
return result; | |
} | |
/** | |
* Demonstrate | |
* | |
* - Creating 3 read only certificates | |
* - Verify erasure of existing cert is disallowed since it's Read Only | |
* - Verify recreation of existing cert is disallowed since it's Read Only | |
* - Certificate Enumeration | |
* - Get Certificate value | |
* - Verify unable to update certificate value since it's Read Only | |
* | |
* @param[in] initMode Visit the documentation of ::a71chInitModule for more information on this parameter | |
*/ | |
static U8 exCertUsageReadOnly(U8 initMode) | |
{ | |
U8 result = 1; | |
HLSE_RET_CODE hlseRc; | |
HLSE_OBJECT_HANDLE objHandle, objHandle2, objHandle3, objHandle4; | |
HLSE_OBJECT_INDEX index = 1; | |
HLSE_OBJECT_TYPE objType = HLSE_CERTIFICATE; | |
U8 readOnly = 1; | |
U8 certData[50]; | |
HLSE_ATTRIBUTE attr[4]; | |
unsigned short templateSize = 4; | |
U8 largeCertData[300]; | |
memset(certData, 0xAA, sizeof(certData)); | |
memset(largeCertData, 0xAC, sizeof(largeCertData)); | |
PRINTF("\r\n-----------\r\nStart exCertUsageReadOnly(%s)\r\n------------\r\n", getInitModeAsString(initMode)); | |
// Initialize the A71CH (Debug mode restrictions may apply) | |
result &= hlse_a71chInitModule(initMode); | |
assert(result); | |
// start with clean GP table to avoid cached data from previous test | |
hlseRc = Debug_ForceReadGPDataTable(); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
attr[0].type = HLSE_ATTR_OBJECT_TYPE; | |
attr[0].value = &objType; | |
attr[0].valueLen = sizeof(objType); | |
attr[1].type = HLSE_ATTR_OBJECT_INDEX; | |
attr[1].value = &index; | |
attr[1].valueLen = sizeof(index); | |
attr[2].type = HLSE_ATTR_OBJECT_VALUE; | |
attr[2].value = certData; | |
attr[2].valueLen = sizeof(certData); | |
attr[3].type = HLSE_ATTR_READ_ONLY; // meaning further modification of the GP storage area is disallowed | |
attr[3].value = &readOnly; | |
attr[3].valueLen = sizeof(readOnly); | |
// Create certificate objects index 1 to 3 - with HLSE_ATTR_READ_ONLY | |
hlseRc = HLSE_CreateObject(attr, templateSize, &objHandle); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
index = 2; | |
hlseRc = HLSE_CreateObject(attr, templateSize, &objHandle2); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
// Create large certificate - READ ONLY | |
index = 3; | |
attr[2].value = largeCertData; | |
attr[2].valueLen = sizeof(largeCertData); | |
hlseRc = HLSE_CreateObject(attr, templateSize, &objHandle3); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
// Create large certificate | |
index = 4; | |
hlseRc = HLSE_CreateObject(attr, 3 /* without READ ONLY */, &objHandle4); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
// Try to erase certificate object at index 2 - should be disallowed as we created it with HLSE_ATTR_READ_ONLY attribute | |
hlseRc = HLSE_EraseObject(objHandle2); | |
result &= AX_CHECK_SW(hlseRc, HLSE_ERR_API_ERROR, "err"); | |
// Certificate Enumeration | |
result &= exCertEnumerate(); | |
// Get certificate Attributes | |
result &= exCertGetAttr(); | |
// Set Certificate Attributes | |
result &= exCertSetAttr(); | |
// Certificate Enumeration | |
result &= exCertEnumerate(); | |
PRINTF("\r\n-----------\r\nEnd exCertUsageReadOnly(), result = %s\r\n------------\r\n", ((result == 1) ? "OK" : "FAILED")); | |
return result; | |
} | |
/** | |
* Internal function , called from exCertUsageReadOnly() | |
* | |
* Demonstrate | |
* - using HLSE_EnumerateObjects() for certificate enumeration | |
* - using HLSE_GetObjectAttribute() to get certificate tag | |
* | |
*/ | |
static U8 exCertEnumerate() | |
{ | |
HLSE_OBJECT_HANDLE handles[10] = { 0 }; | |
U16 handleNum = 10; | |
HLSE_RET_CODE hlseRc; | |
U16 i; | |
U8 result = 1; | |
PRINTF("\r\n-----------\r\nStart exCertEnumerate()\r\n------------\r\n"); | |
hlseRc = HLSE_EnumerateObjects(HLSE_CERTIFICATE, handles, &handleNum); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
for (i = 0 ; i < handleNum ; ++i) { | |
U32 tag = 0; | |
HLSE_ATTRIBUTE attr; | |
attr.type = HLSE_ATTR_OBJECT_INDEX; | |
attr.value = &tag; | |
attr.valueLen = sizeof(tag); | |
hlseRc = HLSE_GetObjectAttribute(handles[i], &attr); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
PRINTF("exCertEnumerate - tag = 0x%lx\r\n", tag); | |
} | |
PRINTF("\r\n-----------\r\nEnd exCertEnumerate(), result = %s\r\n------------\r\n", ((result == 1) ? "OK" : "FAILED")); | |
return result; | |
} | |
/** | |
* Internal function , called from exCertUsageReadOnly() | |
* | |
* Demonstrate | |
* - using HLSE_EnumerateObjects() for certificate enumeration | |
* - using HLSE_GetObjectAttribute() with HLSE_ATTR_OBJECT_VALUE to get object's value | |
* | |
*/ | |
static U8 exCertGetAttr() | |
{ | |
U8 result = 1; | |
HLSE_RET_CODE hlseRc; | |
HLSE_OBJECT_HANDLE handles[10] = { 0 }; | |
U16 handleNum = 10; | |
U16 i; | |
PRINTF("\r\n-----------\r\nStart exCertGetAttr()\r\n------------\r\n"); | |
hlseRc = HLSE_EnumerateObjects(HLSE_CERTIFICATE, handles, &handleNum); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
for (i = 0; i < handleNum; ++i) { | |
U8 data[300]; | |
HLSE_ATTRIBUTE attr; | |
attr.type = HLSE_ATTR_OBJECT_VALUE; | |
attr.value = data; | |
attr.valueLen = sizeof(data); | |
hlseRc = HLSE_GetObjectAttribute(handles[i], &attr); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
} | |
PRINTF("\r\n-----------\r\nEnd exCertGetAttr(), result = %s\r\n------------\r\n", ((result == 1) ? "OK" : "FAILED")); | |
return result; | |
} | |
/** | |
* Demonstrate | |
* - using HLSE_EnumerateObjects() for certificate enumeration | |
* - shows using HLSE_SetObjectAttribute() to change an object's value fails when credential is frozen | |
* | |
*/ | |
static U8 exCertSetAttr() | |
{ | |
U8 result = 1; | |
HLSE_RET_CODE hlseRc; | |
HLSE_OBJECT_HANDLE handles[10]; | |
U16 handleNum = 10; | |
U8 certData[40]; | |
U8 largeCertData[300]; | |
U16 i ; | |
memset(certData, 0xBB, sizeof(certData)); | |
memset(largeCertData, 0xBD, sizeof(largeCertData)); | |
PRINTF("\r\n-----------\r\nStart exCertSetAttr()\r\n------------\r\n"); | |
hlseRc = HLSE_EnumerateObjects(HLSE_CERTIFICATE, handles, &handleNum); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
for (i = 0; i < handleNum-2; ++i) { | |
HLSE_ATTRIBUTE attr; | |
attr.type = HLSE_ATTR_OBJECT_VALUE; | |
attr.value = certData; | |
attr.valueLen = sizeof(certData); | |
hlseRc = HLSE_SetObjectAttribute(handles[i], &attr); | |
result &= AX_CHECK_SW(hlseRc, SW_COMMAND_NOT_ALLOWED, "Expected to fail, frozen credential cannot be changed"); | |
} | |
// Try to update large cert data which is locked in GP storage | |
i = handleNum - 2; | |
{ | |
HLSE_ATTRIBUTE attr; | |
attr.type = HLSE_ATTR_OBJECT_VALUE; | |
attr.value = largeCertData; | |
attr.valueLen = sizeof(largeCertData); | |
hlseRc = HLSE_SetObjectAttribute(handles[i], &attr); | |
result &= AX_CHECK_SW(hlseRc, SW_COMMAND_NOT_ALLOWED, "Expected to fail, frozen credential cannot be changed"); | |
// Last one is not frozen and should allow update | |
i = handleNum - 1; | |
hlseRc = HLSE_SetObjectAttribute(handles[i], &attr); | |
result &= AX_CHECK_SW(hlseRc, HLSE_SW_OK, "err"); | |
} | |
PRINTF("\r\n-----------\r\nEnd exCertSetAttr(), result = %s\r\n------------\r\n", ((result == 1) ? "OK" : "FAILED")); | |
return result; | |
} | |
/** | |
* Internal utility to patch the TLV header of a data buffer so it contains the | |
* certificate header TLV correct | |
* | |
* A certificate header consists of the 0x30 tag followes by a length which could be encoded as | |
* 1) one byte: the length byte in case of length <= 127 | |
* 2) 2 bytes : 0x81 followed byte the length byte in case 127 < length <= 255 | |
* 3) 3 bytes : 0x82 followed by 2 bytes length otherwise | |
*/ | |
static HLSE_RET_CODE patchCertificateInitialTL(U8 *clientCertDer, U16 clientCertDerLen) | |
{ | |
if (clientCertDerLen < 3) | |
{ | |
// This is too short for a certificate | |
return ERR_GP_NO_CERT; | |
} | |
else if (clientCertDerLen <= LEN_SHORT_FORM_MAX) | |
{ | |
clientCertDer[0] = 0x30; | |
clientCertDer[1] = (clientCertDerLen-2) & 0x00FF; | |
} | |
else if (clientCertDerLen <= LEN_LONG_FORM_ONE_BYTE_MAX) | |
{ | |
clientCertDer[0] = 0x30; | |
clientCertDer[1] = 0x81; | |
clientCertDer[2] = (clientCertDerLen-3) & 0x00FF; | |
} | |
else | |
{ | |
clientCertDer[0] = 0x30; | |
clientCertDer[1] = 0x82; | |
clientCertDer[2] = ((clientCertDerLen-4) >> 8) & 0x00FF; | |
clientCertDer[3] = (clientCertDerLen-4) & 0x00FF; | |
} | |
return HLSE_SW_OK; | |
} | |
/** | |
* Internal - called from exMixedCertsAndDataObjUsage | |
* Get an object's value and length based on based on object handle provided | |
* | |
* @param[in] handle object handle | |
* @param[out] data buffer to store object's value retrieved | |
* @param[in,out] len in - length of data buffer, out - actual object's length | |
*/ | |
static HLSE_RET_CODE getObject(HLSE_OBJECT_HANDLE handle, U8 *data, U16 *len) | |
{ | |
HLSE_RET_CODE hlseRc; | |
HLSE_ATTRIBUTE attr; | |
HLSE_OBJECT_TYPE type; | |
U16 offset; | |
// We are looking for the object on index i in handles array | |
type = HLSE_GET_OBJECT_TYPE(handle); | |
if (type == HLSE_CERTIFICATE) { | |
PRINTF("get Certificate Object, handle=0x%lX\n", handle); | |
} | |
else { | |
PRINTF("get Data Object, handle=0x%lX\n", handle); | |
} | |
// Read | |
attr.type = HLSE_ATTR_OBJECT_VALUE; | |
attr.value = data; | |
attr.valueLen = *len; | |
hlseRc = HLSE_GetObjectAttribute(handle, &attr); | |
if (hlseRc != HLSE_SW_OK) { | |
return hlseRc; | |
} | |
*len = attr.valueLen; | |
// obtain object's GP offset | |
{ | |
HLSE_ATTRIBUTE attrL; | |
attrL.type = HLSE_ATTR_OBJECT_OFFSET; | |
attrL.value = &offset; | |
attrL.valueLen = sizeof(offset); | |
hlseRc = HLSE_GetObjectAttribute(handle, &attrL); | |
if (hlseRc != HLSE_SW_OK) { | |
return hlseRc; | |
} | |
} | |
PRINTF("Object retrieved: Offset=%d, Size=%d\n", offset, *len); | |
return HLSE_SW_OK; | |
} | |
/** | |
* Internal - called from exMixedCertsAndDataObjUsage | |
* Set a Certificate or Data object's value based on on object handle provided | |
* | |
* @param[in] handle object handle | |
* @param[in] data buffer of data to set obj value | |
* @param[in] len in - length of data buffer | |
*/ | |
static HLSE_RET_CODE setObject(HLSE_OBJECT_HANDLE handle, U8 *data, U16 len) | |
{ | |
HLSE_RET_CODE hlseRc; | |
HLSE_OBJECT_TYPE type; | |
// We are looking for the object on index i in handles array | |
type = HLSE_GET_OBJECT_TYPE(handle); | |
if (type == HLSE_CERTIFICATE) { | |
PRINTF("Set Certificate Object, handle=0x%lX\n", handle); | |
} | |
else { | |
PRINTF("Set Data Object, handle=0x%lX\n", handle); | |
} | |
// Update | |
{ | |
HLSE_ATTRIBUTE attrL; | |
attrL.type = HLSE_ATTR_OBJECT_VALUE; | |
attrL.value = data; | |
attrL.valueLen = len; | |
hlseRc = HLSE_SetObjectAttribute(handle, &attrL); | |
if (hlseRc != HLSE_SW_OK) { | |
return hlseRc; | |
} | |
} | |
return HLSE_SW_OK; | |
} |