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 "iotivity_config.h"
21 #include "caadapternetdtls.h"
23 #include "caipinterface.h"
25 #include "oic_malloc.h"
26 #include "oic_string.h"
29 #if defined(HAVE_WINSOCK2_H) && defined(HAVE_WS2TCPIP_H)
37 /* tinyDTLS library error code */
38 #define TINY_DTLS_ERROR (-1)
39 /* tinyDTLS library success code */
40 #define TINY_DTLS_SUCCESS (0)
45 #include "cainterface.h"
47 /* lenght of ASN.1 header in DER format
48 * for subject field in X.509 certificate */
49 #define DER_SUBJECT_HEADER_LEN (9)
52 #define VERIFY_SUCCESS(op, successCode) { if ((op) != (successCode)) \
53 {OIC_LOG_V(FATAL, NET_DTLS_TAG, "%s failed!!", #op); goto exit;} }
58 * @brief Logging tag for module name
60 #define NET_DTLS_TAG "OIC_CA_NET_DTLS"
63 * @var g_caDtlsContext
64 * @brief global context which holds dtls context and cache list information.
66 static stCADtlsContext_t *g_caDtlsContext = NULL;
69 * @var g_dtlsContextMutex
70 * @brief Mutex to synchronize access to g_caDtlsContext.
72 static ca_mutex g_dtlsContextMutex = NULL;
75 * @var g_getCredentialsCallback
76 * @brief callback to get DTLS credentials
78 static CAGetDTLSPskCredentialsHandler g_getCredentialsCallback = NULL;
81 * @var RETRANSMISSION_TIME
82 * @brief Maximum timeout value (in seconds) to start DTLS retransmission.
84 #define RETRANSMISSION_TIME 1
87 * @var g_dtlsHandshakeCallback
88 * @brief callback to deliver the DTLS handshake result
90 static CAErrorCallback g_dtlsHandshakeCallback = NULL;
94 * @var g_getX509CredentialsCallback
95 * @brief callback to get DTLS certificate credentials
97 static CAGetDTLSX509CredentialsHandler g_getX509CredentialsCallback = NULL;
99 * @var g_getCrlCallback
100 * @brief callback to get CRL for DTLS
102 static CAGetDTLSCrlHandler g_getCrlCallback = NULL;
103 #endif //__WITH_X509__
106 static CASecureEndpoint_t *GetPeerInfo(const CAEndpoint_t *peer)
108 uint32_t list_index = 0;
109 uint32_t list_length = 0;
113 OIC_LOG(ERROR, NET_DTLS_TAG, "CAPeerInfoListContains invalid parameters");
117 CASecureEndpoint_t *peerInfo = NULL;
118 list_length = u_arraylist_length(g_caDtlsContext->peerInfoList);
119 for (list_index = 0; list_index < list_length; list_index++)
121 peerInfo = (CASecureEndpoint_t *)u_arraylist_get(g_caDtlsContext->peerInfoList, list_index);
122 if (NULL == peerInfo)
127 if((0 == strncmp(peer->addr, peerInfo->endpoint.addr, MAX_ADDR_STR_SIZE_CA)) &&
128 (peer->port == peerInfo->endpoint.port))
136 static CAResult_t CAAddIdToPeerInfoList(const char *peerAddr, uint32_t port,
137 const unsigned char *id, uint16_t id_length)
143 || CA_MAX_ENDPOINT_IDENTITY_LEN < id_length)
145 OIC_LOG(ERROR, NET_DTLS_TAG, "CAAddIdToPeerInfoList invalid parameters");
146 return CA_STATUS_INVALID_PARAM;
149 CASecureEndpoint_t *peer = (CASecureEndpoint_t *)OICCalloc(1, sizeof (CASecureEndpoint_t));
152 OIC_LOG(ERROR, NET_DTLS_TAG, "peerInfo malloc failed!");
153 return CA_MEMORY_ALLOC_FAILED;
156 OICStrcpy(peer->endpoint.addr, sizeof(peer->endpoint.addr), peerAddr);
157 peer->endpoint.port = port;
159 memcpy(peer->identity.id, id, id_length);
160 peer->identity.id_length = id_length;
162 if (NULL != GetPeerInfo(&peer->endpoint))
164 OIC_LOG(ERROR, NET_DTLS_TAG, "CAAddIdToPeerInfoList peer already exist");
166 return CA_STATUS_FAILED;
169 bool result = u_arraylist_add(g_caDtlsContext->peerInfoList, (void *)peer);
172 OIC_LOG(ERROR, NET_DTLS_TAG, "u_arraylist_add failed!");
174 return CA_STATUS_FAILED;
180 static void CAFreePeerInfoList()
182 uint32_t list_length = u_arraylist_length(g_caDtlsContext->peerInfoList);
183 for (uint32_t list_index = 0; list_index < list_length; list_index++)
185 CAEndpoint_t *peerInfo = (CAEndpoint_t *)u_arraylist_get(
186 g_caDtlsContext->peerInfoList, list_index);
189 u_arraylist_free(&(g_caDtlsContext->peerInfoList));
190 g_caDtlsContext->peerInfoList = NULL;
193 static void CARemovePeerFromPeerInfoList(const char * addr, uint16_t port)
195 if (NULL == addr || 0 >= port)
197 OIC_LOG(ERROR, NET_DTLS_TAG, "CADTLSGetPeerPSKId invalid parameters");
201 uint32_t list_length = u_arraylist_length(g_caDtlsContext->peerInfoList);
202 for (uint32_t list_index = 0; list_index < list_length; list_index++)
204 CAEndpoint_t *peerInfo = (CAEndpoint_t *)u_arraylist_get(
205 g_caDtlsContext->peerInfoList,list_index);
206 if (NULL == peerInfo)
210 if((0 == strncmp(addr, peerInfo->addr, MAX_ADDR_STR_SIZE_CA)) &&
211 (port == peerInfo->port))
213 OICFree(u_arraylist_remove(g_caDtlsContext->peerInfoList, list_index));
219 static int CASizeOfAddrInfo(stCADtlsAddrInfo_t *addrInfo)
221 VERIFY_NON_NULL_RET(addrInfo, NET_DTLS_TAG, "addrInfo is NULL" , DTLS_FAIL);
223 switch (addrInfo->addr.st.ss_family)
227 return sizeof (struct sockaddr_in);
231 return sizeof (struct sockaddr_in6);
238 return sizeof (struct sockaddr_storage);
241 static eDtlsRet_t CAAdapterNetDtlsEncryptInternal(const stCADtlsAddrInfo_t *dstSession,
242 uint8_t *data, uint32_t dataLen)
244 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
246 VERIFY_NON_NULL_RET(dstSession, NET_DTLS_TAG, "Param dstSession is NULL" , DTLS_FAIL);
247 VERIFY_NON_NULL_RET(data, NET_DTLS_TAG, "Param data is NULL" , DTLS_FAIL);
251 OIC_LOG(ERROR, NET_DTLS_TAG, "Given Packet length is equal to zero.");
255 if (NULL == g_caDtlsContext)
257 OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
261 // @todo: Remove need to typecast stCADtlsAddrInfo_t --> session_t below.
262 // Until then, apply a static assert.
263 OC_STATIC_ASSERT((sizeof(session_t) == sizeof(stCADtlsAddrInfo_t)),
264 "BUG: session_t size must exactly match stCADtlsAddrInfo_t!");
266 int retLen = dtls_write(g_caDtlsContext->dtlsContext, (session_t *)dstSession, data,
268 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "dtls_write retun len [%d]", retLen);
271 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT FAILURE");
276 // A new DTLS session was initiated by tinyDTLS library and wait for callback.
277 return DTLS_SESSION_INITIATED;
279 else if (dataLen != (uint32_t)retLen)
281 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT FAILURE");
284 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
288 static eDtlsRet_t CAAdapterNetDtlsDecryptInternal(const stCADtlsAddrInfo_t *srcSession,
289 uint8_t *buf, uint32_t bufLen)
291 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
293 VERIFY_NON_NULL_RET(srcSession, NET_DTLS_TAG, "Param srcSession is NULL", DTLS_FAIL);
294 VERIFY_NON_NULL_RET(buf, NET_DTLS_TAG, "Param buf is NULL", DTLS_FAIL);
298 OIC_LOG(ERROR, NET_DTLS_TAG, "Given Packet length is equal to zero.");
302 eDtlsRet_t ret = DTLS_FAIL;
304 // @todo: Remove need to typecast stCADtlsAddrInfo_t --> session_t below.
305 if (dtls_handle_message(g_caDtlsContext->dtlsContext, (session_t *)srcSession, buf, bufLen) == 0)
307 OIC_LOG(DEBUG, NET_DTLS_TAG, "dtls_handle_message success");
311 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
315 static void CAFreeCacheMsg(stCACacheMessage_t *msg)
317 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
318 VERIFY_NON_NULL_VOID(msg, NET_DTLS_TAG, "msg");
323 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
326 static void CAClearCacheList()
328 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
329 uint32_t list_index = 0;
330 uint32_t list_length = 0;
331 if (NULL == g_caDtlsContext)
333 OIC_LOG(ERROR, NET_DTLS_TAG, "Dtls Context is NULL");
336 list_length = u_arraylist_length(g_caDtlsContext->cacheList);
337 for (list_index = 0; list_index < list_length; list_index++)
339 stCACacheMessage_t *msg = (stCACacheMessage_t *)u_arraylist_get(g_caDtlsContext->cacheList,
346 u_arraylist_free(&g_caDtlsContext->cacheList);
347 g_caDtlsContext->cacheList = NULL;
348 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
351 static CAResult_t CADtlsCacheMsg(stCACacheMessage_t *msg)
353 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
355 if (NULL == g_caDtlsContext)
357 OIC_LOG(ERROR, NET_DTLS_TAG, "Dtls Context is NULL");
358 return CA_STATUS_FAILED;
361 bool result = u_arraylist_add(g_caDtlsContext->cacheList, (void *)msg);
364 OIC_LOG(ERROR, NET_DTLS_TAG, "u_arraylist_add failed!");
365 return CA_STATUS_FAILED;
368 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
373 static bool CAIsAddressMatching(const stCADtlsAddrInfo_t *a, const stCADtlsAddrInfo_t *b)
375 if (a->size != b->size)
379 if (memcmp(&a->addr, &b->addr, a->size))
386 static void CASendCachedMsg(const stCADtlsAddrInfo_t *dstSession)
388 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
389 VERIFY_NON_NULL_VOID(dstSession, NET_DTLS_TAG, "Param dstSession is NULL");
391 uint32_t list_index = 0;
392 uint32_t list_length = 0;
393 list_length = u_arraylist_length(g_caDtlsContext->cacheList);
394 for (list_index = 0; list_index < list_length;)
396 stCACacheMessage_t *msg = (stCACacheMessage_t *)u_arraylist_get(g_caDtlsContext->cacheList,
398 if ((NULL != msg) && (true == CAIsAddressMatching(&(msg->destSession), dstSession)))
400 eDtlsRet_t ret = CAAdapterNetDtlsEncryptInternal(&(msg->destSession),
401 msg->data, msg->dataLen);
404 OIC_LOG(DEBUG, NET_DTLS_TAG, "CAAdapterNetDtlsEncryptInternal success");
408 OIC_LOG(ERROR, NET_DTLS_TAG, "CAAdapterNetDtlsEncryptInternal failed.");
411 if (u_arraylist_remove(g_caDtlsContext->cacheList, list_index))
414 // Reduce list length by 1 as we removed one element.
419 OIC_LOG(ERROR, NET_DTLS_TAG, "u_arraylist_remove failed.");
425 // Move to the next element
430 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
433 static int32_t CAReadDecryptedPayload(dtls_context_t *context,
439 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
441 VERIFY_NON_NULL_RET(session, NET_DTLS_TAG, "Param Session is NULL", 0);
442 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "Decrypted buf len [%zu]", bufLen);
444 stCADtlsAddrInfo_t *addrInfo = (stCADtlsAddrInfo_t *)session;
446 CASecureEndpoint_t sep =
448 { .adapter = CA_ADAPTER_IP, .flags =
449 ((addrInfo->addr.st.ss_family == AF_INET) ? CA_IPV4 : CA_IPV6) | CA_SECURE, .port = 0 },
452 CAConvertAddrToName(&(addrInfo->addr.st), addrInfo->size, sep.endpoint.addr, &sep.endpoint.port);
454 if (NULL == g_caDtlsContext)
456 OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
457 return TINY_DTLS_ERROR;
461 if ((0 <= type) && (MAX_SUPPORTED_ADAPTERS > type) &&
462 (NULL != g_caDtlsContext->adapterCallbacks[type].recvCallback))
464 // Get identity of the source of packet
465 CASecureEndpoint_t *peerInfo = GetPeerInfo(&sep.endpoint);
468 sep.identity = peerInfo->identity;
471 g_caDtlsContext->adapterCallbacks[type].recvCallback(&sep, buf, bufLen);
475 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "recvCallback Callback or adapter type is wrong [%d]", type);
478 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
479 return TINY_DTLS_SUCCESS;
482 static int32_t CASendSecureData(dtls_context_t *context,
488 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
490 VERIFY_NON_NULL_RET(session, NET_DTLS_TAG, "Param Session is NULL", -1);
491 VERIFY_NON_NULL_RET(buf, NET_DTLS_TAG, "Param buf is NULL", -1);
495 OIC_LOG(ERROR, NET_DTLS_TAG, "Encrypted Buffer length is equal to zero");
499 stCADtlsAddrInfo_t *addrInfo = (stCADtlsAddrInfo_t *)session;
501 CAEndpoint_t endpoint = {.adapter = CA_DEFAULT_ADAPTER};
503 CAConvertAddrToName(&(addrInfo->addr.st), addrInfo->size, endpoint.addr, &endpoint.port);
504 endpoint.flags = addrInfo->addr.st.ss_family == AF_INET ? CA_IPV4 : CA_IPV6;
505 endpoint.flags |= CA_SECURE;
506 endpoint.adapter = CA_ADAPTER_IP;
507 endpoint.ifindex = session->ifindex;
510 //Mutex is not required for g_caDtlsContext. It will be called in same thread.
511 if ((0 <= type) && (MAX_SUPPORTED_ADAPTERS > type) &&
512 (NULL != g_caDtlsContext->adapterCallbacks[type].sendCallback))
514 g_caDtlsContext->adapterCallbacks[type].sendCallback(&endpoint, buf, bufLen);
518 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "send Callback or adapter type is wrong [%d]", type );
521 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
525 static int32_t CAHandleSecureEvent(dtls_context_t *context,
527 dtls_alert_level_t level,
531 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
533 VERIFY_NON_NULL_RET(session, NET_DTLS_TAG, "Param Session is NULL", 0);
535 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "level [%d] code [%u]\n", level, code);
537 CAEndpoint_t endpoint = {.adapter=CA_DEFAULT_ADAPTER};
538 CAErrorInfo_t errorInfo = {.result=CA_STATUS_OK};
540 stCADtlsAddrInfo_t *addrInfo = (stCADtlsAddrInfo_t *)session;
541 char peerAddr[MAX_ADDR_STR_SIZE_CA] = { 0 };
543 CAConvertAddrToName(&(addrInfo->addr.st), addrInfo->size, peerAddr, &port);
545 if (!level && (DTLS_EVENT_CONNECTED == code))
547 OIC_LOG(DEBUG, NET_DTLS_TAG, "Received DTLS_EVENT_CONNECTED. Sending Cached data");
549 if(g_dtlsHandshakeCallback)
551 OICStrcpy(endpoint.addr, MAX_ADDR_STR_SIZE_CA, peerAddr);
552 endpoint.port = port;
553 errorInfo.result = CA_STATUS_OK;
554 g_dtlsHandshakeCallback(&endpoint, &errorInfo);
557 CASendCachedMsg((stCADtlsAddrInfo_t *)session);
559 else if(DTLS_ALERT_LEVEL_FATAL == level && DTLS_ALERT_DECRYPT_ERROR == code)
561 if(g_dtlsHandshakeCallback)
563 OICStrcpy(endpoint.addr, MAX_ADDR_STR_SIZE_CA, peerAddr);
564 endpoint.addr[MAX_ADDR_STR_SIZE_CA - 1] = '\0';
565 endpoint.port = port;
566 errorInfo.result = CA_DTLS_AUTHENTICATION_FAILURE;
567 g_dtlsHandshakeCallback(&endpoint, &errorInfo);
570 else if(DTLS_ALERT_LEVEL_FATAL == level && DTLS_ALERT_HANDSHAKE_FAILURE == code)
572 OIC_LOG(INFO, NET_DTLS_TAG, "Failed to DTLS handshake, the peer will be removed.");
573 CARemovePeerFromPeerInfoList(peerAddr, port);
575 else if(DTLS_ALERT_LEVEL_FATAL == level || DTLS_ALERT_CLOSE_NOTIFY == code)
577 OIC_LOG(INFO, NET_DTLS_TAG, "Peer closing connection");
578 CARemovePeerFromPeerInfoList(peerAddr, port);
581 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
582 return TINY_DTLS_SUCCESS;
586 static int32_t CAGetPskCredentials(dtls_context_t *ctx,
587 const session_t *session,
588 dtls_credentials_type_t type,
589 const unsigned char *desc, size_t descLen,
590 unsigned char *result, size_t resultLen)
592 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
594 int32_t ret = TINY_DTLS_ERROR;
595 if(NULL == ctx || NULL == session || NULL == result)
597 OIC_LOG(ERROR, NET_DTLS_TAG, "CAGetPskCredentials invalid parameters");
601 VERIFY_NON_NULL_RET(g_getCredentialsCallback, NET_DTLS_TAG, "GetCredential callback", -1);
603 // Retrieve the credentials blob from security module
604 ret = g_getCredentialsCallback(type, desc, descLen, result, resultLen);
608 // TODO SRM needs identity of the remote end-point with every data packet to
609 // perform access control management. tinyDTLS 'frees' the handshake parameters
610 // data structure when handshake completes. Therefore, currently this is a
611 // workaround to cache remote end-point identity when tinyDTLS asks for PSK.
612 stCADtlsAddrInfo_t *addrInfo = (stCADtlsAddrInfo_t *)session;
613 char peerAddr[MAX_ADDR_STR_SIZE_CA] = { 0 };
615 CAConvertAddrToName(&(addrInfo->addr.st), addrInfo->size, peerAddr, &port);
617 if(CA_STATUS_OK != CAAddIdToPeerInfoList(peerAddr, port, desc, descLen) )
619 OIC_LOG(ERROR, NET_DTLS_TAG, "Fail to add peer id to gDtlsPeerInfoList");
626 void CADTLSSetAdapterCallbacks(CAPacketReceivedCallback recvCallback,
627 CAPacketSendCallback sendCallback,
628 CATransportAdapter_t type)
630 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
631 ca_mutex_lock(g_dtlsContextMutex);
632 if (NULL == g_caDtlsContext)
634 OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
635 ca_mutex_unlock(g_dtlsContextMutex);
639 if ((0 <= type) && (MAX_SUPPORTED_ADAPTERS > type))
641 // TODO: change the zeros to better values.
642 g_caDtlsContext->adapterCallbacks[0].recvCallback = recvCallback;
643 g_caDtlsContext->adapterCallbacks[0].sendCallback = sendCallback;
646 ca_mutex_unlock(g_dtlsContextMutex);
648 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
651 void CADTLSSetHandshakeCallback(CAErrorCallback dtlsHandshakeCallback)
653 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
654 g_dtlsHandshakeCallback = dtlsHandshakeCallback;
655 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
658 void CADTLSSetCredentialsCallback(CAGetDTLSPskCredentialsHandler credCallback)
660 // TODO Does this method needs protection of DtlsContextMutex ?
661 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
662 g_getCredentialsCallback = credCallback;
663 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
667 void CADTLSSetX509CredentialsCallback(CAGetDTLSX509CredentialsHandler credCallback)
669 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
670 g_getX509CredentialsCallback = credCallback;
671 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
673 void CADTLSSetCrlCallback(CAGetDTLSCrlHandler crlCallback)
675 // TODO Does this method needs protection of DtlsContextMutex ?
676 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
677 g_getCrlCallback = crlCallback;
678 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
680 #endif // __WITH_X509__
682 CAResult_t CADtlsSelectCipherSuite(const dtls_cipher_t cipher)
684 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN CADtlsSelectCipherSuite");
686 ca_mutex_lock(g_dtlsContextMutex);
687 if (NULL == g_caDtlsContext)
689 OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
690 ca_mutex_unlock(g_dtlsContextMutex);
691 return CA_STATUS_FAILED;
693 dtls_select_cipher(g_caDtlsContext->dtlsContext, cipher);
694 ca_mutex_unlock(g_dtlsContextMutex);
696 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "Selected cipher suite is 0x%02X%02X\n",
697 ((uint8_t*)(&cipher))[1], ((uint8_t*)(&cipher))[0]);
698 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT CADtlsSelectCipherSuite");
700 return CA_STATUS_OK ;
703 CAResult_t CADtlsEnableAnonECDHCipherSuite(const bool enable)
705 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN CADtlsEnablesAnonEcdh");
707 ca_mutex_lock(g_dtlsContextMutex);
708 if (NULL == g_caDtlsContext)
710 OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
711 ca_mutex_unlock(g_dtlsContextMutex);
712 return CA_STATUS_FAILED;
714 dtls_enables_anon_ecdh(g_caDtlsContext->dtlsContext,
715 enable == true ? DTLS_CIPHER_ENABLE : DTLS_CIPHER_DISABLE);
716 ca_mutex_unlock(g_dtlsContextMutex);
717 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256 is %s",
718 enable ? "enabled" : "disabled");
720 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT CADtlsEnablesAnonEcdh");
722 return CA_STATUS_OK ;
725 CAResult_t CADtlsInitiateHandshake(const CAEndpoint_t *endpoint)
727 stCADtlsAddrInfo_t dst = { 0 };
729 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN CADtlsInitiateHandshake");
733 return CA_STATUS_INVALID_PARAM;
736 CAConvertNameToAddr(endpoint->addr, endpoint->port, &(dst.addr.st));
738 dst.size = CASizeOfAddrInfo(&dst);
740 ca_mutex_lock(g_dtlsContextMutex);
741 if(NULL == g_caDtlsContext)
743 OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
744 ca_mutex_unlock(g_dtlsContextMutex);
745 return CA_STATUS_FAILED;
748 if(0 > dtls_connect(g_caDtlsContext->dtlsContext, (session_t*)(&dst)))
750 OIC_LOG(ERROR, NET_DTLS_TAG, "Failed to connect");
751 ca_mutex_unlock(g_dtlsContextMutex);
752 return CA_STATUS_FAILED;
755 ca_mutex_unlock(g_dtlsContextMutex);
757 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT CADtlsInitiateHandshake");
762 CAResult_t CADtlsClose(const CAEndpoint_t *endpoint)
764 stCADtlsAddrInfo_t dst = { 0 };
766 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN CADtlsDisconnect");
770 return CA_STATUS_INVALID_PARAM;
773 CAConvertNameToAddr(endpoint->addr, endpoint->port, &(dst.addr.st));
775 dst.size = CASizeOfAddrInfo(&dst);
777 ca_mutex_lock(g_dtlsContextMutex);
778 if (NULL == g_caDtlsContext)
780 OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
781 ca_mutex_unlock(g_dtlsContextMutex);
782 return CA_STATUS_FAILED;
785 if (0 > dtls_close(g_caDtlsContext->dtlsContext, (session_t*)(&dst)))
787 OIC_LOG(ERROR, NET_DTLS_TAG, "Failed to close the session");
788 ca_mutex_unlock(g_dtlsContextMutex);
789 return CA_STATUS_FAILED;
792 ca_mutex_unlock(g_dtlsContextMutex);
794 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT CADtlsDisconnect");
799 CAResult_t CADtlsGenerateOwnerPSK(const CAEndpoint_t *endpoint,
800 const uint8_t* label, const size_t labelLen,
801 const uint8_t* rsrcServerDeviceID, const size_t rsrcServerDeviceIDLen,
802 const uint8_t* provServerDeviceID, const size_t provServerDeviceIDLen,
803 uint8_t* ownerPSK, const size_t ownerPSKSize)
805 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN CADtlsGenerateOwnerPSK");
807 if(!endpoint || !label || 0 == labelLen || !ownerPSK || 0 == ownerPSKSize)
809 return CA_STATUS_INVALID_PARAM;
812 stCADtlsAddrInfo_t dst = { 0 };
814 CAConvertNameToAddr(endpoint->addr, endpoint->port, &(dst.addr.st));
816 dst.size = CASizeOfAddrInfo(&dst);
818 ca_mutex_lock(g_dtlsContextMutex);
819 if (NULL == g_caDtlsContext)
821 OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
822 ca_mutex_unlock(g_dtlsContextMutex);
823 return CA_STATUS_FAILED;
826 if( 0 == dtls_prf_with_current_keyblock(g_caDtlsContext->dtlsContext, (session_t*)(&dst),
827 label, labelLen, rsrcServerDeviceID, rsrcServerDeviceIDLen,
828 provServerDeviceID, provServerDeviceIDLen, ownerPSK, ownerPSKSize))
830 OIC_LOG(ERROR, NET_DTLS_TAG, "Failed to DTLS PRF");
831 ca_mutex_unlock(g_dtlsContextMutex);
832 return CA_STATUS_FAILED;
834 ca_mutex_unlock(g_dtlsContextMutex);
836 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT CADtlsGenerateOwnerPSK");
842 static CADtlsX509Creds_t g_X509Cred = {{0}, 0, 0, {0}, {0}, {0}};
846 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN CAInitX509");
847 VERIFY_NON_NULL_RET(g_getX509CredentialsCallback, NET_DTLS_TAG, "GetX509Credential callback", -1);
848 int isX509Init = (0 == g_getX509CredentialsCallback(&g_X509Cred));
852 uint8_t crlData[CRL_MAX_LEN] = {0};
853 ByteArray crlArray = {crlData, CRL_MAX_LEN};
854 g_getCrlCallback(&crlArray);
855 if (crlArray.len > 0)
857 uint8_t keyData[PUBLIC_KEY_SIZE] = {0};
858 CertificateList crl = CRL_INITIALIZER;
859 ByteArray rootPubKey = {keyData, PUBLIC_KEY_SIZE};
860 memcpy(keyData, g_X509Cred.rootPublicKeyX, PUBLIC_KEY_SIZE / 2);
861 memcpy(keyData + PUBLIC_KEY_SIZE / 2, g_X509Cred.rootPublicKeyY, PUBLIC_KEY_SIZE / 2);
862 DecodeCertificateList(crlArray, &crl, rootPubKey);
866 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT CAInitX509");
878 static int CAIsX509Active(struct dtls_context_t *ctx)
881 return TINY_DTLS_SUCCESS;
884 static int CAGetDeviceKey(struct dtls_context_t *ctx,
885 const session_t *session,
886 const dtls_ecc_key_t **result)
888 OIC_LOG(DEBUG, NET_DTLS_TAG, "CAGetDeviceKey");
889 static dtls_ecc_key_t ecdsa_key = {DTLS_ECDH_CURVE_SECP256R1, NULL, NULL, NULL};
891 int ret = TINY_DTLS_ERROR;
892 VERIFY_SUCCESS(CAInitX509(), 0);
894 ecdsa_key.priv_key = g_X509Cred.devicePrivateKey;
895 *result = &ecdsa_key;
897 ret = TINY_DTLS_SUCCESS;
903 CAGetDeviceCertificate(struct dtls_context_t *ctx,
904 const session_t *session,
905 const unsigned char **cert,
908 OIC_LOG(DEBUG, NET_DTLS_TAG, "CAGetDeviceCertificate");
909 int ret = TINY_DTLS_ERROR;
911 VERIFY_SUCCESS(CAInitX509(), 0);
913 *cert = g_X509Cred.certificateChain;
914 *cert_size = g_X509Cred.certificateChainLen;
916 ByteArray ownCert = {g_X509Cred.certificateChain, g_X509Cred.certificateChainLen};
917 PRINT_BYTE_ARRAY("OWN CERT: \n", ownCert);
920 ret = TINY_DTLS_SUCCESS;
926 * @brief Gets x and y components of Root Certificate Autority public key
928 * @return 0 on success otherwise a positive error value.
931 static int CAGetRootKey(const unsigned char **ca_pub_x, const unsigned char **ca_pub_y)
933 OIC_LOG(DEBUG, NET_DTLS_TAG, "CAGetRootKey");
936 VERIFY_SUCCESS(CAInitX509(), 0);
938 *ca_pub_x = g_X509Cred.rootPublicKeyX;
939 *ca_pub_y = g_X509Cred.rootPublicKeyY;
947 static int CAVerifyCertificate(struct dtls_context_t *ctx, const session_t *session,
948 const unsigned char *cert, size_t certLen,
949 const unsigned char *x, size_t xLen,
950 const unsigned char *y, size_t yLen)
952 OIC_LOG(DEBUG, NET_DTLS_TAG, "Verify Certificate");
954 ByteArray crtChainDer[MAX_CHAIN_LEN];
955 CertificateX509 crtChain[MAX_CHAIN_LEN];
959 int ret = TINY_DTLS_ERROR;
960 const unsigned char *ca_pub_x;
961 const unsigned char *ca_pub_y;
962 ByteArray certDerCode = BYTE_ARRAY_INITIALIZER;
963 ByteArray caPubKey = BYTE_ARRAY_INITIALIZER;
964 unsigned char ca_pub_key[PUBLIC_KEY_SIZE];
966 if ( !ctx || !session || !cert || !x || !y)
968 return TINY_DTLS_ERROR;
971 CAGetRootKey (&ca_pub_x, &ca_pub_y);
973 certDerCode.data = (uint8_t *)cert;
974 certDerCode.len = certLen;
977 PRINT_BYTE_ARRAY("CERT :\n", certDerCode);
981 caPubKey.len = PUBLIC_KEY_SIZE;
982 caPubKey.data = ca_pub_key;
984 memcpy(caPubKey.data, ca_pub_x, PUBLIC_KEY_SIZE / 2);
985 memcpy(caPubKey.data + PUBLIC_KEY_SIZE / 2, ca_pub_y, PUBLIC_KEY_SIZE / 2);
987 ret = (int) LoadCertificateChain (certDerCode, crtChainDer, &chainLength);
988 VERIFY_SUCCESS(ret, PKI_SUCCESS);
989 ret = (int) ParseCertificateChain (crtChainDer, crtChain, chainLength );
990 VERIFY_SUCCESS(ret, PKI_SUCCESS);
991 ret = (int) CheckCertificateChain (crtChain, chainLength, caPubKey);
992 VERIFY_SUCCESS(ret, PKI_SUCCESS);
994 INC_BYTE_ARRAY(crtChain[0].pubKey, 2);
996 memcpy(x, crtChain[0].pubKey.data, xLen);
997 memcpy(y, crtChain[0].pubKey.data + PUBLIC_KEY_SIZE / 2, yLen);
999 stCADtlsAddrInfo_t *addrInfo = (stCADtlsAddrInfo_t *)session;
1000 char peerAddr[MAX_ADDR_STR_SIZE_CA] = { 0 };
1002 CAConvertAddrToName(&(addrInfo->addr.st), addrInfo->size, peerAddr, &port);
1004 CAResult_t result = CAAddIdToPeerInfoList(peerAddr, port,
1005 crtChain[0].subject.data + DER_SUBJECT_HEADER_LEN + 2, crtChain[0].subject.data[DER_SUBJECT_HEADER_LEN + 1]);
1006 if (CA_STATUS_OK != result )
1008 OIC_LOG(ERROR, NET_DTLS_TAG, "Fail to add peer id to gDtlsPeerInfoList");
1014 OIC_LOG(ERROR, NET_DTLS_TAG, "Certificate verification FAILED\n");
1015 return TINY_DTLS_ERROR;
1019 OIC_LOG(DEBUG, NET_DTLS_TAG, "Certificate verification SUCCESS\n");
1020 return TINY_DTLS_SUCCESS;
1026 static void CAStartRetransmit()
1028 static int timerId = -1;
1031 //clear previous timer
1032 unregisterTimer(timerId);
1034 ca_mutex_lock(g_dtlsContextMutex);
1036 //stop retransmission if context is invalid
1037 if(NULL == g_caDtlsContext)
1039 OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL. Stop retransmission");
1040 ca_mutex_unlock(g_dtlsContextMutex);
1043 dtls_check_retransmit(g_caDtlsContext->dtlsContext, NULL);
1044 ca_mutex_unlock(g_dtlsContextMutex);
1047 registerTimer(RETRANSMISSION_TIME, &timerId, CAStartRetransmit);
1050 CAResult_t CAAdapterNetDtlsInit()
1052 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
1054 // Initialize mutex for DtlsContext
1055 if (NULL == g_dtlsContextMutex)
1057 g_dtlsContextMutex = ca_mutex_new();
1058 VERIFY_NON_NULL_RET(g_dtlsContextMutex, NET_DTLS_TAG, "malloc failed",
1059 CA_MEMORY_ALLOC_FAILED);
1063 OIC_LOG(ERROR, NET_DTLS_TAG, "CAAdapterNetDtlsInit done already!");
1064 return CA_STATUS_OK;
1067 // Lock DtlsContext mutex and create DtlsContext
1068 ca_mutex_lock(g_dtlsContextMutex);
1069 g_caDtlsContext = (stCADtlsContext_t *)OICCalloc(1, sizeof(stCADtlsContext_t));
1071 if (NULL == g_caDtlsContext)
1073 OIC_LOG(ERROR, NET_DTLS_TAG, "Context malloc failed");
1074 ca_mutex_unlock(g_dtlsContextMutex);
1075 ca_mutex_free(g_dtlsContextMutex);
1076 return CA_MEMORY_ALLOC_FAILED;
1080 // Create PeerInfoList and CacheList
1081 g_caDtlsContext->peerInfoList = u_arraylist_create();
1082 g_caDtlsContext->cacheList = u_arraylist_create();
1084 if( (NULL == g_caDtlsContext->peerInfoList) ||
1085 (NULL == g_caDtlsContext->cacheList))
1087 OIC_LOG(ERROR, NET_DTLS_TAG, "peerInfoList or cacheList initialization failed!");
1089 CAFreePeerInfoList();
1090 OICFree(g_caDtlsContext);
1091 g_caDtlsContext = NULL;
1092 ca_mutex_unlock(g_dtlsContextMutex);
1093 ca_mutex_free(g_dtlsContextMutex);
1094 return CA_STATUS_FAILED;
1097 // Initialize clock, crypto and other global vars in tinyDTLS library
1100 // Create tinydtls Context
1101 g_caDtlsContext->dtlsContext = dtls_new_context(g_caDtlsContext);
1103 if (NULL == g_caDtlsContext->dtlsContext)
1105 OIC_LOG(ERROR, NET_DTLS_TAG, "dtls_new_context failed");
1106 ca_mutex_unlock(g_dtlsContextMutex);
1107 CAAdapterNetDtlsDeInit();
1108 return CA_STATUS_FAILED;
1111 g_caDtlsContext->callbacks.write = CASendSecureData;
1112 g_caDtlsContext->callbacks.read = CAReadDecryptedPayload;
1113 g_caDtlsContext->callbacks.event = CAHandleSecureEvent;
1115 g_caDtlsContext->callbacks.get_psk_info = CAGetPskCredentials;
1116 #ifdef __WITH_X509__
1117 g_caDtlsContext->callbacks.get_x509_key = CAGetDeviceKey;
1118 g_caDtlsContext->callbacks.verify_x509_cert = CAVerifyCertificate;
1119 g_caDtlsContext->callbacks.get_x509_cert = CAGetDeviceCertificate;
1120 g_caDtlsContext->callbacks.is_x509_active = CAIsX509Active;
1121 #endif //__WITH_X509__*
1122 dtls_set_handler(g_caDtlsContext->dtlsContext, &(g_caDtlsContext->callbacks));
1123 ca_mutex_unlock(g_dtlsContextMutex);
1125 CAStartRetransmit();
1127 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
1128 return CA_STATUS_OK;
1131 void CAAdapterNetDtlsDeInit()
1133 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
1135 VERIFY_NON_NULL_VOID(g_caDtlsContext, NET_DTLS_TAG, "context is NULL");
1136 VERIFY_NON_NULL_VOID(g_dtlsContextMutex, NET_DTLS_TAG, "context mutex is NULL");
1138 //Lock DtlsContext mutex
1139 ca_mutex_lock(g_dtlsContextMutex);
1142 CAFreePeerInfoList();
1145 // De-initialize tinydtls context
1146 dtls_free_context(g_caDtlsContext->dtlsContext);
1147 g_caDtlsContext->dtlsContext = NULL;
1149 // De-initialize DtlsContext
1150 OICFree(g_caDtlsContext);
1151 g_caDtlsContext = NULL;
1153 // Unlock DtlsContext mutex and de-initialize it
1154 ca_mutex_unlock(g_dtlsContextMutex);
1155 ca_mutex_free(g_dtlsContextMutex);
1156 g_dtlsContextMutex = NULL;
1158 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
1161 CAResult_t CAAdapterNetDtlsEncrypt(const CAEndpoint_t *endpoint,
1162 void *data, uint32_t dataLen)
1165 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
1167 VERIFY_NON_NULL_RET(endpoint, NET_DTLS_TAG,"Param remoteAddress is NULL",
1168 CA_STATUS_INVALID_PARAM);
1169 VERIFY_NON_NULL_RET(data, NET_DTLS_TAG, "Param data is NULL" ,
1170 CA_STATUS_INVALID_PARAM);
1174 OIC_LOG_V(ERROR, NET_DTLS_TAG, "dataLen is less than or equal zero [%d]", dataLen);
1175 return CA_STATUS_FAILED;
1178 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "Data to be encrypted dataLen [%d]", dataLen);
1180 stCADtlsAddrInfo_t addrInfo = { 0 };
1182 CAConvertNameToAddr(endpoint->addr, endpoint->port, &(addrInfo.addr.st));
1183 addrInfo.ifIndex = 0;
1184 addrInfo.size = CASizeOfAddrInfo(&addrInfo);
1186 ca_mutex_lock(g_dtlsContextMutex);
1187 if(NULL == g_caDtlsContext)
1189 OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
1190 ca_mutex_unlock(g_dtlsContextMutex);
1191 return CA_STATUS_FAILED;
1194 eDtlsRet_t ret = CAAdapterNetDtlsEncryptInternal(&addrInfo, data, dataLen);
1195 if (ret == DTLS_SESSION_INITIATED)
1197 stCACacheMessage_t *message = (stCACacheMessage_t *)OICCalloc(1, sizeof(stCACacheMessage_t));
1198 if (NULL == message)
1200 OIC_LOG(ERROR, NET_DTLS_TAG, "calloc failed!");
1201 ca_mutex_unlock(g_dtlsContextMutex);
1202 return CA_MEMORY_ALLOC_FAILED;
1205 message->data = (uint8_t *)OICCalloc(dataLen + 1, sizeof(uint8_t));
1206 if (NULL == message->data)
1208 OIC_LOG(ERROR, NET_DTLS_TAG, "calloc failed!");
1210 ca_mutex_unlock(g_dtlsContextMutex);
1211 return CA_MEMORY_ALLOC_FAILED;
1213 memcpy(message->data, data, dataLen);
1214 message->dataLen = dataLen;
1215 message->destSession = addrInfo;
1217 CAResult_t result = CADtlsCacheMsg(message);
1218 if (CA_STATUS_OK != result)
1220 OIC_LOG(DEBUG, NET_DTLS_TAG, "CADtlsCacheMsg failed!");
1221 CAFreeCacheMsg(message);
1223 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "OUT Initiating Dtls session [%d]", result);
1224 ca_mutex_unlock(g_dtlsContextMutex);
1228 ca_mutex_unlock(g_dtlsContextMutex);
1232 OIC_LOG(ERROR, NET_DTLS_TAG, "OUT FAILURE");
1233 return CA_STATUS_FAILED;
1236 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
1237 return CA_STATUS_OK;
1240 CAResult_t CAAdapterNetDtlsDecrypt(const CASecureEndpoint_t *sep,
1241 uint8_t *data, uint32_t dataLen)
1243 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
1244 VERIFY_NON_NULL_RET(sep, NET_DTLS_TAG, "endpoint is NULL" , CA_STATUS_INVALID_PARAM);
1246 stCADtlsAddrInfo_t addrInfo = { 0 };
1248 CAConvertNameToAddr(sep->endpoint.addr, sep->endpoint.port, &(addrInfo.addr.st));
1249 addrInfo.ifIndex = 0;
1250 addrInfo.size = CASizeOfAddrInfo(&addrInfo);
1252 ca_mutex_lock(g_dtlsContextMutex);
1253 if (NULL == g_caDtlsContext)
1255 OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
1256 ca_mutex_unlock(g_dtlsContextMutex);
1257 return CA_STATUS_FAILED;
1260 eDtlsRet_t ret = CAAdapterNetDtlsDecryptInternal(&addrInfo, data, dataLen);
1261 ca_mutex_unlock(g_dtlsContextMutex);
1263 if (DTLS_OK == ret || DTLS_HS_MSG == ret)
1265 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "Successfully Decrypted or Handshake msg recvd [%d]", ret);
1266 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
1267 return CA_STATUS_OK;
1270 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT FAILURE");
1271 return CA_STATUS_FAILED;