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"
33 #include "cainterface.h"
35 /* lenght of ASN.1 header in DER format
36 * for subject field in X.509 certificate */
37 #define DER_SUBJECT_HEADER_LEN (9)
40 #define VERIFY_SUCCESS(op, successCode) { if ((op) != (successCode)) \
41 {OIC_LOG_V(FATAL, NET_DTLS_TAG, "%s failed!!", #op); goto exit;} }
46 * @brief Logging tag for module name
48 #define NET_DTLS_TAG "OIC_CA_NET_DTLS"
51 * @var g_caDtlsContext
52 * @brief global context which holds dtls context and cache list information.
54 static stCADtlsContext_t *g_caDtlsContext = NULL;
57 * @var g_dtlsContextMutex
58 * @brief Mutex to synchronize access to g_caDtlsContext.
60 static ca_mutex g_dtlsContextMutex = NULL;
63 * @var g_getCredentialsCallback
64 * @brief callback to get DTLS credentials
66 static CAGetDTLSPskCredentialsHandler g_getCredentialsCallback = NULL;
69 * @var MAX_RETRANSMISSION_TIME
70 * @brief Maximum timeout value (in seconds) to start DTLS retransmission.
72 #define MAX_RETRANSMISSION_TIME 1
75 * @var g_dtlsHandshakeCallback
76 * @brief callback to deliver the DTLS handshake result
78 static CAErrorCallback g_dtlsHandshakeCallback = NULL;
82 * @var g_getX509CredentialsCallback
83 * @brief callback to get DTLS certificate credentials
85 static CAGetDTLSX509CredentialsHandler g_getX509CredentialsCallback = NULL;
87 * @var g_getCrlCallback
88 * @brief callback to get CRL for DTLS
90 static CAGetDTLSCrlHandler g_getCrlCallback = NULL;
91 #endif //__WITH_X509__
94 static CASecureEndpoint_t *GetPeerInfo(const CAEndpoint_t *peer)
96 uint32_t list_index = 0;
97 uint32_t list_length = 0;
101 OIC_LOG(ERROR, NET_DTLS_TAG, "CAPeerInfoListContains invalid parameters");
105 CASecureEndpoint_t *peerInfo = NULL;
106 list_length = u_arraylist_length(g_caDtlsContext->peerInfoList);
107 for (list_index = 0; list_index < list_length; list_index++)
109 peerInfo = (CASecureEndpoint_t *)u_arraylist_get(g_caDtlsContext->peerInfoList, list_index);
110 if (NULL == peerInfo)
115 if((0 == strncmp(peer->addr, peerInfo->endpoint.addr, MAX_ADDR_STR_SIZE_CA)) &&
116 (peer->port == peerInfo->endpoint.port))
124 static CAResult_t CAAddIdToPeerInfoList(const char *peerAddr, uint32_t port,
125 const unsigned char *id, uint16_t id_length)
131 || CA_MAX_ENDPOINT_IDENTITY_LEN < id_length)
133 OIC_LOG(ERROR, NET_DTLS_TAG, "CAAddIdToPeerInfoList invalid parameters");
134 return CA_STATUS_INVALID_PARAM;
137 CASecureEndpoint_t *peer = (CASecureEndpoint_t *)OICCalloc(1, sizeof (CASecureEndpoint_t));
140 OIC_LOG(ERROR, NET_DTLS_TAG, "peerInfo malloc failed!");
141 return CA_MEMORY_ALLOC_FAILED;
144 OICStrcpy(peer->endpoint.addr, sizeof(peer->endpoint.addr), peerAddr);
145 peer->endpoint.port = port;
147 memcpy(peer->identity.id, id, id_length);
148 peer->identity.id_length = id_length;
150 if (NULL != GetPeerInfo(&peer->endpoint))
152 OIC_LOG(ERROR, NET_DTLS_TAG, "CAAddIdToPeerInfoList peer already exist");
154 return CA_STATUS_FAILED;
157 bool result = u_arraylist_add(g_caDtlsContext->peerInfoList, (void *)peer);
160 OIC_LOG(ERROR, NET_DTLS_TAG, "u_arraylist_add failed!");
162 return CA_STATUS_FAILED;
168 static void CAFreePeerInfoList()
170 uint32_t list_length = u_arraylist_length(g_caDtlsContext->peerInfoList);
171 for (uint32_t list_index = 0; list_index < list_length; list_index++)
173 CAEndpoint_t *peerInfo = (CAEndpoint_t *)u_arraylist_get(
174 g_caDtlsContext->peerInfoList, list_index);
177 u_arraylist_free(&(g_caDtlsContext->peerInfoList));
178 g_caDtlsContext->peerInfoList = NULL;
181 static void CARemovePeerFromPeerInfoList(const char * addr, uint16_t port)
183 if (NULL == addr || 0 >= port)
185 OIC_LOG(ERROR, NET_DTLS_TAG, "CADTLSGetPeerPSKId invalid parameters");
189 uint32_t list_length = u_arraylist_length(g_caDtlsContext->peerInfoList);
190 for (uint32_t list_index = 0; list_index < list_length; list_index++)
192 CAEndpoint_t *peerInfo = (CAEndpoint_t *)u_arraylist_get(
193 g_caDtlsContext->peerInfoList,list_index);
194 if (NULL == peerInfo)
198 if((0 == strncmp(addr, peerInfo->addr, MAX_ADDR_STR_SIZE_CA)) &&
199 (port == peerInfo->port))
201 OICFree(u_arraylist_remove(g_caDtlsContext->peerInfoList, list_index));
207 static int CASizeOfAddrInfo(stCADtlsAddrInfo_t *addrInfo)
209 VERIFY_NON_NULL_RET(addrInfo, NET_DTLS_TAG, "addrInfo is NULL" , DTLS_FAIL);
211 switch (addrInfo->addr.st.ss_family)
215 return sizeof (struct sockaddr_in);
219 return sizeof (struct sockaddr_in6);
226 return sizeof (struct sockaddr_storage);
229 static eDtlsRet_t CAAdapterNetDtlsEncryptInternal(const stCADtlsAddrInfo_t *dstSession,
230 uint8_t *data, uint32_t dataLen)
232 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
234 VERIFY_NON_NULL_RET(dstSession, NET_DTLS_TAG, "Param dstSession is NULL" , DTLS_FAIL);
235 VERIFY_NON_NULL_RET(data, NET_DTLS_TAG, "Param data is NULL" , DTLS_FAIL);
239 OIC_LOG(ERROR, NET_DTLS_TAG, "Given Packet length is equal to zero.");
243 if (NULL == g_caDtlsContext)
245 OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
249 int retLen = dtls_write(g_caDtlsContext->dtlsContext, (session_t *)dstSession, data,
251 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "dtls_write retun len [%d]", retLen);
254 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT FAILURE");
259 // A new DTLS session was initiated by tinyDTLS library and wait for callback.
260 return DTLS_SESSION_INITIATED;
262 else if (dataLen != (uint32_t)retLen)
264 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT FAILURE");
267 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
271 static eDtlsRet_t CAAdapterNetDtlsDecryptInternal(const stCADtlsAddrInfo_t *srcSession,
272 uint8_t *buf, uint32_t bufLen)
274 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
276 VERIFY_NON_NULL_RET(srcSession, NET_DTLS_TAG, "Param srcSession is NULL", DTLS_FAIL);
277 VERIFY_NON_NULL_RET(buf, NET_DTLS_TAG, "Param buf is NULL", DTLS_FAIL);
281 OIC_LOG(ERROR, NET_DTLS_TAG, "Given Packet length is equal to zero.");
285 eDtlsRet_t ret = DTLS_FAIL;
287 if (dtls_handle_message(g_caDtlsContext->dtlsContext, (session_t *)srcSession, buf, bufLen) == 0)
289 OIC_LOG(DEBUG, NET_DTLS_TAG, "dtls_handle_message success");
293 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
297 static void CAFreeCacheMsg(stCACacheMessage_t *msg)
299 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
300 VERIFY_NON_NULL_VOID(msg, NET_DTLS_TAG, "msg");
305 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
308 static void CAClearCacheList()
310 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
311 uint32_t list_index = 0;
312 uint32_t list_length = 0;
313 if (NULL == g_caDtlsContext)
315 OIC_LOG(ERROR, NET_DTLS_TAG, "Dtls Context is NULL");
318 list_length = u_arraylist_length(g_caDtlsContext->cacheList);
319 for (list_index = 0; list_index < list_length; list_index++)
321 stCACacheMessage_t *msg = (stCACacheMessage_t *)u_arraylist_get(g_caDtlsContext->cacheList,
328 u_arraylist_free(&g_caDtlsContext->cacheList);
329 g_caDtlsContext->cacheList = NULL;
330 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
333 static CAResult_t CADtlsCacheMsg(stCACacheMessage_t *msg)
335 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
337 if (NULL == g_caDtlsContext)
339 OIC_LOG(ERROR, NET_DTLS_TAG, "Dtls Context is NULL");
340 return CA_STATUS_FAILED;
343 bool result = u_arraylist_add(g_caDtlsContext->cacheList, (void *)msg);
346 OIC_LOG(ERROR, NET_DTLS_TAG, "u_arraylist_add failed!");
347 return CA_STATUS_FAILED;
350 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
355 static bool CAIsAddressMatching(const stCADtlsAddrInfo_t *a, const stCADtlsAddrInfo_t *b)
357 if (a->size != b->size)
361 if (memcmp(&a->addr, &b->addr, a->size))
368 static void CASendCachedMsg(const stCADtlsAddrInfo_t *dstSession)
370 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
371 VERIFY_NON_NULL_VOID(dstSession, NET_DTLS_TAG, "Param dstSession is NULL");
373 uint32_t list_index = 0;
374 uint32_t list_length = 0;
375 list_length = u_arraylist_length(g_caDtlsContext->cacheList);
376 for (list_index = 0; list_index < list_length;)
378 stCACacheMessage_t *msg = (stCACacheMessage_t *)u_arraylist_get(g_caDtlsContext->cacheList,
380 if ((NULL != msg) && (true == CAIsAddressMatching(&(msg->destSession), dstSession)))
382 eDtlsRet_t ret = CAAdapterNetDtlsEncryptInternal(&(msg->destSession),
383 msg->data, msg->dataLen);
386 OIC_LOG(DEBUG, NET_DTLS_TAG, "CAAdapterNetDtlsEncryptInternal success");
390 OIC_LOG(ERROR, NET_DTLS_TAG, "CAAdapterNetDtlsEncryptInternal failed.");
393 if (u_arraylist_remove(g_caDtlsContext->cacheList, list_index))
396 // Reduce list length by 1 as we removed one element.
401 OIC_LOG(ERROR, NET_DTLS_TAG, "u_arraylist_remove failed.");
407 // Move to the next element
412 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
415 static int32_t CAReadDecryptedPayload(dtls_context_t *context,
421 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
423 VERIFY_NON_NULL_RET(session, NET_DTLS_TAG, "Param Session is NULL", 0);
424 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "Decrypted buf len [%zu]", bufLen);
426 stCADtlsAddrInfo_t *addrInfo = (stCADtlsAddrInfo_t *)session;
428 CASecureEndpoint_t sep =
430 { .adapter = CA_ADAPTER_IP, .flags =
431 ((addrInfo->addr.st.ss_family == AF_INET) ? CA_IPV4 : CA_IPV6) | CA_SECURE, .port = 0 },
434 CAConvertAddrToName(&(addrInfo->addr.st), addrInfo->size, sep.endpoint.addr, &sep.endpoint.port);
436 if (NULL == g_caDtlsContext)
438 OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
443 if ((0 <= type) && (MAX_SUPPORTED_ADAPTERS > type) &&
444 (NULL != g_caDtlsContext->adapterCallbacks[type].recvCallback))
446 // Get identity of the source of packet
447 CASecureEndpoint_t *peerInfo = GetPeerInfo(&sep.endpoint);
450 sep.identity = peerInfo->identity;
453 g_caDtlsContext->adapterCallbacks[type].recvCallback(&sep, buf, bufLen);
457 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "recvCallback Callback or adapter type is wrong [%d]", type);
460 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
464 static int32_t CASendSecureData(dtls_context_t *context,
470 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
472 VERIFY_NON_NULL_RET(session, NET_DTLS_TAG, "Param Session is NULL", -1);
473 VERIFY_NON_NULL_RET(buf, NET_DTLS_TAG, "Param buf is NULL", -1);
477 OIC_LOG(ERROR, NET_DTLS_TAG, "Encrypted Buffer length is equal to zero");
481 stCADtlsAddrInfo_t *addrInfo = (stCADtlsAddrInfo_t *)session;
483 CAEndpoint_t endpoint = {.adapter = CA_DEFAULT_ADAPTER};
485 CAConvertAddrToName(&(addrInfo->addr.st), addrInfo->size, endpoint.addr, &endpoint.port);
486 endpoint.flags = addrInfo->addr.st.ss_family == AF_INET ? CA_IPV4 : CA_IPV6;
487 endpoint.flags |= CA_SECURE;
488 endpoint.adapter = CA_ADAPTER_IP;
489 endpoint.interface = session->ifindex;
492 //Mutex is not required for g_caDtlsContext. It will be called in same thread.
493 if ((0 <= type) && (MAX_SUPPORTED_ADAPTERS > type) &&
494 (NULL != g_caDtlsContext->adapterCallbacks[type].sendCallback))
496 g_caDtlsContext->adapterCallbacks[type].sendCallback(&endpoint, buf, bufLen);
500 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "send Callback or adapter type is wrong [%d]", type );
503 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
507 static int32_t CAHandleSecureEvent(dtls_context_t *context,
509 dtls_alert_level_t level,
513 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
515 VERIFY_NON_NULL_RET(session, NET_DTLS_TAG, "Param Session is NULL", 0);
517 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "level [%d] code [%u]\n", level, code);
519 CAEndpoint_t endpoint = {.adapter=CA_DEFAULT_ADAPTER};
520 CAErrorInfo_t errorInfo = {.result=CA_STATUS_OK};
522 stCADtlsAddrInfo_t *addrInfo = (stCADtlsAddrInfo_t *)session;
523 char peerAddr[MAX_ADDR_STR_SIZE_CA] = { 0 };
525 CAConvertAddrToName(&(addrInfo->addr.st), addrInfo->size, peerAddr, &port);
527 if (!level && (DTLS_EVENT_CONNECTED == code))
529 OIC_LOG(DEBUG, NET_DTLS_TAG, "Received DTLS_EVENT_CONNECTED. Sending Cached data");
531 if(g_dtlsHandshakeCallback)
533 OICStrcpy(endpoint.addr, MAX_ADDR_STR_SIZE_CA, peerAddr);
534 endpoint.port = port;
535 errorInfo.result = CA_STATUS_OK;
536 g_dtlsHandshakeCallback(&endpoint, &errorInfo);
539 CASendCachedMsg((stCADtlsAddrInfo_t *)session);
541 else if(DTLS_ALERT_LEVEL_FATAL == level && DTLS_ALERT_DECRYPT_ERROR == code)
543 if(g_dtlsHandshakeCallback)
545 OICStrcpy(endpoint.addr, MAX_ADDR_STR_SIZE_CA, peerAddr);
546 endpoint.addr[MAX_ADDR_STR_SIZE_CA - 1] = '\0';
547 endpoint.port = port;
548 errorInfo.result = CA_DTLS_AUTHENTICATION_FAILURE;
549 g_dtlsHandshakeCallback(&endpoint, &errorInfo);
552 else if(DTLS_ALERT_LEVEL_FATAL == level && DTLS_ALERT_CLOSE_NOTIFY == code)
554 OIC_LOG(INFO, NET_DTLS_TAG, "Peer closing connection");
555 CARemovePeerFromPeerInfoList(peerAddr, port);
558 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
563 static int32_t CAGetPskCredentials(dtls_context_t *ctx,
564 const session_t *session,
565 dtls_credentials_type_t type,
566 const unsigned char *desc, size_t descLen,
567 unsigned char *result, size_t resultLen)
569 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
572 if(NULL == ctx || NULL == session || NULL == result)
574 OIC_LOG(ERROR, NET_DTLS_TAG, "CAGetPskCredentials invalid parameters");
578 VERIFY_NON_NULL_RET(g_getCredentialsCallback, NET_DTLS_TAG, "GetCredential callback", -1);
580 // Retrieve the credentials blob from security module
581 ret = g_getCredentialsCallback(type, desc, descLen, result, resultLen);
585 // TODO SRM needs identity of the remote end-point with every data packet to
586 // perform access control management. tinyDTLS 'frees' the handshake parameters
587 // data structure when handshake completes. Therefore, currently this is a
588 // workaround to cache remote end-point identity when tinyDTLS asks for PSK.
589 stCADtlsAddrInfo_t *addrInfo = (stCADtlsAddrInfo_t *)session;
590 char peerAddr[MAX_ADDR_STR_SIZE_CA] = { 0 };
592 CAConvertAddrToName(&(addrInfo->addr.st), addrInfo->size, peerAddr, &port);
594 if(CA_STATUS_OK != CAAddIdToPeerInfoList(peerAddr, port, desc, descLen) )
596 OIC_LOG(ERROR, NET_DTLS_TAG, "Fail to add peer id to gDtlsPeerInfoList");
603 void CADTLSSetAdapterCallbacks(CAPacketReceivedCallback recvCallback,
604 CAPacketSendCallback sendCallback,
605 CATransportAdapter_t type)
607 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
608 ca_mutex_lock(g_dtlsContextMutex);
609 if (NULL == g_caDtlsContext)
611 OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
612 ca_mutex_unlock(g_dtlsContextMutex);
616 if ((0 <= type) && (MAX_SUPPORTED_ADAPTERS > type))
618 // TODO: change the zeros to better values.
619 g_caDtlsContext->adapterCallbacks[0].recvCallback = recvCallback;
620 g_caDtlsContext->adapterCallbacks[0].sendCallback = sendCallback;
623 ca_mutex_unlock(g_dtlsContextMutex);
625 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
628 void CADTLSSetHandshakeCallback(CAErrorCallback dtlsHandshakeCallback)
630 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
631 g_dtlsHandshakeCallback = dtlsHandshakeCallback;
632 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
635 void CADTLSSetCredentialsCallback(CAGetDTLSPskCredentialsHandler credCallback)
637 // TODO Does this method needs protection of DtlsContextMutex ?
638 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
639 g_getCredentialsCallback = credCallback;
640 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
644 void CADTLSSetX509CredentialsCallback(CAGetDTLSX509CredentialsHandler credCallback)
646 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
647 g_getX509CredentialsCallback = credCallback;
648 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
650 void CADTLSSetCrlCallback(CAGetDTLSCrlHandler crlCallback)
652 // TODO Does this method needs protection of DtlsContextMutex ?
653 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
654 g_getCrlCallback = crlCallback;
655 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
657 #endif // __WITH_X509__
659 CAResult_t CADtlsSelectCipherSuite(const dtls_cipher_t cipher)
661 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN CADtlsSelectCipherSuite");
663 ca_mutex_lock(g_dtlsContextMutex);
664 if (NULL == g_caDtlsContext)
666 OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
667 ca_mutex_unlock(g_dtlsContextMutex);
668 return CA_STATUS_FAILED;
670 dtls_select_cipher(g_caDtlsContext->dtlsContext, cipher);
671 ca_mutex_unlock(g_dtlsContextMutex);
673 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "Selected cipher suite is 0x%02X%02X\n",
674 ((uint8_t*)(&cipher))[1], ((uint8_t*)(&cipher))[0]);
675 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT CADtlsSelectCipherSuite");
677 return CA_STATUS_OK ;
680 CAResult_t CADtlsEnableAnonECDHCipherSuite(const bool enable)
682 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN CADtlsEnablesAnonEcdh");
684 ca_mutex_lock(g_dtlsContextMutex);
685 if (NULL == g_caDtlsContext)
687 OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
688 ca_mutex_unlock(g_dtlsContextMutex);
689 return CA_STATUS_FAILED;
691 dtls_enables_anon_ecdh(g_caDtlsContext->dtlsContext,
692 enable == true ? DTLS_CIPHER_ENABLE : DTLS_CIPHER_DISABLE);
693 ca_mutex_unlock(g_dtlsContextMutex);
694 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256 is %s",
695 enable ? "enabled" : "disabled");
697 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT CADtlsEnablesAnonEcdh");
699 return CA_STATUS_OK ;
702 CAResult_t CADtlsInitiateHandshake(const CAEndpoint_t *endpoint)
704 stCADtlsAddrInfo_t dst = { 0 };
706 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN CADtlsInitiateHandshake");
710 return CA_STATUS_INVALID_PARAM;
713 CAConvertNameToAddr(endpoint->addr, endpoint->port, &(dst.addr.st));
715 dst.size = CASizeOfAddrInfo(&dst);
717 ca_mutex_lock(g_dtlsContextMutex);
718 if(NULL == g_caDtlsContext)
720 OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
721 ca_mutex_unlock(g_dtlsContextMutex);
722 return CA_STATUS_FAILED;
725 if(0 > dtls_connect(g_caDtlsContext->dtlsContext, (session_t*)(&dst)))
727 OIC_LOG(ERROR, NET_DTLS_TAG, "Failed to connect");
728 ca_mutex_unlock(g_dtlsContextMutex);
729 return CA_STATUS_FAILED;
732 ca_mutex_unlock(g_dtlsContextMutex);
734 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT CADtlsInitiateHandshake");
739 CAResult_t CADtlsClose(const CAEndpoint_t *endpoint)
741 stCADtlsAddrInfo_t dst = { 0 };
743 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN CADtlsDisconnect");
747 return CA_STATUS_INVALID_PARAM;
750 CAConvertNameToAddr(endpoint->addr, endpoint->port, &(dst.addr.st));
752 dst.size = CASizeOfAddrInfo(&dst);
754 ca_mutex_lock(g_dtlsContextMutex);
755 if (NULL == g_caDtlsContext)
757 OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
758 ca_mutex_unlock(g_dtlsContextMutex);
759 return CA_STATUS_FAILED;
762 if (0 > dtls_close(g_caDtlsContext->dtlsContext, (session_t*)(&dst)))
764 OIC_LOG(ERROR, NET_DTLS_TAG, "Failed to close the session");
765 ca_mutex_unlock(g_dtlsContextMutex);
766 return CA_STATUS_FAILED;
769 ca_mutex_unlock(g_dtlsContextMutex);
771 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT CADtlsDisconnect");
776 CAResult_t CADtlsGenerateOwnerPSK(const CAEndpoint_t *endpoint,
777 const uint8_t* label, const size_t labelLen,
778 const uint8_t* rsrcServerDeviceID, const size_t rsrcServerDeviceIDLen,
779 const uint8_t* provServerDeviceID, const size_t provServerDeviceIDLen,
780 uint8_t* ownerPSK, const size_t ownerPSKSize)
782 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN CADtlsGenerateOwnerPSK");
784 if(!endpoint || !label || 0 == labelLen || !ownerPSK || 0 == ownerPSKSize)
786 return CA_STATUS_INVALID_PARAM;
789 stCADtlsAddrInfo_t dst = { 0 };
791 CAConvertNameToAddr(endpoint->addr, endpoint->port, &(dst.addr.st));
793 dst.size = CASizeOfAddrInfo(&dst);
795 ca_mutex_lock(g_dtlsContextMutex);
796 if (NULL == g_caDtlsContext)
798 OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
799 ca_mutex_unlock(g_dtlsContextMutex);
800 return CA_STATUS_FAILED;
803 if( 0 == dtls_prf_with_current_keyblock(g_caDtlsContext->dtlsContext, (session_t*)(&dst),
804 label, labelLen, rsrcServerDeviceID, rsrcServerDeviceIDLen,
805 provServerDeviceID, provServerDeviceIDLen, ownerPSK, ownerPSKSize))
807 OIC_LOG(ERROR, NET_DTLS_TAG, "Failed to DTLS PRF");
808 ca_mutex_unlock(g_dtlsContextMutex);
809 return CA_STATUS_FAILED;
811 ca_mutex_unlock(g_dtlsContextMutex);
813 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT CADtlsGenerateOwnerPSK");
819 static CADtlsX509Creds_t g_X509Cred = {{0}, 0, 0, {0}, {0}, {0}};
823 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN CAInitX509");
824 VERIFY_NON_NULL_RET(g_getX509CredentialsCallback, NET_DTLS_TAG, "GetX509Credential callback", -1);
825 int isX509Init = (0 == g_getX509CredentialsCallback(&g_X509Cred));
829 uint8_t crlData[CRL_MAX_LEN] = {0};
830 ByteArray crlArray = {crlData, CRL_MAX_LEN};
831 g_getCrlCallback(crlArray);
832 if (crlArray.len > 0)
834 uint8_t keyData[PUBLIC_KEY_SIZE] = {0};
835 CertificateList crl = CRL_INITIALIZER;
836 ByteArray rootPubKey = {keyData, PUBLIC_KEY_SIZE};
837 memcpy(keyData, g_X509Cred.rootPublicKeyX, PUBLIC_KEY_SIZE / 2);
838 memcpy(keyData + PUBLIC_KEY_SIZE / 2, g_X509Cred.rootPublicKeyY, PUBLIC_KEY_SIZE / 2);
839 DecodeCertificateList(crlArray, &crl, rootPubKey);
843 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT CAInitX509");
855 static int CAIsX509Active(struct dtls_context_t *ctx)
861 static int CAGetDeviceKey(struct dtls_context_t *ctx,
862 const session_t *session,
863 const dtls_ecc_key_t **result)
865 OIC_LOG(DEBUG, NET_DTLS_TAG, "CAGetDeviceKey");
866 static dtls_ecc_key_t ecdsa_key = {DTLS_ECDH_CURVE_SECP256R1, NULL, NULL, NULL};
869 VERIFY_SUCCESS(CAInitX509(), 0);
871 ecdsa_key.priv_key = g_X509Cred.devicePrivateKey;
872 *result = &ecdsa_key;
880 CAGetDeviceCertificate(struct dtls_context_t *ctx,
881 const session_t *session,
882 const unsigned char **cert,
885 OIC_LOG(DEBUG, NET_DTLS_TAG, "CAGetDeviceCertificate");
888 VERIFY_SUCCESS(CAInitX509(), 0);
890 *cert = g_X509Cred.certificateChain;
891 *cert_size = g_X509Cred.certificateChainLen;
893 ByteArray ownCert = {g_X509Cred.certificateChain, g_X509Cred.certificateChainLen};
894 PRINT_BYTE_ARRAY("OWN CERT: \n", ownCert);
903 * @brief Gets x and y components of Root Certificate Autority public key
905 * @return 0 on success otherwise a positive error value.
908 static int CAGetRootKey(const unsigned char **ca_pub_x, const unsigned char **ca_pub_y)
910 OIC_LOG(DEBUG, NET_DTLS_TAG, "CAGetRootKey");
913 VERIFY_SUCCESS(CAInitX509(), 0);
915 *ca_pub_x = g_X509Cred.rootPublicKeyX;
916 *ca_pub_y = g_X509Cred.rootPublicKeyY;
924 static int CAVerifyCertificate(struct dtls_context_t *ctx, const session_t *session,
925 const unsigned char *cert, size_t certLen,
926 const unsigned char *x, size_t xLen,
927 const unsigned char *y, size_t yLen)
929 OIC_LOG(DEBUG, NET_DTLS_TAG, "Verify Certificate");
931 ByteArray crtChainDer[MAX_CHAIN_LEN];
932 CertificateX509 crtChain[MAX_CHAIN_LEN];
937 const unsigned char *ca_pub_x;
938 const unsigned char *ca_pub_y;
939 ByteArray certDerCode = BYTE_ARRAY_INITIALIZER;
940 ByteArray caPubKey = BYTE_ARRAY_INITIALIZER;
941 unsigned char ca_pub_key[PUBLIC_KEY_SIZE];
943 if ( !ctx || !session || !cert || !x || !y)
945 return -PKI_NULL_PASSED;
948 CAGetRootKey (&ca_pub_x, &ca_pub_y);
950 certDerCode.data = (uint8_t *)cert;
951 certDerCode.len = certLen;
954 PRINT_BYTE_ARRAY("CERT :\n", certDerCode);
958 caPubKey.len = PUBLIC_KEY_SIZE;
959 caPubKey.data = ca_pub_key;
961 memcpy(caPubKey.data, ca_pub_x, PUBLIC_KEY_SIZE / 2);
962 memcpy(caPubKey.data + PUBLIC_KEY_SIZE / 2, ca_pub_y, PUBLIC_KEY_SIZE / 2);
964 ret = (int) LoadCertificateChain (certDerCode, crtChainDer, &chainLength);
965 VERIFY_SUCCESS(ret, PKI_SUCCESS);
966 ret = (int) ParseCertificateChain (crtChainDer, crtChain, chainLength );
967 VERIFY_SUCCESS(ret, PKI_SUCCESS);
968 ret = (int) CheckCertificateChain (crtChain, chainLength, caPubKey);
969 VERIFY_SUCCESS(ret, PKI_SUCCESS);
971 INC_BYTE_ARRAY(crtChain[0].pubKey, 2);
973 memcpy(x, crtChain[0].pubKey.data, xLen);
974 memcpy(y, crtChain[0].pubKey.data + PUBLIC_KEY_SIZE / 2, yLen);
976 stCADtlsAddrInfo_t *addrInfo = (stCADtlsAddrInfo_t *)session;
977 char peerAddr[MAX_ADDR_STR_SIZE_CA] = { 0 };
979 CAConvertAddrToName(&(addrInfo->addr.st), addrInfo->size, peerAddr, &port);
981 CAResult_t result = CAAddIdToPeerInfoList(peerAddr, port,
982 crtChain[0].subject.data + DER_SUBJECT_HEADER_LEN + 2, crtChain[0].subject.data[DER_SUBJECT_HEADER_LEN + 1]);
983 if (CA_STATUS_OK != result )
985 OIC_LOG(ERROR, NET_DTLS_TAG, "Fail to add peer id to gDtlsPeerInfoList");
991 OIC_LOG(DEBUG, NET_DTLS_TAG, "Certificate verification FAILED\n");
995 OIC_LOG(DEBUG, NET_DTLS_TAG, "Certificate verification SUCCESS\n");
1002 static void CAStartRetransmit()
1004 static int timerId = -1;
1005 clock_time_t nextSchedule = MAX_RETRANSMISSION_TIME;
1007 OIC_LOG(DEBUG, NET_DTLS_TAG, "CAStartRetransmit IN");
1011 //clear previous timer
1012 unregisterTimer(timerId);
1014 ca_mutex_lock(g_dtlsContextMutex);
1016 //stop retransmission if context is invalid
1017 if(NULL == g_caDtlsContext)
1019 OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL. Stop retransmission");
1020 ca_mutex_unlock(g_dtlsContextMutex);
1024 OIC_LOG(DEBUG, NET_DTLS_TAG, "Check retransmission");
1025 dtls_check_retransmit(g_caDtlsContext->dtlsContext, &nextSchedule);
1026 ca_mutex_unlock(g_dtlsContextMutex);
1028 //re-transmission timeout should not be greater then max one
1029 //this will cover case when several clients start dtls sessions
1030 nextSchedule /= CLOCKS_PER_SEC;
1031 if (nextSchedule > MAX_RETRANSMISSION_TIME)
1033 nextSchedule = MAX_RETRANSMISSION_TIME;
1038 OIC_LOG(DEBUG, NET_DTLS_TAG, "Start new timer");
1039 registerTimer(nextSchedule, &timerId, CAStartRetransmit);
1041 OIC_LOG(DEBUG, NET_DTLS_TAG, "CAStartRetransmit OUT");
1044 CAResult_t CAAdapterNetDtlsInit()
1046 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
1048 // Initialize mutex for DtlsContext
1049 if (NULL == g_dtlsContextMutex)
1051 g_dtlsContextMutex = ca_mutex_new();
1052 VERIFY_NON_NULL_RET(g_dtlsContextMutex, NET_DTLS_TAG, "malloc failed",
1053 CA_MEMORY_ALLOC_FAILED);
1057 OIC_LOG(ERROR, NET_DTLS_TAG, "CAAdapterNetDtlsInit done already!");
1058 return CA_STATUS_OK;
1061 // Lock DtlsContext mutex and create DtlsContext
1062 ca_mutex_lock(g_dtlsContextMutex);
1063 g_caDtlsContext = (stCADtlsContext_t *)OICCalloc(1, sizeof(stCADtlsContext_t));
1065 if (NULL == g_caDtlsContext)
1067 OIC_LOG(ERROR, NET_DTLS_TAG, "Context malloc failed");
1068 ca_mutex_unlock(g_dtlsContextMutex);
1069 ca_mutex_free(g_dtlsContextMutex);
1070 return CA_MEMORY_ALLOC_FAILED;
1074 // Create PeerInfoList and CacheList
1075 g_caDtlsContext->peerInfoList = u_arraylist_create();
1076 g_caDtlsContext->cacheList = u_arraylist_create();
1078 if( (NULL == g_caDtlsContext->peerInfoList) ||
1079 (NULL == g_caDtlsContext->cacheList))
1081 OIC_LOG(ERROR, NET_DTLS_TAG, "peerInfoList or cacheList initialization failed!");
1083 CAFreePeerInfoList();
1084 OICFree(g_caDtlsContext);
1085 g_caDtlsContext = NULL;
1086 ca_mutex_unlock(g_dtlsContextMutex);
1087 ca_mutex_free(g_dtlsContextMutex);
1088 return CA_STATUS_FAILED;
1091 // Initialize clock, crypto and other global vars in tinyDTLS library
1094 // Create tinydtls Context
1095 g_caDtlsContext->dtlsContext = dtls_new_context(g_caDtlsContext);
1097 if (NULL == g_caDtlsContext->dtlsContext)
1099 OIC_LOG(ERROR, NET_DTLS_TAG, "dtls_new_context failed");
1100 ca_mutex_unlock(g_dtlsContextMutex);
1101 CAAdapterNetDtlsDeInit();
1102 return CA_STATUS_FAILED;
1105 g_caDtlsContext->callbacks.write = CASendSecureData;
1106 g_caDtlsContext->callbacks.read = CAReadDecryptedPayload;
1107 g_caDtlsContext->callbacks.event = CAHandleSecureEvent;
1109 g_caDtlsContext->callbacks.get_psk_info = CAGetPskCredentials;
1110 #ifdef __WITH_X509__
1111 g_caDtlsContext->callbacks.get_x509_key = CAGetDeviceKey;
1112 g_caDtlsContext->callbacks.verify_x509_cert = CAVerifyCertificate;
1113 g_caDtlsContext->callbacks.get_x509_cert = CAGetDeviceCertificate;
1114 g_caDtlsContext->callbacks.is_x509_active = CAIsX509Active;
1115 #endif //__WITH_X509__*
1116 dtls_set_handler(g_caDtlsContext->dtlsContext, &(g_caDtlsContext->callbacks));
1117 ca_mutex_unlock(g_dtlsContextMutex);
1119 CAStartRetransmit();
1121 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
1122 return CA_STATUS_OK;
1125 void CAAdapterNetDtlsDeInit()
1127 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
1129 VERIFY_NON_NULL_VOID(g_caDtlsContext, NET_DTLS_TAG, "context is NULL");
1130 VERIFY_NON_NULL_VOID(g_dtlsContextMutex, NET_DTLS_TAG, "context mutex is NULL");
1132 //Lock DtlsContext mutex
1133 ca_mutex_lock(g_dtlsContextMutex);
1136 CAFreePeerInfoList();
1139 // De-initialize tinydtls context
1140 dtls_free_context(g_caDtlsContext->dtlsContext);
1141 g_caDtlsContext->dtlsContext = NULL;
1143 // De-initialize DtlsContext
1144 OICFree(g_caDtlsContext);
1145 g_caDtlsContext = NULL;
1147 // Unlock DtlsContext mutex and de-initialize it
1148 ca_mutex_unlock(g_dtlsContextMutex);
1149 ca_mutex_free(g_dtlsContextMutex);
1150 g_dtlsContextMutex = NULL;
1152 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
1155 CAResult_t CAAdapterNetDtlsEncrypt(const CAEndpoint_t *endpoint,
1156 void *data, uint32_t dataLen)
1159 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
1161 VERIFY_NON_NULL_RET(endpoint, NET_DTLS_TAG,"Param remoteAddress is NULL",
1162 CA_STATUS_INVALID_PARAM);
1163 VERIFY_NON_NULL_RET(data, NET_DTLS_TAG, "Param data is NULL" ,
1164 CA_STATUS_INVALID_PARAM);
1168 OIC_LOG_V(ERROR, NET_DTLS_TAG, "dataLen is less than or equal zero [%d]", dataLen);
1169 return CA_STATUS_FAILED;
1172 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "Data to be encrypted dataLen [%d]", dataLen);
1174 stCADtlsAddrInfo_t addrInfo = { 0 };
1176 CAConvertNameToAddr(endpoint->addr, endpoint->port, &(addrInfo.addr.st));
1177 addrInfo.ifIndex = 0;
1178 addrInfo.size = CASizeOfAddrInfo(&addrInfo);
1180 ca_mutex_lock(g_dtlsContextMutex);
1181 if(NULL == g_caDtlsContext)
1183 OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
1184 ca_mutex_unlock(g_dtlsContextMutex);
1185 return CA_STATUS_FAILED;
1188 eDtlsRet_t ret = CAAdapterNetDtlsEncryptInternal(&addrInfo, data, dataLen);
1189 if (ret == DTLS_SESSION_INITIATED)
1191 stCACacheMessage_t *message = (stCACacheMessage_t *)OICCalloc(1, sizeof(stCACacheMessage_t));
1192 if (NULL == message)
1194 OIC_LOG(ERROR, NET_DTLS_TAG, "calloc failed!");
1195 ca_mutex_unlock(g_dtlsContextMutex);
1196 return CA_MEMORY_ALLOC_FAILED;
1199 message->data = (uint8_t *)OICCalloc(dataLen + 1, sizeof(uint8_t));
1200 if (NULL == message->data)
1202 OIC_LOG(ERROR, NET_DTLS_TAG, "calloc failed!");
1204 ca_mutex_unlock(g_dtlsContextMutex);
1205 return CA_MEMORY_ALLOC_FAILED;
1207 memcpy(message->data, data, dataLen);
1208 message->dataLen = dataLen;
1209 message->destSession = addrInfo;
1211 CAResult_t result = CADtlsCacheMsg(message);
1212 if (CA_STATUS_OK != result)
1214 OIC_LOG(DEBUG, NET_DTLS_TAG, "CADtlsCacheMsg failed!");
1215 CAFreeCacheMsg(message);
1217 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "OUT Initiating Dtls session [%d]", result);
1218 ca_mutex_unlock(g_dtlsContextMutex);
1222 ca_mutex_unlock(g_dtlsContextMutex);
1226 OIC_LOG(ERROR, NET_DTLS_TAG, "OUT FAILURE");
1227 return CA_STATUS_FAILED;
1230 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
1231 return CA_STATUS_OK;
1234 CAResult_t CAAdapterNetDtlsDecrypt(const CASecureEndpoint_t *sep,
1235 uint8_t *data, uint32_t dataLen)
1237 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
1238 VERIFY_NON_NULL_RET(sep, NET_DTLS_TAG, "endpoint is NULL" , CA_STATUS_INVALID_PARAM);
1240 stCADtlsAddrInfo_t addrInfo = { 0 };
1242 CAConvertNameToAddr(sep->endpoint.addr, sep->endpoint.port, &(addrInfo.addr.st));
1243 addrInfo.ifIndex = 0;
1244 addrInfo.size = CASizeOfAddrInfo(&addrInfo);
1246 ca_mutex_lock(g_dtlsContextMutex);
1247 if (NULL == g_caDtlsContext)
1249 OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
1250 ca_mutex_unlock(g_dtlsContextMutex);
1251 return CA_STATUS_FAILED;
1254 eDtlsRet_t ret = CAAdapterNetDtlsDecryptInternal(&addrInfo, data, dataLen);
1255 ca_mutex_unlock(g_dtlsContextMutex);
1257 if (DTLS_OK == ret || DTLS_HS_MSG == ret)
1259 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "Successfully Decrypted or Handshake msg recvd [%d]", ret);
1260 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
1261 return CA_STATUS_OK;
1264 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT FAILURE");
1265 return CA_STATUS_FAILED;