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