/**
* 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 DtlsFlightHandler.c
*
* \brief This file implements the DTLS Flight handling details.
*
* \addtogroup grMutualAuth
* @{
*/
#include "optiga/dtls/DtlsFlighthandler.h"
#ifdef MODULE_ENABLE_DTLS_MUTUAL_AUTH
/// @cond hidden
#define LSBREM8(x) (x & 0x07)
#define LSTBYTE(x) ( ((LSBREM8(x))) ? 1 : 0)
#define DIVBY8(x) (x >> 3)
#define DIVBY4(x) (x >> 2)
#define UPDATEGRANLRTY 32
#define MSG_BITMAP8SET(dwNumBits, pbByte2Set, dwStartBit) (*pbByte2Set |= (uint8_t)((uint8_t)((1 << dwNumBits)-1) << dwStartBit))
#define MSG_BITMAP32SET(dwNumBits, pbWord2Set, dwStartBit) (*pbWord2Set |= ((uint32_t)(0-1)) << dwStartBit)
#define MSG_ID(X) (X & 0xFF)
#define FLIGHT_IDLIMITCHK(LL, X, UL) (((X)>=(LL) && (X)<=(UL)) ? OCP_FL_OK : OCP_FL_ERROR)
///Maximum message payload
#define MAX_MSG_PAYLOAD 1536 //1558-5(APDU)-12(Msg header)-5(Session ID)
///Offset for handshake message
#define HANDSHAKE_HEADER_OFFSET 0x00
///Offset for Message ID in handshake header
#define OFFSET_HS_MSG_TYPE (HANDSHAKE_HEADER_OFFSET + 0)
///Offset for Message length in handshake header
#define OFFSET_HS_MSG_LENGTH (OFFSET_HS_MSG_TYPE + 1)
///Offset for Message Sequence number in handshake header
#define OFFSET_HS_MSG_SEQNUM (OFFSET_HS_MSG_LENGTH + 3)
///Offset for Fragment offset in handshake header
#define OFFSET_HS_MSG_FRAGOFFSET (OFFSET_HS_MSG_SEQNUM + 2)
///Offset for Fragment length in handshake header
#define OFFSET_HS_MSG_FRAGLEN (OFFSET_HS_MSG_FRAGOFFSET + 3)
///Offset for message data
#define OFFSET_HS_MSG_DATA (OFFSET_HS_MSG_FRAGLEN + 3) //12
///Message header length
#define LENGTH_HS_MSG_HEADER (OFFSET_HS_MSG_DATA)
///Value of Message type in handshake header
#define HS_MESSAGE_TYPE(X) (*((X)+(OFFSET_HS_MSG_TYPE)))
///Value of Message length in handshake header
#define HS_MESSAGE_LENGTH(X) (Utility_GetUint24((X)+(OFFSET_HS_MSG_LENGTH)))
///Value of Message sequence number in handshake header
#define HS_MESSAGE_SEQNUM(X) (Utility_GetUint16((X)+(OFFSET_HS_MSG_SEQNUM)))
///Value of Message fragment offset in handshake header
#define HS_MESSAGE_FRAGOFFSET(X) (Utility_GetUint24((X)+(OFFSET_HS_MSG_FRAGOFFSET)))
///Value of Message fragment length in handshake header
#define HS_MESSAGE_FRAGLEN(X) (Utility_GetUint24((X)+(OFFSET_HS_MSG_FRAGLEN)))
#define UPDATE_RX_MSGSEQNUM(X,Y) (X=Y)
#define OCP_FLIGHT_TABLE_MAX_SIZE 3
#define UPDATE_MSGSTATE(X,Y) (X=Y)
/// @endcond
///Maximum number of retransmission of a flight in a session during the handshake protocol
#define OCP_MSGRX_MAX_COUNT 6
/**
* \brief Initializes the pointer to bit map representing message status.
*/
_STATIC_H int32_t DtlsHS_MsgCompleteInit(uint32_t PdwMsgLen, uint8_t** PppbMapPtr);
/**
* \brief Sets the number of bits in bit map equal to the number of bytes received in message/ fragment.
*/
_STATIC_H int32_t DtlsHS_MsgUptBitMsk(uint32_t PdwOffset, uint32_t PdwFragLen, uint8_t* PprgbMapPtr, uint32_t PdwMsgLen);
/**
* \brief Checks if all the bits in the bitmap are set for the message completion.
*/
_STATIC_H int32_t DtlsHS_MsgCompleteCheck(uint8_t* PprgbMapPtr, uint32_t PdwMsgLen);
/**
* \brief Clears all the bits in the bitmap.
*/
_STATIC_H int32_t DtlsHS_MsgClearBitMap(uint8_t* PprgbMapPtr, uint32_t PdwMsgLen);
/**
* \brief Searches the look-up table and returns the flight descriptor.
*/
_STATIC_H int32_t DtlsHS_GetFlightDescriptor(uint8_t PbFlightID, uint16_t* PpwFlightID);
/**
* \brief Searches the look-up table and returns the flight handler.
*/
_STATIC_H int32_t DtlsHS_GetFlightHandler(uint8_t PeFlightID, fFlightHandler * PfHndler);
/**
* \brief Inserts the message node to flight head node.
*/
_STATIC_H void DtlsHS_InsertMsgNode(sMsgInfo_d** PppsNodeHead, sMsgInfo_d* PpsNewNode);
/**
* \brief Adds a message node to the end of the message list.
*/
_STATIC_H void DtlsHS_AddMsgNode(sMsgInfo_d** PppsNodeHead, sMsgInfo_d* PpsNewNode);
/**
* \brief Initialises message node to respective parameters.
*/
_STATIC_H int32_t DtlsHS_SInit_MessageNode(sMsgInfo_d* PpsMsgNode, const sMsgLyr_d* PpsMessageLayer);
/**
* \brief Checks if given optional message is in the list.
*/
_STATIC_H int32_t DtlsHS_CheckOptMsg(uint8_t PbMsgID, const uint8_t* PpbOptMsgList);
/**
* \brief Checks if the given message can be sent to the server or not.
*/
_STATIC_H int32_t DtlsHS_Flight5_CheckOptMsg(uint8_t PbMsgID, const uint8_t* PpbOptMsgList, const sMsgLyr_d* PpsMessageLayer);
/**
* \brief Forms the change cipher spec message.
*/
_STATIC_H int32_t DtlsHS_SInit_ChangeCipherSpec(sMsgInfo_d* PpsMsgNode);
/**
* \brief Returns the sequence number of the last message in a flight.
*/
_STATIC_H void DtlsHS_FlightGetLastMsgSeqNum(const sMsgInfo_d *PpsMessageList, uint16_t *PwLastMsgSeqNum);
/**
* \brief Initializes the message node with respective parameters and updates the bit map.
*/
_STATIC_H int32_t DtlsHS_RInit_MessageNode(sMsgInfo_d* PpsMsgNode, sMsgLyr_d* PpsMessageLayer);
/**
* \brief Returns the total number of messages in a flight.
*/
_STATIC_H void DtlsHS_GetTotalMsgCount(const uint16_t *PwMsgDescList, uint8_t *PbMsgCount);
/**
* \brief Returns the number of optional messages in a flight.
*/
_STATIC_H void DtlsHS_GetOptMsgCount(const uint16_t *PwMsgDescList, uint8_t *PbOptMsgCount);
/**
* \brief Returns the message descriptor from the list of messages.
*/
_STATIC_H void DtlsHS_GetMsgDesc(const uint16_t *PwMsgDescList, uint8_t PbMsgType, uint16_t *PwMsgDesc);
/**
* \brief Adds a optional message to the list of optional messages.
*/
_STATIC_H void DtlsHS_Update_OptList(sMsgLyr_d* PpsMessageLayer, uint8_t PbMsgType, uint8_t PeFlightID);
/**
* \brief Checks if all the messages of a flight are completely received.
*/
_STATIC_H int32_t DtlsHS_CheckFlight_Compl(sMsgInfo_d *PpsMessageList, uint8_t PeFlightID, const sMsgLyr_d* PpsMessageLayer);
/**
* \brief Checks if a message is received more than or equal to six times.
*/
_STATIC_H int32_t DtlsHS_MessageLimitCheck(sMsgInfo_d *PpsMsgNode);
/**
* \brief Buffers the received message/ fragment.
*/
_STATIC_H int32_t DtlsHS_FlightMsgChkAndBuffer(sMsgInfo_d *PpsMessageList, uint8_t bMsgID, const sbBlob_d* PpsMsgIn, sMsgLyr_d* PpsMessageLayer, uint8_t PeFlightID);
/**
* \brief Checks if the message type of the received message/ fragment belongs to the flight.
*/
_STATIC_H int32_t DtlsHS_Flight_LimitChk(uint8_t PbFlightID, uint8_t PbMsgID);
/**
* \brief Sends the message to be processed to Security Chip.
*/
_STATIC_H int32_t DtlsHS_SendFlightToOptiga(sMsgInfo_d *PpsMessageList, const sMsgLyr_d* PpsMessageLayer);
/**
* \brief Resets the flight 2 node.
*/
_STATIC_H void DtlsHS_ResetFlight2MsgNode(const sFlightStats_d* PpsThisFlight);
/**
* \brief Checks if message sequence number of received message/ fragment of flight4 is correct.
*/
_STATIC_H int32_t DtlsHS_Flight4CheckMsgSeqNum(const sMsgLyr_d* PpsMessageLayer, uint8_t PbRxMsgID, uint16_t PwRxMsgSeqNum);
/**
* \brief Checks if message sequence number and length of received message/ fragment of flight4 is the same as the buffered one.
*/
_STATIC_H int32_t DtlsHS_Flight4CheckBuffMsg(uint8_t PbMsgType, uint16_t PwMsgSeqNum, uint32_t PdwMsgLen, sMsgInfo_d *PpsMsgList);
/**
* \brief Checks for flight4 completion.
*/
_STATIC_H int32_t DtlsHS_Flight4ReRxCompl(sMsgInfo_d *PpsMsgList);
/**
* \brief Clears the messages of a flight and resets the bit map.
*/
_STATIC_H void DtlsHS_Flight4ClearMsgsInList(sMsgInfo_d *PpsMsgList);
/**
* \brief Updates bit map and sets the message state.
*/
_STATIC_H int32_t DtlsHS_Flight4UpdateMsgStat(uint8_t PbMsgID, sMsgInfo_d *PpsMsgList, const sMsgLyr_d* PpsMessageLayer);
/**
* \brief Checks whether flight six is received.
*/
_STATIC_H int32_t DtlsHS_CheckFlight6_Compl(sMsgInfo_d *PpsMessageList);
/**
* \brief Checks Message Sequence number of flight six messages.
*/
_STATIC_H int32_t DtlsHS_Flight6CheckMsgSeqNum(const sMsgLyr_d* PpsMessageLayer, uint8_t PbMsgID, uint16_t PwMsgSeqNum);
/**
* \brief Frees a node and all the pointers in it .
*/
_STATIC_H void DtlsHS_FreeMsgNode(sMsgInfo_d *PpsMsgNode);
/**
* Initializes the pointer to bit map representing message status.
*
* \param[in] PdwMsgLen Total length of the message received.
* \param[out] PppbMapPtr Pointer container to map pointer.
*
* \retval #OCP_FL_OK Successful execution
* \retval #OCP_FL_MSG_ERROR Failure in execution
\if ENABLE_NULL_CHECKS
* \retval #OCP_FL_NULL_PARAM Null parameter
\endif
*/
_STATIC_H int32_t DtlsHS_MsgCompleteInit(uint32_t PdwMsgLen, uint8_t** PppbMapPtr)
{
int32_t i4Status = (int32_t)OCP_FL_MSG_ERROR;
uint32_t dwMapSize;
uint8_t* pbMapPtr = NULL;
uint8_t bLbyteMsk;
do
{
#ifdef ENABLE_NULL_CHECKS
if(NULL == PppbMapPtr)
{
i4Status = (int32_t)OCP_FL_NULL_PARAM;
break;
}
#endif
dwMapSize = DIVBY8(PdwMsgLen) + LSTBYTE(PdwMsgLen);
if(*PppbMapPtr == NULL)
{
pbMapPtr = (uint8_t*)OCP_CALLOC(dwMapSize, sizeof(uint8_t));
if(pbMapPtr == NULL)
{
i4Status = (int32_t)OCP_FL_MALLOC_FAILURE;
break;
}
*PppbMapPtr = pbMapPtr;
// Set remaining bits in last byte
bLbyteMsk = (uint8_t)((uint8_t)( (1 << (8 - (LSBREM8(PdwMsgLen) ))) - (LSTBYTE(PdwMsgLen)) ) << (LSBREM8(PdwMsgLen)));
*(pbMapPtr+(dwMapSize-1)) |= bLbyteMsk;
}
i4Status = (int32_t)OCP_FL_OK;
}while(0);
return i4Status;
}
/**
* Sets the number of bits in bit map equal to the number of bytes received in message/ fragment.
*
* \param[in] PdwOffset Offset of the message/ fragment received.
* \param[in] PdwFragLen Length of the message/ fragment received.
* \param[in,out] PprgbMapPtr Pointer to bit map.
* \param[in] PdwMsgLen Length of the message/ fragment received.
*
* \retval #OCP_FL_OK Successful execution
* \retval #OCP_FL_MSG_ERROR Failure in execution
\if ENABLE_NULL_CHECKS
* \retval #OCP_FL_NULL_PARAM Null parameter
\endif
*/
_STATIC_H int32_t DtlsHS_MsgUptBitMsk(uint32_t PdwOffset, uint32_t PdwFragLen, uint8_t* PprgbMapPtr, uint32_t PdwMsgLen)
{
int32_t i4Status = (int32_t)OCP_FL_MSG_ERROR;
uint32_t dwStartByte, dwStartBit, dwNumofBit2Set, dwLoopCount, dwCount;
uint8_t* prgbByte2Set = NULL;
do
{
#ifdef ENABLE_NULL_CHECKS
if(NULL == PprgbMapPtr)
{
i4Status = (int32_t)OCP_FL_NULL_PARAM;
break;
}
#endif
dwStartByte = DIVBY8(PdwOffset);
dwStartBit = LSBREM8(PdwOffset);
dwNumofBit2Set = PdwFragLen;
prgbByte2Set = PprgbMapPtr + dwStartByte;
if(dwStartBit != 0)
{
if(dwNumofBit2Set < (8-dwStartBit))
{
MSG_BITMAP8SET(dwNumofBit2Set, prgbByte2Set, dwStartBit);
dwNumofBit2Set -= dwNumofBit2Set;
}
else
{
MSG_BITMAP8SET((8-dwStartBit), prgbByte2Set, dwStartBit);
dwNumofBit2Set -= (8-dwStartBit);
}
prgbByte2Set++;
}
if(prgbByte2Set < ( PprgbMapPtr+(DIVBY8(PdwMsgLen)+LSTBYTE(PdwMsgLen))) )
{
dwLoopCount = dwNumofBit2Set/UPDATEGRANLRTY;
for(dwCount=0; dwCount < dwLoopCount; dwCount++)
{
//lint --e{826} suppress "Implicit type casting to 32 bit pointer for 32 bit granularity check"
MSG_BITMAP32SET(UPDATEGRANLRTY, (uint32_t*)prgbByte2Set, 0);
prgbByte2Set += (UPDATEGRANLRTY >> 3);
dwNumofBit2Set -= UPDATEGRANLRTY;
}
if(dwNumofBit2Set >= 0x08)
{
dwLoopCount = DIVBY8(dwNumofBit2Set);
for(dwCount=0; dwCount < dwLoopCount; dwCount++)
{
MSG_BITMAP8SET(8, prgbByte2Set, 0);
prgbByte2Set++;
dwNumofBit2Set -= 8;
}
}
if(dwNumofBit2Set)
{
MSG_BITMAP8SET(dwNumofBit2Set, prgbByte2Set, 0);
dwNumofBit2Set -= dwNumofBit2Set;
}
}
i4Status = (int32_t)OCP_FL_OK;
}while(0);
return i4Status;
}
/**
* Checks if all the bits in the bitmap is set for the message completion.
*
* \param[in] PprgbMapPtr Pointer to bit map.
* \param[in] PdwMsgLen Total Length of the message received.
*
* \retval #OCP_FL_OK Successful execution
* \retval #OCP_FL_MSG_ERROR Failure in execution
\if ENABLE_NULL_CHECKS
* \retval #OCP_FL_NULL_PARAM Null parameter
\endif
*/
_STATIC_H int32_t DtlsHS_MsgCompleteCheck(uint8_t* PprgbMapPtr, uint32_t PdwMsgLen)
{
uint32_t dwLoopCount;
int32_t i4Status = (int32_t)OCP_FL_OK;
uint32_t* pdwMapptr = NULL;
uint8_t* pbMapptr = NULL;
dwLoopCount = DIVBY4(DIVBY8(PdwMsgLen));
/// @cond hidden
#define DWVAL 0xFFFFFFFF
/// @endcond
do
{
#ifdef ENABLE_NULL_CHECKS
if(NULL == PprgbMapPtr)
{
i4Status = (int32_t)OCP_FL_NULL_PARAM;
break;
}
#endif
//lint --e{826} suppress "Implicit type casting to 32 bit pointer for 32 bit granularity check"
pdwMapptr = (uint32_t*)PprgbMapPtr;
while(dwLoopCount--)
{
if(*pdwMapptr++ < DWVAL )
{
i4Status = (int32_t)OCP_FL_MSG_ERROR;
break;
}
PdwMsgLen -= UPDATEGRANLRTY;
}
if(i4Status != (int32_t)OCP_FL_MSG_ERROR)
{
dwLoopCount = DIVBY8(PdwMsgLen)+LSTBYTE(PdwMsgLen);
pbMapptr = (uint8_t*)pdwMapptr;
while(dwLoopCount--)
{
if(*pbMapptr++ < ((1<<8)-1))
{
i4Status = (int32_t)OCP_FL_MSG_ERROR;
break;
}
}
}
}while(0);
/// @cond hidden
#undef DWVAL
/// @endcond
return i4Status;
}
/**
* Clears all the bits in the bitmap.
*
* \param[in,out] PprgbMapPtr Pointer to bit map.
* \param[in] PdwMsgLen Total length of the message received.
*
* \retval #OCP_FL_OK Successful execution
* \retval #OCP_FL_MSG_ERROR Failure in execution
\if ENABLE_NULL_CHECKS
* \retval #OCP_FL_NULL_PARAM Null parameter
\endif
*/
_STATIC_H int32_t DtlsHS_MsgClearBitMap(uint8_t* PprgbMapPtr, uint32_t PdwMsgLen)
{
uint32_t dwLoopCount, dwMapSize;
int32_t i4Status = (int32_t)OCP_FL_MSG_ERROR;
uint32_t* pdwMapptr = NULL;
uint8_t* pbMapptr = NULL;
uint8_t bLbyteMsk;
do
{
#ifdef ENABLE_NULL_CHECKS
if(NULL == PprgbMapPtr)
{
i4Status = (int32_t)OCP_FL_NULL_PARAM;
break;
}
#endif
//lint --e{826} suppress "Implicit type casting to 32 bit pointer for 32 bit granularity check"
pdwMapptr = (uint32_t*)PprgbMapPtr;
dwMapSize = DIVBY8(PdwMsgLen) + LSTBYTE(PdwMsgLen);
dwLoopCount = DIVBY4(DIVBY8(PdwMsgLen));
while(dwLoopCount--)
{
*pdwMapptr++ = 0x00;
PdwMsgLen -= UPDATEGRANLRTY;
}
dwLoopCount = DIVBY8(PdwMsgLen)+LSTBYTE(PdwMsgLen);
pbMapptr = (uint8_t*)pdwMapptr;
while(dwLoopCount--)
{
*pbMapptr++ = 0x00;
}
bLbyteMsk = (uint8_t)((uint8_t)((1 << (8 - (LSBREM8(PdwMsgLen) ))) - (LSTBYTE(PdwMsgLen)) ) << (LSBREM8(PdwMsgLen)));
*(PprgbMapPtr+(dwMapSize-1)) |= bLbyteMsk;
i4Status = (int32_t)OCP_FL_OK;
}while(0);
return i4Status;
}
/**
* Searches the look-up table and returns the flight descriptor.
*
* \param[in] PbFlightID Flight number
* \param[in,out] PpwFlightID Container to flight descriptor
*
* \retval #OCP_HL_OK Successful Execution
* \retval #OCP_HL_ERROR Failure Execution
*/
_STATIC_H int32_t DtlsHS_GetFlightDescriptor(uint8_t PbFlightID, uint16_t* PpwFlightID)
{
int32_t i4Status = (int32_t)OCP_FL_ERROR;
uint8_t bIndex = 0;
do
{
for(bIndex = 0; bIndex < OCP_FLIGHT_TABLE_MAX_SIZE; bIndex++)
{
if(((rgsSFlightInfo[bIndex].wFlightDesc) & 0xFF) == (PbFlightID))
{
*PpwFlightID = rgsSFlightInfo[bIndex].wFlightDesc;
i4Status = (int32_t)OCP_FL_OK;
break;
}
}
if((int32_t)OCP_FL_ERROR == i4Status)
{
for(bIndex = 0; bIndex < OCP_FLIGHT_TABLE_MAX_SIZE; bIndex++)
{
if((rgsRFlightInfo[bIndex].wFlightDesc & 0xFF) == (PbFlightID))
{
*PpwFlightID = rgsRFlightInfo[bIndex].wFlightDesc;
i4Status = (int32_t)OCP_FL_OK;
break;
}
}
}
}while(0);
return i4Status;
}
/**
* Searches the look-up table and returns the flight handler.
*
* \param[in] PeFlightID Flight number
* \param[in,out] PfHndler Container to flight handler
*
* \retval #OCP_HL_OK Successful Execution
* \retval #OCP_HL_ERROR Failure Execution
*/
_STATIC_H int32_t DtlsHS_GetFlightHandler(uint8_t PeFlightID, fFlightHandler * PfHndler)
{
int32_t i4Status = (int32_t)OCP_FL_ERROR;
uint8_t bIndex;
do
{
for(bIndex = 0; bIndex < OCP_FLIGHT_TABLE_MAX_SIZE; bIndex++)
{
if(((rgsSFlightInfo[bIndex].wFlightDesc) & 0xFF) == (uint8_t)PeFlightID)
{
*PfHndler = (rgsSFlightInfo[bIndex].pFlightHndlr);
i4Status = (int32_t)OCP_FL_OK;
break;
}
}
if((int32_t)OCP_FL_ERROR == i4Status)
{
for(bIndex = 0; bIndex < OCP_FLIGHT_TABLE_MAX_SIZE; bIndex++)
{
if(((rgsRFlightInfo[bIndex].wFlightDesc) & 0xFF) == (uint8_t)PeFlightID)
{
*PfHndler = (rgsRFlightInfo[bIndex].pFlightHndlr);
i4Status = (int32_t)OCP_FL_OK;
break;
}
}
}
}while(0);
return i4Status;
}
/**
* Inserts the message node to flight head node .
*
* \param[in,out] PppsNodeHead Pointer container holding head node pointer.
* \param[in] PpsNewNode Pointer to the message node to be inserted.
*
*/
_STATIC_H void DtlsHS_InsertMsgNode(sMsgInfo_d** PppsNodeHead, sMsgInfo_d* PpsNewNode)
{
sMsgInfo_d* pTravA = *PppsNodeHead;
sMsgInfo_d* pTravB = NULL;
do
{
if(NULL == pTravA)
{
*PppsNodeHead = PpsNewNode;
}
else
{
do
{
pTravB = pTravA->psNext;
if (PpsNewNode->bMsgType < pTravA->bMsgType)
{
PpsNewNode->psNext = pTravA;
*PppsNodeHead = PpsNewNode;
break;
}
else if (NULL != pTravB)
{
if((PpsNewNode->bMsgType > pTravA->bMsgType) && (PpsNewNode->bMsgType < pTravB->bMsgType))
{
pTravA->psNext = PpsNewNode;
PpsNewNode->psNext = pTravB;
break;
}
}
else
{
if(PpsNewNode->bMsgType > pTravA->bMsgType)
{
pTravA->psNext = PpsNewNode;
PpsNewNode->psNext = NULL;
}
break;
}
pTravA = pTravA->psNext;
}while(NULL != pTravA);
}
}while(0);
}
/**
* Adds a message node to the end of the message list.
*
* \param[in,out] PppsNodeHead Pointer container holding head node pointer.
* \param[in] PpsNewNode Pointer to the message node to be added.
*
*/
_STATIC_H void DtlsHS_AddMsgNode(sMsgInfo_d** PppsNodeHead, sMsgInfo_d* PpsNewNode)
{
sMsgInfo_d* psTrav = *PppsNodeHead;
do
{
if(NULL == psTrav)
{
*PppsNodeHead = PpsNewNode;
}
else
{
while(NULL != psTrav->psNext)
{
psTrav = psTrav->psNext;
}
psTrav->psNext = PpsNewNode;
}
}while(0);
}
/**
* Initialises message node to respective parameters.
* - Calls message layer to get the message.
* - Checks the header of the message received from message layer.
* - Updates the bit map.
*
* \param[in,out] PpsMsgNode Pointer to the message node.
* \param[in] PpsMessageLayer Pointer to the structure containing message configuration information.
*
* \retval #OCP_FL_OK Successful Execution
* \retval #OCP_FL_ERROR Failure Execution
*/
_STATIC_H int32_t DtlsHS_SInit_MessageNode(sMsgInfo_d* PpsMsgNode, const sMsgLyr_d* PpsMessageLayer)
{
int32_t i4Status = (int32_t)OCP_FL_OK;
sbBlob_d sbBlobMessage;
sbBlob_d sMessage;
sMessageLayer_d sMessageLayer;
uint32_t dwTotalLength;
sMessageLayer.wOIDDevCertificate = PpsMessageLayer->wOIDDevCertificate;
sMessageLayer.pfGetUnixTIme = PpsMessageLayer->pfGetUnixTIme;
sMessageLayer.psConfigRL = PpsMessageLayer->psConfigRL;
sMessageLayer.wMaxPmtu = PpsMessageLayer->wMaxPmtu;
sMessageLayer.wSessionID = PpsMessageLayer->wSessionID;
do
{
i4Status = MsgLayer_FormMessage((eMsgType_d)PpsMsgNode->bMsgType, &sMessageLayer, &sbBlobMessage);
if(OCP_ML_OK != i4Status)
{
break;
}
PpsMsgNode->psMsgHolder = sbBlobMessage.prgbStream;
//Assign the pointer from Handshake message header to local blob
sMessage.prgbStream = sbBlobMessage.prgbStream + (OVERHEAD_LEN - MSG_HEADER_LEN);
sMessage.wLen = sbBlobMessage.wLen - (OVERHEAD_LEN - MSG_HEADER_LEN);
dwTotalLength = HS_MESSAGE_LENGTH(sMessage.prgbStream);
if(sMessage.wLen != (dwTotalLength + MSG_HEADER_LEN))
{
break;
}
PpsMsgNode->psMsgMapPtr = NULL;
PpsMsgNode->dwMsgLength = dwTotalLength;
PpsMsgNode->wMsgSequence = HS_MESSAGE_SEQNUM(sMessage.prgbStream);
PpsMsgNode->eMsgState = eComplete;
i4Status = (int32_t)OCP_FL_OK;
}while(0);
return i4Status;
}
/**
* Checks if given optional message is in the list.
*
* \param[in] PbMsgID Message type.
* \param[in] PpbOptMsgList List of received optional messages.
*
* \retval #OCP_FL_OK Requested message found in list
* \retval #OCP_FL_ERROR Requested message not found in list
*/
_STATIC_H int32_t DtlsHS_CheckOptMsg(uint8_t PbMsgID, const uint8_t* PpbOptMsgList)
{
int32_t i4Status = (int32_t)OCP_FL_ERROR;
do
{
if(NULL == PpbOptMsgList)
{
break;
}
while(0xFF != *(PpbOptMsgList))
{
if(PbMsgID == *PpbOptMsgList)
{
i4Status = (int32_t)OCP_FL_OK;
break;
}
PpbOptMsgList++;
}
}while(0);
return i4Status;
}
/**
* Checks if the given message can be sent to the server or not.
*
* \param[in] PbMsgID Message type.
* \param[in] PpbOptMsgList List of received optional messages.
* \param[in] PpsMessageLayer Pointer to the structure containing message configuration information.
*
* \retval #OCP_FL_OK Requested message can be sent
* \retval #OCP_FL_ERROR Requested message cannot be sent
*/
_STATIC_H int32_t DtlsHS_Flight5_CheckOptMsg(uint8_t PbMsgID, const uint8_t* PpbOptMsgList, const sMsgLyr_d* PpsMessageLayer)
{
int32_t i4Status = (int32_t)OCP_FL_OK;
do
{
if(((uint8_t)eClientCertificate == PbMsgID) || ((uint8_t)eCertificateVerify == PbMsgID))
{
if(OCP_FL_OK != DtlsHS_CheckOptMsg((uint8_t)eCertificateRequest, PpbOptMsgList))
{
i4Status = (int32_t)OCP_FL_ERROR;
break;
}
}
if(((uint8_t)eCertificateVerify == PbMsgID) && (0x0000 == PpsMessageLayer->wOIDDevCertificate))
{
i4Status = (int32_t)OCP_FL_ERROR;
break;
}
}while(0);
return i4Status;
}
/**
* Initialises message node to respective parameters.
* - Forms the change cipher spec message.
*
* \param[in,out] PpsMsgNode Pointer to the message node.
*
* \retval #OCP_FL_OK Requested message can be sent
* \retval #OCP_FL_ERROR Requested message cannot be sent
*/
_STATIC_H int32_t DtlsHS_SInit_ChangeCipherSpec(sMsgInfo_d* PpsMsgNode)
{
int32_t i4Status = (int32_t)OCP_FL_OK;
/// @cond hidden
#define CHANGE_CIPHERSPEC_MSGSIZE 1
/// @endcond
do
{
PpsMsgNode->psMsgHolder = (uint8_t*)OCP_MALLOC(CHANGE_CIPHERSPEC_MSGSIZE);
if(NULL == PpsMsgNode->psMsgHolder)
{
i4Status = (int32_t)OCP_FL_MALLOC_FAILURE;
break;
}
*PpsMsgNode->psMsgHolder = (int32_t)0x01;
PpsMsgNode->dwMsgLength = CHANGE_CIPHERSPEC_MSGSIZE;
PpsMsgNode->psMsgMapPtr = NULL;
}while(0);
/// @cond hidden
#undef CHANGE_CIPHERSPEC_MSGSIZE
/// @endcond
return i4Status;
}
/**
* Returns the sequence number of the last message in a flight.
*
* \param[in] PpsMessageList Pointer to list of messages.
* \param[out] PwLastMsgSeqNum Pointer to last sequence number.
*
* \retval #OCP_FL_OK Successful Execution
* \retval #OCP_FL_ERROR Failure Execution
*/
_STATIC_H void DtlsHS_FlightGetLastMsgSeqNum(const sMsgInfo_d *PpsMessageList, uint16_t *PwLastMsgSeqNum)
{
do
{
if(NULL == PpsMessageList)
{
break;
}
while(NULL != PpsMessageList->psNext)
{
PpsMessageList = PpsMessageList->psNext;
}
*PwLastMsgSeqNum = PpsMessageList->wMsgSequence;
}while(0);
}
/**
* Initializes the message node with respective parameters and updates the bit map.
*
* \param[in,out] PpsMsgNode Pointer to new message node.
* \param[in] PpsMessageLayer Pointer to the structure containing message configuration information.
*
* \retval #OCP_FL_OK Successful Execution
* \retval #OCP_FL_ERROR Failure Execution
* \retval #OCP_FL_MSG_INCOMPLETE Message is not completely received
*/
_STATIC_H int32_t DtlsHS_RInit_MessageNode(sMsgInfo_d* PpsMsgNode, sMsgLyr_d* PpsMessageLayer)
{
int32_t i4Status = OCP_FL_OK;
uint32_t dwOffset;
uint32_t dwFragLen;
uint32_t dwTotalLen;
do
{
PpsMsgNode->bMsgType = HS_MESSAGE_TYPE(PpsMessageLayer->sMsg.prgbStream);
dwOffset = HS_MESSAGE_FRAGOFFSET(PpsMessageLayer->sMsg.prgbStream);
dwFragLen = HS_MESSAGE_FRAGLEN(PpsMessageLayer->sMsg.prgbStream);
dwTotalLen = HS_MESSAGE_LENGTH(PpsMessageLayer->sMsg.prgbStream);
//Length of the message payload should not exceed 1536 bytes
if(MAX_MSG_PAYLOAD < dwTotalLen)
{
i4Status = (int32_t)OCP_HL_BUFFER_OVERFLOW;
break;
}
memcpy((PpsMsgNode->psMsgHolder + OVERHEAD_LEN + dwOffset), PpsMessageLayer->sMsg.prgbStream + LENGTH_HS_MSG_HEADER, dwFragLen);
PpsMsgNode->wMsgSequence = HS_MESSAGE_SEQNUM(PpsMessageLayer->sMsg.prgbStream);
PpsMsgNode->dwMsgLength = dwTotalLen;
PpsMsgNode->psMsgMapPtr = NULL;
PpsMsgNode->bMsgCount = 0;
//lint --e{534} suppress "Return value is not required to be checked"
DtlsHS_PrepareMsgHeader((PpsMsgNode->psMsgHolder + (OVERHEAD_LEN - MSG_HEADER_LEN)), PpsMsgNode);
//Initialise Bit Map for message status
if(OCP_FL_OK != DtlsHS_MsgCompleteInit(PpsMsgNode->dwMsgLength, &PpsMsgNode->psMsgMapPtr))
{
i4Status = (int32_t)OCP_FL_ERROR;
break;
}
//lint --e{534} suppress "Return value is not required to be checked"
DtlsHS_MsgUptBitMsk(dwOffset, dwFragLen, PpsMsgNode->psMsgMapPtr, PpsMsgNode->dwMsgLength);
// Check Message Completeness
if(OCP_FL_OK != DtlsHS_MsgCompleteCheck(PpsMsgNode->psMsgMapPtr, PpsMsgNode->dwMsgLength))
{
i4Status = (int32_t)OCP_FL_MSG_INCOMPLETE;
break;
}
DtlsHS_Update_OptList(PpsMessageLayer, PpsMsgNode->bMsgType, (uint8_t)PpsMessageLayer->eFlight);
// If message is completely received, change state to Received
UPDATE_MSGSTATE(PpsMsgNode->eMsgState, eComplete);
PpsMsgNode->bMsgCount++;
}while(0);
return i4Status;
}
/**
* Returns the total number of messages in a flight.
*
* \param[in] PwMsgDescList Pointer to list of messages.
* \param[out] PbMsgCount Pointer to message counter.
*
*/
_STATIC_H void DtlsHS_GetTotalMsgCount(const uint16_t *PwMsgDescList, uint8_t *PbMsgCount)
{
*PbMsgCount = 0;
do
{
(*PbMsgCount)++;
}while(0xFFFF != *(++PwMsgDescList));
}
/**
* Returns the number of optional messages in a flight.
*
* \param[in] PwMsgDescList Pointer to list of messages.
* \param[out] PbOptMsgCount Pointer to message counter.
*
*/
_STATIC_H void DtlsHS_GetOptMsgCount(const uint16_t *PwMsgDescList, uint8_t *PbOptMsgCount)
{
do
{
if(IsOptional(*PwMsgDescList))
{
(*PbOptMsgCount)++;
}
}while(0xFFFF != *(++PwMsgDescList));
}
/**
* Returns the message descriptor from the list of messages.
*
* \param[in] PwMsgDescList Pointer to list of messages.
* \param[in] PbMsgType Message ID of which descriptor is required.
* \param[out] PwMsgDesc Pointer to message descriptor.
*
*/
_STATIC_H void DtlsHS_GetMsgDesc(const uint16_t *PwMsgDescList, uint8_t PbMsgType, uint16_t *PwMsgDesc)
{
do
{
if(MSG_ID(*PwMsgDescList) == PbMsgType)
{
*PwMsgDesc = *PwMsgDescList;
}
PwMsgDescList++;
}while(0xFFFF != *PwMsgDescList);
}
/**
* Adds a optional message to the list of optional messages.
*
* \param[in,out] PpsMessageLayer Pointer to the structure containing message configuration information.
* \param[in] PbMsgType Optional Message ID.
* \param[in] PeFlightID Flight ID.
*
*/
_STATIC_H void DtlsHS_Update_OptList(sMsgLyr_d* PpsMessageLayer, uint8_t PbMsgType, uint8_t PeFlightID)
{
int32_t i4Status = (int32_t)OCP_FL_ERROR;
uint8_t bIndex = 0;
uint16_t *pwFlightMsgs;
do
{
DtlsHS_GetFlightMsgInfo(PeFlightID, &pwFlightMsgs);
//Check whether given message is optional
while(0xFFFF != *pwFlightMsgs)
{
if(MSG_ID(*pwFlightMsgs) == PbMsgType)
{
if(IsOptional(*pwFlightMsgs))
{
i4Status = (int32_t)OCP_FL_OK;
break;
}
}
pwFlightMsgs++;
}
//If the Message is optional, then store the message ID in Optional Message list
if((int32_t)OCP_FL_OK == i4Status)
{
do
{
if((PpsMessageLayer->rgbOptMsgList[bIndex] == PbMsgType) || (PpsMessageLayer->rgbOptMsgList[bIndex] == 0xFF))
{
PpsMessageLayer->rgbOptMsgList[bIndex] = PbMsgType;
break;
}
}while(++bIndex < ((sizeof(PpsMessageLayer->rgbOptMsgList)/sizeof(PpsMessageLayer->rgbOptMsgList[0]))));
}
}while(0);
}
/**
* Checks if all the messages of a flight are completely received.
*
* \param[in] PpsMessageList Pointer to list of messages of a flight.
* \param[in] PeFlightID Flight ID.
* \param[in] PpsMessageLayer Pointer to the structure containing message configuration information.
*
* \retval #OCP_FL_OK All messages are completely received
* \retval #OCP_FL_ERROR Atleast one message is incomplete
*/
_STATIC_H int32_t DtlsHS_CheckFlight_Compl(sMsgInfo_d *PpsMessageList, uint8_t PeFlightID, const sMsgLyr_d* PpsMessageLayer)
{
int32_t i4Status = (int32_t)OCP_FL_ERROR;
sMsgInfo_d* psMsgListTrav = PpsMessageList;
uint32_t dwLastMsgSeq, dwPrevFlightMsgSeq;
uint16_t *pwFlightMsgs;
uint8_t bOptMsgCount = 0;
uint8_t bTotalMsgInFlight = 0;
uint8_t bTotalOptMsgInFlight = 0;
uint8_t bTotalMsgRxDInFlight = 0;
uint16_t wMsgDesc;
uint8_t bSeqNumFlag = TRUE, bLoopCount, bIndex;
dwLastMsgSeq = PpsMessageLayer->dwRMsgSeqNum;
dwPrevFlightMsgSeq = PpsMessageLayer->dwRMsgSeqNum;
do
{
#ifdef ENABLE_NULL_CHECKS
if(NULL == psMsgListTrav)
{
break;
}
#endif
DtlsHS_GetFlightMsgInfo(PeFlightID, &pwFlightMsgs);
DtlsHS_GetTotalMsgCount(pwFlightMsgs, &bTotalMsgInFlight);
DtlsHS_GetOptMsgCount(pwFlightMsgs, &bTotalOptMsgInFlight);
if(dwPrevFlightMsgSeq == 0xFFFFFFFF)
{
bLoopCount = 2;
}
else
{
bLoopCount = 1;
}
for(bIndex = 0; bIndex < bLoopCount; bIndex++)
{
psMsgListTrav = PpsMessageList;
do
{
if(eComplete == psMsgListTrav->eMsgState)
{
DtlsHS_GetMsgDesc(pwFlightMsgs, psMsgListTrav->bMsgType, &wMsgDesc);
if(IsOptional(wMsgDesc))
{
bOptMsgCount++;
}
if(psMsgListTrav->wMsgSequence != dwLastMsgSeq+1)
{
bSeqNumFlag = FALSE;
}
dwLastMsgSeq = psMsgListTrav->wMsgSequence;
bTotalMsgRxDInFlight++;
}
psMsgListTrav = psMsgListTrav->psNext;
}while(NULL != psMsgListTrav);
if((bOptMsgCount != 0) && ((bTotalMsgInFlight == bTotalMsgRxDInFlight) && (TRUE == bSeqNumFlag)))
{
i4Status = (int32_t)OCP_FL_OK;
break;
}
else if((bOptMsgCount == 0) && ((bTotalMsgRxDInFlight == bTotalMsgInFlight-bTotalOptMsgInFlight) && (TRUE == bSeqNumFlag)))
{
i4Status = (int32_t)OCP_FL_OK;
break;
}
else
{
i4Status = (int32_t)OCP_FL_MSG_INCOMPLETE;
}
dwLastMsgSeq = dwPrevFlightMsgSeq+1;
bOptMsgCount = 0;
bTotalMsgRxDInFlight = 0;
bSeqNumFlag = TRUE;
}
}while(0);
return i4Status;
}
/**
* Checks if a message is received more than or equal to six times.
*
* \param[in] PpsMsgNode Pointer to message node.
*
* \retval #OCP_FL_OK Message is received less than six times
* \retval #OCP_FL_ERROR Message is received six times
*/
_STATIC_H int32_t DtlsHS_MessageLimitCheck(sMsgInfo_d *PpsMsgNode)
{
int32_t i4Status = OCP_FL_OK;
do
{
if(++(PpsMsgNode->bMsgCount) > OCP_MSGRX_MAX_COUNT)
{
PpsMsgNode->bMsgCount = OCP_MSGRX_MAX_COUNT;
i4Status = (int32_t)OCP_FL_ERROR;
}
}while(0);
return i4Status;
}
/**
* Buffers the received message/ fragment.
*
* \param[in,out] PpsMessageList Pointer to list of messages in a flight.
* \param[in] PbMsgID Received message type.
* \param[in] PpsMsgIn Pointer to the received message buffer.
* \param[in] PpsMessageLayer Pointer to the structure containing message configuration information.
* \param[in] PeFlightID Flight number.
*
* \retval #OCP_FL_OK Successful execution
* \retval #OCP_FL_ERROR Failure in execution
* \retval #OCP_FL_MSG_NODE_NOT_AVAIL Node corresponding to message is not in the list of messages
* \retval #OCP_FL_MALLOC_FAILURE Memory allocation failure
* \retval #OCP_FL_INVALID_MSG_LENGTH Message Length of new fragment does not match the buffered message length
* \retval #OCP_FL_INVALID_MSG_SEQ Sequence number of new fragment does not match the buffered message/ fragment sequence length
* \retval #OCP_FL_MSG_INCOMPLETE Message is not completely received
* \retval #OCP_FL_MSG_MAXCOUNT Message is received six times
*/
_STATIC_H int32_t DtlsHS_FlightMsgChkAndBuffer(sMsgInfo_d *PpsMessageList, uint8_t PbMsgID, const sbBlob_d* PpsMsgIn, sMsgLyr_d* PpsMessageLayer, uint8_t PeFlightID)
{
int32_t i4Status = (int32_t)OCP_FL_MSG_NODE_NOT_AVAIL;
uint32_t dwOffset = 0;
uint32_t dwFragLength = 0;
sMsgInfo_d *psMsgListTrav = PpsMessageList;
do
{
if(NULL == psMsgListTrav)
{
break;
}
do
{
if(psMsgListTrav->bMsgType == PbMsgID)
{
if((ePartial == psMsgListTrav->eMsgState))
{
dwOffset = HS_MESSAGE_FRAGOFFSET(PpsMsgIn->prgbStream);
dwFragLength = HS_MESSAGE_FRAGLEN(PpsMsgIn->prgbStream);
if(NULL == psMsgListTrav->psMsgHolder)
{
psMsgListTrav->dwMsgLength = HS_MESSAGE_LENGTH(PpsMsgIn->prgbStream);
psMsgListTrav->bMsgType = *PpsMsgIn->prgbStream;
psMsgListTrav->psMsgHolder = (uint8_t*)OCP_MALLOC( psMsgListTrav->dwMsgLength + OVERHEAD_LEN);
if(NULL == psMsgListTrav->psMsgHolder)
{
i4Status = (int32_t)OCP_FL_MALLOC_FAILURE;
break;
}
//lint --e{534} suppress "Return value is not required to be checked"
DtlsHS_PrepareMsgHeader((psMsgListTrav->psMsgHolder + (OVERHEAD_LEN - MSG_HEADER_LEN)), psMsgListTrav);
}
if(NULL == psMsgListTrav->psMsgMapPtr)
{
//Initialise Bit Map for message status
if(OCP_FL_OK != DtlsHS_MsgCompleteInit(psMsgListTrav->dwMsgLength, &psMsgListTrav->psMsgMapPtr))
{
i4Status = (int32_t)OCP_FL_ERROR;
break;
}
}
if(psMsgListTrav->dwMsgLength != HS_MESSAGE_LENGTH(PpsMsgIn->prgbStream))
{
i4Status = (int32_t)OCP_FL_INVALID_MSG_LENGTH;
break;
}
if(psMsgListTrav->wMsgSequence != HS_MESSAGE_SEQNUM(PpsMsgIn->prgbStream))
{
i4Status = (int32_t)OCP_FL_INVALID_MSG_SEQ;
break;
}
//Buffer the message
memcpy(psMsgListTrav->psMsgHolder+OVERHEAD_LEN+dwOffset, PpsMsgIn->prgbStream+LENGTH_HS_MSG_HEADER, dwFragLength);
//Update message status
//lint --e{534} suppress "Return value is not required to be checked"
DtlsHS_MsgUptBitMsk(dwOffset, dwFragLength, psMsgListTrav->psMsgMapPtr, psMsgListTrav->dwMsgLength);
}
// Check Message Completeness
if(OCP_FL_OK != DtlsHS_MsgCompleteCheck(psMsgListTrav->psMsgMapPtr, psMsgListTrav->dwMsgLength))
{
i4Status = (int32_t)OCP_FL_MSG_INCOMPLETE;
break;
}
// If message is completely received, change state to Complete
UPDATE_MSGSTATE(psMsgListTrav->eMsgState, eComplete);
DtlsHS_Update_OptList(PpsMessageLayer, psMsgListTrav->bMsgType, PeFlightID);
if(OCP_FL_OK != DtlsHS_MessageLimitCheck(psMsgListTrav))
{
i4Status = (int32_t)OCP_FL_MSG_MAXCOUNT;
break;
}
i4Status = OCP_FL_OK;
}
psMsgListTrav = psMsgListTrav->psNext;
}while(NULL != psMsgListTrav);
}while(0);
return i4Status;
}
/**
* Checks if the message type of the received message/ fragment belongs to the flight.
*
* \param[in] PbFlightID Flight ID.
* \param[in] PbMsgID Received Message type
*
* \retval #OCP_FL_OK Successful execution
* \retval #OCP_FL_MSG_NOT_IN_FLIGHT Received message is not in flight
*/
_STATIC_H int32_t DtlsHS_Flight_LimitChk(uint8_t PbFlightID, uint8_t PbMsgID)
{
int32_t i4Status = (int32_t)OCP_FL_MSG_NOT_IN_FLIGHT;
uint16_t* pwMsgList = NULL;
do
{
DtlsHS_GetFlightMsgInfo(PbFlightID, &pwMsgList);
while(0xFFFF != *pwMsgList)
{
if(PbMsgID == FLIGHTID(*pwMsgList))
{
i4Status = OCP_FL_OK;
break;
}
pwMsgList++;
}
}while(0);
return i4Status;
}
/**
* Sends the message to be processed to Security Chip.
*
* \param[in] PpsMessageList Pointer to the structure containing message linked list.
* \param[in] PpsMessageLayer Pointer to the structure containing message configuration information.
*
* \retval #OCP_ML_OK Successful execution
* \retval #OCP_ML_ERROR Failure in execution
* \retval #CMD_DEV_ERROR Command lib error
* \retval #OCP_FL_SEND_MSG_TO_OPTIGA_ERROR Message processing failed on Security Chip
*
*/
_STATIC_H int32_t DtlsHS_SendFlightToOptiga(sMsgInfo_d *PpsMessageList, const sMsgLyr_d* PpsMessageLayer)
{
int32_t i4Status = (int32_t)OCP_ML_ERROR;
sMessageLayer_d sMessageLayer;
sbBlob_d sMessage;
do
{
sMessageLayer.wOIDDevCertificate = PpsMessageLayer->wOIDDevCertificate;
sMessageLayer.pfGetUnixTIme = PpsMessageLayer->pfGetUnixTIme;
sMessageLayer.psConfigRL = PpsMessageLayer->psConfigRL;
sMessageLayer.wMaxPmtu = PpsMessageLayer->wMaxPmtu;
sMessageLayer.wSessionID = PpsMessageLayer->wSessionID;
while(NULL != PpsMessageList)
{
if(NULL != PpsMessageList->psMsgHolder)
{
sMessage.prgbStream = PpsMessageList->psMsgHolder;
sMessage.wLen = (uint16_t)PpsMessageList->dwMsgLength + OVERHEAD_LEN;
//Process the obtained message by sending the message to Security Chip
i4Status = MsgLayer_ProcessMessage((eMsgType_d)PpsMessageList->bMsgType, &sMessageLayer, &sMessage);
if((i4Status & (int32_t)DEV_ERROR_CODE_MASK) == (int32_t)CMD_DEV_ERROR)
{
break;
}
else if((int32_t)OCP_ML_OK != i4Status)
{
i4Status = (int32_t)OCP_FL_SEND_MSG_TO_OPTIGA_ERROR;
break;
}
}
UPDATE_MSGSTATE(PpsMessageList->eMsgState, eProcessed);
PpsMessageList = PpsMessageList->psNext;
}
}while(0);
return i4Status;
}
/**
* Resets the flight 2 node .
*
* \param[in,out] PpsThisFlight Pointer to the structure containing flight status.
*
*/
_STATIC_H void DtlsHS_ResetFlight2MsgNode(const sFlightStats_d* PpsThisFlight)
{
do
{
if(NULL != PpsThisFlight->psMessageList->psMsgHolder)
{
OCP_FREE(PpsThisFlight->psMessageList->psMsgHolder);
PpsThisFlight->psMessageList->psMsgHolder = NULL;
}
if(NULL != PpsThisFlight->psMessageList->psMsgMapPtr)
{
OCP_FREE(PpsThisFlight->psMessageList->psMsgMapPtr);
PpsThisFlight->psMessageList->psMsgMapPtr = NULL;
}
PpsThisFlight->psMessageList->eMsgState = ePartial;
}while(0);
}
/**
* Frees a node and all the pointers in it .
*
* \param[in] PpsMsgNode Pointer to the message node.
*
*/
_STATIC_H void DtlsHS_FreeMsgNode(sMsgInfo_d *PpsMsgNode)
{
if(NULL != PpsMsgNode->psMsgHolder)
{
OCP_FREE(PpsMsgNode->psMsgHolder);
PpsMsgNode->psMsgHolder = NULL;
}
if(NULL != PpsMsgNode->psMsgMapPtr)
{
OCP_FREE(PpsMsgNode->psMsgMapPtr);
PpsMsgNode->psMsgMapPtr = NULL;
}
OCP_FREE(PpsMsgNode);
}
/**
* Checks if message sequence number and length of received message/ fragment of flight4 is the same as the buffered one.
*
* \param[in] PbRxMsgType Message type of received message/ fragment.
* \param[in] PwRxMsgSeqNum Message sequence number of received message/ fragment.
* \param[in] PdwRxMsgLen Message sequence number of received message/ fragment.
* \param[in] PpsMsgList Pointer to list of messages in the flight.
*
* \retval #OCP_FL_OK Sequence number and message length of buffered message is same as re-received message/ fragment
* \retval #OCP_FL_ERROR Received message/ fragment can be ignored
*/
_STATIC_H int32_t DtlsHS_Flight4CheckBuffMsg(uint8_t PbRxMsgType, uint16_t PwRxMsgSeqNum, uint32_t PdwRxMsgLen, sMsgInfo_d *PpsMsgList)
{
int32_t i4Status = (int32_t)OCP_FL_ERROR;
sMsgInfo_d *psMsgListTrav = PpsMsgList;
do
{
if(psMsgListTrav->bMsgType == PbRxMsgType)
{
if((psMsgListTrav->wMsgSequence == PwRxMsgSeqNum) && (psMsgListTrav->dwMsgLength == PdwRxMsgLen))
{
i4Status = (int32_t)OCP_FL_OK;
break;
}
}
psMsgListTrav = psMsgListTrav->psNext;
}while(NULL != psMsgListTrav);
return i4Status;
}
/**
* Checks for flight4 completion.
*
* \param[in] PpsMsgList Pointer to message list of the flight.
*
* \retval #OCP_FL_OK Flight 4 is received completely
* \retval #OCP_FL_ERROR Flight 4 is not received completely
*/
_STATIC_H int32_t DtlsHS_Flight4ReRxCompl(sMsgInfo_d *PpsMsgList)
{
int32_t i4Status = (int32_t)OCP_FL_OK;
sMsgInfo_d *psMsgListTrav = PpsMsgList;
do
{
if(eProcessed != psMsgListTrav->eMsgState)
{
i4Status = (int32_t)OCP_FL_ERROR;
break;
}
psMsgListTrav = psMsgListTrav->psNext;
}while(NULL != psMsgListTrav);
return i4Status;
}
/**
* Updates bit map and sets the message state.
*
* \param[in] PbMsgID Message type of received message/ fragment.
* \param[in] PpsMsgList Pointer to message list of the flight.
* \param[in] PpsMessageLayer Pointer to the structure containing message configuration information.
*
* \retval #OCP_FL_OK Successful execution
* \retval #OCP_FL_ERROR Received message/ fragment can be ignored
*/
_STATIC_H int32_t DtlsHS_Flight4UpdateMsgStat(uint8_t PbMsgID, sMsgInfo_d *PpsMsgList, const sMsgLyr_d* PpsMessageLayer)
{
int32_t i4Status = (int32_t)OCP_FL_ERROR;
sMsgInfo_d *psMsgListTrav = PpsMsgList;
uint32_t dwOffset, dwFragLen;
dwOffset = HS_MESSAGE_FRAGOFFSET(PpsMessageLayer->sMsg.prgbStream);
dwFragLen = HS_MESSAGE_FRAGLEN(PpsMessageLayer->sMsg.prgbStream);
do
{
do
{
if(NULL != psMsgListTrav)
{
if(psMsgListTrav->bMsgType == PbMsgID)
{
i4Status = (int32_t)OCP_FL_OK;
break;
}
psMsgListTrav = psMsgListTrav->psNext;
}
}while(NULL != psMsgListTrav);
//lint --e{613} suppress "If 'psMsgListTrav' parameter is null then based on return code it doesnt enter the below path"
if(OCP_FL_OK == i4Status)
{
if(OCP_FL_OK != DtlsHS_MsgUptBitMsk(dwOffset, dwFragLen, psMsgListTrav->psMsgMapPtr, psMsgListTrav->dwMsgLength))
{
i4Status = (int32_t)OCP_FL_ERROR;
break;
}
// Check Message Completeness
if(OCP_FL_OK != DtlsHS_MsgCompleteCheck(psMsgListTrav->psMsgMapPtr, psMsgListTrav->dwMsgLength))
{
i4Status = (int32_t)OCP_FL_MSG_INCOMPLETE;
break;
}
UPDATE_MSGSTATE(psMsgListTrav->eMsgState, eProcessed);
if(OCP_FL_OK != DtlsHS_MessageLimitCheck(psMsgListTrav))
{
i4Status = (int32_t)OCP_FL_MSG_MAXCOUNT;
break;
}
}
}while(0);
return i4Status;
}
/**
* Clears the messages of a flight and resets the bit map.
*
* \param[in, out] PpsMsgList Pointer to list of messages.
*
*/
_STATIC_H void DtlsHS_Flight4ClearMsgsInList(sMsgInfo_d *PpsMsgList)
{
sMsgInfo_d *psMsgListTrav = PpsMsgList;
do
{
if(NULL!= psMsgListTrav->psMsgHolder)
{
OCP_FREE(psMsgListTrav->psMsgHolder);
psMsgListTrav->psMsgHolder = NULL;
}
if(NULL != psMsgListTrav->psMsgMapPtr)
{
if(OCP_FL_OK == DtlsHS_MsgClearBitMap(psMsgListTrav->psMsgMapPtr, psMsgListTrav->dwMsgLength))
{
UPDATE_MSGSTATE(psMsgListTrav->eMsgState, ePartial);
}
else
{
break;
}
}
psMsgListTrav = psMsgListTrav->psNext;
}while(NULL != psMsgListTrav);
}
/**
* Checks Message Sequence number of flight six messages.
*
* \param[in] PpsMessageLayer Pointer to the structure containing message configuration information.
* \param[in] PbMsgID Message Type of the received message/ fragment.
* \param[in] PwMsgSeqNum Message sequence number of received message.
*
* \retval #OCP_FL_OK Sequence number is correct
* \retval #OCP_FL_ERROR Sequence number is incorrect
*/
_STATIC_H int32_t DtlsHS_Flight6CheckMsgSeqNum(const sMsgLyr_d* PpsMessageLayer, uint8_t PbMsgID, uint16_t PwMsgSeqNum)
{
int32_t i4Status = (int32_t)OCP_FL_OK;
do
{
if((PbMsgID == (uint8_t)eServerFinished) && (PwMsgSeqNum != (uint16_t)PpsMessageLayer->dwRMsgSeqNum+1))
{
i4Status = (int32_t)OCP_FL_ERROR;
}
else if(PbMsgID == (uint8_t)eChangeCipherSpec)
{
i4Status = (int32_t)OCP_FL_OK;
}
}while(0);
return i4Status;
}
/**
* Searches the look-up table and returns the message descriptors of a flight.
*
* \param[in] PeFlightID Flight number.
* \param[in,out] PpwMessageList Pointer container to message descriptor.
*
*/
void DtlsHS_GetFlightMsgInfo(uint8_t PeFlightID, uint16_t** PpwMessageList)
{
int32_t i4Status = (int32_t)OCP_FL_ERROR;
uint8_t bIndex;
do
{
for(bIndex = 0; bIndex < OCP_FLIGHT_TABLE_MAX_SIZE; bIndex++)
{
if(((rgsSFlightInfo[bIndex].wFlightDesc) & 0xFF) == (uint8_t)PeFlightID)
{
*PpwMessageList = (uint16_t*)&(rgsSFlightInfo[bIndex].wMsgTypes[0]);
i4Status = (int32_t)OCP_FL_OK;
break;
}
}
if((int32_t)OCP_FL_ERROR == i4Status)
{
for(bIndex = 0; bIndex < OCP_FLIGHT_TABLE_MAX_SIZE; bIndex++)
{
if(((rgsRFlightInfo[bIndex].wFlightDesc) & 0xFF) == (uint8_t)PeFlightID)
{
*PpwMessageList = (uint16_t*)&(rgsRFlightInfo[bIndex].wMsgTypes[0]);
break;
}
}
}
}while(0);
}
/**
* Initialises flight node to default parameters.
*
* \param[in,out] PpsFlightNode Pointer to flight node
* \param[in] PbLastProcFlight Last processed flight ID
*
* \retval #OCP_HL_OK Successful Execution
* \retval #OCP_HL_ERROR Failure Execution
*/
int32_t DtlsHS_FlightNodeInit(sFlightDetails_d* PpsFlightNode, uint8_t PbLastProcFlight)
{
int32_t i4Status = (int32_t)OCP_FL_OK;
do
{
PpsFlightNode->psNext = NULL;
if(OCP_FL_OK != DtlsHS_GetFlightDescriptor(PbLastProcFlight+1, &PpsFlightNode->wFlightDecp))
{
i4Status = (int32_t)OCP_FL_ERROR;
break;
}
if(OCP_FL_OK != DtlsHS_GetFlightHandler(FLIGHTID(PpsFlightNode->wFlightDecp), &PpsFlightNode->pFlightHndlr))
{
i4Status = (int32_t)OCP_FL_ERROR;
break;
}
PpsFlightNode->sFlightStats.psMessageList = NULL;
UPDATE_FSTATE(PpsFlightNode->sFlightStats.bFlightState, (uint8_t)efInit);
}while(0);
return i4Status;
}
/**
* Gets the Flight type for the corresponding message type.
*
* \param[in] PbMsgType Message type
* \param[in,out] PpFlightID Pointer to the flight number
*
* \retval #OCP_FL_OK Successful Execution
* \retval #OCP_FL_ERROR Failure Execution
*/
int32_t DtlsHS_GetFlightID(uint8_t PbMsgType, uint8_t* PpFlightID)
{
int32_t i4Status = (int32_t)OCP_FL_ERROR;
uint8_t bFlightIndex,bMsgIndex ;
do
{
for(bFlightIndex = 0; bFlightIndex < OCP_FLIGHT_TABLE_MAX_SIZE; bFlightIndex++)
{
bMsgIndex = 0;
while(MSG_ID(rgsRFlightInfo[bFlightIndex].wMsgTypes[bMsgIndex]) != 0xFF)
{
if(MSG_ID(rgsRFlightInfo[bFlightIndex].wMsgTypes[bMsgIndex]) == PbMsgType)
{
*PpFlightID = FLIGHTID(rgsRFlightInfo[bFlightIndex].wFlightDesc);
i4Status = (int32_t)OCP_FL_OK;
break;
}
bMsgIndex++;
}
if((int32_t)OCP_FL_OK == i4Status)
{
break;
}
}
}while(0);
return i4Status;
}
/**
* Checks whether the received message belongs to the expected flight.
*
* \param[in] PbLastProcFlight Last processed flight number
* \param[in,out] PpsBlobMessage Pointer to the Blob containing record
* \param[in] PpsMessageLayer Pointer to the structure containing message layer information
*
* \retval #OCP_FL_OK Successful Execution
* \retval #OCP_FL_ERROR Failure Execution
*/
int32_t DtlsHS_MsgCheck(uint8_t PbLastProcFlight, const sbBlob_d* PpsBlobMessage, const sMsgLyr_d* PpsMessageLayer)
{
uint8_t bFlightA = 0;
uint8_t bFlightB = 0;
int32_t i4Status = (int32_t)OCP_FL_OK;
uint8_t bMsgType;
uint32_t dwTotalMsgLen = 0;
uint8_t bFirstMsgFlightID = 0;
uint8_t bMsgFlightID;
sbBlob_d sMsgIn;
do
{
//Change cipher spec record is received
if(PpsMessageLayer->psConfigRL->sRL.bRecvCCSRecord == CCS_RECORD_RECV)
{
if((PpsMessageLayer->eFlight != eFlight5) && (PpsMessageLayer->eFlight != eFlight6))
{
//CCS message doesn't belongs to flight 6
i4Status = (int32_t)OCP_FL_MSG_NOT_IN_FLIGHT;
PpsMessageLayer->psConfigRL->sRL.bRecvCCSRecord = CCS_RECORD_NOTRECV;
}
break;
}
//Minimum length check
if(LENGTH_HS_MSG_HEADER > PpsBlobMessage->wLen)
{
i4Status = (int32_t)OCP_HL_INVALID_LENGTH;
break;
}
sMsgIn.prgbStream = PpsBlobMessage->prgbStream;
sMsgIn.wLen = PpsBlobMessage->wLen;
//Check for default flight state
if((uint8_t)PpsMessageLayer->eFlight == PbLastProcFlight)
{
if((PbLastProcFlight == 1) || (PbLastProcFlight == 3))
{
bFlightA = (uint8_t)eFlight2;
bFlightB = (uint8_t)eFlight4;
}
else if(PbLastProcFlight == 5)
{
bFlightA = (uint8_t)eFlight4;
bFlightB = (uint8_t)eFlight6;
}
bMsgType = *(sMsgIn.prgbStream);
//Get the flight number to which the message belongs
if(OCP_FL_OK != DtlsHS_GetFlightID(bMsgType, &bFirstMsgFlightID))
{
i4Status = (int32_t)OCP_FL_MSG_NOT_LISTED;
break;
}
//Check if the flight number belongs to the expected the flight
if((bFlightA != bFirstMsgFlightID) && (bFlightB != bFirstMsgFlightID))
{
i4Status = (int32_t)OCP_FL_MSG_NOT_IN_FLIGHT;
break;
}
//Header validation
i4Status = DtlsHS_ProcHeader(sMsgIn);
if(OCP_HL_OK == i4Status)
{
i4Status = (int32_t)OCP_FL_OK;
}
else
{
break;
}
dwTotalMsgLen = Utility_GetUint24(sMsgIn.prgbStream + OFFSET_HS_MSG_FRAGLEN);
sMsgIn.prgbStream += dwTotalMsgLen + LENGTH_HS_MSG_HEADER;
sMsgIn.wLen -= (uint16_t)dwTotalMsgLen + LENGTH_HS_MSG_HEADER;
}
//For multiple messages in a record
while(sMsgIn.wLen != 0)
{
bMsgType = *(sMsgIn.prgbStream);
//Minimum length check
if(LENGTH_HS_MSG_HEADER > sMsgIn.wLen)
{
i4Status = (int32_t)OCP_HL_INVALID_LENGTH;
break;
}
//Get the flight number to which the message belongs
if(OCP_FL_OK != DtlsHS_GetFlightID(bMsgType, &bMsgFlightID))
{
i4Status = (int32_t)OCP_FL_MSG_NOT_LISTED;
break;
}
if((uint8_t)PpsMessageLayer->eFlight == PbLastProcFlight)
{
if(bFirstMsgFlightID != bMsgFlightID)
{
i4Status = (int32_t)OCP_FL_MSG_NOT_IN_FLIGHT;
break;
}
}
else
{
if(PpsMessageLayer->eFlight != (eFlight_d)bMsgFlightID)
{
i4Status = (int32_t)OCP_FL_MSG_NOT_IN_FLIGHT;
break;
}
}
i4Status = DtlsHS_ProcHeader(sMsgIn);
if(OCP_HL_OK == i4Status)
{
i4Status = (int32_t)OCP_FL_OK;
}
else
{
break;
}
dwTotalMsgLen = Utility_GetUint24(sMsgIn.prgbStream + OFFSET_HS_MSG_FRAGLEN);
sMsgIn.wLen -= (uint16_t)dwTotalMsgLen + LENGTH_HS_MSG_HEADER;
if(sMsgIn.wLen != 0)
{
sMsgIn.prgbStream += dwTotalMsgLen + LENGTH_HS_MSG_HEADER;
}
}
}while(0);
return i4Status;
}
/**
* Flight one handler to process flight 1 messages .
*
* \param[in] PbLastProcFlight Last processed flight.
* \param[in,out] PpsThisFlight Pointer to structure containing flight1 status.
* \param[in] PpsMessageLayer Pointer to the structure containing message configuration information.
*
* \retval #OCP_FL_OK Successful execution
* \retval #OCP_FL_MSG_ERROR Failure in execution
* \retval #OCP_FL_MALLOC_FAILURE Malloc failure
* \retval #OCP_FL_GET_MSG_FROM_OPTIGA_ERROR Error from Security Chip
* \retval #OCP_FL_FLIGHTSEND_ERROR Error while sending flight to Security Chip
*/
//lint --e{818} suppress "This is ignored as same flight handler pointer is used for both send and receive"
int32_t DtlsHS_Flight1Handler(uint8_t PbLastProcFlight, sFlightStats_d* PpsThisFlight, sMsgLyr_d* PpsMessageLayer)
{
int32_t i4Status = (int32_t)OCP_FL_OK;
sMsgInfo_d* psMsgListTrav = NULL;
uint16_t *pwMsgIDList = NULL;
do
{
if(((uint8_t)efInit == PpsThisFlight->bFlightState) && ((uint8_t)eFlight0 == PbLastProcFlight))
{
//Generate List of Messages of this flight
//create list of messages of this flight and call Command lib to get messages from Security Chip
DtlsHS_GetFlightMsgInfo((uint8_t)eFlight1, &pwMsgIDList);
while(0xFF != MSG_ID(*pwMsgIDList))
{
psMsgListTrav = (sMsgInfo_d*)OCP_MALLOC(sizeof(sMsgInfo_d));
if(NULL == psMsgListTrav)
{
i4Status = (int32_t)OCP_FL_MALLOC_FAILURE;
break;
}
psMsgListTrav->bMsgType = MSG_ID(*pwMsgIDList);
psMsgListTrav->eMsgState = ePartial;
psMsgListTrav->psNext = NULL;
psMsgListTrav->psMsgMapPtr = NULL;
psMsgListTrav->psMsgHolder = NULL;
DtlsHS_InsertMsgNode(&PpsThisFlight->psMessageList, psMsgListTrav);
pwMsgIDList++;
}
if((int32_t)OCP_FL_OK == i4Status)
{
UPDATE_FSTATE(PpsThisFlight->bFlightState, (uint8_t)efReady);
}
}
else if(((uint8_t)eFlight1 == PbLastProcFlight+1) || ((uint8_t)eFlight1 == PbLastProcFlight))
{
if((uint8_t)efReady == PpsThisFlight->bFlightState)
{
//Get Message from Security Chip and Send to Server
psMsgListTrav = PpsThisFlight->psMessageList;
while(NULL != psMsgListTrav)
{
if(ePartial == psMsgListTrav->eMsgState)
{
i4Status = DtlsHS_SInit_MessageNode(psMsgListTrav, PpsMessageLayer);
if((i4Status & (int32_t)DEV_ERROR_CODE_MASK) == (int32_t)CMD_DEV_ERROR)
{
break;
}
else if((int32_t)OCP_FL_OK != i4Status)
{
i4Status = (int32_t)OCP_FL_GET_MSG_FROM_OPTIGA_ERROR;
break;
}
psMsgListTrav->eMsgState = eComplete;
}
if(OCP_HL_OK != DtlsHS_FSendMessage(psMsgListTrav, PpsMessageLayer))
{
i4Status = (int32_t)OCP_FL_FLIGHTSEND_ERROR;
break;
}
psMsgListTrav->eMsgState = eProcessed;
psMsgListTrav = psMsgListTrav->psNext;
}
if((int32_t)OCP_FL_OK == i4Status)
{
PpsMessageLayer->eFlight = eFlight1;
UPDATE_FSTATE(PpsThisFlight->bFlightState, (uint8_t)efTransmitted);
}
}
else if((uint8_t)efReTransmit == PpsThisFlight->bFlightState)
{
psMsgListTrav = PpsThisFlight->psMessageList;
//If already transmitted, now retransmit
while(NULL != psMsgListTrav)
{
if(OCP_HL_OK != DtlsHS_FSendMessage(psMsgListTrav, PpsMessageLayer))
{
i4Status = (int32_t)OCP_FL_FLIGHTSEND_ERROR;
break;
}
psMsgListTrav = psMsgListTrav->psNext;
}
if((int32_t)OCP_FL_OK == i4Status)
{
UPDATE_FSTATE(PpsThisFlight->bFlightState, (uint8_t)efTransmitted);
}
}
}
else
{
PpsThisFlight->bFlightState = (uint8_t)efDone;
break;
}
}while(0);
return i4Status;
}
/**
* Flight three handler to process flight 3 message.
*
* \param[in] PbLastProcFlight Last processed flight.
* \param[in,out] PpsThisFlight Pointer to structure containing flight3 status.
* \param[in] PpsMessageLayer Pointer to the structure containing message configuration information.
*
* \retval #OCP_FL_OK Successful execution
* \retval #OCP_FL_MSG_ERROR Failure in execution
* \retval #OCP_FL_MALLOC_FAILURE Malloc failure
* \retval #OCP_FL_GET_MSG_FROM_OPTIGA_ERROR Error from Security Chip
* \retval #OCP_FL_FLIGHTSEND_ERROR Error while sending flight to Security Chip
*/
int32_t DtlsHS_Flight3Handler(uint8_t PbLastProcFlight, sFlightStats_d* PpsThisFlight, sMsgLyr_d* PpsMessageLayer)
{
int32_t i4Status = (int32_t)OCP_FL_OK;
sMsgInfo_d* psMsgListTrav = NULL;
uint16_t *pwMsgIDList = NULL;
uint8_t bMsgType = 0;
do
{
if(((uint8_t)efInit == PpsThisFlight->bFlightState) && ((uint8_t)eFlight2 == PbLastProcFlight))
{
//create list of messages of this flight and call Command lib to get messages from Security Chip
DtlsHS_GetFlightMsgInfo((uint8_t)eFlight3, &pwMsgIDList);
while(0xFF != MSG_ID(*pwMsgIDList))
{
psMsgListTrav = (sMsgInfo_d*)OCP_MALLOC(sizeof(sMsgInfo_d));
if(NULL == psMsgListTrav)
{
i4Status = (int32_t)OCP_FL_MALLOC_FAILURE;
break;
}
psMsgListTrav->bMsgType = MSG_ID(*pwMsgIDList);
psMsgListTrav->eMsgState = ePartial;
psMsgListTrav->psNext = NULL;
psMsgListTrav->psMsgMapPtr = NULL;
psMsgListTrav->psMsgHolder = NULL;
DtlsHS_InsertMsgNode(&PpsThisFlight->psMessageList, psMsgListTrav);
pwMsgIDList++;
}
if((int32_t)OCP_FL_OK == i4Status)
{
UPDATE_FSTATE(PpsThisFlight->bFlightState, (uint8_t)efReady);
}
}
else if((uint8_t)eFlight3 == PbLastProcFlight+1)
{
if(((uint8_t)efReady == PpsThisFlight->bFlightState) || ((uint8_t)efTransmitted == PpsThisFlight->bFlightState))
{
//Get Message from Security Chip and Send to Server
psMsgListTrav = PpsThisFlight->psMessageList;
if((uint8_t)efTransmitted == PpsThisFlight->bFlightState)
{
OCP_FREE(psMsgListTrav->psMsgHolder);
psMsgListTrav->psMsgHolder = NULL;
psMsgListTrav->eMsgState = ePartial;
}
while(NULL != psMsgListTrav)
{
if(ePartial == psMsgListTrav->eMsgState)
{
bMsgType = psMsgListTrav->bMsgType;
psMsgListTrav->bMsgType = (uint8_t)eClientHelloWithCookie;
i4Status = DtlsHS_SInit_MessageNode(psMsgListTrav, PpsMessageLayer);
psMsgListTrav->bMsgType = bMsgType;
if((i4Status & (int32_t)DEV_ERROR_CODE_MASK) == (int32_t)CMD_DEV_ERROR)
{
break;
}
else if((int32_t)OCP_FL_OK != i4Status)
{
i4Status = (int32_t)OCP_FL_GET_MSG_FROM_OPTIGA_ERROR;
break;
}
psMsgListTrav->eMsgState = eComplete;
}
if(OCP_HL_OK != DtlsHS_FSendMessage(psMsgListTrav, PpsMessageLayer))
{
i4Status = (int32_t)OCP_FL_FLIGHTSEND_ERROR;
break;
}
psMsgListTrav->eMsgState = eProcessed;
psMsgListTrav = psMsgListTrav->psNext;
}
if(OCP_FL_OK == i4Status)
{
PpsMessageLayer->eFlight = eFlight3;
UPDATE_FSTATE(PpsThisFlight->bFlightState, (uint8_t)efTransmitted);
}
}
}
else if((uint8_t)eFlight3 == PbLastProcFlight)
{
if((uint8_t)efReTransmit == PpsThisFlight->bFlightState)
{
psMsgListTrav = PpsThisFlight->psMessageList;
//If already transmitted, now retransmit
while(NULL != psMsgListTrav)
{
if(OCP_HL_OK != DtlsHS_FSendMessage(psMsgListTrav, PpsMessageLayer))
{
i4Status = (int32_t)OCP_FL_FLIGHTSEND_ERROR;
break;
}
psMsgListTrav = psMsgListTrav->psNext;
}
if(OCP_FL_OK == i4Status)
{
UPDATE_FSTATE(PpsThisFlight->bFlightState, (uint8_t)efTransmitted);
}
}
}
else
{
PpsThisFlight->bFlightState = (uint8_t)efDone;
break;
}
}while(0);
return i4Status;
}
/**
* Flight five handler to process flight 5 messages .
*
* \param[in] PbLastProcFlight Last processed flight.
* \param[in,out] PpsThisFlight Pointer to structure containing flight5 status.
* \param[in] PpsMessageLayer Pointer to the structure containing message configuration information.
*
* \retval #OCP_FL_OK Successful execution
* \retval #OCP_FL_MSG_ERROR Failure in execution
* \retval #OCP_FL_MALLOC_FAILURE Malloc failure
* \retval #OCP_FL_GET_MSG_FROM_OPTIGA_ERROR Error from Security Chip
* \retval #OCP_FL_FLIGHTSEND_ERROR Error while sending flight to Security Chip
*/
//lint --e{818} suppress "This is ignored as same flight handler pointer is used for both send and receive"
int32_t DtlsHS_Flight5Handler(uint8_t PbLastProcFlight, sFlightStats_d* PpsThisFlight, sMsgLyr_d* PpsMessageLayer)
{
int32_t i4Status = (int32_t)OCP_FL_OK;
sMsgInfo_d* psMsgListTrav = NULL;
uint16_t *pwMsgIDList = NULL;
do
{
if(((uint8_t)efInit == PpsThisFlight->bFlightState) && ((uint8_t)eFlight4 == PbLastProcFlight))
{
//create list of messages of this flight and call Command lib to get messages from Security Chip
DtlsHS_GetFlightMsgInfo((uint8_t)eFlight5, &pwMsgIDList);
while(0xFF != MSG_ID(*pwMsgIDList))
{
if(OCP_FL_OK == DtlsHS_Flight5_CheckOptMsg(MSG_ID(*pwMsgIDList), &(PpsMessageLayer->rgbOptMsgList[0]), PpsMessageLayer))
{
psMsgListTrav = (sMsgInfo_d*)OCP_MALLOC(sizeof(sMsgInfo_d));
if(NULL == psMsgListTrav)
{
i4Status = (int32_t)OCP_FL_MALLOC_FAILURE;
break;
}
psMsgListTrav->bMsgType = MSG_ID(*pwMsgIDList);
psMsgListTrav->eMsgState = ePartial;
psMsgListTrav->psNext = NULL;
psMsgListTrav->psMsgMapPtr = NULL;
psMsgListTrav->psMsgHolder = NULL;
DtlsHS_AddMsgNode(&PpsThisFlight->psMessageList, psMsgListTrav);
}
pwMsgIDList++;
}
if((int32_t)OCP_FL_OK == i4Status)
{
UPDATE_FSTATE(PpsThisFlight->bFlightState, (uint8_t)efReady);
}
}
else if(((uint8_t)eFlight5 == PbLastProcFlight+1) || ((uint8_t)eFlight5 == PbLastProcFlight))
{
if((uint8_t)efReady == PpsThisFlight->bFlightState)
{
//Get Message from Security Chip and Send to Server
psMsgListTrav = PpsThisFlight->psMessageList;
while(NULL != psMsgListTrav)
{
if(ePartial == psMsgListTrav->eMsgState)
{
if((uint8_t)eChangeCipherSpec == psMsgListTrav->bMsgType)
{
i4Status = DtlsHS_SInit_ChangeCipherSpec(psMsgListTrav);
}
else
{
i4Status = DtlsHS_SInit_MessageNode(psMsgListTrav, PpsMessageLayer);
}
if((i4Status & (int32_t)DEV_ERROR_CODE_MASK) == (int32_t)CMD_DEV_ERROR)
{
break;
}
else if((int32_t)OCP_FL_OK != i4Status)
{
i4Status = (int32_t)OCP_FL_GET_MSG_FROM_OPTIGA_ERROR;
break;
}
psMsgListTrav->eMsgState = eComplete;
}
if(OCP_HL_OK != DtlsHS_FSendMessage(psMsgListTrav, PpsMessageLayer))
{
i4Status = (int32_t)OCP_FL_FLIGHTSEND_ERROR;
break;
}
psMsgListTrav->eMsgState = eProcessed;
psMsgListTrav = psMsgListTrav->psNext;
}
if((int32_t)OCP_FL_OK == i4Status)
{
PpsMessageLayer->eFlight = eFlight5;
UPDATE_FSTATE(PpsThisFlight->bFlightState, (uint8_t)efTransmitted);
}
}
else if(((uint8_t)efReTransmit == PpsThisFlight->bFlightState) || ((uint8_t)efTransmitted == PpsThisFlight->bFlightState))
{
PpsMessageLayer->psConfigRL->sRL.fRetransmit = TRUE;
psMsgListTrav = PpsThisFlight->psMessageList;
//If already transmitted, now retransmit
while(NULL != psMsgListTrav)
{
if(OCP_HL_OK != DtlsHS_FSendMessage(psMsgListTrav, PpsMessageLayer))
{
i4Status = (int32_t)OCP_FL_FLIGHTSEND_ERROR;
break;
}
psMsgListTrav = psMsgListTrav->psNext;
}
if((int32_t)OCP_FL_OK == i4Status)
{
UPDATE_FSTATE(PpsThisFlight->bFlightState, (uint8_t)efTransmitted);
}
}
}
}while(0);
return i4Status;
}
/**
* Validates the sequence number of message/ fragment received of flight 2.
*
* \param[in] PbRxMsgID Message type of the received message/ fragment.
* \param[in] PwRxMsgSeqNum Message sequence number of the received message/ fragment.
* \param[in] PpsMessageList Pointer to list of messages.
*
* \retval #OCP_FL_OK Successful Execution
* \retval #OCP_FL_INVALID_MSG_SEQNUM Sequence number does not match to buffered fragment sequence number
*/
int32_t DtlsHS_Flight2CheckMsgSeqNum(uint8_t PbRxMsgID, uint16_t PwRxMsgSeqNum, const sMsgInfo_d *PpsMessageList)
{
int32_t i4Status = (int32_t)OCP_FL_OK;
do
{
if(PwRxMsgSeqNum > 1)
{
i4Status = (int32_t)OCP_FL_INVALID_MSG_SEQNUM;
break;
}
while(NULL != PpsMessageList)
{
if(PpsMessageList->bMsgType == PbRxMsgID)
{
if(PpsMessageList->wMsgSequence != PwRxMsgSeqNum)
{
i4Status = (int32_t)OCP_FL_INVALID_MSG_SEQNUM;
break;
}
}
PpsMessageList = PpsMessageList->psNext;
}
}while(0);
return i4Status;
}
/**
* Flight two handler to process flight 2 messages.
*
* \param[in] PbLastProcFlight Last processed flight.
* \param[in,out] PpsThisFlight Pointer to the structure containing flight2 status.
* \param[in] PpsMessageLayer Pointer to the structure containing message configuration information.
*
* \retval #OCP_FL_OK Successful execution
* \retval #OCP_FL_MSG_ERROR Failure in execution
* \retval #OCP_FL_MALLOC_FAILURE Memory allocation failure
* \retval #OCP_FL_INVALID_MSG_SEQNUM Invalid Message sequence number
* \retval #OCP_FL_MSG_NOT_IN_FLIGHT Message doesn't belong to current flight
* \retval #OCP_FL_RXING Message is not yet completely received
*/
//lint --e{818} suppress "This is ignored as same flight handler pointer is used for both send and receive"
int32_t DtlsHS_Flight2Handler(uint8_t PbLastProcFlight, sFlightStats_d* PpsThisFlight, sMsgLyr_d* PpsMessageLayer)
{
int32_t i4Status = (int32_t)OCP_FL_OK;
uint16_t bMsgSeqNum;
uint8_t bMsgID;
sMsgInfo_d* psMsgListTrav = NULL;
uint16_t wFlightLastMsgSeqNum = 0xFFFF;
do
{
//Check Message/ Fragment
//Optional Message Check
//Check Message Sequence Number
//Buffer the message/ De-Fragmentation()
//Message Completeness()
//Send to Security Chip for Processing()
if((uint8_t)efInit == PpsThisFlight->bFlightState)
{
PpsThisFlight->bFlightState = (uint8_t)efReady;
break;
}
else if((PpsThisFlight->bFlightState == (uint8_t)efReady) || (PpsThisFlight->bFlightState == (uint8_t)efProcessed) || (PpsThisFlight->bFlightState == (uint8_t)efReReceive))
{
if(PpsThisFlight->bFlightState == (uint8_t)efProcessed)
{
PpsThisFlight->bFlightState = (uint8_t)efReReceive;
}
bMsgSeqNum = HS_MESSAGE_SEQNUM(PpsMessageLayer->sMsg.prgbStream);
bMsgID = HS_MESSAGE_TYPE(PpsMessageLayer->sMsg.prgbStream);
if(OCP_FL_OK != DtlsHS_Flight_LimitChk((uint8_t)eFlight2,bMsgID))
{
i4Status = (int32_t)OCP_FL_MSG_NOT_IN_FLIGHT;
break;
}
if(OCP_FL_OK != FLIGHT_IDLIMITCHK(1, PbLastProcFlight, 3))
{
i4Status = (int32_t)OCP_FL_INVALID_PROCFLIGHT;
break;
}
if(OCP_FL_OK != DtlsHS_Flight2CheckMsgSeqNum(bMsgID, bMsgSeqNum, PpsThisFlight->psMessageList))
{
i4Status = (int32_t)OCP_FL_INVALID_MSG_SEQNUM;
break;
}
i4Status = DtlsHS_FlightMsgChkAndBuffer(PpsThisFlight->psMessageList, bMsgID, &(PpsMessageLayer->sMsg), PpsMessageLayer, (uint8_t)eFlight2);
if(((int32_t)OCP_FL_ERROR == i4Status) || ((int32_t)OCP_FL_MSG_MAXCOUNT == i4Status) || ((int32_t)OCP_FL_MALLOC_FAILURE == i4Status))
{
break;
}
PpsMessageLayer->eFlight = eFlight2;
if((int32_t)OCP_FL_MSG_NODE_NOT_AVAIL == i4Status)
{
// Buffer the message
psMsgListTrav = (sMsgInfo_d*)OCP_MALLOC(sizeof(sMsgInfo_d));
if(NULL == psMsgListTrav)
{
i4Status = (int32_t)OCP_FL_MALLOC_FAILURE;
break;
}
psMsgListTrav->eMsgState = ePartial;
psMsgListTrav->psNext = NULL;
psMsgListTrav->psMsgMapPtr = NULL;
psMsgListTrav->psMsgHolder = (uint8_t*)OCP_MALLOC(HS_MESSAGE_LENGTH(PpsMessageLayer->sMsg.prgbStream) + OVERHEAD_LEN);
if(NULL == psMsgListTrav->psMsgHolder)
{
DtlsHS_FreeMsgNode(psMsgListTrav);
i4Status = (int32_t)OCP_FL_MALLOC_FAILURE;
break;
}
i4Status = DtlsHS_RInit_MessageNode(psMsgListTrav, PpsMessageLayer);
if(((int32_t)OCP_FL_OK != i4Status) && ((int32_t)OCP_FL_MSG_INCOMPLETE != i4Status))
{
DtlsHS_FreeMsgNode(psMsgListTrav);
break;
}
DtlsHS_InsertMsgNode(&PpsThisFlight->psMessageList, psMsgListTrav);
}
//Check Flight Completeness
if(NULL != PpsThisFlight->psMessageList)
{
if((eComplete != PpsThisFlight->psMessageList->eMsgState) && (eProcessed != PpsThisFlight->psMessageList->eMsgState))
{
i4Status = (int32_t)OCP_FL_RXING;
break;
}
}
else
{
i4Status = (int32_t)OCP_FL_ERROR;
break;
}
PpsThisFlight->bFlightState = (uint8_t)efReceived;
//Send to Security Chip For Processing
i4Status = DtlsHS_SendFlightToOptiga(PpsThisFlight->psMessageList, PpsMessageLayer);
if(OCP_ML_OK != i4Status)
{
break;
}
//Update Flight Status
PpsThisFlight->bFlightState = (uint8_t)efProcessed;
DtlsHS_ResetFlight2MsgNode(PpsThisFlight);
DtlsHS_FlightGetLastMsgSeqNum(PpsThisFlight->psMessageList, &wFlightLastMsgSeqNum);
UPDATE_RX_MSGSEQNUM(PpsMessageLayer->dwRMsgSeqNum, wFlightLastMsgSeqNum);
}
i4Status = OCP_FL_OK;
}while(0);
return i4Status;
}
/**
* Checks if message sequence number of received message/ fragment of flight4 is correct.
*
* \param[in] PpsMessageLayer Pointer to the structure containing message configuration information.
* \param[in] PbRxMsgID Message type of received message/ fragment.
* \param[in] PwRxMsgSeqNum Message sequence number of received message/ fragment.
*
* \retval #OCP_FL_OK Successful execution
* \retval #OCP_FL_ERROR Message Sequence number incorrect
*/
int32_t DtlsHS_Flight4CheckMsgSeqNum(const sMsgLyr_d* PpsMessageLayer, uint8_t PbRxMsgID, uint16_t PwRxMsgSeqNum)
{
int32_t i4Status = (int32_t)OCP_FL_ERROR;
uint16_t *pwFlightMsgs = NULL;
uint32_t dwPrevFlightMsgSeq, dwLastFlightSeqNum ;
uint8_t bOptMsgCount = 0;
uint8_t bLoopCount, bIndex, bMandtryMsgCount = 0;
do
{
dwLastFlightSeqNum = PpsMessageLayer->dwRMsgSeqNum;
dwPrevFlightMsgSeq = PpsMessageLayer->dwRMsgSeqNum;
if(dwPrevFlightMsgSeq == 0xFFFFFFFF)
{
bLoopCount = 2;
}
else
{
bLoopCount = 1;
}
for(bIndex = 0; bIndex < bLoopCount; bIndex++)
{
DtlsHS_GetFlightMsgInfo((uint8_t)eFlight4, &pwFlightMsgs);
do
{
if(IsMandatory(*pwFlightMsgs))
{
bMandtryMsgCount++;
}
else
{
bOptMsgCount++;
}
if(MSG_ID(*pwFlightMsgs) == PbRxMsgID)
{
if(((dwLastFlightSeqNum+bMandtryMsgCount+bOptMsgCount) == PwRxMsgSeqNum) || ((dwLastFlightSeqNum+bMandtryMsgCount) == PwRxMsgSeqNum))
{
i4Status = (int32_t)OCP_FL_OK;
break;
}
}
}while(0xFFFF != *(++pwFlightMsgs));
if((int32_t)OCP_FL_OK == i4Status)
{
break;
}
dwLastFlightSeqNum = dwPrevFlightMsgSeq + 1;
bMandtryMsgCount = 0;
bOptMsgCount = 0;
}
}while(FALSE);
return i4Status;
}
/**
* Flight four handler to process flight 4 messages.
*
* \param[in] PbLastProcFlight Last processed flight.
* \param[in,out] PpsThisFlight Pointer to the structure containing flight4 status.
* \param[in] PpsMessageLayer Pointer to the structure containing message configuration information.
*
* \retval #OCP_FL_OK Successful execution
* \retval #OCP_FL_MSG_ERROR Failure in execution
* \retval #OCP_FL_MALLOC_FAILURE Memory allocation failure
* \retval #OCP_FL_INVALID_MSG_SEQNUM Invalid Message sequence number
* \retval #OCP_FL_MSG_NOT_IN_FLIGHT Message doesn't belong to current flight
* \retval #OCP_FL_RXING Message is not yet completely received
* \retval #OCP_FL_MSG_MAXCOUNT Message is received at least 6 times
*/
int32_t DtlsHS_Flight4Handler(uint8_t PbLastProcFlight, sFlightStats_d* PpsThisFlight, sMsgLyr_d* PpsMessageLayer)
{
int32_t i4Status = (int32_t)OCP_FL_OK;
sMsgInfo_d* psMsgListTrav = NULL;
uint8_t bMsgID;
uint16_t wMsgSeqNum;
uint32_t dwMsgLen;
uint16_t wFlightLastMsgSeqNum = 0xFFFF;
do
{
//Check Message/ Fragment
//Optional Message Check
//Check Message Sequence Number
//Buffer the message/ De-Fragmentation()
//Message Completeness()
//Send to Security Chip for Processing()
if((uint8_t)efInit == PpsThisFlight->bFlightState)
{
PpsThisFlight->bFlightState = (uint8_t)efReady;
break;
}
else if((uint8_t)efReady == PpsThisFlight->bFlightState)
{
bMsgID = HS_MESSAGE_TYPE(PpsMessageLayer->sMsg.prgbStream);
wMsgSeqNum = HS_MESSAGE_SEQNUM(PpsMessageLayer->sMsg.prgbStream);
dwMsgLen = HS_MESSAGE_LENGTH(PpsMessageLayer->sMsg.prgbStream);
if(OCP_FL_OK != DtlsHS_Flight_LimitChk((uint8_t)eFlight4,bMsgID))
{
i4Status = (int32_t)OCP_FL_MSG_NOT_IN_FLIGHT;
break;
}
if(0x00 != PpsMessageLayer->psConfigRL->sRL.bDecRecord)
{
i4Status = (int32_t)OCP_FL_MSG_NOT_IN_FLIGHT;
break;
}
if(OCP_FL_OK != FLIGHT_IDLIMITCHK(1, PbLastProcFlight, 5))
{
i4Status = (int32_t)OCP_FL_INVALID_PROCFLIGHT;
break;
}
if(OCP_FL_OK != DtlsHS_Flight4CheckMsgSeqNum(PpsMessageLayer, bMsgID, wMsgSeqNum))
{
i4Status = (int32_t)OCP_FL_INVALID_MSG_SEQNUM;
break;
}
i4Status = DtlsHS_FlightMsgChkAndBuffer(PpsThisFlight->psMessageList, bMsgID, &(PpsMessageLayer->sMsg), PpsMessageLayer, (uint8_t)eFlight4);
if(((int32_t)OCP_FL_ERROR == i4Status) || ((int32_t)OCP_FL_MSG_MAXCOUNT == i4Status) || ((int32_t)OCP_FL_MALLOC_FAILURE == i4Status))
{
break;
}
PpsMessageLayer->eFlight = eFlight4;
if((int32_t)OCP_FL_MSG_NODE_NOT_AVAIL == i4Status)
{
// Buffer the message
psMsgListTrav = (sMsgInfo_d*)OCP_MALLOC(sizeof(sMsgInfo_d));
if(NULL == psMsgListTrav)
{
i4Status = (int32_t)OCP_FL_MALLOC_FAILURE;
break;
}
psMsgListTrav->eMsgState = ePartial;
psMsgListTrav->psNext = NULL;
psMsgListTrav->psMsgMapPtr = NULL;
psMsgListTrav->psMsgHolder = (uint8_t*)OCP_MALLOC(HS_MESSAGE_LENGTH(PpsMessageLayer->sMsg.prgbStream) + OVERHEAD_LEN);
if(NULL == psMsgListTrav->psMsgHolder)
{
DtlsHS_FreeMsgNode(psMsgListTrav);
i4Status = (int32_t)OCP_FL_MALLOC_FAILURE;
break;
}
i4Status = DtlsHS_RInit_MessageNode(psMsgListTrav, PpsMessageLayer);
if(((int32_t)OCP_FL_OK != i4Status) && ((int32_t)OCP_FL_MSG_INCOMPLETE != i4Status))
{
DtlsHS_FreeMsgNode(psMsgListTrav);
break;
}
DtlsHS_InsertMsgNode(&PpsThisFlight->psMessageList, psMsgListTrav);
}
//Check Flight Completeness
i4Status = DtlsHS_CheckFlight_Compl(PpsThisFlight->psMessageList, (uint8_t)eFlight4, PpsMessageLayer);
if((int32_t)OCP_FL_MSG_INCOMPLETE == i4Status)
{
i4Status = (int32_t)OCP_FL_RXING;
break;
}
if(OCP_FL_OK != i4Status)
{
break;
}
PpsThisFlight->bFlightState = (uint8_t)efReceived;
//Send to Security Chip For Processing
i4Status = DtlsHS_SendFlightToOptiga(PpsThisFlight->psMessageList, PpsMessageLayer);
if(OCP_ML_OK != i4Status)
{
break;
}
//Update Flight Status
PpsThisFlight->bFlightState = (uint8_t)efProcessed;
DtlsHS_FlightGetLastMsgSeqNum(PpsThisFlight->psMessageList, &wFlightLastMsgSeqNum);
UPDATE_RX_MSGSEQNUM(PpsMessageLayer->dwRMsgSeqNum, wFlightLastMsgSeqNum);
PpsMessageLayer->eFlight = eFlight0;
DtlsHS_Flight4ClearMsgsInList(PpsThisFlight->psMessageList);
}
else if (((uint8_t)efProcessed == PpsThisFlight->bFlightState) || ((uint8_t)efReReceive == PpsThisFlight->bFlightState))
{
if((uint8_t)efProcessed == PpsThisFlight->bFlightState)
{
UPDATE_FSTATE(PpsThisFlight->bFlightState, (uint8_t)efReReceive);
}
if(PpsMessageLayer->psConfigRL->sRL.bRecvCCSRecord == CCS_RECORD_RECV)
{
i4Status = (int32_t)OCP_FL_MSG_NOT_IN_FLIGHT;
break;
}
bMsgID = HS_MESSAGE_TYPE(PpsMessageLayer->sMsg.prgbStream);
wMsgSeqNum = HS_MESSAGE_SEQNUM(PpsMessageLayer->sMsg.prgbStream);
dwMsgLen = HS_MESSAGE_LENGTH(PpsMessageLayer->sMsg.prgbStream);
psMsgListTrav = PpsThisFlight->psMessageList;
if(OCP_FL_OK != DtlsHS_Flight_LimitChk((uint8_t)eFlight4,bMsgID))
{
i4Status = (int32_t)OCP_FL_MSG_NOT_IN_FLIGHT;
break;
}
if(0x00 != PpsMessageLayer->psConfigRL->sRL.bDecRecord)
{
i4Status = (int32_t)OCP_FL_MSG_NOT_IN_FLIGHT;
break;
}
if(OCP_FL_OK != DtlsHS_Flight4CheckBuffMsg(bMsgID, wMsgSeqNum, dwMsgLen, PpsThisFlight->psMessageList))
{
i4Status = (int32_t)OCP_FL_MSG_IGNORE;
break;
}
PpsMessageLayer->eFlight = eFlight4;
i4Status = DtlsHS_Flight4UpdateMsgStat(bMsgID, PpsThisFlight->psMessageList, PpsMessageLayer);
if(((int32_t)OCP_FL_OK != i4Status) && ((int32_t)OCP_FL_MSG_INCOMPLETE != i4Status))
{
break;
}
if(OCP_FL_OK != DtlsHS_Flight4ReRxCompl(PpsThisFlight->psMessageList))
{
i4Status = (int32_t)OCP_FL_RXING;
break;
}
//Update Flight Status
UPDATE_FSTATE(PpsThisFlight->bFlightState, (uint8_t)efProcessed);
DtlsHS_Flight4ClearMsgsInList(PpsThisFlight->psMessageList);
}
i4Status = (int32_t)OCP_FL_OK;
}while(0);
return i4Status;
}
/**
* Checks whether flight six is received.
*
* \param[in] PpsMessageList Pointer to the list of messages of flight6.
*
* \retval #OCP_FL_OK Flight six is received
* \retval #OCP_FL_ERROR Flight six is not received
*/
_STATIC_H int32_t DtlsHS_CheckFlight6_Compl(sMsgInfo_d *PpsMessageList)
{
int32_t i4Status = (int32_t)OCP_FL_OK;
sMsgInfo_d * psMsgListTrav = PpsMessageList;
uint16_t * pwFlightMsgs;
uint8_t bTotalMsgInFlight;
uint8_t bNumMsgRxdInFlight = 0;
DtlsHS_GetFlightMsgInfo((uint8_t)eFlight6, &pwFlightMsgs);
DtlsHS_GetTotalMsgCount(pwFlightMsgs, &bTotalMsgInFlight);
do
{
while(NULL != psMsgListTrav)
{
bNumMsgRxdInFlight++;
if(eComplete != psMsgListTrav->eMsgState)
{
i4Status = (int32_t)OCP_FL_MSG_INCOMPLETE;
break;
}
psMsgListTrav = psMsgListTrav->psNext;
}
if(((int32_t)OCP_FL_OK == i4Status) && (bNumMsgRxdInFlight != bTotalMsgInFlight))
{
i4Status = (int32_t)OCP_FL_MSG_INCOMPLETE;
break;
}
}while(0);
return i4Status;
}
/**
* Flight six handler to process flight 6 messages.
*
* \param[in] PbLastProcFlight Last processed flight.
* \param[in,out] PpsThisFlight Pointer to the structure containing flight6 status.
* \param[in] PpsMessageLayer Pointer to the structure containing message configuration information.
*
* \retval #OCP_FL_OK Successful execution
* \retval #OCP_FL_MSG_ERROR Failure in execution
* \retval #OCP_FL_MALLOC_FAILURE Memory allocation failure
* \retval #OCP_FL_INVALID_MSG_SEQNUM Invalid Message sequence number
* \retval #OCP_FL_MSG_NOT_IN_FLIGHT Message doesn't belong to current flight
* \retval #OCP_FL_RXING Message is not yet completely received
* \retval #OCP_FL_MSG_MAXCOUNT Message is received at least 6 times
*/
int32_t DtlsHS_Flight6Handler(uint8_t PbLastProcFlight, sFlightStats_d* PpsThisFlight, sMsgLyr_d* PpsMessageLayer)
{
int32_t i4Status = (int32_t)OCP_FL_OK;
sMsgInfo_d* psMsgListTrav = NULL;
uint8_t bMsgID;
uint16_t wMsgSeqNum = 0;
sCBStateTrn_d sCBStateTrn;
uint16_t wFlightLastMsgSeqNum = 0xFFFF;
/// @cond hidden
#define SETFULL_BITMAP 0xFF
#define SIZE_OF_CCSMSG 0x01
#define CHANGE_CIPHER_SPEC_PROTOCOL 0x01
#define INTERNAL_PROC_ERROR 0x06
#define INVALID_HS_MESSAGE 0x21
/// @endcond
do
{
//Check Message/ Fragment
//Optional Message Check
//Check Message Sequence Number
//Buffer the message/ De-Fragmentation()
//Message Completeness()
//Send to Security Chip for Processing()
if((uint8_t)efInit == PpsThisFlight->bFlightState)
{
PpsThisFlight->bFlightState = (uint8_t)efReady;
break;
}
else if((uint8_t)efReady == PpsThisFlight->bFlightState)
{
if(PpsMessageLayer->psConfigRL->sRL.bRecvCCSRecord == CCS_RECORD_RECV)
{
if((*(PpsMessageLayer->sMsg.prgbStream) != (uint8_t)CHANGE_CIPHER_SPEC_PROTOCOL) || (PpsMessageLayer->sMsg.wLen != (uint16_t)SIZE_OF_CCSMSG))
{
i4Status = (int32_t)OCP_FL_MSG_NOT_IN_FLIGHT;
PpsMessageLayer->psConfigRL->sRL.bRecvCCSRecord = CCS_RECORD_NOTRECV;
break;
}
if(NULL != PpsMessageLayer->psConfigRL->sRL.fServerStateTrn)
{
sCBStateTrn.phRLHdl = PpsMessageLayer->psConfigRL->sRL.phRLHdl;
PpsMessageLayer->psConfigRL->sRL.fServerStateTrn((Void*)&sCBStateTrn);
}
else
{
i4Status = (int32_t)OCP_FL_NULL_PARAM;
break;
}
bMsgID = (uint8_t)eChangeCipherSpec;
}
else
{
bMsgID = HS_MESSAGE_TYPE(PpsMessageLayer->sMsg.prgbStream);
wMsgSeqNum = HS_MESSAGE_SEQNUM(PpsMessageLayer->sMsg.prgbStream);
}
if(OCP_FL_OK != DtlsHS_Flight_LimitChk((uint8_t)eFlight6, bMsgID))
{
i4Status = (int32_t)OCP_FL_MSG_NOT_IN_FLIGHT;
break;
}
if(OCP_FL_OK != FLIGHT_IDLIMITCHK(4, PbLastProcFlight, 6))
{
i4Status = (int32_t)OCP_FL_INVALID_PROCFLIGHT;
break;
}
if(OCP_FL_OK != DtlsHS_Flight6CheckMsgSeqNum(PpsMessageLayer, bMsgID, wMsgSeqNum))
{
i4Status = (int32_t)OCP_FL_INVALID_MSG_SEQNUM;
break;
}
i4Status = DtlsHS_FlightMsgChkAndBuffer(PpsThisFlight->psMessageList, bMsgID, &(PpsMessageLayer->sMsg), PpsMessageLayer, (uint8_t)eFlight6);
if(((int32_t)OCP_FL_ERROR == i4Status) || ((int32_t)OCP_FL_MSG_MAXCOUNT == i4Status) || ((int32_t)OCP_FL_MALLOC_FAILURE == i4Status))
{
break;
}
PpsMessageLayer->eFlight = eFlight6;
if((int32_t)OCP_FL_MSG_NODE_NOT_AVAIL == i4Status)
{
// Buffer the message
psMsgListTrav = (sMsgInfo_d*)OCP_MALLOC(sizeof(sMsgInfo_d));
if(NULL == psMsgListTrav)
{
i4Status = (int32_t)OCP_FL_MALLOC_FAILURE;
break;
}
if((uint8_t)eChangeCipherSpec == bMsgID)
{
psMsgListTrav->bMsgType = (uint8_t)eChangeCipherSpec;
psMsgListTrav->psNext = NULL;
psMsgListTrav->psMsgHolder = NULL;
psMsgListTrav->bMsgCount = 1;
psMsgListTrav->psMsgMapPtr = (uint8_t*)OCP_MALLOC(SIZE_OF_CCSMSG);
if(NULL == psMsgListTrav->psMsgMapPtr)
{
DtlsHS_FreeMsgNode(psMsgListTrav);
i4Status = (int32_t)OCP_FL_MALLOC_FAILURE;
break;
}
*psMsgListTrav->psMsgMapPtr = SETFULL_BITMAP;
psMsgListTrav->dwMsgLength = SIZE_OF_CCSMSG;
psMsgListTrav->eMsgState = eComplete;
i4Status = OCP_FL_OK;
}
else
{
psMsgListTrav->eMsgState = ePartial;
psMsgListTrav->psNext = NULL;
psMsgListTrav->psMsgMapPtr = NULL;
psMsgListTrav->psMsgHolder = (uint8_t*)OCP_MALLOC(HS_MESSAGE_LENGTH(PpsMessageLayer->sMsg.prgbStream) + OVERHEAD_LEN);
if(NULL == psMsgListTrav->psMsgHolder)
{
DtlsHS_FreeMsgNode(psMsgListTrav);
i4Status = (int32_t)OCP_FL_MALLOC_FAILURE;
break;
}
i4Status = DtlsHS_RInit_MessageNode(psMsgListTrav, PpsMessageLayer);
if(((int32_t)OCP_FL_OK != i4Status) && ((int32_t)OCP_FL_MSG_INCOMPLETE != i4Status))
{
DtlsHS_FreeMsgNode(psMsgListTrav);
break;
}
}
DtlsHS_InsertMsgNode(&PpsThisFlight->psMessageList, psMsgListTrav);
}
//Check Flight Completeness
if((int32_t)OCP_FL_MSG_INCOMPLETE == DtlsHS_CheckFlight6_Compl(PpsThisFlight->psMessageList))
{
i4Status = (int32_t)OCP_FL_RXING;
break;
}
if(OCP_FL_OK != i4Status)
{
break;
}
PpsThisFlight->bFlightState = (uint8_t)efReceived;
//Send to Security Chip For Processing
i4Status = DtlsHS_SendFlightToOptiga(PpsThisFlight->psMessageList, PpsMessageLayer);
if(OCP_ML_OK != i4Status)
{
if((i4Status & (int32_t)DEV_ERROR_CODE_MASK) == (int32_t)CMD_DEV_ERROR)
{
if((i4Status & (int32_t)DEV_ERROR_LSBCODE_MASK) == INTERNAL_PROC_ERROR)
{
i4Status = (int32_t)OCP_FL_INT_ERROR;
}
else if((i4Status & (int32_t)DEV_ERROR_LSBCODE_MASK) == INVALID_HS_MESSAGE)
{
i4Status = (int32_t)OCP_FL_HS_ERROR;
}
}
break;
}
//Update Flight Status
PpsThisFlight->bFlightState = (uint8_t)efProcessed;
DtlsHS_FlightGetLastMsgSeqNum(PpsThisFlight->psMessageList, &wFlightLastMsgSeqNum);
UPDATE_RX_MSGSEQNUM(PpsMessageLayer->dwRMsgSeqNum, wFlightLastMsgSeqNum);
}
i4Status = (int32_t)OCP_FL_OK;
}while(0);
/// @cond hidden
#undef SETFULL_BITMAP
#undef SIZE_OF_CCSMSG
#undef CHANGE_CIPHER_SPEC_PROTOCOL
#undef INTERNAL_PROC_ERROR
#undef INVALID_HS_MESSAGE
/// @endcond
return i4Status;
}
/**
* @}
*/
#endif /*MODULE_ENABLE_DTLS_MUTUAL_AUTH*/