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"
31 #include "cainterface.h"
32 #include "credresource.h"
34 #define VERIFY_SUCCESS(op, successCode) { if ((op) != (successCode)) \
35 {OIC_LOG_V(FATAL, NET_DTLS_TAG, "%s failed!!", #op); goto exit;} }
40 * @brief Logging tag for module name
42 #define NET_DTLS_TAG "NET_DTLS"
45 * @var g_caDtlsContext
46 * @brief global context which holds dtls context and cache list information.
48 static stCADtlsContext_t *g_caDtlsContext = NULL;
51 * @var g_dtlsContextMutex
52 * @brief Mutex to synchronize access to g_caDtlsContext.
54 static ca_mutex g_dtlsContextMutex = NULL;
57 * @var g_getCredentialsCallback
58 * @brief callback to get DTLS credentials
60 static CAGetDTLSCredentialsHandler g_getCredentialsCallback = NULL;
62 static CASecureEndpoint_t *GetPeerInfo(const CAEndpoint_t *peer)
64 uint32_t list_index = 0;
65 uint32_t list_length = 0;
69 OIC_LOG(ERROR, NET_DTLS_TAG, "CAPeerInfoListContains invalid parameters");
73 CASecureEndpoint_t *peerInfo = NULL;
74 list_length = u_arraylist_length(g_caDtlsContext->peerInfoList);
75 for (list_index = 0; list_index < list_length; list_index++)
77 peerInfo = (CASecureEndpoint_t *)u_arraylist_get(g_caDtlsContext->peerInfoList, list_index);
83 if((0 == strncmp(peer->addr, peerInfo->endpoint.addr, MAX_ADDR_STR_SIZE_CA)) &&
84 (peer->port == peerInfo->endpoint.port))
92 static CAResult_t CAAddIdToPeerInfoList(const char *peerAddr, uint32_t port,
93 const unsigned char *id, uint16_t id_length)
99 || CA_MAX_ENDPOINT_IDENTITY_LEN < id_length)
101 OIC_LOG(ERROR, NET_DTLS_TAG, "CAAddIdToPeerInfoList invalid parameters");
102 return CA_STATUS_INVALID_PARAM;
105 CASecureEndpoint_t *peer = (CASecureEndpoint_t *)OICCalloc(1, sizeof (CASecureEndpoint_t));
108 OIC_LOG(ERROR, NET_DTLS_TAG, "peerInfo malloc failed!");
109 return CA_MEMORY_ALLOC_FAILED;
112 OICStrcpy(peer->endpoint.addr, sizeof(peer->endpoint.addr), peerAddr);
113 peer->endpoint.port = port;
115 memcpy(peer->identity.id, id, id_length);
116 peer->identity.id_length = id_length;
118 if (NULL != GetPeerInfo(&peer->endpoint))
120 OIC_LOG(ERROR, NET_DTLS_TAG, "CAAddIdToPeerInfoList peer already exist");
122 return CA_STATUS_FAILED;
125 bool result = u_arraylist_add(g_caDtlsContext->peerInfoList, (void *)peer);
128 OIC_LOG(ERROR, NET_DTLS_TAG, "u_arraylist_add failed!");
130 return CA_STATUS_FAILED;
136 static void CAFreePeerInfoList()
138 uint32_t list_length = u_arraylist_length(g_caDtlsContext->peerInfoList);
139 for (uint32_t list_index = 0; list_index < list_length; list_index++)
141 CAEndpoint_t *peerInfo = (CAEndpoint_t *)u_arraylist_get(
142 g_caDtlsContext->peerInfoList, list_index);
145 u_arraylist_free(&(g_caDtlsContext->peerInfoList));
146 g_caDtlsContext->peerInfoList = NULL;
149 static void CARemovePeerFromPeerInfoList(const char * addr, uint16_t port)
151 if (NULL == addr || 0 >= port)
153 OIC_LOG(ERROR, NET_DTLS_TAG, "CADTLSGetPeerPSKId invalid parameters");
157 uint32_t list_length = u_arraylist_length(g_caDtlsContext->peerInfoList);
158 for (uint32_t list_index = 0; list_index < list_length; list_index++)
160 CAEndpoint_t *peerInfo = (CAEndpoint_t *)u_arraylist_get(
161 g_caDtlsContext->peerInfoList,list_index);
162 if (NULL == peerInfo)
166 if((0 == strncmp(addr, peerInfo->addr, MAX_ADDR_STR_SIZE_CA)) &&
167 (port == peerInfo->port))
169 OICFree(u_arraylist_remove(g_caDtlsContext->peerInfoList, list_index));
175 static int CASizeOfAddrInfo(stCADtlsAddrInfo_t *addrInfo)
177 VERIFY_NON_NULL_RET(addrInfo, NET_DTLS_TAG, "addrInfo is NULL" , DTLS_FAIL);
179 switch (addrInfo->addr.st.ss_family)
183 return sizeof (struct sockaddr_in);
187 return sizeof (struct sockaddr_in6);
194 return sizeof (struct sockaddr_storage);
197 static eDtlsRet_t CAAdapterNetDtlsEncryptInternal(const stCADtlsAddrInfo_t *dstSession,
198 uint8_t *data, uint32_t dataLen)
200 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
202 VERIFY_NON_NULL_RET(dstSession, NET_DTLS_TAG, "Param dstSession is NULL" , DTLS_FAIL);
203 VERIFY_NON_NULL_RET(data, NET_DTLS_TAG, "Param data is NULL" , DTLS_FAIL);
207 OIC_LOG(ERROR, NET_DTLS_TAG, "Given Packet length is equal to zero.");
211 if (NULL == g_caDtlsContext)
213 OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
217 int retLen = dtls_write(g_caDtlsContext->dtlsContext, (session_t *)dstSession, data,
219 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "dtls_write retun len [%d]", retLen);
222 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT FAILURE");
227 // A new DTLS session was initiated by tinyDTLS library and wait for callback.
228 return DTLS_SESSION_INITIATED;
230 else if (dataLen != (uint32_t)retLen)
232 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT FAILURE");
235 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
239 static eDtlsRet_t CAAdapterNetDtlsDecryptInternal(const stCADtlsAddrInfo_t *srcSession,
240 uint8_t *buf, uint32_t bufLen)
242 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
244 VERIFY_NON_NULL_RET(srcSession, NET_DTLS_TAG, "Param srcSession is NULL", DTLS_FAIL);
245 VERIFY_NON_NULL_RET(buf, NET_DTLS_TAG, "Param buf is NULL", DTLS_FAIL);
249 OIC_LOG(ERROR, NET_DTLS_TAG, "Given Packet length is equal to zero.");
253 eDtlsRet_t ret = DTLS_FAIL;
255 if (dtls_handle_message(g_caDtlsContext->dtlsContext, (session_t *)srcSession, buf, bufLen) == 0)
257 OIC_LOG(DEBUG, NET_DTLS_TAG, "dtls_handle_message success");
261 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
265 static void CAFreeCacheMsg(stCACacheMessage_t *msg)
267 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
268 VERIFY_NON_NULL_VOID(msg, NET_DTLS_TAG, "msg");
273 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
276 static void CAClearCacheList()
278 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
279 uint32_t list_index = 0;
280 uint32_t list_length = 0;
281 if (NULL == g_caDtlsContext)
283 OIC_LOG(ERROR, NET_DTLS_TAG, "Dtls Context is NULL");
286 list_length = u_arraylist_length(g_caDtlsContext->cacheList);
287 for (list_index = 0; list_index < list_length; list_index++)
289 stCACacheMessage_t *msg = (stCACacheMessage_t *)u_arraylist_get(g_caDtlsContext->cacheList,
296 u_arraylist_free(&g_caDtlsContext->cacheList);
297 g_caDtlsContext->cacheList = NULL;
298 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
301 static CAResult_t CADtlsCacheMsg(stCACacheMessage_t *msg)
303 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
305 if (NULL == g_caDtlsContext)
307 OIC_LOG(ERROR, NET_DTLS_TAG, "Dtls Context is NULL");
308 return CA_STATUS_FAILED;
311 bool result = u_arraylist_add(g_caDtlsContext->cacheList, (void *)msg);
314 OIC_LOG(ERROR, NET_DTLS_TAG, "u_arraylist_add failed!");
315 return CA_STATUS_FAILED;
318 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
323 static bool CAIsAddressMatching(const stCADtlsAddrInfo_t *a, const stCADtlsAddrInfo_t *b)
325 if (a->size != b->size)
329 if (memcmp(&a->addr, &b->addr, a->size))
336 static void CASendCachedMsg(const stCADtlsAddrInfo_t *dstSession)
338 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
339 VERIFY_NON_NULL_VOID(dstSession, NET_DTLS_TAG, "Param dstSession is NULL");
341 uint32_t list_index = 0;
342 uint32_t list_length = 0;
343 list_length = u_arraylist_length(g_caDtlsContext->cacheList);
344 for (list_index = 0; list_index < list_length;)
346 stCACacheMessage_t *msg = (stCACacheMessage_t *)u_arraylist_get(g_caDtlsContext->cacheList,
348 if ((NULL != msg) && (true == CAIsAddressMatching(&(msg->destSession), dstSession)))
350 eDtlsRet_t ret = CAAdapterNetDtlsEncryptInternal(&(msg->destSession),
351 msg->data, msg->dataLen);
354 OIC_LOG(DEBUG, NET_DTLS_TAG, "CAAdapterNetDtlsEncryptInternal success");
358 OIC_LOG(ERROR, NET_DTLS_TAG, "CAAdapterNetDtlsEncryptInternal failed.");
361 if (u_arraylist_remove(g_caDtlsContext->cacheList, list_index))
364 // Reduce list length by 1 as we removed one element.
369 OIC_LOG(ERROR, NET_DTLS_TAG, "u_arraylist_remove failed.");
375 // Move to the next element
380 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
383 static int32_t CAReadDecryptedPayload(dtls_context_t *context,
389 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
391 VERIFY_NON_NULL_RET(session, NET_DTLS_TAG, "Param Session is NULL", 0);
392 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "Decrypted buf len [%d]", bufLen);
394 stCADtlsAddrInfo_t *addrInfo = (stCADtlsAddrInfo_t *)session;
396 CASecureEndpoint_t sep =
398 { .adapter = CA_ADAPTER_IP, .flags =
399 ((addrInfo->addr.st.ss_family == AF_INET) ? CA_IPV4 : CA_IPV6) | CA_SECURE, .port = 0 },
402 CAConvertAddrToName(&(addrInfo->addr.st), sep.endpoint.addr, &sep.endpoint.port);
404 if (NULL == g_caDtlsContext)
406 OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
411 if ((0 <= type) && (MAX_SUPPORTED_ADAPTERS > type) &&
412 (NULL != g_caDtlsContext->adapterCallbacks[type].recvCallback))
414 // Get identity of the source of packet
415 CASecureEndpoint_t *peerInfo = GetPeerInfo(&sep.endpoint);
418 sep.identity = peerInfo->identity;
421 g_caDtlsContext->adapterCallbacks[type].recvCallback(&sep, buf, bufLen);
425 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "recvCallback Callback or adapter type is wrong [%d]", type);
428 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
432 static int32_t CASendSecureData(dtls_context_t *context,
438 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
440 VERIFY_NON_NULL_RET(session, NET_DTLS_TAG, "Param Session is NULL", -1);
441 VERIFY_NON_NULL_RET(buf, NET_DTLS_TAG, "Param buf is NULL", -1);
445 OIC_LOG(ERROR, NET_DTLS_TAG, "Encrypted Buffer length is equal to zero");
449 stCADtlsAddrInfo_t *addrInfo = (stCADtlsAddrInfo_t *)session;
451 CAEndpoint_t endpoint = {.adapter = CA_DEFAULT_ADAPTER};
453 CAConvertAddrToName(&(addrInfo->addr.st), endpoint.addr, &endpoint.port);
454 endpoint.flags = addrInfo->addr.st.ss_family == AF_INET ? CA_IPV4 : CA_IPV6;
455 endpoint.flags |= CA_SECURE;
456 endpoint.adapter = CA_ADAPTER_IP;
457 endpoint.interface = session->ifindex;
460 //Mutex is not required for g_caDtlsContext. It will be called in same thread.
461 if ((0 <= type) && (MAX_SUPPORTED_ADAPTERS > type) &&
462 (NULL != g_caDtlsContext->adapterCallbacks[type].sendCallback))
464 g_caDtlsContext->adapterCallbacks[type].sendCallback(&endpoint, buf, bufLen);
468 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "send Callback or adapter type is wrong [%d]", type );
471 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
475 static int32_t CAHandleSecureEvent(dtls_context_t *context,
477 dtls_alert_level_t level,
481 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
483 VERIFY_NON_NULL_RET(session, NET_DTLS_TAG, "Param Session is NULL", 0);
485 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "level [%d] code [%u]", level, code);
487 if (!level && (code == DTLS_EVENT_CONNECTED))
489 OIC_LOG(DEBUG, NET_DTLS_TAG, "Received DTLS_EVENT_CONNECTED. Sending Cached data");
490 CASendCachedMsg((stCADtlsAddrInfo_t *)session);
493 if(DTLS_ALERT_LEVEL_FATAL == level && DTLS_ALERT_CLOSE_NOTIFY == code)
495 OIC_LOG(INFO, NET_DTLS_TAG, "Peer closing connection");
497 stCADtlsAddrInfo_t *addrInfo = (stCADtlsAddrInfo_t *)session;
498 char peerAddr[MAX_ADDR_STR_SIZE_CA] = { 0 };
500 CAConvertAddrToName(&(addrInfo->addr.st), peerAddr, &port);
501 CARemovePeerFromPeerInfoList(peerAddr, port);
504 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
509 static int32_t CAGetPskCredentials(dtls_context_t *ctx,
510 const session_t *session,
511 dtls_credentials_type_t type,
512 const unsigned char *desc, size_t descLen,
513 unsigned char *result, size_t resultLen)
515 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
518 if(NULL == ctx || NULL == session || NULL == result)
520 OIC_LOG(ERROR, NET_DTLS_TAG, "CAGetPskCredentials invalid parameters");
524 VERIFY_NON_NULL_RET(g_getCredentialsCallback, NET_DTLS_TAG, "GetCredential callback", -1);
525 VERIFY_NON_NULL_RET(result, NET_DTLS_TAG, "result", -1);
527 CADtlsPskCredsBlob_t *credInfo = NULL;
529 // Retrieve the credentials blob from security module
530 g_getCredentialsCallback(&credInfo);
532 VERIFY_NON_NULL_RET(credInfo, NET_DTLS_TAG, "credInfo is NULL", -1);
533 if(NULL == credInfo->creds)
535 OIC_LOG(DEBUG, NET_DTLS_TAG, "credentials are NULL");
536 memset(credInfo, 0, sizeof(CADtlsPskCredsBlob_t));
541 if ((type == DTLS_PSK_HINT) || (type == DTLS_PSK_IDENTITY))
543 if (DTLS_PSK_ID_LEN <= resultLen)
545 memcpy(result, credInfo->identity, DTLS_PSK_ID_LEN);
546 ret = DTLS_PSK_ID_LEN;
550 if ((type == DTLS_PSK_KEY) && (desc) && (descLen == DTLS_PSK_PSK_LEN))
552 // Check if we have the credentials for the device with which we
553 // are trying to perform a handshake
554 for (uint32_t index = 0; index < credInfo->num; index++)
556 if (memcmp(desc, credInfo->creds[index].id, DTLS_PSK_ID_LEN) == 0)
558 if(NULL != ctx->peers && DTLS_SERVER == ctx->peers->role )
560 // TODO SRM needs identity of the remote end-point with every data packet to
561 // perform access control management. tinyDTLS 'frees' the handshake parameters
562 // data structure when handshake completes. Therefore, currently this is a
563 // workaround to cache remote end-point identity when tinyDTLS asks for PSK.
564 stCADtlsAddrInfo_t *addrInfo = (stCADtlsAddrInfo_t *)session;
565 char peerAddr[MAX_ADDR_STR_SIZE_CA] = { 0 };
567 CAConvertAddrToName(&(addrInfo->addr.st), peerAddr, &port);
569 CAResult_t result = CAAddIdToPeerInfoList(peerAddr, port, desc, descLen);
570 if(CA_STATUS_OK != result )
572 OIC_LOG(ERROR, NET_DTLS_TAG, "Fail to add peer id to gDtlsPeerInfoList");
575 memcpy(result, credInfo->creds[index].psk, DTLS_PSK_PSK_LEN);
576 ret = DTLS_PSK_PSK_LEN;
581 // Erase sensitive data before freeing.
582 memset(credInfo->creds, 0, sizeof(OCDtlsPskCreds) * (credInfo->num));
583 OICFree(credInfo->creds);
585 memset(credInfo, 0, sizeof(CADtlsPskCredsBlob_t));
592 void CADTLSSetAdapterCallbacks(CAPacketReceivedCallback recvCallback,
593 CAPacketSendCallback sendCallback,
594 CATransportAdapter_t type)
596 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
597 ca_mutex_lock(g_dtlsContextMutex);
598 if (NULL == g_caDtlsContext)
600 OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
601 ca_mutex_unlock(g_dtlsContextMutex);
605 if ((0 <= type) && (MAX_SUPPORTED_ADAPTERS > type))
607 // TODO: change the zeros to better values.
608 g_caDtlsContext->adapterCallbacks[0].recvCallback = recvCallback;
609 g_caDtlsContext->adapterCallbacks[0].sendCallback = sendCallback;
612 ca_mutex_unlock(g_dtlsContextMutex);
614 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
617 void CADTLSSetCredentialsCallback(CAGetDTLSCredentialsHandler credCallback)
619 // TODO Does this method needs protection of DtlsContextMutex ?
620 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
621 g_getCredentialsCallback = credCallback;
622 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
625 CAResult_t CADtlsSelectCipherSuite(const dtls_cipher_t cipher)
627 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN CADtlsSelectCipherSuite");
629 ca_mutex_lock(g_dtlsContextMutex);
630 if (NULL == g_caDtlsContext)
632 OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
633 ca_mutex_unlock(g_dtlsContextMutex);
634 return CA_STATUS_FAILED;
636 dtls_select_cipher(g_caDtlsContext->dtlsContext, cipher);
637 ca_mutex_unlock(g_dtlsContextMutex);
639 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "Selected cipher suite is 0x%02X%02X\n",
640 ((uint8_t*)(&cipher))[1], ((uint8_t*)(&cipher))[0]);
641 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT CADtlsSelectCipherSuite");
643 return CA_STATUS_OK ;
646 CAResult_t CADtlsEnableAnonECDHCipherSuite(const bool enable)
648 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN CADtlsEnablesAnonEcdh");
650 ca_mutex_lock(g_dtlsContextMutex);
651 if (NULL == g_caDtlsContext)
653 OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
654 ca_mutex_unlock(g_dtlsContextMutex);
655 return CA_STATUS_FAILED;
657 dtls_enables_anon_ecdh(g_caDtlsContext->dtlsContext,
658 enable == true ? DTLS_CIPHER_ENABLE : DTLS_CIPHER_DISABLE);
659 ca_mutex_unlock(g_dtlsContextMutex);
660 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256 is %s",
661 enable ? "enabled" : "disabled");
663 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT CADtlsEnablesAnonEcdh");
665 return CA_STATUS_OK ;
668 CAResult_t CADtlsInitiateHandshake(const CAEndpoint_t *endpoint)
670 stCADtlsAddrInfo_t dst = { 0 };
672 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN CADtlsInitiateHandshake");
676 return CA_STATUS_INVALID_PARAM;
679 CAConvertNameToAddr(endpoint->addr, endpoint->port, &(dst.addr.st));
681 dst.size = CASizeOfAddrInfo(&dst);
683 ca_mutex_lock(g_dtlsContextMutex);
684 if(NULL == g_caDtlsContext)
686 OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
687 ca_mutex_unlock(g_dtlsContextMutex);
688 return CA_STATUS_FAILED;
691 if(0 > dtls_connect(g_caDtlsContext->dtlsContext, (session_t*)(&dst)))
693 OIC_LOG(ERROR, NET_DTLS_TAG, "Failed to connect");
694 ca_mutex_unlock(g_dtlsContextMutex);
695 return CA_STATUS_FAILED;
698 ca_mutex_unlock(g_dtlsContextMutex);
700 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT CADtlsInitiateHandshake");
705 CAResult_t CADtlsClose(const CAEndpoint_t *endpoint)
707 stCADtlsAddrInfo_t dst = { 0 };
709 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN CADtlsDisconnect");
713 return CA_STATUS_INVALID_PARAM;
716 CAConvertNameToAddr(endpoint->addr, endpoint->port, &(dst.addr.st));
718 dst.size = CASizeOfAddrInfo(&dst);
720 ca_mutex_lock(g_dtlsContextMutex);
721 if (NULL == g_caDtlsContext)
723 OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
724 ca_mutex_unlock(g_dtlsContextMutex);
725 return CA_STATUS_FAILED;
728 if (0 > dtls_close(g_caDtlsContext->dtlsContext, (session_t*)(&dst)))
730 OIC_LOG(ERROR, NET_DTLS_TAG, "Failed to close the session");
731 ca_mutex_unlock(g_dtlsContextMutex);
732 return CA_STATUS_FAILED;
735 ca_mutex_unlock(g_dtlsContextMutex);
737 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT CADtlsDisconnect");
742 CAResult_t CADtlsGenerateOwnerPSK(const CAEndpoint_t *endpoint,
743 const uint8_t* label, const size_t labelLen,
744 const uint8_t* rsrcServerDeviceID, const size_t rsrcServerDeviceIDLen,
745 const uint8_t* provServerDeviceID, const size_t provServerDeviceIDLen,
746 uint8_t* ownerPSK, const size_t ownerPSKSize)
748 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN CADtlsGenerateOwnerPSK");
750 if(!endpoint || !label || 0 == labelLen || !ownerPSK || 0 == ownerPSKSize)
752 return CA_STATUS_INVALID_PARAM;
755 stCADtlsAddrInfo_t dst = { 0 };
757 CAConvertNameToAddr(endpoint->addr, endpoint->port, &(dst.addr.st));
759 dst.size = CASizeOfAddrInfo(&dst);
761 ca_mutex_lock(g_dtlsContextMutex);
762 if (NULL == g_caDtlsContext)
764 OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
765 ca_mutex_unlock(g_dtlsContextMutex);
766 return CA_STATUS_FAILED;
769 if( 0 == dtls_prf_with_current_keyblock(g_caDtlsContext->dtlsContext, (session_t*)(&dst),
770 label, labelLen, rsrcServerDeviceID, rsrcServerDeviceIDLen,
771 provServerDeviceID, provServerDeviceIDLen, ownerPSK, ownerPSKSize))
773 OIC_LOG(ERROR, NET_DTLS_TAG, "Failed to DTLS PRF");
774 ca_mutex_unlock(g_dtlsContextMutex);
775 return CA_STATUS_FAILED;
777 ca_mutex_unlock(g_dtlsContextMutex);
779 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT CADtlsGenerateOwnerPSK");
785 static CADtlsCertCreds_t g_X509Cred = {{0}, 0, 0, {0}, {0}, {0}};
787 static int g_IsX509Init = 0;
791 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN CAInitX509");
792 g_IsX509Init = (OC_STACK_OK == GetDtlsCertCredentials(&g_X509Cred));
794 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT CAInitX509");
795 return !g_IsX509Init;
805 static int CAIsX509Active(struct dtls_context_t *ctx)
811 static int CAGetDeviceKey(struct dtls_context_t *ctx,
812 const session_t *session,
813 const dtls_ecc_key_t **result)
815 OIC_LOG(DEBUG, NET_DTLS_TAG, "CAGetDeviceKey");
816 static dtls_ecc_key_t ecdsa_key = {DTLS_ECDH_CURVE_SECP256R1, NULL, NULL, NULL};
821 VERIFY_SUCCESS(CAInitX509(), 0);
824 ecdsa_key.priv_key = g_X509Cred.devicePrivateKey;
825 *result = &ecdsa_key;
833 CAGetDeviceCertificate(struct dtls_context_t *ctx,
834 const session_t *session,
835 const unsigned char **cert,
838 OIC_LOG(DEBUG, NET_DTLS_TAG, "CAGetDeviceCertificate");
842 VERIFY_SUCCESS(CAInitX509(), 0);
844 *cert = g_X509Cred.certificateChain;
845 *cert_size = g_X509Cred.certificateChainLen;
847 ByteArray ownCert = {g_X509Cred.certificateChain, g_X509Cred.certificateChainLen};
848 PRINT_BYTE_ARRAY("OWN CERT: \n", ownCert);
857 * @brief Gets x and y components of Root Certificate Autority public key
859 * @return 0 on success otherwise a positive error value.
862 static int CAGetRootKey(const unsigned char **ca_pub_x, const unsigned char **ca_pub_y)
864 OIC_LOG(DEBUG, NET_DTLS_TAG, "CAGetRootKey");
868 VERIFY_SUCCESS(CAInitX509(), 0);
870 *ca_pub_x = g_X509Cred.rootPublicKeyX;
871 *ca_pub_y = g_X509Cred.rootPublicKeyY;
879 static int CAVerifyCertificate(struct dtls_context_t *ctx, const session_t *session,
880 const unsigned char *cert, size_t certLen,
881 const unsigned char *x, size_t xLen,
882 const unsigned char *y, size_t yLen)
884 OIC_LOG(DEBUG, NET_DTLS_TAG, "Verify Certificate");
886 ByteArray crtChainDer[MAX_CHAIN_LEN];
887 CertificateX509 crtChain[MAX_CHAIN_LEN];
892 const unsigned char *ca_pub_x;
893 const unsigned char *ca_pub_y;
894 ByteArray certDerCode = BYTE_ARRAY_INITIALIZER;
895 ByteArray caPubKey = BYTE_ARRAY_INITIALIZER;
896 unsigned char ca_pub_key[PUBLIC_KEY_SIZE];
898 CAGetRootKey (&ca_pub_x, &ca_pub_y);
900 certDerCode.data = (uint8_t *)cert;
901 certDerCode.len = certLen;
904 PRINT_BYTE_ARRAY("CERT :\n", certDerCode);
908 caPubKey.len = PUBLIC_KEY_SIZE;
909 caPubKey.data = ca_pub_key;
911 memcpy(caPubKey.data, ca_pub_x, PUBLIC_KEY_SIZE / 2);
912 memcpy(caPubKey.data + PUBLIC_KEY_SIZE / 2, ca_pub_y, PUBLIC_KEY_SIZE / 2);
914 ret = (int) LoadCertificateChain (certDerCode, crtChainDer, &chainLength);
915 VERIFY_SUCCESS(ret, PKI_SUCCESS);
916 ret = (int) ParseCertificateChain (crtChainDer, crtChain, chainLength );
917 VERIFY_SUCCESS(ret, PKI_SUCCESS);
918 ret = (int) CheckCertificateChain (crtChain, chainLength, caPubKey);
919 VERIFY_SUCCESS(ret, PKI_SUCCESS);
921 INC_BYTE_ARRAY(crtChain[0].pubKey, 2);
923 memcpy(x, crtChain[0].pubKey.data, xLen);
924 memcpy(y, crtChain[0].pubKey.data + PUBLIC_KEY_SIZE / 2, yLen);
927 if (NULL != ctx->peers && DTLS_SERVER == ctx->peers->role )
929 stCADtlsAddrInfo_t *addrInfo = (stCADtlsAddrInfo_t *)session;
930 char peerAddr[MAX_ADDR_STR_SIZE_CA] = { 0 };
932 CAConvertAddrToName(&(addrInfo->addr.st), peerAddr, &port);
934 CAResult_t result = CAAddIdToPeerInfoList(peerAddr, port,
935 crtChain[0].subject.data + crtChain[0].subject.len - sizeof(OicUuid_t), sizeof(OicUuid_t));
936 if (CA_STATUS_OK != result )
938 OIC_LOG(ERROR, NET_DTLS_TAG, "Fail to add peer id to gDtlsPeerInfoList");
944 if (ret != 0) OIC_LOG(DEBUG, NET_DTLS_TAG, "Certificate verification FAILED\n");
945 else OIC_LOG(DEBUG, NET_DTLS_TAG, "Certificate verification SUCCESS\n");
954 CAResult_t CAAdapterNetDtlsInit()
956 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
958 // Initialize mutex for DtlsContext
959 if (NULL == g_dtlsContextMutex)
961 g_dtlsContextMutex = ca_mutex_new();
962 VERIFY_NON_NULL_RET(g_dtlsContextMutex, NET_DTLS_TAG, "malloc failed",
963 CA_MEMORY_ALLOC_FAILED);
967 OIC_LOG(ERROR, NET_DTLS_TAG, "CAAdapterNetDtlsInit done already!");
971 // Lock DtlsContext mutex and create DtlsContext
972 ca_mutex_lock(g_dtlsContextMutex);
973 g_caDtlsContext = (stCADtlsContext_t *)OICCalloc(1, sizeof(stCADtlsContext_t));
975 if (NULL == g_caDtlsContext)
977 OIC_LOG(ERROR, NET_DTLS_TAG, "Context malloc failed");
978 ca_mutex_unlock(g_dtlsContextMutex);
979 ca_mutex_free(g_dtlsContextMutex);
980 return CA_MEMORY_ALLOC_FAILED;
984 // Create PeerInfoList and CacheList
985 g_caDtlsContext->peerInfoList = u_arraylist_create();
986 g_caDtlsContext->cacheList = u_arraylist_create();
988 if( (NULL == g_caDtlsContext->peerInfoList) ||
989 (NULL == g_caDtlsContext->cacheList))
991 OIC_LOG(ERROR, NET_DTLS_TAG, "peerInfoList or cacheList initialization failed!");
993 CAFreePeerInfoList();
994 OICFree(g_caDtlsContext);
995 g_caDtlsContext = NULL;
996 ca_mutex_unlock(g_dtlsContextMutex);
997 ca_mutex_free(g_dtlsContextMutex);
998 return CA_STATUS_FAILED;
1001 // Initialize clock, crypto and other global vars in tinyDTLS library
1004 // Create tinydtls Context
1005 g_caDtlsContext->dtlsContext = dtls_new_context(g_caDtlsContext);
1007 if (NULL == g_caDtlsContext->dtlsContext)
1009 OIC_LOG(ERROR, NET_DTLS_TAG, "dtls_new_context failed");
1010 ca_mutex_unlock(g_dtlsContextMutex);
1011 CAAdapterNetDtlsDeInit();
1012 return CA_STATUS_FAILED;
1015 g_caDtlsContext->callbacks.write = CASendSecureData;
1016 g_caDtlsContext->callbacks.read = CAReadDecryptedPayload;
1017 g_caDtlsContext->callbacks.event = CAHandleSecureEvent;
1019 #ifdef __WITH_X509__
1021 if (g_IsX509Init == 0)
1022 #endif //__WITH_X509__
1023 g_caDtlsContext->callbacks.get_psk_info = CAGetPskCredentials;
1024 #ifdef __WITH_X509__
1025 g_caDtlsContext->callbacks.get_x509_key = CAGetDeviceKey;
1026 g_caDtlsContext->callbacks.verify_x509_cert = CAVerifyCertificate;
1027 g_caDtlsContext->callbacks.get_x509_cert = CAGetDeviceCertificate;
1028 g_caDtlsContext->callbacks.is_x509_active = CAIsX509Active;
1029 #endif //__WITH_X509__*
1030 dtls_set_handler(g_caDtlsContext->dtlsContext, &(g_caDtlsContext->callbacks));
1031 ca_mutex_unlock(g_dtlsContextMutex);
1032 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
1033 return CA_STATUS_OK;
1036 void CAAdapterNetDtlsDeInit()
1038 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
1040 VERIFY_NON_NULL_VOID(g_caDtlsContext, NET_DTLS_TAG, "context is NULL");
1041 VERIFY_NON_NULL_VOID(g_dtlsContextMutex, NET_DTLS_TAG, "context mutex is NULL");
1043 //Lock DtlsContext mutex
1044 ca_mutex_lock(g_dtlsContextMutex);
1047 CAFreePeerInfoList();
1050 // De-initialize tinydtls context
1051 dtls_free_context(g_caDtlsContext->dtlsContext);
1052 g_caDtlsContext->dtlsContext = NULL;
1054 // De-initialize DtlsContext
1055 OICFree(g_caDtlsContext);
1056 g_caDtlsContext = NULL;
1058 // Unlock DtlsContext mutex and de-initialize it
1059 ca_mutex_unlock(g_dtlsContextMutex);
1060 ca_mutex_free(g_dtlsContextMutex);
1061 g_dtlsContextMutex = NULL;
1063 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
1066 CAResult_t CAAdapterNetDtlsEncrypt(const CAEndpoint_t *endpoint,
1067 void *data, uint32_t dataLen)
1070 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
1072 VERIFY_NON_NULL_RET(endpoint, NET_DTLS_TAG,"Param remoteAddress is NULL",
1073 CA_STATUS_INVALID_PARAM);
1074 VERIFY_NON_NULL_RET(data, NET_DTLS_TAG, "Param data is NULL" ,
1075 CA_STATUS_INVALID_PARAM);
1079 OIC_LOG_V(ERROR, NET_DTLS_TAG, "dataLen is less than or equal zero [%d]", dataLen);
1080 return CA_STATUS_FAILED;
1083 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "Data to be encrypted dataLen [%d]", dataLen);
1085 stCADtlsAddrInfo_t addrInfo = { 0 };
1087 CAConvertNameToAddr(endpoint->addr, endpoint->port, &(addrInfo.addr.st));
1088 addrInfo.ifIndex = 0;
1089 addrInfo.size = CASizeOfAddrInfo(&addrInfo);
1091 ca_mutex_lock(g_dtlsContextMutex);
1092 if(NULL == g_caDtlsContext)
1094 OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
1095 ca_mutex_unlock(g_dtlsContextMutex);
1096 return CA_STATUS_FAILED;
1099 eDtlsRet_t ret = CAAdapterNetDtlsEncryptInternal(&addrInfo, data, dataLen);
1100 if (ret == DTLS_SESSION_INITIATED)
1102 stCACacheMessage_t *message = (stCACacheMessage_t *)OICCalloc(1, sizeof(stCACacheMessage_t));
1103 if (NULL == message)
1105 OIC_LOG(ERROR, NET_DTLS_TAG, "calloc failed!");
1106 ca_mutex_unlock(g_dtlsContextMutex);
1107 return CA_MEMORY_ALLOC_FAILED;
1110 message->data = (uint8_t *)OICCalloc(dataLen + 1, sizeof(uint8_t));
1111 if (NULL == message->data)
1113 OIC_LOG(ERROR, NET_DTLS_TAG, "calloc failed!");
1115 ca_mutex_unlock(g_dtlsContextMutex);
1116 return CA_MEMORY_ALLOC_FAILED;
1118 memcpy(message->data, data, dataLen);
1119 message->dataLen = dataLen;
1120 message->destSession = addrInfo;
1122 CAResult_t result = CADtlsCacheMsg(message);
1123 if (CA_STATUS_OK != result)
1125 OIC_LOG(DEBUG, NET_DTLS_TAG, "CADtlsCacheMsg failed!");
1126 CAFreeCacheMsg(message);
1128 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "OUT Initiating Dtls session [%d]", result);
1129 ca_mutex_unlock(g_dtlsContextMutex);
1133 ca_mutex_unlock(g_dtlsContextMutex);
1137 OIC_LOG(ERROR, NET_DTLS_TAG, "OUT FAILURE");
1138 return CA_STATUS_FAILED;
1141 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
1142 return CA_STATUS_OK;
1145 CAResult_t CAAdapterNetDtlsDecrypt(const CASecureEndpoint_t *sep,
1146 uint8_t *data, uint32_t dataLen)
1148 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
1149 VERIFY_NON_NULL_RET(sep, NET_DTLS_TAG, "endpoint is NULL" , CA_STATUS_INVALID_PARAM);
1151 stCADtlsAddrInfo_t addrInfo = { 0 };
1153 CAConvertNameToAddr(sep->endpoint.addr, sep->endpoint.port, &(addrInfo.addr.st));
1154 addrInfo.ifIndex = 0;
1155 addrInfo.size = CASizeOfAddrInfo(&addrInfo);
1157 ca_mutex_lock(g_dtlsContextMutex);
1158 if (NULL == g_caDtlsContext)
1160 OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
1161 ca_mutex_unlock(g_dtlsContextMutex);
1162 return CA_STATUS_FAILED;
1165 eDtlsRet_t ret = CAAdapterNetDtlsDecryptInternal(&addrInfo, data, dataLen);
1166 ca_mutex_unlock(g_dtlsContextMutex);
1168 if (DTLS_OK == ret || DTLS_HS_MSG == ret)
1170 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "Successfully Decrypted or Handshake msg recvd [%d]", ret);
1171 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
1172 return CA_STATUS_OK;
1175 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT FAILURE");
1176 return CA_STATUS_FAILED;