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"
28 * @brief Logging tag for module name
30 #define NET_DTLS_TAG "NET_DTLS"
33 * @var g_caDtlsContext
34 * @brief global context which holds dtls context and cache list information.
36 static stCADtlsContext_t *g_caDtlsContext = NULL;
39 * @var g_dtlsContextMutex
40 * @brief Mutex to synchronize access to g_caDtlsContext.
42 static ca_mutex g_dtlsContextMutex = NULL;
45 * @var g_dtlsListMutex
46 * @brief Mutex to synchronize access to DTLS Cache.
48 static ca_mutex g_dtlsListMutex = NULL;
51 * @var g_getCredentialsCallback
52 * @brief callback to get DTLS credentials
54 static CAGetDTLSCredentialsHandler g_getCredentialsCallback = NULL;
56 static eDtlsRet_t CAAdapterNetDtlsEncryptInternal(const stCADtlsAddrInfo_t *dstSession,
57 uint8_t *data, uint32_t dataLen)
59 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
61 VERIFY_NON_NULL_RET(dstSession, NET_DTLS_TAG, "Param dstSession is NULL" , DTLS_FAIL);
62 VERIFY_NON_NULL_RET(data, NET_DTLS_TAG, "Param data is NULL" , DTLS_FAIL);
66 OIC_LOG(ERROR, NET_DTLS_TAG, "Given Packet length is equal to zero.");
70 ca_mutex_lock(g_dtlsContextMutex);
71 if (NULL == g_caDtlsContext)
73 OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
74 ca_mutex_unlock(g_dtlsContextMutex);
78 int retLen = dtls_write(g_caDtlsContext->dtlsContext, (session_t *)dstSession, data,
80 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "dtls_write retun len [%d]", retLen);
81 ca_mutex_unlock(g_dtlsContextMutex);
85 // A new DTLS session was initiated by tinyDTLS library and wait for callback.
86 return DTLS_SESSION_INITIATED;
88 else if (dataLen == retLen)
90 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
93 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT FAILURE");
97 static eDtlsRet_t CAAdapterNetDtlsDecryptInternal(const stCADtlsAddrInfo_t *srcSession,
98 uint8_t *buf, uint32_t bufLen)
100 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
102 VERIFY_NON_NULL_RET(srcSession, NET_DTLS_TAG, "Param srcSession is NULL", DTLS_FAIL);
103 VERIFY_NON_NULL_RET(buf, NET_DTLS_TAG, "Param buf is NULL", DTLS_FAIL);
107 OIC_LOG(ERROR, NET_DTLS_TAG, "Given Packet length is equal to zero.");
111 eDtlsRet_t ret = DTLS_FAIL;
113 /// TODO: how to protect g_caDtlsContext as dtls_handle_message is blocking call
114 if (dtls_handle_message(g_caDtlsContext->dtlsContext, (session_t *)srcSession, buf, bufLen) == 0)
116 OIC_LOG(DEBUG, NET_DTLS_TAG, "dtls_handle_message success");
120 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
124 static void CAFreeCacheMsg(stCACacheMessage_t *msg)
126 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
127 VERIFY_NON_NULL_VOID(msg, NET_DTLS_TAG, "msg");
129 OICFree(msg->destSession);
133 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
136 static void CAClearCacheList()
138 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
139 uint32_t list_index = 0;
140 uint32_t list_length = 0;
141 ca_mutex_lock(g_dtlsListMutex);
142 if (NULL == g_caDtlsContext)
144 OIC_LOG(ERROR, NET_DTLS_TAG, "Dtls Context is NULL");
145 ca_mutex_unlock(g_dtlsListMutex);
148 list_length = u_arraylist_length(g_caDtlsContext->cacheList);
149 for (list_index = 0; list_index < list_length; list_index++)
151 stCACacheMessage_t *msg = (stCACacheMessage_t *)u_arraylist_get(g_caDtlsContext->cacheList,
158 u_arraylist_free(&g_caDtlsContext->cacheList);
159 g_caDtlsContext->cacheList = NULL;
160 ca_mutex_unlock(g_dtlsListMutex);
161 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
164 static CAResult_t CADtlsCacheMsg(stCACacheMessage_t *msg)
166 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
168 ca_mutex_lock(g_dtlsListMutex);
169 if (NULL == g_caDtlsContext)
171 OIC_LOG(ERROR, NET_DTLS_TAG, "Dtls Context is NULL");
172 ca_mutex_unlock(g_dtlsListMutex);
173 return CA_STATUS_FAILED;
176 CAResult_t result = u_arraylist_add(g_caDtlsContext->cacheList, (void *)msg);
177 if (CA_STATUS_OK != result)
179 OIC_LOG(ERROR, NET_DTLS_TAG, "u_arraylist_add failed!");
181 ca_mutex_unlock(g_dtlsListMutex);
183 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
188 static bool CAIsAddressMatching(const stCADtlsAddrInfo_t *a, const stCADtlsAddrInfo_t *b)
190 return (a->size == b->size) &&
191 (a->addr.sa.sa_family == b->addr.sa.sa_family) &&
192 (a->addr.sin.sin_port == b->addr.sin.sin_port) &&
193 memcmp(&a->addr.sin.sin_addr, &b->addr.sin.sin_addr, sizeof(struct in_addr)) == 0;
196 static void CASendCachedMsg(const stCADtlsAddrInfo_t *dstSession)
198 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
199 VERIFY_NON_NULL_VOID(dstSession, NET_DTLS_TAG, "Param dstSession is NULL");
201 uint32_t list_index = 0;
202 uint32_t list_length = 0;
203 ca_mutex_lock(g_dtlsListMutex);
204 list_length = u_arraylist_length(g_caDtlsContext->cacheList);
205 for (list_index = 0; list_index < list_length;)
207 stCACacheMessage_t *msg = (stCACacheMessage_t *)u_arraylist_get(g_caDtlsContext->cacheList,
209 if ((NULL != msg) && (true == CAIsAddressMatching(msg->destSession, dstSession)))
211 eDtlsRet_t ret = CAAdapterNetDtlsEncryptInternal(msg->destSession,
212 msg->data, msg->dataLen);
215 OIC_LOG(DEBUG, NET_DTLS_TAG, "CAAdapterNetDtlsEncryptInternal success");
219 OIC_LOG(ERROR, NET_DTLS_TAG, "CAAdapterNetDtlsEncryptInternal failed.");
222 if (u_arraylist_remove(g_caDtlsContext->cacheList, list_index))
225 // Reduce list length by 1 as we removed one element.
230 OIC_LOG(ERROR, NET_DTLS_TAG, "u_arraylist_remove failed.");
236 // Move to the next element
240 ca_mutex_unlock(g_dtlsListMutex);
242 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
245 static int32_t CAReadDecryptedPayload(dtls_context_t *dtlsContext,
250 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
252 VERIFY_NON_NULL_RET(session, NET_DTLS_TAG, "Param Session is NULL", 0);
253 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "Decrypted buf len [%d]", bufLen);
255 stCADtlsAddrInfo_t *addrInfo = (stCADtlsAddrInfo_t *)session;
257 char *remoteAddress = inet_ntoa(addrInfo->addr.sin.sin_addr);
258 uint32_t port = ntohs(addrInfo->addr.sin.sin_port);
259 eDtlsAdapterType_t type = (eDtlsAdapterType_t)addrInfo->ifIndex;
261 ca_mutex_lock(g_dtlsContextMutex);
262 if (NULL == g_caDtlsContext)
264 OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
265 ca_mutex_unlock(g_dtlsContextMutex);
269 if ((0 <= type) && (MAX_SUPPORTED_ADAPTERS > type) &&
270 (NULL != g_caDtlsContext->adapterCallbacks[type].recvCallback))
272 g_caDtlsContext->adapterCallbacks[type].recvCallback(remoteAddress, port,
277 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "recvCallback Callback or adapter type is wrong [%d]", type);
279 ca_mutex_unlock(g_dtlsContextMutex);
281 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
285 static int32_t CASendSecureData(dtls_context_t *dtlsContext,
290 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
292 VERIFY_NON_NULL_RET(session, NET_DTLS_TAG, "Param Session is NULL", -1);
293 VERIFY_NON_NULL_RET(buf, NET_DTLS_TAG, "Param buf is NULL", -1);
297 OIC_LOG(ERROR, NET_DTLS_TAG, "Encrypted Buffer length is equal to zero");
301 stCADtlsAddrInfo_t *addrInfo = (stCADtlsAddrInfo_t *)session;
303 char *remoteAddress = inet_ntoa(addrInfo->addr.sin.sin_addr);
304 uint16_t port = ntohs(addrInfo->addr.sin.sin_port);
305 eDtlsAdapterType_t type = (eDtlsAdapterType_t)addrInfo->ifIndex;
307 //Mutex is not required for g_caDtlsContext. It will be called in same thread.
309 if ((0 <= type) && (MAX_SUPPORTED_ADAPTERS > type) &&
310 (NULL != g_caDtlsContext->adapterCallbacks[type].sendCallback))
312 sentLen = g_caDtlsContext->adapterCallbacks[type].sendCallback(remoteAddress, port,
317 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "send Callback or adapter type is wrong [%d]", type );
320 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "sent buffer length [%d]", sentLen);
322 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
327 static int32_t CAHandleSecureEvent(dtls_context_t *dtlsContext,
329 dtls_alert_level_t level,
332 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
334 VERIFY_NON_NULL_RET(session, NET_DTLS_TAG, "Param Session is NULL", 0);
336 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "level [%d] code [%u]", level, code);
338 if (!level && (code == DTLS_EVENT_CONNECTED))
340 OIC_LOG(DEBUG, NET_DTLS_TAG, "Received DTLS_EVENT_CONNECTED. Sending Cached data");
341 CASendCachedMsg((stCADtlsAddrInfo_t *)session);
344 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
349 static int32_t CAGetPskCredentials(dtls_context_t *ctx,
350 const session_t *session,
351 dtls_credentials_type_t type,
352 const unsigned char *desc, size_t descLen,
353 unsigned char *result, size_t resultLen)
355 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
359 VERIFY_NON_NULL_RET(g_getCredentialsCallback, NET_DTLS_TAG, "GetCredential callback", -1);
360 VERIFY_NON_NULL_RET(result, NET_DTLS_TAG, "result", -1);
362 CADtlsPskCredsBlob_t *credInfo = NULL;
364 // Retrieve the credentials blob from security module
365 g_getCredentialsCallback(&credInfo);
367 VERIFY_NON_NULL_RET(credInfo, NET_DTLS_TAG, "credInfo is NULL", -1);
368 if(NULL == credInfo->creds)
370 OIC_LOG(DEBUG, NET_DTLS_TAG, "credentials are NULL");
371 memset(credInfo, 0, sizeof(CADtlsPskCredsBlob_t));
376 if ((type == DTLS_PSK_HINT) || (type == DTLS_PSK_IDENTITY))
378 if (DTLS_PSK_ID_LEN <= resultLen)
380 memcpy(result, credInfo->identity, DTLS_PSK_ID_LEN);
381 ret = DTLS_PSK_ID_LEN;
385 if ((type == DTLS_PSK_KEY) && (desc) && (descLen == DTLS_PSK_PSK_LEN))
387 // Check if we have the credentials for the device with which we
388 // are trying to perform a handshake
390 for (index = 0; index < credInfo->num; index++)
392 if (memcmp(desc, credInfo->creds[index].id, DTLS_PSK_ID_LEN) == 0)
394 memcpy(result, credInfo->creds[index].psk, DTLS_PSK_PSK_LEN);
395 ret = DTLS_PSK_PSK_LEN;
400 // Erase sensitive data before freeing.
401 memset(credInfo->creds, 0, sizeof(OCDtlsPskCreds) * (credInfo->num));
402 OICFree(credInfo->creds);
404 memset(credInfo, 0, sizeof(CADtlsPskCredsBlob_t));
411 void CADTLSSetAdapterCallbacks(CAPacketReceivedCallback recvCallback,
412 CAPacketSendCallback sendCallback, eDtlsAdapterType_t type)
414 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
415 ca_mutex_lock(g_dtlsContextMutex);
416 if (NULL == g_caDtlsContext)
418 OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
419 ca_mutex_unlock(g_dtlsContextMutex);
423 if ((0 <= type) && (MAX_SUPPORTED_ADAPTERS > type))
425 g_caDtlsContext->adapterCallbacks[type].recvCallback = recvCallback;
426 g_caDtlsContext->adapterCallbacks[type].sendCallback = sendCallback;
429 ca_mutex_unlock(g_dtlsContextMutex);
431 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
434 void CADTLSSetCredentialsCallback(CAGetDTLSCredentialsHandler credCallback)
436 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
437 g_getCredentialsCallback = credCallback;
438 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
441 CAResult_t CAAdapterNetDtlsInit()
443 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
445 if (NULL == g_dtlsContextMutex)
447 g_dtlsContextMutex = ca_mutex_new();
448 VERIFY_NON_NULL_RET(g_dtlsContextMutex, NET_DTLS_TAG, "malloc failed",
449 CA_MEMORY_ALLOC_FAILED);
453 OIC_LOG(ERROR, NET_DTLS_TAG, "CAAdapterNetDtlsInit done already!");
457 if (NULL == g_dtlsListMutex)
459 g_dtlsListMutex = ca_mutex_new();
460 if (NULL == g_dtlsListMutex)
462 OIC_LOG(ERROR, NET_DTLS_TAG, "g_dtlsListMutex malloc failed");
463 ca_mutex_free(g_dtlsContextMutex);
464 return CA_MEMORY_ALLOC_FAILED;
468 ca_mutex_lock(g_dtlsContextMutex);
469 g_caDtlsContext = (stCADtlsContext_t *)OICCalloc(1, sizeof(stCADtlsContext_t));
471 if (NULL == g_caDtlsContext)
473 OIC_LOG(ERROR, NET_DTLS_TAG, "Context malloc failed");
474 ca_mutex_free(g_dtlsListMutex);
475 ca_mutex_unlock(g_dtlsContextMutex);
476 ca_mutex_free(g_dtlsContextMutex);
477 return CA_MEMORY_ALLOC_FAILED;
480 ca_mutex_lock(g_dtlsListMutex);
481 g_caDtlsContext->cacheList = u_arraylist_create();
483 if (NULL == g_caDtlsContext->cacheList)
485 OIC_LOG(ERROR, NET_DTLS_TAG, "cacheList initialization failed!");
486 ca_mutex_unlock(g_dtlsListMutex);
487 ca_mutex_free(g_dtlsListMutex);
488 ca_mutex_unlock(g_dtlsContextMutex);
489 ca_mutex_free(g_dtlsContextMutex);
490 OICFree(g_caDtlsContext);
491 g_caDtlsContext = NULL;
492 return CA_STATUS_FAILED;
494 ca_mutex_unlock(g_dtlsListMutex);
495 // Initialize clock, crypto and other global vars in tinyDTLS library
498 g_caDtlsContext->dtlsContext = dtls_new_context(g_caDtlsContext);
500 if (NULL == g_caDtlsContext->dtlsContext)
502 OIC_LOG(ERROR, NET_DTLS_TAG, "dtls_new_context failed");
503 ca_mutex_unlock(g_dtlsContextMutex);
504 CAAdapterNetDtlsDeInit();
505 return CA_STATUS_FAILED;
508 g_caDtlsContext->callbacks.write = CASendSecureData;
509 g_caDtlsContext->callbacks.read = CAReadDecryptedPayload;
510 g_caDtlsContext->callbacks.event = CAHandleSecureEvent;
511 g_caDtlsContext->callbacks.get_psk_info = CAGetPskCredentials;
513 dtls_set_handler(g_caDtlsContext->dtlsContext, &(g_caDtlsContext->callbacks));
514 ca_mutex_unlock(g_dtlsContextMutex);
515 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
519 void CAAdapterNetDtlsDeInit()
521 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
523 VERIFY_NON_NULL_VOID(g_caDtlsContext, NET_DTLS_TAG, "context is NULL");
525 ca_mutex_lock(g_dtlsContextMutex);
527 dtls_free_context(g_caDtlsContext->dtlsContext);
528 g_caDtlsContext->dtlsContext = NULL;
529 OICFree(g_caDtlsContext);
530 g_caDtlsContext = NULL;
531 ca_mutex_unlock(g_dtlsContextMutex);
533 ca_mutex_free(g_dtlsContextMutex);
534 g_dtlsContextMutex = NULL;
535 ca_mutex_free(g_dtlsListMutex);
536 g_dtlsListMutex = NULL;
537 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
540 CAResult_t CAAdapterNetDtlsEncrypt(const char *remoteAddress,
545 eDtlsAdapterType_t adapterType)
548 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
550 VERIFY_NON_NULL_RET(remoteAddress, NET_DTLS_TAG,"Param remoteAddress is NULL",CA_STATUS_FAILED);
552 VERIFY_NON_NULL_RET(data, NET_DTLS_TAG, "Param data is NULL" , CA_STATUS_FAILED);
556 OIC_LOG_V(ERROR, NET_DTLS_TAG, "dataLen is less than or equal zero [%d]", dataLen);
557 return CA_STATUS_FAILED;
560 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "Data to be encrypted dataLen [%d]", dataLen);
562 stCADtlsAddrInfo_t *addrInfo = (stCADtlsAddrInfo_t *)OICCalloc(1, sizeof(stCADtlsAddrInfo_t));
564 VERIFY_NON_NULL_RET(addrInfo, NET_DTLS_TAG, "malloc failed" , CA_MEMORY_ALLOC_FAILED);
566 addrInfo->addr.sin.sin_family = AF_INET;
567 addrInfo->addr.sin.sin_port = htons(port);
568 // Conversion from ASCII format to Network format
569 if (inet_aton(remoteAddress, &addrInfo->addr.sin.sin_addr) == 0)
571 OIC_LOG(ERROR, NET_DTLS_TAG, "Failed to convert from ASCII to Network Address");
573 return CA_STATUS_FAILED;
575 addrInfo->size = sizeof(addrInfo->addr);
576 addrInfo->ifIndex = adapterType;
578 eDtlsRet_t ret = CAAdapterNetDtlsEncryptInternal(addrInfo, data, dataLen);
579 if (ret == DTLS_SESSION_INITIATED)
581 stCACacheMessage_t *message = (stCACacheMessage_t *)OICCalloc(1, sizeof(stCACacheMessage_t));
584 OIC_LOG(ERROR, NET_DTLS_TAG, "calloc failed!");
586 return CA_MEMORY_ALLOC_FAILED;
589 message->data = (uint8_t *)OICCalloc(dataLen + 1, sizeof(uint8_t));
590 if (NULL == message->data)
592 OIC_LOG(ERROR, NET_DTLS_TAG, "calloc failed!");
595 return CA_MEMORY_ALLOC_FAILED;
597 memcpy(message->data, data, dataLen);
598 message->dataLen = dataLen;
599 message->destSession = addrInfo;
601 CAResult_t result = CADtlsCacheMsg(message);
602 if (CA_STATUS_OK == result)
611 OIC_LOG(DEBUG, NET_DTLS_TAG, "CADtlsCacheMsg failed!");
612 CAFreeCacheMsg(message);
614 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "OUT Initiating Dtls session [%d]", result);
622 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
626 OIC_LOG(ERROR, NET_DTLS_TAG, "OUT FAILURE");
627 return CA_STATUS_FAILED;
631 CAResult_t CAAdapterNetDtlsDecrypt(const char *remoteAddress,
635 eDtlsAdapterType_t adapterType)
637 OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
639 stCADtlsAddrInfo_t *addrInfo = (stCADtlsAddrInfo_t *)OICCalloc(1, sizeof(stCADtlsAddrInfo_t));
641 VERIFY_NON_NULL_RET(addrInfo, NET_DTLS_TAG, "calloc failed" , CA_MEMORY_ALLOC_FAILED);
643 addrInfo->addr.sin.sin_family = AF_INET;
644 addrInfo->addr.sin.sin_port = htons(port);
646 // Conversion from ASCII format to Network format
647 if (inet_aton(remoteAddress, &addrInfo->addr.sin.sin_addr) == 0)
649 OIC_LOG(ERROR, NET_DTLS_TAG, "Failed to convert from ASCII to Network Address");
651 return CA_STATUS_FAILED;
653 addrInfo->size = sizeof(addrInfo->addr);
654 addrInfo->ifIndex = adapterType;
656 eDtlsRet_t ret = CAAdapterNetDtlsDecryptInternal(addrInfo, data, dataLen);
659 if (DTLS_OK == ret || DTLS_HS_MSG == ret)
661 OIC_LOG_V(DEBUG, NET_DTLS_TAG, "Successfully Decrypted or Handshake msg recvd [%d]", ret);
662 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
666 OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT FAILURE");
667 return CA_STATUS_FAILED;