Imported Upstream version 0.9.2
[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 /**
30  * @def NET_DTLS_TAG
31  * @brief Logging tag for module name
32  */
33 #define NET_DTLS_TAG "NET_DTLS"
34
35 /**
36  * @var g_caDtlsContext
37  * @brief global context which holds dtls context and cache list information.
38  */
39 static stCADtlsContext_t *g_caDtlsContext = NULL;
40
41 /**
42  * @var g_dtlsContextMutex
43  * @brief Mutex to synchronize access to g_caDtlsContext.
44  */
45 static ca_mutex g_dtlsContextMutex = NULL;
46
47 /**
48  * @var g_getCredentialsCallback
49  * @brief callback to get DTLS credentials
50  */
51 static CAGetDTLSCredentialsHandler g_getCredentialsCallback = NULL;
52
53 static CAEndpoint_t *GetPeerInfo(const CAEndpoint_t *peer)
54 {
55     uint32_t list_index = 0;
56     uint32_t list_length = 0;
57
58     if(NULL == peer)
59     {
60         OIC_LOG(ERROR, NET_DTLS_TAG, "CAPeerInfoListContains invalid parameters");
61         return NULL;
62     }
63
64     CAEndpoint_t *peerInfo;
65     list_length = u_arraylist_length(g_caDtlsContext->peerInfoList);
66     for (list_index = 0; list_index < list_length; list_index++)
67     {
68         peerInfo = (CAEndpoint_t *)u_arraylist_get(g_caDtlsContext->peerInfoList, list_index);
69         if (NULL == peerInfo)
70         {
71             continue;
72         }
73
74         if((0 == strncmp(peer->addr, peerInfo->addr, MAX_ADDR_STR_SIZE_CA)) &&
75                 (peer->port == peerInfo->port))
76         {
77             return peerInfo;
78         }
79     }
80     return NULL;
81 }
82
83 static CAResult_t CAAddIdToPeerInfoList(const char *peerAddr, uint32_t port,
84                                     const unsigned char *id, uint16_t id_length)
85 {
86     if(NULL == peerAddr
87        || NULL == id
88        || 0 == port
89        || 0 == id_length
90        || CA_MAX_ENDPOINT_IDENTITY_LEN < id_length)
91     {
92         OIC_LOG(ERROR, NET_DTLS_TAG, "CAAddIdToPeerInfoList invalid parameters");
93         return CA_STATUS_INVALID_PARAM;
94     }
95
96     CAEndpoint_t *peer = (CAEndpoint_t *)OICCalloc(1, sizeof (CAEndpoint_t));
97     if (NULL == peer)
98     {
99         OIC_LOG(ERROR, NET_DTLS_TAG, "peerInfo malloc failed!");
100         return CA_MEMORY_ALLOC_FAILED;
101     }
102
103     OICStrcpy(peer->addr, sizeof(peer->addr), peerAddr);
104     peer->port = port;
105
106     memcpy(peer->identity.id, id, id_length);
107     peer->identity.id_length = id_length;
108
109     if(NULL != GetPeerInfo(peer))
110     {
111         OIC_LOG(ERROR, NET_DTLS_TAG, "CAAddIdToPeerInfoList peer already exist");
112         OICFree(peer);
113         return CA_STATUS_FAILED;
114     }
115
116     CAResult_t result = u_arraylist_add(g_caDtlsContext->peerInfoList, (void *)peer);
117     if (CA_STATUS_OK != result)
118     {
119         OIC_LOG(ERROR, NET_DTLS_TAG, "u_arraylist_add failed!");
120         OICFree(peer);
121     }
122
123     return result;
124 }
125
126 static void CAFreePeerInfoList()
127 {
128     uint32_t list_length = u_arraylist_length(g_caDtlsContext->peerInfoList);
129     for (uint32_t list_index = 0; list_index < list_length; list_index++)
130     {
131         CAEndpoint_t *peerInfo = (CAEndpoint_t *)u_arraylist_get(
132                                      g_caDtlsContext->peerInfoList, list_index);
133         OICFree(peerInfo);
134     }
135     u_arraylist_free(&(g_caDtlsContext->peerInfoList));
136     g_caDtlsContext->peerInfoList = NULL;
137 }
138
139 static void CARemovePeerFromPeerInfoList(const char * addr, uint32_t port)
140 {
141     if (NULL == addr || 0 >= port)
142     {
143         OIC_LOG(ERROR, NET_DTLS_TAG, "CADTLSGetPeerPSKId invalid parameters");
144         return;
145     }
146
147     uint32_t list_length = u_arraylist_length(g_caDtlsContext->peerInfoList);
148     for (uint32_t list_index = 0; list_index < list_length; list_index++)
149     {
150         CAEndpoint_t *peerInfo = (CAEndpoint_t *)u_arraylist_get(
151                                 g_caDtlsContext->peerInfoList,list_index);
152         if (NULL == peerInfo)
153         {
154             continue;
155         }
156         if((0 == strncmp(addr, peerInfo->addr, MAX_ADDR_STR_SIZE_CA)) &&
157                 (port == peerInfo->port))
158         {
159             OICFree(u_arraylist_remove(g_caDtlsContext->peerInfoList, list_index));
160             return;
161         }
162     }
163 }
164
165 static int CASizeOfAddrInfo(stCADtlsAddrInfo_t *addrInfo)
166 {
167     VERIFY_NON_NULL_RET(addrInfo, NET_DTLS_TAG, "addrInfo is NULL" , DTLS_FAIL);
168
169     switch (addrInfo->addr.st.ss_family)
170     {
171     case AF_INET:
172         {
173             return sizeof (struct sockaddr_in);
174         }
175     case AF_INET6:
176         {
177             return sizeof (struct sockaddr_in6);
178         }
179     default:
180         {
181             break;
182         }
183     }
184     return sizeof (struct sockaddr_storage);
185 }
186
187 static eDtlsRet_t CAAdapterNetDtlsEncryptInternal(const stCADtlsAddrInfo_t *dstSession,
188         uint8_t *data, uint32_t dataLen)
189 {
190     OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
191
192     VERIFY_NON_NULL_RET(dstSession, NET_DTLS_TAG, "Param dstSession is NULL" , DTLS_FAIL);
193     VERIFY_NON_NULL_RET(data, NET_DTLS_TAG, "Param data is NULL" , DTLS_FAIL);
194
195     if (0 == dataLen)
196     {
197         OIC_LOG(ERROR, NET_DTLS_TAG, "Given Packet length is equal to zero.");
198         return DTLS_FAIL;
199     }
200
201     if (NULL == g_caDtlsContext)
202     {
203         OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
204         return DTLS_FAIL;
205     }
206
207     int retLen = dtls_write(g_caDtlsContext->dtlsContext, (session_t *)dstSession, data,
208                                 dataLen);
209     OIC_LOG_V(DEBUG, NET_DTLS_TAG, "dtls_write retun len [%d]", retLen);
210     if (0 == retLen)
211     {
212         // A new DTLS session was initiated by tinyDTLS library and wait for callback.
213         return DTLS_SESSION_INITIATED;
214     }
215     else if (dataLen == retLen)
216     {
217         OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
218         return DTLS_OK;
219     }
220     OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT FAILURE");
221     return DTLS_FAIL;
222 }
223
224 static eDtlsRet_t CAAdapterNetDtlsDecryptInternal(const stCADtlsAddrInfo_t *srcSession,
225         uint8_t *buf, uint32_t bufLen)
226 {
227     OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
228
229     VERIFY_NON_NULL_RET(srcSession, NET_DTLS_TAG, "Param srcSession is NULL", DTLS_FAIL);
230     VERIFY_NON_NULL_RET(buf, NET_DTLS_TAG, "Param buf is NULL", DTLS_FAIL);
231
232     if (0 == bufLen)
233     {
234         OIC_LOG(ERROR, NET_DTLS_TAG, "Given Packet length is equal to zero.");
235         return DTLS_FAIL;
236     }
237
238     eDtlsRet_t ret = DTLS_FAIL;
239
240     if (dtls_handle_message(g_caDtlsContext->dtlsContext, (session_t *)srcSession, buf, bufLen) == 0)
241     {
242         OIC_LOG(DEBUG, NET_DTLS_TAG, "dtls_handle_message success");
243         ret = DTLS_OK;
244     }
245
246     OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
247     return ret;
248 }
249
250 static void CAFreeCacheMsg(stCACacheMessage_t *msg)
251 {
252     OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
253     VERIFY_NON_NULL_VOID(msg, NET_DTLS_TAG, "msg");
254
255     OICFree(msg->data);
256     OICFree(msg);
257
258     OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
259 }
260
261 static void CAClearCacheList()
262 {
263     OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
264     uint32_t list_index = 0;
265     uint32_t list_length = 0;
266     if (NULL == g_caDtlsContext)
267     {
268         OIC_LOG(ERROR, NET_DTLS_TAG, "Dtls Context is NULL");
269         return;
270     }
271     list_length = u_arraylist_length(g_caDtlsContext->cacheList);
272     for (list_index = 0; list_index < list_length; list_index++)
273     {
274         stCACacheMessage_t *msg = (stCACacheMessage_t *)u_arraylist_get(g_caDtlsContext->cacheList,
275                                   list_index);
276         if (msg != NULL)
277         {
278             CAFreeCacheMsg(msg);
279         }
280     }
281     u_arraylist_free(&g_caDtlsContext->cacheList);
282     g_caDtlsContext->cacheList = NULL;
283     OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
284 }
285
286 static CAResult_t CADtlsCacheMsg(stCACacheMessage_t *msg)
287 {
288     OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
289
290     if (NULL == g_caDtlsContext)
291     {
292         OIC_LOG(ERROR, NET_DTLS_TAG, "Dtls Context is NULL");
293         return CA_STATUS_FAILED;
294     }
295
296     CAResult_t result = u_arraylist_add(g_caDtlsContext->cacheList, (void *)msg);
297     if (CA_STATUS_OK != result)
298     {
299         OIC_LOG(ERROR, NET_DTLS_TAG, "u_arraylist_add failed!");
300     }
301
302     OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
303     return result;
304 }
305
306
307 static bool CAIsAddressMatching(const stCADtlsAddrInfo_t *a,  const stCADtlsAddrInfo_t *b)
308 {
309     if (a->size != b->size)
310     {
311         return false;
312     }
313     if (memcmp(&a->addr, &b->addr, a->size))
314     {
315         return false;
316     }
317     return true;
318 }
319
320 static void CASendCachedMsg(const stCADtlsAddrInfo_t *dstSession)
321 {
322     OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
323     VERIFY_NON_NULL_VOID(dstSession, NET_DTLS_TAG, "Param dstSession is NULL");
324
325     uint32_t list_index = 0;
326     uint32_t list_length = 0;
327     list_length = u_arraylist_length(g_caDtlsContext->cacheList);
328     for (list_index = 0; list_index < list_length;)
329     {
330         stCACacheMessage_t *msg = (stCACacheMessage_t *)u_arraylist_get(g_caDtlsContext->cacheList,
331                                   list_index);
332         if ((NULL != msg) && (true == CAIsAddressMatching(&(msg->destSession), dstSession)))
333         {
334             eDtlsRet_t ret = CAAdapterNetDtlsEncryptInternal(&(msg->destSession),
335                              msg->data, msg->dataLen);
336             if (ret == DTLS_OK)
337             {
338                 OIC_LOG(DEBUG, NET_DTLS_TAG, "CAAdapterNetDtlsEncryptInternal success");
339             }
340             else
341             {
342                 OIC_LOG(ERROR, NET_DTLS_TAG, "CAAdapterNetDtlsEncryptInternal failed.");
343             }
344
345             if (u_arraylist_remove(g_caDtlsContext->cacheList, list_index))
346             {
347                 CAFreeCacheMsg(msg);
348                 // Reduce list length by 1 as we removed one element.
349                 list_length--;
350             }
351             else
352             {
353                 OIC_LOG(ERROR, NET_DTLS_TAG, "u_arraylist_remove failed.");
354                 break;
355             }
356         }
357         else
358         {
359             // Move to the next element
360             ++list_index;
361         }
362     }
363
364     OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
365 }
366
367 static int32_t CAReadDecryptedPayload(dtls_context_t *dtlsContext,
368                                       session_t *session,
369                                       uint8_t *buf,
370                                       size_t bufLen )
371 {
372     OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
373
374     VERIFY_NON_NULL_RET(session, NET_DTLS_TAG, "Param Session is NULL", 0);
375     OIC_LOG_V(DEBUG, NET_DTLS_TAG, "Decrypted buf len [%d]", bufLen);
376
377     stCADtlsAddrInfo_t *addrInfo = (stCADtlsAddrInfo_t *)session;
378
379     CAEndpoint_t endpoint = { 0 };
380     CAConvertAddrToName(&(addrInfo->addr.st), endpoint.addr, &endpoint.port);
381     endpoint.flags = addrInfo->addr.st.ss_family == AF_INET ? CA_IPV4 : CA_IPV6;
382     endpoint.flags |= CA_SECURE;
383     endpoint.adapter = CA_ADAPTER_IP;
384     int type = 0;
385
386     if (NULL == g_caDtlsContext)
387     {
388         OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
389         return 0;
390     }
391
392     if ((0 <= type) && (MAX_SUPPORTED_ADAPTERS > type) &&
393         (NULL != g_caDtlsContext->adapterCallbacks[type].recvCallback))
394     {
395         // Get identity of the source of packet
396         CAEndpoint_t *peerInfo = GetPeerInfo(&endpoint);
397         if (peerInfo)
398         {
399             endpoint.identity = peerInfo->identity;
400         }
401
402         g_caDtlsContext->adapterCallbacks[type].recvCallback(&endpoint, buf, bufLen);
403     }
404     else
405     {
406         OIC_LOG_V(DEBUG, NET_DTLS_TAG, "recvCallback Callback or adapter type is wrong [%d]", type);
407     }
408
409     OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
410     return 0;
411 }
412
413 static int32_t CASendSecureData(dtls_context_t *dtlsContext,
414                                 session_t *session,
415                                 uint8_t *buf,
416                                 size_t bufLen)
417 {
418     OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
419
420     VERIFY_NON_NULL_RET(session, NET_DTLS_TAG, "Param Session is NULL", -1);
421     VERIFY_NON_NULL_RET(buf, NET_DTLS_TAG, "Param buf is NULL", -1);
422
423     if (0 == bufLen)
424     {
425         OIC_LOG(ERROR, NET_DTLS_TAG, "Encrypted Buffer length is equal to zero");
426         return 0;
427     }
428
429     stCADtlsAddrInfo_t *addrInfo = (stCADtlsAddrInfo_t *)session;
430
431     CAEndpoint_t endpoint;
432     CAConvertAddrToName(&(addrInfo->addr.st), endpoint.addr, &endpoint.port);
433     endpoint.flags = addrInfo->addr.st.ss_family == AF_INET ? CA_IPV4 : CA_IPV6;
434     endpoint.flags |= CA_SECURE;
435     endpoint.adapter = CA_ADAPTER_IP;
436     int type = 0;
437
438     //Mutex is not required for g_caDtlsContext. It will be called in same thread.
439     if ((0 <= type) && (MAX_SUPPORTED_ADAPTERS > type) &&
440         (NULL != g_caDtlsContext->adapterCallbacks[type].sendCallback))
441     {
442         g_caDtlsContext->adapterCallbacks[type].sendCallback(&endpoint, buf, bufLen);
443     }
444     else
445     {
446         OIC_LOG_V(DEBUG, NET_DTLS_TAG, "send Callback or adapter type is wrong [%d]", type );
447     }
448
449     OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
450     return bufLen;
451 }
452
453 static int32_t CAHandleSecureEvent(dtls_context_t *dtlsContext,
454                                    session_t *session,
455                                    dtls_alert_level_t level,
456                                    unsigned short code)
457 {
458     OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
459
460     VERIFY_NON_NULL_RET(session, NET_DTLS_TAG, "Param Session is NULL", 0);
461
462     OIC_LOG_V(DEBUG, NET_DTLS_TAG, "level [%d] code [%u]", level, code);
463
464     if (!level && (code == DTLS_EVENT_CONNECTED))
465     {
466         OIC_LOG(DEBUG, NET_DTLS_TAG, "Received DTLS_EVENT_CONNECTED. Sending Cached data");
467         CASendCachedMsg((stCADtlsAddrInfo_t *)session);
468     }
469
470     if(DTLS_ALERT_LEVEL_FATAL == level && DTLS_ALERT_CLOSE_NOTIFY == code)
471     {
472         OIC_LOG(INFO, NET_DTLS_TAG, "Peer closing connection");
473
474         stCADtlsAddrInfo_t *addrInfo = (stCADtlsAddrInfo_t *)session;
475         char *peerAddr = inet_ntoa(addrInfo->addr.sin.sin_addr);
476         uint32_t port = ntohs(addrInfo->addr.sin.sin_port);
477
478         CARemovePeerFromPeerInfoList(peerAddr, port);
479     }
480
481     OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
482     return 0;
483 }
484
485
486 static int32_t CAGetPskCredentials(dtls_context_t *ctx,
487                                    const session_t *session,
488                                    dtls_credentials_type_t type,
489                                    const unsigned char *desc, size_t descLen,
490                                    unsigned char *result, size_t resultLen)
491 {
492     OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
493
494     int32_t ret  = -1;
495     if(NULL == ctx || NULL == session || NULL == result)
496     {
497         OIC_LOG(ERROR, NET_DTLS_TAG, "CAGetPskCredentials invalid parameters");
498         return ret;
499     }
500
501     VERIFY_NON_NULL_RET(g_getCredentialsCallback, NET_DTLS_TAG, "GetCredential callback", -1);
502     VERIFY_NON_NULL_RET(result, NET_DTLS_TAG, "result", -1);
503
504     CADtlsPskCredsBlob_t *credInfo = NULL;
505
506     // Retrieve the credentials blob from security module
507     g_getCredentialsCallback(&credInfo);
508
509     VERIFY_NON_NULL_RET(credInfo, NET_DTLS_TAG, "credInfo is NULL", -1);
510     if(NULL == credInfo->creds)
511     {
512         OIC_LOG(DEBUG, NET_DTLS_TAG, "credentials are NULL");
513         memset(credInfo, 0, sizeof(CADtlsPskCredsBlob_t));
514         OICFree(credInfo);
515         return -1;
516     }
517
518     if ((type == DTLS_PSK_HINT) || (type == DTLS_PSK_IDENTITY))
519     {
520         if (DTLS_PSK_ID_LEN <= resultLen)
521         {
522             memcpy(result, credInfo->identity, DTLS_PSK_ID_LEN);
523             ret = DTLS_PSK_ID_LEN;
524         }
525     }
526
527     if ((type == DTLS_PSK_KEY) && (desc) && (descLen == DTLS_PSK_PSK_LEN))
528     {
529         // Check if we have the credentials for the device with which we
530         // are trying to perform a handshake
531         int index = 0;
532         for (index = 0; index < credInfo->num; index++)
533         {
534             if (memcmp(desc, credInfo->creds[index].id, DTLS_PSK_ID_LEN) == 0)
535             {
536                 if(NULL != ctx->peers && DTLS_SERVER == ctx->peers->role )
537                 {
538                     // TODO SRM needs identity of the remote end-point with every data packet to
539                     // perform access control management. tinyDTLS 'frees' the handshake parameters
540                     // data structure when handshake completes. Therefore, currently this is a
541                     // workaround to cache remote end-point identity when tinyDTLS asks for PSK.
542                     stCADtlsAddrInfo_t *addrInfo = (stCADtlsAddrInfo_t *)session;
543                     char *peerAddress = inet_ntoa(addrInfo->addr.sin.sin_addr);
544                     uint32_t port = ntohs(addrInfo->addr.sin.sin_port);
545
546                     CAResult_t result = CAAddIdToPeerInfoList(peerAddress, port, desc, descLen);
547                     if(CA_STATUS_OK != result )
548                     {
549                         OIC_LOG(ERROR, NET_DTLS_TAG, "Fail to add peer id to gDtlsPeerInfoList");
550                     }
551                 }
552                 memcpy(result, credInfo->creds[index].psk, DTLS_PSK_PSK_LEN);
553                 ret = DTLS_PSK_PSK_LEN;
554             }
555         }
556     }
557
558     // Erase sensitive data before freeing.
559     memset(credInfo->creds, 0, sizeof(OCDtlsPskCreds) * (credInfo->num));
560     OICFree(credInfo->creds);
561
562     memset(credInfo, 0, sizeof(CADtlsPskCredsBlob_t));
563     OICFree(credInfo);
564     credInfo = NULL;
565
566     return ret;
567 }
568
569 void CADTLSSetAdapterCallbacks(CAPacketReceivedCallback recvCallback,
570                                CAPacketSendCallback sendCallback,
571                                CATransportAdapter_t type)
572 {
573     OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
574     ca_mutex_lock(g_dtlsContextMutex);
575     if (NULL == g_caDtlsContext)
576     {
577         OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
578         ca_mutex_unlock(g_dtlsContextMutex);
579         return;
580     }
581
582     if ((0 <= type) && (MAX_SUPPORTED_ADAPTERS > type))
583     {
584         // TODO: change the zeros to better values.
585         g_caDtlsContext->adapterCallbacks[0].recvCallback = recvCallback;
586         g_caDtlsContext->adapterCallbacks[0].sendCallback = sendCallback;
587     }
588
589     ca_mutex_unlock(g_dtlsContextMutex);
590
591     OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
592 }
593
594 void CADTLSSetCredentialsCallback(CAGetDTLSCredentialsHandler credCallback)
595 {
596     // TODO Does this method needs protection of DtlsContextMutex ?
597     OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
598     g_getCredentialsCallback = credCallback;
599     OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
600 }
601
602 CAResult_t CADtlsSelectCipherSuite(const dtls_cipher_t cipher)
603 {
604     OIC_LOG(DEBUG, NET_DTLS_TAG, "IN CADtlsSelectCipherSuite");
605
606     ca_mutex_lock(g_dtlsContextMutex);
607     if (NULL == g_caDtlsContext)
608     {
609         OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
610         ca_mutex_unlock(g_dtlsContextMutex);
611         return CA_STATUS_FAILED;
612     }
613     dtls_select_cipher(g_caDtlsContext->dtlsContext, cipher);
614     ca_mutex_unlock(g_dtlsContextMutex);
615
616     OIC_LOG_V(DEBUG, NET_DTLS_TAG, "Selected cipher suite is 0x%02X%02X\n",
617         ((uint8_t*)(&cipher))[1], ((uint8_t*)(&cipher))[0]);
618     OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT CADtlsSelectCipherSuite");
619
620     return CA_STATUS_OK ;
621 }
622
623 CAResult_t CADtlsEnableAnonECDHCipherSuite(const bool enable)
624 {
625     OIC_LOG(DEBUG, NET_DTLS_TAG, "IN CADtlsEnablesAnonEcdh");
626
627     ca_mutex_lock(g_dtlsContextMutex);
628     if (NULL == g_caDtlsContext)
629     {
630         OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
631         ca_mutex_unlock(g_dtlsContextMutex);
632         return CA_STATUS_FAILED;
633     }
634     dtls_enables_anon_ecdh(g_caDtlsContext->dtlsContext,
635         enable == true ? DTLS_CIPHER_ENABLE : DTLS_CIPHER_DISABLE);
636     ca_mutex_unlock(g_dtlsContextMutex);
637     OIC_LOG_V(DEBUG, NET_DTLS_TAG, "TLS_ECDH_anon_WITH_AES_128_CBC_SHA  is %s",
638         enable ? "enabled" : "disabled");
639
640     OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT CADtlsEnablesAnonEcdh");
641
642     return CA_STATUS_OK ;
643 }
644
645 CAResult_t CADtlsInitiateHandshake(const CAEndpoint_t *endpoint)
646 {
647     stCADtlsAddrInfo_t dst = {};
648
649     OIC_LOG(DEBUG, NET_DTLS_TAG, "IN CADtlsInitiateHandshake");
650
651     if(!endpoint)
652     {
653         return CA_STATUS_INVALID_PARAM;
654     }
655
656     CAConvertNameToAddr(endpoint->addr, endpoint->port, &(dst.addr.st));
657     dst.ifIndex = 0;
658     dst.size = CASizeOfAddrInfo(&dst);
659
660     ca_mutex_lock(g_dtlsContextMutex);
661     if(NULL == g_caDtlsContext)
662     {
663         OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
664         ca_mutex_unlock(g_dtlsContextMutex);
665         return CA_STATUS_FAILED;
666     }
667
668     if(0 > dtls_connect(g_caDtlsContext->dtlsContext, (session_t*)(&dst)))
669     {
670         OIC_LOG(ERROR, NET_DTLS_TAG, "Failed to connect");
671         ca_mutex_unlock(g_dtlsContextMutex);
672         return CA_STATUS_FAILED;
673     }
674
675     ca_mutex_unlock(g_dtlsContextMutex);
676
677     OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT CADtlsInitiateHandshake");
678
679     return CA_STATUS_OK;
680 }
681
682 CAResult_t CADtlsClose(const CAEndpoint_t *endpoint)
683 {
684     stCADtlsAddrInfo_t dst = {};
685
686     OIC_LOG(DEBUG, NET_DTLS_TAG, "IN CADtlsDisconnect");
687
688     if(!endpoint)
689     {
690         return CA_STATUS_INVALID_PARAM;
691     }
692
693     CAConvertNameToAddr(endpoint->addr, endpoint->port, &(dst.addr.st));
694     dst.ifIndex = 0;
695     dst.size = CASizeOfAddrInfo(&dst);
696
697     ca_mutex_lock(g_dtlsContextMutex);
698     if (NULL == g_caDtlsContext)
699     {
700         OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
701         ca_mutex_unlock(g_dtlsContextMutex);
702         return CA_STATUS_FAILED;
703     }
704
705     if (0 > dtls_close(g_caDtlsContext->dtlsContext, (session_t*)(&dst)))
706     {
707         OIC_LOG(ERROR, NET_DTLS_TAG, "Failed to close the session");
708         ca_mutex_unlock(g_dtlsContextMutex);
709         return CA_STATUS_FAILED;
710     }
711
712     ca_mutex_unlock(g_dtlsContextMutex);
713
714     OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT CADtlsDisconnect");
715
716     return CA_STATUS_OK;
717 }
718
719 CAResult_t CADtlsGenerateOwnerPSK(const CAEndpoint_t *endpoint,
720                     const uint8_t* label, const size_t labelLen,
721                     const uint8_t* rsrcServerDeviceID, const size_t rsrcServerDeviceIDLen,
722                     const uint8_t* provServerDeviceID, const size_t provServerDeviceIDLen,
723                     uint8_t* ownerPSK, const size_t ownerPSKSize)
724 {
725     OIC_LOG(DEBUG, NET_DTLS_TAG, "IN CADtlsGenerateOwnerPSK");
726
727     if(!endpoint || !label || 0 == labelLen || !ownerPSK || 0 == ownerPSKSize)
728     {
729         return CA_STATUS_INVALID_PARAM;
730     }
731
732     stCADtlsAddrInfo_t dst = {};
733
734     CAConvertNameToAddr(endpoint->addr, endpoint->port, &(dst.addr.st));
735     dst.ifIndex = 0;
736     dst.size = CASizeOfAddrInfo(&dst);
737
738     ca_mutex_lock(g_dtlsContextMutex);
739     if (NULL == g_caDtlsContext)
740     {
741         OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
742         ca_mutex_unlock(g_dtlsContextMutex);
743         return CA_STATUS_FAILED;
744     }
745
746     if( 0 == dtls_prf_with_current_keyblock(g_caDtlsContext->dtlsContext, (session_t*)(&dst),
747                  label, labelLen, rsrcServerDeviceID, rsrcServerDeviceIDLen,
748                  provServerDeviceID, provServerDeviceIDLen, ownerPSK, ownerPSKSize))
749     {
750         OIC_LOG(ERROR, NET_DTLS_TAG, "Failed to DTLS PRF");
751         ca_mutex_unlock(g_dtlsContextMutex);
752         return CA_STATUS_FAILED;
753     }
754     ca_mutex_unlock(g_dtlsContextMutex);
755
756     OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT CADtlsGenerateOwnerPSK");
757
758     return CA_STATUS_OK;
759 }
760
761 CAResult_t CAAdapterNetDtlsInit()
762 {
763     OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
764
765     // Initialize mutex for DtlsContext
766     if (NULL == g_dtlsContextMutex)
767     {
768         g_dtlsContextMutex = ca_mutex_new();
769         VERIFY_NON_NULL_RET(g_dtlsContextMutex, NET_DTLS_TAG, "malloc failed",
770             CA_MEMORY_ALLOC_FAILED);
771     }
772     else
773     {
774         OIC_LOG(ERROR, NET_DTLS_TAG, "CAAdapterNetDtlsInit done already!");
775         return CA_STATUS_OK;
776     }
777
778     // Lock DtlsContext mutex and create DtlsContext
779     ca_mutex_lock(g_dtlsContextMutex);
780     g_caDtlsContext = (stCADtlsContext_t *)OICCalloc(1, sizeof(stCADtlsContext_t));
781
782     if (NULL == g_caDtlsContext)
783     {
784         OIC_LOG(ERROR, NET_DTLS_TAG, "Context malloc failed");
785         ca_mutex_unlock(g_dtlsContextMutex);
786         ca_mutex_free(g_dtlsContextMutex);
787         return CA_MEMORY_ALLOC_FAILED;
788     }
789
790
791     // Create PeerInfoList and CacheList
792     g_caDtlsContext->peerInfoList = u_arraylist_create();
793     g_caDtlsContext->cacheList = u_arraylist_create();
794
795     if( (NULL == g_caDtlsContext->peerInfoList) ||
796         (NULL == g_caDtlsContext->cacheList))
797     {
798     OIC_LOG(ERROR, NET_DTLS_TAG, "peerInfoList or cacheList initialization failed!");
799         CAClearCacheList();
800         CAFreePeerInfoList();
801         OICFree(g_caDtlsContext);
802         g_caDtlsContext = NULL;
803         ca_mutex_unlock(g_dtlsContextMutex);
804         ca_mutex_free(g_dtlsContextMutex);
805         return CA_STATUS_FAILED;
806     }
807
808     // Initialize clock, crypto and other global vars in tinyDTLS library
809     dtls_init();
810
811     // Create tinydtls Context
812     g_caDtlsContext->dtlsContext = dtls_new_context(g_caDtlsContext);
813
814     if (NULL ==  g_caDtlsContext->dtlsContext)
815     {
816         OIC_LOG(ERROR, NET_DTLS_TAG, "dtls_new_context failed");
817         ca_mutex_unlock(g_dtlsContextMutex);
818         CAAdapterNetDtlsDeInit();
819         return CA_STATUS_FAILED;
820     }
821
822     g_caDtlsContext->callbacks.write = CASendSecureData;
823     g_caDtlsContext->callbacks.read  = CAReadDecryptedPayload;
824     g_caDtlsContext->callbacks.event = CAHandleSecureEvent;
825     g_caDtlsContext->callbacks.get_psk_info = CAGetPskCredentials;
826
827     dtls_set_handler(g_caDtlsContext->dtlsContext, &(g_caDtlsContext->callbacks));
828     ca_mutex_unlock(g_dtlsContextMutex);
829     OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
830     return CA_STATUS_OK;
831 }
832
833 void CAAdapterNetDtlsDeInit()
834 {
835     OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
836
837     VERIFY_NON_NULL_VOID(g_caDtlsContext, NET_DTLS_TAG, "context is NULL");
838     VERIFY_NON_NULL_VOID(g_dtlsContextMutex, NET_DTLS_TAG, "context mutex is NULL");
839
840     //Lock DtlsContext mutex
841     ca_mutex_lock(g_dtlsContextMutex);
842
843     // Clear all lists
844     CAFreePeerInfoList();
845     CAClearCacheList();
846
847     // De-initialize tinydtls context
848     dtls_free_context(g_caDtlsContext->dtlsContext);
849     g_caDtlsContext->dtlsContext = NULL;
850
851     // De-initialize DtlsContext
852     OICFree(g_caDtlsContext);
853     g_caDtlsContext = NULL;
854
855     // Unlock DtlsContext mutex and de-initialize it
856     ca_mutex_unlock(g_dtlsContextMutex);
857     ca_mutex_free(g_dtlsContextMutex);
858     g_dtlsContextMutex = NULL;
859
860     OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
861 }
862
863 CAResult_t CAAdapterNetDtlsEncrypt(const CAEndpoint_t *endpoint,
864                                    void *data, uint32_t dataLen)
865 {
866
867     OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
868
869     VERIFY_NON_NULL_RET(endpoint, NET_DTLS_TAG,"Param remoteAddress is NULL",
870                         CA_STATUS_INVALID_PARAM);
871     VERIFY_NON_NULL_RET(data, NET_DTLS_TAG, "Param data is NULL" ,
872                         CA_STATUS_INVALID_PARAM);
873
874     if (0 == dataLen)
875     {
876         OIC_LOG_V(ERROR, NET_DTLS_TAG, "dataLen is less than or equal zero [%d]", dataLen);
877         return CA_STATUS_FAILED;
878     }
879
880     OIC_LOG_V(DEBUG, NET_DTLS_TAG, "Data to be encrypted dataLen [%d]", dataLen);
881
882     stCADtlsAddrInfo_t addrInfo = {};
883
884     CAConvertNameToAddr(endpoint->addr, endpoint->port, &(addrInfo.addr.st));
885     addrInfo.ifIndex = 0;
886     addrInfo.size = CASizeOfAddrInfo(&addrInfo);
887
888     ca_mutex_lock(g_dtlsContextMutex);
889     if(NULL == g_caDtlsContext)
890     {
891         OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
892         ca_mutex_unlock(g_dtlsContextMutex);
893         return CA_STATUS_FAILED;
894     }
895
896     eDtlsRet_t ret = CAAdapterNetDtlsEncryptInternal(&addrInfo, data, dataLen);
897     if (ret == DTLS_SESSION_INITIATED)
898     {
899         stCACacheMessage_t *message = (stCACacheMessage_t *)OICCalloc(1, sizeof(stCACacheMessage_t));
900         if (NULL == message)
901         {
902             OIC_LOG(ERROR, NET_DTLS_TAG, "calloc failed!");
903             ca_mutex_unlock(g_dtlsContextMutex);
904             return CA_MEMORY_ALLOC_FAILED;
905         }
906
907         message->data = (uint8_t *)OICCalloc(dataLen + 1, sizeof(uint8_t));
908         if (NULL == message->data)
909         {
910             OIC_LOG(ERROR, NET_DTLS_TAG, "calloc failed!");
911             OICFree(message);
912             ca_mutex_unlock(g_dtlsContextMutex);
913             return CA_MEMORY_ALLOC_FAILED;
914         }
915         memcpy(message->data, data, dataLen);
916         message->dataLen = dataLen;
917         message->destSession = addrInfo;
918
919         CAResult_t result = CADtlsCacheMsg(message);
920         if (CA_STATUS_OK != result)
921         {
922             OIC_LOG(DEBUG, NET_DTLS_TAG, "CADtlsCacheMsg failed!");
923             CAFreeCacheMsg(message);
924         }
925         OIC_LOG_V(DEBUG, NET_DTLS_TAG, "OUT Initiating Dtls session [%d]", result);
926         ca_mutex_unlock(g_dtlsContextMutex);
927         return result;
928     }
929
930     ca_mutex_unlock(g_dtlsContextMutex);
931
932     if (ret != DTLS_OK)
933     {
934         OIC_LOG(ERROR, NET_DTLS_TAG, "OUT FAILURE");
935         return CA_STATUS_FAILED;
936     }
937
938     OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
939     return CA_STATUS_OK;
940 }
941
942 CAResult_t CAAdapterNetDtlsDecrypt(const CAEndpoint_t *endpoint,
943                                    uint8_t *data, uint32_t dataLen)
944 {
945     OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
946     VERIFY_NON_NULL_RET(endpoint, NET_DTLS_TAG, "endpoint is NULL" , CA_STATUS_INVALID_PARAM);
947
948     stCADtlsAddrInfo_t addrInfo = {};
949
950     CAConvertNameToAddr(endpoint->addr, endpoint->port, &(addrInfo.addr.st));
951     addrInfo.ifIndex = 0;
952     addrInfo.size = CASizeOfAddrInfo(&addrInfo);
953
954     ca_mutex_lock(g_dtlsContextMutex);
955     if (NULL == g_caDtlsContext)
956     {
957         OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
958         ca_mutex_unlock(g_dtlsContextMutex);
959         return CA_STATUS_FAILED;
960     }
961
962     eDtlsRet_t ret = CAAdapterNetDtlsDecryptInternal(&addrInfo, data, dataLen);
963     ca_mutex_unlock(g_dtlsContextMutex);
964
965     if (DTLS_OK == ret || DTLS_HS_MSG == ret)
966     {
967         OIC_LOG_V(DEBUG, NET_DTLS_TAG, "Successfully Decrypted or Handshake msg recvd [%d]", ret);
968         OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
969         return CA_STATUS_OK;
970     }
971
972     OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT FAILURE");
973     return CA_STATUS_FAILED;
974 }
975