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