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