Fix crash in ssl retransmission thread
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / adapter_util / ca_adapter_net_ssl.c
index 48dbb6d..d0f44bd 100644 (file)
 #include "cacommon.h"
 #include "caipinterface.h"
 #include "oic_malloc.h"
+#include "ocrandom.h"
 #include "byte_array.h"
 #include "camutex.h"
+#include "timer.h"
+
 
 // headers required for mbed TLS
 #include "mbedtls/platform.h"
 #include "mbedtls/ctr_drbg.h"
 #include "mbedtls/pkcs12.h"
 #include "mbedtls/ssl_internal.h"
+#include "mbedtls/net.h"
 #ifdef __WITH_DTLS__
 #include "mbedtls/timing.h"
 #include "mbedtls/ssl_cookie.h"
 #endif
 
-#ifndef NDEBUG
+#if !defined(NDEBUG) || defined(TB_LOG)
 #include "mbedtls/debug.h"
 #include "mbedtls/version.h"
 #endif
  * @param[in] peer remote peer
  * @param[in] ret used internaly
  */
+
+/**
+ * @var RETRANSMISSION_TIME
+ * @brief Maximum timeout value (in seconds) to start DTLS retransmission.
+ */
+#define RETRANSMISSION_TIME 1
+
 #define SSL_CLOSE_NOTIFY(peer, ret)                                                                \
 do                                                                                                 \
 {                                                                                                  \
@@ -157,7 +168,7 @@ if (g_sslCallback)
  * @param[in] ret error code
  * @param[in] str debug string
  * @param[in] mutex ca mutex
- * @param[in] return error code
+ * @param[in] if code does not equal to -1 returns error code
  * @param[in] msg allert message
  */
 #define SSL_CHECK_FAIL(peer, ret, str, mutex, error, msg)                                          \
@@ -172,14 +183,24 @@ if (0 != (ret) && MBEDTLS_ERR_SSL_WANT_READ != (int) (ret) &&
     {                                                                                              \
         mbedtls_ssl_send_alert_message(&(peer)->ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, (msg));        \
     }                                                                                              \
-    SSL_RES((peer), CA_STATUS_FAILED);                                                             \
+    if ((int) MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE == (int) (ret) &&                                \
+        ((int) MBEDTLS_SSL_ALERT_MSG_DECRYPTION_FAILED == (peer)->ssl.in_msg[1] ||                 \
+         (int) MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR == (peer)->ssl.in_msg[1] ||                     \
+         (int) MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE == (peer)->ssl.in_msg[1] ||                 \
+         (int) MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC == (peer)->ssl.in_msg[1]))                     \
+    {                                                                                              \
+        SSL_RES((peer), CA_DTLS_AUTHENTICATION_FAILURE);                                           \
+    }                                                                                              \
     RemovePeerFromList(&(peer)->sep.endpoint);                                                     \
     if (mutex)                                                                                     \
     {                                                                                              \
         ca_mutex_unlock(g_sslContextMutex);                                                        \
     }                                                                                              \
     OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);                                             \
-    return (error);                                                                                \
+    if (-1 != error)                                                                               \
+    {                                                                                              \
+        return (error);                                                                            \
+    }                                                                                              \
 }
 /** @def CHECK_MBEDTLS_RET(f, ...)
  * A macro that checks \a f function return code
@@ -201,6 +222,8 @@ typedef enum
     ADAPTER_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8,
     ADAPTER_TLS_ECDH_ANON_WITH_AES_128_CBC_SHA_256,
     ADAPTER_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256,
+    ADAPTER_TLS_ECDHE_ECDSA_WITH_AES_128_CCM,
+    ADAPTER_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
     ADAPTER_CIPHER_MAX
 } AdapterCipher_t;
 
@@ -215,7 +238,9 @@ int tlsCipher[ADAPTER_CIPHER_MAX][2] =
     {MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA, 0},
     {MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, 0},
     {MBEDTLS_TLS_ECDH_ANON_WITH_AES_128_CBC_SHA256, 0},
-    {MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, 0}
+    {MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, 0},
+    {MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM, 0},
+    {MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, 0}
 };
 
 static int g_cipherSuitesList[ADAPTER_CIPHER_MAX];
@@ -270,7 +295,7 @@ static int GetAlertCode(uint32_t flags)
     return 0;
 }
 
-#ifndef NDEBUG
+#if !defined(NDEBUG) || defined(TB_LOG)
 /**
  * Pass a message to the OIC logger.
  *
@@ -313,7 +338,7 @@ static void * memmem(const void *l, size_t lLen, const void *s, size_t sLen)
     }
     if (sLen == 1)
     {
-        return memchr(l, (int)*cs, lLen);
+        return (void *)memchr(l, (int)*cs, lLen);
     }
 
     last = (char *)cl + lLen - sLen;
@@ -360,16 +385,17 @@ typedef struct SslContext
     mbedtls_ssl_config serverTlsConf;
     mbedtls_ssl_config clientDtlsConf;
     mbedtls_ssl_config serverDtlsConf;
-#ifdef __WITH_DTLS__
-    mbedtls_ssl_cookie_ctx cookie_ctx;
-    mbedtls_timing_delay_context timer;
-#endif // __WITH_DTLS__
+
     AdapterCipher_t cipher;
     SslCallbacks_t adapterCallbacks[MAX_SUPPORTED_ADAPTERS];
     mbedtls_x509_crl crl;
     bool cipherFlag[2];
     int selectedCipher;
 
+#ifdef __WITH_DTLS__
+    int timerId;
+#endif
+
 } SslContext_t;
 
 /**
@@ -430,8 +456,8 @@ typedef struct SslEndPoint
     uint8_t random[2*RANDOM_LEN];
 #ifdef __WITH_DTLS__
     mbedtls_ssl_cookie_ctx cookieCtx;
-#endif
-
+    mbedtls_timing_delay_context timer;
+#endif // __WITH_DTLS__
 } SslEndPoint_t;
 
 void CAsetPskCredentialsCallback(CAgetPskCredentialsHandler credCallback)
@@ -475,29 +501,35 @@ static int GetAdapterIndex(CATransportAdapter_t adapter)
  * @param[in]  data    message
  * @param[in]  dataLen    message length
  *
- * @return  message length
+ * @return  message length or -1 on error.
  */
 static int SendCallBack(void * tep, const unsigned char * data, size_t dataLen)
 {
     OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s", __func__);
-    VERIFY_NON_NULL_RET(tep, NET_SSL_TAG, "secure endpoint is NULL", 0);
-    VERIFY_NON_NULL_RET(data, NET_SSL_TAG, "data is NULL", 0);
+    VERIFY_NON_NULL_RET(tep, NET_SSL_TAG, "secure endpoint is NULL", -1);
+    VERIFY_NON_NULL_RET(data, NET_SSL_TAG, "data is NULL", -1);
     OIC_LOG_V(DEBUG, NET_SSL_TAG, "Data len: %zu", dataLen);
     OIC_LOG_V(DEBUG, NET_SSL_TAG, "Adapter: %u", ((SslEndPoint_t * )tep)->sep.endpoint.adapter);
+    ssize_t sentLen = 0;
     int adapterIndex = GetAdapterIndex(((SslEndPoint_t * )tep)->sep.endpoint.adapter);
     if (0 == adapterIndex || 1 == adapterIndex)
     {
         CAPacketSendCallback sendCallback = g_caSslContext->adapterCallbacks[adapterIndex].sendCallback;
-        sendCallback(&(((SslEndPoint_t * )tep)->sep.endpoint), (const void *) data, (uint32_t) dataLen);
+        sentLen = sendCallback(&(((SslEndPoint_t * )tep)->sep.endpoint), (const void *) data, dataLen);
+        if (sentLen != dataLen)
+        {
+            OIC_LOG_V(DEBUG, NET_SSL_TAG,
+                      "Packet was partially sent - total/sent/remained bytes : %d/%d/%d",
+                      sentLen, dataLen, (dataLen - sentLen));
+        }
     }
     else
     {
         OIC_LOG(ERROR, NET_SSL_TAG, "Unsupported adapter");
-        dataLen = 0;
     }
 
     OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
-    return dataLen;
+    return sentLen;
 }
 /**
  * Read callback.
@@ -765,6 +797,45 @@ static SslEndPoint_t *GetSslPeer(const CAEndpoint_t *peer)
     OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
     return NULL;
 }
+
+#ifdef _ENABLE_MULTIPLE_OWNER_
+/**
+ * Gets CA secure endpoint info corresponding for endpoint.
+ *
+ * @param[in]  peer    remote address
+ *
+ * @return  CASecureEndpoint or NULL
+ */
+const CASecureEndpoint_t *GetCASecureEndpointData(const CAEndpoint_t* peer)
+{
+    OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s", __func__);
+
+    // TODO: Added as workaround, need to debug
+    ca_mutex_unlock(g_sslContextMutex);
+
+    ca_mutex_lock(g_sslContextMutex);
+    if (NULL == g_caSslContext)
+    {
+        OIC_LOG(ERROR, NET_SSL_TAG, "Context is NULL");
+        ca_mutex_unlock(g_sslContextMutex);
+        return NULL;
+    }
+
+    SslEndPoint_t* sslPeer = GetSslPeer(peer);
+    if(sslPeer)
+    {
+        OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
+        ca_mutex_unlock(g_sslContextMutex);
+        return &sslPeer->sep;
+    }
+
+    OIC_LOG(DEBUG, NET_SSL_TAG, "Return NULL");
+    OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
+    ca_mutex_unlock(g_sslContextMutex);
+    return NULL;
+}
+#endif
+
 /**
  * Deletes cached message.
  *
@@ -899,6 +970,44 @@ CAResult_t CAcloseSslConnection(const CAEndpoint_t *endpoint)
     OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
     return CA_STATUS_OK;
 }
+
+void CAcloseSslConnectionAll()
+{
+    OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s", __func__);
+    ca_mutex_lock(g_sslContextMutex);
+    if (NULL == g_caSslContext)
+    {
+        OIC_LOG(ERROR, NET_SSL_TAG, "Context is NULL");
+        ca_mutex_unlock(g_sslContextMutex);
+        return;
+    }
+
+    uint32_t listLength = u_arraylist_length(g_caSslContext->peerList);
+    for (uint32_t i = listLength; i > 0; i--)
+    {
+        SslEndPoint_t *tep = (SslEndPoint_t *)u_arraylist_remove(g_caSslContext->peerList, i - 1);
+        if (NULL == tep)
+        {
+            continue;
+        }
+        OIC_LOG_V(DEBUG, NET_SSL_TAG, "SSL Connection [%s:%d]",
+                  tep->sep.endpoint.addr, tep->sep.endpoint.port);
+
+        // TODO: need to check below code after socket close is ensured.
+        /*int ret = 0;
+        do
+        {
+            ret = mbedtls_ssl_close_notify(&tep->ssl);
+        }
+        while (MBEDTLS_ERR_SSL_WANT_WRITE == ret);*/
+
+        DeleteSslEndPoint(tep);
+    }
+    ca_mutex_unlock(g_sslContextMutex);
+
+    OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
+    return;
+}
 /**
  * Creates session for endpoint.
  *
@@ -935,7 +1044,7 @@ static SslEndPoint_t * NewSslEndPoint(const CAEndpoint_t * endpoint, mbedtls_ssl
     mbedtls_ssl_set_bio(&tep->ssl, tep, SendCallBack, RecvCallBack, NULL);
     if (MBEDTLS_SSL_TRANSPORT_DATAGRAM == config->transport)
     {
-        mbedtls_ssl_set_timer_cb(&tep->ssl, &g_caSslContext->timer,
+        mbedtls_ssl_set_timer_cb(&tep->ssl, &tep->timer,
                                   mbedtls_timing_set_delay, mbedtls_timing_get_delay);
         if (MBEDTLS_SSL_IS_SERVER == config->endpoint)
         {
@@ -1096,7 +1205,19 @@ static SslEndPoint_t * InitiateTlsHandshake(const CAEndpoint_t *endpoint)
     OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
     return tep;
 }
-
+#ifdef __WITH_DTLS__
+/**
+ * Stops DTLS retransmission.
+ */
+static void StopRetransmit()
+{
+    if (g_caSslContext)
+    {
+        unregisterTimer(g_caSslContext->timerId);
+        g_caSslContext->timerId= -1;
+    }
+}
+#endif
 void CAdeinitSslAdapter()
 {
     OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s", __func__);
@@ -1123,7 +1244,9 @@ void CAdeinitSslAdapter()
 #endif // __WITH_DTLS__
     mbedtls_ctr_drbg_free(&g_caSslContext->rnd);
     mbedtls_entropy_free(&g_caSslContext->entropy);
-
+#ifdef __WITH_DTLS__
+    StopRetransmit();
+#endif
     // De-initialize tls Context
     OICFree(g_caSslContext);
     g_caSslContext = NULL;
@@ -1154,13 +1277,60 @@ static int InitConfig(mbedtls_ssl_config * conf, int transport, int mode)
     mbedtls_ssl_conf_renegotiation(conf, MBEDTLS_SSL_RENEGOTIATION_DISABLED);
     mbedtls_ssl_conf_authmode(conf, MBEDTLS_SSL_VERIFY_REQUIRED);
 
-#ifndef NDEBUG
+#if !defined(NDEBUG) || defined(TB_LOG)
     mbedtls_ssl_conf_dbg(conf, DebugSsl, NULL);
     mbedtls_debug_set_threshold(MBED_TLS_DEBUG_LEVEL);
 #endif
     OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
     return 0;
 }
+#ifdef __WITH_DTLS__
+/**
+ * Starts DTLS retransmission.
+ */
+static int StartRetransmit()
+{
+    uint32_t listIndex = 0;
+    uint32_t listLength = 0;
+    SslEndPoint_t *tep = NULL;
+
+    ca_mutex_lock(g_sslContextMutex);
+    if (NULL == g_caSslContext)
+    {
+        OIC_LOG(ERROR, NET_SSL_TAG, "Context is NULL. Stop retransmission");
+        ca_mutex_unlock(g_sslContextMutex);
+        return -1;
+    }
+    if (g_caSslContext->timerId != -1)
+    {
+        //clear previous timer
+        unregisterTimer(g_caSslContext->timerId);
+
+        listLength = u_arraylist_length(g_caSslContext->peerList);
+        for (listIndex = 0; listIndex < listLength; listIndex++)
+        {
+            tep = (SslEndPoint_t *) u_arraylist_get(g_caSslContext->peerList, listIndex);
+            if (NULL == tep
+                || MBEDTLS_SSL_TRANSPORT_STREAM == tep->ssl.conf->transport
+                || MBEDTLS_SSL_HANDSHAKE_OVER == tep->ssl.state)
+            {
+                continue;
+            }
+            int ret = mbedtls_ssl_handshake_step(&tep->ssl);
+
+            if (MBEDTLS_ERR_SSL_CONN_EOF != ret)
+            {
+                SSL_CHECK_FAIL(tep, ret, "Retransmission", NULL, -1,
+                MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE);
+            }
+        }
+    }
+    //start new timer
+    registerTimer(RETRANSMISSION_TIME, &g_caSslContext->timerId, (void *) StartRetransmit);
+    ca_mutex_unlock(g_sslContextMutex);
+    return 0;
+}
+#endif
 
 CAResult_t CAinitSslAdapter()
 {
@@ -1206,7 +1376,7 @@ CAResult_t CAinitSslAdapter()
 
     /* Initialize TLS library
      */
-#ifndef NDEBUG
+#if !defined(NDEBUG) || defined(TB_LOG)
     char version[MBED_TLS_VERSION_LEN];
     mbedtls_version_get_string(version);
     OIC_LOG_V(INFO, NET_SSL_TAG, "mbed TLS version: %s", version);
@@ -1303,7 +1473,14 @@ CAResult_t CAinitSslAdapter()
     mbedtls_pk_init(&g_caSslContext->pkey);
     mbedtls_x509_crl_init(&g_caSslContext->crl);
 
-    ca_mutex_unlock(g_sslContextMutex);
+#ifdef __WITH_DTLS__
+    g_caSslContext->timerId = -1;
+#endif
+
+   ca_mutex_unlock(g_sslContextMutex);
+#ifdef __WITH_DTLS__
+    StartRetransmit();
+#endif
 
     OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
     return CA_STATUS_OK;
@@ -1384,15 +1561,29 @@ CAResult_t CAencryptSsl(const CAEndpoint_t *endpoint,
 
     if (MBEDTLS_SSL_HANDSHAKE_OVER == tep->ssl.state)
     {
-        ret = mbedtls_ssl_write(&tep->ssl, (unsigned char *) data, dataLen);
+        unsigned char *dataBuf = (unsigned char *)data;
+        size_t written = 0;
 
-        if(ret < 0)
+        do
         {
-            OIC_LOG_V(ERROR, NET_SSL_TAG, "mbedTLS write returned %d", ret);
-            RemovePeerFromList(&tep->sep.endpoint);
-            ca_mutex_unlock(g_sslContextMutex);
-            return CA_STATUS_FAILED;
-        }
+            ret = mbedtls_ssl_write(&tep->ssl, dataBuf, dataLen - written);
+            if (ret < 0)
+            {
+                if (MBEDTLS_ERR_SSL_WANT_WRITE != ret)
+                {
+                    OIC_LOG_V(ERROR, NET_SSL_TAG, "mbedTLS write failed! returned 0x%x", -ret);
+                    RemovePeerFromList(&tep->sep.endpoint);
+                    ca_mutex_unlock(g_sslContextMutex);
+                    return CA_STATUS_FAILED;
+                }
+                continue;
+            }
+            OIC_LOG_V(DEBUG, NET_SSL_TAG, "mbedTLS write returned with sent bytes[%d]", ret);
+
+            dataBuf += ret;
+            written += ret;
+        } while (dataLen > written);
+
     }
     else
     {
@@ -1429,16 +1620,27 @@ static void SendCacheMessages(SslEndPoint_t * tep)
         SslCacheMessage_t * msg = (SslCacheMessage_t *) u_arraylist_get(tep->cacheList, listIndex);
         if (NULL != msg && NULL != msg->data && 0 != msg->len)
         {
+            unsigned char *dataBuf = (unsigned char *)msg->data;
+            size_t written = 0;
+
             do
             {
-                ret = mbedtls_ssl_write(&tep->ssl, (unsigned char *) msg->data, msg->len);
-            }
-            while(MBEDTLS_ERR_SSL_WANT_WRITE == ret);
+                ret = mbedtls_ssl_write(&tep->ssl, dataBuf, msg->len - written);
+                if (ret < 0)
+                {
+                    if (MBEDTLS_ERR_SSL_WANT_WRITE != ret)
+                    {
+                        OIC_LOG_V(ERROR, NET_SSL_TAG, "mbedTLS write failed! returned -0x%x", -ret);
+                        break;
+                    }
+                    continue;
+                }
+                OIC_LOG_V(DEBUG, NET_SSL_TAG, "mbedTLS write returned with sent bytes[%d]", ret);
+
+                dataBuf += ret;
+                written += ret;
+            } while (msg->len > written);
 
-            if(ret < 0)
-            {
-                OIC_LOG_V(ERROR, NET_SSL_TAG,"mbedTLS write returned %d", ret );
-            }
             if (u_arraylist_remove(tep->cacheList, listIndex))
             {
                 DeleteCacheMessage(msg);
@@ -1466,55 +1668,6 @@ void CAsetSslHandshakeCallback(CAErrorCallback tlsHandshakeCallback)
     g_sslCallback = tlsHandshakeCallback;
     OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
 }
-// TODO move ConvertStrToUuid function to common module
-/*
- * Converts string UUID to CARemoteId_t
- *
- * @param strUuid Device UUID in string format
- * @param uuid converted UUID in CARemoteId_t format
- *
- * @return 0 for success.
- * */
-static int ConvertStrToUuid(const char* strUuid, CARemoteId_t* uuid)
-{
-    if(NULL == strUuid || NULL == uuid)
-    {
-        OIC_LOG(ERROR, NET_SSL_TAG, "ConvertStrToUuid : Invalid param");
-        return -1;
-    }
-
-    size_t urnIdx = 0;
-    size_t uuidIdx = 0;
-    size_t strUuidLen = 0;
-    char convertedUuid[UUID_LENGTH * 2] = {0};
-
-    strUuidLen = strlen(strUuid);
-    if(0 == strUuidLen)
-    {
-        OIC_LOG(INFO, NET_SSL_TAG, "The empty string detected, The UUID will be converted to "\
-                           "\"00000000-0000-0000-0000-000000000000\"");
-    }
-    else if(UUID_LENGTH * 2 + 4 == strUuidLen)
-    {
-        for(uuidIdx=0, urnIdx=0; uuidIdx < UUID_LENGTH ; uuidIdx++, urnIdx+=2)
-        {
-            if(*(strUuid + urnIdx) == '-')
-            {
-                urnIdx++;
-            }
-            sscanf(strUuid + urnIdx, "%2hhx", &convertedUuid[uuidIdx]);
-        }
-    }
-    else
-    {
-        OIC_LOG(ERROR, NET_SSL_TAG, "Invalid string uuid format");
-        return -1;
-    }
-
-    memcpy(uuid->id, convertedUuid, UUID_LENGTH);
-    uuid->id_length = UUID_LENGTH;
-    return 0;
-}
 
 /* Read data from TLS connection
  */
@@ -1622,7 +1775,8 @@ CAResult_t CAdecryptSsl(const CASecureEndpoint_t *sep, uint8_t *data, uint32_t d
                 if (NULL != uuidPos)
                 {
                     memcpy(uuid, (char*) uuidPos + sizeof(UUID_PREFIX) - 1, UUID_LENGTH * 2 + 4);
-                    ret = ConvertStrToUuid(uuid, &peer->sep.identity);
+                    OIC_LOG_V(DEBUG, NET_SSL_TAG, "certificate uuid string: %s" , uuid);
+                    ret = OCConvertStringToUuid(uuid, peer->sep.identity.id);
                     SSL_CHECK_FAIL(peer, ret, "Failed to convert subject", 1,
                                           CA_STATUS_FAILED, MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT);
                 }
@@ -1636,7 +1790,7 @@ CAResult_t CAdecryptSsl(const CASecureEndpoint_t *sep, uint8_t *data, uint32_t d
                 if (NULL != userIdPos)
                 {
                     memcpy(uuid, (char*) userIdPos + sizeof(USERID_PREFIX) - 1, UUID_LENGTH * 2 + 4);
-                    ret = ConvertStrToUuid(uuid, &peer->sep.userId);
+                    ret = OCConvertStringToUuid(uuid, peer->sep.userId.id);
                     SSL_CHECK_FAIL(peer, ret, "Failed to convert subject alt name", 1,
                                       CA_STATUS_FAILED, MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT);
                 }
@@ -1660,7 +1814,11 @@ CAResult_t CAdecryptSsl(const CASecureEndpoint_t *sep, uint8_t *data, uint32_t d
             ret = mbedtls_ssl_read(&peer->ssl, decryptBuffer, TLS_MSG_BUF_LEN);
         } while (MBEDTLS_ERR_SSL_WANT_READ == ret);
 
-        if (MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY == ret)
+        if (MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY == ret ||
+            // TinyDTLS sends fatal close_notify alert
+            (MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE == ret &&
+             MBEDTLS_SSL_ALERT_LEVEL_FATAL == peer->ssl.in_msg[0] &&
+             MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY == peer->ssl.in_msg[1]))
         {
             OIC_LOG(INFO, NET_SSL_TAG, "Connection was closed gracefully");
             SSL_CLOSE_NOTIFY(peer, ret);
@@ -1821,6 +1979,50 @@ CAResult_t CAsetTlsCipherSuite(const uint32_t cipher)
             g_caSslContext->cipher = ADAPTER_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256;
             break;
         }
+        case MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM:
+        {
+            if (false == g_caSslContext->cipherFlag[1])
+            {
+                OIC_LOG(ERROR, NET_SSL_TAG, "No Credential for ECC");
+                return CA_STATUS_FAILED;
+            }
+#ifdef __WITH_TLS__
+            mbedtls_ssl_conf_ciphersuites(&g_caSslContext->clientTlsConf,
+                                         tlsCipher[ADAPTER_TLS_ECDHE_ECDSA_WITH_AES_128_CCM]);
+            mbedtls_ssl_conf_ciphersuites(&g_caSslContext->serverTlsConf,
+                                         tlsCipher[ADAPTER_TLS_ECDHE_ECDSA_WITH_AES_128_CCM]);
+#endif
+#ifdef __WITH_DTLS__
+            mbedtls_ssl_conf_ciphersuites(&g_caSslContext->clientDtlsConf,
+                                         tlsCipher[ADAPTER_TLS_ECDHE_ECDSA_WITH_AES_128_CCM]);
+            mbedtls_ssl_conf_ciphersuites(&g_caSslContext->serverDtlsConf,
+                                         tlsCipher[ADAPTER_TLS_ECDHE_ECDSA_WITH_AES_128_CCM]);
+#endif
+            g_caSslContext->cipher = ADAPTER_TLS_ECDHE_ECDSA_WITH_AES_128_CCM;
+            break;
+        }
+        case MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:
+        {
+            if (false == g_caSslContext->cipherFlag[1])
+            {
+                OIC_LOG(ERROR, NET_SSL_TAG, "No Credential for ECC");
+                return CA_STATUS_FAILED;
+            }
+#ifdef __WITH_TLS__
+            mbedtls_ssl_conf_ciphersuites(&g_caSslContext->clientTlsConf,
+                                         tlsCipher[ADAPTER_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256]);
+            mbedtls_ssl_conf_ciphersuites(&g_caSslContext->serverTlsConf,
+                                         tlsCipher[ADAPTER_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256]);
+#endif
+#ifdef __WITH_DTLS__
+            mbedtls_ssl_conf_ciphersuites(&g_caSslContext->clientDtlsConf,
+                                         tlsCipher[ADAPTER_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256]);
+            mbedtls_ssl_conf_ciphersuites(&g_caSslContext->serverDtlsConf,
+                                         tlsCipher[ADAPTER_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256]);
+#endif
+            g_caSslContext->cipher = ADAPTER_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256;
+            break;
+        }
         default:
         {
             OIC_LOG(ERROR, NET_SSL_TAG, "Unknown cipher");
@@ -1959,6 +2161,9 @@ CAResult_t CAsslGenerateOwnerPsk(const CAEndpoint_t *endpoint,
     VERIFY_NON_NULL_RET(provServerDeviceId, NET_SSL_TAG, "provId is NULL", CA_STATUS_INVALID_PARAM);
     VERIFY_NON_NULL_RET(ownerPsk, NET_SSL_TAG, "ownerPSK is NULL", CA_STATUS_INVALID_PARAM);
 
+    // TODO: Added as workaround, need to debug
+    ca_mutex_unlock(g_sslContextMutex);
+
     ca_mutex_lock(g_sslContextMutex);
     if (NULL == g_caSslContext)
     {