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