Prepare for merge. Improved consistency and style.
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / adapter_util / caadapternetdtls.c
1 /******************************************************************
2  *
3  * Copyright 2014 Samsung Electronics All Rights Reserved.
4  *
5  *
6  *
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
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
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.
18  *
19  ******************************************************************/
20 #include "caadapternetdtls.h"
21 #include "cacommon.h"
22 #include "caipinterface.h"
23 #include "dtls.h"
24 #include "oic_malloc.h"
25 #include "oic_string.h"
26 #include "global.h"
27 #include "timer.h"
28 #if defined(HAVE_WINSOCK2_H) && defined(HAVE_WS2TCPIP_H)
29 #include <winsock2.h>
30 #include <ws2tcpip.h>
31 #endif
32 #ifdef HAVE_NETDB_H
33 #include <netdb.h>
34 #endif
35
36 /* tinyDTLS library error code */
37 #define TINY_DTLS_ERROR (-1)
38 /* tinyDTLS library success code */
39 #define TINY_DTLS_SUCCESS (0)
40
41 #ifdef __WITH_X509__
42 #include "pki.h"
43 #include "crl.h"
44 #include "cainterface.h"
45
46 /* lenght of ASN.1 header in DER format
47  * for subject field in X.509 certificate */
48 #define DER_SUBJECT_HEADER_LEN  (9)
49
50 #undef VERIFY_SUCCESS
51 #define VERIFY_SUCCESS(op, successCode) { if ((op) != (successCode)) \
52             {OIC_LOG_V(FATAL, NET_DTLS_TAG, "%s failed!!", #op); goto exit;} }
53 #endif
54
55 /**
56  * @def NET_DTLS_TAG
57  * @brief Logging tag for module name
58  */
59 #define NET_DTLS_TAG "OIC_CA_NET_DTLS"
60
61 /**
62  * @var g_caDtlsContext
63  * @brief global context which holds dtls context and cache list information.
64  */
65 static stCADtlsContext_t *g_caDtlsContext = NULL;
66
67 /**
68  * @var g_dtlsContextMutex
69  * @brief Mutex to synchronize access to g_caDtlsContext.
70  */
71 static ca_mutex g_dtlsContextMutex = NULL;
72
73 /**
74  * @var g_getCredentialsCallback
75  * @brief callback to get DTLS credentials
76  */
77 static CAGetDTLSPskCredentialsHandler g_getCredentialsCallback = NULL;
78
79 /**
80  * @var RETRANSMISSION_TIME
81  * @brief Maximum timeout value (in seconds) to start DTLS retransmission.
82  */
83 #define RETRANSMISSION_TIME 1
84
85 /**
86  * @var g_dtlsHandshakeCallback
87  * @brief callback to deliver the DTLS handshake result
88  */
89 static CAErrorCallback g_dtlsHandshakeCallback = NULL;
90
91 #ifdef __WITH_X509__
92 /**
93  * @var g_getX509CredentialsCallback
94  * @brief callback to get DTLS certificate credentials
95  */
96 static CAGetDTLSX509CredentialsHandler g_getX509CredentialsCallback = NULL;
97 /**
98  * @var g_getCrlCallback
99  * @brief callback to get CRL for DTLS
100  */
101 static CAGetDTLSCrlHandler g_getCrlCallback = NULL;
102 #endif //__WITH_X509__
103
104
105 static CASecureEndpoint_t *GetPeerInfo(const CAEndpoint_t *peer)
106 {
107     uint32_t list_index = 0;
108     uint32_t list_length = 0;
109
110     if(NULL == peer)
111     {
112         OIC_LOG(ERROR, NET_DTLS_TAG, "CAPeerInfoListContains invalid parameters");
113         return NULL;
114     }
115
116     CASecureEndpoint_t *peerInfo = NULL;
117     list_length = u_arraylist_length(g_caDtlsContext->peerInfoList);
118     for (list_index = 0; list_index < list_length; list_index++)
119     {
120         peerInfo = (CASecureEndpoint_t *)u_arraylist_get(g_caDtlsContext->peerInfoList, list_index);
121         if (NULL == peerInfo)
122         {
123             continue;
124         }
125
126         if((0 == strncmp(peer->addr, peerInfo->endpoint.addr, MAX_ADDR_STR_SIZE_CA)) &&
127                 (peer->port == peerInfo->endpoint.port))
128         {
129             return peerInfo;
130         }
131     }
132     return NULL;
133 }
134
135 static CAResult_t CAAddIdToPeerInfoList(const char *peerAddr, uint32_t port,
136         const unsigned char *id, uint16_t id_length)
137 {
138     if(NULL == peerAddr
139        || NULL == id
140        || 0 == port
141        || 0 == id_length
142        || CA_MAX_ENDPOINT_IDENTITY_LEN < id_length)
143     {
144         OIC_LOG(ERROR, NET_DTLS_TAG, "CAAddIdToPeerInfoList invalid parameters");
145         return CA_STATUS_INVALID_PARAM;
146     }
147
148     CASecureEndpoint_t *peer = (CASecureEndpoint_t *)OICCalloc(1, sizeof (CASecureEndpoint_t));
149     if (NULL == peer)
150     {
151         OIC_LOG(ERROR, NET_DTLS_TAG, "peerInfo malloc failed!");
152         return CA_MEMORY_ALLOC_FAILED;
153     }
154
155     OICStrcpy(peer->endpoint.addr, sizeof(peer->endpoint.addr), peerAddr);
156     peer->endpoint.port = port;
157
158     memcpy(peer->identity.id, id, id_length);
159     peer->identity.id_length = id_length;
160
161     if (NULL != GetPeerInfo(&peer->endpoint))
162     {
163         OIC_LOG(ERROR, NET_DTLS_TAG, "CAAddIdToPeerInfoList peer already exist");
164         OICFree(peer);
165         return CA_STATUS_FAILED;
166     }
167
168     bool result = u_arraylist_add(g_caDtlsContext->peerInfoList, (void *)peer);
169     if (!result)
170     {
171         OIC_LOG(ERROR, NET_DTLS_TAG, "u_arraylist_add failed!");
172         OICFree(peer);
173         return CA_STATUS_FAILED;
174     }
175
176     return CA_STATUS_OK;
177 }
178
179 static void CAFreePeerInfoList()
180 {
181     uint32_t list_length = u_arraylist_length(g_caDtlsContext->peerInfoList);
182     for (uint32_t list_index = 0; list_index < list_length; list_index++)
183     {
184         CAEndpoint_t *peerInfo = (CAEndpoint_t *)u_arraylist_get(
185                                      g_caDtlsContext->peerInfoList, list_index);
186         OICFree(peerInfo);
187     }
188     u_arraylist_free(&(g_caDtlsContext->peerInfoList));
189     g_caDtlsContext->peerInfoList = NULL;
190 }
191
192 static void CARemovePeerFromPeerInfoList(const char * addr, uint16_t port)
193 {
194     if (NULL == addr || 0 >= port)
195     {
196         OIC_LOG(ERROR, NET_DTLS_TAG, "CADTLSGetPeerPSKId invalid parameters");
197         return;
198     }
199
200     uint32_t list_length = u_arraylist_length(g_caDtlsContext->peerInfoList);
201     for (uint32_t list_index = 0; list_index < list_length; list_index++)
202     {
203         CAEndpoint_t *peerInfo = (CAEndpoint_t *)u_arraylist_get(
204                                 g_caDtlsContext->peerInfoList,list_index);
205         if (NULL == peerInfo)
206         {
207             continue;
208         }
209         if((0 == strncmp(addr, peerInfo->addr, MAX_ADDR_STR_SIZE_CA)) &&
210                 (port == peerInfo->port))
211         {
212             OICFree(u_arraylist_remove(g_caDtlsContext->peerInfoList, list_index));
213             return;
214         }
215     }
216 }
217
218 static int CASizeOfAddrInfo(stCADtlsAddrInfo_t *addrInfo)
219 {
220     VERIFY_NON_NULL_RET(addrInfo, NET_DTLS_TAG, "addrInfo is NULL" , DTLS_FAIL);
221
222     switch (addrInfo->addr.st.ss_family)
223     {
224     case AF_INET:
225         {
226             return sizeof (struct sockaddr_in);
227         }
228     case AF_INET6:
229         {
230             return sizeof (struct sockaddr_in6);
231         }
232     default:
233         {
234             break;
235         }
236     }
237     return sizeof (struct sockaddr_storage);
238 }
239
240 static eDtlsRet_t CAAdapterNetDtlsEncryptInternal(const stCADtlsAddrInfo_t *dstSession,
241         uint8_t *data, uint32_t dataLen)
242 {
243     OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
244
245     VERIFY_NON_NULL_RET(dstSession, NET_DTLS_TAG, "Param dstSession is NULL" , DTLS_FAIL);
246     VERIFY_NON_NULL_RET(data, NET_DTLS_TAG, "Param data is NULL" , DTLS_FAIL);
247
248     if (0 == dataLen)
249     {
250         OIC_LOG(ERROR, NET_DTLS_TAG, "Given Packet length is equal to zero.");
251         return DTLS_FAIL;
252     }
253
254     if (NULL == g_caDtlsContext)
255     {
256         OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
257         return DTLS_FAIL;
258     }
259
260     int retLen = dtls_write(g_caDtlsContext->dtlsContext, (session_t *)dstSession, data,
261                                 dataLen);
262     OIC_LOG_V(DEBUG, NET_DTLS_TAG, "dtls_write retun len [%d]", retLen);
263     if (retLen < 0)
264     {
265         OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT FAILURE");
266         return DTLS_FAIL;
267     }
268     if (0 == retLen)
269     {
270         // A new DTLS session was initiated by tinyDTLS library and wait for callback.
271         return DTLS_SESSION_INITIATED;
272     }
273     else if (dataLen != (uint32_t)retLen)
274     {
275         OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT FAILURE");
276         return DTLS_FAIL;
277     }
278     OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
279     return DTLS_OK;
280 }
281
282 static eDtlsRet_t CAAdapterNetDtlsDecryptInternal(const stCADtlsAddrInfo_t *srcSession,
283         uint8_t *buf, uint32_t bufLen)
284 {
285     OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
286
287     VERIFY_NON_NULL_RET(srcSession, NET_DTLS_TAG, "Param srcSession is NULL", DTLS_FAIL);
288     VERIFY_NON_NULL_RET(buf, NET_DTLS_TAG, "Param buf is NULL", DTLS_FAIL);
289
290     if (0 == bufLen)
291     {
292         OIC_LOG(ERROR, NET_DTLS_TAG, "Given Packet length is equal to zero.");
293         return DTLS_FAIL;
294     }
295
296     eDtlsRet_t ret = DTLS_FAIL;
297
298     if (dtls_handle_message(g_caDtlsContext->dtlsContext, (session_t *)srcSession, buf, bufLen) == 0)
299     {
300         OIC_LOG(DEBUG, NET_DTLS_TAG, "dtls_handle_message success");
301         ret = DTLS_OK;
302     }
303
304     OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
305     return ret;
306 }
307
308 static void CAFreeCacheMsg(stCACacheMessage_t *msg)
309 {
310     OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
311     VERIFY_NON_NULL_VOID(msg, NET_DTLS_TAG, "msg");
312
313     OICFree(msg->data);
314     OICFree(msg);
315
316     OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
317 }
318
319 static void CAClearCacheList()
320 {
321     OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
322     uint32_t list_index = 0;
323     uint32_t list_length = 0;
324     if (NULL == g_caDtlsContext)
325     {
326         OIC_LOG(ERROR, NET_DTLS_TAG, "Dtls Context is NULL");
327         return;
328     }
329     list_length = u_arraylist_length(g_caDtlsContext->cacheList);
330     for (list_index = 0; list_index < list_length; list_index++)
331     {
332         stCACacheMessage_t *msg = (stCACacheMessage_t *)u_arraylist_get(g_caDtlsContext->cacheList,
333                                   list_index);
334         if (msg != NULL)
335         {
336             CAFreeCacheMsg(msg);
337         }
338     }
339     u_arraylist_free(&g_caDtlsContext->cacheList);
340     g_caDtlsContext->cacheList = NULL;
341     OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
342 }
343
344 static CAResult_t CADtlsCacheMsg(stCACacheMessage_t *msg)
345 {
346     OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
347
348     if (NULL == g_caDtlsContext)
349     {
350         OIC_LOG(ERROR, NET_DTLS_TAG, "Dtls Context is NULL");
351         return CA_STATUS_FAILED;
352     }
353
354     bool result = u_arraylist_add(g_caDtlsContext->cacheList, (void *)msg);
355     if (!result)
356     {
357         OIC_LOG(ERROR, NET_DTLS_TAG, "u_arraylist_add failed!");
358         return CA_STATUS_FAILED;
359     }
360
361     OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
362     return CA_STATUS_OK;
363 }
364
365
366 static bool CAIsAddressMatching(const stCADtlsAddrInfo_t *a,  const stCADtlsAddrInfo_t *b)
367 {
368     if (a->size != b->size)
369     {
370         return false;
371     }
372     if (memcmp(&a->addr, &b->addr, a->size))
373     {
374         return false;
375     }
376     return true;
377 }
378
379 static void CASendCachedMsg(const stCADtlsAddrInfo_t *dstSession)
380 {
381     OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
382     VERIFY_NON_NULL_VOID(dstSession, NET_DTLS_TAG, "Param dstSession is NULL");
383
384     uint32_t list_index = 0;
385     uint32_t list_length = 0;
386     list_length = u_arraylist_length(g_caDtlsContext->cacheList);
387     for (list_index = 0; list_index < list_length;)
388     {
389         stCACacheMessage_t *msg = (stCACacheMessage_t *)u_arraylist_get(g_caDtlsContext->cacheList,
390                                   list_index);
391         if ((NULL != msg) && (true == CAIsAddressMatching(&(msg->destSession), dstSession)))
392         {
393             eDtlsRet_t ret = CAAdapterNetDtlsEncryptInternal(&(msg->destSession),
394                              msg->data, msg->dataLen);
395             if (ret == DTLS_OK)
396             {
397                 OIC_LOG(DEBUG, NET_DTLS_TAG, "CAAdapterNetDtlsEncryptInternal success");
398             }
399             else
400             {
401                 OIC_LOG(ERROR, NET_DTLS_TAG, "CAAdapterNetDtlsEncryptInternal failed.");
402             }
403
404             if (u_arraylist_remove(g_caDtlsContext->cacheList, list_index))
405             {
406                 CAFreeCacheMsg(msg);
407                 // Reduce list length by 1 as we removed one element.
408                 list_length--;
409             }
410             else
411             {
412                 OIC_LOG(ERROR, NET_DTLS_TAG, "u_arraylist_remove failed.");
413                 break;
414             }
415         }
416         else
417         {
418             // Move to the next element
419             ++list_index;
420         }
421     }
422
423     OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
424 }
425
426 static int32_t CAReadDecryptedPayload(dtls_context_t *context,
427                                       session_t *session,
428                                       uint8_t *buf,
429                                       size_t bufLen )
430 {
431     (void)context;
432     OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
433
434     VERIFY_NON_NULL_RET(session, NET_DTLS_TAG, "Param Session is NULL", 0);
435     OIC_LOG_V(DEBUG, NET_DTLS_TAG, "Decrypted buf len [%zu]", bufLen);
436
437     stCADtlsAddrInfo_t *addrInfo = (stCADtlsAddrInfo_t *)session;
438
439     CASecureEndpoint_t sep =
440     { .endpoint =
441     { .adapter = CA_ADAPTER_IP, .flags =
442             ((addrInfo->addr.st.ss_family == AF_INET) ? CA_IPV4 : CA_IPV6) | CA_SECURE, .port = 0 },
443             .identity =
444             { 0 } };
445     CAConvertAddrToName(&(addrInfo->addr.st), addrInfo->size, sep.endpoint.addr, &sep.endpoint.port);
446
447     if (NULL == g_caDtlsContext)
448     {
449         OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
450         return TINY_DTLS_ERROR;
451     }
452
453     int type = 0;
454     if ((0 <= type) && (MAX_SUPPORTED_ADAPTERS > type) &&
455         (NULL != g_caDtlsContext->adapterCallbacks[type].recvCallback))
456     {
457         // Get identity of the source of packet
458         CASecureEndpoint_t *peerInfo = GetPeerInfo(&sep.endpoint);
459         if (peerInfo)
460         {
461             sep.identity = peerInfo->identity;
462         }
463
464         g_caDtlsContext->adapterCallbacks[type].recvCallback(&sep, buf, bufLen);
465     }
466     else
467     {
468         OIC_LOG_V(DEBUG, NET_DTLS_TAG, "recvCallback Callback or adapter type is wrong [%d]", type);
469     }
470
471     OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
472     return TINY_DTLS_SUCCESS;
473 }
474
475 static int32_t CASendSecureData(dtls_context_t *context,
476                                 session_t *session,
477                                 uint8_t *buf,
478                                 size_t bufLen)
479 {
480     (void)context;
481     OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
482
483     VERIFY_NON_NULL_RET(session, NET_DTLS_TAG, "Param Session is NULL", -1);
484     VERIFY_NON_NULL_RET(buf, NET_DTLS_TAG, "Param buf is NULL", -1);
485
486     if (0 == bufLen)
487     {
488         OIC_LOG(ERROR, NET_DTLS_TAG, "Encrypted Buffer length is equal to zero");
489         return 0;
490     }
491
492     stCADtlsAddrInfo_t *addrInfo = (stCADtlsAddrInfo_t *)session;
493
494     CAEndpoint_t endpoint = {.adapter = CA_DEFAULT_ADAPTER};
495
496     CAConvertAddrToName(&(addrInfo->addr.st), addrInfo->size, endpoint.addr, &endpoint.port);
497     endpoint.flags = addrInfo->addr.st.ss_family == AF_INET ? CA_IPV4 : CA_IPV6;
498     endpoint.flags |= CA_SECURE;
499     endpoint.adapter = CA_ADAPTER_IP;
500     endpoint.ifindex = session->ifindex;
501     int type = 0;
502
503     //Mutex is not required for g_caDtlsContext. It will be called in same thread.
504     if ((0 <= type) && (MAX_SUPPORTED_ADAPTERS > type) &&
505         (NULL != g_caDtlsContext->adapterCallbacks[type].sendCallback))
506     {
507         g_caDtlsContext->adapterCallbacks[type].sendCallback(&endpoint, buf, bufLen);
508     }
509     else
510     {
511         OIC_LOG_V(DEBUG, NET_DTLS_TAG, "send Callback or adapter type is wrong [%d]", type );
512     }
513
514     OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
515     return bufLen;
516 }
517
518 static int32_t CAHandleSecureEvent(dtls_context_t *context,
519                                    session_t *session,
520                                    dtls_alert_level_t level,
521                                    unsigned short code)
522 {
523     (void)context;
524     OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
525
526     VERIFY_NON_NULL_RET(session, NET_DTLS_TAG, "Param Session is NULL", 0);
527
528     OIC_LOG_V(DEBUG, NET_DTLS_TAG, "level [%d] code [%u]\n", level, code);
529
530     CAEndpoint_t endpoint = {.adapter=CA_DEFAULT_ADAPTER};
531     CAErrorInfo_t errorInfo = {.result=CA_STATUS_OK};
532
533     stCADtlsAddrInfo_t *addrInfo = (stCADtlsAddrInfo_t *)session;
534     char peerAddr[MAX_ADDR_STR_SIZE_CA] = { 0 };
535     uint16_t port = 0;
536     CAConvertAddrToName(&(addrInfo->addr.st), addrInfo->size, peerAddr, &port);
537
538     if (!level && (DTLS_EVENT_CONNECTED == code))
539     {
540         OIC_LOG(DEBUG, NET_DTLS_TAG, "Received DTLS_EVENT_CONNECTED. Sending Cached data");
541
542         if(g_dtlsHandshakeCallback)
543         {
544             OICStrcpy(endpoint.addr, MAX_ADDR_STR_SIZE_CA, peerAddr);
545             endpoint.port = port;
546             errorInfo.result = CA_STATUS_OK;
547             g_dtlsHandshakeCallback(&endpoint, &errorInfo);
548         }
549
550         CASendCachedMsg((stCADtlsAddrInfo_t *)session);
551     }
552     else if(DTLS_ALERT_LEVEL_FATAL == level && DTLS_ALERT_DECRYPT_ERROR == code)
553     {
554         if(g_dtlsHandshakeCallback)
555         {
556             OICStrcpy(endpoint.addr, MAX_ADDR_STR_SIZE_CA, peerAddr);
557             endpoint.addr[MAX_ADDR_STR_SIZE_CA - 1] = '\0';
558             endpoint.port = port;
559             errorInfo.result = CA_DTLS_AUTHENTICATION_FAILURE;
560             g_dtlsHandshakeCallback(&endpoint, &errorInfo);
561         }
562     }
563     else if(DTLS_ALERT_LEVEL_FATAL == level && DTLS_ALERT_CLOSE_NOTIFY == code)
564     {
565         OIC_LOG(INFO, NET_DTLS_TAG, "Peer closing connection");
566         CARemovePeerFromPeerInfoList(peerAddr, port);
567     }
568     else if(DTLS_ALERT_LEVEL_FATAL == level && DTLS_ALERT_HANDSHAKE_FAILURE == code)
569     {
570         OIC_LOG(INFO, NET_DTLS_TAG, "Failed to DTLS handshake, the peer will be removed.");
571         CARemovePeerFromPeerInfoList(peerAddr, port);
572     }
573
574     OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
575     return TINY_DTLS_SUCCESS;
576 }
577
578
579 static int32_t CAGetPskCredentials(dtls_context_t *ctx,
580                                    const session_t *session,
581                                    dtls_credentials_type_t type,
582                                    const unsigned char *desc, size_t descLen,
583                                    unsigned char *result, size_t resultLen)
584 {
585     OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
586
587     int32_t ret = TINY_DTLS_ERROR;
588     if(NULL == ctx || NULL == session || NULL == result)
589     {
590         OIC_LOG(ERROR, NET_DTLS_TAG, "CAGetPskCredentials invalid parameters");
591         return ret;
592     }
593
594     VERIFY_NON_NULL_RET(g_getCredentialsCallback, NET_DTLS_TAG, "GetCredential callback", -1);
595
596     // Retrieve the credentials blob from security module
597     ret =  g_getCredentialsCallback(type, desc, descLen, result, resultLen);
598
599     if (ret > 0)
600     {
601         // TODO SRM needs identity of the remote end-point with every data packet to
602         // perform access control management. tinyDTLS 'frees' the handshake parameters
603         // data structure when handshake completes. Therefore, currently this is a
604         // workaround to cache remote end-point identity when tinyDTLS asks for PSK.
605         stCADtlsAddrInfo_t *addrInfo = (stCADtlsAddrInfo_t *)session;
606         char peerAddr[MAX_ADDR_STR_SIZE_CA] = { 0 };
607         uint16_t port = 0;
608         CAConvertAddrToName(&(addrInfo->addr.st), addrInfo->size, peerAddr, &port);
609
610         if(CA_STATUS_OK != CAAddIdToPeerInfoList(peerAddr, port, desc, descLen) )
611         {
612             OIC_LOG(ERROR, NET_DTLS_TAG, "Fail to add peer id to gDtlsPeerInfoList");
613         }
614     }
615
616     return ret;
617 }
618
619 void CADTLSSetAdapterCallbacks(CAPacketReceivedCallback recvCallback,
620                                CAPacketSendCallback sendCallback,
621                                CATransportAdapter_t type)
622 {
623     OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
624     ca_mutex_lock(g_dtlsContextMutex);
625     if (NULL == g_caDtlsContext)
626     {
627         OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
628         ca_mutex_unlock(g_dtlsContextMutex);
629         return;
630     }
631
632     if ((0 <= type) && (MAX_SUPPORTED_ADAPTERS > type))
633     {
634         // TODO: change the zeros to better values.
635         g_caDtlsContext->adapterCallbacks[0].recvCallback = recvCallback;
636         g_caDtlsContext->adapterCallbacks[0].sendCallback = sendCallback;
637     }
638
639     ca_mutex_unlock(g_dtlsContextMutex);
640
641     OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
642 }
643
644 void CADTLSSetHandshakeCallback(CAErrorCallback dtlsHandshakeCallback)
645 {
646     OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
647     g_dtlsHandshakeCallback = dtlsHandshakeCallback;
648     OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
649 }
650
651 void CADTLSSetCredentialsCallback(CAGetDTLSPskCredentialsHandler credCallback)
652 {
653     // TODO Does this method needs protection of DtlsContextMutex ?
654     OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
655     g_getCredentialsCallback = credCallback;
656     OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
657 }
658
659 #ifdef __WITH_X509__
660 void CADTLSSetX509CredentialsCallback(CAGetDTLSX509CredentialsHandler credCallback)
661 {
662     OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
663     g_getX509CredentialsCallback = credCallback;
664     OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
665 }
666 void CADTLSSetCrlCallback(CAGetDTLSCrlHandler crlCallback)
667 {
668     // TODO Does this method needs protection of DtlsContextMutex ?
669     OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
670     g_getCrlCallback = crlCallback;
671     OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
672 }
673 #endif // __WITH_X509__
674
675 CAResult_t CADtlsSelectCipherSuite(const dtls_cipher_t cipher)
676 {
677     OIC_LOG(DEBUG, NET_DTLS_TAG, "IN CADtlsSelectCipherSuite");
678
679     ca_mutex_lock(g_dtlsContextMutex);
680     if (NULL == g_caDtlsContext)
681     {
682         OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
683         ca_mutex_unlock(g_dtlsContextMutex);
684         return CA_STATUS_FAILED;
685     }
686     dtls_select_cipher(g_caDtlsContext->dtlsContext, cipher);
687     ca_mutex_unlock(g_dtlsContextMutex);
688
689     OIC_LOG_V(DEBUG, NET_DTLS_TAG, "Selected cipher suite is 0x%02X%02X\n",
690         ((uint8_t*)(&cipher))[1], ((uint8_t*)(&cipher))[0]);
691     OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT CADtlsSelectCipherSuite");
692
693     return CA_STATUS_OK ;
694 }
695
696 CAResult_t CADtlsEnableAnonECDHCipherSuite(const bool enable)
697 {
698     OIC_LOG(DEBUG, NET_DTLS_TAG, "IN CADtlsEnablesAnonEcdh");
699
700     ca_mutex_lock(g_dtlsContextMutex);
701     if (NULL == g_caDtlsContext)
702     {
703         OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
704         ca_mutex_unlock(g_dtlsContextMutex);
705         return CA_STATUS_FAILED;
706     }
707     dtls_enables_anon_ecdh(g_caDtlsContext->dtlsContext,
708         enable == true ? DTLS_CIPHER_ENABLE : DTLS_CIPHER_DISABLE);
709     ca_mutex_unlock(g_dtlsContextMutex);
710     OIC_LOG_V(DEBUG, NET_DTLS_TAG, "TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256  is %s",
711         enable ? "enabled" : "disabled");
712
713     OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT CADtlsEnablesAnonEcdh");
714
715     return CA_STATUS_OK ;
716 }
717
718 CAResult_t CADtlsInitiateHandshake(const CAEndpoint_t *endpoint)
719 {
720     stCADtlsAddrInfo_t dst = { 0 };
721
722     OIC_LOG(DEBUG, NET_DTLS_TAG, "IN CADtlsInitiateHandshake");
723
724     if(!endpoint)
725     {
726         return CA_STATUS_INVALID_PARAM;
727     }
728
729     CAConvertNameToAddr(endpoint->addr, endpoint->port, &(dst.addr.st));
730     dst.ifIndex = 0;
731     dst.size = CASizeOfAddrInfo(&dst);
732
733     ca_mutex_lock(g_dtlsContextMutex);
734     if(NULL == g_caDtlsContext)
735     {
736         OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
737         ca_mutex_unlock(g_dtlsContextMutex);
738         return CA_STATUS_FAILED;
739     }
740
741     if(0 > dtls_connect(g_caDtlsContext->dtlsContext, (session_t*)(&dst)))
742     {
743         OIC_LOG(ERROR, NET_DTLS_TAG, "Failed to connect");
744         ca_mutex_unlock(g_dtlsContextMutex);
745         return CA_STATUS_FAILED;
746     }
747
748     ca_mutex_unlock(g_dtlsContextMutex);
749
750     OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT CADtlsInitiateHandshake");
751
752     return CA_STATUS_OK;
753 }
754
755 CAResult_t CADtlsClose(const CAEndpoint_t *endpoint)
756 {
757     stCADtlsAddrInfo_t dst = { 0 };
758
759     OIC_LOG(DEBUG, NET_DTLS_TAG, "IN CADtlsDisconnect");
760
761     if(!endpoint)
762     {
763         return CA_STATUS_INVALID_PARAM;
764     }
765
766     CAConvertNameToAddr(endpoint->addr, endpoint->port, &(dst.addr.st));
767     dst.ifIndex = 0;
768     dst.size = CASizeOfAddrInfo(&dst);
769
770     ca_mutex_lock(g_dtlsContextMutex);
771     if (NULL == g_caDtlsContext)
772     {
773         OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
774         ca_mutex_unlock(g_dtlsContextMutex);
775         return CA_STATUS_FAILED;
776     }
777
778     if (0 > dtls_close(g_caDtlsContext->dtlsContext, (session_t*)(&dst)))
779     {
780         OIC_LOG(ERROR, NET_DTLS_TAG, "Failed to close the session");
781         ca_mutex_unlock(g_dtlsContextMutex);
782         return CA_STATUS_FAILED;
783     }
784
785     ca_mutex_unlock(g_dtlsContextMutex);
786
787     OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT CADtlsDisconnect");
788
789     return CA_STATUS_OK;
790 }
791
792 CAResult_t CADtlsGenerateOwnerPSK(const CAEndpoint_t *endpoint,
793                     const uint8_t* label, const size_t labelLen,
794                     const uint8_t* rsrcServerDeviceID, const size_t rsrcServerDeviceIDLen,
795                     const uint8_t* provServerDeviceID, const size_t provServerDeviceIDLen,
796                     uint8_t* ownerPSK, const size_t ownerPSKSize)
797 {
798     OIC_LOG(DEBUG, NET_DTLS_TAG, "IN CADtlsGenerateOwnerPSK");
799
800     if(!endpoint || !label || 0 == labelLen || !ownerPSK || 0 == ownerPSKSize)
801     {
802         return CA_STATUS_INVALID_PARAM;
803     }
804
805     stCADtlsAddrInfo_t dst = { 0 };
806
807     CAConvertNameToAddr(endpoint->addr, endpoint->port, &(dst.addr.st));
808     dst.ifIndex = 0;
809     dst.size = CASizeOfAddrInfo(&dst);
810
811     ca_mutex_lock(g_dtlsContextMutex);
812     if (NULL == g_caDtlsContext)
813     {
814         OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
815         ca_mutex_unlock(g_dtlsContextMutex);
816         return CA_STATUS_FAILED;
817     }
818
819     if( 0 == dtls_prf_with_current_keyblock(g_caDtlsContext->dtlsContext, (session_t*)(&dst),
820                  label, labelLen, rsrcServerDeviceID, rsrcServerDeviceIDLen,
821                  provServerDeviceID, provServerDeviceIDLen, ownerPSK, ownerPSKSize))
822     {
823         OIC_LOG(ERROR, NET_DTLS_TAG, "Failed to DTLS PRF");
824         ca_mutex_unlock(g_dtlsContextMutex);
825         return CA_STATUS_FAILED;
826     }
827     ca_mutex_unlock(g_dtlsContextMutex);
828
829     OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT CADtlsGenerateOwnerPSK");
830
831     return CA_STATUS_OK;
832 }
833
834 #ifdef __WITH_X509__
835 static CADtlsX509Creds_t g_X509Cred = {{0}, 0, 0, {0}, {0}, {0}};
836
837 int CAInitX509()
838 {
839     OIC_LOG(DEBUG, NET_DTLS_TAG, "IN CAInitX509");
840     VERIFY_NON_NULL_RET(g_getX509CredentialsCallback, NET_DTLS_TAG, "GetX509Credential callback", -1);
841     int isX509Init = (0 == g_getX509CredentialsCallback(&g_X509Cred));
842
843     if (isX509Init)
844     {
845         uint8_t crlData[CRL_MAX_LEN] = {0};
846         ByteArray crlArray = {crlData, CRL_MAX_LEN};
847         g_getCrlCallback(&crlArray);
848         if (crlArray.len > 0)
849         {
850             uint8_t keyData[PUBLIC_KEY_SIZE] = {0};
851             CertificateList crl = CRL_INITIALIZER;
852             ByteArray rootPubKey = {keyData, PUBLIC_KEY_SIZE};
853             memcpy(keyData, g_X509Cred.rootPublicKeyX, PUBLIC_KEY_SIZE / 2);
854             memcpy(keyData + PUBLIC_KEY_SIZE / 2, g_X509Cred.rootPublicKeyY, PUBLIC_KEY_SIZE / 2);
855             DecodeCertificateList(crlArray, &crl, rootPubKey);
856         }
857     }
858
859     OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT CAInitX509");
860     if (isX509Init)
861     {
862         return 0;
863     }
864     else
865     {
866         return 1;
867     }
868 }
869
870
871 static int CAIsX509Active(struct dtls_context_t *ctx)
872 {
873     (void)ctx;
874     return TINY_DTLS_SUCCESS;
875 }
876
877 static int CAGetDeviceKey(struct dtls_context_t *ctx,
878                        const session_t *session,
879                        const dtls_ecc_key_t **result)
880 {
881     OIC_LOG(DEBUG, NET_DTLS_TAG, "CAGetDeviceKey");
882     static dtls_ecc_key_t ecdsa_key = {DTLS_ECDH_CURVE_SECP256R1, NULL, NULL, NULL};
883
884     int ret = TINY_DTLS_ERROR;
885     VERIFY_SUCCESS(CAInitX509(), 0);
886
887     ecdsa_key.priv_key = g_X509Cred.devicePrivateKey;
888     *result = &ecdsa_key;
889
890     ret = TINY_DTLS_SUCCESS;
891 exit:
892     return ret;
893 }
894
895 static int
896 CAGetDeviceCertificate(struct dtls_context_t *ctx,
897                     const session_t *session,
898                     const unsigned char **cert,
899                     size_t *cert_size)
900 {
901     OIC_LOG(DEBUG, NET_DTLS_TAG, "CAGetDeviceCertificate");
902     int ret = TINY_DTLS_ERROR;
903
904     VERIFY_SUCCESS(CAInitX509(), 0);
905
906     *cert = g_X509Cred.certificateChain;
907     *cert_size = g_X509Cred.certificateChainLen;
908 #ifdef X509_DEBUG
909     ByteArray ownCert = {g_X509Cred.certificateChain, g_X509Cred.certificateChainLen};
910     PRINT_BYTE_ARRAY("OWN CERT: \n", ownCert);
911 #endif
912
913     ret = TINY_DTLS_SUCCESS;
914 exit:
915     return ret;
916 }
917 /**
918  * @fn  CAGetRootKey
919  * @brief  Gets x and y components of Root Certificate Autority public key
920  *
921  * @return  0 on success otherwise a positive error value.
922  *
923  */
924 static int CAGetRootKey(const unsigned char **ca_pub_x, const unsigned char **ca_pub_y)
925 {
926     OIC_LOG(DEBUG, NET_DTLS_TAG, "CAGetRootKey");
927     int ret = 1;
928
929     VERIFY_SUCCESS(CAInitX509(), 0);
930
931     *ca_pub_x = g_X509Cred.rootPublicKeyX;
932     *ca_pub_y = g_X509Cred.rootPublicKeyY;
933
934     ret = 0;
935 exit:
936     return ret;
937 }
938
939
940 static int CAVerifyCertificate(struct dtls_context_t *ctx, const session_t *session,
941                                const unsigned char *cert, size_t certLen,
942                                const unsigned char *x, size_t xLen,
943                                const unsigned char *y, size_t yLen)
944 {
945     OIC_LOG(DEBUG, NET_DTLS_TAG, "Verify Certificate");
946
947     ByteArray crtChainDer[MAX_CHAIN_LEN];
948     CertificateX509 crtChain[MAX_CHAIN_LEN];
949
950     uint8_t chainLength;
951
952     int ret = TINY_DTLS_ERROR;
953     const unsigned char *ca_pub_x;
954     const unsigned char *ca_pub_y;
955     ByteArray certDerCode = BYTE_ARRAY_INITIALIZER;
956     ByteArray caPubKey = BYTE_ARRAY_INITIALIZER;
957     unsigned char ca_pub_key[PUBLIC_KEY_SIZE];
958
959     if ( !ctx ||  !session ||  !cert || !x || !y)
960     {
961         return TINY_DTLS_ERROR;
962     }
963
964     CAGetRootKey (&ca_pub_x, &ca_pub_y);
965
966     certDerCode.data = (uint8_t *)cert;
967     certDerCode.len = certLen;
968
969 #ifdef X509_DEBUG
970     PRINT_BYTE_ARRAY("CERT :\n", certDerCode);
971 #endif
972
973
974     caPubKey.len = PUBLIC_KEY_SIZE;
975     caPubKey.data = ca_pub_key;
976
977     memcpy(caPubKey.data, ca_pub_x, PUBLIC_KEY_SIZE / 2);
978     memcpy(caPubKey.data + PUBLIC_KEY_SIZE / 2, ca_pub_y, PUBLIC_KEY_SIZE / 2);
979
980     ret = (int)  LoadCertificateChain (certDerCode, crtChainDer, &chainLength);
981     VERIFY_SUCCESS(ret, PKI_SUCCESS);
982     ret = (int)  ParseCertificateChain (crtChainDer, crtChain, chainLength );
983     VERIFY_SUCCESS(ret, PKI_SUCCESS);
984     ret = (int)  CheckCertificateChain (crtChain, chainLength, caPubKey);
985     VERIFY_SUCCESS(ret, PKI_SUCCESS);
986
987     INC_BYTE_ARRAY(crtChain[0].pubKey, 2);
988
989     memcpy(x, crtChain[0].pubKey.data, xLen);
990     memcpy(y, crtChain[0].pubKey.data + PUBLIC_KEY_SIZE / 2, yLen);
991
992     stCADtlsAddrInfo_t *addrInfo = (stCADtlsAddrInfo_t *)session;
993     char peerAddr[MAX_ADDR_STR_SIZE_CA] = { 0 };
994     uint16_t port = 0;
995     CAConvertAddrToName(&(addrInfo->addr.st), addrInfo->size, peerAddr, &port);
996
997     CAResult_t result = CAAddIdToPeerInfoList(peerAddr, port,
998             crtChain[0].subject.data + DER_SUBJECT_HEADER_LEN + 2, crtChain[0].subject.data[DER_SUBJECT_HEADER_LEN + 1]);
999     if (CA_STATUS_OK != result )
1000     {
1001         OIC_LOG(ERROR, NET_DTLS_TAG, "Fail to add peer id to gDtlsPeerInfoList");
1002     }
1003
1004 exit:
1005     if (ret != 0)
1006     {
1007         OIC_LOG(ERROR, NET_DTLS_TAG, "Certificate verification FAILED\n");
1008         return TINY_DTLS_ERROR;
1009     }
1010     else
1011     {
1012         OIC_LOG(DEBUG, NET_DTLS_TAG, "Certificate verification SUCCESS\n");
1013         return TINY_DTLS_SUCCESS;
1014     }
1015 }
1016
1017 #endif
1018
1019 static void CAStartRetransmit()
1020 {
1021     static int timerId = -1;
1022     if (timerId != -1)
1023     {
1024         //clear previous timer
1025         unregisterTimer(timerId);
1026
1027         ca_mutex_lock(g_dtlsContextMutex);
1028
1029         //stop retransmission if context is invalid
1030         if(NULL == g_caDtlsContext)
1031         {
1032             OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL. Stop retransmission");
1033             ca_mutex_unlock(g_dtlsContextMutex);
1034             return;
1035         }
1036         dtls_check_retransmit(g_caDtlsContext->dtlsContext, NULL);
1037         ca_mutex_unlock(g_dtlsContextMutex);
1038     }
1039     //start new timer
1040     registerTimer(RETRANSMISSION_TIME, &timerId, CAStartRetransmit);
1041 }
1042
1043 CAResult_t CAAdapterNetDtlsInit()
1044 {
1045     OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
1046
1047     // Initialize mutex for DtlsContext
1048     if (NULL == g_dtlsContextMutex)
1049     {
1050         g_dtlsContextMutex = ca_mutex_new();
1051         VERIFY_NON_NULL_RET(g_dtlsContextMutex, NET_DTLS_TAG, "malloc failed",
1052             CA_MEMORY_ALLOC_FAILED);
1053     }
1054     else
1055     {
1056         OIC_LOG(ERROR, NET_DTLS_TAG, "CAAdapterNetDtlsInit done already!");
1057         return CA_STATUS_OK;
1058     }
1059
1060     // Lock DtlsContext mutex and create DtlsContext
1061     ca_mutex_lock(g_dtlsContextMutex);
1062     g_caDtlsContext = (stCADtlsContext_t *)OICCalloc(1, sizeof(stCADtlsContext_t));
1063
1064     if (NULL == g_caDtlsContext)
1065     {
1066         OIC_LOG(ERROR, NET_DTLS_TAG, "Context malloc failed");
1067         ca_mutex_unlock(g_dtlsContextMutex);
1068         ca_mutex_free(g_dtlsContextMutex);
1069         return CA_MEMORY_ALLOC_FAILED;
1070     }
1071
1072
1073     // Create PeerInfoList and CacheList
1074     g_caDtlsContext->peerInfoList = u_arraylist_create();
1075     g_caDtlsContext->cacheList = u_arraylist_create();
1076
1077     if( (NULL == g_caDtlsContext->peerInfoList) ||
1078         (NULL == g_caDtlsContext->cacheList))
1079     {
1080     OIC_LOG(ERROR, NET_DTLS_TAG, "peerInfoList or cacheList initialization failed!");
1081         CAClearCacheList();
1082         CAFreePeerInfoList();
1083         OICFree(g_caDtlsContext);
1084         g_caDtlsContext = NULL;
1085         ca_mutex_unlock(g_dtlsContextMutex);
1086         ca_mutex_free(g_dtlsContextMutex);
1087         return CA_STATUS_FAILED;
1088     }
1089
1090     // Initialize clock, crypto and other global vars in tinyDTLS library
1091     dtls_init();
1092
1093     // Create tinydtls Context
1094     g_caDtlsContext->dtlsContext = dtls_new_context(g_caDtlsContext);
1095
1096     if (NULL ==  g_caDtlsContext->dtlsContext)
1097     {
1098         OIC_LOG(ERROR, NET_DTLS_TAG, "dtls_new_context failed");
1099         ca_mutex_unlock(g_dtlsContextMutex);
1100         CAAdapterNetDtlsDeInit();
1101         return CA_STATUS_FAILED;
1102     }
1103
1104     g_caDtlsContext->callbacks.write = CASendSecureData;
1105     g_caDtlsContext->callbacks.read  = CAReadDecryptedPayload;
1106     g_caDtlsContext->callbacks.event = CAHandleSecureEvent;
1107
1108     g_caDtlsContext->callbacks.get_psk_info = CAGetPskCredentials;
1109 #ifdef __WITH_X509__
1110     g_caDtlsContext->callbacks.get_x509_key = CAGetDeviceKey;
1111     g_caDtlsContext->callbacks.verify_x509_cert = CAVerifyCertificate;
1112     g_caDtlsContext->callbacks.get_x509_cert = CAGetDeviceCertificate;
1113     g_caDtlsContext->callbacks.is_x509_active = CAIsX509Active;
1114 #endif //__WITH_X509__*
1115     dtls_set_handler(g_caDtlsContext->dtlsContext, &(g_caDtlsContext->callbacks));
1116     ca_mutex_unlock(g_dtlsContextMutex);
1117
1118     CAStartRetransmit();
1119
1120     OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
1121     return CA_STATUS_OK;
1122 }
1123
1124 void CAAdapterNetDtlsDeInit()
1125 {
1126     OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
1127
1128     VERIFY_NON_NULL_VOID(g_caDtlsContext, NET_DTLS_TAG, "context is NULL");
1129     VERIFY_NON_NULL_VOID(g_dtlsContextMutex, NET_DTLS_TAG, "context mutex is NULL");
1130
1131     //Lock DtlsContext mutex
1132     ca_mutex_lock(g_dtlsContextMutex);
1133
1134     // Clear all lists
1135     CAFreePeerInfoList();
1136     CAClearCacheList();
1137
1138     // De-initialize tinydtls context
1139     dtls_free_context(g_caDtlsContext->dtlsContext);
1140     g_caDtlsContext->dtlsContext = NULL;
1141
1142     // De-initialize DtlsContext
1143     OICFree(g_caDtlsContext);
1144     g_caDtlsContext = NULL;
1145
1146     // Unlock DtlsContext mutex and de-initialize it
1147     ca_mutex_unlock(g_dtlsContextMutex);
1148     ca_mutex_free(g_dtlsContextMutex);
1149     g_dtlsContextMutex = NULL;
1150
1151     OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
1152 }
1153
1154 CAResult_t CAAdapterNetDtlsEncrypt(const CAEndpoint_t *endpoint,
1155                                    void *data, uint32_t dataLen)
1156 {
1157
1158     OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
1159
1160     VERIFY_NON_NULL_RET(endpoint, NET_DTLS_TAG,"Param remoteAddress is NULL",
1161                         CA_STATUS_INVALID_PARAM);
1162     VERIFY_NON_NULL_RET(data, NET_DTLS_TAG, "Param data is NULL" ,
1163                         CA_STATUS_INVALID_PARAM);
1164
1165     if (0 == dataLen)
1166     {
1167         OIC_LOG_V(ERROR, NET_DTLS_TAG, "dataLen is less than or equal zero [%d]", dataLen);
1168         return CA_STATUS_FAILED;
1169     }
1170
1171     OIC_LOG_V(DEBUG, NET_DTLS_TAG, "Data to be encrypted dataLen [%d]", dataLen);
1172
1173     stCADtlsAddrInfo_t addrInfo = { 0 };
1174
1175     CAConvertNameToAddr(endpoint->addr, endpoint->port, &(addrInfo.addr.st));
1176     addrInfo.ifIndex = 0;
1177     addrInfo.size = CASizeOfAddrInfo(&addrInfo);
1178
1179     ca_mutex_lock(g_dtlsContextMutex);
1180     if(NULL == g_caDtlsContext)
1181     {
1182         OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
1183         ca_mutex_unlock(g_dtlsContextMutex);
1184         return CA_STATUS_FAILED;
1185     }
1186
1187     eDtlsRet_t ret = CAAdapterNetDtlsEncryptInternal(&addrInfo, data, dataLen);
1188     if (ret == DTLS_SESSION_INITIATED)
1189     {
1190         stCACacheMessage_t *message = (stCACacheMessage_t *)OICCalloc(1, sizeof(stCACacheMessage_t));
1191         if (NULL == message)
1192         {
1193             OIC_LOG(ERROR, NET_DTLS_TAG, "calloc failed!");
1194             ca_mutex_unlock(g_dtlsContextMutex);
1195             return CA_MEMORY_ALLOC_FAILED;
1196         }
1197
1198         message->data = (uint8_t *)OICCalloc(dataLen + 1, sizeof(uint8_t));
1199         if (NULL == message->data)
1200         {
1201             OIC_LOG(ERROR, NET_DTLS_TAG, "calloc failed!");
1202             OICFree(message);
1203             ca_mutex_unlock(g_dtlsContextMutex);
1204             return CA_MEMORY_ALLOC_FAILED;
1205         }
1206         memcpy(message->data, data, dataLen);
1207         message->dataLen = dataLen;
1208         message->destSession = addrInfo;
1209
1210         CAResult_t result = CADtlsCacheMsg(message);
1211         if (CA_STATUS_OK != result)
1212         {
1213             OIC_LOG(DEBUG, NET_DTLS_TAG, "CADtlsCacheMsg failed!");
1214             CAFreeCacheMsg(message);
1215         }
1216         OIC_LOG_V(DEBUG, NET_DTLS_TAG, "OUT Initiating Dtls session [%d]", result);
1217         ca_mutex_unlock(g_dtlsContextMutex);
1218         return result;
1219     }
1220
1221     ca_mutex_unlock(g_dtlsContextMutex);
1222
1223     if (ret != DTLS_OK)
1224     {
1225         OIC_LOG(ERROR, NET_DTLS_TAG, "OUT FAILURE");
1226         return CA_STATUS_FAILED;
1227     }
1228
1229     OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
1230     return CA_STATUS_OK;
1231 }
1232
1233 CAResult_t CAAdapterNetDtlsDecrypt(const CASecureEndpoint_t *sep,
1234                                    uint8_t *data, uint32_t dataLen)
1235 {
1236     OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
1237     VERIFY_NON_NULL_RET(sep, NET_DTLS_TAG, "endpoint is NULL" , CA_STATUS_INVALID_PARAM);
1238
1239     stCADtlsAddrInfo_t addrInfo = { 0 };
1240
1241     CAConvertNameToAddr(sep->endpoint.addr, sep->endpoint.port, &(addrInfo.addr.st));
1242     addrInfo.ifIndex = 0;
1243     addrInfo.size = CASizeOfAddrInfo(&addrInfo);
1244
1245     ca_mutex_lock(g_dtlsContextMutex);
1246     if (NULL == g_caDtlsContext)
1247     {
1248         OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
1249         ca_mutex_unlock(g_dtlsContextMutex);
1250         return CA_STATUS_FAILED;
1251     }
1252
1253     eDtlsRet_t ret = CAAdapterNetDtlsDecryptInternal(&addrInfo, data, dataLen);
1254     ca_mutex_unlock(g_dtlsContextMutex);
1255
1256     if (DTLS_OK == ret || DTLS_HS_MSG == ret)
1257     {
1258         OIC_LOG_V(DEBUG, NET_DTLS_TAG, "Successfully Decrypted or Handshake msg recvd [%d]", ret);
1259         OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
1260         return CA_STATUS_OK;
1261     }
1262
1263     OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT FAILURE");
1264     return CA_STATUS_FAILED;
1265 }
1266