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