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