1 /******************************************************************
3 * Copyright 2014 Samsung Electronics All Rights Reserved.
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
19 ******************************************************************/
20 #include "caadapternetdtls.h"
22 #include "caipinterface.h"
24 #include "oic_malloc.h"
25 #include "oic_string.h"
28 #if defined(HAVE_WINSOCK2_H) && defined(HAVE_WS2TCPIP_H)
36 /* tinyDTLS library error code */
37 #define TINY_DTLS_ERROR (-1)
38 /* tinyDTLS library success code */
39 #define TINY_DTLS_SUCCESS (0)
44 #include "cainterface.h"
46 /* lenght of ASN.1 header in DER format
47 * for subject field in X.509 certificate */
48 #define DER_SUBJECT_HEADER_LEN (9)
51 #define VERIFY_SUCCESS(op, successCode) { if ((op) != (successCode)) \
52 {OIC_LOG_V(FATAL, NET_DTLS_TAG, "%s failed!!", #op); goto exit;} }
57 * @brief Logging tag for module name
59 #define NET_DTLS_TAG "OIC_CA_NET_DTLS"
62 * @var g_caDtlsContext
63 * @brief global context which holds dtls context and cache list information.
65 static stCADtlsContext_t *g_caDtlsContext = NULL;
68 * @var g_dtlsContextMutex
69 * @brief Mutex to synchronize access to g_caDtlsContext.
71 static ca_mutex g_dtlsContextMutex = NULL;
74 * @var g_getCredentialsCallback
75 * @brief callback to get DTLS credentials
77 static CAGetDTLSPskCredentialsHandler g_getCredentialsCallback = NULL;
80 * @var RETRANSMISSION_TIME
81 * @brief Maximum timeout value (in seconds) to start DTLS retransmission.
83 #define RETRANSMISSION_TIME 1
86 * @var g_dtlsHandshakeCallback
87 * @brief callback to deliver the DTLS handshake result
89 static CAErrorCallback g_dtlsHandshakeCallback = NULL;
93 * @var g_getX509CredentialsCallback
94 * @brief callback to get DTLS certificate credentials
96 static CAGetDTLSX509CredentialsHandler g_getX509CredentialsCallback = NULL;
98 * @var g_getCrlCallback
99 * @brief callback to get CRL for DTLS
101 static CAGetDTLSCrlHandler g_getCrlCallback = NULL;
102 #endif //__WITH_X509__
105 static CASecureEndpoint_t *GetPeerInfo(const CAEndpoint_t *peer)
107 uint32_t list_index = 0;
108 uint32_t list_length = 0;
112 OIC_LOG(ERROR, NET_DTLS_TAG, "CAPeerInfoListContains invalid parameters");
116 CASecureEndpoint_t *peerInfo = NULL;
117 list_length = u_arraylist_length(g_caDtlsContext->peerInfoList);
118 for (list_index = 0; list_index < list_length; list_index++)
120 peerInfo = (CASecureEndpoint_t *)u_arraylist_get(g_caDtlsContext->peerInfoList, list_index);
121 if (NULL == peerInfo)
126 if((0 == strncmp(peer->addr, peerInfo->endpoint.addr, MAX_ADDR_STR_SIZE_CA)) &&
127 (peer->port == peerInfo->endpoint.port))
135 static CAResult_t CAAddIdToPeerInfoList(const char *peerAddr, uint32_t port,
136 const unsigned char *id, uint16_t id_length)
142 || CA_MAX_ENDPOINT_IDENTITY_LEN < id_length)
144 OIC_LOG(ERROR, NET_DTLS_TAG, "CAAddIdToPeerInfoList invalid parameters");
145 return CA_STATUS_INVALID_PARAM;
148 CASecureEndpoint_t *peer = (CASecureEndpoint_t *)OICCalloc(1, sizeof (CASecureEndpoint_t));
151 OIC_LOG(ERROR, NET_DTLS_TAG, "peerInfo malloc failed!");
152 return CA_MEMORY_ALLOC_FAILED;
155 OICStrcpy(peer->endpoint.addr, sizeof(peer->endpoint.addr), peerAddr);
156 peer->endpoint.port = port;
158 memcpy(peer->identity.id, id, id_length);
159 peer->identity.id_length = id_length;
161 if (NULL != GetPeerInfo(&peer->endpoint))
163 OIC_LOG(ERROR, NET_DTLS_TAG, "CAAddIdToPeerInfoList peer already exist");
165 return CA_STATUS_FAILED;
168 bool result = u_arraylist_add(g_caDtlsContext->peerInfoList, (void *)peer);
171 OIC_LOG(ERROR, NET_DTLS_TAG, "u_arraylist_add failed!");
173 return CA_STATUS_FAILED;
179 static void CAFreePeerInfoList()
181 uint32_t list_length = u_arraylist_length(g_caDtlsContext->peerInfoList);
182 for (uint32_t list_index = 0; list_index < list_length; list_index++)
184 CAEndpoint_t *peerInfo = (CAEndpoint_t *)u_arraylist_get(
185 g_caDtlsContext->peerInfoList, list_index);
188 u_arraylist_free(&(g_caDtlsContext->peerInfoList));
189 g_caDtlsContext->peerInfoList = NULL;
192 static void CARemovePeerFromPeerInfoList(const char * addr, uint16_t port)
194 if (NULL == addr || 0 >= port)
196 OIC_LOG(ERROR, NET_DTLS_TAG, "CADTLSGetPeerPSKId invalid parameters");
200 uint32_t list_length = u_arraylist_length(g_caDtlsContext->peerInfoList);
201 for (uint32_t list_index = 0; list_index < list_length; list_index++)
203 CAEndpoint_t *peerInfo = (CAEndpoint_t *)u_arraylist_get(
204 g_caDtlsContext->peerInfoList,list_index);
205 if (NULL == peerInfo)
209 if((0 == strncmp(addr, peerInfo->addr, MAX_ADDR_STR_SIZE_CA)) &&
210 (port == peerInfo->port))
212 OICFree(u_arraylist_remove(g_caDtlsContext->peerInfoList, list_index));
218 static int CASizeOfAddrInfo(stCADtlsAddrInfo_t *addrInfo)
220 VERIFY_NON_NULL_RET(addrInfo, NET_DTLS_TAG, "addrInfo is NULL" , DTLS_FAIL);
222 switch (addrInfo->addr.st.ss_family)
226 return sizeof (struct sockaddr_in);
230 return sizeof (struct sockaddr_in6);
237 return sizeof (struct sockaddr_storage);
240 static eDtlsRet_t CAAdapterNetDtlsEncryptInternal(const stCADtlsAddrInfo_t *dstSession,
241 uint8_t *data, uint32_t dataLen)
243 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
245 VERIFY_NON_NULL_RET(dstSession, NET_DTLS_TAG, "Param dstSession is NULL" , DTLS_FAIL);
246 VERIFY_NON_NULL_RET(data, NET_DTLS_TAG, "Param data is NULL" , DTLS_FAIL);
250 OIC_LOG(ERROR, NET_DTLS_TAG, "Given Packet length is equal to zero.");
254 if (NULL == g_caDtlsContext)
256 OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
260 int retLen = dtls_write(g_caDtlsContext->dtlsContext, (session_t *)dstSession, data,
262 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "dtls_write retun len [%d]", retLen);
265 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT FAILURE");
270 // A new DTLS session was initiated by tinyDTLS library and wait for callback.
271 return DTLS_SESSION_INITIATED;
273 else if (dataLen != (uint32_t)retLen)
275 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT FAILURE");
278 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
282 static eDtlsRet_t CAAdapterNetDtlsDecryptInternal(const stCADtlsAddrInfo_t *srcSession,
283 uint8_t *buf, uint32_t bufLen)
285 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
287 VERIFY_NON_NULL_RET(srcSession, NET_DTLS_TAG, "Param srcSession is NULL", DTLS_FAIL);
288 VERIFY_NON_NULL_RET(buf, NET_DTLS_TAG, "Param buf is NULL", DTLS_FAIL);
292 OIC_LOG(ERROR, NET_DTLS_TAG, "Given Packet length is equal to zero.");
296 eDtlsRet_t ret = DTLS_FAIL;
298 if (dtls_handle_message(g_caDtlsContext->dtlsContext, (session_t *)srcSession, buf, bufLen) == 0)
300 OIC_LOG(DEBUG, NET_DTLS_TAG, "dtls_handle_message success");
304 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
308 static void CAFreeCacheMsg(stCACacheMessage_t *msg)
310 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
311 VERIFY_NON_NULL_VOID(msg, NET_DTLS_TAG, "msg");
316 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
319 static void CAClearCacheList()
321 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
322 uint32_t list_index = 0;
323 uint32_t list_length = 0;
324 if (NULL == g_caDtlsContext)
326 OIC_LOG(ERROR, NET_DTLS_TAG, "Dtls Context is NULL");
329 list_length = u_arraylist_length(g_caDtlsContext->cacheList);
330 for (list_index = 0; list_index < list_length; list_index++)
332 stCACacheMessage_t *msg = (stCACacheMessage_t *)u_arraylist_get(g_caDtlsContext->cacheList,
339 u_arraylist_free(&g_caDtlsContext->cacheList);
340 g_caDtlsContext->cacheList = NULL;
341 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
344 static CAResult_t CADtlsCacheMsg(stCACacheMessage_t *msg)
346 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
348 if (NULL == g_caDtlsContext)
350 OIC_LOG(ERROR, NET_DTLS_TAG, "Dtls Context is NULL");
351 return CA_STATUS_FAILED;
354 bool result = u_arraylist_add(g_caDtlsContext->cacheList, (void *)msg);
357 OIC_LOG(ERROR, NET_DTLS_TAG, "u_arraylist_add failed!");
358 return CA_STATUS_FAILED;
361 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
366 static bool CAIsAddressMatching(const stCADtlsAddrInfo_t *a, const stCADtlsAddrInfo_t *b)
368 if (a->size != b->size)
372 if (memcmp(&a->addr, &b->addr, a->size))
379 static void CASendCachedMsg(const stCADtlsAddrInfo_t *dstSession)
381 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
382 VERIFY_NON_NULL_VOID(dstSession, NET_DTLS_TAG, "Param dstSession is NULL");
384 uint32_t list_index = 0;
385 uint32_t list_length = 0;
386 list_length = u_arraylist_length(g_caDtlsContext->cacheList);
387 for (list_index = 0; list_index < list_length;)
389 stCACacheMessage_t *msg = (stCACacheMessage_t *)u_arraylist_get(g_caDtlsContext->cacheList,
391 if ((NULL != msg) && (true == CAIsAddressMatching(&(msg->destSession), dstSession)))
393 eDtlsRet_t ret = CAAdapterNetDtlsEncryptInternal(&(msg->destSession),
394 msg->data, msg->dataLen);
397 OIC_LOG(DEBUG, NET_DTLS_TAG, "CAAdapterNetDtlsEncryptInternal success");
401 OIC_LOG(ERROR, NET_DTLS_TAG, "CAAdapterNetDtlsEncryptInternal failed.");
404 if (u_arraylist_remove(g_caDtlsContext->cacheList, list_index))
407 // Reduce list length by 1 as we removed one element.
412 OIC_LOG(ERROR, NET_DTLS_TAG, "u_arraylist_remove failed.");
418 // Move to the next element
423 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
426 static int32_t CAReadDecryptedPayload(dtls_context_t *context,
432 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
434 VERIFY_NON_NULL_RET(session, NET_DTLS_TAG, "Param Session is NULL", 0);
435 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "Decrypted buf len [%zu]", bufLen);
437 stCADtlsAddrInfo_t *addrInfo = (stCADtlsAddrInfo_t *)session;
439 CASecureEndpoint_t sep =
441 { .adapter = CA_ADAPTER_IP, .flags =
442 ((addrInfo->addr.st.ss_family == AF_INET) ? CA_IPV4 : CA_IPV6) | CA_SECURE, .port = 0 },
445 CAConvertAddrToName(&(addrInfo->addr.st), addrInfo->size, sep.endpoint.addr, &sep.endpoint.port);
447 if (NULL == g_caDtlsContext)
449 OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
450 return TINY_DTLS_ERROR;
454 if ((0 <= type) && (MAX_SUPPORTED_ADAPTERS > type) &&
455 (NULL != g_caDtlsContext->adapterCallbacks[type].recvCallback))
457 // Get identity of the source of packet
458 CASecureEndpoint_t *peerInfo = GetPeerInfo(&sep.endpoint);
461 sep.identity = peerInfo->identity;
464 g_caDtlsContext->adapterCallbacks[type].recvCallback(&sep, buf, bufLen);
468 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "recvCallback Callback or adapter type is wrong [%d]", type);
471 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
472 return TINY_DTLS_SUCCESS;
475 static int32_t CASendSecureData(dtls_context_t *context,
481 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
483 VERIFY_NON_NULL_RET(session, NET_DTLS_TAG, "Param Session is NULL", -1);
484 VERIFY_NON_NULL_RET(buf, NET_DTLS_TAG, "Param buf is NULL", -1);
488 OIC_LOG(ERROR, NET_DTLS_TAG, "Encrypted Buffer length is equal to zero");
492 stCADtlsAddrInfo_t *addrInfo = (stCADtlsAddrInfo_t *)session;
494 CAEndpoint_t endpoint = {.adapter = CA_DEFAULT_ADAPTER};
496 CAConvertAddrToName(&(addrInfo->addr.st), addrInfo->size, endpoint.addr, &endpoint.port);
497 endpoint.flags = addrInfo->addr.st.ss_family == AF_INET ? CA_IPV4 : CA_IPV6;
498 endpoint.flags |= CA_SECURE;
499 endpoint.adapter = CA_ADAPTER_IP;
500 endpoint.ifindex = session->ifindex;
503 //Mutex is not required for g_caDtlsContext. It will be called in same thread.
504 if ((0 <= type) && (MAX_SUPPORTED_ADAPTERS > type) &&
505 (NULL != g_caDtlsContext->adapterCallbacks[type].sendCallback))
507 g_caDtlsContext->adapterCallbacks[type].sendCallback(&endpoint, buf, bufLen);
511 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "send Callback or adapter type is wrong [%d]", type );
514 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
518 static int32_t CAHandleSecureEvent(dtls_context_t *context,
520 dtls_alert_level_t level,
524 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
526 VERIFY_NON_NULL_RET(session, NET_DTLS_TAG, "Param Session is NULL", 0);
528 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "level [%d] code [%u]\n", level, code);
530 CAEndpoint_t endpoint = {.adapter=CA_DEFAULT_ADAPTER};
531 CAErrorInfo_t errorInfo = {.result=CA_STATUS_OK};
533 stCADtlsAddrInfo_t *addrInfo = (stCADtlsAddrInfo_t *)session;
534 char peerAddr[MAX_ADDR_STR_SIZE_CA] = { 0 };
536 CAConvertAddrToName(&(addrInfo->addr.st), addrInfo->size, peerAddr, &port);
538 if (!level && (DTLS_EVENT_CONNECTED == code))
540 OIC_LOG(DEBUG, NET_DTLS_TAG, "Received DTLS_EVENT_CONNECTED. Sending Cached data");
542 if(g_dtlsHandshakeCallback)
544 OICStrcpy(endpoint.addr, MAX_ADDR_STR_SIZE_CA, peerAddr);
545 endpoint.port = port;
546 errorInfo.result = CA_STATUS_OK;
547 g_dtlsHandshakeCallback(&endpoint, &errorInfo);
550 CASendCachedMsg((stCADtlsAddrInfo_t *)session);
552 else if(DTLS_ALERT_LEVEL_FATAL == level && DTLS_ALERT_DECRYPT_ERROR == code)
554 if(g_dtlsHandshakeCallback)
556 OICStrcpy(endpoint.addr, MAX_ADDR_STR_SIZE_CA, peerAddr);
557 endpoint.addr[MAX_ADDR_STR_SIZE_CA - 1] = '\0';
558 endpoint.port = port;
559 errorInfo.result = CA_DTLS_AUTHENTICATION_FAILURE;
560 g_dtlsHandshakeCallback(&endpoint, &errorInfo);
563 else if(DTLS_ALERT_LEVEL_FATAL == level && DTLS_ALERT_CLOSE_NOTIFY == code)
565 OIC_LOG(INFO, NET_DTLS_TAG, "Peer closing connection");
566 CARemovePeerFromPeerInfoList(peerAddr, port);
568 else if(DTLS_ALERT_LEVEL_FATAL == level && DTLS_ALERT_HANDSHAKE_FAILURE == code)
570 OIC_LOG(INFO, NET_DTLS_TAG, "Failed to DTLS handshake, the peer will be removed.");
571 CARemovePeerFromPeerInfoList(peerAddr, port);
574 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
575 return TINY_DTLS_SUCCESS;
579 static int32_t CAGetPskCredentials(dtls_context_t *ctx,
580 const session_t *session,
581 dtls_credentials_type_t type,
582 const unsigned char *desc, size_t descLen,
583 unsigned char *result, size_t resultLen)
585 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
587 int32_t ret = TINY_DTLS_ERROR;
588 if(NULL == ctx || NULL == session || NULL == result)
590 OIC_LOG(ERROR, NET_DTLS_TAG, "CAGetPskCredentials invalid parameters");
594 VERIFY_NON_NULL_RET(g_getCredentialsCallback, NET_DTLS_TAG, "GetCredential callback", -1);
596 // Retrieve the credentials blob from security module
597 ret = g_getCredentialsCallback(type, desc, descLen, result, resultLen);
601 // TODO SRM needs identity of the remote end-point with every data packet to
602 // perform access control management. tinyDTLS 'frees' the handshake parameters
603 // data structure when handshake completes. Therefore, currently this is a
604 // workaround to cache remote end-point identity when tinyDTLS asks for PSK.
605 stCADtlsAddrInfo_t *addrInfo = (stCADtlsAddrInfo_t *)session;
606 char peerAddr[MAX_ADDR_STR_SIZE_CA] = { 0 };
608 CAConvertAddrToName(&(addrInfo->addr.st), addrInfo->size, peerAddr, &port);
610 if(CA_STATUS_OK != CAAddIdToPeerInfoList(peerAddr, port, desc, descLen) )
612 OIC_LOG(ERROR, NET_DTLS_TAG, "Fail to add peer id to gDtlsPeerInfoList");
619 void CADTLSSetAdapterCallbacks(CAPacketReceivedCallback recvCallback,
620 CAPacketSendCallback sendCallback,
621 CATransportAdapter_t type)
623 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
624 ca_mutex_lock(g_dtlsContextMutex);
625 if (NULL == g_caDtlsContext)
627 OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
628 ca_mutex_unlock(g_dtlsContextMutex);
632 if ((0 <= type) && (MAX_SUPPORTED_ADAPTERS > type))
634 // TODO: change the zeros to better values.
635 g_caDtlsContext->adapterCallbacks[0].recvCallback = recvCallback;
636 g_caDtlsContext->adapterCallbacks[0].sendCallback = sendCallback;
639 ca_mutex_unlock(g_dtlsContextMutex);
641 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
644 void CADTLSSetHandshakeCallback(CAErrorCallback dtlsHandshakeCallback)
646 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
647 g_dtlsHandshakeCallback = dtlsHandshakeCallback;
648 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
651 void CADTLSSetCredentialsCallback(CAGetDTLSPskCredentialsHandler credCallback)
653 // TODO Does this method needs protection of DtlsContextMutex ?
654 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
655 g_getCredentialsCallback = credCallback;
656 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
660 void CADTLSSetX509CredentialsCallback(CAGetDTLSX509CredentialsHandler credCallback)
662 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
663 g_getX509CredentialsCallback = credCallback;
664 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
666 void CADTLSSetCrlCallback(CAGetDTLSCrlHandler crlCallback)
668 // TODO Does this method needs protection of DtlsContextMutex ?
669 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
670 g_getCrlCallback = crlCallback;
671 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
673 #endif // __WITH_X509__
675 CAResult_t CADtlsSelectCipherSuite(const dtls_cipher_t cipher)
677 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN CADtlsSelectCipherSuite");
679 ca_mutex_lock(g_dtlsContextMutex);
680 if (NULL == g_caDtlsContext)
682 OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
683 ca_mutex_unlock(g_dtlsContextMutex);
684 return CA_STATUS_FAILED;
686 dtls_select_cipher(g_caDtlsContext->dtlsContext, cipher);
687 ca_mutex_unlock(g_dtlsContextMutex);
689 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "Selected cipher suite is 0x%02X%02X\n",
690 ((uint8_t*)(&cipher))[1], ((uint8_t*)(&cipher))[0]);
691 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT CADtlsSelectCipherSuite");
693 return CA_STATUS_OK ;
696 CAResult_t CADtlsEnableAnonECDHCipherSuite(const bool enable)
698 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN CADtlsEnablesAnonEcdh");
700 ca_mutex_lock(g_dtlsContextMutex);
701 if (NULL == g_caDtlsContext)
703 OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
704 ca_mutex_unlock(g_dtlsContextMutex);
705 return CA_STATUS_FAILED;
707 dtls_enables_anon_ecdh(g_caDtlsContext->dtlsContext,
708 enable == true ? DTLS_CIPHER_ENABLE : DTLS_CIPHER_DISABLE);
709 ca_mutex_unlock(g_dtlsContextMutex);
710 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256 is %s",
711 enable ? "enabled" : "disabled");
713 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT CADtlsEnablesAnonEcdh");
715 return CA_STATUS_OK ;
718 CAResult_t CADtlsInitiateHandshake(const CAEndpoint_t *endpoint)
720 stCADtlsAddrInfo_t dst = { 0 };
722 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN CADtlsInitiateHandshake");
726 return CA_STATUS_INVALID_PARAM;
729 CAConvertNameToAddr(endpoint->addr, endpoint->port, &(dst.addr.st));
731 dst.size = CASizeOfAddrInfo(&dst);
733 ca_mutex_lock(g_dtlsContextMutex);
734 if(NULL == g_caDtlsContext)
736 OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
737 ca_mutex_unlock(g_dtlsContextMutex);
738 return CA_STATUS_FAILED;
741 if(0 > dtls_connect(g_caDtlsContext->dtlsContext, (session_t*)(&dst)))
743 OIC_LOG(ERROR, NET_DTLS_TAG, "Failed to connect");
744 ca_mutex_unlock(g_dtlsContextMutex);
745 return CA_STATUS_FAILED;
748 ca_mutex_unlock(g_dtlsContextMutex);
750 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT CADtlsInitiateHandshake");
755 CAResult_t CADtlsClose(const CAEndpoint_t *endpoint)
757 stCADtlsAddrInfo_t dst = { 0 };
759 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN CADtlsDisconnect");
763 return CA_STATUS_INVALID_PARAM;
766 CAConvertNameToAddr(endpoint->addr, endpoint->port, &(dst.addr.st));
768 dst.size = CASizeOfAddrInfo(&dst);
770 ca_mutex_lock(g_dtlsContextMutex);
771 if (NULL == g_caDtlsContext)
773 OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
774 ca_mutex_unlock(g_dtlsContextMutex);
775 return CA_STATUS_FAILED;
778 if (0 > dtls_close(g_caDtlsContext->dtlsContext, (session_t*)(&dst)))
780 OIC_LOG(ERROR, NET_DTLS_TAG, "Failed to close the session");
781 ca_mutex_unlock(g_dtlsContextMutex);
782 return CA_STATUS_FAILED;
785 ca_mutex_unlock(g_dtlsContextMutex);
787 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT CADtlsDisconnect");
792 CAResult_t CADtlsGenerateOwnerPSK(const CAEndpoint_t *endpoint,
793 const uint8_t* label, const size_t labelLen,
794 const uint8_t* rsrcServerDeviceID, const size_t rsrcServerDeviceIDLen,
795 const uint8_t* provServerDeviceID, const size_t provServerDeviceIDLen,
796 uint8_t* ownerPSK, const size_t ownerPSKSize)
798 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN CADtlsGenerateOwnerPSK");
800 if(!endpoint || !label || 0 == labelLen || !ownerPSK || 0 == ownerPSKSize)
802 return CA_STATUS_INVALID_PARAM;
805 stCADtlsAddrInfo_t dst = { 0 };
807 CAConvertNameToAddr(endpoint->addr, endpoint->port, &(dst.addr.st));
809 dst.size = CASizeOfAddrInfo(&dst);
811 ca_mutex_lock(g_dtlsContextMutex);
812 if (NULL == g_caDtlsContext)
814 OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
815 ca_mutex_unlock(g_dtlsContextMutex);
816 return CA_STATUS_FAILED;
819 if( 0 == dtls_prf_with_current_keyblock(g_caDtlsContext->dtlsContext, (session_t*)(&dst),
820 label, labelLen, rsrcServerDeviceID, rsrcServerDeviceIDLen,
821 provServerDeviceID, provServerDeviceIDLen, ownerPSK, ownerPSKSize))
823 OIC_LOG(ERROR, NET_DTLS_TAG, "Failed to DTLS PRF");
824 ca_mutex_unlock(g_dtlsContextMutex);
825 return CA_STATUS_FAILED;
827 ca_mutex_unlock(g_dtlsContextMutex);
829 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT CADtlsGenerateOwnerPSK");
835 static CADtlsX509Creds_t g_X509Cred = {{0}, 0, 0, {0}, {0}, {0}};
839 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN CAInitX509");
840 VERIFY_NON_NULL_RET(g_getX509CredentialsCallback, NET_DTLS_TAG, "GetX509Credential callback", -1);
841 int isX509Init = (0 == g_getX509CredentialsCallback(&g_X509Cred));
845 uint8_t crlData[CRL_MAX_LEN] = {0};
846 ByteArray crlArray = {crlData, CRL_MAX_LEN};
847 g_getCrlCallback(&crlArray);
848 if (crlArray.len > 0)
850 uint8_t keyData[PUBLIC_KEY_SIZE] = {0};
851 CertificateList crl = CRL_INITIALIZER;
852 ByteArray rootPubKey = {keyData, PUBLIC_KEY_SIZE};
853 memcpy(keyData, g_X509Cred.rootPublicKeyX, PUBLIC_KEY_SIZE / 2);
854 memcpy(keyData + PUBLIC_KEY_SIZE / 2, g_X509Cred.rootPublicKeyY, PUBLIC_KEY_SIZE / 2);
855 DecodeCertificateList(crlArray, &crl, rootPubKey);
859 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT CAInitX509");
871 static int CAIsX509Active(struct dtls_context_t *ctx)
874 return TINY_DTLS_SUCCESS;
877 static int CAGetDeviceKey(struct dtls_context_t *ctx,
878 const session_t *session,
879 const dtls_ecc_key_t **result)
881 OIC_LOG(DEBUG, NET_DTLS_TAG, "CAGetDeviceKey");
882 static dtls_ecc_key_t ecdsa_key = {DTLS_ECDH_CURVE_SECP256R1, NULL, NULL, NULL};
884 int ret = TINY_DTLS_ERROR;
885 VERIFY_SUCCESS(CAInitX509(), 0);
887 ecdsa_key.priv_key = g_X509Cred.devicePrivateKey;
888 *result = &ecdsa_key;
890 ret = TINY_DTLS_SUCCESS;
896 CAGetDeviceCertificate(struct dtls_context_t *ctx,
897 const session_t *session,
898 const unsigned char **cert,
901 OIC_LOG(DEBUG, NET_DTLS_TAG, "CAGetDeviceCertificate");
902 int ret = TINY_DTLS_ERROR;
904 VERIFY_SUCCESS(CAInitX509(), 0);
906 *cert = g_X509Cred.certificateChain;
907 *cert_size = g_X509Cred.certificateChainLen;
909 ByteArray ownCert = {g_X509Cred.certificateChain, g_X509Cred.certificateChainLen};
910 PRINT_BYTE_ARRAY("OWN CERT: \n", ownCert);
913 ret = TINY_DTLS_SUCCESS;
919 * @brief Gets x and y components of Root Certificate Autority public key
921 * @return 0 on success otherwise a positive error value.
924 static int CAGetRootKey(const unsigned char **ca_pub_x, const unsigned char **ca_pub_y)
926 OIC_LOG(DEBUG, NET_DTLS_TAG, "CAGetRootKey");
929 VERIFY_SUCCESS(CAInitX509(), 0);
931 *ca_pub_x = g_X509Cred.rootPublicKeyX;
932 *ca_pub_y = g_X509Cred.rootPublicKeyY;
940 static int CAVerifyCertificate(struct dtls_context_t *ctx, const session_t *session,
941 const unsigned char *cert, size_t certLen,
942 const unsigned char *x, size_t xLen,
943 const unsigned char *y, size_t yLen)
945 OIC_LOG(DEBUG, NET_DTLS_TAG, "Verify Certificate");
947 ByteArray crtChainDer[MAX_CHAIN_LEN];
948 CertificateX509 crtChain[MAX_CHAIN_LEN];
952 int ret = TINY_DTLS_ERROR;
953 const unsigned char *ca_pub_x;
954 const unsigned char *ca_pub_y;
955 ByteArray certDerCode = BYTE_ARRAY_INITIALIZER;
956 ByteArray caPubKey = BYTE_ARRAY_INITIALIZER;
957 unsigned char ca_pub_key[PUBLIC_KEY_SIZE];
959 if ( !ctx || !session || !cert || !x || !y)
961 return TINY_DTLS_ERROR;
964 CAGetRootKey (&ca_pub_x, &ca_pub_y);
966 certDerCode.data = (uint8_t *)cert;
967 certDerCode.len = certLen;
970 PRINT_BYTE_ARRAY("CERT :\n", certDerCode);
974 caPubKey.len = PUBLIC_KEY_SIZE;
975 caPubKey.data = ca_pub_key;
977 memcpy(caPubKey.data, ca_pub_x, PUBLIC_KEY_SIZE / 2);
978 memcpy(caPubKey.data + PUBLIC_KEY_SIZE / 2, ca_pub_y, PUBLIC_KEY_SIZE / 2);
980 ret = (int) LoadCertificateChain (certDerCode, crtChainDer, &chainLength);
981 VERIFY_SUCCESS(ret, PKI_SUCCESS);
982 ret = (int) ParseCertificateChain (crtChainDer, crtChain, chainLength );
983 VERIFY_SUCCESS(ret, PKI_SUCCESS);
984 ret = (int) CheckCertificateChain (crtChain, chainLength, caPubKey);
985 VERIFY_SUCCESS(ret, PKI_SUCCESS);
987 INC_BYTE_ARRAY(crtChain[0].pubKey, 2);
989 memcpy(x, crtChain[0].pubKey.data, xLen);
990 memcpy(y, crtChain[0].pubKey.data + PUBLIC_KEY_SIZE / 2, yLen);
992 stCADtlsAddrInfo_t *addrInfo = (stCADtlsAddrInfo_t *)session;
993 char peerAddr[MAX_ADDR_STR_SIZE_CA] = { 0 };
995 CAConvertAddrToName(&(addrInfo->addr.st), addrInfo->size, peerAddr, &port);
997 CAResult_t result = CAAddIdToPeerInfoList(peerAddr, port,
998 crtChain[0].subject.data + DER_SUBJECT_HEADER_LEN + 2, crtChain[0].subject.data[DER_SUBJECT_HEADER_LEN + 1]);
999 if (CA_STATUS_OK != result )
1001 OIC_LOG(ERROR, NET_DTLS_TAG, "Fail to add peer id to gDtlsPeerInfoList");
1007 OIC_LOG(ERROR, NET_DTLS_TAG, "Certificate verification FAILED\n");
1008 return TINY_DTLS_ERROR;
1012 OIC_LOG(DEBUG, NET_DTLS_TAG, "Certificate verification SUCCESS\n");
1013 return TINY_DTLS_SUCCESS;
1019 static void CAStartRetransmit()
1021 static int timerId = -1;
1024 //clear previous timer
1025 unregisterTimer(timerId);
1027 ca_mutex_lock(g_dtlsContextMutex);
1029 //stop retransmission if context is invalid
1030 if(NULL == g_caDtlsContext)
1032 OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL. Stop retransmission");
1033 ca_mutex_unlock(g_dtlsContextMutex);
1036 dtls_check_retransmit(g_caDtlsContext->dtlsContext, NULL);
1037 ca_mutex_unlock(g_dtlsContextMutex);
1040 registerTimer(RETRANSMISSION_TIME, &timerId, CAStartRetransmit);
1043 CAResult_t CAAdapterNetDtlsInit()
1045 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
1047 // Initialize mutex for DtlsContext
1048 if (NULL == g_dtlsContextMutex)
1050 g_dtlsContextMutex = ca_mutex_new();
1051 VERIFY_NON_NULL_RET(g_dtlsContextMutex, NET_DTLS_TAG, "malloc failed",
1052 CA_MEMORY_ALLOC_FAILED);
1056 OIC_LOG(ERROR, NET_DTLS_TAG, "CAAdapterNetDtlsInit done already!");
1057 return CA_STATUS_OK;
1060 // Lock DtlsContext mutex and create DtlsContext
1061 ca_mutex_lock(g_dtlsContextMutex);
1062 g_caDtlsContext = (stCADtlsContext_t *)OICCalloc(1, sizeof(stCADtlsContext_t));
1064 if (NULL == g_caDtlsContext)
1066 OIC_LOG(ERROR, NET_DTLS_TAG, "Context malloc failed");
1067 ca_mutex_unlock(g_dtlsContextMutex);
1068 ca_mutex_free(g_dtlsContextMutex);
1069 return CA_MEMORY_ALLOC_FAILED;
1073 // Create PeerInfoList and CacheList
1074 g_caDtlsContext->peerInfoList = u_arraylist_create();
1075 g_caDtlsContext->cacheList = u_arraylist_create();
1077 if( (NULL == g_caDtlsContext->peerInfoList) ||
1078 (NULL == g_caDtlsContext->cacheList))
1080 OIC_LOG(ERROR, NET_DTLS_TAG, "peerInfoList or cacheList initialization failed!");
1082 CAFreePeerInfoList();
1083 OICFree(g_caDtlsContext);
1084 g_caDtlsContext = NULL;
1085 ca_mutex_unlock(g_dtlsContextMutex);
1086 ca_mutex_free(g_dtlsContextMutex);
1087 return CA_STATUS_FAILED;
1090 // Initialize clock, crypto and other global vars in tinyDTLS library
1093 // Create tinydtls Context
1094 g_caDtlsContext->dtlsContext = dtls_new_context(g_caDtlsContext);
1096 if (NULL == g_caDtlsContext->dtlsContext)
1098 OIC_LOG(ERROR, NET_DTLS_TAG, "dtls_new_context failed");
1099 ca_mutex_unlock(g_dtlsContextMutex);
1100 CAAdapterNetDtlsDeInit();
1101 return CA_STATUS_FAILED;
1104 g_caDtlsContext->callbacks.write = CASendSecureData;
1105 g_caDtlsContext->callbacks.read = CAReadDecryptedPayload;
1106 g_caDtlsContext->callbacks.event = CAHandleSecureEvent;
1108 g_caDtlsContext->callbacks.get_psk_info = CAGetPskCredentials;
1109 #ifdef __WITH_X509__
1110 g_caDtlsContext->callbacks.get_x509_key = CAGetDeviceKey;
1111 g_caDtlsContext->callbacks.verify_x509_cert = CAVerifyCertificate;
1112 g_caDtlsContext->callbacks.get_x509_cert = CAGetDeviceCertificate;
1113 g_caDtlsContext->callbacks.is_x509_active = CAIsX509Active;
1114 #endif //__WITH_X509__*
1115 dtls_set_handler(g_caDtlsContext->dtlsContext, &(g_caDtlsContext->callbacks));
1116 ca_mutex_unlock(g_dtlsContextMutex);
1118 CAStartRetransmit();
1120 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
1121 return CA_STATUS_OK;
1124 void CAAdapterNetDtlsDeInit()
1126 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
1128 VERIFY_NON_NULL_VOID(g_caDtlsContext, NET_DTLS_TAG, "context is NULL");
1129 VERIFY_NON_NULL_VOID(g_dtlsContextMutex, NET_DTLS_TAG, "context mutex is NULL");
1131 //Lock DtlsContext mutex
1132 ca_mutex_lock(g_dtlsContextMutex);
1135 CAFreePeerInfoList();
1138 // De-initialize tinydtls context
1139 dtls_free_context(g_caDtlsContext->dtlsContext);
1140 g_caDtlsContext->dtlsContext = NULL;
1142 // De-initialize DtlsContext
1143 OICFree(g_caDtlsContext);
1144 g_caDtlsContext = NULL;
1146 // Unlock DtlsContext mutex and de-initialize it
1147 ca_mutex_unlock(g_dtlsContextMutex);
1148 ca_mutex_free(g_dtlsContextMutex);
1149 g_dtlsContextMutex = NULL;
1151 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
1154 CAResult_t CAAdapterNetDtlsEncrypt(const CAEndpoint_t *endpoint,
1155 void *data, uint32_t dataLen)
1158 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
1160 VERIFY_NON_NULL_RET(endpoint, NET_DTLS_TAG,"Param remoteAddress is NULL",
1161 CA_STATUS_INVALID_PARAM);
1162 VERIFY_NON_NULL_RET(data, NET_DTLS_TAG, "Param data is NULL" ,
1163 CA_STATUS_INVALID_PARAM);
1167 OIC_LOG_V(ERROR, NET_DTLS_TAG, "dataLen is less than or equal zero [%d]", dataLen);
1168 return CA_STATUS_FAILED;
1171 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "Data to be encrypted dataLen [%d]", dataLen);
1173 stCADtlsAddrInfo_t addrInfo = { 0 };
1175 CAConvertNameToAddr(endpoint->addr, endpoint->port, &(addrInfo.addr.st));
1176 addrInfo.ifIndex = 0;
1177 addrInfo.size = CASizeOfAddrInfo(&addrInfo);
1179 ca_mutex_lock(g_dtlsContextMutex);
1180 if(NULL == g_caDtlsContext)
1182 OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
1183 ca_mutex_unlock(g_dtlsContextMutex);
1184 return CA_STATUS_FAILED;
1187 eDtlsRet_t ret = CAAdapterNetDtlsEncryptInternal(&addrInfo, data, dataLen);
1188 if (ret == DTLS_SESSION_INITIATED)
1190 stCACacheMessage_t *message = (stCACacheMessage_t *)OICCalloc(1, sizeof(stCACacheMessage_t));
1191 if (NULL == message)
1193 OIC_LOG(ERROR, NET_DTLS_TAG, "calloc failed!");
1194 ca_mutex_unlock(g_dtlsContextMutex);
1195 return CA_MEMORY_ALLOC_FAILED;
1198 message->data = (uint8_t *)OICCalloc(dataLen + 1, sizeof(uint8_t));
1199 if (NULL == message->data)
1201 OIC_LOG(ERROR, NET_DTLS_TAG, "calloc failed!");
1203 ca_mutex_unlock(g_dtlsContextMutex);
1204 return CA_MEMORY_ALLOC_FAILED;
1206 memcpy(message->data, data, dataLen);
1207 message->dataLen = dataLen;
1208 message->destSession = addrInfo;
1210 CAResult_t result = CADtlsCacheMsg(message);
1211 if (CA_STATUS_OK != result)
1213 OIC_LOG(DEBUG, NET_DTLS_TAG, "CADtlsCacheMsg failed!");
1214 CAFreeCacheMsg(message);
1216 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "OUT Initiating Dtls session [%d]", result);
1217 ca_mutex_unlock(g_dtlsContextMutex);
1221 ca_mutex_unlock(g_dtlsContextMutex);
1225 OIC_LOG(ERROR, NET_DTLS_TAG, "OUT FAILURE");
1226 return CA_STATUS_FAILED;
1229 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
1230 return CA_STATUS_OK;
1233 CAResult_t CAAdapterNetDtlsDecrypt(const CASecureEndpoint_t *sep,
1234 uint8_t *data, uint32_t dataLen)
1236 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
1237 VERIFY_NON_NULL_RET(sep, NET_DTLS_TAG, "endpoint is NULL" , CA_STATUS_INVALID_PARAM);
1239 stCADtlsAddrInfo_t addrInfo = { 0 };
1241 CAConvertNameToAddr(sep->endpoint.addr, sep->endpoint.port, &(addrInfo.addr.st));
1242 addrInfo.ifIndex = 0;
1243 addrInfo.size = CASizeOfAddrInfo(&addrInfo);
1245 ca_mutex_lock(g_dtlsContextMutex);
1246 if (NULL == g_caDtlsContext)
1248 OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
1249 ca_mutex_unlock(g_dtlsContextMutex);
1250 return CA_STATUS_FAILED;
1253 eDtlsRet_t ret = CAAdapterNetDtlsDecryptInternal(&addrInfo, data, dataLen);
1254 ca_mutex_unlock(g_dtlsContextMutex);
1256 if (DTLS_OK == ret || DTLS_HS_MSG == ret)
1258 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "Successfully Decrypted or Handshake msg recvd [%d]", ret);
1259 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
1260 return CA_STATUS_OK;
1263 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT FAILURE");
1264 return CA_STATUS_FAILED;