replace : iotivity -> iotivity-sec
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / adapter_util / ca_adapter_net_ssl.c
index b88e2a0..7b8f60e 100644 (file)
  *
  ******************************************************************/
 
+#define MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE
+
+#ifndef _GNU_SOURCE
 #define _GNU_SOURCE
+#endif // _GNU_SOURCE
 
 #include <stddef.h>
+#include <stdint.h>
 #include <stdbool.h>
 #include "ca_adapter_net_ssl.h"
 #include "cacommon.h"
+#include "caadapterutils.h"
+#include "cainterface.h"
 #include "caipinterface.h"
 #include "oic_malloc.h"
+#include "ocrandom.h"
 #include "byte_array.h"
-#include "camutex.h"
+#include "octhread.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
+#include "pkix_interface.h"
 
-#ifndef NDEBUG
+#if !defined(NDEBUG) || defined(TB_LOG)
 #include "mbedtls/debug.h"
 #include "mbedtls/version.h"
 #endif
  * @def TLS_MSG_BUF_LEN
  * @brief Buffer size for TLS record. A single TLS record may be up to 16384 octets in length
  */
-
+#if defined (__TIZENRT__)
+#define TLS_MSG_BUF_LEN (2048)
+#else
 #define TLS_MSG_BUF_LEN (16384)
+#endif
+
 /**
  * @def PSK_LENGTH
  * @brief PSK keys max length
  */
 #define RANDOM_LEN (32)
 /**
- * @def RANDOM_LEN
- * @brief PSK generated keyblock length
+ * @def SHA384_MAC_KEY_LENGTH
+ * @brief MAC key length for SHA384 cipher suites
+ */
+#define SHA384_MAC_KEY_LENGTH (48)
+/**
+ * @def SHA256_MAC_KEY_LENGTH
+ * @brief MAC key length for SHA256 cipher suites
+ */
+#define SHA256_MAC_KEY_LENGTH (32)
+/**
+ * @def CCM_MAC_KEY_LENGTH
+ * @brief MAC key length for CCM cipher suites
+ */
+#define CCM_MAC_KEY_LENGTH (0)
+/**
+ * @def AES256_KEY_LENGTH
+ * @brief key material length for AES256 cipher suites
+ */
+#define AES256_KEY_LENGTH (32)
+/**
+ * @def AES128_KEY_LENGTH
+ * @brief key material length for AES128 cipher suites
+ */
+#define AES128_KEY_LENGTH (16)
+/**
+ * @def GCM_IV_LENGTH
+ * @brief length of nonce for GCM cipher suites
+ */
+#define GCM_IV_LENGTH (12)
+/**
+ * @def CCM_IV_LENGTH
+ * @brief length of nonce for CCM cipher suites
+ */
+#define CCM_IV_LENGTH (4)
+/**
+ * @def CBC_IV_LENGTH
+ * @brief length of nonce for CBC cipher suites
+ */
+#define CBC_IV_LENGTH (0)
+
+/**
+ * @var RETRANSMISSION_TIME
+ * @brief Maximum timeout value (in seconds) to start DTLS retransmission.
  */
-#define KEY_BLOCK_LEN (96)
+#define RETRANSMISSION_TIME 1
 
 /**@def SSL_CLOSE_NOTIFY(peer, ret)
  *
@@ -157,30 +214,62 @@ 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] error 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)                                          \
-if (0 != (ret) && MBEDTLS_ERR_SSL_WANT_READ != (int) (ret) &&                                      \
-    MBEDTLS_ERR_SSL_WANT_WRITE != (int) (ret) &&                                                   \
+if (0 != (ret) && MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY != (int) (ret) &&                              \
     MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED != (int) (ret) &&                                        \
-    MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY != (int) (ret))                                              \
+    MBEDTLS_ERR_SSL_WANT_READ != (int) (ret) &&                                                    \
+    MBEDTLS_ERR_SSL_WANT_WRITE != (int) (ret) &&                                                   \
+    MBEDTLS_ERR_SSL_NON_FATAL != (int) (ret) &&                                                    \
+    MBEDTLS_SSL_ALERT_MSG_USER_CANCELED != (int) (ret) &&                                          \
+    MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION != (int) (ret) &&                                       \
+    MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT != (int) (ret) &&                                        \
+    MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY != (int) (ret) &&                                           \
+    MBEDTLS_SSL_ALERT_MSG_NO_CERT != (int) (ret) &&                                                \
+    MBEDTLS_SSL_ALERT_MSG_BAD_CERT != (int) (ret) &&                                               \
+    MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT != (int) (ret) &&                                       \
+    MBEDTLS_SSL_ALERT_MSG_CERT_REVOKED != (int) (ret) &&                                           \
+    MBEDTLS_SSL_ALERT_MSG_CERT_EXPIRED != (int) (ret) &&                                           \
+    MBEDTLS_SSL_ALERT_MSG_CERT_UNKNOWN != (int) (ret) &&                                           \
+    MBEDTLS_SSL_ALERT_MSG_INAPROPRIATE_FALLBACK != (int) (ret) &&                                  \
+    MBEDTLS_SSL_ALERT_MSG_UNRECOGNIZED_NAME != (int) (ret) &&                                      \
+    MBEDTLS_SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY != (int) (ret) &&                                   \
+    MBEDTLS_SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL != (int) (ret))                                  \
 {                                                                                                  \
     OIC_LOG_V(ERROR, NET_SSL_TAG, "%s: -0x%x", (str), -(ret));                                     \
     if ((int) MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE != (int) (ret) &&                                \
-       (int) MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO != (int) (ret))                                   \
+        (int) MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO != (int) (ret))                                  \
     {                                                                                              \
         mbedtls_ssl_send_alert_message(&(peer)->ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, (msg));        \
     }                                                                                              \
-    SSL_RES((peer), CA_STATUS_FAILED);                                                             \
     RemovePeerFromList(&(peer)->sep.endpoint);                                                     \
     if (mutex)                                                                                     \
     {                                                                                              \
-        ca_mutex_unlock(g_sslContextMutex);                                                        \
+        oc_mutex_unlock(g_sslContextMutex);                                                        \
+    }                                                                                              \
+    if ((int) MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO != (int)(ret))                                   \
+    {                                                                                              \
+        SSL_RES((peer), CA_DTLS_AUTHENTICATION_FAILURE);                                           \
     }                                                                                              \
     OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);                                             \
-    return (error);                                                                                \
+    if (-1 != (intptr_t)error)                                                                               \
+    {                                                                                              \
+        return (error);                                                                            \
+    }                                                                                              \
 }
+
+/**@def CONF_SSL(clientConf, serverConf, fn, ...)
+ *
+ * Calls \a fn for \a clientConf and \a serverConf.
+ *
+ */
+#define CONF_SSL(clientConf, serverConf, fn, ...) do {                                             \
+fn((clientConf), __VA_ARGS__);                                                                     \
+fn((serverConf), __VA_ARGS__);                                                                     \
+} while (0)
+
 /** @def CHECK_MBEDTLS_RET(f, ...)
  * A macro that checks \a f function return code
  *
@@ -193,16 +282,25 @@ int ret = (f)(__VA_ARGS__);
 if (0 != ret) {                                                                                    \
     OIC_LOG_V(ERROR, NET_SSL_TAG, "%s returned -0x%04x\n", __func__, -(ret));                      \
     goto exit;                                                                                     \
-} } while(0)
+} } while (0)
 
 typedef enum
 {
-    ADAPTER_TLS_RSA_WITH_AES_256_CBC_SHA,
-    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_CIPHER_MAX
-} AdapterCipher_t;
+    SSL_RSA_WITH_AES_256_CBC_SHA256,
+    SSL_RSA_WITH_AES_128_GCM_SHA256,
+    SSL_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+    SSL_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
+    SSL_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
+    SSL_ECDHE_ECDSA_WITH_AES_128_CCM_8,
+    SSL_ECDHE_ECDSA_WITH_AES_128_CCM,
+    SSL_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
+    SSL_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
+    SSL_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
+    SSL_ECDHE_PSK_WITH_AES_128_CBC_SHA256,
+    SSL_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
+    SSL_ECDH_ANON_WITH_AES_128_CBC_SHA256,
+    SSL_CIPHER_MAX
+} SslCipher_t;
 
 typedef enum
 {
@@ -210,15 +308,35 @@ typedef enum
     ADAPTER_CURVE_MAX
 } AdapterCurve_t;
 
-int tlsCipher[ADAPTER_CIPHER_MAX][2] =
+static const int tlsCipher[SSL_CIPHER_MAX][2] =
 {
-    {MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA, 0},
+    {MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256, 0},
+    {MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256, 0},
+    {MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0},
+    {MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 0},
+    {MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 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_ECDSA_WITH_AES_128_CCM, 0},
+    {MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, 0},
+    {MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, 0},
+    {MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 0},
+    {MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, 0},
+    {MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, 0},
+    {MBEDTLS_TLS_ECDH_ANON_WITH_AES_128_CBC_SHA256, 0}
 };
 
-static int g_cipherSuitesList[ADAPTER_CIPHER_MAX];
+static int g_cipherSuitesList[SSL_CIPHER_MAX];
+
+static int g_ssl_ordered_default_hashes[] = {
+#if defined(MBEDTLS_SHA256_C)
+    MBEDTLS_MD_SHA256,
+    MBEDTLS_MD_SHA224,
+#endif
+#if defined(MBEDTLS_SHA1_C)
+    MBEDTLS_MD_SHA1,
+#endif
+    MBEDTLS_MD_NONE
+};
 
 mbedtls_ecp_group_id curve[ADAPTER_CURVE_MAX][2] =
 {
@@ -270,7 +388,7 @@ static int GetAlertCode(uint32_t flags)
     return 0;
 }
 
-#ifndef NDEBUG
+#if !defined(NDEBUG) || defined(TB_LOG)
 /**
  * Pass a message to the OIC logger.
  *
@@ -291,7 +409,7 @@ static void DebugSsl(void *ctx, int level, const char *file, int line, const cha
 }
 #endif
 
-#if defined(_WIN32)
+#if defined(_WIN32) || defined (__TIZENRT__)
 /*
  * Finds the first occurrence of the byte string s in byte string l.
  */
@@ -360,16 +478,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;
+
+    SslCipher_t cipher;
     SslCallbacks_t adapterCallbacks[MAX_SUPPORTED_ADAPTERS];
     mbedtls_x509_crl crl;
     bool cipherFlag[2];
     int selectedCipher;
 
+#ifdef __WITH_DTLS__
+    mbedtls_ssl_cookie_ctx cookieCtx;
+    int timerId;
+#endif
 } SslContext_t;
 
 /**
@@ -378,6 +497,10 @@ typedef struct SslContext
  */
 static SslContext_t * g_caSslContext = NULL;
 
+static SslExportKeysCallback_t gTlsExportKeysCallback = NULL;
+
+static SslExportKeysCallback_t gDtlsExportKeysCallback = NULL;
+
 /**
  * @var g_getCredentialsCallback
  * @brief callback to get TLS credentials (same as for DTLS)
@@ -396,10 +519,17 @@ static CAgetCredentialTypesHandler g_getCredentialTypesCallback = NULL;
 static CAgetPkixInfoHandler g_getPkixInfoCallback = NULL;
 
 /**
+ * @var g_setupPkContextCallback
+ *
+ * @brief callback to setup PK context handler for H/W based Public Key Infrastructure
+ */
+static CAsetupPkContextHandler g_setupPkContextCallback = NULL;
+
+/**
  * @var g_dtlsContextMutex
  * @brief Mutex to synchronize access to g_caSslContext.
  */
-static ca_mutex g_sslContextMutex = NULL;
+static oc_mutex g_sslContextMutex = NULL;
 
 /**
  * @var g_sslCallback
@@ -408,6 +538,28 @@ static ca_mutex g_sslContextMutex = NULL;
 static CAErrorCallback g_sslCallback = NULL;
 
 /**
+ * Data structure for PeerCertCallback.
+ */
+typedef struct
+{
+    PeerCertCallback cb;
+    void *ctx;
+} PeerCertCallback_t;
+
+/**
+ * @var g_peerCertCallback
+ *
+ * @brief callback to utilize peer certificate information
+ */
+static PeerCertCallback_t g_peerCertCallback = {NULL, NULL};
+
+/**
+ * @var g_decryptBuffer
+ * @brief decrypt buffer which will be used for decryption
+ */
+static uint8_t *g_decryptBuffer = NULL;
+
+/**
  * Data structure for holding the data to be received.
  */
 typedef struct SslRecBuf
@@ -429,9 +581,8 @@ typedef struct SslEndPoint
     uint8_t master[MASTER_SECRET_LEN];
     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)
@@ -448,6 +599,14 @@ void CAsetPkixInfoCallback(CAgetPkixInfoHandler infoCallback)
     g_getPkixInfoCallback = infoCallback;
     OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
 }
+
+void CAsetSetupPkContextCallback(CAsetupPkContextHandler setupPkCtxCallback)
+{
+    OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s", __func__);
+    g_setupPkContextCallback = setupPkCtxCallback;
+    OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
+}
+
 void CAsetCredentialTypesCallback(CAgetCredentialTypesHandler credTypesCallback)
 {
     OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s", __func__);
@@ -463,6 +622,8 @@ static int GetAdapterIndex(CATransportAdapter_t adapter)
             return 0;
         case CA_ADAPTER_TCP:
             return 1;
+        case CA_ADAPTER_GATT_BTLE:
+            return 2;
         default:
             OIC_LOG(ERROR, NET_SSL_TAG, "Unsupported adapter");
             return -1;
@@ -475,29 +636,42 @@ 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);
+    OIC_LOG_V(INFO, NET_SSL_TAG, "In %s", __func__);
+    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);
+    VERIFY_NON_NULL_RET(g_caSslContext, NET_SSL_TAG, "SSL Context 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)
+    if (0 <= adapterIndex && MAX_SUPPORTED_ADAPTERS > 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 < 0)
+        {
+            OIC_LOG_V(ERROR, NET_SSL_TAG, "sendCallback() is Failed(%zd)", sentLen);
+            return -1;
+        }
+        else if ((size_t)sentLen != dataLen)
+        {
+            OIC_LOG_V(DEBUG, NET_SSL_TAG,
+                    "Packet was partially sent - total/sent/remained bytes : %zd/%zu/%lu",
+                    sentLen, dataLen, (dataLen - sentLen));
+        }
     }
     else
     {
         OIC_LOG(ERROR, NET_SSL_TAG, "Unsupported adapter");
-        dataLen = 0;
+        return -1;
     }
 
-    OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
-    return dataLen;
+    OIC_LOG_V(INFO, NET_SSL_TAG, "Out %s", __func__);
+    return sentLen;
 }
 /**
  * Read callback.
@@ -525,27 +699,138 @@ static int RecvCallBack(void * tep, unsigned char * data, size_t dataLen)
     return (int)retLen;
 }
 
+static int CASslExportKeysHandler(void *p_expkey,
+                                const unsigned char *ms,
+                                const unsigned char *kb,
+                                size_t maclen,
+                                size_t keylen,
+                                size_t ivlen)
+{
+    OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s", __func__);
+
+    if (NULL == g_caSslContext)
+    {
+        OIC_LOG(ERROR, NET_SSL_TAG, "SSL Context is not initialized.");
+        return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
+    }
+    if (NULL == p_expkey)
+    {
+        OIC_LOG(ERROR, NET_SSL_TAG, "Can not find the protocol information from 'p_expkey'.");
+        return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
+    }
+
+    CASslEkcbProtocol_t* protocol = (CASslEkcbProtocol_t*)p_expkey;
+
+    if (gTlsExportKeysCallback && CA_SSL_EKCB_TLS == (*protocol))
+    {
+        OIC_LOG(DEBUG, NET_SSL_TAG, "Invoking TLS export key callback.");
+        gTlsExportKeysCallback(ms, kb, maclen, keylen, ivlen);
+    }
+    else if (gDtlsExportKeysCallback && CA_SSL_EKCB_DTLS == (*protocol))
+    {
+        OIC_LOG(DEBUG, NET_SSL_TAG, "Invoking DTLS export key callback.");
+        gDtlsExportKeysCallback(ms, kb, maclen, keylen, ivlen);
+    }
+    else
+    {
+        OIC_LOG(ERROR, NET_SSL_TAG, "Failed to Invoke (D)TLS export key callback.");
+        return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
+    }
+
+    OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
+    return 0;
+}
+
+CAResult_t CASetSslExportKeysCallback(SslExportKeysCallback_t exportKeysCb,
+                                      CASslEkcbProtocol_t protocol, CASslEkcbRole_t role)
+{
+    OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s", __func__);
+    mbedtls_ssl_config* sslConf = NULL;
+    static CASslEkcbProtocol_t protocolCtx = CA_SSL_EKCB_TLS;
+
+    if (CA_SSL_EKCB_TLS != protocol && CA_SSL_EKCB_DTLS != protocol)
+    {
+        OIC_LOG(ERROR, NET_SSL_TAG, "Invaild protocol.");
+        return CA_STATUS_INVALID_PARAM;
+    }
+    if (CA_SSL_EKCB_CLIENT != role && CA_SSL_EKCB_SERVER != role)
+    {
+        OIC_LOG(ERROR, NET_SSL_TAG, "Invaild role.");
+        return CA_STATUS_INVALID_PARAM;
+    }
+
+    OIC_LOG_V(DEBUG, NET_SSL_TAG, "TLS Export Key Callback Type : [%s] [%s]",
+              (CA_SSL_EKCB_TLS == protocol ? "TLS" : "DTLS"),
+              (CA_SSL_EKCB_CLIENT == role ? "Client" : "Server"));
+
+    oc_mutex_lock(g_sslContextMutex);
+    if (NULL == g_caSslContext)
+    {
+        OIC_LOG(ERROR, NET_SSL_TAG, "SSL Context is not initialized.");
+        oc_mutex_unlock(g_sslContextMutex);
+        return CA_STATUS_NOT_INITIALIZED;
+    }
+
+    if (CA_SSL_EKCB_TLS == protocol)
+    {
+        gTlsExportKeysCallback = exportKeysCb;
+        if (CA_SSL_EKCB_CLIENT == role)
+        {
+            sslConf = &g_caSslContext->clientTlsConf;
+        }
+        else
+        {
+            sslConf = &g_caSslContext->serverTlsConf;
+        }
+    }
+    else
+    {
+        gDtlsExportKeysCallback = exportKeysCb;
+        if (CA_SSL_EKCB_CLIENT == role)
+        {
+            sslConf = &g_caSslContext->clientDtlsConf;
+        }
+        else
+        {
+            sslConf = &g_caSslContext->serverDtlsConf;
+        }
+    }
+    protocolCtx = protocol;
+
+    if (NULL == exportKeysCb)
+    {
+        mbedtls_ssl_conf_export_keys_cb(sslConf, NULL, NULL);
+        OIC_LOG(DEBUG, NET_SSL_TAG, "Export key callback unregistered.");
+    }
+    else
+    {
+        mbedtls_ssl_conf_export_keys_cb(sslConf, CASslExportKeysHandler, (void*)(&protocolCtx));
+        OIC_LOG(DEBUG, NET_SSL_TAG, "Export key callback registered.");
+    }
+    oc_mutex_unlock(g_sslContextMutex);
+
+    OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
+
+    return CA_STATUS_OK;
+}
+
 /**
  * Parse chain of X.509 certificates.
  *
  * @param[out] crt     container for X.509 certificates
  * @param[in]  data    buffer with X.509 certificates. Certificates may be in either in PEM
-                       or DER format in a jumble. Each PEM certificate must be NULL-terminated.
+                       or DER format in a jumble, delimiting symbols does not matter.
  * @param[in]  bufLen  buffer length
+ * @param[in]  errNum  number certificates that failed to parse
  *
- * @return  0 on success, -1 on error
+ * @return  number of successfully parsed certificates or -1 on error
  */
-static int ParseChain(mbedtls_x509_crt * crt, const unsigned char * buf, int bufLen)
+static int ParseChain(mbedtls_x509_crt * crt, unsigned char * buf, size_t bufLen, int * errNum)
 {
     OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s", __func__);
     VERIFY_NON_NULL_RET(crt, NET_SSL_TAG, "Param crt is NULL" , -1);
     VERIFY_NON_NULL_RET(buf, NET_SSL_TAG, "Param buf is NULL" , -1);
 
-    int pos = 0;
-    int ret = 0;
-    size_t len = 0;
-    unsigned char * tmp = NULL;
-
     char pemCertHeader[] = {
         0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x43, 0x45, 0x52,
         0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d
@@ -557,6 +842,13 @@ static int ParseChain(mbedtls_x509_crt * crt, const unsigned char * buf, int buf
     size_t pemCertHeaderLen = sizeof(pemCertHeader);
     size_t pemCertFooterLen = sizeof(pemCertFooter);
 
+    size_t len = 0;
+    unsigned char * tmp = NULL;
+    int count = 0;
+    int ret = 0;
+    size_t pos = 0;
+
+    *errNum = 0;
     while (pos < bufLen)
     {
         if (buf[pos] == 0x30 && buf[pos + 1] == 0x82)
@@ -565,11 +857,21 @@ static int ParseChain(mbedtls_x509_crt * crt, const unsigned char * buf, int buf
             CHECK_MBEDTLS_RET(mbedtls_asn1_get_len, &tmp, buf + bufLen, &len);
             if (pos + len < bufLen)
             {
-                CHECK_MBEDTLS_RET(mbedtls_x509_crt_parse_der, crt, buf + pos, len + 4);
+                ret = mbedtls_x509_crt_parse_der(crt, buf + pos, len + 4);
+                if (0 == ret)
+                {
+                    count++;
+                }
+                else
+                {
+                    (*errNum)++;
+                    OIC_LOG_V(ERROR, NET_SSL_TAG, "mbedtls_x509_crt_parse_der returned -0x%04x\n", -(ret));
+                }
             }
             pos += len + 4;
         }
-        else if (0 == memcmp(buf + pos, pemCertHeader, pemCertHeaderLen))
+        else if ((buf + pos + pemCertHeaderLen < buf + bufLen) &&
+                 (0 == memcmp(buf + pos, pemCertHeader, pemCertHeaderLen)))
         {
             void * endPos = NULL;
             endPos = memmem(&(buf[pos]), bufLen - pos, pemCertFooter, pemCertFooterLen);
@@ -579,47 +881,124 @@ static int ParseChain(mbedtls_x509_crt * crt, const unsigned char * buf, int buf
                 OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
                 return -1;
             }
-            if ((*((char*)endPos + pemCertFooterLen + 0) == 0x0d) &&
-                (*((char*)endPos + pemCertFooterLen + 1) == 0x0a) &&
-                (*((char*)endPos + pemCertFooterLen + 2) == 0x00))
-            {
-                len = (char*)endPos - ((char*)buf + pos) + pemCertFooterLen + 3;
-            }
-            else if ((*((char*)endPos + pemCertFooterLen + 0) == 0x0a) &&
-                     (*((char*)endPos + pemCertFooterLen + 1) == 0x00))
+            len = (char*)endPos - ((char*)buf + pos) + pemCertFooterLen;
+            if (pos + len + 1 <= bufLen)
             {
-                len = (char*)endPos - ((char*)buf + pos) + pemCertFooterLen + 2;
+                char con = buf[pos + len];
+                buf[pos + len] = 0x00;
+                ret = mbedtls_x509_crt_parse(crt, buf + pos, len + 1);
+                if (0 == ret)
+                {
+                    count++;
+                }
+                else
+                {
+                    (*errNum)++;
+                    OIC_LOG_V(ERROR, NET_SSL_TAG, "mbedtls_x509_crt_parse returned -0x%04x\n", -(ret));
+                }
+                buf[pos + len] = con;
             }
             else
             {
-                OIC_LOG_V(ERROR, NET_SSL_TAG, "Incorrect PEM certificate ending");
-                OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
-                return -1;
+                unsigned char * lastCert = (unsigned char *)OICMalloc((len + 1) * sizeof(unsigned char));
+                memcpy(lastCert, buf + pos, len);
+                lastCert[len] = 0x00;
+                ret = mbedtls_x509_crt_parse(crt, lastCert, len + 1);
+                if (0 == ret)
+                {
+                    count++;
+                }
+                else
+                {
+                    (*errNum)++;
+                    OIC_LOG_V(ERROR, NET_SSL_TAG, "mbedtls_x509_crt_parse returned -0x%04x\n", -(ret));
+                }
+                OICFree(lastCert);
             }
-            CHECK_MBEDTLS_RET(mbedtls_x509_crt_parse, crt, buf + pos, len);
             pos += len;
         }
         else
         {
-             OIC_LOG_BUFFER(DEBUG, NET_SSL_TAG, buf, bufLen);
-             OIC_LOG_V(ERROR, NET_SSL_TAG, "parseChain returned -0x%x", -ret);
-             OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
-             return -1;
+            pos++;
         }
     }
+    OIC_LOG_V(INFO, NET_SSL_TAG, "%s successfully parsed %d certificates", __func__, count);
     OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
-    return 0;
+    return count;
 
 exit:
     return -1;
 }
 
+static int VerifyCertificateCallback(void *p_vrfy, mbedtls_x509_crt *crt, int depth,
+        uint32_t *flags)
+{
+    (void)p_vrfy;
+    char buf[1024] = {0};
+
+    if (0 != *flags) // Invalid Cerificate
+    {
+        int ret;
+        ret = mbedtls_x509_crt_verify_info(buf, sizeof(buf), "", *flags);
+        if (0 < ret)
+        {
+            OIC_LOG_V(ERROR, NET_SSL_TAG, "%s(%d)", buf, *flags);
+        }
+        return 1;
+    }
+
+    if (NULL == g_peerCertCallback.cb)
+    {
+        OIC_LOG(DEBUG, NET_SSL_TAG, "NOT SET g_peerCertCallback");
+        return 0;
+    }
+
+    /*
+     * e.g.
+     * depth = 0 : Own Cert.
+     * depth = 1 : Sub CA Cert.
+     * depth = 2 : Root CA Cert.
+     */
+    OIC_LOG_V(INFO, NET_SSL_TAG, "Depth : %d", depth);
+
+    mbedtls_x509_crt_info(buf, sizeof(buf) - 1, "", crt);
+    OIC_LOG_V(DEBUG, NET_SSL_TAG, "crt : %s", buf);
+
+    g_peerCertCallback.cb(g_peerCertCallback.ctx, crt, depth);
+
+    return 0;
+}
+
+CAResult_t CAsetPeerCertCallback(void *ctx, PeerCertCallback peerCertCallback)
+{
+#ifndef __WITH_DTLS__
+    UNUSED(ctx);
+    UNUSED(peerCertCallback);
+    OIC_LOG(ERROR, NET_SSL_TAG, "Not Supported");
+    return CA_NOT_SUPPORTED;
+#endif
+
+    if (peerCertCallback)
+    {
+        OIC_LOG(DEBUG, NET_SSL_TAG, "SET peerCertCallback");
+        g_peerCertCallback.cb = peerCertCallback;
+        g_peerCertCallback.ctx = ctx;
+    }
+    else
+    {
+        OIC_LOG(DEBUG, NET_SSL_TAG, "UNSET peerCertCallback");
+        g_peerCertCallback.cb = NULL;
+        g_peerCertCallback.ctx = NULL;
+    }
+    return CA_STATUS_OK;
+}
+
 //Loads PKIX related information from SRM
 static int InitPKIX(CATransportAdapter_t adapter)
 {
-    OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s", __func__);
+    OIC_LOG_V(INFO, NET_SSL_TAG, "In %s", __func__);
     VERIFY_NON_NULL_RET(g_getPkixInfoCallback, NET_SSL_TAG, "PKIX info callback is NULL", -1);
-    g_getPkixInfoCallback(&g_pkiInfo);
+    VERIFY_NON_NULL_RET(g_caSslContext, NET_SSL_TAG, "SSL Context is NULL", -1);
 
     mbedtls_x509_crt_free(&g_caSslContext->ca);
     mbedtls_x509_crt_free(&g_caSslContext->crt);
@@ -631,19 +1010,88 @@ static int InitPKIX(CATransportAdapter_t adapter)
     mbedtls_pk_init(&g_caSslContext->pkey);
     mbedtls_x509_crl_init(&g_caSslContext->crl);
 
-    mbedtls_ssl_config * serverConf = (adapter == CA_ADAPTER_IP ?
+    mbedtls_ssl_config * serverConf = (adapter == CA_ADAPTER_IP ||
+                                   adapter == CA_ADAPTER_GATT_BTLE ?
                                    &g_caSslContext->serverDtlsConf : &g_caSslContext->serverTlsConf);
-    mbedtls_ssl_config * clientConf = (adapter == CA_ADAPTER_IP ?
+    mbedtls_ssl_config * clientConf = (adapter == CA_ADAPTER_IP ||
+                                   adapter == CA_ADAPTER_GATT_BTLE ?
                                    &g_caSslContext->clientDtlsConf : &g_caSslContext->clientTlsConf);
-    // optional
-    int ret = ParseChain(&g_caSslContext->crt, g_pkiInfo.crt.data, g_pkiInfo.crt.len);
-    if (0 != ret)
+
+#ifdef __WITH_DTLS__
+    /*
+     * Conf. is initialized in CAinitSslAdapter()
+     */
+    mbedtls_ssl_conf_verify(&g_caSslContext->clientDtlsConf, VerifyCertificateCallback, NULL);
+#endif
+
+    // load pk key, cert, trust chain and crl
+    if (g_getPkixInfoCallback)
+    {
+        OIC_LOG(INFO, NET_SSL_TAG, "g_getPkixInfoCallback will be invoked");
+        g_getPkixInfoCallback(&g_pkiInfo);
+    }
+
+    // parse own certficate (optional)
+    int ret;
+    int errNum;
+    int count = ParseChain(&g_caSslContext->crt, g_pkiInfo.crt.data, g_pkiInfo.crt.len, &errNum);
+    if (0 >= count)
     {
         OIC_LOG(WARNING, NET_SSL_TAG, "Own certificate chain parsing error");
         goto required;
     }
-    ret =  mbedtls_pk_parse_key(&g_caSslContext->pkey, g_pkiInfo.key.data, g_pkiInfo.key.len,
-                                                                               NULL, 0);
+    if (0 != errNum)
+    {
+        OIC_LOG_V(WARNING, NET_SSL_TAG, "Own certificate chain parsing error: %d certs failed to parse", errNum);
+        goto required;
+    }
+
+    // parse private key if hw is not supported (optional)
+    if(NULL == g_setupPkContextCallback)
+    {
+        OIC_LOG(INFO, NET_SSL_TAG, "g_setupPkContextCallback is NULL");
+        ret =  mbedtls_pk_parse_key(&g_caSslContext->pkey, g_pkiInfo.key.data, g_pkiInfo.key.len,
+                                                                                   NULL, 0);
+    }
+    else
+    {
+        OIC_LOG(INFO, NET_SSL_TAG, "g_setupPkContextCallback will be invoked");
+        // setup hw pk context (optional)
+        ret = g_setupPkContextCallback(&g_caSslContext->pkey);
+        if (0 == ret)
+        {
+            // setup public parameter
+            mbedtls_pk_type_t ktype = mbedtls_pk_get_type(&g_caSslContext->pkey);
+            if (MBEDTLS_PK_ECKEY == ktype || MBEDTLS_PK_ECKEY_DH == ktype
+                || MBEDTLS_PK_ECDSA == ktype)
+            {
+                OIC_LOG_V(DEBUG, NET_SSL_TAG, "Copy ecp public param from cert, keytype [%d]", ktype);
+                mbedtls_ecp_keypair *eckey = (mbedtls_ecp_keypair*)g_caSslContext->crt.pk.pk_ctx;
+                mbedtls_ecdsa_context *ecdsa = (mbedtls_ecdsa_context*)g_caSslContext->pkey.pk_ctx;
+                if (ecdsa && eckey)
+                {
+                    ret = mbedtls_ecdsa_from_keypair(ecdsa, eckey);
+                    if(0 != ret )
+                    {
+                        OIC_LOG_V(ERROR, NET_SSL_TAG, "Fail to copy public param [0x%x]", ret);
+                    }
+                }
+                else
+                {
+                    OIC_LOG_V(WARNING, NET_SSL_TAG, "key-ctx(%p), cert-ctx(%p)", ecdsa, eckey);
+                    goto required;
+                }
+            }
+            else
+            {
+                OIC_LOG_V(INFO, NET_SSL_TAG, "loaded key is not one of eckey type [%d]", ktype);
+            }
+        }
+        else
+        {
+            OIC_LOG_V(ERROR, NET_SSL_TAG, "Fail to call g_setupPkContextCallback [%d]", ret);
+        }
+    }
     if (0 != ret)
     {
         OIC_LOG(WARNING, NET_SSL_TAG, "Key parsing error");
@@ -664,28 +1112,32 @@ static int InitPKIX(CATransportAdapter_t adapter)
     }
 
     required:
-    ret = ParseChain(&g_caSslContext->ca, g_pkiInfo.ca.data, g_pkiInfo.ca.len);
-    if(0 != ret)
+    count = ParseChain(&g_caSslContext->ca, g_pkiInfo.ca.data, g_pkiInfo.ca.len, &errNum);
+    if(0 >= count)
     {
-        OIC_LOG(ERROR, NET_SSL_TAG, "CA chain parsing error");
+        OIC_LOG(WARNING, NET_SSL_TAG, "CA chain in svr db was not parsed");
+        OIC_LOG(WARNING, NET_SSL_TAG, "    but if working as server, chain not required");
         OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
         return -1;
     }
+    if(0 != errNum)
+    {
+        OIC_LOG_V(WARNING, NET_SSL_TAG, "CA chain parsing warning: %d certs failed to parse", errNum);
+    }
 
     ret = mbedtls_x509_crl_parse_der(&g_caSslContext->crl, g_pkiInfo.crl.data, g_pkiInfo.crl.len);
     if(0 != ret)
     {
-        OIC_LOG(WARNING, NET_SSL_TAG, "CRL parsing error");
-        mbedtls_ssl_conf_ca_chain(clientConf, &g_caSslContext->ca, NULL);
-        mbedtls_ssl_conf_ca_chain(serverConf, &g_caSslContext->ca, NULL);
+        OIC_LOG(WARNING, NET_SSL_TAG, "CRL in svr db was not parsed");
+        CONF_SSL(clientConf, serverConf, mbedtls_ssl_conf_ca_chain, &g_caSslContext->ca, NULL);
     }
     else
     {
-        mbedtls_ssl_conf_ca_chain(clientConf, &g_caSslContext->ca, &g_caSslContext->crl);
-        mbedtls_ssl_conf_ca_chain(serverConf, &g_caSslContext->ca, &g_caSslContext->crl);
+        CONF_SSL(clientConf, serverConf, mbedtls_ssl_conf_ca_chain,
+                 &g_caSslContext->ca, &g_caSslContext->crl);
     }
 
-    OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
+    OIC_LOG_V(INFO, NET_SSL_TAG, "Out %s", __func__);
     return 0;
 }
 
@@ -729,6 +1181,7 @@ static int GetPskCredentialsCallback(void * notUsed, mbedtls_ssl_context * ssl,
     OIC_LOG_V(WARNING, NET_SSL_TAG, "Out %s", __func__);
     return -1;
 }
+
 /**
  * Gets session corresponding for endpoint.
  *
@@ -742,6 +1195,7 @@ static SslEndPoint_t *GetSslPeer(const CAEndpoint_t *peer)
     uint32_t listLength = 0;
     OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s", __func__);
     VERIFY_NON_NULL_RET(peer, NET_SSL_TAG, "TLS peer is NULL", NULL);
+    VERIFY_NON_NULL_RET(g_caSslContext, NET_SSL_TAG, "SSL Context is NULL", NULL);
 
     SslEndPoint_t *tep = NULL;
     listLength = u_arraylist_length(g_caSslContext->peerList);
@@ -752,28 +1206,144 @@ static SslEndPoint_t *GetSslPeer(const CAEndpoint_t *peer)
         {
             continue;
         }
-        OIC_LOG_V(DEBUG, NET_SSL_TAG, "Compare [%s:%d] and [%s:%d]",
-                  peer->addr, peer->port, tep->sep.endpoint.addr, tep->sep.endpoint.port);
-        if((0 == strncmp(peer->addr, tep->sep.endpoint.addr, MAX_ADDR_STR_SIZE_CA))
-                && (peer->port == tep->sep.endpoint.port))
+
+        OIC_LOG_V(DEBUG, NET_SSL_TAG, "Compare [%s:%d] and [%s:%d] for %d adapter",
+                  peer->addr, peer->port, tep->sep.endpoint.addr, tep->sep.endpoint.port,
+                  peer->adapter);
+
+        if((peer->adapter == tep->sep.endpoint.adapter)
+                && (0 == strncmp(peer->addr, tep->sep.endpoint.addr, MAX_ADDR_STR_SIZE_CA))
+                && (peer->port == tep->sep.endpoint.port || CA_ADAPTER_GATT_BTLE == peer->adapter))
         {
+            OIC_LOG_V(DEBUG, NET_SSL_TAG, "Found Peer:[%s:%d] for %d adapter",
+                    peer->addr, peer->port, peer->adapter);
             OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
             return tep;
         }
     }
-    OIC_LOG(DEBUG, NET_SSL_TAG, "Return NULL");
+    OIC_LOG_V(INFO, NET_SSL_TAG, "Peer not found:[%s:%d] for %d adapter",
+            peer->addr, peer->port, peer->adapter);
     OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
     return NULL;
 }
-/**
- * Deletes cached message.
- *
- * @param[in]  msg    message
- */
-static void DeleteCacheMessage(SslCacheMessage_t * msg)
+
+bool CAIsExistSslPeer(const CAEndpoint_t *peer)
 {
-    OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s", __func__);
-    VERIFY_NON_NULL_VOID(msg, NET_SSL_TAG, "msg");
+    oc_mutex_lock(g_sslContextMutex);
+    if (NULL == g_caSslContext)
+    {
+        OIC_LOG(ERROR, NET_SSL_TAG, "Context is NULL");
+        oc_mutex_unlock(g_sslContextMutex);
+        return false;
+    }
+
+    if (GetSslPeer(peer))
+    {
+        OIC_LOG_V(DEBUG, NET_SSL_TAG, "Exist Peer");
+        oc_mutex_unlock(g_sslContextMutex);
+        return true;
+    }
+    else
+    {
+        OIC_LOG_V(DEBUG, NET_SSL_TAG, "Not Exist Peer");
+        oc_mutex_unlock(g_sslContextMutex);
+        return false;
+    }
+}
+
+/**
+ * Gets session corresponding for endpoint.
+ *
+ * @param[in]  peer    remote address
+ *
+ * @return  TLS session or NULL
+ */
+static SslEndPoint_t *GetSslPeerUsingUuid(const uint8_t *identity, size_t idLength)
+{
+    uint32_t listIndex = 0;
+    uint32_t listLength = 0;
+    OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s", __func__);
+    VERIFY_NON_NULL_RET(identity, NET_SSL_TAG, "Param identity is NULL", NULL);
+    VERIFY_NON_NULL_RET(g_caSslContext, NET_SSL_TAG, "SSL Context is NULL", NULL);
+
+    OIC_LOG(INFO, NET_SSL_TAG, "[Target UUID]");
+    OIC_LOG_BUFFER(INFO, NET_SSL_TAG, identity, idLength);
+
+    SslEndPoint_t *tep = NULL;
+    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)
+        {
+            continue;
+        }
+
+        OIC_LOG_V(DEBUG, NET_SSL_TAG, "Compare UUID for [%s:%d]",
+                  tep->sep.endpoint.addr, tep->sep.endpoint.port);
+
+        if ((tep->sep.identity.id_length == idLength)
+            && (0 == memcmp(identity, tep->sep.identity.id, idLength)))
+        {
+            OIC_LOG_V(INFO, NET_SSL_TAG, "Found matched UUID in [%s:%d]",
+                      tep->sep.endpoint.addr, tep->sep.endpoint.port);
+            OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
+            return tep;
+        }
+    }
+    OIC_LOG(INFO, NET_SSL_TAG, "Peer not found");
+    OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
+    return NULL;
+}
+
+
+#ifdef 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
+    oc_mutex_unlock(g_sslContextMutex);
+
+    oc_mutex_lock(g_sslContextMutex);
+    if (NULL == g_caSslContext)
+    {
+        OIC_LOG(ERROR, NET_SSL_TAG, "Context is NULL");
+        oc_mutex_unlock(g_sslContextMutex);
+        return NULL;
+    }
+
+    SslEndPoint_t* sslPeer = GetSslPeer(peer);
+    if(sslPeer)
+    {
+        OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
+        oc_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__);
+    oc_mutex_unlock(g_sslContextMutex);
+    return NULL;
+}
+#endif
+
+/**
+ * Deletes cached message.
+ *
+ * @param[in]  msg    message
+ */
+static void DeleteCacheMessage(SslCacheMessage_t * msg)
+{
+    OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s", __func__);
+    VERIFY_NON_NULL_VOID(msg, NET_SSL_TAG, "msg");
 
     OICFree(msg->data);
     OICFree(msg);
@@ -816,9 +1386,6 @@ static void DeleteSslEndPoint(SslEndPoint_t * tep)
     VERIFY_NON_NULL_VOID(tep, NET_SSL_TAG, "tep");
 
     mbedtls_ssl_free(&tep->ssl);
-#ifdef __WITH_DTLS__
-    mbedtls_ssl_cookie_free(&tep->cookieCtx);
-#endif
     DeleteCacheList(tep->cacheList);
     OICFree(tep);
     OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
@@ -828,10 +1395,12 @@ static void DeleteSslEndPoint(SslEndPoint_t * tep)
  *
  * @param[in]  endpoint    remote address
  */
-static void RemovePeerFromList(CAEndpoint_t * endpoint)
+static void RemovePeerFromList(const CAEndpoint_t * endpoint)
 {
-    uint32_t listLength = u_arraylist_length(g_caSslContext->peerList);
+    OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s", __func__);
+    VERIFY_NON_NULL_VOID(g_caSslContext, NET_SSL_TAG, "SSL Context is NULL");
     VERIFY_NON_NULL_VOID(endpoint, NET_SSL_TAG, "endpoint");
+    uint32_t listLength = u_arraylist_length(g_caSslContext->peerList);
     for (uint32_t listIndex = 0; listIndex < listLength; listIndex++)
     {
         SslEndPoint_t * tep = (SslEndPoint_t *)u_arraylist_get(g_caSslContext->peerList,listIndex);
@@ -840,19 +1409,28 @@ static void RemovePeerFromList(CAEndpoint_t * endpoint)
             continue;
         }
         if(0 == strncmp(endpoint->addr, tep->sep.endpoint.addr, MAX_ADDR_STR_SIZE_CA)
-                && (endpoint->port == tep->sep.endpoint.port))
+                && (endpoint->port == tep->sep.endpoint.port || CA_ADAPTER_GATT_BTLE == endpoint->adapter))
         {
             u_arraylist_remove(g_caSslContext->peerList, listIndex);
             DeleteSslEndPoint(tep);
+            OIC_LOG_V(INFO, NET_SSL_TAG, "Remove Peer:[%s:%d] for %d adapter",
+                    endpoint->addr, endpoint->port, endpoint->adapter);
+            OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
             return;
         }
     }
+    OIC_LOG_V(INFO, NET_SSL_TAG, "Peer not found:[%s:%d] for %d adapter",
+            endpoint->addr, endpoint->port, endpoint->adapter);
+    OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
 }
 /**
  * Deletes session list.
  */
 static void DeletePeerList()
 {
+    OIC_LOG_V(DEBUG, NET_SSL_TAG, "%s", __func__);
+    VERIFY_NON_NULL_VOID(g_caSslContext, NET_SSL_TAG, "SSL Context is NULL");
+
     uint32_t listLength = u_arraylist_length(g_caSslContext->peerList);
     for (uint32_t listIndex = 0; listIndex < listLength; listIndex++)
     {
@@ -861,6 +1439,15 @@ static void DeletePeerList()
         {
             continue;
         }
+        if (MBEDTLS_SSL_HANDSHAKE_OVER == tep->ssl.state)
+        {
+            int ret = 0;
+            do
+            {
+                ret = mbedtls_ssl_close_notify(&tep->ssl);
+            }
+            while (MBEDTLS_ERR_SSL_WANT_WRITE == ret);
+        }
         DeleteSslEndPoint(tep);
     }
     u_arraylist_free(&g_caSslContext->peerList);
@@ -868,21 +1455,21 @@ static void DeletePeerList()
 
 CAResult_t CAcloseSslConnection(const CAEndpoint_t *endpoint)
 {
-    OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s", __func__);
+    OIC_LOG_V(INFO, NET_SSL_TAG, "In %s", __func__);
     VERIFY_NON_NULL_RET(endpoint, NET_SSL_TAG, "Param endpoint is NULL" , CA_STATUS_INVALID_PARAM);
 
-    ca_mutex_lock(g_sslContextMutex);
+    oc_mutex_lock(g_sslContextMutex);
     if (NULL == g_caSslContext)
     {
         OIC_LOG(ERROR, NET_SSL_TAG, "Context is NULL");
-        ca_mutex_unlock(g_sslContextMutex);
+        oc_mutex_unlock(g_sslContextMutex);
         return CA_STATUS_FAILED;
     }
     SslEndPoint_t * tep = GetSslPeer(endpoint);
     if (NULL == tep)
     {
         OIC_LOG(ERROR, NET_SSL_TAG, "Session does not exist");
-        ca_mutex_unlock(g_sslContextMutex);
+        oc_mutex_unlock(g_sslContextMutex);
         return CA_STATUS_FAILED;
     }
     /* No error checking, the connection might be closed already */
@@ -894,11 +1481,96 @@ CAResult_t CAcloseSslConnection(const CAEndpoint_t *endpoint)
     while (MBEDTLS_ERR_SSL_WANT_WRITE == ret);
 
     RemovePeerFromList(&tep->sep.endpoint);
-    ca_mutex_unlock(g_sslContextMutex);
+    oc_mutex_unlock(g_sslContextMutex);
+
+    OIC_LOG_V(INFO, NET_SSL_TAG, "Out %s", __func__);
+    return CA_STATUS_OK;
+}
+
+CAResult_t CAcloseSslConnectionUsingUuid(const uint8_t *identity, size_t idLength)
+{
+    OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s", __func__);
+    VERIFY_NON_NULL_RET(identity, NET_SSL_TAG, "Param identity is NULL" , CA_STATUS_INVALID_PARAM);
+
+    oc_mutex_lock(g_sslContextMutex);
+    if (NULL == g_caSslContext)
+    {
+        OIC_LOG(ERROR, NET_SSL_TAG, "Context is NULL");
+        oc_mutex_unlock(g_sslContextMutex);
+        return CA_STATUS_FAILED;
+    }
+
+    SslEndPoint_t* tep = GetSslPeerUsingUuid(identity, idLength);
+    if (NULL == tep)
+    {
+        OIC_LOG(ERROR, NET_SSL_TAG, "Session does not exist");
+        oc_mutex_unlock(g_sslContextMutex);
+        return CA_STATUS_FAILED;
+    }
+
+    /* No error checking, the connection might be closed already */
+    int ret = 0;
+    do
+    {
+        ret = mbedtls_ssl_close_notify(&tep->ssl);
+    }
+    while (MBEDTLS_ERR_SSL_WANT_WRITE == ret);
+
+    RemovePeerFromList(&tep->sep.endpoint);
+    oc_mutex_unlock(g_sslContextMutex);
 
     OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
     return CA_STATUS_OK;
 }
+
+void CAcloseSslConnectionAll(CATransportAdapter_t transportType)
+{
+    OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s", __func__);
+    oc_mutex_lock(g_sslContextMutex);
+    if (NULL == g_caSslContext)
+    {
+        OIC_LOG(ERROR, NET_SSL_TAG, "Context is NULL");
+        oc_mutex_unlock(g_sslContextMutex);
+        return;
+    }
+
+    uint32_t listLength = u_arraylist_length(g_caSslContext->peerList);
+    OIC_LOG_V(INFO, NET_SSL_TAG,
+            "Required transport [%d], peer count [%d]", transportType, listLength);
+    for (uint32_t i = listLength; i > 0; i--)
+    {
+        SslEndPoint_t *tep = (SslEndPoint_t *)u_arraylist_get(g_caSslContext->peerList, i - 1);
+        if (NULL == tep)
+        {
+            continue;
+        }
+        OIC_LOG_V(INFO, NET_SSL_TAG, "SSL Connection [%s:%d], Transport [%d]",
+                  tep->sep.endpoint.addr, tep->sep.endpoint.port, tep->sep.endpoint.adapter);
+
+        // check transport matching
+        if (0 == (tep->sep.endpoint.adapter & transportType))
+        {
+            OIC_LOG(DEBUG, NET_SSL_TAG, "Skip the un-matched transport session");
+            continue;
+        }
+
+        // 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);*/
+
+        // delete from list
+        u_arraylist_remove(g_caSslContext->peerList, i - 1);
+        DeleteSslEndPoint(tep);
+    }
+    oc_mutex_unlock(g_sslContextMutex);
+
+    OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
+    return;
+}
 /**
  * Creates session for endpoint.
  *
@@ -910,9 +1582,10 @@ CAResult_t CAcloseSslConnection(const CAEndpoint_t *endpoint)
 static SslEndPoint_t * NewSslEndPoint(const CAEndpoint_t * endpoint, mbedtls_ssl_config * config)
 {
     SslEndPoint_t * tep = NULL;
-    OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s", __func__);
+    OIC_LOG_V(INFO, NET_SSL_TAG, "In %s", __func__);
     VERIFY_NON_NULL_RET(endpoint, NET_SSL_TAG, "endpoint", NULL);
     VERIFY_NON_NULL_RET(config, NET_SSL_TAG, "config", NULL);
+    VERIFY_NON_NULL_RET(g_caSslContext, NET_SSL_TAG, "SSL Context is NULL", NULL);
 
     tep = (SslEndPoint_t *) OICCalloc(1, sizeof (SslEndPoint_t));
     if (NULL == tep)
@@ -928,31 +1601,22 @@ static SslEndPoint_t * NewSslEndPoint(const CAEndpoint_t * endpoint, mbedtls_ssl
     {
         OIC_LOG(ERROR, NET_SSL_TAG, "Setup failed");
         OICFree(tep);
-        OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
+        OIC_LOG_V(INFO, NET_SSL_TAG, "Out %s", __func__);
         return NULL;
     }
 
     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)
         {
-            if (0 != mbedtls_ssl_cookie_setup(&tep->cookieCtx, mbedtls_ctr_drbg_random,
-                                              &g_caSslContext->rnd))
-            {
-                OIC_LOG(ERROR, NET_SSL_TAG, "Cookie setup failed!");
-                OICFree(tep);
-                OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
-                return NULL;
-            }
-            mbedtls_ssl_conf_dtls_cookies(config, mbedtls_ssl_cookie_write, mbedtls_ssl_cookie_check,
-                                          &tep->cookieCtx);
             if (0 != mbedtls_ssl_set_client_transport_id(&tep->ssl,
                                     (const unsigned char *) endpoint->addr, sizeof(endpoint->addr)))
             {
                 OIC_LOG(ERROR, NET_SSL_TAG, "Transport id setup failed!");
+                mbedtls_ssl_free(&tep->ssl);
                 OICFree(tep);
                 OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
                 return NULL;
@@ -968,6 +1632,9 @@ static SslEndPoint_t * NewSslEndPoint(const CAEndpoint_t * endpoint, mbedtls_ssl
         OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
         return NULL;
     }
+    OIC_LOG_V(INFO, NET_SSL_TAG, "New [%s role] endpoint added [%s:%d]",
+            (MBEDTLS_SSL_IS_SERVER==config->endpoint ? "server" : "client"),
+            endpoint->addr, endpoint->port);
     OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
     return tep;
 }
@@ -980,17 +1647,20 @@ static SslEndPoint_t * NewSslEndPoint(const CAEndpoint_t * endpoint, mbedtls_ssl
  */
 static int InitPskIdentity(mbedtls_ssl_config * config)
 {
+    uint8_t keyBuf[PSK_LENGTH] = {0};
     uint8_t idBuf[UUID_LENGTH] = {0};
     OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s", __func__);
     VERIFY_NON_NULL_RET(config, NET_SSL_TAG, "Param config is NULL" , -1);
 
+    //Retrieve PSK identity from SVR DB
     if (0 > g_getCredentialsCallback(CA_DTLS_PSK_IDENTITY, NULL, 0, idBuf, UUID_LENGTH))
     {
         OIC_LOG(ERROR, NET_SSL_TAG, "Identity not found");
         OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
         return -1;
     }
-    if (0 != mbedtls_ssl_conf_psk(config, idBuf, 0, idBuf, UUID_LENGTH))
+    //Store PSK ideneity in mbedtls_ssl_config
+    if (0 != mbedtls_ssl_conf_psk(config, keyBuf, PSK_LENGTH, idBuf, UUID_LENGTH))
     {
         OIC_LOG(ERROR, NET_SSL_TAG, "Identity initialization failed!");
         OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
@@ -1003,22 +1673,23 @@ static void SetupCipher(mbedtls_ssl_config * config, CATransportAdapter_t adapte
 {
     int index = 0;
     OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s", __func__);
-    if (NULL == g_getCredentialTypesCallback)
-    {
-        OIC_LOG(ERROR, NET_SSL_TAG, "Param callback is null");
-        return;
-    }
+    VERIFY_NON_NULL_VOID(config, NET_SSL_TAG, "Invaild param");
+    VERIFY_NON_NULL_VOID(g_caSslContext, NET_SSL_TAG, "SSL Context is NULL");
+    VERIFY_NON_NULL_VOID(g_getCredentialTypesCallback, NET_SSL_TAG, "Param callback is null");
+
+    //Resetting cipherFlag
+    g_caSslContext->cipherFlag[0] = false;
+    g_caSslContext->cipherFlag[1] = false;
 
     g_getCredentialTypesCallback(g_caSslContext->cipherFlag);
     // Retrieve the PSK credential from SRM
-    // PIN OTM if (true == g_caSslContext->cipherFlag[0] && 0 != InitPskIdentity(config))
     if (0 != InitPskIdentity(config))
     {
         OIC_LOG(ERROR, NET_SSL_TAG, "PSK identity initialization failed!");
     }
 
-    // Retrieve the ECC credential from SRM
-    if (true == g_caSslContext->cipherFlag[1] || ADAPTER_TLS_RSA_WITH_AES_256_CBC_SHA == g_caSslContext->cipher)
+    // Retrieve the Cert credential from SRM
+    if (true == g_caSslContext->cipherFlag[1])
     {
         int ret = InitPKIX(adapter);
         if (0 != ret)
@@ -1028,19 +1699,47 @@ static void SetupCipher(mbedtls_ssl_config * config, CATransportAdapter_t adapte
     }
 
     memset(g_cipherSuitesList, 0, sizeof(g_cipherSuitesList));
-    if (ADAPTER_CIPHER_MAX != g_caSslContext->cipher)
+
+    // Add the preferred ciphersuite first
+    if (SSL_CIPHER_MAX != g_caSslContext->cipher)
     {
         g_cipherSuitesList[index] = tlsCipher[g_caSslContext->cipher][0];
-        index ++;
+        OIC_LOG_V(DEBUG, NET_SSL_TAG, "Preferred ciphersuite added");
+        index++;
+    }
+
+    // Add PSK ciphersuite
+    if (true == g_caSslContext->cipherFlag[0] &&
+                MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 != tlsCipher[g_caSslContext->cipher][0])
+    {
+       g_cipherSuitesList[index] = MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256;
+       OIC_LOG(DEBUG, NET_SSL_TAG, "PSK ciphersuite added");
+       index++;
     }
+
+    // Add all certificate ciphersuites
     if (true == g_caSslContext->cipherFlag[1])
     {
-        g_cipherSuitesList[index] = MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8;
-        index ++;
+        for (unsigned int i = 0; i < SSL_CIPHER_MAX - 1; i++)
+        {
+            if (MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 != tlsCipher[i][0] &&
+                i != g_caSslContext->cipher)
+            {
+                g_cipherSuitesList[index] = tlsCipher[i][0];
+                index ++;
+            }
+        }
+
+        if (MBEDTLS_SSL_IS_SERVER == config->endpoint)
+        {
+            mbedtls_ssl_conf_authmode(config, MBEDTLS_SSL_VERIFY_OPTIONAL);
+        }
     }
-    if (true == g_caSslContext->cipherFlag[0])
+
+    OIC_LOG(INFO, NET_SSL_TAG, "Supported ciphersuites:");
+    for (int i = 0; i < index; i++)
     {
-       g_cipherSuitesList[index] = MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256;
+        OIC_LOG_V(INFO, NET_SSL_TAG, "Ciphersuite %04x", g_cipherSuitesList[i]);
     }
 
     mbedtls_ssl_conf_ciphersuites(config, g_cipherSuitesList);
@@ -1059,11 +1758,15 @@ static SslEndPoint_t * InitiateTlsHandshake(const CAEndpoint_t *endpoint)
     int ret = 0;
     SslEndPoint_t * tep = NULL;
 
-    OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s", __func__);
+    OIC_LOG_V(INFO, NET_SSL_TAG, "In %s", __func__);
     VERIFY_NON_NULL_RET(endpoint, NET_SSL_TAG, "Param endpoint is NULL" , NULL);
+    VERIFY_NON_NULL_RET(g_caSslContext, NET_SSL_TAG, "SSL Context is NULL", NULL);
 
+    //Remove previous peer info from peer list.
+    RemovePeerFromList(endpoint);
 
-    mbedtls_ssl_config * config = (endpoint->adapter == CA_ADAPTER_IP ?
+    mbedtls_ssl_config * config = (endpoint->adapter == CA_ADAPTER_IP ||
+                                   endpoint->adapter == CA_ADAPTER_GATT_BTLE ?
                                    &g_caSslContext->clientDtlsConf : &g_caSslContext->clientTlsConf);
     tep = NewSslEndPoint(endpoint, config);
     if (NULL == tep)
@@ -1075,7 +1778,6 @@ static SslEndPoint_t * InitiateTlsHandshake(const CAEndpoint_t *endpoint)
     //Load allowed SVR suites from SVR DB
     SetupCipher(config, endpoint->adapter);
 
-    OIC_LOG_V(DEBUG, NET_SSL_TAG, "Add %s:%d", tep->sep.endpoint.addr, tep->sep.endpoint.port);
     ret = u_arraylist_add(g_caSslContext->peerList, (void *) tep);
     if (!ret)
     {
@@ -1091,12 +1793,30 @@ static SslEndPoint_t * InitiateTlsHandshake(const CAEndpoint_t *endpoint)
         {
             break;
         }
+        else if (-1 == ret)
+        {
+            OIC_LOG(ERROR, NET_SSL_TAG, "Handshake failed due to socket error");
+            RemovePeerFromList(&tep->sep.endpoint);
+            return NULL;
+        }
         SSL_CHECK_FAIL(tep, ret, "Handshake error", 0, NULL, MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE);
     }
-    OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
+    OIC_LOG_V(INFO, 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__);
@@ -1105,14 +1825,16 @@ void CAdeinitSslAdapter()
     VERIFY_NON_NULL_VOID(g_sslContextMutex, NET_SSL_TAG, "context mutex is NULL");
 
     //Lock tlsContext mutex
-    ca_mutex_lock(g_sslContextMutex);
+    oc_mutex_lock(g_sslContextMutex);
 
     // Clear all lists
     DeletePeerList();
 
     // De-initialize mbedTLS
+    mbedtls_x509_crt_free(&g_caSslContext->ca);
     mbedtls_x509_crt_free(&g_caSslContext->crt);
     mbedtls_pk_free(&g_caSslContext->pkey);
+    mbedtls_x509_crl_free(&g_caSslContext->crl);
 #ifdef __WITH_TLS__
     mbedtls_ssl_config_free(&g_caSslContext->clientTlsConf);
     mbedtls_ssl_config_free(&g_caSslContext->serverTlsConf);
@@ -1120,17 +1842,27 @@ void CAdeinitSslAdapter()
 #ifdef __WITH_DTLS__
     mbedtls_ssl_config_free(&g_caSslContext->clientDtlsConf);
     mbedtls_ssl_config_free(&g_caSslContext->serverDtlsConf);
+    mbedtls_ssl_cookie_free(&g_caSslContext->cookieCtx);
 #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;
 
+    // Delete decrypt buffer
+    if (g_decryptBuffer)
+    {
+        OICFree(g_decryptBuffer);
+        g_decryptBuffer = NULL;
+    }
+
     // Unlock tlsContext mutex and de-initialize it
-    ca_mutex_unlock(g_sslContextMutex);
-    ca_mutex_free(g_sslContextMutex);
+    oc_mutex_unlock(g_sslContextMutex);
+    oc_mutex_free(g_sslContextMutex);
     g_sslContextMutex = NULL;
 
     OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s ", __func__);
@@ -1140,6 +1872,7 @@ static int InitConfig(mbedtls_ssl_config * conf, int transport, int mode)
 {
     OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s", __func__);
     VERIFY_NON_NULL_RET(conf, NET_SSL_TAG, "Param conf is NULL" , -1);
+    VERIFY_NON_NULL_RET(g_caSslContext, NET_SSL_TAG, "SSL Context is NULL", -1);
     mbedtls_ssl_config_init(conf);
     if (mbedtls_ssl_config_defaults(conf, mode, transport, MBEDTLS_SSL_PRESET_DEFAULT) != 0)
     {
@@ -1153,14 +1886,78 @@ static int InitConfig(mbedtls_ssl_config * conf, int transport, int mode)
     mbedtls_ssl_conf_min_version(conf, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3);
     mbedtls_ssl_conf_renegotiation(conf, MBEDTLS_SSL_RENEGOTIATION_DISABLED);
     mbedtls_ssl_conf_authmode(conf, MBEDTLS_SSL_VERIFY_REQUIRED);
+    mbedtls_ssl_conf_sig_hashes(conf, g_ssl_ordered_default_hashes);
+
+#ifdef __WITH_DTLS__
+    if (MBEDTLS_SSL_TRANSPORT_DATAGRAM == transport &&
+            MBEDTLS_SSL_IS_SERVER == mode)
+    {
+        mbedtls_ssl_conf_dtls_cookies(conf, mbedtls_ssl_cookie_write, mbedtls_ssl_cookie_check,
+                                      &g_caSslContext->cookieCtx);
+    }
+#endif // __WITH_DTLS__
 
-#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;
+
+    oc_mutex_lock(g_sslContextMutex);
+    if (NULL == g_caSslContext)
+    {
+        OIC_LOG(ERROR, NET_SSL_TAG, "Context is NULL. Stop retransmission");
+        oc_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
+                || (tep->ssl.conf && MBEDTLS_SSL_TRANSPORT_STREAM == tep->ssl.conf->transport)
+                || MBEDTLS_SSL_HANDSHAKE_OVER == tep->ssl.state)
+            {
+                continue;
+            }
+            OIC_LOG_V(INFO, NET_SSL_TAG, "peer #%d", (int) listIndex);
+
+            int ret = mbedtls_ssl_handshake_step(&tep->ssl);
+
+            if (MBEDTLS_ERR_SSL_CONN_EOF != ret)
+            {
+                //start new timer
+                registerTimer(RETRANSMISSION_TIME, &g_caSslContext->timerId, (void *) StartRetransmit);
+                //unlock & return
+                SSL_CHECK_FAIL(tep, ret, "Retransmission", 1, CA_STATUS_FAILED,
+                MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE);
+            }
+        }
+    }
+    //start new timer
+    registerTimer(RETRANSMISSION_TIME, &g_caSslContext->timerId, (void *) StartRetransmit);
+    oc_mutex_unlock(g_sslContextMutex);
+
+    return 0;
+}
+#endif
 
 CAResult_t CAinitSslAdapter()
 {
@@ -1168,7 +1965,7 @@ CAResult_t CAinitSslAdapter()
     // Initialize mutex for tlsContext
     if (NULL == g_sslContextMutex)
     {
-        g_sslContextMutex = ca_mutex_new();
+        g_sslContextMutex = oc_mutex_new();
         VERIFY_NON_NULL_RET(g_sslContextMutex, NET_SSL_TAG, "malloc failed", CA_MEMORY_ALLOC_FAILED);
     }
     else
@@ -1178,14 +1975,14 @@ CAResult_t CAinitSslAdapter()
     }
 
     // Lock tlsContext mutex and create tlsContext
-    ca_mutex_lock(g_sslContextMutex);
+    oc_mutex_lock(g_sslContextMutex);
     g_caSslContext = (SslContext_t *)OICCalloc(1, sizeof(SslContext_t));
 
     if (NULL == g_caSslContext)
     {
         OIC_LOG(ERROR, NET_SSL_TAG, "Context malloc failed");
-        ca_mutex_unlock(g_sslContextMutex);
-        ca_mutex_free(g_sslContextMutex);
+        oc_mutex_unlock(g_sslContextMutex);
+        oc_mutex_free(g_sslContextMutex);
         g_sslContextMutex = NULL;
         return CA_MEMORY_ALLOC_FAILED;
     }
@@ -1198,15 +1995,15 @@ CAResult_t CAinitSslAdapter()
         OIC_LOG(ERROR, NET_SSL_TAG, "peerList initialization failed!");
         OICFree(g_caSslContext);
         g_caSslContext = NULL;
-        ca_mutex_unlock(g_sslContextMutex);
-        ca_mutex_free(g_sslContextMutex);
+        oc_mutex_unlock(g_sslContextMutex);
+        oc_mutex_free(g_sslContextMutex);
         g_sslContextMutex = NULL;
         return CA_STATUS_FAILED;
     }
 
     /* 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);
@@ -1224,7 +2021,7 @@ CAResult_t CAinitSslAdapter()
     if(urandomFd == -1)
     {
         OIC_LOG(ERROR, NET_SSL_TAG, "Fails open /dev/urandom!");
-        ca_mutex_unlock(g_sslContextMutex);
+        oc_mutex_unlock(g_sslContextMutex);
         CAdeinitSslAdapter();
         return CA_STATUS_FAILED;
     }
@@ -1232,7 +2029,7 @@ CAResult_t CAinitSslAdapter()
     {
         OIC_LOG(ERROR, NET_SSL_TAG, "Fails read from /dev/urandom!");
         close(urandomFd);
-        ca_mutex_unlock(g_sslContextMutex);
+        oc_mutex_unlock(g_sslContextMutex);
         CAdeinitSslAdapter();
         return CA_STATUS_FAILED;
     }
@@ -1245,7 +2042,7 @@ CAResult_t CAinitSslAdapter()
                                   &g_caSslContext->entropy, seed, sizeof(SEED)))
     {
         OIC_LOG(ERROR, NET_SSL_TAG, "Seed initialization failed!");
-        ca_mutex_unlock(g_sslContextMutex);
+        oc_mutex_unlock(g_sslContextMutex);
         CAdeinitSslAdapter();
         return CA_STATUS_FAILED;
     }
@@ -1256,7 +2053,7 @@ CAResult_t CAinitSslAdapter()
                         MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_IS_CLIENT))
     {
         OIC_LOG(ERROR, NET_SSL_TAG, "Client config initialization failed!");
-        ca_mutex_unlock(g_sslContextMutex);
+        oc_mutex_unlock(g_sslContextMutex);
         CAdeinitSslAdapter();
         OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
         return CA_STATUS_FAILED;
@@ -1266,18 +2063,29 @@ CAResult_t CAinitSslAdapter()
                         MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_IS_SERVER))
     {
         OIC_LOG(ERROR, NET_SSL_TAG, "Server config initialization failed!");
-        ca_mutex_unlock(g_sslContextMutex);
+        oc_mutex_unlock(g_sslContextMutex);
         CAdeinitSslAdapter();
         OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
         return CA_STATUS_FAILED;
     }
 #endif // __WITH_TLS__
 #ifdef __WITH_DTLS__
+    mbedtls_ssl_cookie_init(&g_caSslContext->cookieCtx);
+    if (0 != mbedtls_ssl_cookie_setup(&g_caSslContext->cookieCtx, mbedtls_ctr_drbg_random,
+                                      &g_caSslContext->rnd))
+    {
+        OIC_LOG(ERROR, NET_SSL_TAG, "Cookie setup failed!");
+        oc_mutex_unlock(g_sslContextMutex);
+        CAdeinitSslAdapter();
+        OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
+        return CA_STATUS_FAILED;
+    }
+
     if (0 != InitConfig(&g_caSslContext->clientDtlsConf,
                         MBEDTLS_SSL_TRANSPORT_DATAGRAM, MBEDTLS_SSL_IS_CLIENT))
     {
         OIC_LOG(ERROR, NET_SSL_TAG, "Client config initialization failed!");
-        ca_mutex_unlock(g_sslContextMutex);
+        oc_mutex_unlock(g_sslContextMutex);
         CAdeinitSslAdapter();
         OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
         return CA_STATUS_FAILED;
@@ -1287,7 +2095,7 @@ CAResult_t CAinitSslAdapter()
                         MBEDTLS_SSL_TRANSPORT_DATAGRAM, MBEDTLS_SSL_IS_SERVER))
     {
         OIC_LOG(ERROR, NET_SSL_TAG, "Server config initialization failed!");
-        ca_mutex_unlock(g_sslContextMutex);
+        oc_mutex_unlock(g_sslContextMutex);
         CAdeinitSslAdapter();
         OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
         return CA_STATUS_FAILED;
@@ -1295,7 +2103,7 @@ CAResult_t CAinitSslAdapter()
 #endif // __WITH_DTLS__
 
     // set default cipher
-    g_caSslContext->cipher = ADAPTER_CIPHER_MAX;
+    g_caSslContext->cipher = SSL_CIPHER_MAX;
 
     // init X.509
     mbedtls_x509_crt_init(&g_caSslContext->ca);
@@ -1303,7 +2111,25 @@ 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
+
+    // create decrypt buffer
+    g_decryptBuffer = (uint8_t *)OICCalloc(1, TLS_MSG_BUF_LEN);
+    if (NULL == g_decryptBuffer)
+    {
+        OIC_LOG(ERROR, NET_SSL_TAG, "Decrypt buffer malloc failed");
+        oc_mutex_unlock(g_sslContextMutex);
+        CAdeinitSslAdapter();
+        OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
+        return CA_MEMORY_ALLOC_FAILED;
+    }
+
+    oc_mutex_unlock(g_sslContextMutex);
+#ifdef __WITH_DTLS__
+    StartRetransmit();
+#endif
 
     OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
     return CA_STATUS_OK;
@@ -1348,7 +2174,7 @@ CAResult_t CAencryptSsl(const CAEndpoint_t *endpoint,
 {
     int ret = 0;
 
-    OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s ", __func__);
+    OIC_LOG_V(INFO, NET_SSL_TAG, "In %s ", __func__);
 
     VERIFY_NON_NULL_RET(endpoint, NET_SSL_TAG,"Remote address is NULL", CA_STATUS_INVALID_PARAM);
     VERIFY_NON_NULL_RET(data, NET_SSL_TAG, "Data is NULL", CA_STATUS_INVALID_PARAM);
@@ -1362,11 +2188,11 @@ CAResult_t CAencryptSsl(const CAEndpoint_t *endpoint,
 
     OIC_LOG_V(DEBUG, NET_SSL_TAG, "Data to be encrypted dataLen [%d]", dataLen);
 
-    ca_mutex_lock(g_sslContextMutex);
+    oc_mutex_lock(g_sslContextMutex);
     if(NULL == g_caSslContext)
     {
         OIC_LOG(ERROR, NET_SSL_TAG, "Context is NULL");
-        ca_mutex_unlock(g_sslContextMutex);
+        oc_mutex_unlock(g_sslContextMutex);
         return CA_STATUS_FAILED;
     }
 
@@ -1378,21 +2204,37 @@ CAResult_t CAencryptSsl(const CAEndpoint_t *endpoint,
     if (NULL == tep)
     {
         OIC_LOG(ERROR, NET_SSL_TAG, "TLS handshake failed");
-        ca_mutex_unlock(g_sslContextMutex);
+        oc_mutex_unlock(g_sslContextMutex);
         return CA_STATUS_FAILED;
     }
 
     if (MBEDTLS_SSL_HANDSHAKE_OVER == tep->ssl.state)
     {
-        ret = mbedtls_ssl_write(&tep->ssl, (unsigned char *) data, dataLen);
+        OIC_LOG(INFO, NET_SSL_TAG, "(MBEDTLS_SSL_HANDSHAKE_OVER == tep->ssl.state)");
+
+        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);
+                    oc_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
     {
@@ -1400,14 +2242,14 @@ CAResult_t CAencryptSsl(const CAEndpoint_t *endpoint,
         if (NULL == msg || !u_arraylist_add(tep->cacheList, (void *) msg))
         {
             OIC_LOG(ERROR, NET_SSL_TAG, "u_arraylist_add failed!");
-            ca_mutex_unlock(g_sslContextMutex);
+            oc_mutex_unlock(g_sslContextMutex);
             return CA_STATUS_FAILED;
         }
     }
 
-    ca_mutex_unlock(g_sslContextMutex);
+    oc_mutex_unlock(g_sslContextMutex);
 
-    OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
+    OIC_LOG_V(INFO, NET_SSL_TAG, "Out %s", __func__);
     return CA_STATUS_OK;
 }
 /**
@@ -1429,16 +2271,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,70 +2319,21 @@ 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
  */
 CAResult_t CAdecryptSsl(const CASecureEndpoint_t *sep, uint8_t *data, uint32_t dataLen)
 {
     int ret = 0;
-    OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s", __func__);
+    OIC_LOG_V(INFO, NET_SSL_TAG, "In %s", __func__);
     VERIFY_NON_NULL_RET(sep, NET_SSL_TAG, "endpoint is NULL" , CA_STATUS_INVALID_PARAM);
     VERIFY_NON_NULL_RET(data, NET_SSL_TAG, "Param data is NULL" , CA_STATUS_INVALID_PARAM);
 
-    ca_mutex_lock(g_sslContextMutex);
+    oc_mutex_lock(g_sslContextMutex);
     if (NULL == g_caSslContext)
     {
         OIC_LOG(ERROR, NET_SSL_TAG, "Context is NULL");
-        ca_mutex_unlock(g_sslContextMutex);
+        oc_mutex_unlock(g_sslContextMutex);
         return CA_STATUS_FAILED;
     }
 
@@ -1537,13 +2341,14 @@ CAResult_t CAdecryptSsl(const CASecureEndpoint_t *sep, uint8_t *data, uint32_t d
     SslEndPoint_t * peer = GetSslPeer(&sep->endpoint);
     if (NULL == peer)
     {
-        mbedtls_ssl_config * config = (sep->endpoint.adapter == CA_ADAPTER_IP ?
+        mbedtls_ssl_config * config = (sep->endpoint.adapter == CA_ADAPTER_IP ||
+                                   sep->endpoint.adapter == CA_ADAPTER_GATT_BTLE ?
                                    &g_caSslContext->serverDtlsConf : &g_caSslContext->serverTlsConf);
         peer = NewSslEndPoint(&sep->endpoint, config);
         if (NULL == peer)
         {
             OIC_LOG(ERROR, NET_SSL_TAG, "Malloc failed!");
-            ca_mutex_unlock(g_sslContextMutex);
+            oc_mutex_unlock(g_sslContextMutex);
             return CA_STATUS_FAILED;
         }
         //Load allowed TLS suites from SVR DB
@@ -1554,7 +2359,7 @@ CAResult_t CAdecryptSsl(const CASecureEndpoint_t *sep, uint8_t *data, uint32_t d
         {
             OIC_LOG(ERROR, NET_SSL_TAG, "u_arraylist_add failed!");
             OICFree(peer);
-            ca_mutex_unlock(g_sslContextMutex);
+            oc_mutex_unlock(g_sslContextMutex);
             return CA_STATUS_FAILED;
         }
     }
@@ -1580,12 +2385,15 @@ CAResult_t CAdecryptSsl(const CASecureEndpoint_t *sep, uint8_t *data, uint32_t d
                                                  sizeof(sep->endpoint.addr));
             ret = mbedtls_ssl_handshake_step(&peer->ssl);
         }
-        uint32_t flags = mbedtls_ssl_get_verify_result(&peer->ssl);
-        if (0 != flags)
+        if (MBEDTLS_SSL_IS_CLIENT == peer->ssl.conf->endpoint)
         {
-            OIC_LOG_BUFFER(ERROR, NET_SSL_TAG, (const uint8_t *) &flags, sizeof(flags));
-            SSL_CHECK_FAIL(peer, flags, "Cert verification failed", 1,
-                                                     CA_STATUS_FAILED, GetAlertCode(flags));
+            uint32_t flags = mbedtls_ssl_get_verify_result(&peer->ssl);
+            if (0 != flags)
+            {
+                OIC_LOG_BUFFER(ERROR, NET_SSL_TAG, (const uint8_t *) &flags, sizeof(flags));
+                SSL_CHECK_FAIL(peer, flags, "Cert verification failed", 1,
+                                                         CA_STATUS_FAILED, GetAlertCode(flags));
+            }
         }
         SSL_CHECK_FAIL(peer, ret, "Handshake error", 1, CA_STATUS_FAILED, MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE);
         if (MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC == peer->ssl.state)
@@ -1606,93 +2414,148 @@ CAResult_t CAdecryptSsl(const CASecureEndpoint_t *sep, uint8_t *data, uint32_t d
                 SendCacheMessages(peer);
             }
 
-            if (MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 == g_caSslContext->selectedCipher ||
-                MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA == g_caSslContext->selectedCipher)
+            int selectedCipher = peer->ssl.session->ciphersuite;
+            OIC_LOG_V(DEBUG, NET_SSL_TAG, "(D)TLS Session is connected via ciphersuite [0x%x]", selectedCipher);
+            if (MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 != selectedCipher &&
+                MBEDTLS_TLS_ECDH_ANON_WITH_AES_128_CBC_SHA256 != selectedCipher)
             {
                 char uuid[UUID_LENGTH * 2 + 5] = {0};
                 void * uuidPos = NULL;
                 void * userIdPos = NULL;
                 const mbedtls_x509_crt * peerCert = mbedtls_ssl_get_peer_cert(&peer->ssl);
                 ret = (NULL == peerCert ? -1 : 0);
-                SSL_CHECK_FAIL(peer, ret, "Failed to retrieve cert", 1,
-                                            CA_STATUS_FAILED, MBEDTLS_SSL_ALERT_MSG_NO_CERT);
-                uuidPos = memmem(peerCert->subject_raw.p, peerCert->subject_raw.len,
-                                                 UUID_PREFIX, sizeof(UUID_PREFIX) - 1);
-
-                if (NULL != uuidPos)
+                //SSL_CHECK_FAIL(peer, ret, "Failed to retrieve cert", 1,
+                //                            CA_STATUS_FAILED, MBEDTLS_SSL_ALERT_MSG_NO_CERT);
+                if (0 == ret)
                 {
-                    memcpy(uuid, (char*) uuidPos + sizeof(UUID_PREFIX) - 1, UUID_LENGTH * 2 + 4);
-                    ret = ConvertStrToUuid(uuid, &peer->sep.identity);
-                    SSL_CHECK_FAIL(peer, ret, "Failed to convert subject", 1,
+                    uuidPos = memmem(peerCert->subject_raw.p, peerCert->subject_raw.len,
+                                                     UUID_PREFIX, sizeof(UUID_PREFIX) - 1);
+
+                    if (NULL != uuidPos)
+                    {
+                        memcpy(uuid, (char*) uuidPos + sizeof(UUID_PREFIX) - 1, UUID_LENGTH * 2 + 4);
+                        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);
+                    }
+                    else
+                    {
+                        OIC_LOG(WARNING, NET_SSL_TAG, "uuid not found");
+                    }
+
+                    userIdPos = memmem(peerCert->subject_raw.p, peerCert->subject_raw.len,
+                                                 USERID_PREFIX, sizeof(USERID_PREFIX) - 1);
+                    if (NULL != userIdPos)
+                    {
+                        memcpy(uuid, (char*) userIdPos + sizeof(USERID_PREFIX) - 1, UUID_LENGTH * 2 + 4);
+                        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);
+                    }
+                    else
+                    {
+                        OIC_LOG(WARNING, NET_SSL_TAG, "Subject alternative name not found");
+                    }
                 }
-                else
-                {
-                    OIC_LOG(WARNING, NET_SSL_TAG, "uuid not found");
-                }
+            }
 
-                userIdPos = memmem(peerCert->subject_raw.p, peerCert->subject_raw.len,
-                                             USERID_PREFIX, sizeof(USERID_PREFIX) - 1);
-                if (NULL != userIdPos)
-                {
-                    memcpy(uuid, (char*) userIdPos + sizeof(USERID_PREFIX) - 1, UUID_LENGTH * 2 + 4);
-                    ret = ConvertStrToUuid(uuid, &peer->sep.userId);
-                    SSL_CHECK_FAIL(peer, ret, "Failed to convert subject alt name", 1,
-                                      CA_STATUS_FAILED, MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT);
-                }
-                else
-                {
-                    OIC_LOG(WARNING, NET_SSL_TAG, "Subject alternative name not found");
-                }
+            if (MBEDTLS_SSL_IS_CLIENT == peer->ssl.conf->endpoint)
+            {
+                SendCacheMessages(peer);
             }
+            mbedtls_ssl_config * config = (sep->endpoint.adapter == CA_ADAPTER_IP ||
+                                       sep->endpoint.adapter == CA_ADAPTER_GATT_BTLE ?
+                                       &g_caSslContext->serverDtlsConf : &g_caSslContext->serverTlsConf);
 
-            ca_mutex_unlock(g_sslContextMutex);
-            OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
+            mbedtls_ssl_conf_authmode(config, MBEDTLS_SSL_VERIFY_REQUIRED);
+
+            oc_mutex_unlock(g_sslContextMutex);
+            OIC_LOG_V(INFO, NET_SSL_TAG, "Out %s", __func__);
             return CA_STATUS_OK;
         }
     }
 
     if (MBEDTLS_SSL_HANDSHAKE_OVER == peer->ssl.state)
     {
-        uint8_t decryptBuffer[TLS_MSG_BUF_LEN] = {0};
+        OIC_LOG(INFO, NET_SSL_TAG, "(MBEDTLS_SSL_HANDSHAKE_OVER == peer->ssl.state)");
+
+        // flag to read again remained data
+        bool read_more = false;
         do
         {
-            ret = mbedtls_ssl_read(&peer->ssl, decryptBuffer, TLS_MSG_BUF_LEN);
-        } while (MBEDTLS_ERR_SSL_WANT_READ == ret);
+            if (NULL == g_decryptBuffer)
+            {
+                OIC_LOG(ERROR, NET_SSL_TAG, "decrypt buffer is NULL");
+                oc_mutex_unlock(g_sslContextMutex);
+                return CA_STATUS_FAILED;
+            }
+            memset(g_decryptBuffer, 0, TLS_MSG_BUF_LEN);
+            read_more = false;
 
-        if (MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY == ret)
-        {
-            OIC_LOG(INFO, NET_SSL_TAG, "Connection was closed gracefully");
-            SSL_CLOSE_NOTIFY(peer, ret);
-            RemovePeerFromList(&peer->sep.endpoint);
-            ca_mutex_unlock(g_sslContextMutex);
-            return CA_STATUS_OK;
-        }
+            do
+            {
+                ret = mbedtls_ssl_read(&peer->ssl, g_decryptBuffer, TLS_MSG_BUF_LEN);
+            } while (MBEDTLS_ERR_SSL_WANT_READ == 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");
+                RemovePeerFromList(&peer->sep.endpoint);
+                oc_mutex_unlock(g_sslContextMutex);
+                return CA_STATUS_OK;
+            }
 
-        if (0 > ret)
-        {
-            OIC_LOG_V(ERROR, NET_SSL_TAG, "mbedtls_ssl_read returned -0x%x", -ret);
-            //SSL_RES(peer, CA_STATUS_FAILED);
-            RemovePeerFromList(&peer->sep.endpoint);
-            ca_mutex_unlock(g_sslContextMutex);
-            return CA_STATUS_FAILED;
-        }
-        int adapterIndex = GetAdapterIndex(peer->sep.endpoint.adapter);
-        if (0 == adapterIndex || adapterIndex == 1)
-        {
-            g_caSslContext->adapterCallbacks[adapterIndex].recvCallback(&peer->sep, decryptBuffer, ret);
-        }
-        else
-        {
-            OIC_LOG(ERROR, NET_SSL_TAG, "Unsuported adapter");
-            RemovePeerFromList(&peer->sep.endpoint);
-            ca_mutex_unlock(g_sslContextMutex);
-            return CA_STATUS_FAILED;
-        }
+            if (0 > ret)
+            {
+                OIC_LOG_V(ERROR, NET_SSL_TAG, "mbedtls_ssl_read returned -0x%x", -ret);
+                //SSL_RES(peer, CA_STATUS_FAILED);
+                RemovePeerFromList(&peer->sep.endpoint);
+                oc_mutex_unlock(g_sslContextMutex);
+                return CA_STATUS_FAILED;
+            }
+            else if (0 < ret)
+            {
+                int adapterIndex = GetAdapterIndex(peer->sep.endpoint.adapter);
+                if (0 <= adapterIndex && MAX_SUPPORTED_ADAPTERS > adapterIndex)
+                {
+                    CAResult_t res;
+                    res = g_caSslContext->adapterCallbacks[adapterIndex].recvCallback(&peer->sep,
+                            g_decryptBuffer, ret);
+                    if (CA_STATUS_OK != res)
+                    {
+                        OIC_LOG(ERROR, NET_SSL_TAG, "recvCallback is failed");
+                        RemovePeerFromList(&peer->sep.endpoint);
+                        oc_mutex_unlock(g_sslContextMutex);
+                        return CA_STATUS_FAILED;
+                    }
+
+                    // check if decrypted data is remained in stream transport
+                    size_t remained = mbedtls_ssl_get_bytes_avail(&peer->ssl);
+                    if (0 < remained &&
+                        MBEDTLS_SSL_TRANSPORT_STREAM == peer->ssl.conf->transport)
+                    {
+                        OIC_LOG_V(DEBUG, NET_SSL_TAG, "need to read %zu bytes more", remained);
+                        read_more = true;
+                    }
+                }
+                else
+                {
+                    OIC_LOG(ERROR, NET_SSL_TAG, "Unsuported adapter");
+                    RemovePeerFromList(&peer->sep.endpoint);
+                    oc_mutex_unlock(g_sslContextMutex);
+                    return CA_STATUS_FAILED;
+                }
+            }
+        } while (read_more);
     }
 
-    ca_mutex_unlock(g_sslContextMutex);
-    OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
+    oc_mutex_unlock(g_sslContextMutex);
+    OIC_LOG_V(INFO, NET_SSL_TAG, "Out %s", __func__);
     return CA_STATUS_OK;
 }
 
@@ -1703,131 +2566,130 @@ void CAsetSslAdapterCallbacks(CAPacketReceivedCallback recvCallback,
     OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s", __func__);
     VERIFY_NON_NULL_VOID(sendCallback, NET_SSL_TAG, "sendCallback is NULL");
     VERIFY_NON_NULL_VOID(recvCallback, NET_SSL_TAG, "recvCallback is NULL");
-    ca_mutex_lock(g_sslContextMutex);
+    oc_mutex_lock(g_sslContextMutex);
     if (NULL == g_caSslContext)
     {
         OIC_LOG(ERROR, NET_SSL_TAG, "Context is NULL");
-        ca_mutex_unlock(g_sslContextMutex);
+        oc_mutex_unlock(g_sslContextMutex);
         return;
     }
 
-//    if (MAX_SUPPORTED_ADAPTERS > type)
+    switch (type)
     {
-        switch (type)
-        {
-            case CA_ADAPTER_IP:
-                g_caSslContext->adapterCallbacks[0].recvCallback = recvCallback;
-                g_caSslContext->adapterCallbacks[0].sendCallback = sendCallback;
-                break;
-            case CA_ADAPTER_TCP:
-                g_caSslContext->adapterCallbacks[1].recvCallback = recvCallback;
-                g_caSslContext->adapterCallbacks[1].sendCallback = sendCallback;
-                break;
-            default:
-                OIC_LOG_V(ERROR, NET_SSL_TAG, "Unsupported adapter: %d", type);
-        }
+        case CA_ADAPTER_IP:
+            g_caSslContext->adapterCallbacks[0].recvCallback = recvCallback;
+            g_caSslContext->adapterCallbacks[0].sendCallback = sendCallback;
+            break;
+        case CA_ADAPTER_TCP:
+            g_caSslContext->adapterCallbacks[1].recvCallback = recvCallback;
+            g_caSslContext->adapterCallbacks[1].sendCallback = sendCallback;
+            break;
+        case CA_ADAPTER_GATT_BTLE:
+            g_caSslContext->adapterCallbacks[2].recvCallback = recvCallback;
+            g_caSslContext->adapterCallbacks[2].sendCallback = sendCallback;
+            break;
+        default:
+            OIC_LOG_V(ERROR, NET_SSL_TAG, "Unsupported adapter: %d", type);
     }
 
-    ca_mutex_unlock(g_sslContextMutex);
+    oc_mutex_unlock(g_sslContextMutex);
     OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
 }
+/**
+ * Gets index of the TLS ciphersuite in the SslCipher_t enum.
+ *
+ * @param[in]  cipher    TLS chiphersuite code
+ *
+ * @return   corresponding enum
+ */
 
-CAResult_t CAsetTlsCipherSuite(const uint32_t cipher)
+static SslCipher_t GetCipherIndex(const uint32_t cipher)
 {
-    OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s", __func__);
-    VERIFY_NON_NULL_RET(g_getCredentialTypesCallback, NET_SSL_TAG, "Param callback is null", CA_STATUS_FAILED);
-    g_getCredentialTypesCallback(g_caSslContext->cipherFlag);
     switch(cipher)
     {
-        case MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA:
+        case MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256:
         {
-#ifdef __WITH_TLS__
-            //todo check that Cred with RSA cert exists
-            mbedtls_ssl_conf_ciphersuites(&g_caSslContext->clientTlsConf,
-                                         tlsCipher[ADAPTER_TLS_RSA_WITH_AES_256_CBC_SHA]);
-            mbedtls_ssl_conf_ciphersuites(&g_caSslContext->serverTlsConf,
-                                         tlsCipher[ADAPTER_TLS_RSA_WITH_AES_256_CBC_SHA]);
-#endif
-#ifdef __WITH_DTLS__
-            //todo check that Cred with RSA cert exists
-            mbedtls_ssl_conf_ciphersuites(&g_caSslContext->clientDtlsConf,
-                                         tlsCipher[ADAPTER_TLS_RSA_WITH_AES_256_CBC_SHA]);
-            mbedtls_ssl_conf_ciphersuites(&g_caSslContext->serverDtlsConf,
-                                         tlsCipher[ADAPTER_TLS_RSA_WITH_AES_256_CBC_SHA]);
-#endif
-            g_caSslContext->cipher = ADAPTER_TLS_RSA_WITH_AES_256_CBC_SHA;
-            break;
+            return SSL_RSA_WITH_AES_256_CBC_SHA256;
+        }
+        case MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256:
+        {
+            return SSL_RSA_WITH_AES_128_GCM_SHA256;
+        }
+        case MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
+        {
+            return SSL_ECDHE_RSA_WITH_AES_128_GCM_SHA256;
+        }
+        case MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:
+        {
+            return SSL_ECDHE_RSA_WITH_AES_256_GCM_SHA384;
+        }
+        case MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
+        {
+            return SSL_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256;
         }
         case MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8:
         {
-            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_8]);
-            mbedtls_ssl_conf_ciphersuites(&g_caSslContext->serverTlsConf,
-                                         tlsCipher[ADAPTER_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8]);
-#endif
-#ifdef __WITH_DTLS__
-            mbedtls_ssl_conf_ciphersuites(&g_caSslContext->clientDtlsConf,
-                                         tlsCipher[ADAPTER_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8]);
-            mbedtls_ssl_conf_ciphersuites(&g_caSslContext->serverDtlsConf,
-                                         tlsCipher[ADAPTER_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8]);
-#endif
-            g_caSslContext->cipher = ADAPTER_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8;
-            break;
+            return SSL_ECDHE_ECDSA_WITH_AES_128_CCM_8;
         }
-        case MBEDTLS_TLS_ECDH_ANON_WITH_AES_128_CBC_SHA256:
+        case MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM:
         {
-#ifdef __WITH_TLS__
-            mbedtls_ssl_conf_ciphersuites(&g_caSslContext->clientTlsConf,
-                                         tlsCipher[ADAPTER_TLS_ECDH_ANON_WITH_AES_128_CBC_SHA_256]);
-            mbedtls_ssl_conf_ciphersuites(&g_caSslContext->serverTlsConf,
-                                         tlsCipher[ADAPTER_TLS_ECDH_ANON_WITH_AES_128_CBC_SHA_256]);
-#endif
-#ifdef __WITH_DTLS__
-            mbedtls_ssl_conf_ciphersuites(&g_caSslContext->clientDtlsConf,
-                                         tlsCipher[ADAPTER_TLS_ECDH_ANON_WITH_AES_128_CBC_SHA_256]);
-            mbedtls_ssl_conf_ciphersuites(&g_caSslContext->serverDtlsConf,
-                                         tlsCipher[ADAPTER_TLS_ECDH_ANON_WITH_AES_128_CBC_SHA_256]);
-#endif
-            g_caSslContext->cipher = ADAPTER_TLS_ECDH_ANON_WITH_AES_128_CBC_SHA_256;
-            break;
+            return SSL_ECDHE_ECDSA_WITH_AES_128_CCM;
+        }
+        case MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:
+        {
+            return SSL_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256;
+        }
+        case MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384:
+        {
+            return SSL_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384;
+        }
+        case MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:
+        {
+            return SSL_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384;
         }
         case MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256:
         {
-#if 0 // PIN OTM
-            if (false == g_caSslContext->cipherFlag[0])
-            {
-                OIC_LOG(ERROR, NET_SSL_TAG, "No Credential for PSK");
-                return CA_STATUS_FAILED;
-            }
-#endif
-#ifdef __WITH_TLS__
-            mbedtls_ssl_conf_ciphersuites(&g_caSslContext->clientTlsConf,
-                                          tlsCipher[ADAPTER_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256]);
-            mbedtls_ssl_conf_ciphersuites(&g_caSslContext->serverTlsConf,
-                                          tlsCipher[ADAPTER_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256]);
-#endif
-#ifdef __WITH_DTLS__
-            mbedtls_ssl_conf_ciphersuites(&g_caSslContext->clientDtlsConf,
-                                          tlsCipher[ADAPTER_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256]);
-            mbedtls_ssl_conf_ciphersuites(&g_caSslContext->serverDtlsConf,
-                                          tlsCipher[ADAPTER_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256]);
-#endif
-            g_caSslContext->cipher = ADAPTER_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256;
-            break;
+            return SSL_ECDHE_PSK_WITH_AES_128_CBC_SHA256;
+        }
+        case MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
+        {
+            return SSL_ECDHE_RSA_WITH_AES_128_CBC_SHA256;
+        }
+        case MBEDTLS_TLS_ECDH_ANON_WITH_AES_128_CBC_SHA256:
+        {
+            return SSL_ECDH_ANON_WITH_AES_128_CBC_SHA256;
         }
         default:
         {
-            OIC_LOG(ERROR, NET_SSL_TAG, "Unknown cipher");
-            return CA_STATUS_FAILED;
+            return SSL_CIPHER_MAX;
         }
     }
-    OIC_LOG_V(DEBUG, NET_SSL_TAG, "Selected cipher: 0x%x", cipher);
+}
+
+CAResult_t CAsetTlsCipherSuite(const uint32_t cipher)
+{
+    OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s", __func__);
+    VERIFY_NON_NULL_RET(g_caSslContext, NET_SSL_TAG, "SSL context is not initialized." , CA_STATUS_NOT_INITIALIZED);
+
+    SslCipher_t index = GetCipherIndex(cipher);
+    if (SSL_CIPHER_MAX == index)
+    {
+        OIC_LOG(WARNING, NET_SSL_TAG, "Unknown cipher");
+    }
+    else
+    {
+#ifdef __WITH_TLS__
+        CONF_SSL(&g_caSslContext->clientTlsConf, &g_caSslContext->serverTlsConf,
+        mbedtls_ssl_conf_ciphersuites, tlsCipher[index]);
+#endif
+#ifdef __WITH_DTLS__
+        CONF_SSL(&g_caSslContext->clientDtlsConf, &g_caSslContext->serverDtlsConf,
+        mbedtls_ssl_conf_ciphersuites, tlsCipher[index]);
+#endif
+        OIC_LOG_V(INFO, NET_SSL_TAG, "Selected cipher: 0x%x", cipher);
+    }
+    g_caSslContext->cipher = index;
+
     OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
     return CA_STATUS_OK;
 }
@@ -1837,13 +2699,13 @@ CAResult_t CAinitiateSslHandshake(const CAEndpoint_t *endpoint)
     CAResult_t res = CA_STATUS_OK;
     OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s", __func__);
     VERIFY_NON_NULL_RET(endpoint, NET_SSL_TAG, "Param endpoint is NULL" , CA_STATUS_INVALID_PARAM);
-    ca_mutex_lock(g_sslContextMutex);
+    oc_mutex_lock(g_sslContextMutex);
     if (NULL == InitiateTlsHandshake(endpoint))
     {
         OIC_LOG(ERROR, NET_SSL_TAG, "TLS handshake failed");
         res = CA_STATUS_FAILED;
     }
-    ca_mutex_unlock(g_sslContextMutex);
+    oc_mutex_unlock(g_sslContextMutex);
     OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
     return res;
 }
@@ -1959,11 +2821,11 @@ 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);
 
-    ca_mutex_lock(g_sslContextMutex);
+    oc_mutex_lock(g_sslContextMutex);
     if (NULL == g_caSslContext)
     {
         OIC_LOG(ERROR, NET_SSL_TAG, "Context is NULL");
-        ca_mutex_unlock(g_sslContextMutex);
+        oc_mutex_unlock(g_sslContextMutex);
         OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
         return CA_STATUS_FAILED;
     }
@@ -1971,34 +2833,105 @@ CAResult_t CAsslGenerateOwnerPsk(const CAEndpoint_t *endpoint,
     if (NULL == tep)
     {
         OIC_LOG(ERROR, NET_SSL_TAG, "Session does not exist");
-        ca_mutex_unlock(g_sslContextMutex);
+        oc_mutex_unlock(g_sslContextMutex);
+        return CA_STATUS_FAILED;
+    }
+
+    // keyBlockLen set up according to OIC 1.1 Security Specification Section 7.3.2
+    int macKeyLen = 0;
+    int ivSize = 0;
+    int keySize = 0;
+    int keyBlockLen = 0;
+    if (MBEDTLS_TLS_ECDH_ANON_WITH_AES_128_CBC_SHA256 == g_caSslContext->selectedCipher ||
+        MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 == g_caSslContext->selectedCipher ||
+        MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 == g_caSslContext->selectedCipher ||
+        MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 == g_caSslContext->selectedCipher)
+    {
+        // 2 * ( 32 + 0 + 16 ) = 96
+        macKeyLen = SHA256_MAC_KEY_LENGTH;
+        ivSize = CBC_IV_LENGTH;
+        keySize = AES128_KEY_LENGTH;
+    }
+    else if (MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM == g_caSslContext->selectedCipher ||
+             MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 == g_caSslContext->selectedCipher)
+    {
+        // 2 * ( 0 + 4 + 16 ) = 40
+        macKeyLen = CCM_MAC_KEY_LENGTH;
+        ivSize = CCM_IV_LENGTH;
+        keySize = AES128_KEY_LENGTH;
+    }
+    else if (MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 == g_caSslContext->selectedCipher)
+    {
+        // 2 * ( 32 + 12 + 16 ) = 120
+        macKeyLen = SHA256_MAC_KEY_LENGTH;
+        ivSize = GCM_IV_LENGTH;
+        keySize = AES128_KEY_LENGTH;
+    }
+    else if (MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256 == g_caSslContext->selectedCipher)
+    {
+        // 2 * ( 32 + 0 + 32 ) = 128
+        macKeyLen = SHA256_MAC_KEY_LENGTH;
+        ivSize = CBC_IV_LENGTH;
+        keySize = AES256_KEY_LENGTH;
+    }
+    else if (MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 == g_caSslContext->selectedCipher)
+    {
+        // 2 * ( 48 + 0 + 32 ) = 160
+        macKeyLen = SHA384_MAC_KEY_LENGTH;
+        ivSize = CBC_IV_LENGTH;
+        keySize = AES256_KEY_LENGTH;
+    }
+    else if (MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 == g_caSslContext->selectedCipher)
+    {
+        // 2 * ( 48 + 12 + 32 ) = 184
+        macKeyLen = SHA384_MAC_KEY_LENGTH;
+        ivSize = GCM_IV_LENGTH;
+        keySize = AES256_KEY_LENGTH;
+    }
+    else if (MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256 == g_caSslContext->selectedCipher)
+    {
+        // 2 * ( 48 + 12 + 32 ) = 184
+        macKeyLen = SHA256_MAC_KEY_LENGTH;
+        ivSize = GCM_IV_LENGTH;
+        keySize = AES128_KEY_LENGTH;
+    }
+    keyBlockLen = 2 * (macKeyLen + keySize + ivSize);
+
+    uint8_t * keyblock = (uint8_t *)OICMalloc(keyBlockLen);
+    if (NULL == keyblock)
+    {
+        OIC_LOG(ERROR, NET_SSL_TAG, "Failed to OICMalloc for keyblock");
+        oc_mutex_unlock(g_sslContextMutex);
         return CA_STATUS_FAILED;
     }
 
-    uint8_t keyblock[KEY_BLOCK_LEN] = {0};
     // "key expansion"
     uint8_t lab[] = {0x6b, 0x65, 0x79, 0x20, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x73, 0x69, 0x6f, 0x6e};
     int ret = pHash(tep->master, sizeof(tep->master), lab, sizeof(lab),
                     (tep->random) + RANDOM_LEN, RANDOM_LEN, tep->random, RANDOM_LEN,
-                    keyblock, KEY_BLOCK_LEN);
+                    keyblock, keyBlockLen);
     if (-1 == ret)
     {
         OIC_LOG(ERROR, NET_SSL_TAG, "PSK not generated");
-        ca_mutex_unlock(g_sslContextMutex);
+        OICFree(keyblock);
+        oc_mutex_unlock(g_sslContextMutex);
         return CA_STATUS_FAILED;
     }
-    ret = pHash(keyblock, sizeof(keyblock), label, labelLen,
+
+    ret = pHash(keyblock, keyBlockLen, label, labelLen,
                 rsrcServerDeviceId, rsrcServerDeviceIdLen,
                 provServerDeviceId, provServerDeviceIdLen,
                 ownerPsk, ownerPskSize);
     if (-1 == ret)
     {
         OIC_LOG(ERROR, NET_SSL_TAG, "PSK not generated");
-        ca_mutex_unlock(g_sslContextMutex);
+        OICFree(keyblock);
+        oc_mutex_unlock(g_sslContextMutex);
         return CA_STATUS_FAILED;
     }
 
-    ca_mutex_unlock(g_sslContextMutex);
+    OICFree(keyblock);
+    oc_mutex_unlock(g_sslContextMutex);
 
     OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
     return CA_STATUS_OK;