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"
32 #include "cainterface.h"
34 /* lenght of ASN.1 header in DER format
35 * for subject field in X.509 certificate */
36 #define DER_SUBJECT_HEADER_LEN (9)
39 #define VERIFY_SUCCESS(op, successCode) { if ((op) != (successCode)) \
40 {OIC_LOG_V(FATAL, NET_DTLS_TAG, "%s failed!!", #op); goto exit;} }
45 * @brief Logging tag for module name
47 #define NET_DTLS_TAG "NET_DTLS"
50 * @var g_caDtlsContext
51 * @brief global context which holds dtls context and cache list information.
53 static stCADtlsContext_t *g_caDtlsContext = NULL;
56 * @var g_dtlsContextMutex
57 * @brief Mutex to synchronize access to g_caDtlsContext.
59 static ca_mutex g_dtlsContextMutex = NULL;
62 * @var g_getCredentialsCallback
63 * @brief callback to get DTLS credentials
65 static CAGetDTLSPskCredentialsHandler g_getCredentialsCallback = NULL;
69 * @var g_getX509CredentialsCallback
70 * @brief callback to get DTLS certificate credentials
72 static CAGetDTLSX509CredentialsHandler g_getX509CredentialsCallback = NULL;
74 * @var g_getCrlCallback
75 * @brief callback to get CRL for DTLS
77 static CAGetDTLSCrlHandler g_getCrlCallback = NULL;
78 #endif //__WITH_X509__
80 static CASecureEndpoint_t *GetPeerInfo(const CAEndpoint_t *peer)
82 uint32_t list_index = 0;
83 uint32_t list_length = 0;
87 OIC_LOG(ERROR, NET_DTLS_TAG, "CAPeerInfoListContains invalid parameters");
91 CASecureEndpoint_t *peerInfo = NULL;
92 list_length = u_arraylist_length(g_caDtlsContext->peerInfoList);
93 for (list_index = 0; list_index < list_length; list_index++)
95 peerInfo = (CASecureEndpoint_t *)u_arraylist_get(g_caDtlsContext->peerInfoList, list_index);
101 if((0 == strncmp(peer->addr, peerInfo->endpoint.addr, MAX_ADDR_STR_SIZE_CA)) &&
102 (peer->port == peerInfo->endpoint.port))
110 static CAResult_t CAAddIdToPeerInfoList(const char *peerAddr, uint32_t port,
111 const unsigned char *id, uint16_t id_length)
117 || CA_MAX_ENDPOINT_IDENTITY_LEN < id_length)
119 OIC_LOG(ERROR, NET_DTLS_TAG, "CAAddIdToPeerInfoList invalid parameters");
120 return CA_STATUS_INVALID_PARAM;
123 CASecureEndpoint_t *peer = (CASecureEndpoint_t *)OICCalloc(1, sizeof (CASecureEndpoint_t));
126 OIC_LOG(ERROR, NET_DTLS_TAG, "peerInfo malloc failed!");
127 return CA_MEMORY_ALLOC_FAILED;
130 OICStrcpy(peer->endpoint.addr, sizeof(peer->endpoint.addr), peerAddr);
131 peer->endpoint.port = port;
133 memcpy(peer->identity.id, id, id_length);
134 peer->identity.id_length = id_length;
136 if (NULL != GetPeerInfo(&peer->endpoint))
138 OIC_LOG(ERROR, NET_DTLS_TAG, "CAAddIdToPeerInfoList peer already exist");
140 return CA_STATUS_FAILED;
143 bool result = u_arraylist_add(g_caDtlsContext->peerInfoList, (void *)peer);
146 OIC_LOG(ERROR, NET_DTLS_TAG, "u_arraylist_add failed!");
148 return CA_STATUS_FAILED;
154 static void CAFreePeerInfoList()
156 uint32_t list_length = u_arraylist_length(g_caDtlsContext->peerInfoList);
157 for (uint32_t list_index = 0; list_index < list_length; list_index++)
159 CAEndpoint_t *peerInfo = (CAEndpoint_t *)u_arraylist_get(
160 g_caDtlsContext->peerInfoList, list_index);
163 u_arraylist_free(&(g_caDtlsContext->peerInfoList));
164 g_caDtlsContext->peerInfoList = NULL;
167 static void CARemovePeerFromPeerInfoList(const char * addr, uint16_t port)
169 if (NULL == addr || 0 >= port)
171 OIC_LOG(ERROR, NET_DTLS_TAG, "CADTLSGetPeerPSKId invalid parameters");
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);
180 if (NULL == peerInfo)
184 if((0 == strncmp(addr, peerInfo->addr, MAX_ADDR_STR_SIZE_CA)) &&
185 (port == peerInfo->port))
187 OICFree(u_arraylist_remove(g_caDtlsContext->peerInfoList, list_index));
193 static int CASizeOfAddrInfo(stCADtlsAddrInfo_t *addrInfo)
195 VERIFY_NON_NULL_RET(addrInfo, NET_DTLS_TAG, "addrInfo is NULL" , DTLS_FAIL);
197 switch (addrInfo->addr.st.ss_family)
201 return sizeof (struct sockaddr_in);
205 return sizeof (struct sockaddr_in6);
212 return sizeof (struct sockaddr_storage);
215 static eDtlsRet_t CAAdapterNetDtlsEncryptInternal(const stCADtlsAddrInfo_t *dstSession,
216 uint8_t *data, uint32_t dataLen)
218 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
220 VERIFY_NON_NULL_RET(dstSession, NET_DTLS_TAG, "Param dstSession is NULL" , DTLS_FAIL);
221 VERIFY_NON_NULL_RET(data, NET_DTLS_TAG, "Param data is NULL" , DTLS_FAIL);
225 OIC_LOG(ERROR, NET_DTLS_TAG, "Given Packet length is equal to zero.");
229 if (NULL == g_caDtlsContext)
231 OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
235 int retLen = dtls_write(g_caDtlsContext->dtlsContext, (session_t *)dstSession, data,
237 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "dtls_write retun len [%d]", retLen);
240 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT FAILURE");
245 // A new DTLS session was initiated by tinyDTLS library and wait for callback.
246 return DTLS_SESSION_INITIATED;
248 else if (dataLen != (uint32_t)retLen)
250 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT FAILURE");
253 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
257 static eDtlsRet_t CAAdapterNetDtlsDecryptInternal(const stCADtlsAddrInfo_t *srcSession,
258 uint8_t *buf, uint32_t bufLen)
260 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
262 VERIFY_NON_NULL_RET(srcSession, NET_DTLS_TAG, "Param srcSession is NULL", DTLS_FAIL);
263 VERIFY_NON_NULL_RET(buf, NET_DTLS_TAG, "Param buf is NULL", DTLS_FAIL);
267 OIC_LOG(ERROR, NET_DTLS_TAG, "Given Packet length is equal to zero.");
271 eDtlsRet_t ret = DTLS_FAIL;
273 if (dtls_handle_message(g_caDtlsContext->dtlsContext, (session_t *)srcSession, buf, bufLen) == 0)
275 OIC_LOG(DEBUG, NET_DTLS_TAG, "dtls_handle_message success");
279 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
283 static void CAFreeCacheMsg(stCACacheMessage_t *msg)
285 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
286 VERIFY_NON_NULL_VOID(msg, NET_DTLS_TAG, "msg");
291 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
294 static void CAClearCacheList()
296 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
297 uint32_t list_index = 0;
298 uint32_t list_length = 0;
299 if (NULL == g_caDtlsContext)
301 OIC_LOG(ERROR, NET_DTLS_TAG, "Dtls Context is NULL");
304 list_length = u_arraylist_length(g_caDtlsContext->cacheList);
305 for (list_index = 0; list_index < list_length; list_index++)
307 stCACacheMessage_t *msg = (stCACacheMessage_t *)u_arraylist_get(g_caDtlsContext->cacheList,
314 u_arraylist_free(&g_caDtlsContext->cacheList);
315 g_caDtlsContext->cacheList = NULL;
316 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
319 static CAResult_t CADtlsCacheMsg(stCACacheMessage_t *msg)
321 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
323 if (NULL == g_caDtlsContext)
325 OIC_LOG(ERROR, NET_DTLS_TAG, "Dtls Context is NULL");
326 return CA_STATUS_FAILED;
329 bool result = u_arraylist_add(g_caDtlsContext->cacheList, (void *)msg);
332 OIC_LOG(ERROR, NET_DTLS_TAG, "u_arraylist_add failed!");
333 return CA_STATUS_FAILED;
336 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
341 static bool CAIsAddressMatching(const stCADtlsAddrInfo_t *a, const stCADtlsAddrInfo_t *b)
343 if (a->size != b->size)
347 if (memcmp(&a->addr, &b->addr, a->size))
354 static void CASendCachedMsg(const stCADtlsAddrInfo_t *dstSession)
356 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
357 VERIFY_NON_NULL_VOID(dstSession, NET_DTLS_TAG, "Param dstSession is NULL");
359 uint32_t list_index = 0;
360 uint32_t list_length = 0;
361 list_length = u_arraylist_length(g_caDtlsContext->cacheList);
362 for (list_index = 0; list_index < list_length;)
364 stCACacheMessage_t *msg = (stCACacheMessage_t *)u_arraylist_get(g_caDtlsContext->cacheList,
366 if ((NULL != msg) && (true == CAIsAddressMatching(&(msg->destSession), dstSession)))
368 eDtlsRet_t ret = CAAdapterNetDtlsEncryptInternal(&(msg->destSession),
369 msg->data, msg->dataLen);
372 OIC_LOG(DEBUG, NET_DTLS_TAG, "CAAdapterNetDtlsEncryptInternal success");
376 OIC_LOG(ERROR, NET_DTLS_TAG, "CAAdapterNetDtlsEncryptInternal failed.");
379 if (u_arraylist_remove(g_caDtlsContext->cacheList, list_index))
382 // Reduce list length by 1 as we removed one element.
387 OIC_LOG(ERROR, NET_DTLS_TAG, "u_arraylist_remove failed.");
393 // Move to the next element
398 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
401 static int32_t CAReadDecryptedPayload(dtls_context_t *context,
407 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
409 VERIFY_NON_NULL_RET(session, NET_DTLS_TAG, "Param Session is NULL", 0);
410 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "Decrypted buf len [%d]", bufLen);
412 stCADtlsAddrInfo_t *addrInfo = (stCADtlsAddrInfo_t *)session;
414 CASecureEndpoint_t sep =
416 { .adapter = CA_ADAPTER_IP, .flags =
417 ((addrInfo->addr.st.ss_family == AF_INET) ? CA_IPV4 : CA_IPV6) | CA_SECURE, .port = 0 },
420 CAConvertAddrToName(&(addrInfo->addr.st), addrInfo->size, sep.endpoint.addr, &sep.endpoint.port);
422 if (NULL == g_caDtlsContext)
424 OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
429 if ((0 <= type) && (MAX_SUPPORTED_ADAPTERS > type) &&
430 (NULL != g_caDtlsContext->adapterCallbacks[type].recvCallback))
432 // Get identity of the source of packet
433 CASecureEndpoint_t *peerInfo = GetPeerInfo(&sep.endpoint);
436 sep.identity = peerInfo->identity;
439 g_caDtlsContext->adapterCallbacks[type].recvCallback(&sep, buf, bufLen);
443 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "recvCallback Callback or adapter type is wrong [%d]", type);
446 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
450 static int32_t CASendSecureData(dtls_context_t *context,
456 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
458 VERIFY_NON_NULL_RET(session, NET_DTLS_TAG, "Param Session is NULL", -1);
459 VERIFY_NON_NULL_RET(buf, NET_DTLS_TAG, "Param buf is NULL", -1);
463 OIC_LOG(ERROR, NET_DTLS_TAG, "Encrypted Buffer length is equal to zero");
467 stCADtlsAddrInfo_t *addrInfo = (stCADtlsAddrInfo_t *)session;
469 CAEndpoint_t endpoint = {.adapter = CA_DEFAULT_ADAPTER};
471 CAConvertAddrToName(&(addrInfo->addr.st), addrInfo->size, endpoint.addr, &endpoint.port);
472 endpoint.flags = addrInfo->addr.st.ss_family == AF_INET ? CA_IPV4 : CA_IPV6;
473 endpoint.flags |= CA_SECURE;
474 endpoint.adapter = CA_ADAPTER_IP;
475 endpoint.interface = session->ifindex;
478 //Mutex is not required for g_caDtlsContext. It will be called in same thread.
479 if ((0 <= type) && (MAX_SUPPORTED_ADAPTERS > type) &&
480 (NULL != g_caDtlsContext->adapterCallbacks[type].sendCallback))
482 g_caDtlsContext->adapterCallbacks[type].sendCallback(&endpoint, buf, bufLen);
486 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "send Callback or adapter type is wrong [%d]", type );
489 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
493 static int32_t CAHandleSecureEvent(dtls_context_t *context,
495 dtls_alert_level_t level,
499 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
501 VERIFY_NON_NULL_RET(session, NET_DTLS_TAG, "Param Session is NULL", 0);
503 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "level [%d] code [%u]", level, code);
505 if (!level && (code == DTLS_EVENT_CONNECTED))
507 OIC_LOG(DEBUG, NET_DTLS_TAG, "Received DTLS_EVENT_CONNECTED. Sending Cached data");
508 CASendCachedMsg((stCADtlsAddrInfo_t *)session);
511 if(DTLS_ALERT_LEVEL_FATAL == level && DTLS_ALERT_CLOSE_NOTIFY == code)
513 OIC_LOG(INFO, NET_DTLS_TAG, "Peer closing connection");
515 stCADtlsAddrInfo_t *addrInfo = (stCADtlsAddrInfo_t *)session;
516 char peerAddr[MAX_ADDR_STR_SIZE_CA] = { 0 };
518 CAConvertAddrToName(&(addrInfo->addr.st), addrInfo->size, peerAddr, &port);
519 CARemovePeerFromPeerInfoList(peerAddr, port);
522 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
527 static int32_t CAGetPskCredentials(dtls_context_t *ctx,
528 const session_t *session,
529 dtls_credentials_type_t type,
530 const unsigned char *desc, size_t descLen,
531 unsigned char *result, size_t resultLen)
533 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
536 if(NULL == ctx || NULL == session || NULL == result)
538 OIC_LOG(ERROR, NET_DTLS_TAG, "CAGetPskCredentials invalid parameters");
542 VERIFY_NON_NULL_RET(g_getCredentialsCallback, NET_DTLS_TAG, "GetCredential callback", -1);
544 // Retrieve the credentials blob from security module
545 ret = g_getCredentialsCallback(type, desc, descLen, result, resultLen);
549 // TODO SRM needs identity of the remote end-point with every data packet to
550 // perform access control management. tinyDTLS 'frees' the handshake parameters
551 // data structure when handshake completes. Therefore, currently this is a
552 // workaround to cache remote end-point identity when tinyDTLS asks for PSK.
553 stCADtlsAddrInfo_t *addrInfo = (stCADtlsAddrInfo_t *)session;
554 char peerAddr[MAX_ADDR_STR_SIZE_CA] = { 0 };
556 CAConvertAddrToName(&(addrInfo->addr.st), addrInfo->size, peerAddr, &port);
558 if(CA_STATUS_OK != CAAddIdToPeerInfoList(peerAddr, port, desc, descLen) )
560 OIC_LOG(ERROR, NET_DTLS_TAG, "Fail to add peer id to gDtlsPeerInfoList");
567 void CADTLSSetAdapterCallbacks(CAPacketReceivedCallback recvCallback,
568 CAPacketSendCallback sendCallback,
569 CATransportAdapter_t type)
571 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
572 ca_mutex_lock(g_dtlsContextMutex);
573 if (NULL == g_caDtlsContext)
575 OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
576 ca_mutex_unlock(g_dtlsContextMutex);
580 if ((0 <= type) && (MAX_SUPPORTED_ADAPTERS > type))
582 // TODO: change the zeros to better values.
583 g_caDtlsContext->adapterCallbacks[0].recvCallback = recvCallback;
584 g_caDtlsContext->adapterCallbacks[0].sendCallback = sendCallback;
587 ca_mutex_unlock(g_dtlsContextMutex);
589 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
592 void CADTLSSetCredentialsCallback(CAGetDTLSPskCredentialsHandler credCallback)
594 // TODO Does this method needs protection of DtlsContextMutex ?
595 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
596 g_getCredentialsCallback = credCallback;
597 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
601 void CADTLSSetX509CredentialsCallback(CAGetDTLSX509CredentialsHandler credCallback)
603 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
604 g_getX509CredentialsCallback = credCallback;
605 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
607 void CADTLSSetCrlCallback(CAGetDTLSCrlHandler crlCallback)
609 // TODO Does this method needs protection of DtlsContextMutex ?
610 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
611 g_getCrlCallback = crlCallback;
612 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
614 #endif // __WITH_X509__
616 CAResult_t CADtlsSelectCipherSuite(const dtls_cipher_t cipher)
618 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN CADtlsSelectCipherSuite");
620 ca_mutex_lock(g_dtlsContextMutex);
621 if (NULL == g_caDtlsContext)
623 OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
624 ca_mutex_unlock(g_dtlsContextMutex);
625 return CA_STATUS_FAILED;
627 dtls_select_cipher(g_caDtlsContext->dtlsContext, cipher);
628 ca_mutex_unlock(g_dtlsContextMutex);
630 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "Selected cipher suite is 0x%02X%02X\n",
631 ((uint8_t*)(&cipher))[1], ((uint8_t*)(&cipher))[0]);
632 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT CADtlsSelectCipherSuite");
634 return CA_STATUS_OK ;
637 CAResult_t CADtlsEnableAnonECDHCipherSuite(const bool enable)
639 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN CADtlsEnablesAnonEcdh");
641 ca_mutex_lock(g_dtlsContextMutex);
642 if (NULL == g_caDtlsContext)
644 OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
645 ca_mutex_unlock(g_dtlsContextMutex);
646 return CA_STATUS_FAILED;
648 dtls_enables_anon_ecdh(g_caDtlsContext->dtlsContext,
649 enable == true ? DTLS_CIPHER_ENABLE : DTLS_CIPHER_DISABLE);
650 ca_mutex_unlock(g_dtlsContextMutex);
651 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256 is %s",
652 enable ? "enabled" : "disabled");
654 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT CADtlsEnablesAnonEcdh");
656 return CA_STATUS_OK ;
659 CAResult_t CADtlsInitiateHandshake(const CAEndpoint_t *endpoint)
661 stCADtlsAddrInfo_t dst = { 0 };
663 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN CADtlsInitiateHandshake");
667 return CA_STATUS_INVALID_PARAM;
670 CAConvertNameToAddr(endpoint->addr, endpoint->port, &(dst.addr.st));
672 dst.size = CASizeOfAddrInfo(&dst);
674 ca_mutex_lock(g_dtlsContextMutex);
675 if(NULL == g_caDtlsContext)
677 OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
678 ca_mutex_unlock(g_dtlsContextMutex);
679 return CA_STATUS_FAILED;
682 if(0 > dtls_connect(g_caDtlsContext->dtlsContext, (session_t*)(&dst)))
684 OIC_LOG(ERROR, NET_DTLS_TAG, "Failed to connect");
685 ca_mutex_unlock(g_dtlsContextMutex);
686 return CA_STATUS_FAILED;
689 ca_mutex_unlock(g_dtlsContextMutex);
691 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT CADtlsInitiateHandshake");
696 CAResult_t CADtlsClose(const CAEndpoint_t *endpoint)
698 stCADtlsAddrInfo_t dst = { 0 };
700 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN CADtlsDisconnect");
704 return CA_STATUS_INVALID_PARAM;
707 CAConvertNameToAddr(endpoint->addr, endpoint->port, &(dst.addr.st));
709 dst.size = CASizeOfAddrInfo(&dst);
711 ca_mutex_lock(g_dtlsContextMutex);
712 if (NULL == g_caDtlsContext)
714 OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
715 ca_mutex_unlock(g_dtlsContextMutex);
716 return CA_STATUS_FAILED;
719 if (0 > dtls_close(g_caDtlsContext->dtlsContext, (session_t*)(&dst)))
721 OIC_LOG(ERROR, NET_DTLS_TAG, "Failed to close the session");
722 ca_mutex_unlock(g_dtlsContextMutex);
723 return CA_STATUS_FAILED;
726 ca_mutex_unlock(g_dtlsContextMutex);
728 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT CADtlsDisconnect");
733 CAResult_t CADtlsGenerateOwnerPSK(const CAEndpoint_t *endpoint,
734 const uint8_t* label, const size_t labelLen,
735 const uint8_t* rsrcServerDeviceID, const size_t rsrcServerDeviceIDLen,
736 const uint8_t* provServerDeviceID, const size_t provServerDeviceIDLen,
737 uint8_t* ownerPSK, const size_t ownerPSKSize)
739 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN CADtlsGenerateOwnerPSK");
741 if(!endpoint || !label || 0 == labelLen || !ownerPSK || 0 == ownerPSKSize)
743 return CA_STATUS_INVALID_PARAM;
746 stCADtlsAddrInfo_t dst = { 0 };
748 CAConvertNameToAddr(endpoint->addr, endpoint->port, &(dst.addr.st));
750 dst.size = CASizeOfAddrInfo(&dst);
752 ca_mutex_lock(g_dtlsContextMutex);
753 if (NULL == g_caDtlsContext)
755 OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
756 ca_mutex_unlock(g_dtlsContextMutex);
757 return CA_STATUS_FAILED;
760 if( 0 == dtls_prf_with_current_keyblock(g_caDtlsContext->dtlsContext, (session_t*)(&dst),
761 label, labelLen, rsrcServerDeviceID, rsrcServerDeviceIDLen,
762 provServerDeviceID, provServerDeviceIDLen, ownerPSK, ownerPSKSize))
764 OIC_LOG(ERROR, NET_DTLS_TAG, "Failed to DTLS PRF");
765 ca_mutex_unlock(g_dtlsContextMutex);
766 return CA_STATUS_FAILED;
768 ca_mutex_unlock(g_dtlsContextMutex);
770 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT CADtlsGenerateOwnerPSK");
776 static CADtlsX509Creds_t g_X509Cred = {{0}, 0, 0, {0}, {0}, {0}};
780 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN CAInitX509");
781 VERIFY_NON_NULL_RET(g_getX509CredentialsCallback, NET_DTLS_TAG, "GetX509Credential callback", -1);
782 int isX509Init = (0 == g_getX509CredentialsCallback(&g_X509Cred));
786 uint8_t crlData[CRL_MAX_LEN] = {0};
787 ByteArray crlArray = {crlData, CRL_MAX_LEN};
788 g_getCrlCallback(crlArray);
789 if (crlArray.len > 0)
791 uint8_t keyData[PUBLIC_KEY_SIZE] = {0};
792 CertificateList crl = CRL_INITIALIZER;
793 ByteArray rootPubKey = {keyData, PUBLIC_KEY_SIZE};
794 memcpy(keyData, g_X509Cred.rootPublicKeyX, PUBLIC_KEY_SIZE / 2);
795 memcpy(keyData + PUBLIC_KEY_SIZE / 2, g_X509Cred.rootPublicKeyY, PUBLIC_KEY_SIZE / 2);
796 DecodeCertificateList(crlArray, &crl, rootPubKey);
800 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT CAInitX509");
812 static int CAIsX509Active(struct dtls_context_t *ctx)
818 static int CAGetDeviceKey(struct dtls_context_t *ctx,
819 const session_t *session,
820 const dtls_ecc_key_t **result)
822 OIC_LOG(DEBUG, NET_DTLS_TAG, "CAGetDeviceKey");
823 static dtls_ecc_key_t ecdsa_key = {DTLS_ECDH_CURVE_SECP256R1, NULL, NULL, NULL};
826 VERIFY_SUCCESS(CAInitX509(), 0);
828 ecdsa_key.priv_key = g_X509Cred.devicePrivateKey;
829 *result = &ecdsa_key;
837 CAGetDeviceCertificate(struct dtls_context_t *ctx,
838 const session_t *session,
839 const unsigned char **cert,
842 OIC_LOG(DEBUG, NET_DTLS_TAG, "CAGetDeviceCertificate");
845 VERIFY_SUCCESS(CAInitX509(), 0);
847 *cert = g_X509Cred.certificateChain;
848 *cert_size = g_X509Cred.certificateChainLen;
850 ByteArray ownCert = {g_X509Cred.certificateChain, g_X509Cred.certificateChainLen};
851 PRINT_BYTE_ARRAY("OWN CERT: \n", ownCert);
860 * @brief Gets x and y components of Root Certificate Autority public key
862 * @return 0 on success otherwise a positive error value.
865 static int CAGetRootKey(const unsigned char **ca_pub_x, const unsigned char **ca_pub_y)
867 OIC_LOG(DEBUG, NET_DTLS_TAG, "CAGetRootKey");
870 VERIFY_SUCCESS(CAInitX509(), 0);
872 *ca_pub_x = g_X509Cred.rootPublicKeyX;
873 *ca_pub_y = g_X509Cred.rootPublicKeyY;
881 static int CAVerifyCertificate(struct dtls_context_t *ctx, const session_t *session,
882 const unsigned char *cert, size_t certLen,
883 const unsigned char *x, size_t xLen,
884 const unsigned char *y, size_t yLen)
886 OIC_LOG(DEBUG, NET_DTLS_TAG, "Verify Certificate");
888 ByteArray crtChainDer[MAX_CHAIN_LEN];
889 CertificateX509 crtChain[MAX_CHAIN_LEN];
894 const unsigned char *ca_pub_x;
895 const unsigned char *ca_pub_y;
896 ByteArray certDerCode = BYTE_ARRAY_INITIALIZER;
897 ByteArray caPubKey = BYTE_ARRAY_INITIALIZER;
898 unsigned char ca_pub_key[PUBLIC_KEY_SIZE];
900 if ( !ctx || !session || !cert || !x || !y)
902 return -PKI_NULL_PASSED;
905 CAGetRootKey (&ca_pub_x, &ca_pub_y);
907 certDerCode.data = (uint8_t *)cert;
908 certDerCode.len = certLen;
911 PRINT_BYTE_ARRAY("CERT :\n", certDerCode);
915 caPubKey.len = PUBLIC_KEY_SIZE;
916 caPubKey.data = ca_pub_key;
918 memcpy(caPubKey.data, ca_pub_x, PUBLIC_KEY_SIZE / 2);
919 memcpy(caPubKey.data + PUBLIC_KEY_SIZE / 2, ca_pub_y, PUBLIC_KEY_SIZE / 2);
921 ret = (int) LoadCertificateChain (certDerCode, crtChainDer, &chainLength);
922 VERIFY_SUCCESS(ret, PKI_SUCCESS);
923 ret = (int) ParseCertificateChain (crtChainDer, crtChain, chainLength );
924 VERIFY_SUCCESS(ret, PKI_SUCCESS);
925 ret = (int) CheckCertificateChain (crtChain, chainLength, caPubKey);
926 VERIFY_SUCCESS(ret, PKI_SUCCESS);
928 INC_BYTE_ARRAY(crtChain[0].pubKey, 2);
930 memcpy(x, crtChain[0].pubKey.data, xLen);
931 memcpy(y, crtChain[0].pubKey.data + PUBLIC_KEY_SIZE / 2, yLen);
933 stCADtlsAddrInfo_t *addrInfo = (stCADtlsAddrInfo_t *)session;
934 char peerAddr[MAX_ADDR_STR_SIZE_CA] = { 0 };
936 CAConvertAddrToName(&(addrInfo->addr.st), addrInfo->size, peerAddr, &port);
938 CAResult_t result = CAAddIdToPeerInfoList(peerAddr, port,
939 crtChain[0].subject.data + DER_SUBJECT_HEADER_LEN + 2, crtChain[0].subject.data[DER_SUBJECT_HEADER_LEN + 1]);
940 if (CA_STATUS_OK != result )
942 OIC_LOG(ERROR, NET_DTLS_TAG, "Fail to add peer id to gDtlsPeerInfoList");
948 OIC_LOG(DEBUG, NET_DTLS_TAG, "Certificate verification FAILED\n");
952 OIC_LOG(DEBUG, NET_DTLS_TAG, "Certificate verification SUCCESS\n");
959 CAResult_t CAAdapterNetDtlsInit()
961 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
963 // Initialize mutex for DtlsContext
964 if (NULL == g_dtlsContextMutex)
966 g_dtlsContextMutex = ca_mutex_new();
967 VERIFY_NON_NULL_RET(g_dtlsContextMutex, NET_DTLS_TAG, "malloc failed",
968 CA_MEMORY_ALLOC_FAILED);
972 OIC_LOG(ERROR, NET_DTLS_TAG, "CAAdapterNetDtlsInit done already!");
976 // Lock DtlsContext mutex and create DtlsContext
977 ca_mutex_lock(g_dtlsContextMutex);
978 g_caDtlsContext = (stCADtlsContext_t *)OICCalloc(1, sizeof(stCADtlsContext_t));
980 if (NULL == g_caDtlsContext)
982 OIC_LOG(ERROR, NET_DTLS_TAG, "Context malloc failed");
983 ca_mutex_unlock(g_dtlsContextMutex);
984 ca_mutex_free(g_dtlsContextMutex);
985 return CA_MEMORY_ALLOC_FAILED;
989 // Create PeerInfoList and CacheList
990 g_caDtlsContext->peerInfoList = u_arraylist_create();
991 g_caDtlsContext->cacheList = u_arraylist_create();
993 if( (NULL == g_caDtlsContext->peerInfoList) ||
994 (NULL == g_caDtlsContext->cacheList))
996 OIC_LOG(ERROR, NET_DTLS_TAG, "peerInfoList or cacheList initialization failed!");
998 CAFreePeerInfoList();
999 OICFree(g_caDtlsContext);
1000 g_caDtlsContext = NULL;
1001 ca_mutex_unlock(g_dtlsContextMutex);
1002 ca_mutex_free(g_dtlsContextMutex);
1003 return CA_STATUS_FAILED;
1006 // Initialize clock, crypto and other global vars in tinyDTLS library
1009 // Create tinydtls Context
1010 g_caDtlsContext->dtlsContext = dtls_new_context(g_caDtlsContext);
1012 if (NULL == g_caDtlsContext->dtlsContext)
1014 OIC_LOG(ERROR, NET_DTLS_TAG, "dtls_new_context failed");
1015 ca_mutex_unlock(g_dtlsContextMutex);
1016 CAAdapterNetDtlsDeInit();
1017 return CA_STATUS_FAILED;
1020 g_caDtlsContext->callbacks.write = CASendSecureData;
1021 g_caDtlsContext->callbacks.read = CAReadDecryptedPayload;
1022 g_caDtlsContext->callbacks.event = CAHandleSecureEvent;
1024 g_caDtlsContext->callbacks.get_psk_info = CAGetPskCredentials;
1025 #ifdef __WITH_X509__
1026 g_caDtlsContext->callbacks.get_x509_key = CAGetDeviceKey;
1027 g_caDtlsContext->callbacks.verify_x509_cert = CAVerifyCertificate;
1028 g_caDtlsContext->callbacks.get_x509_cert = CAGetDeviceCertificate;
1029 g_caDtlsContext->callbacks.is_x509_active = CAIsX509Active;
1030 #endif //__WITH_X509__*
1031 dtls_set_handler(g_caDtlsContext->dtlsContext, &(g_caDtlsContext->callbacks));
1032 ca_mutex_unlock(g_dtlsContextMutex);
1033 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
1034 return CA_STATUS_OK;
1037 void CAAdapterNetDtlsDeInit()
1039 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
1041 VERIFY_NON_NULL_VOID(g_caDtlsContext, NET_DTLS_TAG, "context is NULL");
1042 VERIFY_NON_NULL_VOID(g_dtlsContextMutex, NET_DTLS_TAG, "context mutex is NULL");
1044 //Lock DtlsContext mutex
1045 ca_mutex_lock(g_dtlsContextMutex);
1048 CAFreePeerInfoList();
1051 // De-initialize tinydtls context
1052 dtls_free_context(g_caDtlsContext->dtlsContext);
1053 g_caDtlsContext->dtlsContext = NULL;
1055 // De-initialize DtlsContext
1056 OICFree(g_caDtlsContext);
1057 g_caDtlsContext = NULL;
1059 // Unlock DtlsContext mutex and de-initialize it
1060 ca_mutex_unlock(g_dtlsContextMutex);
1061 ca_mutex_free(g_dtlsContextMutex);
1062 g_dtlsContextMutex = NULL;
1064 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
1067 CAResult_t CAAdapterNetDtlsEncrypt(const CAEndpoint_t *endpoint,
1068 void *data, uint32_t dataLen)
1071 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
1073 VERIFY_NON_NULL_RET(endpoint, NET_DTLS_TAG,"Param remoteAddress is NULL",
1074 CA_STATUS_INVALID_PARAM);
1075 VERIFY_NON_NULL_RET(data, NET_DTLS_TAG, "Param data is NULL" ,
1076 CA_STATUS_INVALID_PARAM);
1080 OIC_LOG_V(ERROR, NET_DTLS_TAG, "dataLen is less than or equal zero [%d]", dataLen);
1081 return CA_STATUS_FAILED;
1084 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "Data to be encrypted dataLen [%d]", dataLen);
1086 stCADtlsAddrInfo_t addrInfo = { 0 };
1088 CAConvertNameToAddr(endpoint->addr, endpoint->port, &(addrInfo.addr.st));
1089 addrInfo.ifIndex = 0;
1090 addrInfo.size = CASizeOfAddrInfo(&addrInfo);
1092 ca_mutex_lock(g_dtlsContextMutex);
1093 if(NULL == g_caDtlsContext)
1095 OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
1096 ca_mutex_unlock(g_dtlsContextMutex);
1097 return CA_STATUS_FAILED;
1100 eDtlsRet_t ret = CAAdapterNetDtlsEncryptInternal(&addrInfo, data, dataLen);
1101 if (ret == DTLS_SESSION_INITIATED)
1103 stCACacheMessage_t *message = (stCACacheMessage_t *)OICCalloc(1, sizeof(stCACacheMessage_t));
1104 if (NULL == message)
1106 OIC_LOG(ERROR, NET_DTLS_TAG, "calloc failed!");
1107 ca_mutex_unlock(g_dtlsContextMutex);
1108 return CA_MEMORY_ALLOC_FAILED;
1111 message->data = (uint8_t *)OICCalloc(dataLen + 1, sizeof(uint8_t));
1112 if (NULL == message->data)
1114 OIC_LOG(ERROR, NET_DTLS_TAG, "calloc failed!");
1116 ca_mutex_unlock(g_dtlsContextMutex);
1117 return CA_MEMORY_ALLOC_FAILED;
1119 memcpy(message->data, data, dataLen);
1120 message->dataLen = dataLen;
1121 message->destSession = addrInfo;
1123 CAResult_t result = CADtlsCacheMsg(message);
1124 if (CA_STATUS_OK != result)
1126 OIC_LOG(DEBUG, NET_DTLS_TAG, "CADtlsCacheMsg failed!");
1127 CAFreeCacheMsg(message);
1129 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "OUT Initiating Dtls session [%d]", result);
1130 ca_mutex_unlock(g_dtlsContextMutex);
1134 ca_mutex_unlock(g_dtlsContextMutex);
1138 OIC_LOG(ERROR, NET_DTLS_TAG, "OUT FAILURE");
1139 return CA_STATUS_FAILED;
1142 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
1143 return CA_STATUS_OK;
1146 CAResult_t CAAdapterNetDtlsDecrypt(const CASecureEndpoint_t *sep,
1147 uint8_t *data, uint32_t dataLen)
1149 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
1150 VERIFY_NON_NULL_RET(sep, NET_DTLS_TAG, "endpoint is NULL" , CA_STATUS_INVALID_PARAM);
1152 stCADtlsAddrInfo_t addrInfo = { 0 };
1154 CAConvertNameToAddr(sep->endpoint.addr, sep->endpoint.port, &(addrInfo.addr.st));
1155 addrInfo.ifIndex = 0;
1156 addrInfo.size = CASizeOfAddrInfo(&addrInfo);
1158 ca_mutex_lock(g_dtlsContextMutex);
1159 if (NULL == g_caDtlsContext)
1161 OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
1162 ca_mutex_unlock(g_dtlsContextMutex);
1163 return CA_STATUS_FAILED;
1166 eDtlsRet_t ret = CAAdapterNetDtlsDecryptInternal(&addrInfo, data, dataLen);
1167 ca_mutex_unlock(g_dtlsContextMutex);
1169 if (DTLS_OK == ret || DTLS_HS_MSG == ret)
1171 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "Successfully Decrypted or Handshake msg recvd [%d]", ret);
1172 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
1173 return CA_STATUS_OK;
1176 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT FAILURE");
1177 return CA_STATUS_FAILED;