1213 lines
42 KiB
C
1213 lines
42 KiB
C
/**
|
|
* 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 OCP.c
|
|
*
|
|
* \brief This file implements the API Layer of OCP Library.
|
|
*
|
|
* \addtogroup grOCP
|
|
* @{
|
|
*/
|
|
|
|
#include "optiga/optiga_dtls.h"
|
|
#include "optiga/cmd/CommandLib.h"
|
|
#include "optiga/dtls/AlertProtocol.h"
|
|
|
|
#ifdef MODULE_ENABLE_DTLS_MUTUAL_AUTH
|
|
|
|
/// @cond hidden
|
|
|
|
extern Void ConfigHL(fPerformHandshake_d* PfPerformHandshake_d,eConfiguration_d PeConfiguration);
|
|
extern Void ConfigRL(sConfigRL_d* PpsConfigRL,eConfiguration_d PeConfiguration);
|
|
extern Void ConfigTL(sConfigTL_d* PpsConfigTL,eConfiguration_d PeConfiguration);
|
|
extern Void ConfigCL(sConfigCL_d* PpsConfigCL,eConfiguration_d PeConfiguration);
|
|
extern int32_t DtlsHS_VerifyHR(uint8_t* PprgbData, uint16_t PwLen);
|
|
|
|
///Identifier for Session ID 1
|
|
#define SESSIONID_1 0xE100
|
|
|
|
///Session key is in used
|
|
#define INUSE 0x4A
|
|
|
|
///Session key is not in use
|
|
#define NOTUSED 0xA4
|
|
|
|
/**
|
|
* \brief Structure that defines OCP Application context data
|
|
*/
|
|
typedef struct sAppOCPCtx_d
|
|
{
|
|
///Pointer to function that performs handshake
|
|
fPerformHandshake_d pfPerformHandshake;
|
|
|
|
///Structure that contains Handshake data
|
|
sHandshake_d sHandshake;
|
|
|
|
///Structure that holds Record Layer Configuration
|
|
sConfigRL_d sConfigRL;
|
|
|
|
///Structure that holds logger parameters
|
|
sLogger_d sLogger;
|
|
|
|
///Authentication scheme
|
|
eAuthScheme_d eAuthScheme;
|
|
|
|
///Buffer to store the received application data
|
|
uint8_t* pAppDataBuf;
|
|
}sAppOCPCtx_d;
|
|
|
|
/**
|
|
* \brief Configures the Handshake, Record, Transport and Crypto Layers based on input parameters
|
|
*/
|
|
_STATIC_H Void OCP_Config(sAppOCPCtx_d* PpsAppOCPCntx,eConfiguration_d PeConfiguration)
|
|
{
|
|
ConfigHL(&(PpsAppOCPCntx->pfPerformHandshake),PeConfiguration);
|
|
ConfigRL(&(PpsAppOCPCntx->sConfigRL),PeConfiguration);
|
|
ConfigTL(PpsAppOCPCntx->sConfigRL.sRL.psConfigTL,PeConfiguration);
|
|
ConfigCL(PpsAppOCPCntx->sConfigRL.sRL.psConfigCL,PeConfiguration);
|
|
}
|
|
|
|
/**
|
|
* Allocates the memory for sAppOCPCtx_d<br>
|
|
*/
|
|
_STATIC_H int32_t OCPAllocateMemory(sAppOCPCtx_d ** PppsAppOCPCntx)
|
|
{
|
|
int32_t i4Status = (int32_t)OCP_LIB_MALLOC_FAILURE;
|
|
|
|
#define PS_APPOCPCNTX (* PppsAppOCPCntx)
|
|
|
|
do
|
|
{
|
|
//Allocate the memory for OCP context data structure
|
|
PS_APPOCPCNTX = (sAppOCPCtx_d *)OCP_MALLOC(sizeof(sAppOCPCtx_d));
|
|
if(NULL == PS_APPOCPCNTX)
|
|
{
|
|
break;
|
|
}
|
|
|
|
(*PS_APPOCPCNTX).pAppDataBuf = NULL;
|
|
(*PS_APPOCPCNTX).sConfigRL.sRL.psConfigTL = NULL;
|
|
(*PS_APPOCPCNTX).sConfigRL.sRL.psConfigCL = NULL;
|
|
|
|
//Allocate the memory for the transport layer and crypto layer structure
|
|
PS_APPOCPCNTX->sConfigRL.sRL.psConfigTL = (sConfigTL_d*)OCP_MALLOC(sizeof(sConfigTL_d));
|
|
if(NULL == PS_APPOCPCNTX->sConfigRL.sRL.psConfigTL)
|
|
{
|
|
break;
|
|
}
|
|
|
|
PS_APPOCPCNTX->sConfigRL.sRL.psConfigTL->sTL.phTLHdl = NULL;
|
|
|
|
PS_APPOCPCNTX->sConfigRL.sRL.psConfigCL = (sConfigCL_d*)OCP_MALLOC(sizeof(sConfigCL_d));
|
|
if(NULL == PS_APPOCPCNTX->sConfigRL.sRL.psConfigCL)
|
|
{
|
|
break;
|
|
}
|
|
|
|
PS_APPOCPCNTX->sConfigRL.sRL.psConfigCL->sCL.phCryptoHdl = NULL;
|
|
PS_APPOCPCNTX->sConfigRL.sRL.phRLHdl = NULL;
|
|
i4Status = (int32_t)OCP_LIB_OK;
|
|
}while(FALSE);
|
|
#undef PS_APPOCPCNTX
|
|
return i4Status;
|
|
}
|
|
|
|
/**
|
|
* \brief Frees the allocated memory for sAppOCPCtx_d
|
|
*/
|
|
_STATIC_H Void OCPFreeMemory(sAppOCPCtx_d* PpsAppOCPCntx)
|
|
{
|
|
if(NULL != PpsAppOCPCntx)
|
|
{
|
|
if(NULL != (PpsAppOCPCntx)->pAppDataBuf)
|
|
{
|
|
OCP_FREE((PpsAppOCPCntx)->pAppDataBuf);
|
|
}
|
|
if(NULL != (PpsAppOCPCntx)->sConfigRL.sRL.psConfigCL)
|
|
{
|
|
#define S_RL (PpsAppOCPCntx)->sConfigRL
|
|
|
|
S_RL.sRL.psConfigCL->pfClose(&(PpsAppOCPCntx)->sConfigRL.sRL.psConfigCL->sCL);
|
|
OCP_FREE((PpsAppOCPCntx)->sConfigRL.sRL.psConfigCL);
|
|
}
|
|
|
|
if(NULL != (PpsAppOCPCntx)->sConfigRL.sRL.psConfigTL)
|
|
{
|
|
#define S_TL (PpsAppOCPCntx)->sConfigRL.sRL.psConfigTL->sTL
|
|
|
|
if(NULL != S_TL.phTLHdl)
|
|
{
|
|
//Free the allocated memory for Transport layer
|
|
OCP_FREE(S_TL.phTLHdl);
|
|
|
|
S_TL.phTLHdl = NULL;
|
|
}
|
|
|
|
OCP_FREE((PpsAppOCPCntx)->sConfigRL.sRL.psConfigTL);
|
|
}
|
|
|
|
//Free the memory held by record layer
|
|
S_RL.pfClose(&S_RL.sRL);
|
|
|
|
OCP_FREE(PpsAppOCPCntx);
|
|
}
|
|
#undef S_TL
|
|
#undef S_RL
|
|
}
|
|
|
|
/**
|
|
* \brief Structure defining Session registry content
|
|
*/
|
|
typedef struct sSessionRegistry_d
|
|
{
|
|
///DTLS Session ID
|
|
uint16_t wSessionId;
|
|
///OCP Handle
|
|
hdl_t hOCPHandle;
|
|
///Variable to indicate the session ID usage
|
|
uint8_t bInUse;
|
|
}sSessionRegistry_d;
|
|
|
|
///Static registry for holding Session key Id information
|
|
sSessionRegistry_d sSessionRegistry[1] ={
|
|
{SESSIONID_1, (hdl_t)NULL, NOTUSED}
|
|
};
|
|
|
|
/**
|
|
* This API returns the available Security Chip Session id
|
|
* that can be used by Command Library SetAuthScheme.<br>
|
|
*
|
|
* \param[in,out] PwSessionId Available session id
|
|
*
|
|
* \retval #OCP_LIB_OK
|
|
* \retval #OCP_LIB_SESSIONID_UNAVAILABLE
|
|
*/
|
|
_STATIC_H int32_t Registry_GetSessionId(uint16_t* PwSessionId)
|
|
{
|
|
int32_t i4Status = (int32_t)OCP_LIB_SESSIONID_UNAVAILABLE;
|
|
uint8_t bCount = 0;
|
|
|
|
//Search the registry for unused session key id
|
|
for(bCount= 0;bCount<(sizeof(sSessionRegistry)/sizeof(sSessionRegistry_d));bCount++)
|
|
{
|
|
if(NOTUSED == sSessionRegistry[bCount].bInUse)
|
|
{
|
|
//return unused session key id
|
|
*PwSessionId = sSessionRegistry[bCount].wSessionId;
|
|
i4Status = (int32_t)OCP_LIB_OK;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return i4Status;
|
|
}
|
|
|
|
/**
|
|
* This function updates OCP handle against the given session key id in the registry if the session key id is not already used.<br>
|
|
* The session key is marked as in-use.
|
|
*
|
|
* \param[in] PdwSessionId Session id
|
|
* \param[in,out] PhOCPHandle Context to be updated for input session id
|
|
*
|
|
* \retval #OCP_LIB_OK
|
|
* \retval #OCP_LIB_ERROR
|
|
*/
|
|
_STATIC_H int32_t Registry_Update(uint32_t PdwSessionId,const hdl_t PhOCPHandle)
|
|
{
|
|
int32_t i4Status = (int32_t)OCP_LIB_ERROR;
|
|
uint8_t bCount;
|
|
|
|
//Search the table for the given session key id
|
|
for(bCount= 0;bCount<(sizeof(sSessionRegistry)/sizeof(sSessionRegistry_d));bCount++)
|
|
{
|
|
if((PdwSessionId == sSessionRegistry[bCount].wSessionId) &&
|
|
(NOTUSED == sSessionRegistry[bCount].bInUse))
|
|
{
|
|
//Update the OCP handle
|
|
sSessionRegistry[bCount].hOCPHandle = PhOCPHandle;
|
|
//Update the usage status
|
|
sSessionRegistry[bCount].bInUse = INUSE;
|
|
i4Status = (int32_t) OCP_LIB_OK;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return i4Status;
|
|
}
|
|
|
|
/**
|
|
* This function frees the session key id used for the given OCP handle in the registry.<br>
|
|
* The session key is marked as Not used.
|
|
*
|
|
* \param[in,out] PhOCPHandle Context for which session id to be freed
|
|
*
|
|
*/
|
|
//lint --e{818} suppress "PhOCPHandle is declared as const"
|
|
_STATIC_H Void Registry_Free(const hdl_t PhOCPHandle)
|
|
{
|
|
uint8_t bCount;
|
|
|
|
//Search the table for the given session key id
|
|
for(bCount= 0;bCount<(sizeof(sSessionRegistry)/sizeof(sSessionRegistry_d));bCount++)
|
|
{
|
|
if(PhOCPHandle == sSessionRegistry[bCount].hOCPHandle)
|
|
{
|
|
//Free the usage status
|
|
sSessionRegistry[bCount].bInUse = NOTUSED;
|
|
sSessionRegistry[bCount].hOCPHandle = NULL;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* This function Gets the session key id used for the given OCP handle in the registry.<br>
|
|
*
|
|
* \param[in] PhOCPHandle OCP handle
|
|
* \param[out] PpwSessionId Pointer to the session ID
|
|
*
|
|
* \retval #OCP_LIB_OK
|
|
* \retval #OCP_LIB_SESSIONID_UNAVAILABLE
|
|
*/
|
|
//lint --e{818} suppress "PhOCPHandle is declared as const"
|
|
_STATIC_H int32_t Registry_GetHandleSessionID(const hdl_t PhOCPHandle, uint16_t *PpwSessionId)
|
|
{
|
|
int32_t i4Status = (int32_t)OCP_LIB_SESSIONID_UNAVAILABLE;
|
|
uint8_t bCount = 0;
|
|
|
|
//Search the table for the given OCP handle
|
|
for(bCount= 0;bCount<(sizeof(sSessionRegistry)/sizeof(sSessionRegistry_d));bCount++)
|
|
{
|
|
if(PhOCPHandle == sSessionRegistry[bCount].hOCPHandle)
|
|
{
|
|
*PpwSessionId = sSessionRegistry[bCount].wSessionId;
|
|
i4Status = (int32_t)OCP_LIB_OK;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return i4Status;
|
|
}
|
|
|
|
/**
|
|
* This function validates whether handle is associated with a the session key id from the registry.<br>
|
|
*
|
|
* \param[in] PhOCPHandle OCP handle
|
|
*
|
|
* \retval #OCP_LIB_OK
|
|
* \retval #OCP_LIB_SESSIONID_UNAVAILABLE
|
|
*/
|
|
//lint --e{818} suppress "PhOCPHandle is declared as const"
|
|
_STATIC_H int32_t Registry_ValidateHandleSessionID(const hdl_t PhOCPHandle)
|
|
{
|
|
int32_t i4Status = (int32_t)OCP_LIB_SESSIONID_UNAVAILABLE;
|
|
uint8_t bCount;
|
|
|
|
//Search the table for the given OCP handle
|
|
for(bCount= 0;bCount<(sizeof(sSessionRegistry)/sizeof(sSessionRegistry_d));bCount++)
|
|
{
|
|
if(PhOCPHandle == sSessionRegistry[bCount].hOCPHandle)
|
|
{
|
|
i4Status = (int32_t)OCP_LIB_OK;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return i4Status;
|
|
}
|
|
|
|
/**
|
|
* This Function closes the session ,free the memory allocated and return close notify alert based on input parameter.<br>
|
|
*
|
|
* Notes: <br>
|
|
* - Under some erroneous conditions,error codes from Command Library and transport layer can also be returned. <br>
|
|
*
|
|
* \param[in] PhAppOCPCtx OCP handle
|
|
* \param[in] PfFatalError Flag indicating whether fatal error as occurred or not
|
|
* \param[in] PwSessionId Session ID to be closed
|
|
*
|
|
*/
|
|
_STATIC_H Void CloseSession(hdl_t PhAppOCPCtx, bool_t PfFatalError, uint16_t PwSessionId)
|
|
{
|
|
sAppOCPCtx_d *psCntx = (sAppOCPCtx_d*)PhAppOCPCtx;
|
|
#define S_CONFIGURATION_TL (psCntx->sConfigRL.sRL.psConfigTL)
|
|
|
|
//lint --e{534} ,Return value is ignored as irrespective of this session will be closed"
|
|
if(psCntx->sHandshake.eAuthState != eAuthInitialised)
|
|
{
|
|
if(!PfFatalError)
|
|
{
|
|
SEND_ALERT(&psCntx->sConfigRL,(int32_t) OCP_RL_ERROR);
|
|
}
|
|
//Close the DTLS session on Security Chip
|
|
CmdLib_CloseSession(PwSessionId);
|
|
}
|
|
//Disconnect from the server via transport layer
|
|
S_CONFIGURATION_TL->pfDisconnect(&S_CONFIGURATION_TL->sTL);
|
|
|
|
//Clear the session reference ID registry for the handle
|
|
Registry_Free(PhAppOCPCtx);
|
|
|
|
//Free the memory associated with the handle
|
|
OCPFreeMemory(psCntx);
|
|
|
|
#undef S_CONFIGURATION_TL
|
|
}
|
|
|
|
/// @endcond
|
|
|
|
/**
|
|
* This API initialises the OCP context based on the user inputs provided in PpsAppOCPConfig.Once the OCP context
|
|
* is initialised,PphAppOCPCtx is returned as a handle.<br>
|
|
* PphAppOCPCtx handle is used for all interactions with the OCP APIs #OCP_Connect, #OCP_Disconnect, #OCP_Send and #OCP_Receive.
|
|
* <br>
|
|
* <br>
|
|
* \image html OCPInit.png "OCP_Init()" width=20cm
|
|
*
|
|
*<b>Pre Conditions:</b>
|
|
* - Communication with the security chip is up and running. <br>
|
|
* #optiga_comms_open() must be successfully executed.<br>
|
|
* - The optiga comms context for command library is registered using #CmdLib_SetOptigaCommsContext().
|
|
*
|
|
*<b>API Details:</b>
|
|
* - Checks for an available session OID.
|
|
* - Opens application on the security chip using CmdLib_OpenApplication().<br>
|
|
* - Allocates the memory for internal structures, initialises it and returns as a #hdl_t*
|
|
*
|
|
*<b>User Input:</b><br>
|
|
*The user must provide configuration information in #sAppOCPConfig_d
|
|
* - eMode allows the user to configure the OCP context as a client/server as per #eMode_d. Currently server mode is not supported.<br>
|
|
* - eConfiguration allows the user to choose supported OCP context configuration as per #eConfiguration_d. Currently eTLS_12_TCP_HWCRYPTO is not supported.<br>
|
|
* - wOIDDevCertificate allows the user to choose the supported certificate for client authentication.
|
|
* - If their is no client certificate then set it to 0x0000.<br>
|
|
* - wOIDDevPrivKey allows the user to choose the private key used for client authentication.<br>
|
|
* - psNetworkParams allows the user to configure the port, IP Address and maximum PMTU required for transport layer connection.<br>
|
|
* - Valid IP address and port number must be provided. The correctness of the IP address and port number will not be verified.<br>
|
|
* - PMTU value should range between 296 to 1500,else #OCP_LIB_UNSUPPORTED_PMTU error is returned.<br>
|
|
* - Logger allows user to log data. User must provide the low level log writer through #sLogger_d.<br>
|
|
* - pfGetUnixTIme(#fGetUnixTime_d) is a call-back function pointer that allows user to provide 32-bit Unix time format.<br>
|
|
* - If pfGetUnixTIme is set to NULL, the unix time will not be sent to security chip.<br>
|
|
* - If pfGetUnixTIme is not set to NULL or valid function pointer, the behavior would be unexpected.<br>
|
|
* - The call back function pfGetUnixTIme is expected to return status s as #CALL_BACK_OK for success.
|
|
*
|
|
*<b>Notes:</b>
|
|
* - Currently, only 1 DTLS session is supported by security chip.<br>
|
|
* - If user invokes OCP_Init, with out disconnecting/closing the previous session/context(if available), will lead to error #OCP_LIB_SESSIONID_UNAVAILABLE.<br>
|
|
* - Under some failure conditions, error codes from lower layers could also be returned. <br>
|
|
*
|
|
* \param[in] PpsAppOCPConfig Pointer to structure that contains the configuration from user
|
|
* \param[in,out] PphAppOCPCtx Pointer to the handle of OCP context
|
|
*
|
|
* \retval #OCP_LIB_OK
|
|
* \retval #OCP_LIB_ERROR
|
|
* \retval #OCP_LIB_NULL_PARAM
|
|
* \retval #OCP_LIB_UNSUPPORTED_CONFIG
|
|
* \retval #OCP_LIB_SESSIONID_UNAVAILABLE
|
|
* \retval #OCP_LIB_UNSUPPORTED_PMTU
|
|
*/
|
|
|
|
int32_t OCP_Init(const sAppOCPConfig_d* PpsAppOCPConfig,hdl_t* PphAppOCPCtx)
|
|
{
|
|
int32_t i4Status = (int32_t)OCP_LIB_ERROR;
|
|
sAppOCPCtx_d *psAppOCPCntx = NULL;
|
|
eAuthScheme_d eAuthScheme;
|
|
sOpenApp_d sOpenApp;
|
|
uint16_t wSessionKeyId;
|
|
|
|
do
|
|
{
|
|
//NULL check for input parameters
|
|
if((NULL == PpsAppOCPConfig) || (NULL == PphAppOCPCtx))
|
|
{
|
|
i4Status = (int32_t)OCP_LIB_NULL_PARAM;
|
|
break;
|
|
}
|
|
|
|
//Initialize handle to NULL
|
|
* PphAppOCPCtx = NULL;
|
|
|
|
//Check the registry whether a free session Id is available
|
|
i4Status = Registry_GetSessionId(&wSessionKeyId);
|
|
if(OCP_LIB_OK != i4Status)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//Check for valid configuration
|
|
if(eDTLS_12_UDP_HWCRYPTO != PpsAppOCPConfig->eConfiguration)
|
|
{
|
|
i4Status = (int32_t)OCP_LIB_UNSUPPORTED_CONFIG;
|
|
break;
|
|
}
|
|
|
|
//Initialize the Auth Scheme type
|
|
if((eClient == PpsAppOCPConfig->eMode) && (eDTLS_12_UDP_HWCRYPTO == PpsAppOCPConfig->eConfiguration))
|
|
{
|
|
eAuthScheme = eDTLSClient;
|
|
}
|
|
else
|
|
{
|
|
//If other mode is selected
|
|
i4Status = (int32_t)OCP_LIB_UNSUPPORTED_MODE;
|
|
break;
|
|
}
|
|
|
|
//Check if the PMTU provided is within limit or not
|
|
if((PpsAppOCPConfig->sNetworkParams.wMaxPmtu > MAX_PMTU) || (PpsAppOCPConfig->sNetworkParams.wMaxPmtu < MIN_PMTU))
|
|
{
|
|
i4Status = (int32_t)OCP_LIB_UNSUPPORTED_PMTU;
|
|
break;
|
|
}
|
|
|
|
//Allocate the memory for the Context data structure.It will be used for all interaction with OCP APIs
|
|
i4Status = OCPAllocateMemory(&psAppOCPCntx);
|
|
if(OCP_LIB_OK != i4Status)
|
|
{
|
|
break;
|
|
}
|
|
|
|
OCP_Config(psAppOCPCntx,PpsAppOCPConfig->eConfiguration);
|
|
|
|
sOpenApp.eOpenType = eInit;
|
|
|
|
//Open Application
|
|
i4Status = CmdLib_OpenApplication(&sOpenApp);
|
|
if(CMD_LIB_OK != i4Status)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//Assign the Auth Scheme
|
|
psAppOCPCntx->eAuthScheme = eAuthScheme;
|
|
|
|
//Assign the maximum path transfer unit
|
|
psAppOCPCntx->sHandshake.wMaxPmtu = PpsAppOCPConfig->sNetworkParams.wMaxPmtu;
|
|
|
|
//Assign the Certificate type to be used for Authentication
|
|
psAppOCPCntx->sHandshake.wOIDDevCertificate = PpsAppOCPConfig->wOIDDevCertificate;
|
|
|
|
//Assign the private key to be used for Authentication
|
|
psAppOCPCntx->sHandshake.wOIDDevPrivKey = PpsAppOCPConfig->wOIDDevPrivKey;
|
|
|
|
//Assign the callback function to get unix time
|
|
psAppOCPCntx->sHandshake.pfGetUnixTIme = PpsAppOCPConfig->pfGetUnixTIme;
|
|
|
|
//Assign the record layer configuration pointer to the handshake layer
|
|
psAppOCPCntx->sHandshake.psConfigRL = &psAppOCPCntx->sConfigRL;
|
|
psAppOCPCntx->sHandshake.eMode = PpsAppOCPConfig->eMode;
|
|
|
|
//Set the fatal error occur type to false;
|
|
psAppOCPCntx->sHandshake.fFatalError = FALSE;
|
|
|
|
//Assign the logger pointer for psAppOCPCntx layer
|
|
psAppOCPCntx->sLogger = PpsAppOCPConfig->sLogger;
|
|
|
|
//Assign the logger pointer for handshake layer
|
|
psAppOCPCntx->sHandshake.phLogger = PpsAppOCPConfig->sLogger;
|
|
|
|
//Assign the logger pointer for Record layer
|
|
psAppOCPCntx->sConfigRL.sRL.sLogger.pHdl = PpsAppOCPConfig->sLogger.pHdl;
|
|
psAppOCPCntx->sConfigRL.sRL.sLogger.phfWriter = PpsAppOCPConfig->sLogger.phfWriter;
|
|
|
|
/// @cond hidden
|
|
#define S_TL psAppOCPCntx->sConfigRL.sRL.psConfigTL->sTL
|
|
/// @endcond
|
|
//Assign the IP address to the transport layer parameter
|
|
S_TL.pzIpAddress = PpsAppOCPConfig->sNetworkParams.pzIpAddress;
|
|
|
|
//Assign the port number to the transport layer parameter
|
|
S_TL.wPort = PpsAppOCPConfig->sNetworkParams.wPort;
|
|
|
|
//Assign the UDP Timeout to the transport layer parameter
|
|
S_TL.wTimeout = 200;
|
|
|
|
//Assign the logger pointer for Transport layer
|
|
S_TL.sLogger.pHdl = PpsAppOCPConfig->sLogger.pHdl;
|
|
S_TL.sLogger.phfWriter = PpsAppOCPConfig->sLogger.phfWriter;
|
|
|
|
//Assign the initial connection state of transport layer
|
|
S_TL.eIsConnected = eDisconnected;
|
|
//Assign receive call function type
|
|
S_TL.eCallType = eNonBlocking;
|
|
|
|
//Assign the logger pointer for Transport layer
|
|
psAppOCPCntx->sConfigRL.sRL.psConfigCL->sCL.sLogger.pHdl = PpsAppOCPConfig->sLogger.pHdl;
|
|
psAppOCPCntx->sConfigRL.sRL.psConfigCL->sCL.sLogger.phfWriter = PpsAppOCPConfig->sLogger.phfWriter;
|
|
|
|
//Initialize all the modules
|
|
//Init for logger
|
|
//lint --e{611} suppress "This is ignored as it is known to the user for data type conversion"
|
|
LOG_SETWRITER((pFWriteData2)PpsAppOCPConfig->sLogger.phfWriter,(Void*)PpsAppOCPConfig->sLogger.pHdl);
|
|
//Init Record Layer
|
|
i4Status = psAppOCPCntx->sConfigRL.pfInit(&psAppOCPCntx->sConfigRL.sRL);
|
|
if(OCP_RL_OK != i4Status)
|
|
{
|
|
break;
|
|
}
|
|
//Init Transport Layer
|
|
i4Status = psAppOCPCntx->sConfigRL.sRL.psConfigTL->pfInit(&S_TL);
|
|
if(OCP_TL_OK != i4Status)
|
|
{
|
|
break;
|
|
}
|
|
//Init Crypto Layer
|
|
i4Status = psAppOCPCntx->sConfigRL.sRL.psConfigCL->pfInit(&psAppOCPCntx->sConfigRL.sRL.psConfigCL->sCL, (Void*)&wSessionKeyId);
|
|
if(OCP_CL_OK != i4Status)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//Update the registry with the session ID being used
|
|
i4Status = Registry_Update(wSessionKeyId,(hdl_t) psAppOCPCntx);
|
|
if(OCP_LIB_OK != i4Status)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//Set the Authentication state to initialised
|
|
psAppOCPCntx->sHandshake.eAuthState = eAuthInitialised;
|
|
|
|
*PphAppOCPCtx = (hdl_t) psAppOCPCntx;
|
|
|
|
psAppOCPCntx->sHandshake.PhAppOCPCtx = *PphAppOCPCtx;
|
|
i4Status = (int32_t)OCP_LIB_OK;
|
|
}while(FALSE);
|
|
|
|
if((OCP_LIB_OK != i4Status) && ((int32_t)OCP_LIB_NULL_PARAM != i4Status) && ((int32_t)OCP_LIB_SESSIONID_UNAVAILABLE != i4Status))
|
|
{
|
|
OCPFreeMemory(psAppOCPCntx);
|
|
}
|
|
/// @cond hidden
|
|
#undef S_TL
|
|
/// @endcond
|
|
return i4Status;
|
|
}
|
|
|
|
|
|
/**
|
|
* This API connects to the server and performs a DTLS handshake protocol as per DTLS v1.2
|
|
* <br>
|
|
* <br>
|
|
* \image html OCPConnect.png "OCP_Connect()" width=20cm
|
|
*
|
|
*<b>Pre Conditions:</b>
|
|
* - #OCP_Init() is successful and application context is available.<br>
|
|
* - Server trust anchor must be available in the security chip.<br>
|
|
*
|
|
*<b>API Details:</b>
|
|
* - Connects to the server via the transport layer.<br>
|
|
* - Invokes CmdLib_SetAuthScheme() based on configuration.<br>
|
|
* - Performs a DTLS Handshake.<br>
|
|
*
|
|
*<b>User Input:</b><br>
|
|
* - User must provide a valid PhAppOCPCtx handle otherwise #OCP_LIB_SESSIONID_UNAVAILABLE is returned.<br>
|
|
*
|
|
*<b>Notes:</b>
|
|
* - The default value of timeout for retransmission must be 2 seconds on the server side.<br>
|
|
* - If a connection already exists on the given port and IP address, #OCP_LIB_CONNECTION_ALREADY_EXISTS is returned.<br>
|
|
* - Under some failure conditions, error codes from lower layers could also be returned. <br>
|
|
* - In case of a Failure other than #OCP_LIB_CONNECTION_ALREADY_EXISTS and #OCP_LIB_SESSIONID_UNAVAILABLE<br>
|
|
* - The Session gets closed automatically.<br>
|
|
* - The memory allocated in #OCP_Init() are freed.<br>
|
|
* - OCP handle will not be set to NULL.It is upto the user to check return code and take appropriate action.<br>
|
|
* - If the return value is #CMD_DEV_EXEC_ERROR, it might indicate that the application on the security chip is either
|
|
* closed or a reset has occurred.<br>
|
|
*
|
|
*
|
|
* \param[in] PhAppOCPCtx Handle to OCP Context
|
|
*
|
|
* \retval #OCP_LIB_OK
|
|
* \retval #OCP_LIB_ERROR
|
|
* \retval #OCP_LIB_NULL_PARAM
|
|
* \retval #OCP_LIB_CONNECTION_ALREADY_EXISTS
|
|
* \retval #OCP_LIB_SESSIONID_UNAVAILABLE
|
|
*/
|
|
int32_t OCP_Connect(const hdl_t PhAppOCPCtx)
|
|
{
|
|
int32_t i4Status = (int32_t)OCP_LIB_ERROR;
|
|
sAuthScheme_d sAuthScheme;
|
|
/// @cond hidden
|
|
#define PS_CNTX ((sAppOCPCtx_d*)PhAppOCPCtx)
|
|
#define S_CONFIGURATION_TL (PS_CNTX->sConfigRL.sRL.psConfigTL)
|
|
#define S_CONFIGURATION_CL (PS_CNTX->sConfigRL.sRL.psConfigCL)
|
|
#define S_CONFIGURATION_RL (PS_CNTX->sConfigRL)
|
|
/// @endcond
|
|
do
|
|
{
|
|
//NULL check for handle
|
|
if(NULL == PS_CNTX)
|
|
{
|
|
i4Status = (int32_t)OCP_LIB_NULL_PARAM;
|
|
break;
|
|
}
|
|
|
|
i4Status = Registry_ValidateHandleSessionID(PhAppOCPCtx);
|
|
if(OCP_LIB_OK != i4Status)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//Null checks for other pointers
|
|
if((NULL == S_CONFIGURATION_TL) || (NULL== S_CONFIGURATION_TL->pfConnect)|| (NULL == PS_CNTX->pfPerformHandshake)||
|
|
(NULL == S_CONFIGURATION_RL.pfSend)|| (NULL == S_CONFIGURATION_RL.pfRecv) || (NULL == S_CONFIGURATION_RL.pfClose) ||
|
|
(NULL == S_CONFIGURATION_TL->pfSend) || (NULL == S_CONFIGURATION_TL->pfRecv) || (NULL == S_CONFIGURATION_TL->pfDisconnect) ||
|
|
(NULL == S_CONFIGURATION_CL) || (NULL == S_CONFIGURATION_CL->pfEncrypt) || (NULL == S_CONFIGURATION_CL->pfDecrypt) ||
|
|
(NULL == S_CONFIGURATION_CL->pfClose))
|
|
{
|
|
i4Status = (int32_t)OCP_LIB_NULL_PARAM;
|
|
break;
|
|
}
|
|
|
|
//Check whether connection is already connected
|
|
if(eConnected == S_CONFIGURATION_TL->sTL.eIsConnected)
|
|
{
|
|
i4Status = (int32_t)OCP_LIB_CONNECTION_ALREADY_EXISTS;
|
|
break;
|
|
}
|
|
//Connect to server
|
|
i4Status = S_CONFIGURATION_TL->pfConnect(&S_CONFIGURATION_TL->sTL);
|
|
if(OCP_TL_OK != i4Status)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//Get the Session OID from registry
|
|
i4Status = Registry_GetHandleSessionID(PhAppOCPCtx,&(PS_CNTX->sHandshake.wSessionOID));
|
|
if(OCP_LIB_OK != i4Status)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//Initialize Auth scheme structure
|
|
sAuthScheme.eAuthScheme = PS_CNTX->eAuthScheme;
|
|
sAuthScheme.wDevicePrivKey = PS_CNTX->sHandshake.wOIDDevPrivKey;
|
|
sAuthScheme.wSessionKeyId = PS_CNTX->sHandshake.wSessionOID;
|
|
|
|
//Set the AuthScheme
|
|
i4Status = CmdLib_SetAuthScheme(&sAuthScheme);
|
|
if(CMD_LIB_OK != i4Status)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//Perform Handshake
|
|
i4Status = PS_CNTX->pfPerformHandshake((hdl_t)&PS_CNTX->sHandshake);
|
|
if(OCP_HL_OK != i4Status)
|
|
{
|
|
break;
|
|
}
|
|
i4Status = (int32_t) OCP_LIB_OK;
|
|
|
|
}while(FALSE);
|
|
|
|
do
|
|
{
|
|
if((OCP_LIB_OK != i4Status) &&
|
|
((int32_t)OCP_LIB_CONNECTION_ALREADY_EXISTS != i4Status) &&
|
|
((int32_t)OCP_LIB_NULL_PARAM != i4Status) &&
|
|
((int32_t)OCP_LIB_SESSIONID_UNAVAILABLE != i4Status))
|
|
{
|
|
//lint --e{794} suppress "OCP_LIB_NULL_PARAM check address this lint issue which doesn't allow null pointer in this context,"
|
|
CloseSession(PhAppOCPCtx,PS_CNTX->sHandshake.fFatalError, PS_CNTX->sHandshake.wSessionOID);
|
|
|
|
LOG_TRANSPORTDBVAL(i4Status,eInfo);
|
|
}
|
|
}while(FALSE);
|
|
|
|
/// @cond hidden
|
|
#undef PS_CNTX
|
|
#undef S_CONFIGURATION_CL
|
|
#undef S_CONFIGURATION_TL
|
|
#undef S_CONFIGURATION_RL
|
|
/// @endcond
|
|
return i4Status;
|
|
}
|
|
|
|
/**
|
|
* This API sends application data to the DTLS server
|
|
* <br>
|
|
* <br>
|
|
* \image html OCPSend.png "OCP_Send()" width=20cm
|
|
*
|
|
*<b>Pre Conditions:</b>
|
|
* - #OCP_Connect() is successful and application context is available.<br>
|
|
*
|
|
*<b>API Details:</b>
|
|
* - Sends application data to DTLS server.<br>
|
|
* - Application data is sent only if Mutual Authentication Public Key Scheme (DTLS) was successfully performed.<br>
|
|
* - Encryption of the application data is done at the record layer.<br>
|
|
*<br>
|
|
*
|
|
*<b>User Input:</b><br>
|
|
* - User must provide a valid PhAppOCPCtx handle.<br>
|
|
* - User must provide the data to be sent and its length
|
|
* - If the length of the data to be sent is greater then #MAX_APP_DATALEN(PhAppOCPCtx), then #OCP_LIB_INVALID_LEN is returned.
|
|
* - If the length of the data to be sent is equal to zero, then #OCP_LIB_LENZERO_ERROR is returned.<br>
|
|
*
|
|
*<b>Notes:</b>
|
|
* - The maximum length of data that can be sent by the API depends upon the PMTU value set during #OCP_Init().This length can be obtained by #MAX_APP_DATALEN(PhAppOCPCtx).<br>
|
|
* - Fragmentation of data to be sent should be done by the application. This API does not perform data fragmentation.<br>
|
|
* - If the record sequence number has reached maximum value for epoch 1, then #OCP_RL_SEQUENCE_OVERFLOW error is returned.
|
|
* User must call #OCP_Disconnect() in this condition.No Alert will be sent due to the unavailability of record sequence number.<br>
|
|
* - Under some failure conditions, error codes from lower layers could also be returned. <br>
|
|
* - In case of a Failure,<br>
|
|
* - Existing session remains open and memory allocated during OCP_Init() is not freed.<br>
|
|
* - PhAppOCPCtx handle is not set to NULL.<br>
|
|
* - The API does not send any alert to the server.<br>
|
|
* - If the return value is #CMD_DEV_EXEC_ERROR, it might indicate that the application on the security chip is either
|
|
* closed or a reset has occurred. In such a case, close the existing DTLS session using #OCP_Disconnect.<br>
|
|
*
|
|
*
|
|
* \param[in] PhAppOCPCtx Handle to OCP Context
|
|
* \param[in] PprgbData Pointer to data to be sent
|
|
* \param[in] PwLen Length of the data to be sent
|
|
*
|
|
* \retval #OCP_LIB_OK
|
|
* \retval #OCP_LIB_ERROR
|
|
* \retval #OCP_LIB_NULL_PARAM
|
|
* \retval #OCP_LIB_SESSIONID_UNAVAILABLE
|
|
* \retval #OCP_LIB_AUTHENTICATION_NOTDONE
|
|
* \retval #OCP_LIB_MALLOC_FAILURE
|
|
* \retval #OCP_LIB_LENZERO_ERROR
|
|
* \retval #OCP_LIB_INVALID_LEN
|
|
* \retval #OCP_RL_SEQUENCE_OVERFLOW
|
|
*/
|
|
int32_t OCP_Send(const hdl_t PhAppOCPCtx,const uint8_t* PprgbData,uint16_t PwLen)
|
|
{
|
|
int32_t i4Status = (int32_t)OCP_LIB_ERROR;
|
|
/// @cond hidden
|
|
#define PS_CNTX ((sAppOCPCtx_d*)PhAppOCPCtx)
|
|
#define S_CONFIGURATION_RL (PS_CNTX->sConfigRL)
|
|
#define S_HS (PS_CNTX->sHandshake)
|
|
/// @endcond
|
|
|
|
do
|
|
{
|
|
//NULL check for handle
|
|
if((NULL == PS_CNTX) || (NULL == PprgbData))
|
|
{
|
|
i4Status = (int32_t)OCP_LIB_NULL_PARAM;
|
|
break;
|
|
}
|
|
|
|
//Validate the handle for the sessionID
|
|
i4Status = Registry_ValidateHandleSessionID(PhAppOCPCtx);
|
|
if(OCP_LIB_OK != i4Status)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//Null checks for other pointers
|
|
if((NULL == PS_CNTX->sConfigRL.sRL.psConfigTL) || (NULL == S_CONFIGURATION_RL.pfSend) ||
|
|
(NULL == PS_CNTX->sConfigRL.sRL.psConfigTL->pfSend) || (NULL == PS_CNTX->sConfigRL.sRL.psConfigCL) ||
|
|
(NULL == PS_CNTX->sConfigRL.sRL.psConfigCL->pfEncrypt))
|
|
{
|
|
i4Status = (int32_t)OCP_LIB_NULL_PARAM;
|
|
break;
|
|
}
|
|
|
|
//Is Authentication session closed
|
|
if(S_HS.eAuthState == eAuthSessionClosed)
|
|
{
|
|
i4Status = (int32_t)OCP_LIB_OPERATION_NOT_ALLOWED;
|
|
break;
|
|
}
|
|
|
|
//Is Mutual Authentication complete
|
|
if(S_HS.eAuthState != eAuthCompleted)
|
|
{
|
|
i4Status = (int32_t)OCP_LIB_AUTHENTICATION_NOTDONE;
|
|
break;
|
|
}
|
|
|
|
//Zero Length
|
|
if(0x00 == PwLen)
|
|
{
|
|
i4Status = (int32_t)OCP_LIB_LENZERO_ERROR;
|
|
break;
|
|
}
|
|
|
|
//If length of data to be sent is greater then Max value
|
|
if(MAX_APP_DATALEN(PhAppOCPCtx) < PwLen)
|
|
{
|
|
i4Status = (int32_t)OCP_LIB_INVALID_LEN;
|
|
break;
|
|
}
|
|
|
|
//Memory need to be allocated
|
|
S_CONFIGURATION_RL.sRL.bContentType = CONTENTTYPE_APP_DATA;
|
|
S_CONFIGURATION_RL.sRL.bMemoryAllocated = FALSE;
|
|
|
|
//Call Record layer
|
|
i4Status = S_CONFIGURATION_RL.pfSend(&S_CONFIGURATION_RL.sRL, (uint8_t*)PprgbData, PwLen);
|
|
if(OCP_RL_OK != i4Status)
|
|
{
|
|
break;
|
|
}
|
|
|
|
i4Status = (int32_t)OCP_LIB_OK;
|
|
}while(FALSE);
|
|
/// @cond hidden
|
|
#undef PS_CNTX
|
|
#undef S_CONFIGURATION_RL
|
|
#undef S_HS
|
|
/// @endcond
|
|
return i4Status;
|
|
}
|
|
|
|
/**
|
|
* This API receives application data from the DTLS server
|
|
* <br>
|
|
* <br>
|
|
* \image html OCPRecv.png "OCP_Recv()" width=20cm
|
|
*
|
|
*<b>Pre Conditions:</b>
|
|
* - #OCP_Connect() is successful and application context is available.<br>
|
|
*
|
|
*<b>API Details:</b>
|
|
* - Receives application data from the DTLS server.<br>
|
|
* - Application data is received only if Mutual Authentication Public Key Scheme (DTLS) was successfully performed.<br>
|
|
* - Received data is assumed to be encrypted and processed accordingly. Decryption of the application data is done at the record layer.<br>
|
|
* - Total received application data length is updated in PpwLen.<br>
|
|
*<br>
|
|
*
|
|
*<b>User Input:</b><br>
|
|
* - User must provide a valid PhAppOCPCtx handle.<br>
|
|
* - User must provide the buffer where application data should be returned.<br>
|
|
* - User must provide the length of the buffer.<br>
|
|
* - If the length of the buffer is equal to zero, then #OCP_LIB_LENZERO_ERROR is returned.<br>
|
|
* - User must provide the timeout value in milliseconds. The value should be greater than 0 and maximum up to (2^16)-1.
|
|
* - If the timeout is zero #OCP_LIB_INVALID_TIMEOUT is returned.
|
|
*
|
|
*<b>Notes:</b>
|
|
* - The maximum length of data that can be received by the API depends upon the PMTU value set during #OCP_Init().This length is indicated by #MAX_APP_DATALEN(PhAppOCPCtx).<br>
|
|
* - If required, the Re-Assembly of received data should be done by the application. This API does not perform data re-assembly.<br>
|
|
* - Failure in decrypting data will return #OCP_LIB_DECRYPT_FAILURE.<br>
|
|
* - If a fatal alert with valid description is received,
|
|
* - #OCP_AL_FATAL_ERROR is returned.<br>
|
|
* - User must invoke #OCP_Disconnect() in this condition.Invoking OCP_Send() or OCP_Recv() will return #OCP_LIB_OPERATION_NOT_ALLOWED.<br>
|
|
* - If a valid Hello request is received, the API internally sends a warning alert with description "no-renegotiation" to the server and then waits for data until timeout occurs.<br>
|
|
* - If the length of buffer provided by the application is not sufficient to return received data, #OCP_LIB_INSUFFICIENT_MEMORY is returned. This data will not be returned in subsequent API invocation.<br>
|
|
* - If timeout occurs,#OCP_LIB_TIMEOUT is returned.
|
|
* - Under some failure conditions, error codes from lower layers could also be returned.<br>
|
|
* - In case of a Failure,<br>
|
|
* - Existing session remains open and memory allocated during OCP_Init() is not freed.<br>
|
|
* - PhAppOCPCtx handle is not set to NULL.<br>
|
|
* - The API does not send any alert to the server.<br>
|
|
* - PpwLen is set to zero.<br>
|
|
* - If the return value is #CMD_DEV_EXEC_ERROR, it might indicate that the application on the security chip is either
|
|
* closed or a reset has occurred. In such a case, close the existing DTLS session using #OCP_Disconnect.<br>
|
|
*
|
|
*
|
|
* \param[in] PhAppOCPCtx Handle to OCP Context
|
|
* \param[in,out] PprgbData Pointer to buffer where data is to be received
|
|
* \param[in,out] PpwLen Pointer to the length of buffer. Updated with actual length of received data.
|
|
* \param[in] PwTimeout Timeout in milliseconds
|
|
*
|
|
* \retval #OCP_LIB_OK
|
|
* \retval #OCP_LIB_ERROR
|
|
* \retval #OCP_LIB_NULL_PARAM
|
|
* \retval #OCP_LIB_SESSIONID_UNAVAILABLE
|
|
* \retval #OCP_LIB_AUTHENTICATION_NOTDONE
|
|
* \retval #OCP_LIB_MALLOC_FAILURE
|
|
* \retval #OCP_LIB_LENZERO_ERROR
|
|
* \retval #OCP_AL_FATAL_ERROR
|
|
* \retval #OCP_LIB_INSUFFICIENT_MEMORY
|
|
* \retval #OCP_LIB_INVALID_TIMEOUT
|
|
* \retval #OCP_LIB_TIMEOUT
|
|
* \retval #OCP_LIB_OPERATION_NOT_ALLOWED
|
|
*/
|
|
int32_t OCP_Receive(const hdl_t PhAppOCPCtx, uint8_t* PprgbData, uint16_t* PpwLen, uint16_t PwTimeout)
|
|
{
|
|
int32_t i4Status = (int32_t)OCP_LIB_ERROR;
|
|
sbBlob_d sAppData;
|
|
int32_t i4Alert;
|
|
uint32_t dwStarttime;
|
|
|
|
/// @cond hidden
|
|
#define PS_CNTX ((sAppOCPCtx_d*)PhAppOCPCtx)
|
|
#define S_CONFIGURATION_RL (PS_CNTX->sConfigRL)
|
|
#define S_HS (PS_CNTX->sHandshake)
|
|
/// @endcond
|
|
do
|
|
{
|
|
//NULL check for handle
|
|
if((NULL == PS_CNTX) || (NULL == PprgbData) || (NULL == PpwLen))
|
|
{
|
|
i4Status = (int32_t)OCP_LIB_NULL_PARAM;
|
|
break;
|
|
}
|
|
|
|
//Validate the handle for the sessionID
|
|
i4Status = Registry_ValidateHandleSessionID(PhAppOCPCtx);
|
|
if(OCP_LIB_OK != i4Status)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//Null checks for other pointers
|
|
if((NULL == PS_CNTX->sConfigRL.sRL.psConfigTL) || (NULL == S_CONFIGURATION_RL.pfRecv) ||
|
|
(NULL == PS_CNTX->sConfigRL.sRL.psConfigTL->pfRecv)|| (NULL == PS_CNTX->sConfigRL.sRL.psConfigCL) ||
|
|
(NULL == PS_CNTX->sConfigRL.sRL.psConfigCL->pfDecrypt))
|
|
{
|
|
i4Status = (int32_t)OCP_LIB_NULL_PARAM;
|
|
break;
|
|
}
|
|
|
|
//Is Authentication session closed
|
|
if(S_HS.eAuthState == eAuthSessionClosed)
|
|
{
|
|
i4Status = (int32_t)OCP_LIB_OPERATION_NOT_ALLOWED;
|
|
break;
|
|
}
|
|
|
|
//Is Mutual Authentication Public Key Scheme (DTLS) complete
|
|
if(S_HS.eAuthState != eAuthCompleted)
|
|
{
|
|
i4Status = (int32_t)OCP_LIB_AUTHENTICATION_NOTDONE;
|
|
break;
|
|
}
|
|
|
|
//Zero Length
|
|
if(0x00 == *PpwLen)
|
|
{
|
|
i4Status = (int32_t)OCP_LIB_LENZERO_ERROR;
|
|
break;
|
|
}
|
|
|
|
if(0x00 == PwTimeout)
|
|
{
|
|
i4Status = (int32_t)OCP_LIB_INVALID_TIMEOUT;
|
|
break;
|
|
}
|
|
|
|
if(NULL == PS_CNTX->pAppDataBuf)
|
|
{
|
|
PS_CNTX->pAppDataBuf = OCP_MALLOC(TLBUFFER_SIZE);
|
|
if(NULL == PS_CNTX->pAppDataBuf)
|
|
{
|
|
i4Status = (int32_t)OCP_LIB_MALLOC_FAILURE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
PS_CNTX->sConfigRL.sRL.psConfigTL->sTL.wTimeout = PwTimeout;
|
|
|
|
//Start value for the Flight timeout
|
|
dwStarttime = pal_os_timer_get_time_in_milliseconds();
|
|
|
|
do
|
|
{
|
|
PS_CNTX->sConfigRL.sRL.bContentType = CONTENTTYPE_APP_DATA;
|
|
|
|
sAppData.prgbStream = PS_CNTX->pAppDataBuf;
|
|
sAppData.wLen = TLBUFFER_SIZE;
|
|
|
|
i4Status = PS_CNTX->sConfigRL.pfRecv((sRL_d*)&(PS_CNTX->sConfigRL.sRL), sAppData.prgbStream, &sAppData.wLen);
|
|
|
|
//Application record received
|
|
if((int32_t)OCP_RL_APPDATA_RECEIVED == i4Status)
|
|
{
|
|
if(sAppData.wLen > *PpwLen)
|
|
{
|
|
i4Status = (int32_t)OCP_LIB_INSUFFICIENT_MEMORY;
|
|
break;
|
|
}
|
|
|
|
*PpwLen = sAppData.wLen;
|
|
Utility_Memmove(PprgbData, sAppData.prgbStream, sAppData.wLen);
|
|
i4Status = OCP_LIB_OK;
|
|
break;
|
|
}
|
|
|
|
|
|
//Alert record received
|
|
if((int32_t)OCP_RL_ALERT_RECEIVED == i4Status)
|
|
{
|
|
|
|
i4Status = Alert_ProcessMsg(&sAppData,&i4Alert);
|
|
if(((int32_t)OCP_AL_FATAL_ERROR == i4Alert))
|
|
{
|
|
S_HS.eAuthState = eAuthSessionClosed;
|
|
i4Status = i4Alert;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//Malloc failure
|
|
if(((int32_t)OCP_RL_MALLOC_FAILURE == i4Status))
|
|
{
|
|
//Exit the state machine
|
|
break;
|
|
}
|
|
|
|
//Decryption failure
|
|
if(((int32_t)CMD_LIB_DECRYPT_FAILURE == i4Status))
|
|
{
|
|
i4Status = (int32_t)OCP_LIB_DECRYPT_FAILURE;
|
|
//Exit
|
|
break;
|
|
}
|
|
|
|
//Handshake record received
|
|
if((int32_t)OCP_RL_OK == i4Status)
|
|
{
|
|
i4Status = DtlsHS_VerifyHR(sAppData.prgbStream, sAppData.wLen);
|
|
if(i4Status == OCP_HL_OK)
|
|
{
|
|
SEND_ALERT(&PS_CNTX->sConfigRL,(int32_t) OCP_LIB_NO_RENEGOTIATE);
|
|
}
|
|
}
|
|
|
|
if((uint32_t)(pal_os_timer_get_time_in_milliseconds() - dwStarttime) > (uint32_t)PwTimeout)
|
|
{
|
|
i4Status = (int32_t)OCP_LIB_TIMEOUT;
|
|
break;
|
|
}
|
|
|
|
//Dynamically setting the UDP timeout
|
|
PS_CNTX->sConfigRL.sRL.psConfigTL->sTL.wTimeout = (uint16_t)(PwTimeout - (uint16_t)(pal_os_timer_get_time_in_milliseconds() - dwStarttime));
|
|
}while(TRUE);
|
|
|
|
|
|
}while(FALSE);
|
|
|
|
|
|
if((OCP_LIB_OK != i4Status) && (NULL != PpwLen))
|
|
{
|
|
*PpwLen = 0x00;
|
|
}
|
|
|
|
//lint --e{794} suppress "OCP_LIB_NULL_PARAM check addresses this lint issue which doesn't allow null pointer in this context,"
|
|
if(((int32_t)OCP_LIB_NULL_PARAM != i4Status) && ((int32_t)OCP_LIB_SESSIONID_UNAVAILABLE != i4Status) &&
|
|
((int32_t)OCP_LIB_OPERATION_NOT_ALLOWED != i4Status) && ((int32_t)OCP_LIB_AUTHENTICATION_NOTDONE != i4Status) &&
|
|
((int32_t)OCP_LIB_LENZERO_ERROR != i4Status) && ((int32_t)OCP_LIB_INVALID_TIMEOUT != i4Status) &&
|
|
(NULL != PS_CNTX->pAppDataBuf) && (PS_CNTX->sConfigRL.sRL.bMultipleRecord == 0))
|
|
{
|
|
OCP_FREE(PS_CNTX->pAppDataBuf);
|
|
PS_CNTX->pAppDataBuf = NULL;
|
|
}
|
|
|
|
/// @cond hidden
|
|
#undef PS_CNTX
|
|
#undef S_CONFIGURATION_RL
|
|
#undef S_HS
|
|
/// @endcond
|
|
return i4Status;
|
|
}
|
|
|
|
/**
|
|
* This API disconnects the client from the server and closes the DTLS session
|
|
* <br>
|
|
* <br>
|
|
* \image html OCPDisconnect.png "OCP_Disconnect()" width=20cm
|
|
*
|
|
*<b>Pre Conditions:</b>
|
|
* - OCP_Init() or OCP_Connect() is successful.<br>
|
|
*
|
|
*<b>API Details:</b>
|
|
* - Applicable only if called after a successful OCP_Connect()
|
|
* - Closes DTLS session on security chip via CmdLib_CloseSession().<br>
|
|
* - Sends closure alert to the server via the transport layer.<br>
|
|
* - Disconnects from the server via the transport layer.<br>
|
|
* - Applicable if called after successful OCP_Init() or OCP_Connect()
|
|
* - Clear memory associated with PhAppOCPCtx handle.<br>
|
|
* - Clears the internal session reference Id registry.<br>
|
|
* - PhAppOCPCtx handle will not be set to NULL.It is up to the user to check return code and take appropriate action.<br>
|
|
* <br>
|
|
*
|
|
*<b>User Input:</b><br>
|
|
* - User must provide a valid PhAppOCPCtx handle.<br>
|
|
*
|
|
* Notes: <br>
|
|
* - If the record sequence number has reached maximum value for epoch 1, No Alert will be send due to the unavailability of record sequence number.<br>
|
|
* - DTLS server will not be notified of the fault condition that leads to failure while sending Close_Notify alert.
|
|
*
|
|
*
|
|
* \param[in] PhAppOCPCtx Handle to OCP Context
|
|
*
|
|
* \retval #OCP_LIB_OK
|
|
* \retval #OCP_LIB_NULL_PARAM
|
|
* \retval #OCP_LIB_ERROR
|
|
*/
|
|
int32_t OCP_Disconnect(hdl_t PhAppOCPCtx)
|
|
{
|
|
int32_t i4Status = (int32_t)OCP_LIB_ERROR;
|
|
uint16_t wSessionId = 0;
|
|
/// @cond hidden
|
|
#define PS_CNTX ((sAppOCPCtx_d*)PhAppOCPCtx)
|
|
#define S_CONFIGURATION_TL (PS_CNTX->sConfigRL.sRL.psConfigTL)
|
|
#define S_CONFIGURATION_CL (PS_CNTX->sConfigRL.sRL.psConfigCL)
|
|
/// @endcond
|
|
do
|
|
{
|
|
//NULL check for handle
|
|
if(NULL == PS_CNTX)
|
|
{
|
|
i4Status = (int32_t)OCP_LIB_NULL_PARAM;
|
|
break;
|
|
}
|
|
|
|
//Validate the handle for the sessionID
|
|
i4Status = Registry_ValidateHandleSessionID(PhAppOCPCtx);
|
|
if(OCP_LIB_OK != i4Status)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//Null checks
|
|
if((NULL == S_CONFIGURATION_TL) || (NULL == S_CONFIGURATION_CL) || (NULL == S_CONFIGURATION_CL->pfClose) ||
|
|
(NULL == S_CONFIGURATION_TL->pfDisconnect) || (NULL == PS_CNTX->sConfigRL.pfClose))
|
|
{
|
|
i4Status = (int32_t)OCP_LIB_NULL_PARAM;
|
|
break;
|
|
}
|
|
|
|
//Get the session ID associated with the handle
|
|
i4Status = Registry_GetHandleSessionID(PhAppOCPCtx, &wSessionId);
|
|
if(OCP_LIB_OK != i4Status)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//Close the session and free the memory allocated
|
|
CloseSession(PhAppOCPCtx, PS_CNTX->sHandshake.fFatalError, wSessionId);
|
|
|
|
PhAppOCPCtx = NULL;
|
|
|
|
}while(FALSE);
|
|
|
|
/// @cond hidden
|
|
#undef PS_CNTX
|
|
#undef S_CONFIGURATION_TL
|
|
#undef S_CONFIGURATION_CL
|
|
/// @endcond
|
|
return i4Status;
|
|
}
|
|
|
|
/**
|
|
* @}
|
|
*/
|
|
#endif /*MODULE_ENABLE_DTLS_MUTUAL_AUTH*/
|