481 lines
17 KiB
C
481 lines
17 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 AlertProtocol.c
|
|
*
|
|
* \brief This file implements the DTLS Alert Protocol.
|
|
*
|
|
* \addtogroup grMutualAuth
|
|
* @{
|
|
*/
|
|
|
|
#include "optiga/dtls/DtlsRecordLayer.h"
|
|
#include "optiga/dtls/AlertProtocol.h"
|
|
#include "optiga/dtls/DtlsFlightHandler.h"
|
|
|
|
#ifdef MODULE_ENABLE_DTLS_MUTUAL_AUTH
|
|
|
|
|
|
/// @cond hidden
|
|
|
|
/// Maximum size of Alert Message
|
|
#define LENGTH_ALERT_MSG 0x02
|
|
|
|
/// Offset for Alert Message
|
|
#define OFFSET_ALERT_MSG 0x01
|
|
|
|
//Device Error codes
|
|
|
|
///Invalid OID
|
|
#define INVALID_OID 0x01
|
|
///Invalid param field in the command
|
|
#define INVALID_PARAM_FIELD 0x03
|
|
///Invalid length field in the command
|
|
#define INVALID_LENGTH_FIELD 0x04
|
|
///Invalid parameter in the data field
|
|
#define INVALID_PARAMETER_DATA_FIELD 0x05
|
|
///Device internal error
|
|
#define INTERNAL_PROCESS_ERROR 0x06
|
|
///Invalid command field
|
|
#define INVALID_COMMAND_FIELD 0x0A
|
|
///Command out of sequence
|
|
#define COMMAND_OUT_SEQUENCE 0x0B
|
|
///Command not available
|
|
#define COMMAND_NOT_AVAILABLE 0x0C
|
|
///Illegal parameter in the Handshake header
|
|
#define INVALID_HANDSHAKE_MESSAGE 0x21
|
|
///DTLS Protocol version mismatch
|
|
#define VERSION_MISMATCH 0x22
|
|
///Cipher suite mismatch between client and server
|
|
#define INSUFFICIENT_UNSUPPORTED_CIPHERSUITE 0x23
|
|
///Unsupported extension
|
|
#define UNSUPPORTED_EXTENSION 0x24
|
|
///Unsupported parameters
|
|
#define UNSUPPORTED_PARAMETERS 0x25
|
|
///Invalid Trust Anchor
|
|
#define INVALID_TRUST_ANCHOR 0x26
|
|
///Trust Anchor expired
|
|
#define TRUST_ANCHOR_EXPIRED 0x27
|
|
///Unsupported Trust Anchor
|
|
#define UNSUPPORTED_TRUST_ANCHOR 0x28
|
|
///Invalid Certificate format
|
|
#define INVALID_CERTIFICATE_FORMAT 0x29
|
|
///Unsupported certificate/Unsupported Hash or Sign Algorithm
|
|
#define UNSUPPORTED_CERTIFICATE_HASHSIGN 0x2A
|
|
///Certificate expired
|
|
#define CERTIFICATE_EXPIRED 0x2B
|
|
///Signature verification failed
|
|
#define SIGNATURE_VERIFICATION_FAILURE 0x2C
|
|
|
|
|
|
/**
|
|
* \brief DTLS Alert Level.
|
|
*/
|
|
typedef enum eAlertLevel_d
|
|
{
|
|
///Connection can continue
|
|
eWARNING = 0x01,
|
|
///Terminate the connection
|
|
eFATAL = 0x02
|
|
}eAlertLevel_d;
|
|
|
|
/**
|
|
* \brief DTLS Alert Types.
|
|
*/
|
|
typedef enum eAlertMsg_d
|
|
{
|
|
/// Notifies the recipient that the sender will not send any more messages on this connection
|
|
eCLOSE_NOTIFY = 0x00,
|
|
/// Inappropriate message was received
|
|
eUNEXPECTED_MESSAGE = 0x0A ,
|
|
/// Notifies record is received with an incorrect MAC
|
|
eBAD_RECORD_MAC = 0x14,
|
|
///Decryption Failure
|
|
eDECRYPTION_FAILURE = 0x15,
|
|
/// Notifies record received length is more than 2^14+2048
|
|
eRECORD_OVERFLOW = 0x16,
|
|
/// Notifies decompression function received improper input
|
|
eDECOMPRESSION_FAILURE = 0x1E,
|
|
/// Indicates sender was not able to negotiate with the security parameters
|
|
eHANDSHAKE_FAILURE = 0x28,
|
|
/// Notifies certificate was corrupt
|
|
eBAD_CERTIFICATE = 0x2A,
|
|
///No certificate
|
|
eNO_CERTIFICATE = 0x29,
|
|
/// Notifies certificate was unsupported type
|
|
eUNSUPPORTED_CERTIFICATE = 0x2B,
|
|
/// Notifies the certificate was revoked by signer
|
|
eCERTIFICATE_REVOKED = 0x2C,
|
|
/// Indicates the certificate is Expired
|
|
eCERTIFICATE_EXPIRED = 0x2D,
|
|
/// Indicates unknown issue in processing the certificate
|
|
eCERTIFICATE_UNKNOWN = 0x2E,
|
|
/// Notifies field in handshake is out of range or inconsistent
|
|
eILLEGAL_PARAMETER = 0x2F,
|
|
/// Indicates CA certificate could not be found or not matched
|
|
eUNKNOWN_CA = 0x30,
|
|
/// Notifies the access denied
|
|
eACCESS_DENIED = 0x31,
|
|
/// Notifies message could not be decoded or some field is missing
|
|
eDECODE_ERROR = 0x32,
|
|
/// Notifies cryptographic operation failed
|
|
eDECRYPT_ERROR = 0x33,
|
|
///Export restriction
|
|
eEXPORT_RESTRICTION = 0x3C,
|
|
/// Notifies protocol version attempted to negotiate is not supported
|
|
ePROTOCOL_VERSION = 0x46,
|
|
/// Notifies negotiation has failed specifically because the server requires ciphers more secure
|
|
eINSUFFICIENT_SECURITY = 0x47,
|
|
/// Notifies error is unrelated to peer or protocol
|
|
eINTERNAL_ERROR = 0x50,
|
|
/// Indicates that the handshake is canceled
|
|
eUSER_CANCELLED = 0x5A,
|
|
/// Notifies that the renegotiation is not initiated
|
|
eNO_RENEGOTIATION = 0x64,
|
|
/// Notifies unsupported extension was sent to server
|
|
eUNSUPPORTED_EXTENSION = 0x6E
|
|
}eAlertMsg_d;
|
|
/// @endcond
|
|
|
|
/**
|
|
* \brief Maps the Alert types and level to error code.<br>
|
|
*/
|
|
_STATIC_H int32_t DtlsAlertErrorMapping(const sbBlob_d* PpsAlertMsg, int32_t* Ppi4ErrorCode);
|
|
|
|
//Alert protocol is defined by default. To disable define DISABLE_ALERT
|
|
#ifndef DISABLE_ALERT
|
|
|
|
/**
|
|
* \brief Maps the error code to Alert types and level.<br>
|
|
*/
|
|
_STATIC_H Void DtlsErrorAlertMapping(int32_t Pi4ErrorCode, sbBlob_d* PpsAlertMsg);
|
|
|
|
/**
|
|
* \brief Forms the alert message based on the given internal error code.<br>
|
|
*/
|
|
_STATIC_H Void Alert_FormMsg(int32_t Pi4ErrorCode,sbBlob_d* PpsAlertMsg);
|
|
|
|
/**
|
|
* Maps the error code to Alert types and level.<br>
|
|
*
|
|
* \param[in] Pi4ErrorCode DTLS Internal error code
|
|
* \param[in,out] PpsAlertMsg Pointer to a blob containing Alert message as per DTLS Specification
|
|
*
|
|
*/
|
|
_STATIC_H Void DtlsErrorAlertMapping(int32_t Pi4ErrorCode, sbBlob_d* PpsAlertMsg)
|
|
{
|
|
do
|
|
{
|
|
if((int32_t)OCP_LIB_NO_RENEGOTIATE == Pi4ErrorCode)
|
|
{
|
|
*PpsAlertMsg->prgbStream = (uint8_t)eWARNING;
|
|
}
|
|
else
|
|
{
|
|
*PpsAlertMsg->prgbStream = (uint8_t)eFATAL;
|
|
}
|
|
//Set the Blob length to Alert message length
|
|
PpsAlertMsg->wLen = LENGTH_ALERT_MSG;
|
|
|
|
switch(Pi4ErrorCode)
|
|
{
|
|
case (int32_t)OCP_RL_ERROR:
|
|
case (int32_t)OCP_FL_MSG_MAXCOUNT:
|
|
//Prepare Alert Message
|
|
*(PpsAlertMsg->prgbStream + OFFSET_ALERT_MSG) = (uint8_t)eCLOSE_NOTIFY;
|
|
break;
|
|
case (int32_t)(CMD_DEV_ERROR | INVALID_HANDSHAKE_MESSAGE):
|
|
case (int32_t)(CMD_DEV_ERROR | UNSUPPORTED_PARAMETERS):
|
|
case (int32_t)(CMD_DEV_ERROR | VERSION_MISMATCH):
|
|
case (int32_t) OCP_FL_HS_ERROR:
|
|
//Prepare Alert Message
|
|
*(PpsAlertMsg->prgbStream + OFFSET_ALERT_MSG) = (uint8_t)eILLEGAL_PARAMETER;
|
|
break;
|
|
case (int32_t)OCP_LIB_NO_RENEGOTIATE:
|
|
//Prepare Alert Message
|
|
*(PpsAlertMsg->prgbStream + OFFSET_ALERT_MSG) = (uint8_t)eNO_RENEGOTIATION;
|
|
break;
|
|
case (int32_t)(CMD_DEV_ERROR | INSUFFICIENT_UNSUPPORTED_CIPHERSUITE):
|
|
//Prepare Alert Message
|
|
*(PpsAlertMsg->prgbStream + OFFSET_ALERT_MSG) = (uint8_t)eINSUFFICIENT_SECURITY;
|
|
break;
|
|
case (int32_t)(CMD_DEV_ERROR | UNSUPPORTED_EXTENSION):
|
|
//Prepare Alert Message
|
|
*(PpsAlertMsg->prgbStream + OFFSET_ALERT_MSG) = (uint8_t)eUNSUPPORTED_EXTENSION;
|
|
break;
|
|
|
|
case (int32_t)(CMD_DEV_ERROR | INVALID_TRUST_ANCHOR):
|
|
//Prepare Alert Message
|
|
*(PpsAlertMsg->prgbStream + OFFSET_ALERT_MSG) = (uint8_t)eUNKNOWN_CA;
|
|
break;
|
|
case (int32_t)(CMD_DEV_ERROR | TRUST_ANCHOR_EXPIRED):
|
|
//Prepare Alert Message
|
|
*(PpsAlertMsg->prgbStream + OFFSET_ALERT_MSG) = (uint8_t)eCERTIFICATE_EXPIRED;
|
|
break;
|
|
case (int32_t)(CMD_DEV_ERROR | UNSUPPORTED_TRUST_ANCHOR):
|
|
//Prepare Alert Message
|
|
*(PpsAlertMsg->prgbStream + OFFSET_ALERT_MSG) = (uint8_t)eUNSUPPORTED_CERTIFICATE;
|
|
break;
|
|
case (int32_t)(CMD_DEV_ERROR | INVALID_CERTIFICATE_FORMAT):
|
|
//Prepare Alert Message
|
|
*(PpsAlertMsg->prgbStream + OFFSET_ALERT_MSG) = (uint8_t)eBAD_CERTIFICATE;
|
|
break;
|
|
case (int32_t)(CMD_DEV_ERROR | UNSUPPORTED_CERTIFICATE_HASHSIGN):
|
|
//Prepare Alert Message
|
|
*(PpsAlertMsg->prgbStream + OFFSET_ALERT_MSG) = (uint8_t)eUNSUPPORTED_CERTIFICATE;
|
|
break;
|
|
case (int32_t)(CMD_DEV_ERROR | CERTIFICATE_EXPIRED):
|
|
//Prepare Alert Message
|
|
*(PpsAlertMsg->prgbStream + OFFSET_ALERT_MSG) = (uint8_t)eCERTIFICATE_EXPIRED;
|
|
break;
|
|
case (int32_t)(CMD_DEV_ERROR | SIGNATURE_VERIFICATION_FAILURE):
|
|
//Prepare Alert Message
|
|
*(PpsAlertMsg->prgbStream + OFFSET_ALERT_MSG) = (uint8_t)eDECRYPT_ERROR;
|
|
break;
|
|
default:
|
|
//lint -e750 "The remaining errors returned by the security chip is mapped to Internal error Alert"
|
|
//Prepare Alert Message
|
|
*(PpsAlertMsg->prgbStream + OFFSET_ALERT_MSG) = (uint8_t)eINTERNAL_ERROR;
|
|
break;
|
|
}
|
|
}while(0);
|
|
}
|
|
|
|
/**
|
|
* Forms the alert message based on the given internal error code.<br>
|
|
*
|
|
* \param[in] Pi4ErrorCode DTLS Internal error code
|
|
* \param[in,out] PpsAlertMsg Pointer to a blob containing Alert message as per DTLS Specification
|
|
*
|
|
*/
|
|
_STATIC_H Void Alert_FormMsg(int32_t Pi4ErrorCode,sbBlob_d* PpsAlertMsg)
|
|
{
|
|
//Maps the internal error code to the Alert messages
|
|
DtlsErrorAlertMapping(Pi4ErrorCode,PpsAlertMsg);
|
|
}
|
|
|
|
#endif //DISABLE_ALERT
|
|
|
|
/**
|
|
* Maps the Alert types and level to error code.<br>
|
|
*
|
|
* \param[in] PpsAlertMsg Pointer to a blob containing Alert message as per DTLS Specification
|
|
* \param[in,out] Ppi4ErrorCode Pointer to the DTLS Internal error code
|
|
*
|
|
* \retval #OCP_AL_OK Successful execution
|
|
* \retval #OCP_AL_ERROR Failure in execution
|
|
*
|
|
*/
|
|
_STATIC_H int32_t DtlsAlertErrorMapping(const sbBlob_d* PpsAlertMsg, int32_t* Ppi4ErrorCode)
|
|
{
|
|
int32_t i4Status = (int32_t)OCP_AL_ERROR;
|
|
|
|
do
|
|
{
|
|
//Check for the Alert level type
|
|
if(eFATAL == (eAlertLevel_d)*PpsAlertMsg->prgbStream)
|
|
{
|
|
//Check for various fatal alert messages
|
|
switch((eAlertMsg_d) *(PpsAlertMsg->prgbStream + OFFSET_ALERT_MSG))
|
|
{
|
|
case eCLOSE_NOTIFY:
|
|
case eUNEXPECTED_MESSAGE:
|
|
case eBAD_RECORD_MAC:
|
|
case eDECRYPTION_FAILURE:
|
|
case eRECORD_OVERFLOW:
|
|
case eDECOMPRESSION_FAILURE:
|
|
case eHANDSHAKE_FAILURE:
|
|
case eBAD_CERTIFICATE:
|
|
case eUNSUPPORTED_CERTIFICATE:
|
|
case eNO_CERTIFICATE:
|
|
case eCERTIFICATE_REVOKED:
|
|
case eCERTIFICATE_EXPIRED:
|
|
case eCERTIFICATE_UNKNOWN:
|
|
case eUSER_CANCELLED:
|
|
case eNO_RENEGOTIATION:
|
|
case eILLEGAL_PARAMETER:
|
|
case eUNKNOWN_CA:
|
|
case eACCESS_DENIED:
|
|
case eDECODE_ERROR:
|
|
case eDECRYPT_ERROR:
|
|
case eEXPORT_RESTRICTION:
|
|
case ePROTOCOL_VERSION:
|
|
case eINSUFFICIENT_SECURITY:
|
|
case eINTERNAL_ERROR:
|
|
case eUNSUPPORTED_EXTENSION:
|
|
{
|
|
*Ppi4ErrorCode = (int32_t)OCP_AL_FATAL_ERROR;
|
|
i4Status = (int32_t)OCP_AL_OK;
|
|
}
|
|
break;
|
|
default:
|
|
//Indicates the received Alert is not a valid Fatal Error
|
|
|
|
break;
|
|
}
|
|
}
|
|
//Check for Warning Alert level type
|
|
else if (eWARNING == (eAlertLevel_d)*PpsAlertMsg->prgbStream)
|
|
{
|
|
//Check for various warning alert messages
|
|
switch((eAlertMsg_d) *(PpsAlertMsg->prgbStream + OFFSET_ALERT_MSG))
|
|
{
|
|
case eBAD_CERTIFICATE:
|
|
case eUNSUPPORTED_CERTIFICATE:
|
|
case eCERTIFICATE_REVOKED:
|
|
case eCERTIFICATE_EXPIRED:
|
|
case eCERTIFICATE_UNKNOWN:
|
|
case eUSER_CANCELLED:
|
|
case eNO_RENEGOTIATION:
|
|
{
|
|
|
|
*Ppi4ErrorCode = (int32_t)OCP_AL_WARNING_ERROR;
|
|
i4Status = (int32_t)OCP_AL_OK;
|
|
break;
|
|
}
|
|
default:
|
|
//lint -e788 suppress "As the enum values are divided between Fatal and warning levels"
|
|
//Indicates the received Alert is not a valid warning Error
|
|
|
|
break;
|
|
}
|
|
}
|
|
}while(0);
|
|
return i4Status;
|
|
}
|
|
|
|
|
|
#ifndef DISABLE_ALERT
|
|
/**
|
|
* Sends Alert based on the internal error code via the Record Layer.<br>
|
|
*
|
|
* \param[in] PpsConfigRL Pointer to structure containing Record Layer information.
|
|
* \param[in] Pi4ErrorCode DTLS Internal error code
|
|
*
|
|
*/
|
|
void Alert_Send(sConfigRL_d *PpsConfigRL,int32_t Pi4ErrorCode)
|
|
{
|
|
int32_t i4Status = (int32_t)OCP_AL_ERROR;
|
|
sbBlob_d sAlertMsg;
|
|
uint8_t bEncFlag = 0;
|
|
uint8_t bFlagIncr = 0;
|
|
uint8_t rgbAlertMsg[LENGTH_ALERT_MSG];
|
|
|
|
//Null checks
|
|
if((NULL != PpsConfigRL) && (NULL != PpsConfigRL->pfSend) && (NULL != PpsConfigRL->sRL.phRLHdl))
|
|
{
|
|
do
|
|
{
|
|
/// @cond hidden
|
|
#define PS_RECORDLAYER ((sRecordLayer_d*)PpsConfigRL->sRL.phRLHdl)
|
|
/// @endcond
|
|
|
|
sAlertMsg.prgbStream = rgbAlertMsg;
|
|
sAlertMsg.wLen = LENGTH_ALERT_MSG;
|
|
|
|
//Form the Alert message based on internal error code
|
|
Alert_FormMsg(Pi4ErrorCode, &sAlertMsg);
|
|
|
|
PpsConfigRL->sRL.bMemoryAllocated = FALSE;
|
|
PpsConfigRL->sRL.bContentType = CONTENTTYPE_ALERT;
|
|
|
|
//Until successful completion of Mutual Authentication Public Key Scheme (DTLS) the Client should use previous epoch and messages must not be encrypted
|
|
if(((PS_RECORDLAYER->wServerEpoch != PS_RECORDLAYER->wClientNextEpoch) && (*PS_RECORDLAYER->pbDec != 0x01)) ||
|
|
(Pi4ErrorCode == (int32_t)OCP_FL_INT_ERROR) || (Pi4ErrorCode == (int32_t)OCP_FL_HS_ERROR))
|
|
{
|
|
if((PS_RECORDLAYER->bEncDecFlag == ENC_DEC_ENABLED) && (PS_RECORDLAYER->wClientEpoch != PS_RECORDLAYER->wClientNextEpoch))
|
|
{
|
|
bEncFlag = PS_RECORDLAYER->bEncDecFlag;
|
|
PS_RECORDLAYER->bEncDecFlag = ENC_DEC_DISABLED;
|
|
PS_RECORDLAYER->wClientNextEpoch--;
|
|
bFlagIncr = 0x01;
|
|
}
|
|
}
|
|
//Send the Alert message via record layer
|
|
i4Status = PpsConfigRL->pfSend(&PpsConfigRL->sRL, sAlertMsg.prgbStream, sAlertMsg.wLen);
|
|
|
|
if(bFlagIncr == 0x01)
|
|
{
|
|
PS_RECORDLAYER->bEncDecFlag = bEncFlag;
|
|
PS_RECORDLAYER->wClientNextEpoch++;
|
|
}
|
|
|
|
if(OCP_RL_OK != i4Status)
|
|
{
|
|
break;
|
|
}
|
|
|
|
}while(FALSE);
|
|
|
|
/// @cond hidden
|
|
#undef PS_RECORDLAYER
|
|
/// @endcond
|
|
}
|
|
}
|
|
#endif //DISABLE_ALERT
|
|
/**
|
|
* Processes the received Alert Message<br>
|
|
* Returns the corresponding internal error code.<br>
|
|
*
|
|
* \param[in] PpsAlertMsg Pointer to a blob containing Alert message as per DTLS Specification
|
|
* \param[in,out] Ppi4ErrorCode Pointer to the DTLS Internal error code
|
|
*
|
|
* \retval #OCP_AL_OK Successful execution
|
|
* \retval #OCP_AL_ERROR Failure in execution
|
|
\if ENABLE_NULL_CHECKS
|
|
* \retval #OCP_AL_NULL_PARAM Null parameter(s)
|
|
\endif
|
|
* \retval #OCP_AL_LENZERO_ERROR Length of input parameter is zero
|
|
*
|
|
*/
|
|
int32_t Alert_ProcessMsg(const sbBlob_d* PpsAlertMsg,int32_t* Ppi4ErrorCode)
|
|
{
|
|
int32_t i4Status = (int32_t)OCP_AL_ERROR;
|
|
|
|
do
|
|
{
|
|
#ifdef ENABLE_NULL_CHECKS
|
|
//NULL check for the input parameters
|
|
if((NULL == PpsAlertMsg) || (NULL == Ppi4ErrorCode)|| (NULL == PpsAlertMsg->prgbStream))
|
|
{
|
|
i4Status = (int32_t)OCP_AL_NULL_PARAM;
|
|
break;
|
|
}
|
|
#endif
|
|
//Check for length is less than Alert message size
|
|
if(LENGTH_ALERT_MSG != PpsAlertMsg->wLen)
|
|
{
|
|
break;
|
|
}
|
|
//Maps the received Alert messages to the internal error codes
|
|
i4Status = DtlsAlertErrorMapping(PpsAlertMsg, Ppi4ErrorCode);
|
|
}while(0);
|
|
return i4Status;
|
|
}
|
|
|
|
/**
|
|
* @}
|
|
*/
|
|
#endif /*MODULE_ENABLE_DTLS_MUTUAL_AUTH */
|