/** * 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 the functionality to form and process DTLS messages for OCP Library. * * \addtogroup grMutualAuth * @{ */ #include "optiga/dtls/MessageLayer.h" #ifdef MODULE_ENABLE_DTLS_MUTUAL_AUTH #define CALL_BACK_OK 0x00000001 /** * Call back function to allocate memory to the received message from Security Chip.
* * \param[in,out] PpCBParam Pointer to structure containing information required to allocate memory * \param[in] psInOutMsg Pointer to sBlob containing the received Handshake message from Security Chip * * \retval #CMD_LIB_OK Successful Execution * \retval #CMD_LIB_ERROR Failure Execution */ int32_t CallBack_GetMessage(Void* PpCBParam, const sbBlob_d* psInOutMsg) { int32_t i4Status = (int32_t) CMD_LIB_ERROR; uint32_t dwFragLen; uint32_t dwTotalLen; uint32_t dwOffset; /// @cond hidden #define PS_CBGETMSG ((sCBGetMsg_d*)PpCBParam) #define OFFSET_MSG_FRAG_LENGTH 9 #define OFFSET_MSG_TOTAL_LENGTH 1 #define OFFSET_MSG_FRAGMENT_OFFSET 6 /// @endcond do { dwFragLen = Utility_GetUint24(psInOutMsg->prgbStream + OFFSET_MSG_FRAG_LENGTH); dwTotalLen = Utility_GetUint24(psInOutMsg->prgbStream + OFFSET_MSG_TOTAL_LENGTH); dwOffset = Utility_GetUint24(psInOutMsg->prgbStream + OFFSET_MSG_FRAGMENT_OFFSET); //If first time, allocate memory if(FALSE == PS_CBGETMSG->bRepeatCall) { //Allocate memory PS_CBGETMSG->dwMsgLen = (uint16_t)dwTotalLen + OVERHEAD_LEN; PS_CBGETMSG->pbActualMsg = (uint8_t*)OCP_MALLOC(dwTotalLen + OVERHEAD_LEN); if(PS_CBGETMSG->pbActualMsg == NULL) { i4Status = (int32_t)OCP_ML_MALLOC_FAILURE; break; } //Set to true indicating memory is already allocated PS_CBGETMSG->bRepeatCall = TRUE; OCP_MEMCPY(PS_CBGETMSG->pbActualMsg + (OVERHEAD_LEN - MSG_HEADER_LEN),psInOutMsg->prgbStream,(uint16_t)(dwFragLen + MSG_HEADER_LEN)); //Set fragment offset to zero and fragment len to total len Utility_SetUint24((PS_CBGETMSG->pbActualMsg + (OVERHEAD_LEN - 3)), dwTotalLen); } else { //copy data from offset OCP_MEMCPY(PS_CBGETMSG->pbActualMsg + dwOffset + OVERHEAD_LEN, (psInOutMsg->prgbStream + MSG_HEADER_LEN), (uint16_t)dwFragLen); } i4Status = CMD_LIB_OK; }while(FALSE); /// @cond hidden #undef OFFSET_MSG_FRAG_LENGTH #undef OFFSET_MSG_TOTAL_LENGTH #undef OFFSET_MSG_FRAGMENT_OFFSET #undef PS_CBGETMSG /// @endcond return i4Status; } /** * Provide Handshake message using Command Library.
* Under some erroneous conditions, error codes from Command Library can also be returned.
* * \param[in] eMsgType Message type of the handshake message to be received from Security Chip * \param[in] PpsMessageLayer Pointer to structure containing information required for Message Layer * \param[out] PpsMessage Pointer to sBlob containing the Handshake message * * \retval #OCP_ML_OK Successful Execution * \retval #OCP_ML_ERROR Failure Execution * \retval #OCP_ML_INVALID_UNIXTIME Invalid unix time provided by user */ int32_t MsgLayer_FormMessage(eMsgType_d eMsgType,const sMessageLayer_d* PpsMessageLayer, sbBlob_d* PpsMessage) { int32_t i4Status = (int32_t) OCP_ML_ERROR; sProcMsgData_d sGMsgVector; sCallBack_d sCallBack; sCBGetMsg_d sCBGetMsg; uMsgParams_d uMsgParams; do { //Null Check if((NULL == PpsMessageLayer) || (NULL == PpsMessage)) { i4Status = (int32_t)OCP_ML_NULL_PARAM; break; } //Assign the call back function parameters sCBGetMsg.bRepeatCall = FALSE; sCBGetMsg.pbActualMsg = NULL; sCBGetMsg.dwMsgLen = 0; //Assign call back function to allocate memory sCallBack.pfAcceptMessage = CallBack_GetMessage; sCallBack.fvParams = (Void*) &sCBGetMsg; //Form the Get message command APDU parameters sGMsgVector.eParam = eMsgType; sGMsgVector.wSessionKeyOID = PpsMessageLayer->wSessionID; sGMsgVector.psCallBack = &sCallBack; sGMsgVector.psBlobInBuffer = NULL; //sGMsgVector.puMsgParams = &uMsgParams; sGMsgVector.puMsgParams = NULL; //Based on the message type set the message specific data switch((uint8_t)eMsgType) { case eClientHello: if(NULL != PpsMessageLayer->pfGetUnixTIme) { sGMsgVector.puMsgParams = &uMsgParams; //To use the unix time provided i4Status = PpsMessageLayer->pfGetUnixTIme(&sGMsgVector.puMsgParams->sMsgParamCH_d.dwUnixTime); if(CALL_BACK_OK != i4Status) { i4Status = (int32_t) OCP_ML_INVALID_UNIXTIME; break; } } break; case eClientCertificate: if(0x0000 != PpsMessageLayer->wOIDDevCertificate) { sGMsgVector.puMsgParams = &uMsgParams; sGMsgVector.puMsgParams->sMsgParamCert_d.wCertOID = PpsMessageLayer->wOIDDevCertificate; } break; default: //lint -e788 suppress "Default values for return are already set.No more operation required here" //For other messages there is no message specific data break; } if(((int32_t) OCP_ML_INVALID_UNIXTIME == i4Status) || ((int32_t) OCP_ML_INVALID_CERTTYPE == i4Status)) { break; } //Get the Message using Get Message command from the Security Chip i4Status = CmdLib_GetMessage(&sGMsgVector); if(CMD_LIB_OK != i4Status) { LOG_TRANSPORTDBVAL(i4Status,eInfo); break; } //Allocated memory is assigned the sBlob PpsMessage->prgbStream = sCBGetMsg.pbActualMsg; PpsMessage->wLen = sCBGetMsg.dwMsgLen; i4Status = (int32_t) OCP_ML_OK ; }while(FALSE); return i4Status; } /** * Process Handshake message using Command Library.
* Under some erroneous conditions, error codes from Command Library can also be returned.
* * \param[in] eMsgType Message type of the handshake message to be send to Security Chip * \param[in] PpsMessageLayer Pointer to structure containing information required for Message Layer * \param[in] PpsMessage Pointer to sBlob containing the Handshake message * * \retval #OCP_ML_OK Successful Execution * \retval #OCP_ML_ERROR Failure Execution */ int32_t MsgLayer_ProcessMessage(eMsgType_d eMsgType,const sMessageLayer_d* PpsMessageLayer, sbBlob_d* PpsMessage) { int32_t i4Status = (int32_t) OCP_ML_ERROR; sProcMsgData_d sPMsgVector ; do { //Null Check if((NULL == PpsMessageLayer) || (NULL == PpsMessage) || (NULL == PpsMessage->prgbStream)) { i4Status = (int32_t)OCP_ML_NULL_PARAM; break; } //Length check for input parameters if(0 == PpsMessage->wLen) { i4Status = (int32_t)OCP_ML_ZERO_LEN; break; } //Assign the required parameter(s) for the Put Message command sPMsgVector.eParam = eMsgType; sPMsgVector.psBlobInBuffer = PpsMessage; sPMsgVector.wSessionKeyOID = PpsMessageLayer->wSessionID; sPMsgVector.puMsgParams = NULL; sPMsgVector.psCallBack = NULL; //Invoke the Put Message command API from the command library to send the message to Security Chip to Process i4Status = CmdLib_PutMessage(&sPMsgVector); if(CMD_LIB_OK != i4Status) { LOG_TRANSPORTDBVAL(i4Status,eInfo); break; } i4Status = (int32_t) OCP_ML_OK; }while(FALSE); #undef PhOCPHandle return i4Status; } /** * @} */ #endif /*MODULE_ENABLE_DTLS_MUTUAL_AUTH*/