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