/**
* MIT License
*
* Copyright (c) 2018 Infineon Technologies AG
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*
* \file
*
* \brief This file implements
*
* \addtogroup grOptigaUtil
* @{
*/
#include "optiga/optiga_util.h"
#include "optiga/comms/optiga_comms.h"
#include "optiga/cmd/CommandLib.h"
#include "optiga/pal/pal_os_timer.h"
/**
* OPTIGA util module return values
*/
///OPTIGA util API execution is successful
#define OPTIGA_UTIL_SUCCESS (0x0000)
///OPTIGA util module in busy state
#define OPTIGA_UTIL_BUSY (0x0001)
///OPTIGA util API failed
#define OPTIGA_UTIL_ERROR (0x0302)
///OPTIGA util API called with invalid inputs
#define OPTIGA_UTIL_ERROR_INVALID_INPUT (0x0303)
///OPTIGA util API called with insufficient memory buffer
#define OPTIGA_UTIL_ERROR_MEMORY_INSUFFICIENT (0x0304)
///OPTIGA util API called when, a request of same instance is already in service
#define OPTIGA_UTIL_ERROR_INSTANCE_IN_USE (0x0305)
///Requested operation completed without any error
#define INT_LIB_OK 0x75AB1C02
///Null parameter(s)
#define INT_LIB_NULL_PARAM 0x80002001
///Invalid data in response
#define INT_LIB_INVALID_RESPONSE (INT_LIB_NULL_PARAM + 1)
///Invalid access condition
#define INT_LIB_INVALID_AC (INT_LIB_NULL_PARAM + 2)
///Length of input is zero
#define INT_LIB_ZEROLEN_ERROR (INT_LIB_NULL_PARAM + 3)
///Invalid or unsupported parameter(s)
#define INT_LIB_INVALID_PARAM (INT_LIB_NULL_PARAM + 4)
///Invalid Length
#define INT_LIB_INVALID_LENGTH (INT_LIB_NULL_PARAM + 5)
///Malloc Failures
#define INT_LIB_MALLOC_FAILURE (INT_LIB_NULL_PARAM + 6)
///General error
#define INT_LIB_ERROR 0xFE5A5502
///Length of metadata
#define LENGTH_METADATA 0x1C
///Length of certificate
#define LENGTH_CERTIFICATE 1728
///Length of R and S vector
#define LENGTH_RS_VECTOR 0x40
///Length of maximum additional bytes to encode sign in DER
#define MAXLENGTH_SIGN_ENCODE 0x08
///Length of Signature
#define LENGTH_ASN1_SIGNATURE (LENGTH_RS_VECTOR + MAXLENGTH_SIGN_ENCODE)
///size of public key for NIST-P256
#define LENGTH_PUB_KEY_NISTP256 0x41
///Position of data field in metadata
#define METADATA_MAX_LEN 0x001C
///Offset of Length in the metadata
#define OFFSET_TLV_LENGTH 0x01
///Size of TLV Format Header
#define TLV_HEADER_SIZE 0x02
///Length of metadata header
#define METADATA_HEADER_SIZE TLV_HEADER_SIZE
///Value for parsig failure
#define PARSE_FAILURE 0xFF
///TLV position for Length
#define POS_LEN 0x01
///TLV position for Value
#define POS_VAL 0x02
///Already Found
#define VALUE_TAG_FOUND 0x9B
///Length of R and S vector
#define VALUE_TAG_NOTFOUND 0x31
///ASN Tag for sequence
#define ASN_TAG_SEQUENCE 0x30
///ASN Tag for integer
#define ASN_TAG_INTEGER 0x02
///msb bit mask
#define MASK_MSB 0x80
///TLS Identity Tag
#define TLS_TAG 0xC0
/**
* \brief Enumeration to object ids.
*/
typedef enum eObjectId_d
{
///Life Cycle State Global
eLCSG = 0xE0C0,
///Life Cycle State Application
eLCSA = 0xF1C0
}eObjectId_d;
/**
* \brief Structure to specify general purpose data object parameters for read
*/
typedef struct sACVector_d
{
///OID of data object
uint8_t bLcsA;
uint8_t bLcsG;
uint8_t bLcsO;
sbBlob_d *psMetaData;
}sACVector_d;
/**
* \brief Operators available in simple and complex Access Conditions
*/
typedef enum eOperator_d {
/// Equal
eOP_EQUAL = 0xFA,
/// Greater than
eOP_GREATER_THAN = 0xFB,
/// Less than
eOP_LESS_THAN = 0xFC,
/// AND
eOP_AND = 0xFD,
/// OR
eOP_OR = 0xFE
} eOperator_d;
/**
* \brief Meta data tags
*/
typedef enum eMetaDataTag_d
{
/// Object Life Cycle
eLCSO = 0xC0,
/// Change AC
eCHANGE_AC = 0xD0,
/// Read AC
eREAD_AC = 0xD1
} eMetaDataTag_d;
/**
* \brief IDs associated with the metadata access condition (simple and complex)
*/
typedef enum eAccessConditionID_d
{
/// Always
eACID_ALW = 0x00,
/// Global life cycle status
eACID_LCSG = 0x70,
/// Application specific life cycle status
eACID_LCSA = 0xE0,
/// Data object specific life cycle status
eACID_LCSO = 0xE1,
/// Never
eACID_NEV = 0xFF
} eAccessConditionID_d;
volatile static host_lib_status_t optiga_comms_status;
#ifdef MODULE_ENABLE_READ_WRITE
/**
*
* Implementation to get the metadata tag position.
* Returns error if metadata is not correct
* (if duplication of tag, metadata length / Tag length more than max length of metadata).
*
* PpbPos contains the actual position of the tag if found.
* PpbPos contains 0xFF if tag not found.This is considering that metatdata length is 28 bytes.
* The return value in this case is #INT_LIB_OK.
*
* \param[in] Pprgbmetadata Pointer to the buffer that contains metadata
* \param[in] PbTag Tag type.
* \param[in] PpbPos Pointer to tag position in metadata
*
* \retval #INT_LIB_OK Successful execution
* \retval #INT_LIB_ERROR Failure in execution
*
*/
static int32_t __optiga_util_get_tag_position (const uint8_t* Pprgbmetadata, uint8_t PbTag, puint8_t PpbPos)
{
int32_t i4Status = (int32_t)INT_LIB_ERROR;
uint8_t bMetadataSize, bAcLen;
uint8_t bTempPos, bAlreadyFound=VALUE_TAG_NOTFOUND;
do
{
if (NULL == Pprgbmetadata || NULL == PpbPos)
{
break;
}
bMetadataSize = Pprgbmetadata[OFFSET_TLV_LENGTH];
*PpbPos = 0xFF;
if (METADATA_MAX_LEN < (bMetadataSize + METADATA_HEADER_SIZE))
{
//Metadata Corrupted [Length field in Metadata is more than METADATA_MAX_SIZE]
break;
}
bTempPos = METADATA_HEADER_SIZE;
for(;;)
{
if (Pprgbmetadata[bTempPos] == PbTag)
{
if (VALUE_TAG_FOUND == bAlreadyFound)
{
i4Status = (int32_t)INT_LIB_ERROR;
break;
}
i4Status = INT_LIB_OK;
*PpbPos = bTempPos;
bAlreadyFound = VALUE_TAG_FOUND;
}
if(0xFF == Pprgbmetadata[bTempPos])
{
//Length field in Metadata is not correct
break;
}
bAcLen = Pprgbmetadata[bTempPos+1];
//Is metadata Corrupted?
if (METADATA_MAX_LEN <= (bAcLen+bTempPos+1))
{
//Metadata Corrupted
break;
}
bTempPos += (bAcLen+2);
if(bMetadataSize <= (bTempPos-METADATA_HEADER_SIZE))
{
i4Status = INT_LIB_OK;
break;
}
}
} while(0);
return i4Status;
}
/**
*
* Implementation to verify expressions related to LCSA, LCSG, LCSO.
*
* \param[in] PpsACVal Pointer to the access condition vector
* \param[in] PprgbAC Pointer to the AC expression
* \param[in,out] PpwVerifyOver Pointer to verification status
*
* \retval #INT_LIB_OK Successful execution
* \retval #INT_LIB_ERROR Failure in execution
*
*/
static int32_t __optiga_util_verify_lcsa_lcsg_lcso(const sACVector_d* PpsACVal, const uint8_t* PprgbAC,puint16_t PpwVerifyOver)
{
int32_t i4Status = (int32_t)INT_LIB_ERROR;
uint8_t bVal, bLcs = 0x00;
eOperator_d eOp ;
// Life cycle state of object
#define LCS_O_VAL (PpsACVal->bLcsO)
// Life cycle state of application
#define LCS_A_VAL (PpsACVal->bLcsA)
// Life cycle state of Global
#define LCS_G_VAL (PpsACVal->bLcsG)
do
{
if((NULL == PpwVerifyOver)
|| (NULL == PpsACVal) || (NULL == PprgbAC))
{
break;
}
bLcs = LCS_A_VAL;
if ((uint8_t)eACID_LCSG == *PprgbAC)
{
bLcs = LCS_G_VAL;
}
else if((uint8_t)eACID_LCSO == *PprgbAC)
{
bLcs = LCS_O_VAL;
}
eOp = (eOperator_d)(*(PprgbAC+1));
bVal = *(PprgbAC+2);
if(eOp == eOP_GREATER_THAN)
{
if(bLcs > bVal)
{
i4Status = INT_LIB_OK;
}
}
else if(eOp == eOP_LESS_THAN)
{
if(bLcs < bVal)
{
i4Status = INT_LIB_OK;
}
}
else if(eOp == eOP_EQUAL)
{
if(bLcs == bVal)
{
i4Status = INT_LIB_OK;
}
}
else
{
i4Status = (int32_t)INT_LIB_ERROR;
*PpwVerifyOver = TRUE;
break;
}
} while(0);
return i4Status;
#undef LCS_O_VAL
#undef LCS_A_VAL
#undef LCS_G_VAL
}
/**
*
* Implementation to validate the access conditions.
*
* \param[in] PpsACVal Pointer to the buffer that contains metadata
*
* \retval #INT_LIB_OK Successful execution
* \retval #INT_LIB_ERROR Failure in execution
*
*/
static int32_t __optiga_util_check_ac(const sACVector_d *PpsACVal)
{
int32_t i4Status = (int32_t)INT_LIB_ERROR;
int32_t i4StatusCurr = (int32_t)INT_LIB_ERROR;
int32_t i4StatusPrev = (int32_t)INT_LIB_OK;
uint16_t wIndex = 0, wLen, wIDCount = 0;
uint16_t wVerificationOver = 0;
uint8_t bComplexAcOP = 0x00;
puint8_t prgbAccessCode;
// Remaining bytes of the access condition
#define REMAINING_BYTES (wLen - wIndex)
do
{
if((NULL == PpsACVal) || (NULL == PpsACVal->psMetaData)
|| (NULL == PpsACVal->psMetaData->prgbStream))
{
break;
}
wLen = PpsACVal->psMetaData->wLen;
prgbAccessCode = PpsACVal->psMetaData->prgbStream;
while(wIndex < wLen)
{
switch((eAccessConditionID_d)*(prgbAccessCode+wIndex))
{
case eACID_ALW:
case eACID_NEV:
if((REMAINING_BYTES > 1) || (wIDCount > 0))
{
wVerificationOver = TRUE;
break;
}
i4StatusCurr = INT_LIB_OK;
if((uint8_t)eACID_NEV == *(prgbAccessCode+wIndex))
{
i4StatusCurr = (int32_t)INT_LIB_ERROR;
}
wIndex++;
wIDCount++;
break;
case eACID_LCSO:
case eACID_LCSA:
case eACID_LCSG:
//including access id
if(REMAINING_BYTES < 3)
{
//because of invalid access coding
wVerificationOver = TRUE;
break;
}
i4StatusCurr = __optiga_util_verify_lcsa_lcsg_lcso(PpsACVal, prgbAccessCode+wIndex, &wVerificationOver);
if(TRUE == wVerificationOver)
{
//because of invalid access coding
break;
}
wIndex+=3;
wIDCount++;
break;
default:
//because of invalid access coding
i4StatusPrev = (int32_t)INT_LIB_ERROR;
i4StatusCurr = (int32_t)INT_LIB_ERROR;
wVerificationOver = TRUE;
break;
}//switch
if(wVerificationOver)
{
break;
}
if(bComplexAcOP == (uint8_t)eOP_AND)
{
if(i4StatusCurr != i4StatusPrev)
{
i4StatusCurr = (int32_t)INT_LIB_ERROR;
}
}
if(wIndex == wLen)
{
break;
}
// for operator
if(REMAINING_BYTES < 3)
{
i4StatusPrev = (int32_t)INT_LIB_ERROR;
i4StatusCurr = (int32_t)INT_LIB_ERROR;
//wVerificationOver = TRUE;
break;
}
bComplexAcOP = *(prgbAccessCode+wIndex);
switch(bComplexAcOP)
{
case eOP_AND:
i4StatusPrev = i4StatusCurr;
i4StatusCurr = (int32_t)INT_LIB_ERROR;
break;
case eOP_OR:
i4StatusPrev = INT_LIB_OK;
if(i4StatusCurr == INT_LIB_OK)
{
//Note: further validation not required
//because the metadata itself is protected by checksum
wVerificationOver = TRUE;
}
break;
default:
//because of invalid access coding
i4StatusPrev = (int32_t)INT_LIB_ERROR;
i4StatusCurr = (int32_t)INT_LIB_ERROR;
wVerificationOver = TRUE;
break;
}//switch
if(wVerificationOver)
{
break;
}
wIndex++;
wIDCount++; //indication of complex AC
}//while
if((i4StatusPrev == INT_LIB_OK) &&
(i4StatusCurr == INT_LIB_OK))
{
i4Status = INT_LIB_OK;
}
}while(0);
return i4Status;
#undef REMAINING_BYTES
}
/**
*
* Reads either LcsA or LcsG based on request.
*
* \param[in] PeLcsType ObjectId of LcsA or LcsG
* \param[in,out] PpbValue Pointer for returning life cycle state.
*
* \retval #INT_LIB_OK Successful execution
* \retval #INT_LIB_ERROR Failure in execution
*
*/
static int32_t __optiga_util_read_lcsa_lcsg(eObjectId_d PeLcsType,uint8_t *PpbValue)
{
int32_t i4Status = (int32_t)INT_LIB_ERROR;
sGetData_d sGDVector;
sCmdResponse_d sResponse;
do
{
if(NULL == PpbValue)
{
i4Status = (int32_t)INT_LIB_NULL_PARAM;
break;
}
sGDVector.wOID = (uint16_t)PeLcsType;
sGDVector.wLength = 1;
sGDVector.wOffset = 0;
sGDVector.eDataOrMdata = eDATA;
sResponse.prgbBuffer = PpbValue;
sResponse.wBufferLength = 1;
sResponse.wRespLength = 0;
i4Status = CmdLib_GetDataObject(&sGDVector,&sResponse);
if(CMD_LIB_OK != i4Status)
{
break;
}
//check if the length is 1
if((0x01 != sResponse.wRespLength))
{
i4Status = (int32_t)INT_LIB_INVALID_RESPONSE;
*PpbValue = 0x00;
break;
}
i4Status = INT_LIB_OK;
}while(FALSE);
return i4Status;
}
/**
*
* Verifies the requested access condition in the metadata.
*
* \param[in] PeMetaDataTag Type of access condition
* \param[in] PpsACVal Pointer to metadata.
*
* \retval #INT_LIB_OK Successful execution
* \retval #INT_LIB_ERROR Failure in execution
*
*/
static int32_t __optiga_util_verify_ac(eMetaDataTag_d PeMetaDataTag, sACVector_d *PpsACVal)
{
int32_t i4Status = (int32_t)INT_LIB_ERROR;
uint8_t bTagLocation = 0;
do
{
if((NULL == PpsACVal)||(NULL == PpsACVal->psMetaData)||
(NULL == PpsACVal->psMetaData->prgbStream))
{
i4Status = (int32_t)INT_LIB_NULL_PARAM;
break;
}
//get tag position of lcsO and read lcsO.
//LCO may not be found for all object.It is not an error
i4Status = __optiga_util_get_tag_position(PpsACVal->psMetaData->prgbStream,(uint8_t)eLCSO,&bTagLocation);
if(INT_LIB_OK == i4Status && bTagLocation != PARSE_FAILURE)
{
//get the LcsO value from TLV
PpsACVal->bLcsO = (PpsACVal->psMetaData->prgbStream)[bTagLocation+2];
}
else
{
//LcsO not present
PpsACVal->bLcsO = 0x00;
}
//reset tag location
bTagLocation = 0;
//get tag position
i4Status = __optiga_util_get_tag_position(PpsACVal->psMetaData->prgbStream,(uint8_t)PeMetaDataTag,&bTagLocation);
if((INT_LIB_OK != i4Status) || (PARSE_FAILURE == bTagLocation))
{
i4Status = (int32_t)INT_LIB_ERROR;
break;
}
//check access condition
PpsACVal->psMetaData->wLen = *(PpsACVal->psMetaData->prgbStream + (bTagLocation+POS_LEN));
PpsACVal->psMetaData->prgbStream += (bTagLocation+POS_VAL);
i4Status = __optiga_util_check_ac(PpsACVal);
}while(FALSE);
return i4Status;
}
static void __optiga_util_comms_event_handler(void* upper_layer_ctx, host_lib_status_t event)
{
optiga_comms_status = event;
}
optiga_lib_status_t optiga_util_open_application(optiga_comms_t* p_comms)
{
optiga_lib_status_t status = OPTIGA_LIB_ERROR;
sOpenApp_d sOpenApp;
do {
// OPTIGA Initialisation phase
//Invoke optiga_comms_open to initialize the IFX I2C Protocol and security chip
optiga_comms_status = OPTIGA_COMMS_BUSY;
p_comms->upper_layer_handler = __optiga_util_comms_event_handler;
status = optiga_comms_open(p_comms);
if(E_COMMS_SUCCESS != status)
{
status = OPTIGA_LIB_ERROR;
break;
}
//Wait until IFX I2C initialization is complete
while(optiga_comms_status == OPTIGA_COMMS_BUSY)
{
pal_os_timer_delay_in_milliseconds(1);
}
if((OPTIGA_COMMS_SUCCESS != status) || (optiga_comms_status == OPTIGA_COMMS_ERROR))
{
status = OPTIGA_LIB_ERROR;
break;
}
//Set OPTIGA comms context in Command library before invoking the use case APIs or command library APIs
//This context will be used by command libary to communicate with OPTIGA using IFX I2C Protocol.
CmdLib_SetOptigaCommsContext(p_comms);
//Open the application in Security Chip
sOpenApp.eOpenType = eInit;
status = CmdLib_OpenApplication(&sOpenApp);
if(CMD_LIB_OK != status)
{
status = OPTIGA_LIB_ERROR;
}
// OPTIGA ready
status = OPTIGA_LIB_SUCCESS;
} while(FALSE);
return status;
}
optiga_lib_status_t optiga_util_read_data(uint16_t optiga_oid, uint16_t offset,
uint8_t * p_buffer, uint16_t* buffer_size)
{
//lint --e{818} suppress "PpsGPData is out parameter"
int32_t status = (int32_t)OPTIGA_LIB_ERROR;
sGetData_d cmd_params;
sCmdResponse_d cmd_resp;
do
{
if((NULL == p_buffer) || (NULL == buffer_size) || (0 == *buffer_size))
{
status = (int32_t)OPTIGA_LIB_ERROR;
break;
}
//If access condition satisfied, get the data
cmd_params.wOID = optiga_oid;
cmd_params.wLength = *buffer_size;
cmd_params.wOffset = offset;
cmd_params.eDataOrMdata = eDATA;
cmd_resp.prgbBuffer = p_buffer;
cmd_resp.wBufferLength = *buffer_size;
cmd_resp.wRespLength = 0;
status = CmdLib_GetDataObject(&cmd_params,&cmd_resp);
if(CMD_LIB_OK != status)
{
status = (int32_t)OPTIGA_LIB_ERROR;
break;
}
*buffer_size = cmd_resp.wRespLength;
status = OPTIGA_LIB_SUCCESS;
}while(FALSE);
return status;
}
optiga_lib_status_t optiga_util_read_metadata(uint16_t optiga_oid, uint8_t * p_buffer, uint16_t* buffer_size)
{
//lint --e{818} suppress "PpsGPData is out parameter"
int32_t status = (int32_t)OPTIGA_LIB_ERROR;
sGetData_d cmd_params;
sCmdResponse_d cmd_resp;
uint16_t buffer_limit = *buffer_size;
sbBlob_d meta_data = {LENGTH_METADATA, p_buffer};
sACVector_d ac_vector;
do
{
if((NULL == p_buffer) || (NULL == buffer_size) || (0 == *buffer_size))
{
status = (int32_t)OPTIGA_LIB_ERROR;
break;
}
//Read lcsA
status = __optiga_util_read_lcsa_lcsg(eLCSA,&(ac_vector.bLcsA));
if(INT_LIB_OK != status)
{
status = (int32_t)OPTIGA_LIB_ERROR;
break;
}
//Read lcsG
status = __optiga_util_read_lcsa_lcsg(eLCSG,&(ac_vector.bLcsG));
if(INT_LIB_OK != status)
{
status = (int32_t)OPTIGA_LIB_ERROR;
break;
}
//check if OID is for lcsA or lcaG
if((uint16_t)eLCSA == optiga_oid)
{
//return the read value
*p_buffer = ac_vector.bLcsA;
*buffer_size = 0x01;
break;
}
if((uint16_t)eLCSG == optiga_oid)
{
//return the read value
*p_buffer = ac_vector.bLcsG;
*buffer_size = 0x01;
break;
}
//Get metadata of oid
cmd_params.wOID = optiga_oid;
cmd_params.wLength = LENGTH_METADATA;
cmd_params.wOffset = 0;
cmd_params.eDataOrMdata = eMETA_DATA;
cmd_resp.prgbBuffer = p_buffer;
cmd_resp.wBufferLength = buffer_limit;
cmd_resp.wRespLength = 0;
status = CmdLib_GetDataObject(&cmd_params,&cmd_resp);
if(CMD_LIB_OK != status)
{
status = (int32_t)OPTIGA_LIB_ERROR;
break;
}
//Check the length
*buffer_size = *(cmd_resp.prgbBuffer + POS_LEN );
if((*buffer_size != (cmd_resp.wRespLength-POS_VAL)))
{
status = (int32_t)INT_LIB_INVALID_RESPONSE;
break;
}
//Check read access condition
ac_vector.psMetaData = &meta_data;
status = __optiga_util_verify_ac(eREAD_AC,&ac_vector);
if(INT_LIB_OK != status)
{
status = (int32_t)INT_LIB_INVALID_AC;
break;
}
status = OPTIGA_LIB_SUCCESS;
}while(FALSE);
if(status != OPTIGA_LIB_SUCCESS)
{
status = OPTIGA_LIB_ERROR;
}
return status;
}
optiga_lib_status_t optiga_util_write_data(uint16_t optiga_oid, uint8_t write_type, uint16_t offset, uint8_t * p_buffer, uint16_t buffer_size)
{
int32_t status = (int32_t)OPTIGA_LIB_ERROR;
sSetData_d sd_params;
do
{
if((NULL == p_buffer) || (0x00 == buffer_size))
{
break;
}
if ((OPTIGA_UTIL_WRITE_ONLY != write_type) && (OPTIGA_UTIL_ERASE_AND_WRITE != write_type))
{
status = OPTIGA_UTIL_ERROR_INVALID_INPUT;
break;
}
//If access condition satisfied, set the data
sd_params.wOID = optiga_oid;
sd_params.wOffset = offset;
sd_params.eDataOrMdata = eDATA;
if (OPTIGA_UTIL_ERASE_AND_WRITE == write_type)
sd_params.eWriteOption = eERASE_AND_WRITE;
else
sd_params.eWriteOption = eWRITE;
sd_params.prgbData = p_buffer;
sd_params.wLength = buffer_size;
status = CmdLib_SetDataObject(&sd_params);
if(CMD_LIB_OK != status)
{
break;
}
status = OPTIGA_LIB_SUCCESS;
}while(FALSE);
if(status != OPTIGA_LIB_SUCCESS)
{
status = OPTIGA_LIB_ERROR;
}
return status;
}
optiga_lib_status_t optiga_util_write_metadata(uint16_t optiga_oid, uint8_t * p_buffer, uint8_t buffer_size)
{
int32_t status = (int32_t)OPTIGA_LIB_ERROR;
sSetData_d sd_params;
//If access condition satisfied, set the data
sd_params.wOID = optiga_oid;
sd_params.wOffset = 0;
sd_params.eDataOrMdata = eMETA_DATA;
sd_params.eWriteOption = eWRITE;
sd_params.prgbData = p_buffer;
sd_params.wLength = buffer_size;
status = CmdLib_SetDataObject(&sd_params);
if(CMD_LIB_OK != status)
{
return OPTIGA_LIB_ERROR;
}
return OPTIGA_LIB_SUCCESS;
}
#endif // MODULE_ENABLE_READ_WRITE