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"
30 /* tinyDTLS library error code */
31 #define TINY_DTLS_ERROR (-1)
32 /* tinyDTLS library success code */
33 #define TINY_DTLS_SUCCESS (0)
38 #include "cainterface.h"
40 /* lenght of ASN.1 header in DER format
41 * for subject field in X.509 certificate */
42 #define DER_SUBJECT_HEADER_LEN (9)
45 #define VERIFY_SUCCESS(op, successCode) { if ((op) != (successCode)) \
46 {OIC_LOG_V(FATAL, NET_DTLS_TAG, "%s failed!!", #op); goto exit;} }
51 * @brief Logging tag for module name
53 #define NET_DTLS_TAG "OIC_CA_NET_DTLS"
56 * @var g_caDtlsContext
57 * @brief global context which holds dtls context and cache list information.
59 static stCADtlsContext_t *g_caDtlsContext = NULL;
62 * @var g_dtlsContextMutex
63 * @brief Mutex to synchronize access to g_caDtlsContext.
65 static ca_mutex g_dtlsContextMutex = NULL;
68 * @var g_getCredentialsCallback
69 * @brief callback to get DTLS credentials
71 static CAGetDTLSPskCredentialsHandler g_getCredentialsCallback = NULL;
74 * @var RETRANSMISSION_TIME
75 * @brief Maximum timeout value (in seconds) to start DTLS retransmission.
77 #define RETRANSMISSION_TIME 1
80 * @var g_dtlsHandshakeCallback
81 * @brief callback to deliver the DTLS handshake result
83 static CAErrorCallback g_dtlsHandshakeCallback = NULL;
87 * @var g_getX509CredentialsCallback
88 * @brief callback to get DTLS certificate credentials
90 static CAGetDTLSX509CredentialsHandler g_getX509CredentialsCallback = NULL;
92 * @var g_getCrlCallback
93 * @brief callback to get CRL for DTLS
95 static CAGetDTLSCrlHandler g_getCrlCallback = NULL;
96 #endif //__WITH_X509__
99 static CASecureEndpoint_t *GetPeerInfo(const CAEndpoint_t *peer)
101 uint32_t list_index = 0;
102 uint32_t list_length = 0;
106 OIC_LOG(ERROR, NET_DTLS_TAG, "CAPeerInfoListContains invalid parameters");
110 CASecureEndpoint_t *peerInfo = NULL;
111 list_length = u_arraylist_length(g_caDtlsContext->peerInfoList);
112 for (list_index = 0; list_index < list_length; list_index++)
114 peerInfo = (CASecureEndpoint_t *)u_arraylist_get(g_caDtlsContext->peerInfoList, list_index);
115 if (NULL == peerInfo)
120 if((0 == strncmp(peer->addr, peerInfo->endpoint.addr, MAX_ADDR_STR_SIZE_CA)) &&
121 (peer->port == peerInfo->endpoint.port))
129 static CAResult_t CAAddIdToPeerInfoList(const char *peerAddr, uint32_t port,
130 const unsigned char *id, uint16_t id_length)
136 || CA_MAX_ENDPOINT_IDENTITY_LEN < id_length)
138 OIC_LOG(ERROR, NET_DTLS_TAG, "CAAddIdToPeerInfoList invalid parameters");
139 return CA_STATUS_INVALID_PARAM;
142 CASecureEndpoint_t *peer = (CASecureEndpoint_t *)OICCalloc(1, sizeof (CASecureEndpoint_t));
145 OIC_LOG(ERROR, NET_DTLS_TAG, "peerInfo malloc failed!");
146 return CA_MEMORY_ALLOC_FAILED;
149 OICStrcpy(peer->endpoint.addr, sizeof(peer->endpoint.addr), peerAddr);
150 peer->endpoint.port = port;
152 memcpy(peer->identity.id, id, id_length);
153 peer->identity.id_length = id_length;
155 if (NULL != GetPeerInfo(&peer->endpoint))
157 OIC_LOG(ERROR, NET_DTLS_TAG, "CAAddIdToPeerInfoList peer already exist");
159 return CA_STATUS_FAILED;
162 bool result = u_arraylist_add(g_caDtlsContext->peerInfoList, (void *)peer);
165 OIC_LOG(ERROR, NET_DTLS_TAG, "u_arraylist_add failed!");
167 return CA_STATUS_FAILED;
173 static void CAFreePeerInfoList()
175 uint32_t list_length = u_arraylist_length(g_caDtlsContext->peerInfoList);
176 for (uint32_t list_index = 0; list_index < list_length; list_index++)
178 CAEndpoint_t *peerInfo = (CAEndpoint_t *)u_arraylist_get(
179 g_caDtlsContext->peerInfoList, list_index);
182 u_arraylist_free(&(g_caDtlsContext->peerInfoList));
183 g_caDtlsContext->peerInfoList = NULL;
186 static void CARemovePeerFromPeerInfoList(const char * addr, uint16_t port)
188 if (NULL == addr || 0 >= port)
190 OIC_LOG(ERROR, NET_DTLS_TAG, "CADTLSGetPeerPSKId invalid parameters");
194 uint32_t list_length = u_arraylist_length(g_caDtlsContext->peerInfoList);
195 for (uint32_t list_index = 0; list_index < list_length; list_index++)
197 CAEndpoint_t *peerInfo = (CAEndpoint_t *)u_arraylist_get(
198 g_caDtlsContext->peerInfoList,list_index);
199 if (NULL == peerInfo)
203 if((0 == strncmp(addr, peerInfo->addr, MAX_ADDR_STR_SIZE_CA)) &&
204 (port == peerInfo->port))
206 OICFree(u_arraylist_remove(g_caDtlsContext->peerInfoList, list_index));
212 static int CASizeOfAddrInfo(stCADtlsAddrInfo_t *addrInfo)
214 VERIFY_NON_NULL_RET(addrInfo, NET_DTLS_TAG, "addrInfo is NULL" , DTLS_FAIL);
216 switch (addrInfo->addr.st.ss_family)
220 return sizeof (struct sockaddr_in);
224 return sizeof (struct sockaddr_in6);
231 return sizeof (struct sockaddr_storage);
234 static eDtlsRet_t CAAdapterNetDtlsEncryptInternal(const stCADtlsAddrInfo_t *dstSession,
235 uint8_t *data, uint32_t dataLen)
237 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
239 VERIFY_NON_NULL_RET(dstSession, NET_DTLS_TAG, "Param dstSession is NULL" , DTLS_FAIL);
240 VERIFY_NON_NULL_RET(data, NET_DTLS_TAG, "Param data is NULL" , DTLS_FAIL);
244 OIC_LOG(ERROR, NET_DTLS_TAG, "Given Packet length is equal to zero.");
248 if (NULL == g_caDtlsContext)
250 OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
254 int retLen = dtls_write(g_caDtlsContext->dtlsContext, (session_t *)dstSession, data,
256 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "dtls_write retun len [%d]", retLen);
259 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT FAILURE");
264 // A new DTLS session was initiated by tinyDTLS library and wait for callback.
265 return DTLS_SESSION_INITIATED;
267 else if (dataLen != (uint32_t)retLen)
269 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT FAILURE");
272 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
276 static eDtlsRet_t CAAdapterNetDtlsDecryptInternal(const stCADtlsAddrInfo_t *srcSession,
277 uint8_t *buf, uint32_t bufLen)
279 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
281 VERIFY_NON_NULL_RET(srcSession, NET_DTLS_TAG, "Param srcSession is NULL", DTLS_FAIL);
282 VERIFY_NON_NULL_RET(buf, NET_DTLS_TAG, "Param buf is NULL", DTLS_FAIL);
286 OIC_LOG(ERROR, NET_DTLS_TAG, "Given Packet length is equal to zero.");
290 eDtlsRet_t ret = DTLS_FAIL;
292 if (dtls_handle_message(g_caDtlsContext->dtlsContext, (session_t *)srcSession, buf, bufLen) == 0)
294 OIC_LOG(DEBUG, NET_DTLS_TAG, "dtls_handle_message success");
298 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
302 static void CAFreeCacheMsg(stCACacheMessage_t *msg)
304 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
305 VERIFY_NON_NULL_VOID(msg, NET_DTLS_TAG, "msg");
310 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
313 static void CAClearCacheList()
315 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
316 uint32_t list_index = 0;
317 uint32_t list_length = 0;
318 if (NULL == g_caDtlsContext)
320 OIC_LOG(ERROR, NET_DTLS_TAG, "Dtls Context is NULL");
323 list_length = u_arraylist_length(g_caDtlsContext->cacheList);
324 for (list_index = 0; list_index < list_length; list_index++)
326 stCACacheMessage_t *msg = (stCACacheMessage_t *)u_arraylist_get(g_caDtlsContext->cacheList,
333 u_arraylist_free(&g_caDtlsContext->cacheList);
334 g_caDtlsContext->cacheList = NULL;
335 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
338 static CAResult_t CADtlsCacheMsg(stCACacheMessage_t *msg)
340 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
342 if (NULL == g_caDtlsContext)
344 OIC_LOG(ERROR, NET_DTLS_TAG, "Dtls Context is NULL");
345 return CA_STATUS_FAILED;
348 bool result = u_arraylist_add(g_caDtlsContext->cacheList, (void *)msg);
351 OIC_LOG(ERROR, NET_DTLS_TAG, "u_arraylist_add failed!");
352 return CA_STATUS_FAILED;
355 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
360 static bool CAIsAddressMatching(const stCADtlsAddrInfo_t *a, const stCADtlsAddrInfo_t *b)
362 if (a->size != b->size)
366 if (memcmp(&a->addr, &b->addr, a->size))
373 static void CASendCachedMsg(const stCADtlsAddrInfo_t *dstSession)
375 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
376 VERIFY_NON_NULL_VOID(dstSession, NET_DTLS_TAG, "Param dstSession is NULL");
378 uint32_t list_index = 0;
379 uint32_t list_length = 0;
380 list_length = u_arraylist_length(g_caDtlsContext->cacheList);
381 for (list_index = 0; list_index < list_length;)
383 stCACacheMessage_t *msg = (stCACacheMessage_t *)u_arraylist_get(g_caDtlsContext->cacheList,
385 if ((NULL != msg) && (true == CAIsAddressMatching(&(msg->destSession), dstSession)))
387 eDtlsRet_t ret = CAAdapterNetDtlsEncryptInternal(&(msg->destSession),
388 msg->data, msg->dataLen);
391 OIC_LOG(DEBUG, NET_DTLS_TAG, "CAAdapterNetDtlsEncryptInternal success");
395 OIC_LOG(ERROR, NET_DTLS_TAG, "CAAdapterNetDtlsEncryptInternal failed.");
398 if (u_arraylist_remove(g_caDtlsContext->cacheList, list_index))
401 // Reduce list length by 1 as we removed one element.
406 OIC_LOG(ERROR, NET_DTLS_TAG, "u_arraylist_remove failed.");
412 // Move to the next element
417 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
420 static int32_t CAReadDecryptedPayload(dtls_context_t *context,
426 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
428 VERIFY_NON_NULL_RET(session, NET_DTLS_TAG, "Param Session is NULL", 0);
429 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "Decrypted buf len [%zu]", bufLen);
431 stCADtlsAddrInfo_t *addrInfo = (stCADtlsAddrInfo_t *)session;
433 CASecureEndpoint_t sep =
435 { .adapter = CA_ADAPTER_IP, .flags =
436 ((addrInfo->addr.st.ss_family == AF_INET) ? CA_IPV4 : CA_IPV6) | CA_SECURE, .port = 0 },
439 CAConvertAddrToName(&(addrInfo->addr.st), addrInfo->size, sep.endpoint.addr, &sep.endpoint.port);
441 if (NULL == g_caDtlsContext)
443 OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
444 return TINY_DTLS_ERROR;
448 if ((0 <= type) && (MAX_SUPPORTED_ADAPTERS > type) &&
449 (NULL != g_caDtlsContext->adapterCallbacks[type].recvCallback))
451 // Get identity of the source of packet
452 CASecureEndpoint_t *peerInfo = GetPeerInfo(&sep.endpoint);
455 sep.identity = peerInfo->identity;
458 g_caDtlsContext->adapterCallbacks[type].recvCallback(&sep, buf, bufLen);
462 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "recvCallback Callback or adapter type is wrong [%d]", type);
465 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
466 return TINY_DTLS_SUCCESS;
469 static int32_t CASendSecureData(dtls_context_t *context,
475 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
477 VERIFY_NON_NULL_RET(session, NET_DTLS_TAG, "Param Session is NULL", -1);
478 VERIFY_NON_NULL_RET(buf, NET_DTLS_TAG, "Param buf is NULL", -1);
482 OIC_LOG(ERROR, NET_DTLS_TAG, "Encrypted Buffer length is equal to zero");
486 stCADtlsAddrInfo_t *addrInfo = (stCADtlsAddrInfo_t *)session;
488 CAEndpoint_t endpoint = {.adapter = CA_DEFAULT_ADAPTER};
490 CAConvertAddrToName(&(addrInfo->addr.st), addrInfo->size, endpoint.addr, &endpoint.port);
491 endpoint.flags = addrInfo->addr.st.ss_family == AF_INET ? CA_IPV4 : CA_IPV6;
492 endpoint.flags |= CA_SECURE;
493 endpoint.adapter = CA_ADAPTER_IP;
494 endpoint.interface = session->ifindex;
497 //Mutex is not required for g_caDtlsContext. It will be called in same thread.
498 if ((0 <= type) && (MAX_SUPPORTED_ADAPTERS > type) &&
499 (NULL != g_caDtlsContext->adapterCallbacks[type].sendCallback))
501 g_caDtlsContext->adapterCallbacks[type].sendCallback(&endpoint, buf, bufLen);
505 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "send Callback or adapter type is wrong [%d]", type );
508 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
512 static int32_t CAHandleSecureEvent(dtls_context_t *context,
514 dtls_alert_level_t level,
518 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
520 VERIFY_NON_NULL_RET(session, NET_DTLS_TAG, "Param Session is NULL", 0);
522 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "level [%d] code [%u]\n", level, code);
524 CAEndpoint_t endpoint = {.adapter=CA_DEFAULT_ADAPTER};
525 CAErrorInfo_t errorInfo = {.result=CA_STATUS_OK};
527 stCADtlsAddrInfo_t *addrInfo = (stCADtlsAddrInfo_t *)session;
528 char peerAddr[MAX_ADDR_STR_SIZE_CA] = { 0 };
530 CAConvertAddrToName(&(addrInfo->addr.st), addrInfo->size, peerAddr, &port);
532 if (!level && (DTLS_EVENT_CONNECTED == code))
534 OIC_LOG(DEBUG, NET_DTLS_TAG, "Received DTLS_EVENT_CONNECTED. Sending Cached data");
536 if(g_dtlsHandshakeCallback)
538 OICStrcpy(endpoint.addr, MAX_ADDR_STR_SIZE_CA, peerAddr);
539 endpoint.port = port;
540 errorInfo.result = CA_STATUS_OK;
541 g_dtlsHandshakeCallback(&endpoint, &errorInfo);
544 CASendCachedMsg((stCADtlsAddrInfo_t *)session);
546 else if(DTLS_ALERT_LEVEL_FATAL == level && DTLS_ALERT_DECRYPT_ERROR == code)
548 if(g_dtlsHandshakeCallback)
550 OICStrcpy(endpoint.addr, MAX_ADDR_STR_SIZE_CA, peerAddr);
551 endpoint.addr[MAX_ADDR_STR_SIZE_CA - 1] = '\0';
552 endpoint.port = port;
553 errorInfo.result = CA_DTLS_AUTHENTICATION_FAILURE;
554 g_dtlsHandshakeCallback(&endpoint, &errorInfo);
557 else if(DTLS_ALERT_LEVEL_FATAL == level && DTLS_ALERT_HANDSHAKE_FAILURE == code)
559 OIC_LOG(INFO, NET_DTLS_TAG, "Failed to DTLS handshake, the peer will be removed.");
560 CARemovePeerFromPeerInfoList(peerAddr, port);
562 else if(DTLS_ALERT_LEVEL_FATAL == level || DTLS_ALERT_CLOSE_NOTIFY == code)
564 OIC_LOG(INFO, NET_DTLS_TAG, "Peer closing connection");
565 CARemovePeerFromPeerInfoList(peerAddr, port);
568 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
569 return TINY_DTLS_SUCCESS;
573 static int32_t CAGetPskCredentials(dtls_context_t *ctx,
574 const session_t *session,
575 dtls_credentials_type_t type,
576 const unsigned char *desc, size_t descLen,
577 unsigned char *result, size_t resultLen)
579 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
581 int32_t ret = TINY_DTLS_ERROR;
582 if(NULL == ctx || NULL == session || NULL == result)
584 OIC_LOG(ERROR, NET_DTLS_TAG, "CAGetPskCredentials invalid parameters");
588 VERIFY_NON_NULL_RET(g_getCredentialsCallback, NET_DTLS_TAG, "GetCredential callback", -1);
590 // Retrieve the credentials blob from security module
591 ret = g_getCredentialsCallback(type, desc, descLen, result, resultLen);
595 // TODO SRM needs identity of the remote end-point with every data packet to
596 // perform access control management. tinyDTLS 'frees' the handshake parameters
597 // data structure when handshake completes. Therefore, currently this is a
598 // workaround to cache remote end-point identity when tinyDTLS asks for PSK.
599 stCADtlsAddrInfo_t *addrInfo = (stCADtlsAddrInfo_t *)session;
600 char peerAddr[MAX_ADDR_STR_SIZE_CA] = { 0 };
602 CAConvertAddrToName(&(addrInfo->addr.st), addrInfo->size, peerAddr, &port);
604 if(CA_STATUS_OK != CAAddIdToPeerInfoList(peerAddr, port, desc, descLen) )
606 OIC_LOG(ERROR, NET_DTLS_TAG, "Fail to add peer id to gDtlsPeerInfoList");
613 void CADTLSSetAdapterCallbacks(CAPacketReceivedCallback recvCallback,
614 CAPacketSendCallback sendCallback,
615 CATransportAdapter_t type)
617 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
618 ca_mutex_lock(g_dtlsContextMutex);
619 if (NULL == g_caDtlsContext)
621 OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
622 ca_mutex_unlock(g_dtlsContextMutex);
626 if ((0 <= type) && (MAX_SUPPORTED_ADAPTERS > type))
628 // TODO: change the zeros to better values.
629 g_caDtlsContext->adapterCallbacks[0].recvCallback = recvCallback;
630 g_caDtlsContext->adapterCallbacks[0].sendCallback = sendCallback;
633 ca_mutex_unlock(g_dtlsContextMutex);
635 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
638 void CADTLSSetHandshakeCallback(CAErrorCallback dtlsHandshakeCallback)
640 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
641 g_dtlsHandshakeCallback = dtlsHandshakeCallback;
642 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
645 void CADTLSSetCredentialsCallback(CAGetDTLSPskCredentialsHandler credCallback)
647 // TODO Does this method needs protection of DtlsContextMutex ?
648 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
649 g_getCredentialsCallback = credCallback;
650 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
654 void CADTLSSetX509CredentialsCallback(CAGetDTLSX509CredentialsHandler credCallback)
656 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
657 g_getX509CredentialsCallback = credCallback;
658 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
660 void CADTLSSetCrlCallback(CAGetDTLSCrlHandler crlCallback)
662 // TODO Does this method needs protection of DtlsContextMutex ?
663 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
664 g_getCrlCallback = crlCallback;
665 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
667 #endif // __WITH_X509__
669 CAResult_t CADtlsSelectCipherSuite(const dtls_cipher_t cipher)
671 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN CADtlsSelectCipherSuite");
673 ca_mutex_lock(g_dtlsContextMutex);
674 if (NULL == g_caDtlsContext)
676 OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
677 ca_mutex_unlock(g_dtlsContextMutex);
678 return CA_STATUS_FAILED;
680 dtls_select_cipher(g_caDtlsContext->dtlsContext, cipher);
681 ca_mutex_unlock(g_dtlsContextMutex);
683 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "Selected cipher suite is 0x%02X%02X\n",
684 ((uint8_t*)(&cipher))[1], ((uint8_t*)(&cipher))[0]);
685 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT CADtlsSelectCipherSuite");
687 return CA_STATUS_OK ;
690 CAResult_t CADtlsEnableAnonECDHCipherSuite(const bool enable)
692 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN CADtlsEnablesAnonEcdh");
694 ca_mutex_lock(g_dtlsContextMutex);
695 if (NULL == g_caDtlsContext)
697 OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
698 ca_mutex_unlock(g_dtlsContextMutex);
699 return CA_STATUS_FAILED;
701 dtls_enables_anon_ecdh(g_caDtlsContext->dtlsContext,
702 enable == true ? DTLS_CIPHER_ENABLE : DTLS_CIPHER_DISABLE);
703 ca_mutex_unlock(g_dtlsContextMutex);
704 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256 is %s",
705 enable ? "enabled" : "disabled");
707 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT CADtlsEnablesAnonEcdh");
709 return CA_STATUS_OK ;
712 CAResult_t CADtlsInitiateHandshake(const CAEndpoint_t *endpoint)
714 stCADtlsAddrInfo_t dst = { 0 };
716 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN CADtlsInitiateHandshake");
720 return CA_STATUS_INVALID_PARAM;
723 CAConvertNameToAddr(endpoint->addr, endpoint->port, &(dst.addr.st));
725 dst.size = CASizeOfAddrInfo(&dst);
727 ca_mutex_lock(g_dtlsContextMutex);
728 if(NULL == g_caDtlsContext)
730 OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
731 ca_mutex_unlock(g_dtlsContextMutex);
732 return CA_STATUS_FAILED;
735 if(0 > dtls_connect(g_caDtlsContext->dtlsContext, (session_t*)(&dst)))
737 OIC_LOG(ERROR, NET_DTLS_TAG, "Failed to connect");
738 ca_mutex_unlock(g_dtlsContextMutex);
739 return CA_STATUS_FAILED;
742 ca_mutex_unlock(g_dtlsContextMutex);
744 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT CADtlsInitiateHandshake");
749 CAResult_t CADtlsClose(const CAEndpoint_t *endpoint)
751 stCADtlsAddrInfo_t dst = { 0 };
753 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN CADtlsDisconnect");
757 return CA_STATUS_INVALID_PARAM;
760 CAConvertNameToAddr(endpoint->addr, endpoint->port, &(dst.addr.st));
762 dst.size = CASizeOfAddrInfo(&dst);
764 ca_mutex_lock(g_dtlsContextMutex);
765 if (NULL == g_caDtlsContext)
767 OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
768 ca_mutex_unlock(g_dtlsContextMutex);
769 return CA_STATUS_FAILED;
772 if (0 > dtls_close(g_caDtlsContext->dtlsContext, (session_t*)(&dst)))
774 OIC_LOG(ERROR, NET_DTLS_TAG, "Failed to close the session");
775 ca_mutex_unlock(g_dtlsContextMutex);
776 return CA_STATUS_FAILED;
779 ca_mutex_unlock(g_dtlsContextMutex);
781 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT CADtlsDisconnect");
786 CAResult_t CADtlsGenerateOwnerPSK(const CAEndpoint_t *endpoint,
787 const uint8_t* label, const size_t labelLen,
788 const uint8_t* rsrcServerDeviceID, const size_t rsrcServerDeviceIDLen,
789 const uint8_t* provServerDeviceID, const size_t provServerDeviceIDLen,
790 uint8_t* ownerPSK, const size_t ownerPSKSize)
792 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN CADtlsGenerateOwnerPSK");
794 if(!endpoint || !label || 0 == labelLen || !ownerPSK || 0 == ownerPSKSize)
796 return CA_STATUS_INVALID_PARAM;
799 stCADtlsAddrInfo_t dst = { 0 };
801 CAConvertNameToAddr(endpoint->addr, endpoint->port, &(dst.addr.st));
803 dst.size = CASizeOfAddrInfo(&dst);
805 ca_mutex_lock(g_dtlsContextMutex);
806 if (NULL == g_caDtlsContext)
808 OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
809 ca_mutex_unlock(g_dtlsContextMutex);
810 return CA_STATUS_FAILED;
813 if( 0 == dtls_prf_with_current_keyblock(g_caDtlsContext->dtlsContext, (session_t*)(&dst),
814 label, labelLen, rsrcServerDeviceID, rsrcServerDeviceIDLen,
815 provServerDeviceID, provServerDeviceIDLen, ownerPSK, ownerPSKSize))
817 OIC_LOG(ERROR, NET_DTLS_TAG, "Failed to DTLS PRF");
818 ca_mutex_unlock(g_dtlsContextMutex);
819 return CA_STATUS_FAILED;
821 ca_mutex_unlock(g_dtlsContextMutex);
823 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT CADtlsGenerateOwnerPSK");
829 static CADtlsX509Creds_t g_X509Cred = {{0}, 0, 0, {0}, {0}, {0}};
833 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN CAInitX509");
834 VERIFY_NON_NULL_RET(g_getX509CredentialsCallback, NET_DTLS_TAG, "GetX509Credential callback", -1);
835 int isX509Init = (0 == g_getX509CredentialsCallback(&g_X509Cred));
839 uint8_t crlData[CRL_MAX_LEN] = {0};
840 ByteArray crlArray = {crlData, CRL_MAX_LEN};
841 g_getCrlCallback(&crlArray);
842 if (crlArray.len > 0)
844 uint8_t keyData[PUBLIC_KEY_SIZE] = {0};
845 CertificateList crl = CRL_INITIALIZER;
846 ByteArray rootPubKey = {keyData, PUBLIC_KEY_SIZE};
847 memcpy(keyData, g_X509Cred.rootPublicKeyX, PUBLIC_KEY_SIZE / 2);
848 memcpy(keyData + PUBLIC_KEY_SIZE / 2, g_X509Cred.rootPublicKeyY, PUBLIC_KEY_SIZE / 2);
849 DecodeCertificateList(crlArray, &crl, rootPubKey);
853 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT CAInitX509");
865 static int CAIsX509Active(struct dtls_context_t *ctx)
868 return TINY_DTLS_SUCCESS;
871 static int CAGetDeviceKey(struct dtls_context_t *ctx,
872 const session_t *session,
873 const dtls_ecc_key_t **result)
875 OIC_LOG(DEBUG, NET_DTLS_TAG, "CAGetDeviceKey");
876 static dtls_ecc_key_t ecdsa_key = {DTLS_ECDH_CURVE_SECP256R1, NULL, NULL, NULL};
878 int ret = TINY_DTLS_ERROR;
879 VERIFY_SUCCESS(CAInitX509(), 0);
881 ecdsa_key.priv_key = g_X509Cred.devicePrivateKey;
882 *result = &ecdsa_key;
884 ret = TINY_DTLS_SUCCESS;
890 CAGetDeviceCertificate(struct dtls_context_t *ctx,
891 const session_t *session,
892 const unsigned char **cert,
895 OIC_LOG(DEBUG, NET_DTLS_TAG, "CAGetDeviceCertificate");
896 int ret = TINY_DTLS_ERROR;
898 VERIFY_SUCCESS(CAInitX509(), 0);
900 *cert = g_X509Cred.certificateChain;
901 *cert_size = g_X509Cred.certificateChainLen;
903 ByteArray ownCert = {g_X509Cred.certificateChain, g_X509Cred.certificateChainLen};
904 PRINT_BYTE_ARRAY("OWN CERT: \n", ownCert);
907 ret = TINY_DTLS_SUCCESS;
913 * @brief Gets x and y components of Root Certificate Autority public key
915 * @return 0 on success otherwise a positive error value.
918 static int CAGetRootKey(const unsigned char **ca_pub_x, const unsigned char **ca_pub_y)
920 OIC_LOG(DEBUG, NET_DTLS_TAG, "CAGetRootKey");
923 VERIFY_SUCCESS(CAInitX509(), 0);
925 *ca_pub_x = g_X509Cred.rootPublicKeyX;
926 *ca_pub_y = g_X509Cred.rootPublicKeyY;
934 static int CAVerifyCertificate(struct dtls_context_t *ctx, const session_t *session,
935 const unsigned char *cert, size_t certLen,
936 const unsigned char *x, size_t xLen,
937 const unsigned char *y, size_t yLen)
939 OIC_LOG(DEBUG, NET_DTLS_TAG, "Verify Certificate");
941 ByteArray crtChainDer[MAX_CHAIN_LEN];
942 CertificateX509 crtChain[MAX_CHAIN_LEN];
946 int ret = TINY_DTLS_ERROR;
947 const unsigned char *ca_pub_x;
948 const unsigned char *ca_pub_y;
949 ByteArray certDerCode = BYTE_ARRAY_INITIALIZER;
950 ByteArray caPubKey = BYTE_ARRAY_INITIALIZER;
951 unsigned char ca_pub_key[PUBLIC_KEY_SIZE];
953 if ( !ctx || !session || !cert || !x || !y)
955 return TINY_DTLS_ERROR;
958 CAGetRootKey (&ca_pub_x, &ca_pub_y);
960 certDerCode.data = (uint8_t *)cert;
961 certDerCode.len = certLen;
964 PRINT_BYTE_ARRAY("CERT :\n", certDerCode);
968 caPubKey.len = PUBLIC_KEY_SIZE;
969 caPubKey.data = ca_pub_key;
971 memcpy(caPubKey.data, ca_pub_x, PUBLIC_KEY_SIZE / 2);
972 memcpy(caPubKey.data + PUBLIC_KEY_SIZE / 2, ca_pub_y, PUBLIC_KEY_SIZE / 2);
974 ret = (int) LoadCertificateChain (certDerCode, crtChainDer, &chainLength);
975 VERIFY_SUCCESS(ret, PKI_SUCCESS);
976 ret = (int) ParseCertificateChain (crtChainDer, crtChain, chainLength );
977 VERIFY_SUCCESS(ret, PKI_SUCCESS);
978 ret = (int) CheckCertificateChain (crtChain, chainLength, caPubKey);
979 VERIFY_SUCCESS(ret, PKI_SUCCESS);
981 INC_BYTE_ARRAY(crtChain[0].pubKey, 2);
983 memcpy(x, crtChain[0].pubKey.data, xLen);
984 memcpy(y, crtChain[0].pubKey.data + PUBLIC_KEY_SIZE / 2, yLen);
986 stCADtlsAddrInfo_t *addrInfo = (stCADtlsAddrInfo_t *)session;
987 char peerAddr[MAX_ADDR_STR_SIZE_CA] = { 0 };
989 CAConvertAddrToName(&(addrInfo->addr.st), addrInfo->size, peerAddr, &port);
991 CAResult_t result = CAAddIdToPeerInfoList(peerAddr, port,
992 crtChain[0].subject.data + DER_SUBJECT_HEADER_LEN + 2, crtChain[0].subject.data[DER_SUBJECT_HEADER_LEN + 1]);
993 if (CA_STATUS_OK != result )
995 OIC_LOG(ERROR, NET_DTLS_TAG, "Fail to add peer id to gDtlsPeerInfoList");
1001 OIC_LOG(ERROR, NET_DTLS_TAG, "Certificate verification FAILED\n");
1002 return TINY_DTLS_ERROR;
1006 OIC_LOG(DEBUG, NET_DTLS_TAG, "Certificate verification SUCCESS\n");
1007 return TINY_DTLS_SUCCESS;
1013 static void CAStartRetransmit()
1015 static int timerId = -1;
1018 //clear previous timer
1019 unregisterTimer(timerId);
1021 ca_mutex_lock(g_dtlsContextMutex);
1023 //stop retransmission if context is invalid
1024 if(NULL == g_caDtlsContext)
1026 OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL. Stop retransmission");
1027 ca_mutex_unlock(g_dtlsContextMutex);
1030 dtls_check_retransmit(g_caDtlsContext->dtlsContext, NULL);
1031 ca_mutex_unlock(g_dtlsContextMutex);
1034 registerTimer(RETRANSMISSION_TIME, &timerId, CAStartRetransmit);
1037 CAResult_t CAAdapterNetDtlsInit()
1039 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
1041 // Initialize mutex for DtlsContext
1042 if (NULL == g_dtlsContextMutex)
1044 g_dtlsContextMutex = ca_mutex_new();
1045 VERIFY_NON_NULL_RET(g_dtlsContextMutex, NET_DTLS_TAG, "malloc failed",
1046 CA_MEMORY_ALLOC_FAILED);
1050 OIC_LOG(ERROR, NET_DTLS_TAG, "CAAdapterNetDtlsInit done already!");
1051 return CA_STATUS_OK;
1054 // Lock DtlsContext mutex and create DtlsContext
1055 ca_mutex_lock(g_dtlsContextMutex);
1056 g_caDtlsContext = (stCADtlsContext_t *)OICCalloc(1, sizeof(stCADtlsContext_t));
1058 if (NULL == g_caDtlsContext)
1060 OIC_LOG(ERROR, NET_DTLS_TAG, "Context malloc failed");
1061 ca_mutex_unlock(g_dtlsContextMutex);
1062 ca_mutex_free(g_dtlsContextMutex);
1063 return CA_MEMORY_ALLOC_FAILED;
1067 // Create PeerInfoList and CacheList
1068 g_caDtlsContext->peerInfoList = u_arraylist_create();
1069 g_caDtlsContext->cacheList = u_arraylist_create();
1071 if( (NULL == g_caDtlsContext->peerInfoList) ||
1072 (NULL == g_caDtlsContext->cacheList))
1074 OIC_LOG(ERROR, NET_DTLS_TAG, "peerInfoList or cacheList initialization failed!");
1076 CAFreePeerInfoList();
1077 OICFree(g_caDtlsContext);
1078 g_caDtlsContext = NULL;
1079 ca_mutex_unlock(g_dtlsContextMutex);
1080 ca_mutex_free(g_dtlsContextMutex);
1081 return CA_STATUS_FAILED;
1084 // Initialize clock, crypto and other global vars in tinyDTLS library
1087 // Create tinydtls Context
1088 g_caDtlsContext->dtlsContext = dtls_new_context(g_caDtlsContext);
1090 if (NULL == g_caDtlsContext->dtlsContext)
1092 OIC_LOG(ERROR, NET_DTLS_TAG, "dtls_new_context failed");
1093 ca_mutex_unlock(g_dtlsContextMutex);
1094 CAAdapterNetDtlsDeInit();
1095 return CA_STATUS_FAILED;
1098 g_caDtlsContext->callbacks.write = CASendSecureData;
1099 g_caDtlsContext->callbacks.read = CAReadDecryptedPayload;
1100 g_caDtlsContext->callbacks.event = CAHandleSecureEvent;
1102 g_caDtlsContext->callbacks.get_psk_info = CAGetPskCredentials;
1103 #ifdef __WITH_X509__
1104 g_caDtlsContext->callbacks.get_x509_key = CAGetDeviceKey;
1105 g_caDtlsContext->callbacks.verify_x509_cert = CAVerifyCertificate;
1106 g_caDtlsContext->callbacks.get_x509_cert = CAGetDeviceCertificate;
1107 g_caDtlsContext->callbacks.is_x509_active = CAIsX509Active;
1108 #endif //__WITH_X509__*
1109 dtls_set_handler(g_caDtlsContext->dtlsContext, &(g_caDtlsContext->callbacks));
1110 ca_mutex_unlock(g_dtlsContextMutex);
1112 CAStartRetransmit();
1114 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
1115 return CA_STATUS_OK;
1118 void CAAdapterNetDtlsDeInit()
1120 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
1122 VERIFY_NON_NULL_VOID(g_caDtlsContext, NET_DTLS_TAG, "context is NULL");
1123 VERIFY_NON_NULL_VOID(g_dtlsContextMutex, NET_DTLS_TAG, "context mutex is NULL");
1125 //Lock DtlsContext mutex
1126 ca_mutex_lock(g_dtlsContextMutex);
1129 CAFreePeerInfoList();
1132 // De-initialize tinydtls context
1133 dtls_free_context(g_caDtlsContext->dtlsContext);
1134 g_caDtlsContext->dtlsContext = NULL;
1136 // De-initialize DtlsContext
1137 OICFree(g_caDtlsContext);
1138 g_caDtlsContext = NULL;
1140 // Unlock DtlsContext mutex and de-initialize it
1141 ca_mutex_unlock(g_dtlsContextMutex);
1142 ca_mutex_free(g_dtlsContextMutex);
1143 g_dtlsContextMutex = NULL;
1145 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
1148 CAResult_t CAAdapterNetDtlsEncrypt(const CAEndpoint_t *endpoint,
1149 void *data, uint32_t dataLen)
1152 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
1154 VERIFY_NON_NULL_RET(endpoint, NET_DTLS_TAG,"Param remoteAddress is NULL",
1155 CA_STATUS_INVALID_PARAM);
1156 VERIFY_NON_NULL_RET(data, NET_DTLS_TAG, "Param data is NULL" ,
1157 CA_STATUS_INVALID_PARAM);
1161 OIC_LOG_V(ERROR, NET_DTLS_TAG, "dataLen is less than or equal zero [%d]", dataLen);
1162 return CA_STATUS_FAILED;
1165 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "Data to be encrypted dataLen [%d]", dataLen);
1167 stCADtlsAddrInfo_t addrInfo = { 0 };
1169 CAConvertNameToAddr(endpoint->addr, endpoint->port, &(addrInfo.addr.st));
1170 addrInfo.ifIndex = 0;
1171 addrInfo.size = CASizeOfAddrInfo(&addrInfo);
1173 ca_mutex_lock(g_dtlsContextMutex);
1174 if(NULL == g_caDtlsContext)
1176 OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
1177 ca_mutex_unlock(g_dtlsContextMutex);
1178 return CA_STATUS_FAILED;
1181 eDtlsRet_t ret = CAAdapterNetDtlsEncryptInternal(&addrInfo, data, dataLen);
1182 if (ret == DTLS_SESSION_INITIATED)
1184 stCACacheMessage_t *message = (stCACacheMessage_t *)OICCalloc(1, sizeof(stCACacheMessage_t));
1185 if (NULL == message)
1187 OIC_LOG(ERROR, NET_DTLS_TAG, "calloc failed!");
1188 ca_mutex_unlock(g_dtlsContextMutex);
1189 return CA_MEMORY_ALLOC_FAILED;
1192 message->data = (uint8_t *)OICCalloc(dataLen + 1, sizeof(uint8_t));
1193 if (NULL == message->data)
1195 OIC_LOG(ERROR, NET_DTLS_TAG, "calloc failed!");
1197 ca_mutex_unlock(g_dtlsContextMutex);
1198 return CA_MEMORY_ALLOC_FAILED;
1200 memcpy(message->data, data, dataLen);
1201 message->dataLen = dataLen;
1202 message->destSession = addrInfo;
1204 CAResult_t result = CADtlsCacheMsg(message);
1205 if (CA_STATUS_OK != result)
1207 OIC_LOG(DEBUG, NET_DTLS_TAG, "CADtlsCacheMsg failed!");
1208 CAFreeCacheMsg(message);
1210 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "OUT Initiating Dtls session [%d]", result);
1211 ca_mutex_unlock(g_dtlsContextMutex);
1215 ca_mutex_unlock(g_dtlsContextMutex);
1219 OIC_LOG(ERROR, NET_DTLS_TAG, "OUT FAILURE");
1220 return CA_STATUS_FAILED;
1223 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
1224 return CA_STATUS_OK;
1227 CAResult_t CAAdapterNetDtlsDecrypt(const CASecureEndpoint_t *sep,
1228 uint8_t *data, uint32_t dataLen)
1230 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
1231 VERIFY_NON_NULL_RET(sep, NET_DTLS_TAG, "endpoint is NULL" , CA_STATUS_INVALID_PARAM);
1233 stCADtlsAddrInfo_t addrInfo = { 0 };
1235 CAConvertNameToAddr(sep->endpoint.addr, sep->endpoint.port, &(addrInfo.addr.st));
1236 addrInfo.ifIndex = 0;
1237 addrInfo.size = CASizeOfAddrInfo(&addrInfo);
1239 ca_mutex_lock(g_dtlsContextMutex);
1240 if (NULL == g_caDtlsContext)
1242 OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
1243 ca_mutex_unlock(g_dtlsContextMutex);
1244 return CA_STATUS_FAILED;
1247 eDtlsRet_t ret = CAAdapterNetDtlsDecryptInternal(&addrInfo, data, dataLen);
1248 ca_mutex_unlock(g_dtlsContextMutex);
1250 if (DTLS_OK == ret || DTLS_HS_MSG == ret)
1252 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "Successfully Decrypted or Handshake msg recvd [%d]", ret);
1253 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
1254 return CA_STATUS_OK;
1257 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT FAILURE");
1258 return CA_STATUS_FAILED;