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