AlertProtocol.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480
  1. /**
  2. * MIT License
  3. *
  4. * Copyright (c) 2018 Infineon Technologies AG
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining a copy
  7. * of this software and associated documentation files (the "Software"), to deal
  8. * in the Software without restriction, including without limitation the rights
  9. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. * copies of the Software, and to permit persons to whom the Software is
  11. * furnished to do so, subject to the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be included in all
  14. * copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  22. * SOFTWARE
  23. *
  24. *
  25. * \file AlertProtocol.c
  26. *
  27. * \brief This file implements the DTLS Alert Protocol.
  28. *
  29. * \addtogroup grMutualAuth
  30. * @{
  31. */
  32. #include "optiga/dtls/DtlsRecordLayer.h"
  33. #include "optiga/dtls/AlertProtocol.h"
  34. #include "optiga/dtls/DtlsFlightHandler.h"
  35. #ifdef MODULE_ENABLE_DTLS_MUTUAL_AUTH
  36. /// @cond hidden
  37. /// Maximum size of Alert Message
  38. #define LENGTH_ALERT_MSG 0x02
  39. /// Offset for Alert Message
  40. #define OFFSET_ALERT_MSG 0x01
  41. //Device Error codes
  42. ///Invalid OID
  43. #define INVALID_OID 0x01
  44. ///Invalid param field in the command
  45. #define INVALID_PARAM_FIELD 0x03
  46. ///Invalid length field in the command
  47. #define INVALID_LENGTH_FIELD 0x04
  48. ///Invalid parameter in the data field
  49. #define INVALID_PARAMETER_DATA_FIELD 0x05
  50. ///Device internal error
  51. #define INTERNAL_PROCESS_ERROR 0x06
  52. ///Invalid command field
  53. #define INVALID_COMMAND_FIELD 0x0A
  54. ///Command out of sequence
  55. #define COMMAND_OUT_SEQUENCE 0x0B
  56. ///Command not available
  57. #define COMMAND_NOT_AVAILABLE 0x0C
  58. ///Illegal parameter in the Handshake header
  59. #define INVALID_HANDSHAKE_MESSAGE 0x21
  60. ///DTLS Protocol version mismatch
  61. #define VERSION_MISMATCH 0x22
  62. ///Cipher suite mismatch between client and server
  63. #define INSUFFICIENT_UNSUPPORTED_CIPHERSUITE 0x23
  64. ///Unsupported extension
  65. #define UNSUPPORTED_EXTENSION 0x24
  66. ///Unsupported parameters
  67. #define UNSUPPORTED_PARAMETERS 0x25
  68. ///Invalid Trust Anchor
  69. #define INVALID_TRUST_ANCHOR 0x26
  70. ///Trust Anchor expired
  71. #define TRUST_ANCHOR_EXPIRED 0x27
  72. ///Unsupported Trust Anchor
  73. #define UNSUPPORTED_TRUST_ANCHOR 0x28
  74. ///Invalid Certificate format
  75. #define INVALID_CERTIFICATE_FORMAT 0x29
  76. ///Unsupported certificate/Unsupported Hash or Sign Algorithm
  77. #define UNSUPPORTED_CERTIFICATE_HASHSIGN 0x2A
  78. ///Certificate expired
  79. #define CERTIFICATE_EXPIRED 0x2B
  80. ///Signature verification failed
  81. #define SIGNATURE_VERIFICATION_FAILURE 0x2C
  82. /**
  83. * \brief DTLS Alert Level.
  84. */
  85. typedef enum eAlertLevel_d
  86. {
  87. ///Connection can continue
  88. eWARNING = 0x01,
  89. ///Terminate the connection
  90. eFATAL = 0x02
  91. }eAlertLevel_d;
  92. /**
  93. * \brief DTLS Alert Types.
  94. */
  95. typedef enum eAlertMsg_d
  96. {
  97. /// Notifies the recipient that the sender will not send any more messages on this connection
  98. eCLOSE_NOTIFY = 0x00,
  99. /// Inappropriate message was received
  100. eUNEXPECTED_MESSAGE = 0x0A ,
  101. /// Notifies record is received with an incorrect MAC
  102. eBAD_RECORD_MAC = 0x14,
  103. ///Decryption Failure
  104. eDECRYPTION_FAILURE = 0x15,
  105. /// Notifies record received length is more than 2^14+2048
  106. eRECORD_OVERFLOW = 0x16,
  107. /// Notifies decompression function received improper input
  108. eDECOMPRESSION_FAILURE = 0x1E,
  109. /// Indicates sender was not able to negotiate with the security parameters
  110. eHANDSHAKE_FAILURE = 0x28,
  111. /// Notifies certificate was corrupt
  112. eBAD_CERTIFICATE = 0x2A,
  113. ///No certificate
  114. eNO_CERTIFICATE = 0x29,
  115. /// Notifies certificate was unsupported type
  116. eUNSUPPORTED_CERTIFICATE = 0x2B,
  117. /// Notifies the certificate was revoked by signer
  118. eCERTIFICATE_REVOKED = 0x2C,
  119. /// Indicates the certificate is Expired
  120. eCERTIFICATE_EXPIRED = 0x2D,
  121. /// Indicates unknown issue in processing the certificate
  122. eCERTIFICATE_UNKNOWN = 0x2E,
  123. /// Notifies field in handshake is out of range or inconsistent
  124. eILLEGAL_PARAMETER = 0x2F,
  125. /// Indicates CA certificate could not be found or not matched
  126. eUNKNOWN_CA = 0x30,
  127. /// Notifies the access denied
  128. eACCESS_DENIED = 0x31,
  129. /// Notifies message could not be decoded or some field is missing
  130. eDECODE_ERROR = 0x32,
  131. /// Notifies cryptographic operation failed
  132. eDECRYPT_ERROR = 0x33,
  133. ///Export restriction
  134. eEXPORT_RESTRICTION = 0x3C,
  135. /// Notifies protocol version attempted to negotiate is not supported
  136. ePROTOCOL_VERSION = 0x46,
  137. /// Notifies negotiation has failed specifically because the server requires ciphers more secure
  138. eINSUFFICIENT_SECURITY = 0x47,
  139. /// Notifies error is unrelated to peer or protocol
  140. eINTERNAL_ERROR = 0x50,
  141. /// Indicates that the handshake is canceled
  142. eUSER_CANCELLED = 0x5A,
  143. /// Notifies that the renegotiation is not initiated
  144. eNO_RENEGOTIATION = 0x64,
  145. /// Notifies unsupported extension was sent to server
  146. eUNSUPPORTED_EXTENSION = 0x6E
  147. }eAlertMsg_d;
  148. /// @endcond
  149. /**
  150. * \brief Maps the Alert types and level to error code.<br>
  151. */
  152. _STATIC_H int32_t DtlsAlertErrorMapping(const sbBlob_d* PpsAlertMsg, int32_t* Ppi4ErrorCode);
  153. //Alert protocol is defined by default. To disable define DISABLE_ALERT
  154. #ifndef DISABLE_ALERT
  155. /**
  156. * \brief Maps the error code to Alert types and level.<br>
  157. */
  158. _STATIC_H Void DtlsErrorAlertMapping(int32_t Pi4ErrorCode, sbBlob_d* PpsAlertMsg);
  159. /**
  160. * \brief Forms the alert message based on the given internal error code.<br>
  161. */
  162. _STATIC_H Void Alert_FormMsg(int32_t Pi4ErrorCode,sbBlob_d* PpsAlertMsg);
  163. /**
  164. * Maps the error code to Alert types and level.<br>
  165. *
  166. * \param[in] Pi4ErrorCode DTLS Internal error code
  167. * \param[in,out] PpsAlertMsg Pointer to a blob containing Alert message as per DTLS Specification
  168. *
  169. */
  170. _STATIC_H Void DtlsErrorAlertMapping(int32_t Pi4ErrorCode, sbBlob_d* PpsAlertMsg)
  171. {
  172. do
  173. {
  174. if((int32_t)OCP_LIB_NO_RENEGOTIATE == Pi4ErrorCode)
  175. {
  176. *PpsAlertMsg->prgbStream = (uint8_t)eWARNING;
  177. }
  178. else
  179. {
  180. *PpsAlertMsg->prgbStream = (uint8_t)eFATAL;
  181. }
  182. //Set the Blob length to Alert message length
  183. PpsAlertMsg->wLen = LENGTH_ALERT_MSG;
  184. switch(Pi4ErrorCode)
  185. {
  186. case (int32_t)OCP_RL_ERROR:
  187. case (int32_t)OCP_FL_MSG_MAXCOUNT:
  188. //Prepare Alert Message
  189. *(PpsAlertMsg->prgbStream + OFFSET_ALERT_MSG) = (uint8_t)eCLOSE_NOTIFY;
  190. break;
  191. case (int32_t)(CMD_DEV_ERROR | INVALID_HANDSHAKE_MESSAGE):
  192. case (int32_t)(CMD_DEV_ERROR | UNSUPPORTED_PARAMETERS):
  193. case (int32_t)(CMD_DEV_ERROR | VERSION_MISMATCH):
  194. case (int32_t) OCP_FL_HS_ERROR:
  195. //Prepare Alert Message
  196. *(PpsAlertMsg->prgbStream + OFFSET_ALERT_MSG) = (uint8_t)eILLEGAL_PARAMETER;
  197. break;
  198. case (int32_t)OCP_LIB_NO_RENEGOTIATE:
  199. //Prepare Alert Message
  200. *(PpsAlertMsg->prgbStream + OFFSET_ALERT_MSG) = (uint8_t)eNO_RENEGOTIATION;
  201. break;
  202. case (int32_t)(CMD_DEV_ERROR | INSUFFICIENT_UNSUPPORTED_CIPHERSUITE):
  203. //Prepare Alert Message
  204. *(PpsAlertMsg->prgbStream + OFFSET_ALERT_MSG) = (uint8_t)eINSUFFICIENT_SECURITY;
  205. break;
  206. case (int32_t)(CMD_DEV_ERROR | UNSUPPORTED_EXTENSION):
  207. //Prepare Alert Message
  208. *(PpsAlertMsg->prgbStream + OFFSET_ALERT_MSG) = (uint8_t)eUNSUPPORTED_EXTENSION;
  209. break;
  210. case (int32_t)(CMD_DEV_ERROR | INVALID_TRUST_ANCHOR):
  211. //Prepare Alert Message
  212. *(PpsAlertMsg->prgbStream + OFFSET_ALERT_MSG) = (uint8_t)eUNKNOWN_CA;
  213. break;
  214. case (int32_t)(CMD_DEV_ERROR | TRUST_ANCHOR_EXPIRED):
  215. //Prepare Alert Message
  216. *(PpsAlertMsg->prgbStream + OFFSET_ALERT_MSG) = (uint8_t)eCERTIFICATE_EXPIRED;
  217. break;
  218. case (int32_t)(CMD_DEV_ERROR | UNSUPPORTED_TRUST_ANCHOR):
  219. //Prepare Alert Message
  220. *(PpsAlertMsg->prgbStream + OFFSET_ALERT_MSG) = (uint8_t)eUNSUPPORTED_CERTIFICATE;
  221. break;
  222. case (int32_t)(CMD_DEV_ERROR | INVALID_CERTIFICATE_FORMAT):
  223. //Prepare Alert Message
  224. *(PpsAlertMsg->prgbStream + OFFSET_ALERT_MSG) = (uint8_t)eBAD_CERTIFICATE;
  225. break;
  226. case (int32_t)(CMD_DEV_ERROR | UNSUPPORTED_CERTIFICATE_HASHSIGN):
  227. //Prepare Alert Message
  228. *(PpsAlertMsg->prgbStream + OFFSET_ALERT_MSG) = (uint8_t)eUNSUPPORTED_CERTIFICATE;
  229. break;
  230. case (int32_t)(CMD_DEV_ERROR | CERTIFICATE_EXPIRED):
  231. //Prepare Alert Message
  232. *(PpsAlertMsg->prgbStream + OFFSET_ALERT_MSG) = (uint8_t)eCERTIFICATE_EXPIRED;
  233. break;
  234. case (int32_t)(CMD_DEV_ERROR | SIGNATURE_VERIFICATION_FAILURE):
  235. //Prepare Alert Message
  236. *(PpsAlertMsg->prgbStream + OFFSET_ALERT_MSG) = (uint8_t)eDECRYPT_ERROR;
  237. break;
  238. default:
  239. //lint -e750 "The remaining errors returned by the security chip is mapped to Internal error Alert"
  240. //Prepare Alert Message
  241. *(PpsAlertMsg->prgbStream + OFFSET_ALERT_MSG) = (uint8_t)eINTERNAL_ERROR;
  242. break;
  243. }
  244. }while(0);
  245. }
  246. /**
  247. * Forms the alert message based on the given internal error code.<br>
  248. *
  249. * \param[in] Pi4ErrorCode DTLS Internal error code
  250. * \param[in,out] PpsAlertMsg Pointer to a blob containing Alert message as per DTLS Specification
  251. *
  252. */
  253. _STATIC_H Void Alert_FormMsg(int32_t Pi4ErrorCode,sbBlob_d* PpsAlertMsg)
  254. {
  255. //Maps the internal error code to the Alert messages
  256. DtlsErrorAlertMapping(Pi4ErrorCode,PpsAlertMsg);
  257. }
  258. #endif //DISABLE_ALERT
  259. /**
  260. * Maps the Alert types and level to error code.<br>
  261. *
  262. * \param[in] PpsAlertMsg Pointer to a blob containing Alert message as per DTLS Specification
  263. * \param[in,out] Ppi4ErrorCode Pointer to the DTLS Internal error code
  264. *
  265. * \retval #OCP_AL_OK Successful execution
  266. * \retval #OCP_AL_ERROR Failure in execution
  267. *
  268. */
  269. _STATIC_H int32_t DtlsAlertErrorMapping(const sbBlob_d* PpsAlertMsg, int32_t* Ppi4ErrorCode)
  270. {
  271. int32_t i4Status = (int32_t)OCP_AL_ERROR;
  272. do
  273. {
  274. //Check for the Alert level type
  275. if(eFATAL == (eAlertLevel_d)*PpsAlertMsg->prgbStream)
  276. {
  277. //Check for various fatal alert messages
  278. switch((eAlertMsg_d) *(PpsAlertMsg->prgbStream + OFFSET_ALERT_MSG))
  279. {
  280. case eCLOSE_NOTIFY:
  281. case eUNEXPECTED_MESSAGE:
  282. case eBAD_RECORD_MAC:
  283. case eDECRYPTION_FAILURE:
  284. case eRECORD_OVERFLOW:
  285. case eDECOMPRESSION_FAILURE:
  286. case eHANDSHAKE_FAILURE:
  287. case eBAD_CERTIFICATE:
  288. case eUNSUPPORTED_CERTIFICATE:
  289. case eNO_CERTIFICATE:
  290. case eCERTIFICATE_REVOKED:
  291. case eCERTIFICATE_EXPIRED:
  292. case eCERTIFICATE_UNKNOWN:
  293. case eUSER_CANCELLED:
  294. case eNO_RENEGOTIATION:
  295. case eILLEGAL_PARAMETER:
  296. case eUNKNOWN_CA:
  297. case eACCESS_DENIED:
  298. case eDECODE_ERROR:
  299. case eDECRYPT_ERROR:
  300. case eEXPORT_RESTRICTION:
  301. case ePROTOCOL_VERSION:
  302. case eINSUFFICIENT_SECURITY:
  303. case eINTERNAL_ERROR:
  304. case eUNSUPPORTED_EXTENSION:
  305. {
  306. *Ppi4ErrorCode = (int32_t)OCP_AL_FATAL_ERROR;
  307. i4Status = (int32_t)OCP_AL_OK;
  308. }
  309. break;
  310. default:
  311. //Indicates the received Alert is not a valid Fatal Error
  312. break;
  313. }
  314. }
  315. //Check for Warning Alert level type
  316. else if (eWARNING == (eAlertLevel_d)*PpsAlertMsg->prgbStream)
  317. {
  318. //Check for various warning alert messages
  319. switch((eAlertMsg_d) *(PpsAlertMsg->prgbStream + OFFSET_ALERT_MSG))
  320. {
  321. case eBAD_CERTIFICATE:
  322. case eUNSUPPORTED_CERTIFICATE:
  323. case eCERTIFICATE_REVOKED:
  324. case eCERTIFICATE_EXPIRED:
  325. case eCERTIFICATE_UNKNOWN:
  326. case eUSER_CANCELLED:
  327. case eNO_RENEGOTIATION:
  328. {
  329. *Ppi4ErrorCode = (int32_t)OCP_AL_WARNING_ERROR;
  330. i4Status = (int32_t)OCP_AL_OK;
  331. break;
  332. }
  333. default:
  334. //lint -e788 suppress "As the enum values are divided between Fatal and warning levels"
  335. //Indicates the received Alert is not a valid warning Error
  336. break;
  337. }
  338. }
  339. }while(0);
  340. return i4Status;
  341. }
  342. #ifndef DISABLE_ALERT
  343. /**
  344. * Sends Alert based on the internal error code via the Record Layer.<br>
  345. *
  346. * \param[in] PpsConfigRL Pointer to structure containing Record Layer information.
  347. * \param[in] Pi4ErrorCode DTLS Internal error code
  348. *
  349. */
  350. void Alert_Send(sConfigRL_d *PpsConfigRL,int32_t Pi4ErrorCode)
  351. {
  352. int32_t i4Status = (int32_t)OCP_AL_ERROR;
  353. sbBlob_d sAlertMsg;
  354. uint8_t bEncFlag = 0;
  355. uint8_t bFlagIncr = 0;
  356. uint8_t rgbAlertMsg[LENGTH_ALERT_MSG];
  357. //Null checks
  358. if((NULL != PpsConfigRL) && (NULL != PpsConfigRL->pfSend) && (NULL != PpsConfigRL->sRL.phRLHdl))
  359. {
  360. do
  361. {
  362. /// @cond hidden
  363. #define PS_RECORDLAYER ((sRecordLayer_d*)PpsConfigRL->sRL.phRLHdl)
  364. /// @endcond
  365. sAlertMsg.prgbStream = rgbAlertMsg;
  366. sAlertMsg.wLen = LENGTH_ALERT_MSG;
  367. //Form the Alert message based on internal error code
  368. Alert_FormMsg(Pi4ErrorCode, &sAlertMsg);
  369. PpsConfigRL->sRL.bMemoryAllocated = FALSE;
  370. PpsConfigRL->sRL.bContentType = CONTENTTYPE_ALERT;
  371. //Until successful completion of Mutual Authentication Public Key Scheme (DTLS) the Client should use previous epoch and messages must not be encrypted
  372. if(((PS_RECORDLAYER->wServerEpoch != PS_RECORDLAYER->wClientNextEpoch) && (*PS_RECORDLAYER->pbDec != 0x01)) ||
  373. (Pi4ErrorCode == (int32_t)OCP_FL_INT_ERROR) || (Pi4ErrorCode == (int32_t)OCP_FL_HS_ERROR))
  374. {
  375. if((PS_RECORDLAYER->bEncDecFlag == ENC_DEC_ENABLED) && (PS_RECORDLAYER->wClientEpoch != PS_RECORDLAYER->wClientNextEpoch))
  376. {
  377. bEncFlag = PS_RECORDLAYER->bEncDecFlag;
  378. PS_RECORDLAYER->bEncDecFlag = ENC_DEC_DISABLED;
  379. PS_RECORDLAYER->wClientNextEpoch--;
  380. bFlagIncr = 0x01;
  381. }
  382. }
  383. //Send the Alert message via record layer
  384. i4Status = PpsConfigRL->pfSend(&PpsConfigRL->sRL, sAlertMsg.prgbStream, sAlertMsg.wLen);
  385. if(bFlagIncr == 0x01)
  386. {
  387. PS_RECORDLAYER->bEncDecFlag = bEncFlag;
  388. PS_RECORDLAYER->wClientNextEpoch++;
  389. }
  390. if(OCP_RL_OK != i4Status)
  391. {
  392. break;
  393. }
  394. }while(FALSE);
  395. /// @cond hidden
  396. #undef PS_RECORDLAYER
  397. /// @endcond
  398. }
  399. }
  400. #endif //DISABLE_ALERT
  401. /**
  402. * Processes the received Alert Message<br>
  403. * Returns the corresponding internal error code.<br>
  404. *
  405. * \param[in] PpsAlertMsg Pointer to a blob containing Alert message as per DTLS Specification
  406. * \param[in,out] Ppi4ErrorCode Pointer to the DTLS Internal error code
  407. *
  408. * \retval #OCP_AL_OK Successful execution
  409. * \retval #OCP_AL_ERROR Failure in execution
  410. \if ENABLE_NULL_CHECKS
  411. * \retval #OCP_AL_NULL_PARAM Null parameter(s)
  412. \endif
  413. * \retval #OCP_AL_LENZERO_ERROR Length of input parameter is zero
  414. *
  415. */
  416. int32_t Alert_ProcessMsg(const sbBlob_d* PpsAlertMsg,int32_t* Ppi4ErrorCode)
  417. {
  418. int32_t i4Status = (int32_t)OCP_AL_ERROR;
  419. do
  420. {
  421. #ifdef ENABLE_NULL_CHECKS
  422. //NULL check for the input parameters
  423. if((NULL == PpsAlertMsg) || (NULL == Ppi4ErrorCode)|| (NULL == PpsAlertMsg->prgbStream))
  424. {
  425. i4Status = (int32_t)OCP_AL_NULL_PARAM;
  426. break;
  427. }
  428. #endif
  429. //Check for length is less than Alert message size
  430. if(LENGTH_ALERT_MSG != PpsAlertMsg->wLen)
  431. {
  432. break;
  433. }
  434. //Maps the received Alert messages to the internal error codes
  435. i4Status = DtlsAlertErrorMapping(PpsAlertMsg, Ppi4ErrorCode);
  436. }while(0);
  437. return i4Status;
  438. }
  439. /**
  440. * @}
  441. */
  442. #endif /*MODULE_ENABLE_DTLS_MUTUAL_AUTH */