Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
 
 
 
 

406 lignes
13 KiB

  1. /**
  2. *
  3. * \file
  4. *
  5. * \brief WINC SSL Interface.
  6. *
  7. * Copyright (c) 2017-2018 Microchip Technology Inc. and its subsidiaries.
  8. *
  9. * \asf_license_start
  10. *
  11. * \page License
  12. *
  13. * Subject to your compliance with these terms, you may use Microchip
  14. * software and any derivatives exclusively with Microchip products.
  15. * It is your responsibility to comply with third party license terms applicable
  16. * to your use of third party software (including open source software) that
  17. * may accompany Microchip software.
  18. *
  19. * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
  20. * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
  21. * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
  22. * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
  23. * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
  24. * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
  25. * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
  26. * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
  27. * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
  28. * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
  29. * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
  30. *
  31. * \asf_license_stop
  32. *
  33. */
  34. /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
  35. INCLUDES
  36. *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
  37. #include "driver/include/m2m_ssl.h"
  38. #include "driver/source/m2m_hif.h"
  39. #include "driver/source/nmasic.h"
  40. #include <stdlib.h>
  41. /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
  42. MACROS
  43. *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
  44. /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
  45. DATA TYPES
  46. *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
  47. static tpfAppSSLCb gpfAppSSLCb = NULL;
  48. static uint32 gu32HIFAddr = 0;
  49. static tenuTlsFlashStatus genuStatus = TLS_FLASH_ERR_UNKNOWN;
  50. /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
  51. FUNCTION PROTOTYPES
  52. *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
  53. /*!
  54. @fn \ m2m_ssl_cb(uint8 u8OpCode, uint16 u16DataSize, uint32 u32Addr)
  55. @brief SSL callback function
  56. @param [in] u8OpCode
  57. HIF Opcode type.
  58. @param [in] u16DataSize
  59. HIF data length.
  60. @param [in] u32Addr
  61. HIF address.
  62. */
  63. static void m2m_ssl_cb(uint8 u8OpCode, uint16 u16DataSize, uint32 u32Addr)
  64. {
  65. sint8 s8tmp = M2M_SUCCESS;
  66. switch(u8OpCode)
  67. {
  68. case M2M_SSL_REQ_ECC:
  69. {
  70. tstrEccReqInfo strEccREQ;
  71. s8tmp = hif_receive(u32Addr, (uint8*)&strEccREQ, sizeof(tstrEccReqInfo), 0);
  72. if(s8tmp == M2M_SUCCESS)
  73. {
  74. if (gpfAppSSLCb)
  75. {
  76. gu32HIFAddr = u32Addr + sizeof(tstrEccReqInfo);
  77. gpfAppSSLCb(M2M_SSL_REQ_ECC, &strEccREQ);
  78. }
  79. }
  80. }
  81. break;
  82. case M2M_SSL_RESP_SET_CS_LIST:
  83. {
  84. tstrSslSetActiveCsList strCsList;
  85. s8tmp = hif_receive(u32Addr, (uint8*)&strCsList, sizeof(tstrSslSetActiveCsList), 0);
  86. if(s8tmp == M2M_SUCCESS)
  87. {
  88. if (gpfAppSSLCb)
  89. gpfAppSSLCb(M2M_SSL_RESP_SET_CS_LIST, &strCsList);
  90. }
  91. }
  92. break;
  93. case M2M_SSL_RESP_WRITE_OWN_CERTS:
  94. {
  95. tstrTlsSrvChunkHdr strTlsSrvChunkRsp;
  96. uint8 bCallApp = 1;
  97. s8tmp = hif_receive(u32Addr, (uint8*)&strTlsSrvChunkRsp, sizeof(tstrTlsSrvChunkHdr), 0);
  98. if(s8tmp == M2M_SUCCESS)
  99. {
  100. uint16 offset = strTlsSrvChunkRsp.u16Offset32;
  101. uint16 chunk_size = strTlsSrvChunkRsp.u16Size32;
  102. uint16 total_size = strTlsSrvChunkRsp.u16TotalSize32;
  103. tenuTlsFlashStatus status = (tenuTlsFlashStatus)(strTlsSrvChunkRsp.u16Sig);
  104. /* If first chunk, reset status. */
  105. if (offset == 0)
  106. genuStatus = TLS_FLASH_OK_NO_CHANGE;
  107. /* Only send status to app when processing last chunk. */
  108. if (offset + chunk_size != total_size)
  109. bCallApp = 0;
  110. switch (status)
  111. {
  112. case TLS_FLASH_OK:
  113. // Good flash write. Update status if no errors yet.
  114. if (genuStatus == TLS_FLASH_OK_NO_CHANGE)
  115. genuStatus = status;
  116. break;
  117. case TLS_FLASH_OK_NO_CHANGE:
  118. // No change, don't update status.
  119. break;
  120. case TLS_FLASH_ERR_CORRUPT:
  121. // Corrupt. Always update status.
  122. genuStatus = status;
  123. break;
  124. case TLS_FLASH_ERR_NO_CHANGE:
  125. // Failed flash write. Update status if no more serious error.
  126. if ((genuStatus != TLS_FLASH_ERR_CORRUPT) && (genuStatus != TLS_FLASH_ERR_UNKNOWN))
  127. genuStatus = status;
  128. break;
  129. default:
  130. // Don't expect any other case. Ensure we don't mask a previous corrupt error.
  131. if (genuStatus != TLS_FLASH_ERR_CORRUPT)
  132. genuStatus = TLS_FLASH_ERR_UNKNOWN;
  133. break;
  134. }
  135. }
  136. if (bCallApp && gpfAppSSLCb)
  137. gpfAppSSLCb(M2M_SSL_RESP_WRITE_OWN_CERTS, &genuStatus);
  138. }
  139. break;
  140. }
  141. if(s8tmp != M2M_SUCCESS)
  142. {
  143. M2M_ERR("Error receiving SSL from the HIF\n");
  144. }
  145. }
  146. /*!
  147. @fn \ m2m_ssl_handshake_rsp(tstrEccReqInfo* strECCResp, uint8* pu8RspDataBuff, uint16 u16RspDataSz)
  148. @brief Sends ECC responses to the WINC
  149. @param [in] strECCResp
  150. ECC Response struct.
  151. @param [in] pu8RspDataBuffe
  152. Pointer of the response data to be sent.
  153. @param [in] u16RspDataSz
  154. Response data size.
  155. @return The function SHALL return 0 for success and a negative value otherwise.
  156. */
  157. NMI_API sint8 m2m_ssl_handshake_rsp(tstrEccReqInfo* strECCResp, uint8* pu8RspDataBuff, uint16 u16RspDataSz)
  158. {
  159. sint8 s8Ret = M2M_SUCCESS;
  160. s8Ret = hif_send(M2M_REQ_GROUP_SSL, (M2M_SSL_RESP_ECC | M2M_REQ_DATA_PKT), (uint8*)strECCResp, sizeof(tstrEccReqInfo), pu8RspDataBuff, u16RspDataSz, sizeof(tstrEccReqInfo));
  161. return s8Ret;
  162. }
  163. /*!
  164. @fn \ m2m_ssl_send_certs_to_winc(uint8* sector_buffer, uint32 sector_size)
  165. @brief Sends certificates to the WINC
  166. @param [in] pu8Buffer
  167. Pointer to the certificates.
  168. @param [in] u32BufferSz
  169. Size of the certificates.
  170. @return The function SHALL return 0 for success and a negative value otherwise.
  171. */
  172. NMI_API sint8 m2m_ssl_send_certs_to_winc(uint8* pu8Buffer, uint32 u32BufferSz)
  173. {
  174. sint8 s8Ret = M2M_SUCCESS;
  175. #define TXLIMIT (256 * 6)
  176. if(u32BufferSz <= TXLIMIT)
  177. {
  178. // set chunk header for one chunk
  179. tstrTlsSrvChunkHdr *pchkhdr = (tstrTlsSrvChunkHdr *)pu8Buffer;
  180. pchkhdr->u16Sig = TLS_CERTS_CHUNKED_SIG_VALUE;
  181. pchkhdr->u16TotalSize32 = (u32BufferSz + 3) >> 2;
  182. pchkhdr->u16Offset32 = 0;
  183. pchkhdr->u16Size32 = (u32BufferSz + 3) >> 2;
  184. s8Ret = hif_send(M2M_REQ_GROUP_SSL, (M2M_SSL_REQ_WRITE_OWN_CERTS | M2M_REQ_DATA_PKT), NULL, 0, pu8Buffer, u32BufferSz, 0);
  185. M2M_INFO("Transferred %u bytes of cert data NON-CHUNKED\n", u32BufferSz);
  186. }
  187. else
  188. {
  189. // chunk it
  190. // We are sneaking in a header - tstrTlsSrvChunkHdr
  191. #define CHUNKHDRSZ (sizeof(tstrTlsSrvChunkHdr))
  192. #define CHUNKSZ (TXLIMIT - 256) // divisible by 4
  193. uint8 saveblob[CHUNKHDRSZ];
  194. uint32 ofs = 0;
  195. uint32 thischunksz = 0;
  196. // first is special - over writing our header
  197. m2m_memcpy(saveblob, &pu8Buffer[ofs], CHUNKHDRSZ);
  198. thischunksz = min(CHUNKSZ,u32BufferSz-ofs); // no need to round up to quad words this time
  199. tstrTlsSrvChunkHdr* pchkhdr = (tstrTlsSrvChunkHdr*)&pu8Buffer[ofs];
  200. pchkhdr->u16Sig = TLS_CERTS_CHUNKED_SIG_VALUE;
  201. pchkhdr->u16TotalSize32 = ((u32BufferSz + 3) >> 2);
  202. pchkhdr->u16Offset32 = ((ofs + 3) >> 2);
  203. pchkhdr->u16Size32 = ((thischunksz + 3) >> 2);
  204. s8Ret = hif_send(M2M_REQ_GROUP_SSL, (M2M_SSL_REQ_WRITE_OWN_CERTS | M2M_REQ_DATA_PKT), NULL, 0, &pu8Buffer[ofs], thischunksz, 0);
  205. M2M_INFO("Transferred %u bytes of cert data CHUNKED to offset %u total %u\n", thischunksz, ofs, u32BufferSz);
  206. m2m_memcpy(&pu8Buffer[ofs], saveblob, CHUNKHDRSZ);
  207. ofs += thischunksz;
  208. while (ofs < u32BufferSz)
  209. {
  210. // Subsequent chunks write header before and send a little more
  211. m2m_memcpy(saveblob, &pu8Buffer[ofs-CHUNKHDRSZ], CHUNKHDRSZ);
  212. thischunksz = min(CHUNKSZ,u32BufferSz-ofs);
  213. thischunksz = (thischunksz + 3) & 0xFFFFFFFC; // needs to round up to quad word length
  214. pchkhdr = (tstrTlsSrvChunkHdr*)&pu8Buffer[ofs - CHUNKHDRSZ];
  215. pchkhdr->u16Sig = TLS_CERTS_CHUNKED_SIG_VALUE;
  216. pchkhdr->u16TotalSize32 = ((u32BufferSz + 3) >> 2);
  217. pchkhdr->u16Offset32 = ((ofs + 3) >> 2);
  218. pchkhdr->u16Size32 = ((thischunksz + 3) >> 2);
  219. s8Ret = hif_send(M2M_REQ_GROUP_SSL, (M2M_SSL_REQ_WRITE_OWN_CERTS | M2M_REQ_DATA_PKT), NULL, 0, &pu8Buffer[ofs - CHUNKHDRSZ], thischunksz + CHUNKHDRSZ, 0);
  220. M2M_INFO("Transferred %u bytes of cert data CHUNKED to offset %u total %u\n", thischunksz, ofs, u32BufferSz);
  221. m2m_memcpy(&pu8Buffer[ofs - CHUNKHDRSZ], saveblob, CHUNKHDRSZ);
  222. ofs += thischunksz;
  223. }
  224. }
  225. return s8Ret;
  226. }
  227. /*!
  228. @fn \ m2m_ssl_retrieve_cert(uint32 u32ReadAddr, uint16* pu16CurveType, uint8* pu8Hash, uint8* pu8Sig, tstrECPoint* pu8Key)
  229. @brief Retrieve the certificate to be verified from the WINC
  230. @param [in] pu16CurveType
  231. Pointer to the certificate curve type.
  232. @param [in] pu8Hash
  233. Pointer to the certificate hash.
  234. @param [in] pu8Sig
  235. Pointer to the certificate signature.
  236. @param [in] pu8Key
  237. Pointer to the certificate Key.
  238. @return The function SHALL return 0 for success and a negative value otherwise.
  239. */
  240. NMI_API sint8 m2m_ssl_retrieve_cert(uint16* pu16CurveType, uint8* pu8Hash, uint8* pu8Sig, tstrECPoint* pu8Key)
  241. {
  242. uint8 bSetRxDone = 1;
  243. uint16 u16HashSz, u16SigSz, u16KeySz;
  244. sint8 s8Ret = M2M_SUCCESS;
  245. if(gu32HIFAddr == 0) return M2M_ERR_FAIL;
  246. if(hif_receive(gu32HIFAddr, (uint8*)pu16CurveType, 2, 0) != M2M_SUCCESS) goto __ERR;
  247. gu32HIFAddr += 2;
  248. if(hif_receive(gu32HIFAddr, (uint8*)&u16KeySz, 2, 0) != M2M_SUCCESS) goto __ERR;
  249. gu32HIFAddr += 2;
  250. if(hif_receive(gu32HIFAddr, (uint8*)&u16HashSz, 2, 0) != M2M_SUCCESS) goto __ERR;
  251. gu32HIFAddr += 2;
  252. if(hif_receive(gu32HIFAddr, (uint8*)&u16SigSz, 2, 0) != M2M_SUCCESS) goto __ERR;
  253. gu32HIFAddr += 2;
  254. (*pu16CurveType)= _htons((*pu16CurveType));
  255. pu8Key->u16Size = _htons(u16KeySz);
  256. u16HashSz = _htons(u16HashSz);
  257. u16SigSz = _htons(u16SigSz);
  258. if(hif_receive(gu32HIFAddr, pu8Key->X, pu8Key->u16Size * 2, 0) != M2M_SUCCESS) goto __ERR;
  259. gu32HIFAddr += (pu8Key->u16Size * 2);
  260. if(hif_receive(gu32HIFAddr, pu8Hash, u16HashSz, 0) != M2M_SUCCESS) goto __ERR;
  261. gu32HIFAddr += u16HashSz;
  262. if(hif_receive(gu32HIFAddr, pu8Sig, u16SigSz, 0) != M2M_SUCCESS) goto __ERR;
  263. gu32HIFAddr += u16SigSz;
  264. bSetRxDone = 0;
  265. __ERR:
  266. if(bSetRxDone)
  267. {
  268. s8Ret = M2M_ERR_FAIL;
  269. hif_receive(0, NULL, 0, 1);
  270. }
  271. return s8Ret;
  272. }
  273. /*!
  274. @fn \ m2m_ssl_retrieve_hash(uint32 u32ReadAddr, uint8* pu8Hash, uint16 u16HashSz)
  275. @brief Retrieve the certificate hash
  276. @param [in] pu8Hash
  277. Pointer to the certificate hash.
  278. @param [in] u16HashSz
  279. Hash size.
  280. @return The function SHALL return 0 for success and a negative value otherwise.
  281. */
  282. NMI_API sint8 m2m_ssl_retrieve_hash(uint8* pu8Hash, uint16 u16HashSz)
  283. {
  284. uint8 bSetRxDone = 1;
  285. sint8 s8Ret = M2M_SUCCESS;
  286. if(gu32HIFAddr == 0) return M2M_ERR_FAIL;
  287. if(hif_receive(gu32HIFAddr, pu8Hash, u16HashSz, 0) != M2M_SUCCESS) goto __ERR;
  288. bSetRxDone = 0;
  289. __ERR:
  290. if(bSetRxDone)
  291. {
  292. s8Ret = M2M_ERR_FAIL;
  293. hif_receive(0, NULL, 0, 1);
  294. }
  295. return s8Ret;
  296. }
  297. /*!
  298. @fn \ m2m_ssl_stop_processing_certs(void)
  299. @brief Stops receiving from the HIF
  300. */
  301. NMI_API void m2m_ssl_stop_processing_certs(void)
  302. {
  303. hif_receive(0, NULL, 0, 1);
  304. }
  305. /*!
  306. @fn \ m2m_ssl_ecc_process_done(void)
  307. @brief Stops receiving from the HIF
  308. */
  309. NMI_API void m2m_ssl_ecc_process_done(void)
  310. {
  311. gu32HIFAddr = 0;
  312. }
  313. /*!
  314. @fn \
  315. m2m_ssl_set_active_ciphersuites(uint32 u32SslCsBMP);
  316. Override the default Active SSL ciphers in the SSL module with a certain combination selected by the caller in the form of
  317. a bitmap containing the required ciphers to be on.
  318. There is no need to call this function if the application will not change the default ciphersuites.
  319. @param [in] u32SslCsBMP
  320. Bitmap containing the desired ciphers to be enabled for the SSL module. The ciphersuites are defined in
  321. @ref SSLCipherSuiteID.
  322. The default ciphersuites are all ciphersuites supported by the firmware with the exception of ECC ciphersuites.
  323. The caller can override the default with any desired combination, except for combinations involving both RSA
  324. and ECC; if any RSA ciphersuite is enabled, then firmware will disable all ECC ciphersuites.
  325. If u32SslCsBMP does not contain any ciphersuites supported by firmware, then the current active list will not
  326. be changed.
  327. @return
  328. - [SOCK_ERR_NO_ERROR](@ref SOCK_ERR_NO_ERROR)
  329. - [SOCK_ERR_INVALID_ARG](@ref SOCK_ERR_INVALID_ARG)
  330. */
  331. sint8 m2m_ssl_set_active_ciphersuites(uint32 u32SslCsBMP)
  332. {
  333. sint8 s8Ret = M2M_SUCCESS;
  334. tstrSslSetActiveCsList strCsList;
  335. strCsList.u32CsBMP = u32SslCsBMP;
  336. s8Ret = hif_send(M2M_REQ_GROUP_SSL, M2M_SSL_REQ_SET_CS_LIST, (uint8*)&strCsList, sizeof(tstrSslSetActiveCsList), NULL, 0, 0);
  337. return s8Ret;
  338. }
  339. /*!
  340. @fn \ m2m_ssl_init(tpfAppSslCb pfAppSslCb);
  341. @brief Initializes the SSL layer.
  342. @param [in] pfAppSslCb
  343. Application SSL callback function.
  344. @return The function SHALL return 0 for success and a negative value otherwise.
  345. */
  346. NMI_API sint8 m2m_ssl_init(tpfAppSSLCb pfAppSSLCb)
  347. {
  348. sint8 s8Ret = M2M_SUCCESS;
  349. gpfAppSSLCb = pfAppSSLCb;
  350. gu32HIFAddr = 0;
  351. genuStatus = TLS_FLASH_ERR_UNKNOWN;
  352. s8Ret = hif_register_cb(M2M_REQ_GROUP_SSL,m2m_ssl_cb);
  353. if (s8Ret != M2M_SUCCESS)
  354. {
  355. M2M_ERR("hif_register_cb() failed with ret=%d", s8Ret);
  356. }
  357. return s8Ret;
  358. }