TLS support
authorAndrii Shtompel <a.shtompel@samsung.com>
Wed, 17 Aug 2016 08:39:50 +0000 (11:39 +0300)
committerRandeep Singh <randeep.s@samsung.com>
Wed, 17 Aug 2016 14:45:10 +0000 (14:45 +0000)
Provide TLS connection using mbedTLS

1. Changed TCP adapter to support CoAP and TLS
2. Provisioning works via TLS and DTLS
3. Integrated mbedTLS
4. Added device ID to CASecureEndpoint_t
5. Reset to patch#16 for merging to master

Change-Id: I4c8f2f4f1a21dea984fc2239a31382052c223dfe
Signed-off-by: Dmitriy Zhuravlev <d.zhuravlev@samsung.com>
Signed-off-by: Andrii Shtompel <a.shtompel@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/10543
Reviewed-by: dongik Lee <dongik.lee@samsung.com>
Reviewed-by: Jongmin Choi <jminl.choi@samsung.com>
Tested-by: jenkins-iotivity <jenkins-iotivity@opendaylight.org>
Reviewed-by: Randeep Singh <randeep.s@samsung.com>
46 files changed:
extlibs/mbedtls/SConscript [new file with mode: 0644]
extlibs/mbedtls/ocf.patch [new file with mode: 0644]
resource/c_common/ocrandom/test/SConscript
resource/csdk/SConscript
resource/csdk/connectivity/api/cacommon.h
resource/csdk/connectivity/api/casecurityinterface.h
resource/csdk/connectivity/inc/ca_adapter_net_tls.h [new file with mode: 0644]
resource/csdk/connectivity/inc/caadapterinterface.h
resource/csdk/connectivity/inc/catcpadapter.h
resource/csdk/connectivity/src/SConscript
resource/csdk/connectivity/src/adapter_util/ca_adapter_net_tls.c [new file with mode: 0644]
resource/csdk/connectivity/src/caconnectivitymanager.c
resource/csdk/connectivity/src/tcp_adapter/catcpadapter.c
resource/csdk/connectivity/src/tcp_adapter/catcpserver.c
resource/csdk/connectivity/test/SConscript
resource/csdk/security/SConscript
resource/csdk/security/include/internal/credresource.h
resource/csdk/security/include/securevirtualresourcetypes.h
resource/csdk/security/provisioning/SConscript
resource/csdk/security/provisioning/include/pmtypes.h
resource/csdk/security/provisioning/include/pmutility.h
resource/csdk/security/provisioning/sample/SConscript
resource/csdk/security/provisioning/sample/provisioningclient.c
resource/csdk/security/provisioning/src/ownershiptransfermanager.c
resource/csdk/security/provisioning/src/oxmjustworks.c
resource/csdk/security/provisioning/src/oxmrandompin.c
resource/csdk/security/provisioning/src/pmutility.c
resource/csdk/security/provisioning/src/secureresourceprovider.c
resource/csdk/security/provisioning/unittest/SConscript
resource/csdk/security/src/credresource.c
resource/csdk/security/src/crlresource.c
resource/csdk/security/src/directpairing.c
resource/csdk/security/src/doxmresource.c
resource/csdk/security/src/dpairingresource.c
resource/csdk/security/src/secureresourcemanager.c
resource/csdk/security/tool/SConscript
resource/csdk/security/unittest/SConscript
resource/csdk/stack/samples/linux/secure/SConscript
resource/csdk/stack/samples/linux/secure/occlientbasicops.cpp
resource/csdk/stack/src/ocstack.c
resource/csdk/stack/test/SConscript
resource/csdk/stack/test/linux/SConscript
resource/provisioning/SConscript
resource/provisioning/examples/SConscript
resource/provisioning/unittests/SConscript
resource/unittests/SConscript

diff --git a/extlibs/mbedtls/SConscript b/extlibs/mbedtls/SConscript
new file mode 100644 (file)
index 0000000..fe1b75e
--- /dev/null
@@ -0,0 +1,87 @@
+#******************************************************************
+#
+# Copyright 2016 Samsung Electronics All Rights Reserved.
+#
+#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+Import('env')
+
+import os
+import sys
+
+def run(cmd):
+    """Run a command and decipher the return code. Exit by default."""
+    res = os.system(cmd)
+    # Assumes that if a process doesn't call exit, it was successful
+    if (os.WIFEXITED(res)):
+        code = os.WEXITSTATUS(res)
+        if code != 0:
+            print "Error: return code: " + str(code)
+            if SCons.Script.keep_going_on_error == 0:
+                sys.exit(code)
+
+root_dir = env.get('SRC_DIR')
+
+tls_dir = os.path.join(root_dir, 'extlibs','mbedtls','mbedtls')
+
+if not os.path.exists(tls_dir):
+    print '''
+*********************************** Error: ****************************************
+* Please download mbedtls using the following command:                            *
+*     $ git clone https://github.com/ARMmbed/mbedtls.git extlibs/mbedtls/mbedtls  *
+***********************************************************************************
+'''
+    Exit(1)
+
+start_dir = os.getcwd()
+os.chdir(tls_dir)
+
+#Apply patch to enable TLS_ECDH_ANON_WITH_AES_128_CBC_SHA256 ciphersuite and server identity hint
+cmd = 'git reset --hard ad249f509fd62a3bbea7ccd1fef605dbd482a7bd && git apply ../ocf.patch'
+run(cmd)
+
+build_dir = env.get('BUILD_DIR')
+libs_list = ['libmbedcrypto.so', 'libmbedtls.so', 'libmbedx509.so']
+
+if env.GetOption('clean'):
+       print 'Clean-up mbedtls...'
+       run('make clean')
+
+       #Delete copied libs from out folder
+       for file_name in libs_list:
+               run("rm -f " + build_dir + file_name + "*")
+else:
+       #Pass to make proper debug option
+       if env.get('RELEASE'): debug = ''
+       else: debug = 'DEBUG=1 '
+
+       cmd = 'export SHARED=1 ' + debug + '&& make no_test'
+
+       print 'Making mbedtls libraries...'
+       print cmd
+       run(cmd)
+       
+       #Copy libs to out folder
+       if not os.path.exists(build_dir): os.makedirs(build_dir)
+       for file_name in libs_list:
+               run("cp -d " + tls_dir + '/library/' + file_name + " " + build_dir)
+               run("cp " + tls_dir + '/library/' + file_name + ".* " + build_dir)
+
+os.chdir(start_dir)
+
+
+
diff --git a/extlibs/mbedtls/ocf.patch b/extlibs/mbedtls/ocf.patch
new file mode 100644 (file)
index 0000000..1976f89
--- /dev/null
@@ -0,0 +1,554 @@
+diff --git a/include/mbedtls/check_config.h b/include/mbedtls/check_config.h
+index a95af6c..a3852b2 100644
+--- a/include/mbedtls/check_config.h
++++ b/include/mbedtls/check_config.h
+@@ -184,6 +184,11 @@
+ #error "MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED defined, but not all prerequisites"
+ #endif
++#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ANON_ENABLED) &&                 \
++    ( !defined(MBEDTLS_ECDH_C) )
++#error "MBEDTLS_KEY_EXCHANGE_ECDH_ANON_ENABLED defined, but not all prerequisites"
++#endif
++
+ #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) &&                 \
+     ( !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_ECDSA_C) ||          \
+       !defined(MBEDTLS_X509_CRT_PARSE_C) )
+diff --git a/include/mbedtls/compat-1.3.h b/include/mbedtls/compat-1.3.h
+index 27abbd9..fa4db26 100644
+--- a/include/mbedtls/compat-1.3.h
++++ b/include/mbedtls/compat-1.3.h
+@@ -264,6 +264,9 @@
+ #if defined MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED
+ #define POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED
+ #endif
++#if defined MBEDTLS_KEY_EXCHANGE_ECDH_ANON_ENABLED
++#define POLARSSL_KEY_EXCHANGE_ECDH_ANON_ENABLED MBEDTLS_KEY_EXCHANGE_ECDH_ANON_ENABLED
++#endif
+ #if defined MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED
+ #define POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED
+ #endif
+@@ -1273,6 +1276,7 @@
+ #define POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA
+ #define POLARSSL_KEY_EXCHANGE_ECDHE_PSK MBEDTLS_KEY_EXCHANGE_ECDHE_PSK
+ #define POLARSSL_KEY_EXCHANGE_ECDHE_RSA MBEDTLS_KEY_EXCHANGE_ECDHE_RSA
++#define POLARSSL_KEY_EXCHANGE_ECDH_ANON MBEDTLS_KEY_EXCHANGE_ECDH_ANON
+ #define POLARSSL_KEY_EXCHANGE_ECDH_ECDSA MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA
+ #define POLARSSL_KEY_EXCHANGE_ECDH_RSA MBEDTLS_KEY_EXCHANGE_ECDH_RSA
+ #define POLARSSL_KEY_EXCHANGE_NONE MBEDTLS_KEY_EXCHANGE_NONE
+@@ -1616,6 +1620,7 @@
+ #define TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384
+ #define TLS_ECDHE_RSA_WITH_NULL_SHA MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA
+ #define TLS_ECDHE_RSA_WITH_RC4_128_SHA MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA
++#define TLS_ECDH_ANON_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_ECDH_ANON_WITH_AES_128_CBC_SHA256
+ #define TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
+ #define TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
+ #define TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
+diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h
+index 3b7c85b..5bef190 100644
+--- a/include/mbedtls/config.h
++++ b/include/mbedtls/config.h
+@@ -642,6 +642,21 @@
+ #define MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED
+ /**
++ * \def MBEDTLS_KEY_EXCHANGE_ECDH_ANON_ENABLED
++ *
++ * Enable the ECDHE-ANON based ciphersuite modes in SSL / TLS.
++ *
++ * Requires: MBEDTLS_ECDH_C
++ *
++ *
++ * This enables the following ciphersuites (if other requisites are
++ * enabled as well):
++ *      MBEDTLS_TLS_ECDH_ANON_WITH_AES_128_CBC_SHA256
++ */
++#define MBEDTLS_KEY_EXCHANGE_ECDH_ANON_ENABLED
++
++
++/**
+  * \def MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
+  *
+  * Enable the ECDHE-ECDSA based ciphersuite modes in SSL / TLS.
+@@ -1239,7 +1254,7 @@
+  *
+  * Comment this macro to disable support for SSL session tickets
+  */
+-#define MBEDTLS_SSL_SESSION_TICKETS
++//#define MBEDTLS_SSL_SESSION_TICKETS
+ /**
+  * \def MBEDTLS_SSL_EXPORT_KEYS
+@@ -1479,6 +1494,7 @@
+  *      MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256
+  *      MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256
+  *      MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA
++ *      MBEDTLS_TLS_ECDH_ANON_WITH_AES_128_CBC_SHA256
+  *
+  * PEM_PARSE uses AES for decrypting encrypted keys.
+  */
+diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h
+index 82c0760..88103ad 100644
+--- a/include/mbedtls/ssl.h
++++ b/include/mbedtls/ssl.h
+@@ -356,7 +356,8 @@ union mbedtls_ssl_premaster_secret
+ #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED)    || \
+     defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)  || \
+     defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED)     || \
+-    defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
++    defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)   || \
++    defined(MBEDTLS_KEY_EXCHANGE_ECDH_ANON_ENABLED)
+     unsigned char _pms_ecdh[MBEDTLS_ECP_MAX_BYTES];    /* RFC 4492 5.10 */
+ #endif
+ #if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)
+diff --git a/include/mbedtls/ssl_ciphersuites.h b/include/mbedtls/ssl_ciphersuites.h
+index deaaa37..4f10540 100644
+--- a/include/mbedtls/ssl_ciphersuites.h
++++ b/include/mbedtls/ssl_ciphersuites.h
+@@ -158,6 +158,8 @@ extern "C" {
+ #define MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256     0xC031 /**< TLS 1.2 */
+ #define MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384     0xC032 /**< TLS 1.2 */
++#define MBEDTLS_TLS_ECDH_ANON_WITH_AES_128_CBC_SHA256    0xFF00 /**< TLS 1.2 */
++
+ #define MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA           0xC033 /**< Not in SSL3! */
+ #define MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA      0xC034 /**< Not in SSL3! */
+ #define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA       0xC035 /**< Not in SSL3! */
+@@ -247,6 +249,7 @@ typedef enum {
+     MBEDTLS_KEY_EXCHANGE_ECDH_RSA,
+     MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA,
+     MBEDTLS_KEY_EXCHANGE_ECJPAKE,
++    MBEDTLS_KEY_EXCHANGE_ECDH_ANON,
+ } mbedtls_key_exchange_type_t;
+ /* Key exchanges using a certificate */
+@@ -271,7 +274,8 @@ typedef enum {
+ /* Key exchanges using a ECDHE */
+ #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED)     || \
+     defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)   || \
+-    defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED)
++    defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED)     || \
++    defined(MBEDTLS_KEY_EXCHANGE_ECDH_ANON_ENABLED)
+ #define MBEDTLS_KEY_EXCHANGE__SOME__ECDHE_ENABLED
+ #endif
+diff --git a/library/ssl_ciphersuites.c b/library/ssl_ciphersuites.c
+index 3546331..74cef29 100644
+--- a/library/ssl_ciphersuites.c
++++ b/library/ssl_ciphersuites.c
+@@ -96,6 +96,7 @@ static const int ciphersuite_preference[] =
+     MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
+     MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8,
+     MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8,
++    MBEDTLS_TLS_ECDH_ANON_WITH_AES_128_CBC_SHA256,
+     /* All CAMELLIA-128 ephemeral suites */
+     MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256,
+@@ -408,6 +409,22 @@ static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] =
+ #endif /* MBEDTLS_CIPHER_NULL_CIPHER */
+ #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
++
++#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ANON_ENABLED)
++#if defined(MBEDTLS_AES_C)
++#if defined(MBEDTLS_SHA256_C)
++#if defined(MBEDTLS_CIPHER_MODE_CBC)
++    { MBEDTLS_TLS_ECDH_ANON_WITH_AES_128_CBC_SHA256, "TLS-ECDH-ANON-WITH-AES-128-CBC-SHA256",
++      MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ANON,
++      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
++      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
++      0 },
++#endif /* MBEDTLS_CIPHER_MODE_CBC */
++#endif /* MBEDTLS_SHA256_C */
++#endif /* MBEDTLS_AES_C */
++#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_ANON_ENABLED */
++
++
+ #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED)
+ #if defined(MBEDTLS_AES_C)
+ #if defined(MBEDTLS_SHA1_C)
+@@ -1830,6 +1847,7 @@ int mbedtls_ssl_ciphersuite_uses_ec( const mbedtls_ssl_ciphersuite_t *info )
+         case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK:
+         case MBEDTLS_KEY_EXCHANGE_ECDH_RSA:
+         case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA:
++        case MBEDTLS_KEY_EXCHANGE_ECDH_ANON:
+             return( 1 );
+         default:
+diff --git a/library/ssl_cli.c b/library/ssl_cli.c
+index cd39db0..2503022 100644
+--- a/library/ssl_cli.c
++++ b/library/ssl_cli.c
+@@ -1897,7 +1897,8 @@ static int ssl_parse_server_dh_params( mbedtls_ssl_context *ssl, unsigned char *
+     defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) ||                   \
+     defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) ||                     \
+     defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) ||                      \
+-    defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
++    defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) ||                    \
++    defined(MBEDTLS_KEY_EXCHANGE_ECDH_ANON_ENABLED)
+ static int ssl_check_server_ecdh_params( const mbedtls_ssl_context *ssl )
+ {
+     const mbedtls_ecp_curve_info *curve_info;
+@@ -1927,11 +1928,13 @@ static int ssl_check_server_ecdh_params( const mbedtls_ssl_context *ssl )
+           MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED ||
+           MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED ||
+           MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED ||
+-          MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */
++          MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED ||
++          MBEDTLS_KEY_EXCHANGE_ECDH_ANON_ENABLED */
+ #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) ||                     \
+     defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) ||                   \
+-    defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED)
++    defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) ||                     \
++    defined(MBEDTLS_KEY_EXCHANGE_ECDH_ANON_ENABLED)
+ static int ssl_parse_server_ecdh_params( mbedtls_ssl_context *ssl,
+                                          unsigned char **p,
+                                          unsigned char *end )
+@@ -1963,40 +1966,75 @@ static int ssl_parse_server_ecdh_params( mbedtls_ssl_context *ssl,
+ }
+ #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED ||
+           MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED ||
+-          MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */
++          MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED ||
++          MBEDTLS_KEY_EXCHANGE_ECDH_ANON_ENABLED*/
+ #if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED)
+ static int ssl_parse_server_psk_hint( mbedtls_ssl_context *ssl,
+                                       unsigned char **p,
+                                       unsigned char *end )
+ {
+-    int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
+-    size_t  len;
+-    ((void) ssl);
++        int ret = 0;
++    size_t n;
++
++    if( ssl->conf->f_psk == NULL &&
++        ( ssl->conf->psk == NULL || ssl->conf->psk_identity == NULL ||
++          ssl->conf->psk_identity_len == 0 || ssl->conf->psk_len == 0 ) )
++    {
++        MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no pre-shared key" ) );
++        return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED );
++    }
+     /*
+-     * PSK parameters:
+-     *
+-     * opaque psk_identity_hint<0..2^16-1>;
++     * Receive client pre-shared key identity name
+      */
+-    len = (*p)[0] << 8 | (*p)[1];
++    if( *p + 2 > end )
++    {
++        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
++        return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
++    }
++
++    n = ( (*p)[0] << 8 ) | (*p)[1];
+     *p += 2;
+-    if( (*p) + len > end )
++    if( n < 1 || n > 65535 || *p + n > end )
+     {
+-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message (psk_identity_hint length)" ) );
+-        return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
++        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
++        return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
+     }
+-    /*
+-     * Note: we currently ignore the PKS identity hint, as we only allow one
+-     * PSK to be provisionned on the client. This could be changed later if
+-     * someone needs that feature.
+-     */
+-    *p += len;
+-    ret = 0;
++    if( ssl->conf->f_psk != NULL )
++    {
++        if( ssl->conf->f_psk( ssl->conf->p_psk, ssl, *p, n ) != 0 )
++            ret = MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY;
++    }
++    else
++    {
++        /* Identity is not a big secret since clients send it in the clear,
++         * but treat it carefully anyway, just in case */
++        if( n != ssl->conf->psk_identity_len ||
++            mbedtls_ssl_safer_memcmp( ssl->conf->psk_identity, *p, n ) != 0 )
++        {
++            ret = MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY;
++        }
++    }
+-    return( ret );
++    if( ret == MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY )
++    {
++        MBEDTLS_SSL_DEBUG_BUF( 3, "Unknown PSK identity", *p, n );
++        if( ( ret = mbedtls_ssl_send_alert_message( ssl,
++                              MBEDTLS_SSL_ALERT_LEVEL_FATAL,
++                              MBEDTLS_SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY ) ) != 0 )
++        {
++            return( ret );
++        }
++
++        return( MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY );
++    }
++
++    *p += n;
++
++    return( 0 );
+ }
+ #endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */
+@@ -2292,10 +2330,12 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl )
+           MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */
+ #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) ||                     \
+     defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) ||                     \
+-    defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
++    defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) ||                   \
++    defined(MBEDTLS_KEY_EXCHANGE_ECDH_ANON_ENABLED)
+     if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA ||
+         ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ||
+-        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA )
++        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA ||
++        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ANON )
+     {
+         if( ssl_parse_server_ecdh_params( ssl, &p, end ) != 0 )
+         {
+@@ -2306,7 +2346,8 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl )
+     else
+ #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED ||
+           MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED ||
+-          MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
++          MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED ||
++          MBEDTLS_KEY_EXCHANGE_ECDH_ANON_ENABLED */
+ #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
+     if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE )
+     {
+@@ -2377,6 +2418,10 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl )
+             return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+         }
++// Anonim cipher suite without sign, ecdh param only
++#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ANON_ENABLED)
++        goto exit;
++#endif
+         /*
+          * Read signature
+          */
+@@ -2525,7 +2570,8 @@ static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl )
+         ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ||
+         ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ||
+         ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ||
+-        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE )
++        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ||
++        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ANON )
+     {
+         MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate request" ) );
+         ssl->state++;
+@@ -2550,7 +2596,8 @@ static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl )
+         ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ||
+         ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ||
+         ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ||
+-        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE )
++        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ||
++        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ANON )
+     {
+         MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate request" ) );
+         ssl->state++;
+@@ -2753,11 +2800,13 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl )
+ #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) ||                     \
+     defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) ||                   \
+     defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) ||                      \
+-    defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
++    defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) ||                    \
++    defined(MBEDTLS_KEY_EXCHANGE_ECDH_ANON_ENABLED)
+     if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA ||
+         ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA ||
+         ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_RSA ||
+-        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA )
++        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA ||
++        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ANON)
+     {
+         /*
+          * ECDH key exchange -- send client public value
+@@ -2792,7 +2841,8 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl )
+ #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED ||
+           MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED ||
+           MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED ||
+-          MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */
++          MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED
++          MBEDTLS_KEY_EXCHANGE_ECDH_ANON_ENABLED */
+ #if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED)
+     if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ||
+         ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ||
+@@ -2980,7 +3030,8 @@ static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl )
+         ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ||
+         ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ||
+         ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ||
+-        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE )
++        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ||
++        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ANON )
+     {
+         MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate verify" ) );
+         ssl->state++;
+@@ -3013,7 +3064,8 @@ static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl )
+         ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ||
+         ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ||
+         ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ||
+-        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE )
++        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ||
++        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ANON )
+     {
+         MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate verify" ) );
+         ssl->state++;
+diff --git a/library/ssl_srv.c b/library/ssl_srv.c
+index 7271045..2964015 100644
+--- a/library/ssl_srv.c
++++ b/library/ssl_srv.c
+@@ -2500,6 +2500,7 @@ static int ssl_write_certificate_request( mbedtls_ssl_context *ssl )
+         ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ||
+         ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ||
+         ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ||
++        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ANON ||
+         authmode == MBEDTLS_SSL_VERIFY_NONE )
+     {
+         MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate request" ) );
+@@ -2677,7 +2678,8 @@ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl )
+     defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) ||                     \
+     defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) ||                     \
+     defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) ||                   \
+-    defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
++    defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) ||                        \
++    defined(MBEDTLS_KEY_EXCHANGE_ECDH_ANON_ENABLED)
+     unsigned char *p = ssl->out_msg + 4;
+     unsigned char *dig_signed = p;
+     size_t dig_signed_len = 0, len;
+@@ -2738,12 +2740,11 @@ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl )
+     if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ||
+         ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK )
+     {
+-        /* Note: we don't support identity hints, until someone asks
+-         * for them. */
+-        *(p++) = 0x00;
+-        *(p++) = 0x00;
+-
+-        n += 2;
++        *(p++) = (unsigned char)( ssl->conf->psk_identity_len >> 8 );
++        *(p++) = (unsigned char)( ssl->conf->psk_identity_len      );
++        memcpy(p, ssl->conf->psk_identity, ssl->conf->psk_identity_len);
++        p += ssl->conf->psk_identity_len;
++        n += ssl->conf->psk_identity_len + 2;
+     }
+ #endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED ||
+           MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */
+@@ -2800,7 +2801,8 @@ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl )
+ #if defined(MBEDTLS_KEY_EXCHANGE__SOME__ECDHE_ENABLED)
+     if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA ||
+         ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA ||
+-        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK )
++        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ||
++        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ANON)
+     {
+         /*
+          * Ephemeral ECDH parameters:
+@@ -3338,11 +3340,13 @@ static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl )
+ #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) ||                     \
+     defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) ||                   \
+     defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) ||                      \
+-    defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
++    defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) ||                    \
++    defined(MBEDTLS_KEY_EXCHANGE_ECDH_ANON_ENABLED)
+     if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA ||
+         ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA ||
+         ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_RSA ||
+-        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA )
++        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA ||
++        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ANON )
+     {
+         if( ( ret = mbedtls_ecdh_read_public( &ssl->handshake->ecdh_ctx,
+                                       p, end - p) ) != 0 )
+@@ -3539,7 +3543,8 @@ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl )
+         ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ||
+         ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ||
+         ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ||
+-        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE )
++        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ||
++        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ANON )
+     {
+         MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate verify" ) );
+         ssl->state++;
+@@ -3570,6 +3575,7 @@ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl )
+         ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ||
+         ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ||
+         ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ||
++        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ANON ||
+         ssl->session_negotiate->peer_cert == NULL )
+     {
+         MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate verify" ) );
+diff --git a/library/ssl_tls.c b/library/ssl_tls.c
+index 80a908d..94c8fd7 100644
+--- a/library/ssl_tls.c
++++ b/library/ssl_tls.c
+@@ -4037,7 +4037,8 @@ int mbedtls_ssl_write_certificate( mbedtls_ssl_context *ssl )
+     if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ||
+         ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ||
+         ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ||
+-        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE )
++        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ||
++        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ANON )
+     {
+         MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate" ) );
+         ssl->state++;
+@@ -4057,7 +4058,8 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl )
+     if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ||
+         ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ||
+         ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ||
+-        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE )
++        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ||
++        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ANON )
+     {
+         MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) );
+         ssl->state++;
+@@ -4080,7 +4082,8 @@ int mbedtls_ssl_write_certificate( mbedtls_ssl_context *ssl )
+     if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ||
+         ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ||
+         ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ||
+-        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE )
++        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ||
++        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ANON )
+     {
+         MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate" ) );
+         ssl->state++;
+@@ -4196,7 +4199,8 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl )
+     if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ||
+         ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ||
+         ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ||
+-        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE )
++        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ||
++        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ANON )
+     {
+         MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) );
+         ssl->state++;
+@@ -7510,6 +7514,7 @@ int mbedtls_ssl_check_cert_usage( const mbedtls_x509_crt *cert,
+             case MBEDTLS_KEY_EXCHANGE_DHE_PSK:
+             case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK:
+             case MBEDTLS_KEY_EXCHANGE_ECJPAKE:
++            case MBEDTLS_KEY_EXCHANGE_ECDH_ANON:
+                 usage = 0;
+         }
+     }
+diff --git a/library/version_features.c b/library/version_features.c
+index 5d20ba0..6404a0c 100644
+--- a/library/version_features.c
++++ b/library/version_features.c
+@@ -264,6 +264,9 @@ static const char *features[] = {
+ #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED)
+     "MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED",
+ #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED */
++#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ANON_ENABLED)
++    "MBEDTLS_KEY_EXCHANGE_ECDH_ANON_ENABLED",
++#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_ANON_ENABLED */
+ #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
+     "MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED",
+ #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
index 6b73957..d6ac4dc 100644 (file)
@@ -42,6 +42,10 @@ randomtest_env.PrependUnique(LIBS = ['octbstack',
 if target_os in ['linux']:
     randomtest_env.AppendUnique(LIBS = ['m'])
 
+if randomtest_env.get('SECURED') == '1':
+       if randomtest_env.get('WITH_TCP') == True:
+               randomtest_env.AppendUnique(LIBS = ['mbedtls', 'mbedx509','mbedcrypto'])
+
 if randomtest_env.get('LOGGING'):
        randomtest_env.AppendUnique(CPPDEFINES = ['TB_LOG'])
 
index d3459d3..8606857 100644 (file)
@@ -53,6 +53,7 @@ liboctbstack_env.PrependUnique(CPPPATH = [
                'connectivity/lib/libcoap-4.1.1',
                'connectivity/common/inc',
                'connectivity/inc',
+               'connectivity/inc/pkix',
                'connectivity/api',
                'connectivity/external/inc',
                'security/include',
@@ -115,6 +116,8 @@ if target_os == 'android':
 
 if env.get('SECURED') == '1':
        liboctbstack_env.AppendUnique(LIBS = ['tinydtls'])
+       if env.get('WITH_TCP') == True:
+               liboctbstack_env.AppendUnique(LIBS = ['mbedtls', 'mbedx509','mbedcrypto'])
 
 if env.get('LOGGING'):
        liboctbstack_env.AppendUnique(CPPDEFINES = ['TB_LOG'])
index e42f75a..87d1174 100644 (file)
@@ -286,7 +286,9 @@ typedef struct
 typedef struct
 {
     CAEndpoint_t endpoint;      /**< endpoint */
-    CARemoteId_t identity;      /**< endpoint identity */
+    // TODO change name to deviceId
+    CARemoteId_t identity;      /**< endpoint device uuid */
+    CARemoteId_t userId;        /**< endpoint user uuid */
 } CASecureEndpoint_t;
 
 /**
index cab30a7..277c4ff 100644 (file)
 
 #include "cacommon.h"
 
+#ifdef __WITH_TLS__
+#include "byte_array.h"
+#endif
+
 #ifdef __cplusplus
 extern "C"
 {
 #endif
 
 
-#ifdef __WITH_DTLS__
+#if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
 /**
  * @enum CADtlsPskCredType_t
  * Type of PSK credential required during DTLS handshake
@@ -67,8 +71,10 @@ typedef enum
  *         less than zero on error.
  */
 typedef int (*CAGetDTLSPskCredentialsHandler)(CADtlsPskCredType_t type,
-                     const uint8_t *desc, size_t desc_len,
-                     uint8_t *result, size_t result_length);
+              const uint8_t *desc, size_t desc_len,
+              uint8_t *result, size_t result_length);
+#endif // __WITH_DTLS__ or __WITH_TLS__
+#ifdef __WITH_DTLS__
 
 /**
  * Register callback to receive the result of DTLS handshake.
@@ -86,6 +92,52 @@ CAResult_t CARegisterDTLSCredentialsHandler(CAGetDTLSPskCredentialsHandler GetDT
 
 #endif //__WITH_DTLS__
 
+
+#ifdef __WITH_TLS__
+/**
+ * Binary structure containing PKIX related info
+ * own certificate chain, public key, CA's and CRL's
+ */
+typedef struct
+{
+    // own certificate chain
+    ByteArray crt;
+    // own public key
+    ByteArray key;
+    // trusted CA's
+    ByteArray ca;
+    // trusted CRL's
+    ByteArray crl;
+} PkiInfo_t;
+
+/**
+ * Register callback to receive the result of TLS handshake.
+ * @param[in] tlsHandshakeCallback callback for get tls handshake result
+ * @return ::CA_STATUS_OK
+ */
+CAResult_t CAregisterTlsHandshakeCallback(CAErrorCallback tlsHandshakeCallback);
+
+/**
+ * Register callback to get TLS PSK credentials.
+ * @param[in]   getTLSCredentials    GetDTLS Credetials callback.
+ * @return  ::CA_STATUS_OK
+ */
+CAResult_t CAregisterTlsCredentialsHandler(CAGetDTLSPskCredentialsHandler getTlsCredentials);
+
+/**
+ * @brief   Callback function type for getting PKIX info
+ *
+ * @param   inf[out]   PKIX related info
+ *
+ * @return  NONE
+ */
+typedef void (*CAgetPkixInfoHandler)(PkiInfo_t * inf);
+
+//TODO
+void GetPkixInfo(PkiInfo_t * inf);
+CAResult_t CAregisterPkixInfoHandler(CAgetPkixInfoHandler getPkixInfoHandler);
+#endif //__WITH_TLS__
+
 #ifdef __WITH_X509__
 /**
  * Binary structure containing certificate chain and certificate credentials
@@ -152,7 +204,7 @@ CAResult_t CARegisterDTLSCrlHandler(CAGetDTLSCrlHandler GetCrl);
  * @retval  ::CA_STATUS_INVALID_PARAM  Invalid input arguments.
  * @retval  ::CA_STATUS_FAILED Operation failed.
  */
-CAResult_t CASelectCipherSuite(const uint16_t cipher);
+CAResult_t CASelectCipherSuite(const uint16_t cipher, CATransportAdapter_t adapter);
 
 /**
  * Enable TLS_ECDH_anon_WITH_AES_128_CBC_SHA cipher suite in dtls.
@@ -216,6 +268,29 @@ CAResult_t CACloseDtlsSession(const CAEndpoint_t *endpoint);
 
 #endif /* __WITH_DTLS__ */
 
+#ifdef __WITH_TLS__
+
+/**
+ * Initiate TLS handshake with selected cipher suite.
+ *
+ * @param[in] endpoint information of network address.
+ *
+ * @retval  ::CA_STATUS_OK    Successful.
+ * @retval  ::CA_STATUS_FAILED Operation failed.
+ */
+CAResult_t CAinitiateTlsHandshake(const CAEndpoint_t *endpoint);
+
+/**
+ * Close the DTLS session.
+ *
+ * @param[in] endpoint  information of network address.
+ *
+ * @retval  ::CA_STATUS_OK    Successful.
+ * @retval  ::CA_STATUS_FAILED Operation failed.
+ */
+CAResult_t CAcloseTlsConnection(const CAEndpoint_t *endpoint);
+
+#endif /* __WITH_TLS__ */
 
 #ifdef __cplusplus
 } /* extern "C" */
diff --git a/resource/csdk/connectivity/inc/ca_adapter_net_tls.h b/resource/csdk/connectivity/inc/ca_adapter_net_tls.h
new file mode 100644 (file)
index 0000000..449e79e
--- /dev/null
@@ -0,0 +1,158 @@
+/* *****************************************************************
+ *
+ * Copyright 2016 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************/
+#ifndef CA_ADAPTER_NET_TLS_H_
+#define CA_ADAPTER_NET_TLS_H_
+
+#include "caadapterutils.h"
+#include "cainterface.h"
+
+/**
+ * Currently TLS supported adapters(2) WIFI and ETHENET for linux platform.
+ */
+#define MAX_SUPPORTED_ADAPTERS 2
+
+typedef void (*CAPacketReceivedCallback)(const CASecureEndpoint_t *sep,
+                                         const void *data, uint32_t dataLength);
+
+typedef void (*CAPacketSendCallback)(CAEndpoint_t *endpoint,
+                                         const void *data, uint32_t dataLength);
+
+/**
+ * Select the cipher suite for dtls handshake
+ *
+ * @param[in] cipher    cipher suite
+ *                             0xC018 : TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256
+ *                             0xC0A8 : TLS_PSK_WITH_AES_128_CCM_8
+ *                             0xC0AE : TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8
+ *
+ * @retval  ::CA_STATUS_OK for success, otherwise some error value
+ */
+CAResult_t CAsetTlsCipherSuite(const uint32_t cipher);
+
+/**
+ * Used set send and recv callbacks for different adapters(WIFI,EtherNet).
+ *
+ * @param[in]  recvCallback    packet received callback.
+ * @param[in]  sendCallback    packet sent callback.
+ * @param[in]  type  type of adapter.
+ *
+ */
+void CAsetTlsAdapterCallbacks(CAPacketReceivedCallback recvCallback,
+                              CAPacketSendCallback sendCallback,
+                              CATransportAdapter_t type);
+
+/**
+ * Register callback to get TLS PSK credentials.
+ * @param[in]  credCallback    callback to get TLS PSK credentials.
+ */
+void CAsetTlsCredentialsCallback(CAGetDTLSPskCredentialsHandler credCallback);
+
+/**
+ * Close the TLS session
+ *
+ * @param[in] endpoint  information of network address
+ *
+ * @retval  ::CA_STATUS_OK for success, otherwise some error value
+ */
+CAResult_t CAcloseTlsConnection(const CAEndpoint_t *endpoint);
+
+/**
+ * initialize mbedTLS library and other necessary initialization.
+ *
+ * @return  0 on success otherwise a positive error value.
+ * @retval  ::CA_STATUS_OK  Successful.
+ * @retval  ::CA_MEMORY_ALLOC_FAILED  Memory allocation failed.
+ * @retval  ::CA_STATUS_FAILED Operation failed.
+ *
+ */
+CAResult_t CAinitTlsAdapter();
+
+/**
+ * de-inits mbedTLS library and free the allocated memory.
+ */
+void CAdeinitTlsAdapter();
+
+/**
+ * Performs TLS encryption of the CoAP PDU.
+ *
+ * If a DTLS session does not exist yet with the @dst,
+ * a TLS handshake will be started. In case where a new TLS handshake
+ * is started, pdu info is cached to be send when session setup is finished.
+ *
+ * @param[in]  endpoint  address to which data will be sent.
+ * @param[in]  data  length of data.
+ * @param[in]  dataLen  length of given data
+ *
+ * @return  0 on success otherwise a positive error value.
+ * @retval  ::CA_STATUS_OK  Successful.
+ * @retval  ::CA_STATUS_INVALID_PARAM  Invalid input arguments.
+ * @retval  ::CA_STATUS_FAILED Operation failed.
+ *
+ */
+
+CAResult_t CAencryptTls(const CAEndpoint_t *endpoint, void *data, uint32_t dataLen);
+
+/**
+ * Performs TLS decryption of the data.
+ *
+ * @param[in]  sep  address and flags for which data will be decrypted.
+ * @param[in]  data  length of data.
+ * @param[in]  dataLen  length of given data
+ *
+ * @return  0 on success otherwise a positive error value.
+ * @retval  ::CA_STATUS_OK  Successful.
+ * @retval  ::CA_STATUS_INVALID_PARAM  Invalid input arguments.
+ * @retval  ::CA_STATUS_FAILED Operation failed.
+ *
+ */
+CAResult_t CAdecryptTls(const CASecureEndpoint_t *sep, uint8_t *data, uint32_t dataLen);
+
+/**
+ * Initiate TLS handshake with selected cipher suite.
+ *
+ * @param[in] endpoint  information of network address
+ *
+ * @retval  ::CA_STATUS_OK for success, otherwise some error value
+ */
+CAResult_t CAinitiateTlsHandshake(const CAEndpoint_t *endpoint);
+
+/**
+ * Register callback to deliver the result of TLS handshake
+ * @param[in] tlsHandshakeCallback Callback to receive the result of TLS handshake.
+ */
+void CAsetTlsHandshakeCallback(CAErrorCallback tlsHandshakeCallback);
+
+/**
+ * Generate ownerPSK using the PKCS#12 derivation function
+ *
+ * @param[in,out] ownerPSK  Output buffer for owner PSK
+ * @param[in] ownerPSKSize  Byte length of the ownerPSK to be generated
+ * @param[in] deviceID  ID of new device(Resource Server)
+ * @param[in] deviceIDLen  Byte length of deviceID
+ *
+ * @retval  ::CA_STATUS_OK for success, otherwise some error value
+ */
+CAResult_t CAtlsGenerateOwnerPSK(const CAEndpoint_t *endpoint,
+                                 uint8_t* ownerPSK, const size_t ownerPSKSize,
+                                 const uint8_t* deviceID, const size_t deviceIDLen);
+
+#endif /* CA_ADAPTER_NET_TLS_H_ */
+
+
index 0236089..3b1d466 100644 (file)
@@ -213,3 +213,4 @@ typedef void (*CAErrorHandleCallback)(const CAEndpoint_t *endpoint,
 
 #endif  /* CA_ADAPTER_INTERFACE_H_ */
 
+
index e892e07..db832e5 100644 (file)
@@ -43,9 +43,8 @@ typedef struct
 {
     CASecureEndpoint_t sep;             /**< secure endpoint information */
     int fd;                             /**< file descriptor info */
-    void *recvData;                     /**< received data from remote device*/
-    size_t recvDataLen;                 /**< received data length */
-    size_t totalDataLen;                /**< total data length */
+    unsigned char* data;                /**< received data from remote device */
+    size_t len;                         /**< received data length */
 } CATCPSessionInfo_t;
 
 /**
index 486966d..cffb3e1 100644 (file)
@@ -51,6 +51,7 @@ if env.get('SECURED') == '1':
        env.SConscript(build_dir + 'extlibs/tinydtls/SConscript')
        env.SConscript(build_dir + 'extlibs/timer/SConscript')
        env.AppendUnique(CPPPATH = ['#extlibs/timer'])
+       env.AppendUnique(CPPPATH = [src_dir + '/resource/csdk/connectivity/inc/pkix'])
 
 env.AppendUnique(CA_SRC = [os.path.join(ca_path,
                                         'adapter_util/caadapterutils.c')])
@@ -70,6 +71,18 @@ if env.get('DTLS_WITH_X509') == '1':
        pkix_src = Glob('adapter_util/pkix/*.c');
        env.AppendUnique(CA_SRC = pkix_src)
 
+if ((secured == '1') and (with_tcp == True)):
+       env.AppendUnique(CPPDEFINES = ['__WITH_TLS__'])
+       tls_path = 'extlibs/mbedtls';
+       tls_headers_path = 'mbedtls/include';
+       if ca_os == 'tizen' and os.path.exists(root_dir + '/' + tls_path):
+               env.SConscript(os.path.join(root_dir, tls_path + '/SConscript'))
+               env.AppendUnique(CPPPATH = [os.path.join(root_dir, tls_path + '/' + tls_headers_path)])
+       else:
+               env.SConscript('#' + tls_path + '/SConscript')
+               env.AppendUnique(CPPPATH = ['#' + tls_path + '/' + tls_headers_path])
+               env.AppendUnique(CA_SRC = [os.path.join(ca_path, 'adapter_util/ca_adapter_net_tls.c')])
+
 ca_common_src = None
 
 if env.get('ROUTING') == 'GW':
diff --git a/resource/csdk/connectivity/src/adapter_util/ca_adapter_net_tls.c b/resource/csdk/connectivity/src/adapter_util/ca_adapter_net_tls.c
new file mode 100644 (file)
index 0000000..f4a568c
--- /dev/null
@@ -0,0 +1,1474 @@
+/******************************************************************
+ *
+ * Copyright 2016 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************/
+
+#define _GNU_SOURCE
+
+#include <stddef.h>
+#include "ca_adapter_net_tls.h"
+#include "cacommon.h"
+#include "caipinterface.h"
+#include "oic_malloc.h"
+#include "pkix/byte_array.h"
+#include "camutex.h"
+
+// headers required for mbed TLS
+#include "mbedtls/platform.h"
+#include "mbedtls/ssl.h"
+#include "mbedtls/entropy.h"
+#include "mbedtls/ctr_drbg.h"
+#include "mbedtls/pkcs12.h"
+#include "mbedtls/ssl_internal.h"
+
+#ifndef NDEBUG
+#include "mbedtls/debug.h"
+#include "mbedtls/version.h"
+#endif
+
+#ifdef __unix__
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#endif
+
+#include "pkix/byte_array.h"
+
+/**
+ * @def MBED_TLS_VERSION_LEN
+ * @brief mbedTLS version string length
+ */
+#define MBED_TLS_VERSION_LEN (16)
+/**
+ * @def SEED
+ * @brief Seed for initialization RNG
+ */
+#define SEED "IOTIVITY_RND"
+/**
+ * @def UUID_PREFIX
+ * @brief uuid prefix in certificate subject field
+ */
+#define UUID_PREFIX "uuid:"
+
+/**
+ * @def NET_TLS_TAG
+ * @brief Logging tag for module name
+ */
+#define NET_TLS_TAG "OIC_CA_NET_TLS"
+/**
+ * @def MBED_TLS_TAG
+ * @brief Logging tag for mbedTLS library
+ */
+#define MBED_TLS_TAG "OIC_MBED_TLS"
+/**
+ * @def MMBED_TLS_DEBUG_LEVEL
+ * @brief Logging level for mbedTLS library
+ */
+#define MBED_TLS_DEBUG_LEVEL (4) // Verbose
+
+/**
+ * @def TLS_MSG_BUF_LEN
+ * @brief Buffer size for TLS record. A single TLS record may be up to 16384 octets in length
+ */
+
+#define TLS_MSG_BUF_LEN (16384)
+/**
+ * @def PSK_LENGTH
+ * @brief PSK keys max length
+ */
+#define PSK_LENGTH (256/8)
+/**
+ * @def UUID_LENGTHPSK_LENGTH
+ * @brief Identity max length
+ */
+#define UUID_LENGTH (128/8)
+/**
+ * @def MASTER_SECRET_LEN
+ * @brief TLS master secret length
+ */
+#define MASTER_SECRET_LEN (48)
+
+#define TLS_CLOSE_NOTIFY(peer, ret)                                                                \
+do                                                                                                 \
+{                                                                                                  \
+    ret = mbedtls_ssl_close_notify(&peer->ssl);                                                    \
+} while (MBEDTLS_ERR_SSL_WANT_WRITE == ret)
+
+#define TLS_RET_HANDSHAKE_RES(peer)                                                                \
+if (g_tlsHandshakeCallback)                                                                        \
+{                                                                                                  \
+    CAErrorInfo_t errorInfo = {.result = CA_STATUS_FAILED};                                        \
+    g_tlsHandshakeCallback(&peer->sep.endpoint, &errorInfo);                                       \
+}
+
+#define TLS_CHECK_HANDSHAKE_FAIL(peer, ret, str, mutex, error)                                     \
+if (0 != ret && MBEDTLS_ERR_SSL_WANT_READ != ret &&  MBEDTLS_ERR_SSL_WANT_WRITE != ret)            \
+{                                                                                                  \
+    OIC_LOG_V(ERROR, NET_TLS_TAG, "%s: -0x%x", str, -ret);                                         \
+    TLS_CLOSE_NOTIFY(peer, ret);                                                                   \
+    TLS_RET_HANDSHAKE_RES(peer);                                                                   \
+    removePeerFromList(&peer->sep.endpoint);                                                       \
+    if (mutex)                                                                                     \
+    {                                                                                              \
+        ca_mutex_unlock(g_tlsContextMutex);                                                        \
+    }                                                                                              \
+    return error;                                                                                  \
+}
+
+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;
+
+typedef enum
+{
+    ADAPTER_CURVE_SECP256R1,
+    ADAPTER_CURVE_MAX
+} AdapterCurve_t;
+
+int tlsCipher[ADAPTER_CIPHER_MAX][2] =
+{
+    {MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA, 0},
+    {MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, 0},
+    {MBEDTLS_TLS_ECDH_ANON_WITH_AES_128_CBC_SHA256, 0},
+    {MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, 0}
+};
+
+mbedtls_ecp_group_id curve[ADAPTER_CURVE_MAX][2] =
+{
+    {MBEDTLS_ECP_DP_SECP256R1, 0}
+};
+
+//TODO add description
+static PkiInfo_t g_pkiInfo = {{NULL, 0}, {NULL, 0}, {NULL, 0}, {NULL, 0}};
+
+#ifndef NDEBUG
+/**
+ * Pass a message to the OIC logger.
+ *
+ * @param[in] ctx  opaque context for the callback
+ * @param[in] level  debug level
+ * @param[in] file  file name
+ * @param[in] line  line number
+ * @param[in] str  message
+ */
+static void debugTls(void *ctx, int level, const char *file, int line, const char *str)
+{
+    ((void) level);
+    ((void) file);
+    ((void) line);
+
+    OIC_LOG_V(DEBUG, MBED_TLS_TAG, "%s", str);
+    fflush((FILE *) ctx);
+}
+#endif
+
+/**
+ * structure to holds the information of cache message and address info.
+ */
+typedef ByteArray TlsCacheMessage_t;
+
+
+/**
+ * Data structure for holding the send and recv callbacks.
+ */
+typedef struct TlsCallBacks
+{
+    CAPacketReceivedCallback recvCallback;  /**< Callback used to send data to upper layer. */
+    CAPacketSendCallback sendCallback;      /**< Callback used to send data to socket layer. */
+} TlsCallbacks_t;
+
+/**
+ * Data structure for holding the mbedTLS interface related info.
+ */
+typedef struct TlsContext
+{
+    u_arraylist_t *peerList;         /**< peer list which holds the mapping between
+                                              peer id, it's n/w address and mbedTLS context. */
+    mbedtls_entropy_context entropy;
+    mbedtls_ctr_drbg_context rnd;
+    mbedtls_x509_crt ca;
+    mbedtls_x509_crt crt;
+    mbedtls_pk_context pkey;
+    mbedtls_ssl_config clientConf;
+    mbedtls_ssl_config serverConf;
+    AdapterCipher_t cipher;
+    TlsCallbacks_t adapterCallbacks[MAX_SUPPORTED_ADAPTERS];
+    mbedtls_x509_crl crl;
+
+} TlsContext_t;
+
+/**
+ * @var g_caTlsContext
+ * @brief global context which holds tls context and cache list information.
+ */
+static TlsContext_t * g_caTlsContext = NULL;
+
+/**
+ * @var g_getCredentialsCallback
+ * @brief callback to get TLS credentials (same as for DTLS)
+ */
+static CAGetDTLSPskCredentialsHandler g_getCredentialsCallback = NULL;
+
+/**
+ * @var g_getPkixInfoCallback
+ *
+ * @brief callback to get X.509-based Public Key Infrastructure
+ */
+static CAgetPkixInfoHandler g_getPkixInfoCallback = NULL;
+
+/**
+ * @var g_dtlsContextMutex
+ * @brief Mutex to synchronize access to g_caTlsContext.
+ */
+static ca_mutex g_tlsContextMutex = NULL;
+
+/**
+ * @var g_tlsHandshakeCallback
+ * @brief callback to deliver the TLS handshake result
+ */
+static CAErrorCallback g_tlsHandshakeCallback = NULL;
+
+/**
+ * Data structure for holding the data to be rceived.
+ */
+typedef struct TlsRecBuf
+{
+    uint8_t * buff;
+    size_t len;
+    size_t loaded;
+} TlsRecBuf_t;
+
+/**
+ * Data structure for holding the data related to endpoint
+ * and TLS session.
+ */
+typedef struct TlsEndPoint
+{
+    mbedtls_ssl_context ssl;
+    CASecureEndpoint_t sep;
+    u_arraylist_t * cacheList;
+    TlsRecBuf_t recBuf;
+    uint8_t master[MASTER_SECRET_LEN];
+} TlsEndPoint_t;
+
+void CAsetTlsCredentialsCallback(CAGetDTLSPskCredentialsHandler credCallback)
+{
+    // TODO Does this method needs protection of tlsContextMutex?
+    OIC_LOG_V(DEBUG, NET_TLS_TAG, "In %s", __func__);
+    g_getCredentialsCallback = credCallback;
+    OIC_LOG_V(DEBUG, NET_TLS_TAG, "Out %s", __func__);
+}
+
+void CAsetPkixInfoCallback(CAgetPkixInfoHandler infoCallback)
+{
+    OIC_LOG_V(DEBUG, NET_TLS_TAG, "In %s", __func__);
+    g_getPkixInfoCallback = infoCallback;
+    OIC_LOG_V(DEBUG, NET_TLS_TAG, "Out %s", __func__);
+}
+/**
+ * Write callback.
+ *
+ * @param[in]  tep    TLS endpoint
+ * @param[in]  data    message
+ * @param[in]  dataLen    message length
+ *
+ * @return  message length
+ */
+static int sendTls(void * tep, const unsigned char * data, size_t dataLen)
+{
+    OIC_LOG_V(DEBUG, NET_TLS_TAG, "In %s", __func__);
+    VERIFY_NON_NULL_RET(tep, NET_TLS_TAG, "secure endpoint is NULL", 0);
+    VERIFY_NON_NULL_RET(data, NET_TLS_TAG, "data is NULL", 0);
+    OIC_LOG_V(DEBUG, NET_TLS_TAG, "Data len: %zu", dataLen);
+
+    g_caTlsContext->adapterCallbacks[0].sendCallback(&(((TlsEndPoint_t * )tep)->sep.endpoint),
+            (const void *) data, (uint32_t) dataLen);
+    OIC_LOG_V(DEBUG, NET_TLS_TAG, "Out %s", __func__);
+    return dataLen;
+}
+/**
+ * Read callback.
+ *
+ * @param[in]  tep    TLS endpoint
+ * @param[in]  data    message
+ * @param[in]  dataLen    message length
+ *
+ * @return  read length
+ */
+static int recvTls(void * tep, unsigned char * data, size_t dataLen)
+{
+    OIC_LOG_V(DEBUG, NET_TLS_TAG, "In %s", __func__);
+    VERIFY_NON_NULL_RET(tep, NET_TLS_TAG, "endpoint is NULL", 0);
+    VERIFY_NON_NULL_RET(data, NET_TLS_TAG, "data is NULL", 0);
+
+    TlsRecBuf_t *recBuf = &((TlsEndPoint_t *)tep)->recBuf;
+    size_t retLen = (recBuf->len > recBuf->loaded ? recBuf->len - recBuf->loaded : 0);
+    retLen = (retLen < dataLen ? retLen : dataLen);
+
+    memcpy(data, recBuf->buff + recBuf->loaded, retLen);
+    recBuf->loaded += retLen;
+
+    OIC_LOG_BUFFER(DEBUG, NET_TLS_TAG, data, retLen);
+    OIC_LOG_V(DEBUG, NET_TLS_TAG, "Out %s", __func__);
+    return (int)retLen;
+}
+
+//TODO add description
+static int parseChain(mbedtls_x509_crt * crt, const unsigned char * buf, int buflen)
+{
+    VERIFY_NON_NULL_RET(crt, NET_TLS_TAG, "Param crt is NULL" , -1);
+    VERIFY_NON_NULL_RET(buf, NET_TLS_TAG, "Param buf is NULL" , -1);
+
+    int pos = 0;
+    int len = 0;
+    int ret = 0;
+    while (pos < buflen)
+    {
+        if (0x30 == buf[pos] && 0x82 == buf[pos + 1] && pos + 3 < buflen)
+        {
+            len = (((int) buf[pos+2]) << 8) | buf[pos+3];
+            if (pos + len < buflen)
+            {
+                ret = mbedtls_x509_crt_parse_der(crt, buf+pos, len+4);
+                if( 0 != ret)
+                {
+                    OIC_LOG_V(ERROR, NET_TLS_TAG, "mbedtls_x509_crt_parse returned -0x%x", -ret);
+                    return -1;
+                }
+            }
+            pos += len + 4;
+        }
+        else
+        {
+             OIC_LOG_V(ERROR, NET_TLS_TAG, "mbedtls_x509_crt_parse returned -0x%x", -ret);
+             return -1;
+        }
+    }
+    return 0;
+}
+//TODO add description
+static int loadX509()
+{
+    OIC_LOG_V(DEBUG, NET_TLS_TAG, "In %s", __func__);
+    VERIFY_NON_NULL_RET(g_getPkixInfoCallback, NET_TLS_TAG, "PKIX info callback is NULL", -1);
+
+    g_getPkixInfoCallback(&g_pkiInfo);
+
+    int ret = parseChain(&g_caTlsContext->ca, g_pkiInfo.ca.data, g_pkiInfo.ca.len);
+    if(0 != ret)
+    {
+        OIC_LOG(ERROR, NET_TLS_TAG, "CA chain parsing error");
+        OIC_LOG_V(DEBUG, NET_TLS_TAG, "Out %s", __func__);
+        return -1;
+    }
+    ret = parseChain(&g_caTlsContext->crt, g_pkiInfo.crt.data, g_pkiInfo.crt.len);
+    if(0 != ret)
+    {
+        OIC_LOG(ERROR, NET_TLS_TAG, "Own certificate chain parsing error");
+        OIC_LOG_V(DEBUG, NET_TLS_TAG, "Out %s", __func__);
+        return -1;
+    }
+
+    ret =  mbedtls_pk_parse_key(&g_caTlsContext->pkey, g_pkiInfo.key.data, g_pkiInfo.key.len,
+                                                                                           NULL, 0);
+    if(0 != ret)
+    {
+        OIC_LOG(ERROR, NET_TLS_TAG, "Key parsing error");
+        OIC_LOG_V(DEBUG, NET_TLS_TAG, "Out %s", __func__);
+        return -1;
+    }
+    ret = mbedtls_x509_crl_parse_der(&g_caTlsContext->crl, g_pkiInfo.crl.data, g_pkiInfo.crl.len);
+    if(0 != ret)
+    {
+        OIC_LOG(ERROR, NET_TLS_TAG, "CRL parsing error");
+        OIC_LOG_V(DEBUG, NET_TLS_TAG, "Out %s", __func__);
+        //TODO
+        //return -1;
+    }
+
+    mbedtls_ssl_conf_ca_chain(&g_caTlsContext->clientConf, &g_caTlsContext->ca, NULL);
+    mbedtls_ssl_conf_ca_chain(&g_caTlsContext->serverConf, &g_caTlsContext->ca, NULL);
+
+    ret = mbedtls_ssl_conf_own_cert(&g_caTlsContext->serverConf, &g_caTlsContext->crt,
+                                                                             &g_caTlsContext->pkey);
+    if(0 != ret)
+    {
+        OIC_LOG(ERROR, NET_TLS_TAG, "Certificate parsing error");
+        OIC_LOG_V(DEBUG, NET_TLS_TAG, "Out %s", __func__);
+        return -1;
+    }
+    ret = mbedtls_ssl_conf_own_cert( &g_caTlsContext->clientConf, &g_caTlsContext->crt,
+                                                                             &g_caTlsContext->pkey);
+    if(0 != ret)
+    {
+        OIC_LOG(ERROR, NET_TLS_TAG, "Certificate parsing error");
+        OIC_LOG_V(DEBUG, NET_TLS_TAG, "Out %s", __func__);
+        return -1;
+    }
+
+    OIC_LOG_V(DEBUG, NET_TLS_TAG, "Out %s", __func__);
+    return 0;
+}
+
+/*
+ * PSK callback.
+ *
+ * @param[in]  notUsed     opaque context
+ * @param[in]  ssl    mbedTLS context
+ * @param[in]  desc    identity
+ * @param[in]  descLen    identity length
+ *
+ * @return  0 on success any other return value will result in a denied PSK identity
+ */
+static int getTlsCredentialsCallback(void * notUsed, mbedtls_ssl_context * ssl,
+                                     const unsigned char * desc, size_t descLen)
+{
+    OIC_LOG_V(DEBUG, NET_TLS_TAG, "In %s", __func__);
+    VERIFY_NON_NULL_RET(g_getCredentialsCallback, NET_TLS_TAG, "Credential callback s NULL", -1);
+    VERIFY_NON_NULL_RET(ssl, NET_TLS_TAG, "ssl pointer is NULL", -1);
+    VERIFY_NON_NULL_RET(desc, NET_TLS_TAG, "desc pointer is NULL", -1);
+    if (descLen > CA_MAX_ENDPOINT_IDENTITY_LEN)
+    {
+        OIC_LOG(ERROR, NET_TLS_TAG, "desc too long!");
+        return -1;
+    }
+    (void) notUsed;
+    uint8_t keyBuf[PSK_LENGTH] = {0};
+
+    // Retrieve the credentials blob from security module
+    int ret = g_getCredentialsCallback(2, desc, descLen, keyBuf, PSK_LENGTH);
+    if (ret > 0)
+    {
+        memcpy(((TlsEndPoint_t *) ssl)->sep.identity.id, desc, descLen);
+        ((TlsEndPoint_t *) ssl)->sep.identity.id_length = descLen;
+
+        OIC_LOG_V(DEBUG, NET_TLS_TAG, "Out %s", __func__);
+        return(mbedtls_ssl_set_hs_psk(ssl, keyBuf, PSK_LENGTH));
+    }
+    OIC_LOG_V(DEBUG, NET_TLS_TAG, "Out %s", __func__);
+    return -1;
+}
+/**
+ * Gets session corresponding for endpoint.
+ *
+ * @param[in]  peer    remote address
+ *
+ * @return  TLS session or NULL
+ */
+static TlsEndPoint_t *getTlsPeer(const CAEndpoint_t *peer)
+{
+    uint32_t listIndex = 0;
+    uint32_t listLength = 0;
+    OIC_LOG_V(DEBUG, NET_TLS_TAG, "In %s", __func__);
+    VERIFY_NON_NULL_RET(peer, NET_TLS_TAG, "TLS peer is NULL", NULL);
+
+    TlsEndPoint_t *tep = NULL;
+    listLength = u_arraylist_length(g_caTlsContext->peerList);
+    for (listIndex = 0; listIndex < listLength; listIndex++)
+    {
+        tep = (TlsEndPoint_t *) u_arraylist_get(g_caTlsContext->peerList, listIndex);
+        if (NULL == tep)
+        {
+            continue;
+        }
+        OIC_LOG_V(DEBUG, NET_TLS_TAG, "Compare [%s] and [%s]", peer->addr, tep->sep.endpoint.addr);
+        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_TLS_TAG, "Out %s", __func__);
+            return tep;
+        }
+    }
+    OIC_LOG(DEBUG, NET_TLS_TAG, "Return NULL");
+    OIC_LOG_V(DEBUG, NET_TLS_TAG, "Out %s", __func__);
+    return NULL;
+}
+/**
+ * Deletes cached message.
+ *
+ * @param[in]  msg    message
+ */
+static void deleteTlsCacheMessage(TlsCacheMessage_t * msg)
+{
+    OIC_LOG_V(DEBUG, NET_TLS_TAG, "In %s", __func__);
+    VERIFY_NON_NULL_VOID(msg, NET_TLS_TAG, "msg");
+
+    OICFree(msg->data);
+    OICFree(msg);
+
+    OIC_LOG_V(DEBUG, NET_TLS_TAG, "Out %s", __func__);
+}
+/**
+ * Deletes cached message list.
+ *
+ * @param[in] cacheList  list of cached messages
+ */
+static void deleteCacheList(u_arraylist_t * cacheList)
+{
+    OIC_LOG_V(DEBUG, NET_TLS_TAG, "In %s", __func__);
+    VERIFY_NON_NULL_VOID(cacheList, NET_TLS_TAG, "cacheList");
+    uint32_t listIndex = 0;
+    uint32_t listLength = 0;
+
+    listLength = u_arraylist_length(cacheList);
+    for (listIndex = 0; listIndex < listLength; listIndex++)
+    {
+        TlsCacheMessage_t * msg = (TlsCacheMessage_t *) u_arraylist_get(cacheList, listIndex);
+        if (NULL != msg)
+        {
+            deleteTlsCacheMessage(msg);
+        }
+    }
+    u_arraylist_free(&cacheList);
+
+    OIC_LOG_V(DEBUG, NET_TLS_TAG, "Out %s", __func__);
+}
+/**
+ * Deletes endpoint with session.
+ *
+ * @param[in]  tep    endpoint with session info
+ */
+static void deleteTlsEndPoint(TlsEndPoint_t * tep)
+{
+    OIC_LOG_V(DEBUG, NET_TLS_TAG, "In %s", __func__);
+    VERIFY_NON_NULL_VOID(tep, NET_TLS_TAG, "tep");
+
+    mbedtls_ssl_free(&tep->ssl);
+    deleteCacheList(tep->cacheList);
+    OICFree(tep);
+    OIC_LOG_V(DEBUG, NET_TLS_TAG, "Out %s", __func__);
+}
+/**
+ * Removes endpoint session from list.
+ *
+ * @param[in]  endpoint    remote address
+ */
+static void removePeerFromList(CAEndpoint_t * endpoint)
+{
+    uint32_t listLength = u_arraylist_length(g_caTlsContext->peerList);
+    VERIFY_NON_NULL_VOID(endpoint, NET_TLS_TAG, "endpoint");
+    for (uint32_t listIndex = 0; listIndex < listLength; listIndex++)
+    {
+        TlsEndPoint_t * tep = (TlsEndPoint_t *)u_arraylist_get(g_caTlsContext->peerList,listIndex);
+        if (NULL == tep)
+        {
+            continue;
+        }
+        if(0 == strncmp(endpoint->addr, tep->sep.endpoint.addr, MAX_ADDR_STR_SIZE_CA)
+                && (endpoint->port == tep->sep.endpoint.port))
+        {
+            u_arraylist_remove(g_caTlsContext->peerList, listIndex);
+            deleteTlsEndPoint(tep);
+            return;
+        }
+    }
+}
+/**
+ * Deletes session list.
+ */
+static void deletePeerList()
+{
+    uint32_t listLength = u_arraylist_length(g_caTlsContext->peerList);
+    for (uint32_t listIndex = 0; listIndex < listLength; listIndex++)
+    {
+        TlsEndPoint_t * tep = (TlsEndPoint_t *)u_arraylist_get(g_caTlsContext->peerList,listIndex);
+        if (NULL == tep)
+        {
+            continue;
+        }
+        deleteTlsEndPoint(tep);
+    }
+    u_arraylist_free(&g_caTlsContext->peerList);
+}
+
+CAResult_t CAcloseTlsConnection(const CAEndpoint_t *endpoint)
+{
+    OIC_LOG_V(DEBUG, NET_TLS_TAG, "In %s", __func__);
+    VERIFY_NON_NULL_RET(endpoint, NET_TLS_TAG, "Param endpoint is NULL" , CA_STATUS_INVALID_PARAM);
+
+    ca_mutex_lock(g_tlsContextMutex);
+    if (NULL == g_caTlsContext)
+    {
+        OIC_LOG(ERROR, NET_TLS_TAG, "Context is NULL");
+        ca_mutex_unlock(g_tlsContextMutex);
+        return CA_STATUS_FAILED;
+    }
+    TlsEndPoint_t * tep = getTlsPeer(endpoint);
+    if (NULL == tep)
+    {
+        OIC_LOG(ERROR, NET_TLS_TAG, "Session does not exist");
+        ca_mutex_unlock(g_tlsContextMutex);
+        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);
+    ca_mutex_unlock(g_tlsContextMutex);
+
+    OIC_LOG_V(DEBUG, NET_TLS_TAG, "Out %s", __func__);
+    return CA_STATUS_OK;
+}
+/**
+ * Creates session for endpoint.
+ *
+ * @param[in]  endpoint    remote address
+ * @param[in]  config    mbedTLS configuration info
+ *
+ * @return  TLS endpoint or NULL
+ */
+static TlsEndPoint_t * newTlsEndPoint(const CAEndpoint_t * endpoint, mbedtls_ssl_config * config)
+{
+    TlsEndPoint_t * tep = NULL;
+    OIC_LOG_V(DEBUG, NET_TLS_TAG, "In %s", __func__);
+    VERIFY_NON_NULL_RET(endpoint, NET_TLS_TAG, "endpoint", NULL);
+    VERIFY_NON_NULL_RET(config, NET_TLS_TAG, "config", NULL);
+
+    tep = (TlsEndPoint_t *) OICCalloc(1, sizeof (TlsEndPoint_t));
+    if (NULL == tep)
+    {
+        OIC_LOG(ERROR, NET_TLS_TAG, "Malloc failed!");
+        return NULL;
+    }
+
+    tep->sep.endpoint = *endpoint;
+    tep->sep.endpoint.flags |= CA_SECURE;
+
+    if(0 != mbedtls_ssl_setup( &tep->ssl, config))
+    {
+        OIC_LOG(ERROR, NET_TLS_TAG, "Setup failed");
+        OICFree(tep);
+        OIC_LOG_V(DEBUG, NET_TLS_TAG, "Out %s", __func__);
+        return NULL;
+    }
+
+    mbedtls_ssl_set_bio(&tep->ssl, tep, sendTls, recvTls, NULL);
+
+    tep->cacheList = u_arraylist_create();
+    if (NULL == tep->cacheList)
+    {
+        OIC_LOG(ERROR, NET_TLS_TAG, "cacheList initialization failed!");
+        mbedtls_ssl_free(&tep->ssl);
+        OICFree(tep);
+        OIC_LOG_V(DEBUG, NET_TLS_TAG, "Out %s", __func__);
+        return NULL;
+    }
+    OIC_LOG_V(DEBUG, NET_TLS_TAG, "Out %s", __func__);
+    return tep;
+}
+/**
+ * Initializes PSK identity.
+ *
+ * @param[out]  config    client/server config to be updated
+ *
+ * @return  0 on success or -1 on error
+ */
+static int initPskIdentity(mbedtls_ssl_config * config)
+{
+    uint8_t idBuf[UUID_LENGTH] = {0};
+    VERIFY_NON_NULL_RET(config, NET_TLS_TAG, "Param config is NULL" , -1);
+
+    if (0 > g_getCredentialsCallback(CA_DTLS_PSK_IDENTITY, NULL, 0, idBuf, UUID_LENGTH))
+    {
+        OIC_LOG(ERROR, NET_TLS_TAG, "Identity not found");
+        return -1;
+    }
+    if (0 != mbedtls_ssl_conf_psk(config, idBuf, 0, idBuf, UUID_LENGTH))
+    {
+        OIC_LOG(ERROR, NET_TLS_TAG, "Identity initialization failed!");
+        return -1;
+    }
+    return 0;
+}
+/**
+ * Initiate TLS handshake with endpoint.
+ *
+ * @param[in]  endpoint    remote address
+ *
+ * @return  TLS endpoint or NULL
+ */
+static TlsEndPoint_t * initiateTlsHandshake(const CAEndpoint_t *endpoint)
+{
+    int ret = 0;
+    TlsEndPoint_t * tep = NULL;
+
+    OIC_LOG_V(DEBUG, NET_TLS_TAG, "In %s", __func__);
+    VERIFY_NON_NULL_RET(endpoint, NET_TLS_TAG, "Param endpoint is NULL" , NULL);
+
+    // Retrieve the credentials blob from security module
+    if (ADAPTER_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 == g_caTlsContext->cipher &&
+            0 != initPskIdentity(&g_caTlsContext->clientConf))
+    {
+        OIC_LOG(ERROR, NET_TLS_TAG, "Client PSK identity initialization failed!");
+        return NULL;
+    }
+
+    tep = newTlsEndPoint(endpoint, &g_caTlsContext->clientConf);
+    if (NULL == tep)
+    {
+        OIC_LOG(ERROR, NET_TLS_TAG, "Malloc failed!");
+        return NULL;
+    }
+
+    if (ADAPTER_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 == g_caTlsContext->cipher ||
+        ADAPTER_TLS_RSA_WITH_AES_256_CBC_SHA == g_caTlsContext->cipher)
+    {
+        ret = loadX509();
+        if (0 != ret)
+        {
+            OIC_LOG(ERROR, NET_TLS_TAG, "Failed to init X.509");
+            deleteTlsEndPoint(tep);
+            return NULL;
+        }
+    }
+
+    OIC_LOG_V(DEBUG, NET_TLS_TAG, "Add %s:%d", tep->sep.endpoint.addr, tep->sep.endpoint.port);
+    ret = u_arraylist_add(g_caTlsContext->peerList, (void *) tep);
+    if (!ret)
+    {
+        OIC_LOG(ERROR, NET_TLS_TAG, "u_arraylist_add failed!");
+        deleteTlsEndPoint(tep);
+        return NULL;
+    }
+
+    while (MBEDTLS_SSL_HANDSHAKE_OVER > tep->ssl.state)
+    {
+        ret = mbedtls_ssl_handshake_step(&tep->ssl);
+        if (MBEDTLS_ERR_SSL_CONN_EOF == ret)
+        {
+            break;
+        }
+        TLS_CHECK_HANDSHAKE_FAIL(tep, ret, "Handshake error", 0, NULL);
+    }
+    OIC_LOG_V(DEBUG, NET_TLS_TAG, "Out %s", __func__);
+    return tep;
+}
+
+void CAdeinitTlsAdapter()
+{
+    OIC_LOG_V(DEBUG, NET_TLS_TAG, "In %s", __func__);
+
+    VERIFY_NON_NULL_VOID(g_caTlsContext, NET_TLS_TAG, "context is NULL");
+    VERIFY_NON_NULL_VOID(g_tlsContextMutex, NET_TLS_TAG, "context mutex is NULL");
+
+    //Lock tlsContext mutex
+    ca_mutex_lock(g_tlsContextMutex);
+
+    // Clear all lists
+    deletePeerList();
+
+    // De-initialize mbedTLS
+    mbedtls_x509_crt_free(&g_caTlsContext->crt);
+    mbedtls_pk_free(&g_caTlsContext->pkey);
+    mbedtls_ssl_config_free(&g_caTlsContext->clientConf);
+    mbedtls_ssl_config_free(&g_caTlsContext->serverConf);
+    mbedtls_ctr_drbg_free(&g_caTlsContext->rnd);
+    mbedtls_entropy_free(&g_caTlsContext->entropy);
+
+    // De-initialize tls Context
+    OICFree(g_caTlsContext);
+    g_caTlsContext = NULL;
+
+    // Unlock tlsContext mutex and de-initialize it
+    ca_mutex_unlock(g_tlsContextMutex);
+    ca_mutex_free(g_tlsContextMutex);
+    g_tlsContextMutex = NULL;
+
+    OIC_LOG_V(DEBUG, NET_TLS_TAG, "Out %s ", __func__);
+}
+
+CAResult_t CAinitTlsAdapter()
+{
+    OIC_LOG_V(DEBUG, NET_TLS_TAG, "In %s", __func__);
+
+    // Initialize mutex for tlsContext
+    if (NULL == g_tlsContextMutex)
+    {
+        g_tlsContextMutex = ca_mutex_new();
+        VERIFY_NON_NULL_RET(g_tlsContextMutex, NET_TLS_TAG, "malloc failed",
+                            CA_MEMORY_ALLOC_FAILED);
+    }
+    else
+    {
+        OIC_LOG(ERROR, NET_TLS_TAG, "CAAdapterNettlsInit done already!");
+        return CA_STATUS_OK;
+    }
+
+    // Lock tlsContext mutex and create tlsContext
+    ca_mutex_lock(g_tlsContextMutex);
+    g_caTlsContext = (TlsContext_t *)OICCalloc(1, sizeof(TlsContext_t));
+
+    if (NULL == g_caTlsContext)
+    {
+        OIC_LOG(ERROR, NET_TLS_TAG, "Context malloc failed");
+        ca_mutex_unlock(g_tlsContextMutex);
+        ca_mutex_free(g_tlsContextMutex);
+        g_tlsContextMutex = NULL;
+        return CA_MEMORY_ALLOC_FAILED;
+    }
+
+    // Create peer list
+    g_caTlsContext->peerList = u_arraylist_create();
+
+    if(NULL == g_caTlsContext->peerList)
+    {
+        OIC_LOG(ERROR, NET_TLS_TAG, "peerList initialization failed!");
+        OICFree(g_caTlsContext);
+        g_caTlsContext = NULL;
+        ca_mutex_unlock(g_tlsContextMutex);
+        ca_mutex_free(g_tlsContextMutex);
+        g_tlsContextMutex = NULL;
+        return CA_STATUS_FAILED;
+    }
+
+    /* Initialize TLS library
+     */
+#ifndef NDEBUG
+    char version[MBED_TLS_VERSION_LEN];
+    mbedtls_version_get_string(version);
+    OIC_LOG_V(INFO, NET_TLS_TAG, "mbed TLS version: %s", version);
+#endif
+
+    /* Entropy settings
+     */
+    mbedtls_entropy_init(&g_caTlsContext->entropy);
+    mbedtls_ctr_drbg_init(&g_caTlsContext->rnd);
+
+#ifdef __unix__
+    unsigned char seed[sizeof(SEED)] = {0};
+    int urandomFd = -2;
+    urandomFd = open("/dev/urandom", O_RDONLY);
+    if(urandomFd == -1)
+    {
+        OIC_LOG(ERROR, NET_TLS_TAG, "Fails open /dev/urandom!");
+        ca_mutex_unlock(g_tlsContextMutex);
+        CAdeinitTlsAdapter();
+        return CA_STATUS_FAILED;
+    }
+    if(0 > read(urandomFd, seed, sizeof(seed)))
+    {
+        OIC_LOG(ERROR, NET_TLS_TAG, "Fails read from /dev/urandom!");
+        close(urandomFd);
+        ca_mutex_unlock(g_tlsContextMutex);
+        CAdeinitTlsAdapter();
+        return CA_STATUS_FAILED;
+    }
+    close(urandomFd);
+
+#else
+    unsigned char * seed = (unsigned char*) SEED;
+#endif
+    if(0 != mbedtls_ctr_drbg_seed(&g_caTlsContext->rnd, mbedtls_entropy_func,
+                                  &g_caTlsContext->entropy, seed, sizeof(SEED)))
+    {
+        OIC_LOG(ERROR, NET_TLS_TAG, "Seed initialization failed!");
+        ca_mutex_unlock(g_tlsContextMutex);
+        CAdeinitTlsAdapter();
+        return CA_STATUS_FAILED;
+    }
+    mbedtls_ctr_drbg_set_prediction_resistance(&g_caTlsContext->rnd, MBEDTLS_CTR_DRBG_PR_OFF);
+
+    /* Client SSL configuration
+     */
+    mbedtls_ssl_config_init(&g_caTlsContext->clientConf);
+    if (mbedtls_ssl_config_defaults(&g_caTlsContext->clientConf, MBEDTLS_SSL_IS_CLIENT,
+                                    MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT) != 0)
+    {
+        OIC_LOG(ERROR, NET_TLS_TAG, "Client config initialization failed!");
+        ca_mutex_unlock(g_tlsContextMutex);
+        CAdeinitTlsAdapter();
+        return CA_STATUS_FAILED;
+    }
+
+    OIC_LOG_V(DEBUG, NET_TLS_TAG, "Out %s", __func__);
+
+    mbedtls_ssl_conf_psk_cb(&g_caTlsContext->clientConf, getTlsCredentialsCallback, NULL);
+    mbedtls_ssl_conf_rng( &g_caTlsContext->clientConf, mbedtls_ctr_drbg_random,
+                          &g_caTlsContext->rnd);
+    mbedtls_ssl_conf_curves(&g_caTlsContext->clientConf, curve[ADAPTER_CURVE_SECP256R1]);
+    mbedtls_ssl_conf_min_version(&g_caTlsContext->clientConf, MBEDTLS_SSL_MAJOR_VERSION_3,
+                                 MBEDTLS_SSL_MINOR_VERSION_1);
+    mbedtls_ssl_conf_renegotiation(&g_caTlsContext->clientConf, MBEDTLS_SSL_RENEGOTIATION_DISABLED);
+
+    mbedtls_ssl_conf_authmode(&g_caTlsContext->clientConf, MBEDTLS_SSL_VERIFY_REQUIRED);
+#ifndef NDEBUG
+    mbedtls_ssl_conf_dbg( &g_caTlsContext->clientConf, debugTls, NULL);
+#endif
+
+    /* Server SSL configuration
+     */
+    mbedtls_ssl_config_init(&g_caTlsContext->serverConf);
+    if (mbedtls_ssl_config_defaults(&g_caTlsContext->serverConf, MBEDTLS_SSL_IS_SERVER,
+                                    MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT) != 0)
+    {
+        OIC_LOG(ERROR, NET_TLS_TAG, "Server config initialization failed!");
+        ca_mutex_unlock(g_tlsContextMutex);
+        CAdeinitTlsAdapter();
+        return CA_STATUS_FAILED;
+    }
+
+    mbedtls_ssl_conf_psk_cb(&g_caTlsContext->serverConf, getTlsCredentialsCallback, NULL);
+    mbedtls_ssl_conf_rng( &g_caTlsContext->serverConf, mbedtls_ctr_drbg_random,
+                          &g_caTlsContext->rnd);
+    mbedtls_ssl_conf_curves(&g_caTlsContext->serverConf, curve[ADAPTER_CURVE_SECP256R1]);
+    mbedtls_ssl_conf_min_version(&g_caTlsContext->serverConf, MBEDTLS_SSL_MAJOR_VERSION_3,
+                                 MBEDTLS_SSL_MINOR_VERSION_1);
+    mbedtls_ssl_conf_renegotiation(&g_caTlsContext->serverConf, MBEDTLS_SSL_RENEGOTIATION_DISABLED);
+    mbedtls_ssl_conf_authmode(&g_caTlsContext->serverConf, MBEDTLS_SSL_VERIFY_REQUIRED);
+
+#ifndef NDEBUG
+    mbedtls_ssl_conf_dbg( &g_caTlsContext->serverConf, debugTls, NULL);
+    mbedtls_debug_set_threshold(MBED_TLS_DEBUG_LEVEL);
+#endif
+
+    // set default cipher to PSK
+    CAsetTlsCipherSuite(MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256);
+
+    // init X.509
+    mbedtls_x509_crt_init(&g_caTlsContext->ca);
+    mbedtls_x509_crt_init(&g_caTlsContext->crt);
+    mbedtls_pk_init(&g_caTlsContext->pkey);
+    mbedtls_x509_crl_init(&g_caTlsContext->crl);
+
+    ca_mutex_unlock(g_tlsContextMutex);
+
+    OIC_LOG_V(DEBUG, NET_TLS_TAG, "Out %s", __func__);
+    return CA_STATUS_OK;
+}
+/**
+ * Creates cache message structure and fills with data.
+ *
+ * @param[in]  data    data array
+ * @param[in]  dataLen    data array length
+ *
+ * @return  message or NULL
+ */
+TlsCacheMessage_t *  newTlsCacheMessage(uint8_t * data, size_t dataLen)
+{
+    OIC_LOG_V(DEBUG, NET_TLS_TAG, "In %s", __func__);
+    VERIFY_NON_NULL_RET(data, NET_TLS_TAG, "Param data is NULL" , NULL);
+    if (0 == dataLen)
+    {
+        OIC_LOG(ERROR, NET_TLS_TAG, "dataLen is equal to zero");
+        OIC_LOG_V(DEBUG, NET_TLS_TAG, "Out %s", __func__);
+        return NULL;
+    }
+    TlsCacheMessage_t * message = (TlsCacheMessage_t *) OICCalloc(1, sizeof(TlsCacheMessage_t));
+    if (NULL == message)
+    {
+        OIC_LOG(ERROR, NET_TLS_TAG, "calloc failed!");
+        OIC_LOG_V(DEBUG, NET_TLS_TAG, "Out %s", __func__);
+        return NULL;
+    }
+
+    message->data = (uint8_t *)OICCalloc(dataLen, sizeof(uint8_t));
+    if (NULL == message->data)
+    {
+        OIC_LOG(ERROR, NET_TLS_TAG, "calloc failed!");
+        OICFree(message);
+        OIC_LOG_V(DEBUG, NET_TLS_TAG, "Out %s", __func__);
+        return NULL;
+    }
+    memcpy(message->data, data, dataLen);
+    message->len = dataLen;
+    OIC_LOG_V(DEBUG, NET_TLS_TAG, "Out %s", __func__);
+    return message;
+}
+
+/* Send data via TLS connection.
+ */
+CAResult_t CAencryptTls(const CAEndpoint_t *endpoint,
+                        void *data, uint32_t dataLen)
+{
+    int ret = 0;
+
+    OIC_LOG_V(DEBUG, NET_TLS_TAG, "In %s ", __func__);
+
+    VERIFY_NON_NULL_RET(endpoint, NET_TLS_TAG,"Remote address is NULL", CA_STATUS_INVALID_PARAM);
+    VERIFY_NON_NULL_RET(data, NET_TLS_TAG, "Data is NULL", CA_STATUS_INVALID_PARAM);
+
+    if (0 == dataLen)
+    {
+        OIC_LOG_V(ERROR, NET_TLS_TAG, "dataLen is zero [%d]", dataLen);
+        return CA_STATUS_FAILED;
+    }
+
+    OIC_LOG_V(DEBUG, NET_TLS_TAG, "Data to be encrypted dataLen [%d]", dataLen);
+
+    ca_mutex_lock(g_tlsContextMutex);
+    if(NULL == g_caTlsContext)
+    {
+        OIC_LOG(ERROR, NET_TLS_TAG, "Context is NULL");
+        ca_mutex_unlock(g_tlsContextMutex);
+        return CA_STATUS_FAILED;
+    }
+
+    TlsEndPoint_t * tep = getTlsPeer(endpoint);
+    if (NULL == tep)
+    {
+        tep = initiateTlsHandshake(endpoint);
+    }
+    if (NULL == tep)
+    {
+        OIC_LOG(ERROR, NET_TLS_TAG, "TLS handshake failed");
+        ca_mutex_unlock(g_tlsContextMutex);
+        return CA_STATUS_FAILED;
+    }
+
+    if (MBEDTLS_SSL_HANDSHAKE_OVER == tep->ssl.state)
+    {
+        ret = mbedtls_ssl_write(&tep->ssl, (unsigned char *) data, dataLen);
+
+        if(ret < 0)
+        {
+            OIC_LOG_V(ERROR, NET_TLS_TAG, "mbedTLS write returned %d", ret);
+            if (g_tlsHandshakeCallback)
+            {
+                CAErrorInfo_t errorInfo = {.result = CA_STATUS_FAILED};
+                g_tlsHandshakeCallback(&tep->sep.endpoint, &errorInfo);
+            }
+            removePeerFromList(&tep->sep.endpoint);
+            ca_mutex_unlock(g_tlsContextMutex);
+            return CA_STATUS_FAILED;
+        }
+    }
+    else
+    {
+        TlsCacheMessage_t * msg = newTlsCacheMessage(data, dataLen);
+        if (NULL == msg || !u_arraylist_add(tep->cacheList, (void *) msg))
+        {
+            OIC_LOG(ERROR, NET_TLS_TAG, "u_arraylist_add failed!");
+            ca_mutex_unlock(g_tlsContextMutex);
+            return CA_STATUS_FAILED;
+        }
+    }
+
+    ca_mutex_unlock(g_tlsContextMutex);
+
+    OIC_LOG_V(DEBUG, NET_TLS_TAG, "Out %s", __func__);
+    return CA_STATUS_OK;
+}
+/**
+ * Sends cached messages via TLS connection.
+ *
+ * @param[in]  tep    remote address with session info
+ */
+static void sendCacheMessages(TlsEndPoint_t * tep)
+{
+    OIC_LOG_V(DEBUG, NET_TLS_TAG, "In %s", __func__);
+    VERIFY_NON_NULL_VOID(tep, NET_TLS_TAG, "Param tep is NULL");
+
+    uint32_t listIndex = 0;
+    uint32_t listLength = 0;
+    listLength = u_arraylist_length(tep->cacheList);
+    for (listIndex = 0; listIndex < listLength;)
+    {
+        int ret = 0;
+        TlsCacheMessage_t * msg = (TlsCacheMessage_t *) u_arraylist_get(tep->cacheList, listIndex);
+        if (NULL != msg && NULL != msg->data && 0 != msg->len)
+        {
+            do
+            {
+                ret = mbedtls_ssl_write(&tep->ssl, (unsigned char *) msg->data, msg->len);
+            }
+            while(MBEDTLS_ERR_SSL_WANT_WRITE == ret);
+
+            if(ret < 0)
+            {
+                OIC_LOG_V(ERROR, NET_TLS_TAG,"mbedTLS write returned %d", ret );
+            }
+            if (u_arraylist_remove(tep->cacheList, listIndex))
+            {
+                deleteTlsCacheMessage(msg);
+                // Reduce list length by 1 as we removed one element.
+                listLength--;
+            }
+            else
+            {
+                OIC_LOG(ERROR, NET_TLS_TAG, "u_arraylist_remove failed.");
+                break;
+            }
+        }
+        else
+        {
+            // Move to the next element
+            ++listIndex;
+        }
+    }
+    OIC_LOG_V(DEBUG, NET_TLS_TAG, "Out %s", __func__);
+}
+
+void CAsetTlsHandshakeCallback(CAErrorCallback tlsHandshakeCallback)
+{
+    OIC_LOG_V(DEBUG, NET_TLS_TAG, "In %s", __func__);
+    g_tlsHandshakeCallback = tlsHandshakeCallback;
+    OIC_LOG_V(DEBUG, NET_TLS_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_TLS_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_TLS_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_TLS_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 CAdecryptTls(const CASecureEndpoint_t *sep, uint8_t *data, uint32_t dataLen)
+{
+    int ret = 0;
+    OIC_LOG_V(DEBUG, NET_TLS_TAG, "In %s", __func__);
+    VERIFY_NON_NULL_RET(sep, NET_TLS_TAG, "endpoint is NULL" , CA_STATUS_INVALID_PARAM);
+    VERIFY_NON_NULL_RET(data, NET_TLS_TAG, "Param data is NULL" , CA_STATUS_INVALID_PARAM);
+
+    ca_mutex_lock(g_tlsContextMutex);
+    if (NULL == g_caTlsContext)
+    {
+        OIC_LOG(ERROR, NET_TLS_TAG, "Context is NULL");
+        ca_mutex_unlock(g_tlsContextMutex);
+        return CA_STATUS_FAILED;
+    }
+
+    if (ADAPTER_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 == g_caTlsContext->cipher &&
+            0 != initPskIdentity(&g_caTlsContext->serverConf))
+    {
+        ca_mutex_unlock(g_tlsContextMutex);
+        return CA_STATUS_FAILED;
+    }
+
+    TlsEndPoint_t * peer = getTlsPeer(&sep->endpoint);
+    if (NULL == peer)
+    {
+        peer = newTlsEndPoint(&sep->endpoint, &g_caTlsContext->serverConf);
+        if (NULL == peer)
+        {
+            OIC_LOG(ERROR, NET_TLS_TAG, "Malloc failed!");
+            ca_mutex_unlock(g_tlsContextMutex);
+            return CA_STATUS_FAILED;
+        }
+
+        if (ADAPTER_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 == g_caTlsContext->cipher ||
+            ADAPTER_TLS_RSA_WITH_AES_256_CBC_SHA == g_caTlsContext->cipher)
+        {
+            ret = loadX509();
+            if (0 != ret)
+            {
+                OIC_LOG(ERROR, NET_TLS_TAG, "Failed to init X.509");
+                deleteTlsEndPoint(peer);
+                ca_mutex_unlock(g_tlsContextMutex);
+                return CA_STATUS_FAILED;
+            }
+        }
+
+        ret = u_arraylist_add(g_caTlsContext->peerList, (void *) peer);
+        if (!ret)
+        {
+            OIC_LOG(ERROR, NET_TLS_TAG, "u_arraylist_add failed!");
+            OICFree(peer);
+            ca_mutex_unlock(g_tlsContextMutex);
+            return CA_STATUS_FAILED;
+        }
+    }
+    OIC_LOG_BUFFER(DEBUG, NET_TLS_TAG, data, dataLen);
+    peer->recBuf.buff = data;
+    peer->recBuf.len = dataLen;
+    peer->recBuf.loaded = 0;
+
+    OIC_LOG(DEBUG, NET_TLS_TAG, "Call mbedTLS handshake steps");
+
+    while (MBEDTLS_SSL_HANDSHAKE_OVER > peer->ssl.state)
+    {
+        ret = mbedtls_ssl_handshake_step(&peer->ssl);
+        if (MBEDTLS_ERR_SSL_CONN_EOF == ret)
+        {
+            break;
+        }
+        TLS_CHECK_HANDSHAKE_FAIL(peer, ret, "Handshake error", 1, CA_STATUS_FAILED);
+        if (MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC == peer->ssl.state)
+        {
+            memcpy(peer->master, peer->ssl.session_negotiate->master, sizeof(peer->master));
+        }
+
+        if (MBEDTLS_SSL_HANDSHAKE_OVER == peer->ssl.state)
+        {
+            if (MBEDTLS_SSL_IS_CLIENT == peer->ssl.conf->endpoint)
+            {
+                sendCacheMessages(peer);
+                if (g_tlsHandshakeCallback)
+                {
+                    CAErrorInfo_t errorInfo = {.result = CA_STATUS_OK};
+                    g_tlsHandshakeCallback(&peer->sep.endpoint, &errorInfo);
+                }
+            }
+            else
+            {
+                if (ADAPTER_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 == g_caTlsContext->cipher)
+                {
+                    char uuid[UUID_LENGTH * 2 + 5] = {0};
+                    void * uuidPos = NULL;
+                    const mbedtls_x509_crt * peerCert = mbedtls_ssl_get_peer_cert(&peer->ssl);
+                    ret = (NULL == peerCert ? -1 : 0);
+                    TLS_CHECK_HANDSHAKE_FAIL(peer, ret, "Failed to retrieve subject",
+                                                                               1, CA_STATUS_FAILED);
+                    ret = mbedtls_ssl_get_verify_result(&peer->ssl);
+                    TLS_CHECK_HANDSHAKE_FAIL(peer, ret, "Failed to retrieve subject",
+                                                                               1, CA_STATUS_FAILED);
+                    uuidPos = memmem((void *) peerCert->subject_raw.p, peerCert->subject_raw.len,
+                                                     (void *) UUID_PREFIX, sizeof(UUID_PREFIX) - 1);
+
+                    ret = (NULL == uuidPos ? -1 : 0);
+                    TLS_CHECK_HANDSHAKE_FAIL(peer, ret, "Failed to retrieve subject",
+                                                                               1, CA_STATUS_FAILED);
+
+                    memcpy(uuid, uuidPos + sizeof(UUID_PREFIX) - 1, UUID_LENGTH * 2 + 4);
+                    ret = ConvertStrToUuid(uuid, &peer->sep.identity);
+                    TLS_CHECK_HANDSHAKE_FAIL(peer, ret, "Failed to convert subject",
+                                                                               1, CA_STATUS_FAILED);
+                }
+            }
+            ca_mutex_unlock(g_tlsContextMutex);
+            OIC_LOG_V(DEBUG, NET_TLS_TAG, "Out %s", __func__);
+            return CA_STATUS_OK;
+        }
+    }
+
+    if (MBEDTLS_SSL_HANDSHAKE_OVER == peer->ssl.state)
+    {
+        uint8_t decryptBuffer[TLS_MSG_BUF_LEN] = {0};
+        do
+        {
+            ret = mbedtls_ssl_read(&peer->ssl, decryptBuffer, TLS_MSG_BUF_LEN);
+        } while (MBEDTLS_ERR_SSL_WANT_READ == ret);
+        if (MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY == ret)
+        {
+            OIC_LOG(INFO, NET_TLS_TAG, "Connection was closed gracefully");
+            removePeerFromList(&peer->sep.endpoint);
+            ca_mutex_unlock(g_tlsContextMutex);
+            return CA_STATUS_OK;
+        }
+
+        if (0 >= ret)
+        {
+            OIC_LOG_V(ERROR, NET_TLS_TAG, "mbedtls_ssl_read returned -0x%x", -ret);
+            if (g_tlsHandshakeCallback)
+            {
+                CAErrorInfo_t errorInfo = {.result = CA_STATUS_FAILED};
+                g_tlsHandshakeCallback(&peer->sep.endpoint, &errorInfo);
+            }
+            removePeerFromList(&peer->sep.endpoint);
+            ca_mutex_unlock(g_tlsContextMutex);
+            return CA_STATUS_FAILED;
+        }
+
+        g_caTlsContext->adapterCallbacks[0].recvCallback(&peer->sep, decryptBuffer, ret);
+    }
+
+    ca_mutex_unlock(g_tlsContextMutex);
+    OIC_LOG_V(DEBUG, NET_TLS_TAG, "Out %s", __func__);
+    return CA_STATUS_OK;
+}
+
+void CAsetTlsAdapterCallbacks(CAPacketReceivedCallback recvCallback,
+                              CAPacketSendCallback sendCallback,
+                              CATransportAdapter_t type)
+{
+    OIC_LOG_V(DEBUG, NET_TLS_TAG, "In %s", __func__);
+    VERIFY_NON_NULL_VOID(sendCallback, NET_TLS_TAG, "sendCallback is NULL");
+    VERIFY_NON_NULL_VOID(recvCallback, NET_TLS_TAG, "recvCallback is NULL");
+    ca_mutex_lock(g_tlsContextMutex);
+    if (NULL == g_caTlsContext)
+    {
+        OIC_LOG(ERROR, NET_TLS_TAG, "Context is NULL");
+        ca_mutex_unlock(g_tlsContextMutex);
+        return;
+    }
+
+    if (MAX_SUPPORTED_ADAPTERS > type)
+    {
+        // TODO: change the zeros to better values.
+        g_caTlsContext->adapterCallbacks[0].recvCallback = recvCallback;
+        g_caTlsContext->adapterCallbacks[0].sendCallback = sendCallback;
+    }
+
+    ca_mutex_unlock(g_tlsContextMutex);
+    OIC_LOG_V(DEBUG, NET_TLS_TAG, "Out %s", __func__);
+}
+
+CAResult_t CAsetTlsCipherSuite(const uint32_t cipher)
+{
+    OIC_LOG_V(DEBUG, NET_TLS_TAG, "In %s", __func__);
+    switch(cipher)
+    {
+        case MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA:
+        {
+            mbedtls_ssl_conf_ciphersuites(&g_caTlsContext->clientConf,
+                                         tlsCipher[ADAPTER_TLS_RSA_WITH_AES_256_CBC_SHA]);
+            mbedtls_ssl_conf_ciphersuites(&g_caTlsContext->serverConf,
+                                         tlsCipher[ADAPTER_TLS_RSA_WITH_AES_256_CBC_SHA]);
+            g_caTlsContext->cipher = ADAPTER_TLS_RSA_WITH_AES_256_CBC_SHA;
+            break;
+        }
+        case MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8:
+        {
+            mbedtls_ssl_conf_ciphersuites(&g_caTlsContext->clientConf,
+                                         tlsCipher[ADAPTER_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8]);
+            mbedtls_ssl_conf_ciphersuites(&g_caTlsContext->serverConf,
+                                         tlsCipher[ADAPTER_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8]);
+            g_caTlsContext->cipher = ADAPTER_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8;
+            break;
+        }
+        case MBEDTLS_TLS_ECDH_ANON_WITH_AES_128_CBC_SHA256:
+        {
+            mbedtls_ssl_conf_ciphersuites(&g_caTlsContext->clientConf,
+                                         tlsCipher[ADAPTER_TLS_ECDH_ANON_WITH_AES_128_CBC_SHA_256]);
+            mbedtls_ssl_conf_ciphersuites(&g_caTlsContext->serverConf,
+                                         tlsCipher[ADAPTER_TLS_ECDH_ANON_WITH_AES_128_CBC_SHA_256]);
+            g_caTlsContext->cipher = ADAPTER_TLS_ECDH_ANON_WITH_AES_128_CBC_SHA_256;
+            break;
+        }
+        case MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256:
+        {
+            mbedtls_ssl_conf_ciphersuites(&g_caTlsContext->clientConf,
+                                          tlsCipher[ADAPTER_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256]);
+            mbedtls_ssl_conf_ciphersuites(&g_caTlsContext->serverConf,
+                                          tlsCipher[ADAPTER_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256]);
+            g_caTlsContext->cipher = ADAPTER_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256;
+            break;
+        }
+        default:
+        {
+            OIC_LOG(ERROR, NET_TLS_TAG, "Unknown cipher");
+            return CA_STATUS_FAILED;
+        }
+    }
+    OIC_LOG_V(DEBUG, NET_TLS_TAG, "Selected cipher: 0x%x", cipher);
+    OIC_LOG_V(DEBUG, NET_TLS_TAG, "Out %s", __func__);
+    return CA_STATUS_OK;
+}
+
+CAResult_t CAinitiateTlsHandshake(const CAEndpoint_t *endpoint)
+{
+    CAResult_t res = CA_STATUS_OK;
+    OIC_LOG_V(DEBUG, NET_TLS_TAG, "In %s", __func__);
+    VERIFY_NON_NULL_RET(endpoint, NET_TLS_TAG, "Param endpoint is NULL" , CA_STATUS_INVALID_PARAM);
+    ca_mutex_lock(g_tlsContextMutex);
+    if (NULL == initiateTlsHandshake(endpoint))
+    {
+        OIC_LOG(ERROR, NET_TLS_TAG, "TLS handshake failed");
+        res = CA_STATUS_FAILED;
+    }
+    ca_mutex_unlock(g_tlsContextMutex);
+    OIC_LOG_V(DEBUG, NET_TLS_TAG, "Out %s", __func__);
+    return res;
+}
+
+CAResult_t CAtlsGenerateOwnerPSK(const CAEndpoint_t *endpoint,
+                                 uint8_t* ownerPSK, const size_t ownerPSKSize,
+                                 const uint8_t* deviceID, const size_t deviceIDLen)
+{
+    OIC_LOG_V(DEBUG, NET_TLS_TAG, "In %s", __func__);
+
+    VERIFY_NON_NULL_RET(ownerPSK, NET_TLS_TAG, "ownerPSK is NULL", CA_STATUS_INVALID_PARAM);
+    VERIFY_NON_NULL_RET(deviceID, NET_TLS_TAG, "rsrcID is NULL", CA_STATUS_INVALID_PARAM);
+
+    ca_mutex_lock(g_tlsContextMutex);
+    if (NULL == g_caTlsContext)
+    {
+        OIC_LOG(ERROR, NET_TLS_TAG, "Context is NULL");
+        ca_mutex_unlock(g_tlsContextMutex);
+        OIC_LOG_V(DEBUG, NET_TLS_TAG, "Out %s", __func__);
+        return CA_STATUS_FAILED;
+    }
+    TlsEndPoint_t * tep = getTlsPeer(endpoint);
+    if (NULL == tep)
+    {
+        OIC_LOG(ERROR, NET_TLS_TAG, "Session does not exist");
+        ca_mutex_unlock(g_tlsContextMutex);
+        return CA_STATUS_FAILED;
+    }
+
+    if (0 != mbedtls_pkcs12_derivation(ownerPSK, ownerPSKSize,
+                                       tep->master, sizeof(tep->master),
+                                       deviceID, deviceIDLen,
+                                       MBEDTLS_MD_SHA1, MBEDTLS_PKCS12_DERIVE_KEY, 1))
+    {
+        OIC_LOG(ERROR, NET_TLS_TAG, "Failed to generate key");
+        ca_mutex_unlock(g_tlsContextMutex);
+        OIC_LOG_V(DEBUG, NET_TLS_TAG, "Out %s", __func__);
+        return CA_STATUS_FAILED;
+    }
+    OIC_LOG_V(DEBUG, NET_TLS_TAG, "PSK: ");
+    OIC_LOG_BUFFER(DEBUG, NET_TLS_TAG, tep->master, sizeof(tep->master));
+    ca_mutex_unlock(g_tlsContextMutex);
+
+    OIC_LOG_V(DEBUG, NET_TLS_TAG, "Out %s", __func__);
+    return CA_STATUS_OK;
+}
index f5ddd6f..f333b59 100644 (file)
@@ -37,6 +37,9 @@
 
 #ifdef TCP_ADAPTER
 #include "catcpadapter.h"
+#ifdef __WITH_TLS__
+#include "ca_adapter_net_tls.h"
+#endif
 #endif
 
 CAGlobals_t caglobals = { .clientFlags = 0,
@@ -59,6 +62,12 @@ extern void CADTLSSetX509CredentialsCallback(CAGetDTLSX509CredentialsHandler cre
 extern void CADTLSSetCrlCallback(CAGetDTLSCrlHandler crlCallback);
 #endif
 
+#ifdef __WITH_TLS__
+extern void CAsetPkixInfoCallback(CAgetPkixInfoHandler infCallback);
+extern void CAsetTlsCredentialsCallback(CAGetDTLSPskCredentialsHandler credCallback);
+#endif
+
+
 CAResult_t CAInitialize()
 {
     OIC_LOG_V(DEBUG, TAG, "IoTivity version is v%s", IOTIVITY_VERSION);
@@ -174,6 +183,56 @@ CAResult_t CARegisterDTLSCredentialsHandler(CAGetDTLSPskCredentialsHandler GetDT
     return CA_STATUS_OK;
 }
 #endif //__WITH_DTLS__
+#ifdef __WITH_TLS__
+CAResult_t CAregisterTlsHandshakeCallback(CAErrorCallback tlsHandshakeCallback)
+{
+    OIC_LOG(DEBUG, TAG, "CARegisterTlsHandshakeCallback");
+
+    if(!g_isInitialized)
+    {
+        return CA_STATUS_NOT_INITIALIZED;
+    }
+
+    CAsetTlsHandshakeCallback(tlsHandshakeCallback);
+    return CA_STATUS_OK;
+}
+
+CAResult_t CAregisterTlsCredentialsHandler(CAGetDTLSPskCredentialsHandler getTlsCredentialsHandler)
+{
+    OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
+
+    if (!g_isInitialized)
+    {
+        return CA_STATUS_NOT_INITIALIZED;
+    }
+    CAsetTlsCredentialsCallback(getTlsCredentialsHandler);
+    OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
+    return CA_STATUS_OK;
+}
+
+void GetPkixInfo(PkiInfo_t * inf)
+{
+    OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
+    GetDerOwnCert(&inf->crt);
+    GetDerKey(&inf->key);
+    GetDerCaCert(&inf->ca);
+    GetDerCrl(&inf->crl);
+    OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
+}
+
+CAResult_t CAregisterPkixInfoHandler(CAgetPkixInfoHandler getPkixInfoHandler)
+{
+    OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
+
+    if (!g_isInitialized)
+    {
+        return CA_STATUS_NOT_INITIALIZED;
+    }
+    CAsetPkixInfoCallback(getPkixInfoHandler);
+    OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
+    return CA_STATUS_OK;
+}
+#endif
 
 #ifdef __WITH_X509__
 CAResult_t CARegisterDTLSX509CredentialsHandler(CAGetDTLSX509CredentialsHandler GetDTLSX509CredentialsHandler)
@@ -468,19 +527,48 @@ CAResult_t CAHandleRequestResponse()
     return CA_STATUS_OK;
 }
 
-#ifdef __WITH_DTLS__
-CAResult_t CASelectCipherSuite(const uint16_t cipher)
+#if defined (__WITH_DTLS__) || defined(__WITH_TLS__)
+CAResult_t CASelectCipherSuite(const uint16_t cipher, CATransportAdapter_t adapter)
 {
     OIC_LOG_V(DEBUG, TAG, "CASelectCipherSuite");
-
-    return CADtlsSelectCipherSuite(cipher);
+    if(CA_ADAPTER_IP == adapter)
+    {
+        if (CA_STATUS_OK != CADtlsSelectCipherSuite(cipher))
+        {
+            return CA_STATUS_FAILED;
+        }
+    }
+#ifdef __WITH_TLS__
+    else if(CA_ADAPTER_TCP == adapter)
+    {
+        if (CA_STATUS_OK != CAsetTlsCipherSuite(cipher))
+        {
+            return CA_STATUS_FAILED;
+        }
+    }
+#endif
+    return CA_STATUS_OK;
 }
 
 CAResult_t CAEnableAnonECDHCipherSuite(const bool enable)
 {
     OIC_LOG_V(DEBUG, TAG, "CAEnableAnonECDHCipherSuite");
 
-    return CADtlsEnableAnonECDHCipherSuite(enable);
+#ifdef __WITH_DTLS__
+    if (CA_STATUS_OK != CADtlsEnableAnonECDHCipherSuite(enable))
+    {
+        return CA_STATUS_FAILED;
+    }
+#endif
+#ifdef __WITH_TLS__
+    // TLS_ECDH_ANON_WITH_AES_128_CBC_SHA256    0xFF00 replaces 0xC018
+    // TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256    0xC037
+    if (CA_STATUS_OK != CAsetTlsCipherSuite(enable ? 0xFF00 : 0xC037))
+    {
+        return CA_STATUS_FAILED;
+    }
+#endif
+    return CA_STATUS_OK;
 }
 
 CAResult_t CAGenerateOwnerPSK(const CAEndpoint_t* endpoint,
@@ -499,10 +587,20 @@ CAResult_t CAGenerateOwnerPSK(const CAEndpoint_t* endpoint,
         return CA_STATUS_INVALID_PARAM;
     }
 
-    res = CADtlsGenerateOwnerPSK(endpoint, label, labelLen,
-                                  rsrcServerDeviceID, rsrcServerDeviceIDLen,
-                                  provServerDeviceID, provServerDeviceIDLen,
-                                  ownerPSK, ownerPSKSize);
+    if(CA_ADAPTER_IP == endpoint->adapter)
+    {
+        res = CADtlsGenerateOwnerPSK(endpoint, label, labelLen,
+                                      rsrcServerDeviceID, rsrcServerDeviceIDLen,
+                                      provServerDeviceID, provServerDeviceIDLen,
+                                      ownerPSK, ownerPSKSize);
+    }
+#ifdef __WITH_TLS__
+    else
+    {
+        res = CAtlsGenerateOwnerPSK(endpoint, ownerPSK, ownerPSKSize,
+                rsrcServerDeviceID, rsrcServerDeviceIDLen);
+    }
+#endif
     if (CA_STATUS_OK != res)
     {
         OIC_LOG_V(ERROR, TAG, "Failed to CAGenerateOwnerPSK : %d", res);
index b9f2c11..cec1f42 100644 (file)
@@ -38,7 +38,9 @@
 #include "caremotehandler.h"
 #include "logger.h"
 #include "oic_malloc.h"
-#include "oic_string.h"
+#ifdef __WITH_TLS__
+#include "ca_adapter_net_tls.h"
+#endif
 
 /**
  * Logging tag for module name.
@@ -163,6 +165,21 @@ void CATCPPacketReceivedCB(const CASecureEndpoint_t *sep, const void *data,
     }
 }
 
+#ifdef __WITH_TLS__
+static void CATCPPacketSendCB(CAEndpoint_t *endpoint, const void *data, uint32_t dataLength)
+{
+    OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
+    VERIFY_NON_NULL_VOID(endpoint, TAG, "endpoint is NULL");
+    VERIFY_NON_NULL_VOID(data, TAG, "data is NULL");
+
+    OIC_LOG_V(DEBUG, TAG, "Address: %s, port:%d", endpoint->addr, endpoint->port);
+    OIC_LOG_BUFFER(DEBUG, TAG, data, dataLength);
+
+    CATCPSendData(endpoint, data, dataLength, false);
+    OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
+}
+#endif
+
 void CATCPErrorHandler(const CAEndpoint_t *endpoint, const void *data,
                        uint32_t dataLength, CAResult_t result)
 {
@@ -245,6 +262,11 @@ CAResult_t CAInitializeTCP(CARegisterConnectivityCallback registerCallback,
     CATCPSetPacketReceiveCallback(CATCPPacketReceivedCB);
     CATCPSetErrorHandler(CATCPErrorHandler);
 
+#ifdef __WITH_TLS__
+    CAinitTlsAdapter();
+    CAsetTlsAdapterCallbacks(CATCPPacketReceivedCB, CATCPPacketSendCB, 0);
+#endif
+
     CAConnectivityHandler_t tcpHandler = {
         .startAdapter = CAStartTCP,
         .startListenServer = CAStartTCPListeningServer,
@@ -412,6 +434,10 @@ CAResult_t CAStopTCP()
     //Re-initializing the Globals to start them again
     CAInitializeTCPGlobals();
 
+#ifdef __WITH_TLS__
+    CAdeinitTlsAdapter();
+#endif
+
     return CA_STATUS_OK;
 }
 
@@ -441,6 +467,22 @@ void CATCPSendDataThread(void *threadData)
     }
     else
     {
+#ifdef __WITH_TLS__
+         if (tcpData->remoteEndpoint && tcpData->remoteEndpoint->flags & CA_SECURE)
+         {
+             CAResult_t result = CA_STATUS_OK;
+             OIC_LOG(DEBUG, TAG, "CAencryptTls called!");
+             result = CAencryptTls(tcpData->remoteEndpoint, tcpData->data, tcpData->dataLen);
+
+             if (CA_STATUS_OK != result)
+             {
+                 OIC_LOG(ERROR, TAG, "CAAdapterNetDtlsEncrypt failed!");
+             }
+             OIC_LOG_V(DEBUG, TAG,
+                       "CAAdapterNetDtlsEncrypt returned with result[%d]", result);
+            return;
+         }
+#endif
         //Processing for sending unicast
         CATCPSendData(tcpData->remoteEndpoint, tcpData->data, tcpData->dataLen, false);
     }
index 737c41d..ae6df9d 100644 (file)
 #include "caadapterutils.h"
 #include "camutex.h"
 #include "oic_malloc.h"
-#include "oic_string.h"
+
+#ifdef __WITH_TLS__
+#include "ca_adapter_net_tls.h"
+#endif
 
 /**
  * Logging tag for module name.
  * Maximum CoAP over TCP header length
  * to know the total data length.
  */
-#define TCP_MAX_HEADER_LEN  6
+#define COAP_MAX_HEADER_SIZE  6
+
+/**
+ * TLS header size
+ */
+#define TLS_HEADER_SIZE 5
 
 /**
  * Mutex to synchronize device object list.
@@ -96,6 +104,56 @@ static int CATCPCreateSocket(int family, CATCPSessionInfo_t *tcpServerInfo);
     if (FD > caglobals.tcp.maxfd) \
         caglobals.tcp.maxfd = FD;
 
+#define REALLOC(buffer, length) \
+{ \
+    unsigned char *tmpBuf = OICRealloc(buffer, length); \
+    if (!tmpBuf) \
+    { \
+        OIC_LOG(ERROR, TAG, "out of memory"); \
+        goto error; \
+    } \
+    buffer = tmpBuf; \
+}
+
+/**
+ * Read length amount of data from socket fd
+ * Made a few recv calls if required
+ *
+ * @param[in]  fd     - socket
+ * @param[out] item   - used to update received message length
+ * @param[out] data   - buffer to store data
+ * @param[in]  length - length of data required to read
+ * @param[in]  flags  - additional info about socket
+ */
+#define RECV(fd, item, data, length, flags) \
+{ \
+    int remain_len = length; \
+    int len = 0; \
+    while (remain_len > 0) \
+    { \
+        len = recv(fd, data + item->len, remain_len, flags); \
+        OIC_LOG_V(DEBUG, TAG, "recv len = %d", len); \
+        OIC_LOG_BUFFER(DEBUG, TAG, data + item->len, len); \
+        if (2 == len && 0 == data[item->len] && 0 == data[item->len + 1]) \
+        { \
+            OIC_LOG(DEBUG, TAG, "received RESET message. Skip it"); \
+            continue; \
+        } \
+        if (len < 0) \
+        { \
+            OIC_LOG_V(ERROR, TAG, "recv failed %s", strerror(errno)); \
+            goto error; \
+        } \
+        else if (0 == len) \
+        { \
+            OIC_LOG(INFO, TAG, "Received disconnect from peer. Close connection"); \
+            goto error; \
+        } \
+        item->len += len; \
+        remain_len -= len; \
+    } \
+}
+
 static void CATCPDestroyMutex()
 {
     if (g_mutexObjectList)
@@ -321,6 +379,34 @@ static void CAAcceptConnection(CATransportFlags_t flag, CASocket_t *sock)
     }
 }
 
+#ifdef __WITH_TLS__
+static bool CAIsTlsMessage(const CATCPSessionInfo_t * recvinfo)
+{
+    if (recvinfo->data == NULL || recvinfo->len == 0)
+    {
+        OIC_LOG_V(ERROR, TAG, "%s: null input param", __func__);
+        return false;
+    }
+
+    unsigned char first_byte = recvinfo->data[0];
+
+    //TLS Plaintext has four types: change_cipher_spec = [14], alert = [15],
+    //handshake = [16], application_data = [17] in HEX
+    const uint8_t tls_head_type[] = {0x14, 0x15, 0x16, 0x17};
+    size_t i = 0;
+
+    for (i = 0; i < sizeof(tls_head_type); i++)
+    {
+        if(tls_head_type[i] == first_byte)
+        {
+            return true;
+        }
+    }
+
+    return false;
+}
+#endif
+
 static void CAReceiveMessage(int fd)
 {
     // #1. get remote device information from file descriptor.
@@ -332,70 +418,72 @@ static void CAReceiveMessage(int fd)
         return;
     }
 
-    // #2. get already allocated memory size.
-    size_t bufSize = (svritem->totalDataLen == 0) ? TCP_MAX_HEADER_LEN : svritem->totalDataLen;
-    if (!svritem->recvData)
+    // #2. allocate memory for message header (CoAP header size because it is bigger)
+    svritem->data = (unsigned char *) OICCalloc(1, COAP_MAX_HEADER_SIZE);
+    if (!svritem->data)
     {
-        svritem->recvData = (unsigned char *) OICCalloc(1, bufSize);
-        if (!svritem->recvData)
-        {
-            OIC_LOG(ERROR, TAG, "out of memory");
-            CADisconnectTCPSession(svritem, index);
-            return;
-        }
+        OIC_LOG(ERROR, TAG, "out of memory");
+        goto error;
     }
 
-    // #3. receive data from remote device.
-    ssize_t recvLen = recv(fd, svritem->recvData + svritem->recvDataLen,
-                           bufSize - svritem->recvDataLen, 0);
-    if (recvLen <= 0)
+    // #3. read data (assume TLS header) from remote device.
+    RECV(fd, svritem, svritem->data, TLS_HEADER_SIZE, 0);
+
+#ifdef __WITH_TLS__
+    if (CAIsTlsMessage(svritem))
     {
-        if(EWOULDBLOCK != errno)
-        {
-            OIC_LOG_V(ERROR, TAG, "Recvfrom failed %s", strerror(errno));
-            CADisconnectTCPSession(svritem, index);
-        }
-        return;
-    }
-    svritem->recvDataLen += recvLen;
+        // #4.1 get tls body length from tls header. [3][4] bytes are length of tls body in header
+        unsigned int message_length = (unsigned int)((svritem->data[3] << 8) | svritem->data[4]);
+        OIC_LOG_V(DEBUG, TAG, "%s: message_length = %d", __func__, message_length);
+
+        REALLOC(svritem->data, message_length + TLS_HEADER_SIZE);
 
-    // #4. get actual data length from coap over tcp header.
-    if (!svritem->totalDataLen)
+        RECV(fd, svritem, svritem->data, message_length, 0);
+
+        int ret = CAdecryptTls(&svritem->sep, (uint8_t *)svritem->data, svritem->len);
+
+        OIC_LOG_V(DEBUG, TAG, "%s: CAdecryptTls returned %d", __func__, ret);
+        goto success;
+    }
+    else
+#endif
     {
-        coap_transport_type transport = coap_get_tcp_header_type_from_initbyte(
-                ((unsigned char *) svritem->recvData)[0] >> 4);
+        // #4.2 Seems CoAP data received. read full coap header.
+        coap_transport_type transport = coap_get_tcp_header_type_from_initbyte(svritem->data[0] >> 4);
 
         size_t headerLen = coap_get_tcp_header_length_for_transport(transport);
-        if (svritem->recvDataLen >= headerLen)
+
+        if (svritem->len < headerLen)
         {
-            svritem->totalDataLen = CAGetTotalLengthFromHeader(
-                    (unsigned char *) svritem->recvData);
-            bufSize = svritem->totalDataLen;
-            unsigned char *newBuf = OICRealloc(svritem->recvData, bufSize);
-            if (!newBuf)
-            {
-                OIC_LOG(ERROR, TAG, "out of memory");
-                CADisconnectTCPSession(svritem, index);
-                return;
-            }
-            svritem->recvData = newBuf;
+            // read required bytes to have full CoAP header
+            // usually it is 1 bytes (COAP_MAX_HEADER_SIZE - TLS_HEADER_SIZE)
+            RECV(fd, svritem, svritem->data, headerLen - svritem->len, 0);
         }
-    }
 
-    // #5. pass the received data information to upper layer.
-    if ((svritem->totalDataLen == svritem->recvDataLen) && g_packetReceivedCallback)
-    {
-        svritem->sep.endpoint.adapter = CA_ADAPTER_TCP;
-        g_packetReceivedCallback(&svritem->sep, svritem->recvData, svritem->recvDataLen);
-        OIC_LOG_V(DEBUG, TAG, "total received data len:%d", svritem->recvDataLen);
+        // #4.3 Calculate CoAP message length and read it
+        size_t total_length = CAGetTotalLengthFromHeader(svritem->data);
+        REALLOC(svritem->data, total_length);
+
+        RECV(fd, svritem, svritem->data, total_length - svritem->len, 0);
 
-        // initialize data info to receive next message.
-        OICFree(svritem->recvData);
-        svritem->recvData = NULL;
-        svritem->recvDataLen = 0;
-        svritem->totalDataLen = 0;
+        // #4.4. pass the received data information to upper layer.
+        if (g_packetReceivedCallback)
+        {
+            svritem->sep.endpoint.adapter = CA_ADAPTER_TCP;
+            g_packetReceivedCallback(&svritem->sep, svritem->data, svritem->len);
+        }
+        goto success;
     }
 
+    error:
+    CADisconnectTCPSession(svritem, index);
+
+    success:
+    // initialize data info to receive next message.
+    OICFree(svritem->data);
+    svritem->data = NULL;
+    svritem->len = 0;
+
     return;
 }
 
@@ -745,42 +833,6 @@ void CATCPSetConnectionChangedCallback(CATCPConnectionHandleCallback connHandler
     g_connectionCallback = connHandler;
 }
 
-static size_t CACheckPayloadLength(const void *data, size_t dlen)
-{
-    VERIFY_NON_NULL_RET(data, TAG, "data", -1);
-
-    coap_transport_type transport = coap_get_tcp_header_type_from_initbyte(
-            ((unsigned char *)data)[0] >> 4);
-
-    coap_pdu_t *pdu = coap_new_pdu(transport, dlen);
-    if (!pdu)
-    {
-        OIC_LOG(ERROR, TAG, "outpdu is null");
-        return 0;
-    }
-
-    int ret = coap_pdu_parse((unsigned char *) data, dlen, pdu, transport);
-    if (0 >= ret)
-    {
-        OIC_LOG(ERROR, TAG, "pdu parse failed");
-        coap_delete_pdu(pdu);
-        return 0;
-    }
-
-    size_t payloadLen = 0;
-    size_t headerSize = coap_get_tcp_header_length_for_transport(transport);
-    OIC_LOG_V(DEBUG, TAG, "headerSize : %d, pdu length : %d",
-              headerSize, pdu->length);
-    if (pdu->length > headerSize)
-    {
-        payloadLen = (unsigned char *) pdu->hdr + pdu->length - pdu->data;
-    }
-
-    OICFree(pdu);
-
-    return payloadLen;
-}
-
 static void sendData(const CAEndpoint_t *endpoint, const void *data,
                      size_t dlen, const char *fam)
 {
@@ -802,17 +854,7 @@ static void sendData(const CAEndpoint_t *endpoint, const void *data,
         }
     }
 
-    // #2. check payload length
-    size_t payloadLen = CACheckPayloadLength(data, dlen);
-    // if payload length is zero, disconnect from TCP server
-    if (!payloadLen)
-    {
-        OIC_LOG(DEBUG, TAG, "payload length is zero, disconnect from remote device");
-        CADisconnectTCPSession(svritem, index);
-        return;
-    }
-
-    // #3. check connection state
+    // #2. check connection state
     if (svritem->fd < 0)
     {
         // if file descriptor value is wrong, remove TCP Server info from list
@@ -943,7 +985,8 @@ CAResult_t CADisconnectTCPSession(CATCPSessionInfo_t *svritem, size_t index)
         close(svritem->fd);
     }
     u_arraylist_remove(caglobals.tcp.svrlist, index);
-    OICFree(svritem->recvData);
+    OICFree(svritem->data);
+    svritem->data = NULL;
 
     // pass the connection information to CA Common Layer.
     if (g_connectionCallback)
@@ -970,7 +1013,9 @@ void CATCPDisconnectAll()
         {
             shutdown(svritem->fd, SHUT_RDWR);
             close(svritem->fd);
-            OICFree(svritem->recvData);
+
+            OICFree(svritem->data);
+            svritem->data = NULL;
         }
     }
     u_arraylist_destroy(caglobals.tcp.svrlist);
@@ -1040,9 +1085,9 @@ size_t CAGetTotalLengthFromHeader(const unsigned char *recvBuffer)
                                                         transport);
     size_t headerLen = coap_get_tcp_header_length((unsigned char *)recvBuffer);
 
-    OIC_LOG_V(DEBUG, TAG, "option/paylaod length [%d]", optPaylaodLen);
-    OIC_LOG_V(DEBUG, TAG, "header length [%d]", headerLen);
-    OIC_LOG_V(DEBUG, TAG, "total data length [%d]", headerLen + optPaylaodLen);
+    OIC_LOG_V(DEBUG, TAG, "option/paylaod length [%zu]", optPaylaodLen);
+    OIC_LOG_V(DEBUG, TAG, "header length [%zu]", headerLen);
+    OIC_LOG_V(DEBUG, TAG, "total data length [%zu]", headerLen + optPaylaodLen);
 
     OIC_LOG(DEBUG, TAG, "OUT - CAGetTotalLengthFromHeader");
     return headerLen + optPaylaodLen;
index 71dbdda..0dc19e0 100644 (file)
@@ -49,6 +49,11 @@ if target_os not in ['arduino', 'darwin', 'ios', 'msys_nt', 'windows']:
 if catest_env.get('SECURED') == '1':
        catest_env.AppendUnique(LIBS = ['tinydtls'])
        catest_env.AppendUnique(LIBS = ['timer'])
+       if catest_env.get('WITH_TCP') == True:
+               catest_env.AppendUnique(LIBS = ['mbedtls', 'mbedx509','mbedcrypto'])
+
+if catest_env.get('WITH_RD') == '1':
+       catest_env.PrependUnique(LIBS = ['resource_directory'])
 
 if catest_env.get('LOGGING'):
        catest_env.AppendUnique(CPPDEFINES = ['TB_LOG'])
index ca0ccfc..4952d83 100644 (file)
@@ -50,6 +50,7 @@ libocsrm_env.PrependUnique(CPPPATH = [
                '../connectivity/lib/libcoap-4.1.1',
                '../connectivity/external/inc',
                '../connectivity/common/inc',
+               '../connectivity/inc/pkix',
                '../connectivity/inc',
                '../connectivity/api',
                '../security/include',
@@ -116,7 +117,7 @@ if env.get('SECURED') == '1':
 if target_os in ['windows', 'msys_nt']:
        libocsrm_src  = libocsrm_src + [OCSRM_SRC + 'strptime.c']
 
-if env.get('DTLS_WITH_X509') == '1' and env.get('SECURED') == '1':
+if (env.get('DTLS_WITH_X509') == '1' or env.get('WITH_TCP') == True) and env.get('SECURED') == '1':
        crl_src = [OCSRM_SRC + 'crlresource.c']
        libocsrm_src  = libocsrm_src + crl_src
 
index a8d3e9f..52e105c 100644 (file)
@@ -54,7 +54,7 @@ OCStackResult DeInitCredResource();
  * @return reference to @ref OicSecCred_t, if credential is found, else NULL, if credential
  * not found.
  */
-const OicSecCred_t* GetCredResourceData(const OicUuid_t* subjectId);
+OicSecCred_t* GetCredResourceData(const OicUuid_t* subjectId);
 
 /**
  * This function converts credential data into CBOR format.
@@ -178,6 +178,22 @@ OCStackResult SetCredRownerId(const OicUuid_t* newROwner);
  */
 OCStackResult GetCredRownerId(OicUuid_t *rowneruuid);
 
+#ifdef __WITH_TLS__
+/**
+ * @def CA_SUBJECT_ID
+ * @brief subject uuid for credential with CA certificates
+ */
+#define CA_SUBJECT_ID ("00000000-0000-0000-0000-000000000000")
+/**
+ * Adds the new CA to the chain
+ *
+ * @param cert is the pointer to DER encoded certificate
+ *
+ * @return ::OC_STACK_OK, cert not NULL and persistent storage gets updated.
+ * ::OC_STACK_ERROR, cert is NULL or fails to update persistent storage.
+ */
+OCStackResult AddCA(OicSecCert_t * cert);
+#endif
 #ifdef __cplusplus
 }
 #endif
index 5cefddd..407040e 100644 (file)
@@ -43,9 +43,9 @@
 
 #include <stdint.h> // for uint8_t typedef
 #include <stdbool.h>
-#ifdef __WITH_X509__
+#if defined(__WITH_X509__) || defined(__WITH_TLS__)
 #include "byte_array.h"
-#endif /* __WITH_X509__ */
+#endif /* __WITH_X509__  or __WITH_TLS__*/
 
 #include "platform_features.h"
 
@@ -291,12 +291,12 @@ typedef char *OicUrn_t; //TODO is URN type defined elsewhere?
 typedef struct OicUuid OicUuid_t; //TODO is UUID type defined elsewhere?
 
 
-#ifdef __WITH_X509__
+#if defined(__WITH_X509__) || defined(__WITH_TLS__)
 typedef struct OicSecCrl OicSecCrl_t;
 typedef ByteArray OicSecCert_t;
 #else
 typedef void OicSecCert_t;
-#endif /* __WITH_X509__ */
+#endif /* __WITH_X509__ or __WITH_TLS__*/
 
 /**
  * /oic/uuid (Universal Unique Identifier) data type.
@@ -398,9 +398,10 @@ struct OicSecCred
     //size_t              roleIdsLen;     // the number of elts in RoleIds
     //OicSecRole_t        *roleIds;       // 2:R:M:N:oic.sec.role
     OicSecCredType_t    credType;       // 3:R:S:Y:oic.sec.credtype
-#ifdef __WITH_X509__
-    OicSecCert_t        publicData;     // chain of certificates
-#endif /* __WITH_X509__ */
+#if defined(__WITH_X509__) || defined(__WITH_TLS__)
+    OicSecCert_t        publicData;     // own cerificate chain
+    OicSecCert_t        optionalData;   // CA's cerificate chain
+#endif /* __WITH_X509__  or __WITH_TLS__*/
     OicSecKey_t         privateData;    // 6:R:S:N:oic.sec.key
     char                *period;        // 7:R:S:N:String
     OicUuid_t           rownerID;        // 8:R:S:Y:oic.uuid
@@ -486,14 +487,14 @@ struct OicSecSvc
     OicSecSvc_t             *next;
 };
 
-#ifdef __WITH_X509__
+#if defined(__WITH_X509__) ||  defined(__WITH_TLS__)
 struct OicSecCrl
 {
     uint16_t CrlId;
     ByteArray ThisUpdate;
     ByteArray CrlData;
 };
-#endif /* __WITH_X509__ */
+#endif /* __WITH_X509__ or __WITH_TLS__ */
 
 /**
  * @brief   direct pairing data type
index ed1fa42..df501af 100644 (file)
@@ -41,6 +41,7 @@ provisioning_env.AppendUnique(CPPPATH = [
                '../../../../extlibs/cjson/',
                '../../../../extlibs/tinydtls/',
                '../../connectivity/inc',
+               '../../connectivity/inc/pkix',
                '../../connectivity/external/inc',
                '../../connectivity/common/inc',
                '../../connectivity/lib/libcoap-4.1.1',
index f6b7a7a..b84fb73 100644 (file)
@@ -67,6 +67,9 @@ typedef struct OCProvisionDev
     OicSecDoxm_t    *doxm;           /**< Pointer to target's doxm resource. **/
     OCConnectivityType connType;     /**< Connectivity type of endpoint */
     uint16_t        securePort;      /**< secure port **/
+#ifdef WITH_TCP
+    uint16_t        tcpPort;         /**< tcp port **/
+#endif
     char             secVer[MAX_VERSION_LEN];         /**< security version **/
     DeviceStatus    devStatus;       /**< status of device **/
     struct OCProvisionDev  *next;    /**< Next pointer. **/
index 2a64248..ddb2968 100644 (file)
@@ -37,7 +37,9 @@ extern "C"
 #define COAPS_QUERY "coaps://%s:%d%s"
 #define COAP_QUERY "coap://%s:%d%s"
 
-/**
+#define COAP_TCP_PREFIX "coap+tcp://"
+#define COAPS_TCP_PREFIX "coaps+tcp://"
+    /**
  * Discover owned/unowned devices in the same IP subnet. .
  *
  * @param[in] waittime      Timeout in seconds.
index 191713d..cfbba58 100644 (file)
@@ -43,6 +43,7 @@ provisioning_env.AppendUnique(CPPPATH = [
                '../../../../../extlibs/cjson',
                '../../../../../extlibs/base64',
                '../../../connectivity/inc',
+               '../../../connectivity/inc/pkix',
                '../../../connectivity/common/inc',
                '../../../connectivity/lib/libcoap-4.1.1',
                '../../../connectivity/api'
index 3a6d123..0fb014a 100644 (file)
@@ -58,6 +58,7 @@ extern "C"
 #define _52_RESET_SELEC_DEV_        52
 #define _60_GET_CRED_               60
 #define _61_GET_ACL_                61
+#define _70_SELECT_PROTOCOL_        70
 #define _99_EXIT_PRVN_CLT_          99
 
 #define ACL_RESRC_MAX_NUM   16
@@ -88,7 +89,10 @@ static OCProvisionDev_t* g_unown_list;
 static int g_own_cnt;
 static int g_unown_cnt;
 static bool g_doneCB;
-
+#ifdef __WITH_TLS__
+static int secure_protocol = 1;
+static void setDevProtocol(const OCProvisionDev_t* dev_lst);
+#endif
 // function declaration(s) for calling them before implementing
 static OicSecAcl_t* createAcl(const int);
 static OicSecPdAcl_t* createPdAcl(const int);
@@ -357,7 +361,10 @@ static int discoverAllDevices(void)
     g_own_cnt = printDevList(g_own_list);
     printf("   > Discovered Unowned Devices\n");
     g_unown_cnt = printDevList(g_unown_list);
-
+#ifdef __WITH_TLS__
+    setDevProtocol(g_own_list);
+    setDevProtocol(g_unown_list);
+#endif
     return 0;
 }
 
@@ -382,7 +389,9 @@ static int discoverUnownedDevices(void)
     // display the discovered unowned list
     printf("   > Discovered Unowned Devices\n");
     g_unown_cnt = printDevList(g_unown_list);
-
+#ifdef __WITH_TLS__
+    setDevProtocol(g_unown_list);
+#endif
     return 0;
 }
 
@@ -406,7 +415,9 @@ static int discoverOwnedDevices(void)
     // display the discovered owned list
     printf("   > Discovered Owned Devices\n");
     g_own_cnt = printDevList(g_own_list);
-
+#ifdef __WITH_TLS__
+    setDevProtocol(g_own_list);
+#endif
     return 0;
 }
 
@@ -1574,6 +1585,55 @@ static int selectTwoDiffNum(int* a, int* b, const int max, const char* str)
     return -1;
 }
 
+#ifdef __WITH_TLS__
+
+static void setDevProtocol(const OCProvisionDev_t* dev_lst)
+{
+    if(!dev_lst)
+    {
+        printf("     Device List is Empty..\n\n");
+        return;
+    }
+
+    OCProvisionDev_t* lst = (OCProvisionDev_t*) dev_lst;
+
+    for( ; lst; )
+    {
+        if(2 == secure_protocol)
+        {
+            lst->connType &= ~CT_ADAPTER_IP; //reset IP flag
+            lst->connType |= CT_ADAPTER_TCP; //set TCP flag
+            lst->endpoint.adapter = OC_ADAPTER_TCP;
+            lst->endpoint.port = lst->tcpPort;
+            lst->securePort = lst->tcpPort;
+        }
+        lst = lst->next;
+    }
+}
+
+static void selectSecureProtocol()
+{
+    printf("   Select protocol\n");
+    printf("   1 - DTLS(Default)\n");
+    printf("   2 - TLS\n");
+
+    for(int ret=0; 1!=ret; )
+    {
+        ret = scanf("%d",&secure_protocol);
+        for( ; 0x20<=getchar(); );  // for removing overflow garbages
+        // '0x20<=code' is character region
+    }
+
+    if(0 >= secure_protocol || 2 < secure_protocol)
+    {
+        secure_protocol = 1;
+    }
+
+    setDevProtocol(g_own_list);
+    setDevProtocol(g_unown_list);
+}
+#endif
+
 static void printMenu(void)
 {
     printf("************************************************************\n");
@@ -1606,7 +1666,10 @@ static void printMenu(void)
     printf("** [F] GET SECURITY RESOURCE FOR DEBUGGING ONLY\n");
     printf("** 60. Get the Credential resources of the Selected Device\n");
     printf("** 61. Get the ACL resources of the Selected Device\n\n");
-
+#ifdef __WITH_TLS__
+    printf("** [F] SELECT SECURE PROTOCOL DTLS/TLS\n");
+    printf("** 70. Select secure protocol(default DTLS)\n\n");
+#endif
     printf("** [F] EXIT PROVISIONING CLIENT\n");
     printf("** 99. Exit Provisionong Client\n\n");
 
@@ -1749,6 +1812,11 @@ int main()
                 OIC_LOG(ERROR, TAG, "_61_GET_ACL_: error");
             }
             break;
+#ifdef __WITH_TLS__
+        case  _70_SELECT_PROTOCOL_:
+            selectSecureProtocol();
+            break;
+#endif
         case _99_EXIT_PRVN_CLT_:
             goto PMCLT_ERROR;
         default:
index 296ce17..6499e03 100644 (file)
@@ -243,6 +243,12 @@ static void SetResult(OTMContext_t* otmCtx, const OCStackResult res)
         //Revert psk_info callback and new deivce uuid in case of random PIN OxM
         if(OIC_RANDOM_DEVICE_PIN == otmCtx->selectedDeviceInfo->doxm->oxmSel)
         {
+#ifdef __WITH_TLS__
+            if(CA_STATUS_OK != CAregisterTlsCredentialsHandler(GetDtlsPskCredentials))
+            {
+                OIC_LOG(WARNING, TAG, "Failed to revert  is TLS credential handler.");
+            }
+#endif
             if(CA_STATUS_OK != CARegisterDTLSCredentialsHandler(GetDtlsPskCredentials))
             {
                 OIC_LOG(WARNING, TAG, "Failed to revert  is DTLS credential handler.");
@@ -396,6 +402,7 @@ static OCStackResult SaveOwnerPSK(OCProvisionDev_t *selectedDeviceInfo)
     OICStrcpy(endpoint.addr, MAX_ADDR_STR_SIZE_CA, selectedDeviceInfo->endpoint.addr);
     endpoint.addr[MAX_ADDR_STR_SIZE_CA - 1] = '\0';
     endpoint.port = selectedDeviceInfo->securePort;
+    endpoint.adapter = selectedDeviceInfo->endpoint.adapter;
 
     OicUuid_t ptDeviceID = {.id={0}};
     if (OC_STACK_OK != GetDoxmDeviceID(&ptDeviceID))
@@ -729,7 +736,17 @@ static OCStackApplicationResult OwnerCredentialHandler(void *ctx, OCDoHandle UNU
             //Close the temporal secure session to verify the owner credential
             CAEndpoint_t* endpoint = (CAEndpoint_t *)&otmCtx->selectedDeviceInfo->endpoint;
             endpoint->port = otmCtx->selectedDeviceInfo->securePort;
-            CAResult_t caResult = CACloseDtlsSession(endpoint);
+            CAResult_t caResult = CA_STATUS_OK;
+            if(CA_ADAPTER_IP == endpoint->adapter)
+            {
+                caResult = CACloseDtlsSession(endpoint);
+            }
+#ifdef __WITH_TLS__
+            else
+            {
+                caResult = CAcloseTlsConnection(endpoint);
+            }
+#endif
             if(CA_STATUS_OK != caResult)
             {
                 OIC_LOG(ERROR, TAG, "Failed to close DTLS session");
@@ -741,7 +758,16 @@ static OCStackApplicationResult OwnerCredentialHandler(void *ctx, OCDoHandle UNU
              * If we select NULL cipher,
              * client will select appropriate cipher suite according to server's cipher-suite list.
              */
-            caResult = CASelectCipherSuite(TLS_NULL_WITH_NULL_NULL);
+            if(CA_ADAPTER_IP == endpoint->adapter)
+            {
+                caResult = CASelectCipherSuite(TLS_NULL_WITH_NULL_NULL, endpoint->adapter);
+            }
+            else
+            {
+                // TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256 = 0xC037, /**< see RFC 5489 */
+                caResult = CASelectCipherSuite(0xC037, endpoint->adapter);
+            }
+
             if(CA_STATUS_OK != caResult)
             {
                 OIC_LOG(ERROR, TAG, "Failed to select TLS_NULL_WITH_NULL_NULL");
@@ -758,14 +784,27 @@ static OCStackApplicationResult OwnerCredentialHandler(void *ctx, OCDoHandle UNU
                 OicUuid_t emptyUuid = { .id={0}};
                 SetUuidForRandomPinOxm(&emptyUuid);
 
-                if(CA_STATUS_OK != CARegisterDTLSCredentialsHandler(GetDtlsPskCredentials))
+                if(CA_ADAPTER_IP == endpoint->adapter)
+                {
+                    caResult = CARegisterDTLSCredentialsHandler(GetDtlsPskCredentials);
+                }
+#ifdef __WITH_TLS__
+                else
+                {
+                    caResult = CAregisterTlsCredentialsHandler(GetDtlsPskCredentials);
+                }
+#endif
+
+                if(CA_STATUS_OK != caResult)
                 {
                     OIC_LOG(ERROR, TAG, "Failed to revert DTLS credential handler.");
                     SetResult(otmCtx, OC_STACK_INVALID_CALLBACK);
                     return OC_STACK_DELETE_TRANSACTION;
                 }
             }
-
+#ifdef __WITH_TLS__
+           otmCtx->selectedDeviceInfo->connType |= CT_FLAG_SECURE;
+#endif
             //POST /oic/sec/doxm [{ ..., "owned":"TRUE" }]
             res = PostOwnershipInformation(otmCtx);
             if(OC_STACK_OK != res)
@@ -1318,7 +1357,13 @@ static OCStackResult StartOwnershipTransfer(void* ctx, OCProvisionDev_t* selecte
     {
         OIC_LOG(WARNING, TAG, "StartOwnershipTransfer : Failed to register DTLS handshake callback.");
     }
-
+#ifdef __WITH_TLS__
+    //Register TLS event handler to catch the tls event while handshake
+    if(CA_STATUS_OK != CAregisterTlsHandshakeCallback(DTLSHandshakeCB))
+    {
+        OIC_LOG(WARNING, TAG, "StartOwnershipTransfer : Failed to register TLS handshake callback.");
+    }
+#endif
     OIC_LOG(INFO, TAG, "OUT StartOwnershipTransfer");
 
     return res;
index d8518ff..0417323 100644 (file)
@@ -91,7 +91,7 @@ OCStackResult CreateSecureSessionJustWorksCallback(OTMContext_t* otmCtx)
     }
     OIC_LOG(INFO, TAG, "Anonymous cipher suite Enabled.");
 
-    caresult  = CASelectCipherSuite(TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256);
+    caresult  = CASelectCipherSuite(TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256, otmCtx->selectedDeviceInfo->endpoint.adapter);
     if (CA_STATUS_OK != caresult)
     {
         OIC_LOG_V(ERROR, TAG, "Failed to select TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256");
@@ -109,19 +109,24 @@ OCStackResult CreateSecureSessionJustWorksCallback(OTMContext_t* otmCtx)
     OIC_LOG(INFO, TAG, "TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256 cipher suite selected.");
 
     OCProvisionDev_t *selDevInfo = otmCtx->selectedDeviceInfo;
-    CAEndpoint_t *endpoint = (CAEndpoint_t *)OICCalloc(1, sizeof (CAEndpoint_t));
-    if(NULL == endpoint)
+    CAEndpoint_t endpoint;
+    memcpy(&endpoint, &selDevInfo->endpoint, sizeof(CAEndpoint_t));
+
+    if(CA_ADAPTER_IP == endpoint.adapter)
     {
-        return OC_STACK_NO_MEMORY;
+        endpoint.port = selDevInfo->securePort;
+        caresult = CAInitiateHandshake(&endpoint);
     }
-    memcpy(endpoint, &selDevInfo->endpoint, sizeof(CAEndpoint_t));
-    endpoint->port = selDevInfo->securePort;
-
-    caresult = CAInitiateHandshake(endpoint);
-    OICFree(endpoint);
+#ifdef __WITH_TLS__
+    else
+    {
+        endpoint.port = selDevInfo->tcpPort;
+        caresult = CAinitiateTlsHandshake(&endpoint);
+    }
+#endif
     if (CA_STATUS_OK != caresult)
     {
-        OIC_LOG_V(ERROR, TAG, "DTLS handshake failure.");
+        OIC_LOG_V(ERROR, TAG, "DTLS/TLS handshake failure.");
         return OC_STACK_ERROR;
     }
 
index d1cb7f5..8375fc8 100644 (file)
@@ -92,6 +92,13 @@ OCStackResult InputPinCodeCallback(OTMContext_t *otmCtx)
      * Credential should not be saved into SVR.
      * For this reason, We will use a temporary get_psk_info callback to random PIN OxM.
      */
+#ifdef __WITH_TLS__
+    if(CA_STATUS_OK != CAregisterTlsCredentialsHandler(GetDtlsPskForRandomPinOxm))
+    {
+        OIC_LOG(ERROR, TAG, "Failed to register TLS credentials handler for random PIN OxM.");
+        res = OC_STACK_ERROR;
+    }
+#endif
     if(CA_STATUS_OK != CARegisterDTLSCredentialsHandler(GetDtlsPskForRandomPinOxm))
     {
         OIC_LOG(ERROR, TAG, "Failed to register DTLS credentials handler for random PIN OxM.");
@@ -121,7 +128,7 @@ OCStackResult CreateSecureSessionRandomPinCallback(OTMContext_t* otmCtx)
     }
     OIC_LOG(INFO, TAG, "Anonymous cipher suite disabled.");
 
-    caresult  = CASelectCipherSuite(TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256);
+    caresult  = CASelectCipherSuite(TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256, otmCtx->selectedDeviceInfo->endpoint.adapter);
     if (CA_STATUS_OK != caresult)
     {
         OIC_LOG_V(ERROR, TAG, "Failed to select TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256");
@@ -130,15 +137,21 @@ OCStackResult CreateSecureSessionRandomPinCallback(OTMContext_t* otmCtx)
     OIC_LOG(INFO, TAG, "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256 cipher suite selected.");
 
     OCProvisionDev_t* selDevInfo = otmCtx->selectedDeviceInfo;
-    CAEndpoint_t *endpoint = (CAEndpoint_t *)OICCalloc(1, sizeof (CAEndpoint_t));
-    if (NULL == endpoint)
+    CAEndpoint_t endpoint;
+    memcpy(&endpoint, &selDevInfo->endpoint, sizeof(CAEndpoint_t));
+
+    if(CA_ADAPTER_IP == endpoint.adapter)
+    {
+        endpoint.port = selDevInfo->securePort;
+        caresult = CAInitiateHandshake(&endpoint);
+    }
+#ifdef __WITH_TLS__
+    else
     {
-        return OC_STACK_NO_MEMORY;
+        endpoint.port = selDevInfo->tcpPort;
+        caresult = CAinitiateTlsHandshake(&endpoint);
     }
-    memcpy(endpoint,&selDevInfo->endpoint,sizeof(CAEndpoint_t));
-    endpoint->port = selDevInfo->securePort;
-    caresult = CAInitiateHandshake(endpoint);
-    OICFree(endpoint);
+#endif
     if (CA_STATUS_OK != caresult)
     {
         OIC_LOG_V(ERROR, TAG, "DTLS handshake failure.");
index 7ce7bc8..bda2270 100644 (file)
@@ -148,23 +148,21 @@ OCProvisionDev_t* GetDevice(OCProvisionDev_t **ppDevicesList, const char* addr,
  * Add device information to list.
  *
  * @param[in] pList         List of OCProvisionDev_t.
- * @param[in] addr          address of target device.
- * @param[in] port          port of remote server.
- * @param[in] adapter       adapter type of endpoint.
+ * @param[in] endpoint      target device endpoint.
+ * @param[in] connType      connectivity type of endpoint
  * @param[in] doxm          pointer to doxm instance.
- * @param[in] connType  connectivity type of endpoint
  *
- * @return OC_STACK_OK for success and errorcode otherwise.
+ * @return OC_STACK_OK for success and error code otherwise.
  */
-OCStackResult AddDevice(OCProvisionDev_t **ppDevicesList, const char* addr, const uint16_t port,
-                        OCTransportAdapter adapter, OCConnectivityType connType, OicSecDoxm_t *doxm)
+OCStackResult AddDevice(OCProvisionDev_t **ppDevicesList, OCDevAddr* endpoint,
+                        OCConnectivityType connType, OicSecDoxm_t *doxm)
 {
-    if (NULL == addr)
+    if (NULL == endpoint)
     {
         return OC_STACK_INVALID_PARAM;
     }
 
-    OCProvisionDev_t *ptr = GetDevice(ppDevicesList, addr, port);
+    OCProvisionDev_t *ptr = GetDevice(ppDevicesList, endpoint->addr, endpoint->port);
     if(!ptr)
     {
         ptr = (OCProvisionDev_t *)OICCalloc(1, sizeof (OCProvisionDev_t));
@@ -174,11 +172,9 @@ OCStackResult AddDevice(OCProvisionDev_t **ppDevicesList, const char* addr, cons
             return OC_STACK_NO_MEMORY;
         }
 
-        OICStrcpy(ptr->endpoint.addr, MAX_ADDR_STR_SIZE, addr);
-        ptr->endpoint.port = port;
+        ptr->endpoint = *endpoint;
         ptr->doxm = doxm;
         ptr->securePort = DEFAULT_SECURE_PORT;
-        ptr->endpoint.adapter = adapter;
         ptr->next = NULL;
         ptr->connType = connType;
         ptr->devStatus = DEV_STATUS_ON; //AddDevice is called when discovery(=alive)
@@ -200,8 +196,12 @@ OCStackResult AddDevice(OCProvisionDev_t **ppDevicesList, const char* addr, cons
  *
  * @return OC_STACK_OK for success and errorcode otherwise.
  */
-OCStackResult UpdateSecurePortOfDevice(OCProvisionDev_t **ppDevicesList, const char *addr,
-                                       uint16_t port, uint16_t securePort)
+static OCStackResult UpdateSecurePortOfDevice(OCProvisionDev_t **ppDevicesList, const char *addr,
+                                       uint16_t port, uint16_t securePort
+#ifdef __WITH_TLS__
+                                       ,uint16_t tcpPort
+#endif
+                                       )
 {
     OCProvisionDev_t *ptr = GetDevice(ppDevicesList, addr, port);
 
@@ -213,6 +213,10 @@ OCStackResult UpdateSecurePortOfDevice(OCProvisionDev_t **ppDevicesList, const c
 
     ptr->securePort = securePort;
 
+#ifdef __WITH_TLS__
+    ptr->tcpPort = tcpPort;
+#endif
+
     return OC_STACK_OK;
 }
 
@@ -429,6 +433,8 @@ bool PMGenerateQuery(bool isSecure,
 
     switch(connType & CT_MASK_ADAPTER)
     {
+        case CT_ADAPTER_TCP:
+            prefix = (isSecure == true) ? COAPS_TCP_PREFIX : COAP_TCP_PREFIX;
         case CT_ADAPTER_IP:
             switch(connType & CT_MASK_FLAGS & ~CT_FLAG_SECURE)
             {
@@ -598,11 +604,18 @@ static OCStackApplicationResult SecurePortDiscoveryHandler(void *ctx, OCDoHandle
                 OIC_LOG(INFO, TAG, "Can not find secure port information.");
                 return OC_STACK_DELETE_TRANSACTION;
             }
-
+#ifdef __WITH_TLS__
+            OIC_LOG_V(DEBUG, TAG, "%s: TCP port from discovery = %d", __func__, resPayload->tcpPort);
+#endif
             DiscoveryInfo* pDInfo = (DiscoveryInfo*)ctx;
             OCStackResult res = UpdateSecurePortOfDevice(pDInfo->ppDevicesList,
                                                          clientResponse->devAddr.addr,
-                                                         clientResponse->devAddr.port, securePort);
+                                                         clientResponse->devAddr.port,
+                                                         securePort
+#ifdef __WITH_TLS__
+                                                         ,resPayload->tcpPort
+#endif
+                                                         );
             if (OC_STACK_OK != res)
             {
                 OIC_LOG(ERROR, TAG, "Error while getting secure port.");
@@ -712,9 +725,7 @@ static OCStackApplicationResult DeviceDiscoveryHandler(void *ctx, OCDoHandle UNU
                     return OC_STACK_KEEP_TRANSACTION;
                 }
 
-                res = AddDevice(ppDevicesList, clientResponse->devAddr.addr,
-                        clientResponse->devAddr.port,
-                        clientResponse->devAddr.adapter,
+                res = AddDevice(ppDevicesList, &clientResponse->devAddr,
                         clientResponse->connType, ptrDoxm);
                 if (OC_STACK_OK != res)
                 {
index 837f4bf..e75ea21 100644 (file)
@@ -135,6 +135,7 @@ struct UnlinkData {
 
 //Example of DELETE cred request -> coaps://0.0.0.0:5684/oic/sec/cred?sub=(BASE64 ENCODED UUID)
 const char * SRP_FORM_DELETE_CREDENTIAL = "coaps://[%s]:%d%s?%s=%s";
+const char * SRP_FORM_DELETE_CREDENTIAL_TCP = "coaps+tcp://[%s]:%d%s?%s=%s";
 
 // Structure to carry remove APIs data to callback.
 typedef struct RemoveData RemoveData_t;
@@ -1142,7 +1143,14 @@ static OCStackResult SendDeleteCredentialRequest(void* ctx,
     char reqBuf[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
     int snRet = 0;
                     //coaps://0.0.0.0:5684/oic/sec/cred?subjectid=(Canonical ENCODED UUID)
-    snRet = snprintf(reqBuf, sizeof(reqBuf), SRP_FORM_DELETE_CREDENTIAL, destDev->endpoint.addr,
+    char *srpUri = SRP_FORM_DELETE_CREDENTIAL;
+#ifdef __WITH_TLS__
+    if(CA_ADAPTER_TCP == destDev->endpoint.adapter)
+    {
+        srpUri = SRP_FORM_DELETE_CREDENTIAL_TCP;
+    }
+#endif
+    snRet = snprintf(reqBuf, sizeof(reqBuf), srpUri, destDev->endpoint.addr,
                      destDev->securePort, OIC_RSRC_CRED_URI, OIC_JSON_SUBJECTID_NAME, subID);
     OICFree(subID);
     if (snRet < 0)
index cbc72fb..b1d9412 100644 (file)
@@ -47,6 +47,7 @@ sptest_env.PrependUnique(CPPPATH = [
                '../../../../../extlibs/cjson',
                '../../../../../extlibs/base64',
                '../../../connectivity/inc',
+               '../../../connectivity/inc/pkix',
                '../../../connectivity/common/inc',
                '../../../connectivity/lib/libcoap-4.1.1',
                '../../../connectivity/api',
@@ -69,6 +70,9 @@ if sptest_env.get('DTLS_WITH_X509') == '1':
        sptest_env.AppendUnique(LIBS = ['CKManager'])
        sptest_env.AppendUnique(LIBS = ['asn1'])
 
+if sptest_env.get('WITH_TCP') == True:
+       sptest_env.AppendUnique(LIBS = ['mbedtls', 'mbedx509','mbedcrypto'])
+
 if not sptest_env.get('RELEASE'):
        sptest_env.AppendUnique(CPPDEFINES = ['TB_LOG'])
 
index a8a1683..3fdc187 100644 (file)
@@ -87,7 +87,7 @@ static void FreeCred(OicSecCred_t *cred)
 #endif
 
     //Clean PublicData
-#ifdef __WITH_X509__
+#if defined(__WITH_X509__) || defined(WITH_TLS) 
     OICFree(cred->publicData.data);
 #endif
 
@@ -936,7 +936,7 @@ OCStackResult RemoveAllCredentials(void)
     return OC_STACK_OK;
 }
 
-#ifdef __WITH_DTLS__
+#if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
 /**
  * Internal function to fill private data of owner PSK.
  *
@@ -1023,7 +1023,7 @@ static OCEntityHandlerResult HandlePostRequest(const OCEntityHandlerRequest * eh
     OCStackResult res = CBORPayloadToCred(payload, size, &cred);
     if (res == OC_STACK_OK)
     {
-#ifdef __WITH_DTLS__
+#if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
         OicUuid_t emptyUuid = {.id={0}};
         const OicSecDoxm_t* doxm = GetDoxmResourceData();
         if(doxm && false == doxm->owned && memcmp(&(doxm->owner), &emptyUuid, sizeof(OicUuid_t)) != 0)
@@ -1069,6 +1069,14 @@ static OCEntityHandlerResult HandlePostRequest(const OCEntityHandlerRequest * eh
                             OicUuid_t emptyUuid = { .id={0}};
                             SetUuidForRandomPinOxm(&emptyUuid);
 
+#ifdef __WITH_TLS__
+                            if(CA_STATUS_OK != CAregisterTlsCredentialsHandler(GetDtlsPskCredentials))
+                            {
+                                OIC_LOG(ERROR, TAG, "Failed to revert TLS credential handler.");
+                                ret = OC_EH_ERROR;
+                                break;
+                            }
+#endif
                             if(CA_STATUS_OK != CARegisterDTLSCredentialsHandler(GetDtlsPskCredentials))
                             {
                                 OIC_LOG(ERROR, TAG, "Failed to revert DTLS credential handler.");
@@ -1089,7 +1097,7 @@ static OCEntityHandlerResult HandlePostRequest(const OCEntityHandlerRequest * eh
                         }
 
                         if(CA_STATUS_OK !=
-                           CASelectCipherSuite(TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256))
+                           CASelectCipherSuite(TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256, ehRequest->devAddr.adapter))
                         {
                             OIC_LOG(ERROR, TAG, "Failed to select cipher suite");
                             ret = OC_EH_ERROR;
@@ -1339,7 +1347,7 @@ OCStackResult DeInitCredResource()
     return result;
 }
 
-const OicSecCred_t* GetCredResourceData(const OicUuid_t* subject)
+OicSecCred_t* GetCredResourceData(const OicUuid_t* subject)
 {
     OicSecCred_t *cred = NULL;
 
@@ -1359,7 +1367,7 @@ const OicSecCred_t* GetCredResourceData(const OicUuid_t* subject)
 }
 
 
-#if defined(__WITH_DTLS__)
+#if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
 int32_t GetDtlsPskCredentials(CADtlsPskCredType_t type,
               const uint8_t *desc, size_t desc_len,
               uint8_t *result, size_t result_length)
@@ -1647,3 +1655,258 @@ OCStackResult GetCredRownerId(OicUuid_t *rowneruuid)
     }
     return retVal;
 }
+
+#ifdef __WITH_TLS__
+OCStackResult AddCA(OicSecCert_t * cert)
+{
+    OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
+    OCStackResult ret = OC_STACK_ERROR;
+    if (NULL == cert || NULL == cert->data)
+    {
+        return OC_STACK_INVALID_PARAM;
+    }
+    OicUuid_t  subject;
+    OicUuid_t rowner;
+    ret = GetCredRownerId(&rowner);
+    VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
+    ret = ConvertStrToUuid(CA_SUBJECT_ID, &subject);
+    VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
+
+    OicSecCred_t * cred  = GetCredResourceData(&subject);
+    if (NULL == cred)
+    {
+        //Generating new credential for CA
+        cred = GenerateCredential(&subject, SIGNED_ASYMMETRIC_KEY, cert, NULL, &rowner);
+        VERIFY_NON_NULL(TAG, cred, ERROR);
+        return AddCredential(cred);
+    }
+
+    uint8_t * tempData = OICRealloc(cred->publicData.data, cred->publicData.len + cert->len);
+    if (NULL == tempData)
+    {
+        return OC_STACK_NO_MEMORY;
+    }
+
+    memcpy(tempData + cred->publicData.len, cert->data, cert->len);
+    cred->publicData.data = tempData;
+    cred->publicData.len += cert->len;
+
+    if (UpdatePersistentStorage(gCred))
+    {
+        ret = OC_STACK_OK;
+    }
+
+exit:
+    OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
+    return ret;
+}
+// TODO for testing only
+// will be removed
+const unsigned char ca_cert[] = {
+// AMAZON
+0x30, 0x82, 0x02, 0xFE, 0x30, 0x82, 0x01, 0xE6, 0x02, 0x01, 0x01, 0x30, 0x0D, 0x06, 0x09, 0x2A,
+0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, 0x45, 0x31, 0x0B, 0x30, 0x09,
+0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
+0x04, 0x08, 0x0C, 0x0A, 0x53, 0x6F, 0x6D, 0x65, 0x2D, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31, 0x21,
+0x30, 0x1F, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x18, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x6E, 0x65,
+0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4C, 0x74,
+0x64, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x36, 0x30, 0x36, 0x32, 0x38, 0x30, 0x35, 0x33, 0x33, 0x35,
+0x38, 0x5A, 0x17, 0x0D, 0x32, 0x36, 0x30, 0x36, 0x32, 0x36, 0x30, 0x35, 0x33, 0x33, 0x35, 0x38,
+0x5A, 0x30, 0x45, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x41, 0x55,
+0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0C, 0x0A, 0x53, 0x6F, 0x6D, 0x65, 0x2D,
+0x53, 0x74, 0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x18,
+0x49, 0x6E, 0x74, 0x65, 0x72, 0x6E, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 0x69, 0x74, 0x73,
+0x20, 0x50, 0x74, 0x79, 0x20, 0x4C, 0x74, 0x64, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0D, 0x06, 0x09,
+0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0F, 0x00,
+0x30, 0x82, 0x01, 0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, 0xB5, 0x1C, 0x79, 0x1F, 0x30, 0x6F, 0x5C,
+0x04, 0x9E, 0xD9, 0x78, 0x22, 0x01, 0x29, 0xEE, 0xE9, 0x4A, 0x3A, 0x69, 0xB6, 0xF8, 0xBE, 0x87,
+0x3A, 0x5D, 0x57, 0xBD, 0x96, 0xEE, 0xCC, 0xE9, 0x58, 0x39, 0x53, 0x41, 0xD5, 0x1A, 0x47, 0x12,
+0x8B, 0xF5, 0xAA, 0x0D, 0xC5, 0xBC, 0xAE, 0x17, 0x93, 0x8B, 0xF3, 0x10, 0x10, 0xF6, 0xCD, 0xBC,
+0x22, 0xA2, 0x31, 0x74, 0xF5, 0xBB, 0x5F, 0x72, 0x40, 0x9A, 0x42, 0xE2, 0x83, 0x33, 0x02, 0xA3,
+0x6C, 0x6D, 0x5C, 0x7C, 0xFF, 0x3B, 0x2B, 0xE8, 0x99, 0x4E, 0x9F, 0x86, 0x26, 0xE7, 0x79, 0x0C,
+0x39, 0x0D, 0xEF, 0xA2, 0x52, 0x80, 0xFA, 0xF3, 0x37, 0x46, 0xFB, 0xF9, 0x35, 0x35, 0xC0, 0x16,
+0xC7, 0x1F, 0x95, 0x10, 0x03, 0x30, 0xE1, 0xFB, 0xD9, 0xBD, 0x84, 0x95, 0x11, 0x0D, 0x5A, 0x28,
+0x59, 0xE3, 0xB6, 0xB4, 0x3C, 0xA3, 0xA6, 0x5F, 0x7B, 0x9F, 0x8C, 0x45, 0x3B, 0xC1, 0xAB, 0xE1,
+0xB4, 0xFA, 0x3C, 0x19, 0x58, 0x91, 0x28, 0x29, 0xBA, 0x71, 0x20, 0xFA, 0x4D, 0x58, 0xF1, 0xB1,
+0x01, 0x5D, 0x7B, 0xB4, 0x4A, 0x5E, 0xFA, 0x58, 0x36, 0xEE, 0x31, 0x18, 0x0D, 0x81, 0xB5, 0x41,
+0x48, 0x8B, 0xD9, 0x31, 0xBC, 0xD1, 0x98, 0xD0, 0x40, 0xBF, 0x79, 0x3A, 0x31, 0x13, 0x61, 0xFF,
+0x04, 0x23, 0x1A, 0x2A, 0xAC, 0xA1, 0xEF, 0x1C, 0x2B, 0xC3, 0x8A, 0x7D, 0x33, 0x75, 0xDF, 0x84,
+0xA8, 0xF3, 0x74, 0x63, 0xE4, 0x61, 0x92, 0x5D, 0xCF, 0x62, 0x8C, 0x56, 0x9B, 0xB7, 0x7C, 0xCF,
+0x4A, 0x75, 0x98, 0x3E, 0xE5, 0x73, 0x03, 0x8C, 0xBF, 0x2D, 0x4A, 0x80, 0x48, 0x2D, 0x27, 0xB4,
+0x87, 0xCB, 0x40, 0xF6, 0x48, 0x85, 0xBF, 0x29, 0xA0, 0xE8, 0xC7, 0xF9, 0x11, 0x3C, 0x2D, 0x4F,
+0x92, 0xC1, 0x5E, 0x01, 0x2D, 0x81, 0xD1, 0x9F, 0x73, 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x0D,
+0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x03, 0x82, 0x01,
+0x01, 0x00, 0x0B, 0x47, 0x8E, 0x29, 0x8C, 0xCB, 0x05, 0xE7, 0xF3, 0xDD, 0xC8, 0x7E, 0xED, 0x6F,
+0xB4, 0xD9, 0xCB, 0xF4, 0x84, 0xCC, 0xA5, 0x08, 0x6C, 0x1C, 0x09, 0x60, 0xD5, 0x00, 0x55, 0x13,
+0x28, 0xC6, 0x64, 0xB2, 0x23, 0x52, 0x03, 0x21, 0xB1, 0x69, 0x63, 0x57, 0x04, 0xC2, 0xD4, 0xF7,
+0x41, 0xAC, 0xEE, 0xD5, 0xD0, 0x49, 0x58, 0x6D, 0xE5, 0x7E, 0x2C, 0xA6, 0x06, 0xC0, 0x39, 0x3A,
+0x7E, 0x30, 0x49, 0xA2, 0x00, 0x8B, 0x81, 0x98, 0x94, 0xC3, 0x5F, 0x05, 0xF1, 0x38, 0xC7, 0x0B,
+0xFA, 0x83, 0xB2, 0x85, 0x84, 0xB2, 0x6D, 0x62, 0x07, 0x82, 0x9C, 0x4D, 0x99, 0x24, 0xD2, 0x79,
+0xBF, 0xDA, 0xF8, 0x9D, 0x1C, 0xAD, 0x13, 0x30, 0xBC, 0xC2, 0xA2, 0x14, 0x7B, 0xD7, 0xFB, 0xCD,
+0x29, 0x2D, 0xAB, 0xB6, 0x24, 0x03, 0x60, 0x62, 0x9E, 0xF4, 0x4C, 0xE3, 0x35, 0x23, 0xB7, 0x1A,
+0x50, 0x96, 0x91, 0x54, 0xD8, 0xB4, 0x93, 0x61, 0x00, 0xB6, 0xBF, 0x05, 0xF0, 0xF3, 0x6B, 0x99,
+0x1E, 0x46, 0x4C, 0x26, 0x95, 0xD2, 0x58, 0x86, 0x5C, 0x78, 0xAD, 0x01, 0xF9, 0xC9, 0x54, 0x67,
+0xB7, 0x99, 0x3C, 0xEE, 0xF8, 0xD7, 0xD2, 0x1E, 0xE6, 0xF0, 0xCC, 0xC8, 0xC2, 0x20, 0x1B, 0xDA,
+0xCF, 0xDB, 0xF5, 0x70, 0x65, 0x33, 0x51, 0x6E, 0x17, 0x1D, 0xC5, 0xC5, 0xC5, 0x63, 0x06, 0x5E,
+0xCA, 0xB5, 0x40, 0x14, 0xEE, 0xDC, 0x14, 0xF2, 0xFE, 0x4B, 0x7A, 0x78, 0xD6, 0x0D, 0x21, 0xF5,
+0x0F, 0x58, 0xE7, 0x2A, 0x26, 0x54, 0x52, 0xCA, 0x60, 0xA2, 0xF8, 0x68, 0xB0, 0xF4, 0x6A, 0x9B,
+0x11, 0x8D, 0x5E, 0x57, 0x5A, 0x5F, 0x51, 0x3E, 0x44, 0x99, 0xB1, 0x76, 0xDA, 0x94, 0x56, 0x0E,
+0x1C, 0xA3, 0xFC, 0xE3, 0x01, 0xB4, 0xD8, 0xEC, 0x2F, 0xBB, 0x65, 0x82, 0x19, 0x06, 0x8E, 0x3A,
+0x2E, 0x5D,
+//Google
+
+0x30, 0x82, 0x03, 0x54, 0x30, 0x82, 0x02, 0x3c, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x03, 0x02,
+0x34, 0x56, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05,
+0x00, 0x30, 0x42, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53,
+0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0d, 0x47, 0x65, 0x6f, 0x54, 0x72,
+0x75, 0x73, 0x74, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04,
+0x03, 0x13, 0x12, 0x47, 0x65, 0x6f, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6c, 0x6f, 0x62,
+0x61, 0x6c, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x32, 0x30, 0x35, 0x32, 0x31, 0x30,
+0x34, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x32, 0x32, 0x30, 0x35, 0x32, 0x31, 0x30, 0x34,
+0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x42, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
+0x13, 0x02, 0x55, 0x53, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0d, 0x47,
+0x65, 0x6f, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x1b, 0x30, 0x19,
+0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x12, 0x47, 0x65, 0x6f, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20,
+0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x43, 0x41, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06,
+0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f,
+0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xda, 0xcc, 0x18, 0x63, 0x30, 0xfd,
+0xf4, 0x17, 0x23, 0x1a, 0x56, 0x7e, 0x5b, 0xdf, 0x3c, 0x6c, 0x38, 0xe4, 0x71, 0xb7, 0x78, 0x91,
+0xd4, 0xbc, 0xa1, 0xd8, 0x4c, 0xf8, 0xa8, 0x43, 0xb6, 0x03, 0xe9, 0x4d, 0x21, 0x07, 0x08, 0x88,
+0xda, 0x58, 0x2f, 0x66, 0x39, 0x29, 0xbd, 0x05, 0x78, 0x8b, 0x9d, 0x38, 0xe8, 0x05, 0xb7, 0x6a,
+0x7e, 0x71, 0xa4, 0xe6, 0xc4, 0x60, 0xa6, 0xb0, 0xef, 0x80, 0xe4, 0x89, 0x28, 0x0f, 0x9e, 0x25,
+0xd6, 0xed, 0x83, 0xf3, 0xad, 0xa6, 0x91, 0xc7, 0x98, 0xc9, 0x42, 0x18, 0x35, 0x14, 0x9d, 0xad,
+0x98, 0x46, 0x92, 0x2e, 0x4f, 0xca, 0xf1, 0x87, 0x43, 0xc1, 0x16, 0x95, 0x57, 0x2d, 0x50, 0xef,
+0x89, 0x2d, 0x80, 0x7a, 0x57, 0xad, 0xf2, 0xee, 0x5f, 0x6b, 0xd2, 0x00, 0x8d, 0xb9, 0x14, 0xf8,
+0x14, 0x15, 0x35, 0xd9, 0xc0, 0x46, 0xa3, 0x7b, 0x72, 0xc8, 0x91, 0xbf, 0xc9, 0x55, 0x2b, 0xcd,
+0xd0, 0x97, 0x3e, 0x9c, 0x26, 0x64, 0xcc, 0xdf, 0xce, 0x83, 0x19, 0x71, 0xca, 0x4e, 0xe6, 0xd4,
+0xd5, 0x7b, 0xa9, 0x19, 0xcd, 0x55, 0xde, 0xc8, 0xec, 0xd2, 0x5e, 0x38, 0x53, 0xe5, 0x5c, 0x4f,
+0x8c, 0x2d, 0xfe, 0x50, 0x23, 0x36, 0xfc, 0x66, 0xe6, 0xcb, 0x8e, 0xa4, 0x39, 0x19, 0x00, 0xb7,
+0x95, 0x02, 0x39, 0x91, 0x0b, 0x0e, 0xfe, 0x38, 0x2e, 0xd1, 0x1d, 0x05, 0x9a, 0xf6, 0x4d, 0x3e,
+0x6f, 0x0f, 0x07, 0x1d, 0xaf, 0x2c, 0x1e, 0x8f, 0x60, 0x39, 0xe2, 0xfa, 0x36, 0x53, 0x13, 0x39,
+0xd4, 0x5e, 0x26, 0x2b, 0xdb, 0x3d, 0xa8, 0x14, 0xbd, 0x32, 0xeb, 0x18, 0x03, 0x28, 0x52, 0x04,
+0x71, 0xe5, 0xab, 0x33, 0x3d, 0xe1, 0x38, 0xbb, 0x07, 0x36, 0x84, 0x62, 0x9c, 0x79, 0xea, 0x16,
+0x30, 0xf4, 0x5f, 0xc0, 0x2b, 0xe8, 0x71, 0x6b, 0xe4, 0xf9, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3,
+0x53, 0x30, 0x51, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30,
+0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xc0,
+0x7a, 0x98, 0x68, 0x8d, 0x89, 0xfb, 0xab, 0x05, 0x64, 0x0c, 0x11, 0x7d, 0xaa, 0x7d, 0x65, 0xb8,
+0xca, 0xcc, 0x4e, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14,
+0xc0, 0x7a, 0x98, 0x68, 0x8d, 0x89, 0xfb, 0xab, 0x05, 0x64, 0x0c, 0x11, 0x7d, 0xaa, 0x7d, 0x65,
+0xb8, 0xca, 0xcc, 0x4e, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
+0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x35, 0xe3, 0x29, 0x6a, 0xe5, 0x2f, 0x5d, 0x54,
+0x8e, 0x29, 0x50, 0x94, 0x9f, 0x99, 0x1a, 0x14, 0xe4, 0x8f, 0x78, 0x2a, 0x62, 0x94, 0xa2, 0x27,
+0x67, 0x9e, 0xd0, 0xcf, 0x1a, 0x5e, 0x47, 0xe9, 0xc1, 0xb2, 0xa4, 0xcf, 0xdd, 0x41, 0x1a, 0x05,
+0x4e, 0x9b, 0x4b, 0xee, 0x4a, 0x6f, 0x55, 0x52, 0xb3, 0x24, 0xa1, 0x37, 0x0a, 0xeb, 0x64, 0x76,
+0x2a, 0x2e, 0x2c, 0xf3, 0xfd, 0x3b, 0x75, 0x90, 0xbf, 0xfa, 0x71, 0xd8, 0xc7, 0x3d, 0x37, 0xd2,
+0xb5, 0x05, 0x95, 0x62, 0xb9, 0xa6, 0xde, 0x89, 0x3d, 0x36, 0x7b, 0x38, 0x77, 0x48, 0x97, 0xac,
+0xa6, 0x20, 0x8f, 0x2e, 0xa6, 0xc9, 0x0c, 0xc2, 0xb2, 0x99, 0x45, 0x00, 0xc7, 0xce, 0x11, 0x51,
+0x22, 0x22, 0xe0, 0xa5, 0xea, 0xb6, 0x15, 0x48, 0x09, 0x64, 0xea, 0x5e, 0x4f, 0x74, 0xf7, 0x05,
+0x3e, 0xc7, 0x8a, 0x52, 0x0c, 0xdb, 0x15, 0xb4, 0xbd, 0x6d, 0x9b, 0xe5, 0xc6, 0xb1, 0x54, 0x68,
+0xa9, 0xe3, 0x69, 0x90, 0xb6, 0x9a, 0xa5, 0x0f, 0xb8, 0xb9, 0x3f, 0x20, 0x7d, 0xae, 0x4a, 0xb5,
+0xb8, 0x9c, 0xe4, 0x1d, 0xb6, 0xab, 0xe6, 0x94, 0xa5, 0xc1, 0xc7, 0x83, 0xad, 0xdb, 0xf5, 0x27,
+0x87, 0x0e, 0x04, 0x6c, 0xd5, 0xff, 0xdd, 0xa0, 0x5d, 0xed, 0x87, 0x52, 0xb7, 0x2b, 0x15, 0x02,
+0xae, 0x39, 0xa6, 0x6a, 0x74, 0xe9, 0xda, 0xc4, 0xe7, 0xbc, 0x4d, 0x34, 0x1e, 0xa9, 0x5c, 0x4d,
+0x33, 0x5f, 0x92, 0x09, 0x2f, 0x88, 0x66, 0x5d, 0x77, 0x97, 0xc7, 0x1d, 0x76, 0x13, 0xa9, 0xd5,
+0xe5, 0xf1, 0x16, 0x09, 0x11, 0x35, 0xd5, 0xac, 0xdb, 0x24, 0x71, 0x70, 0x2c, 0x98, 0x56, 0x0b,
+0xd9, 0x17, 0xb4, 0xd1, 0xe3, 0x51, 0x2b, 0x5e, 0x75, 0xe8, 0xd5, 0xd0, 0xdc, 0x4f, 0x34, 0xed,
+0xc2, 0x05, 0x66, 0x80, 0xa1, 0xcb, 0xe6, 0x33,
+// Device
+0x30, 0x82, 0x01, 0x55, 0x30, 0x81, 0xFB, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x30,
+0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x34, 0x31, 0x32, 0x30,
+0x30, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x29, 0x75, 0x75, 0x69, 0x64, 0x3A, 0x33, 0x32, 0x33,
+0x32, 0x33, 0x32, 0x33, 0x32, 0x2D, 0x33, 0x32, 0x33, 0x32, 0x2D, 0x33, 0x32, 0x33, 0x32, 0x2D,
+0x33, 0x32, 0x33, 0x32, 0x2D, 0x33, 0x32, 0x33, 0x32, 0x33, 0x32, 0x33, 0x32, 0x33, 0x32, 0x33,
+0x32, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x36, 0x30, 0x37, 0x32, 0x36, 0x31, 0x34, 0x31, 0x32, 0x32,
+0x31, 0x5A, 0x17, 0x0D, 0x31, 0x37, 0x30, 0x31, 0x30, 0x31, 0x32, 0x32, 0x30, 0x30, 0x30, 0x30,
+0x5A, 0x30, 0x34, 0x31, 0x32, 0x30, 0x30, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x29, 0x75, 0x75,
+0x69, 0x64, 0x3A, 0x33, 0x32, 0x33, 0x32, 0x33, 0x32, 0x33, 0x32, 0x2D, 0x33, 0x32, 0x33, 0x32,
+0x2D, 0x33, 0x32, 0x33, 0x32, 0x2D, 0x33, 0x32, 0x33, 0x32, 0x2D, 0x33, 0x32, 0x33, 0x32, 0x33,
+0x32, 0x33, 0x32, 0x33, 0x32, 0x33, 0x32, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48,
+0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42,
+0x00, 0x04, 0x19, 0x1D, 0x6B, 0x4A, 0x12, 0xA7, 0x20, 0xF1, 0x95, 0xC6, 0x6D, 0x2A, 0xD7, 0x3B,
+0xFA, 0x90, 0x8C, 0x52, 0xEB, 0x75, 0x67, 0xFF, 0x0A, 0x3F, 0xF2, 0xDF, 0x8D, 0x81, 0x44, 0xC7,
+0xC8, 0x84, 0x60, 0xD4, 0x07, 0x57, 0xB1, 0x96, 0xAF, 0x5E, 0x00, 0xA5, 0xED, 0xA1, 0x48, 0x3F,
+0x88, 0x43, 0x8D, 0x15, 0x81, 0x0A, 0x21, 0x9B, 0x6C, 0xD3, 0xBD, 0x85, 0x86, 0xE1, 0xA6, 0xDA,
+0xC5, 0xCE, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x03, 0x49,
+0x00, 0x30, 0x46, 0x02, 0x21, 0x00, 0xF7, 0x8E, 0x43, 0x19, 0xD2, 0x86, 0xF9, 0x21, 0x84, 0x66,
+0x23, 0x4B, 0x18, 0x7C, 0x56, 0x18, 0x37, 0x48, 0xDF, 0x16, 0x3B, 0x70, 0x52, 0x26, 0x62, 0xB3,
+0xAA, 0xD8, 0x3D, 0xE9, 0x43, 0xC3, 0x02, 0x21, 0x00, 0xD0, 0x16, 0xA4, 0x33, 0x7A, 0xE3, 0x7C,
+0x62, 0x88, 0x88, 0x7B, 0x76, 0x99, 0xBF, 0x2D, 0xDF, 0x6C, 0xF5, 0xD0, 0x5F, 0xBE, 0x4B, 0xAE,
+0xBA, 0xE5, 0xC0, 0x05, 0x26, 0xBC, 0x8B, 0x20, 0x84
+};
+const unsigned char own_cert[] = {
+0x30, 0x82, 0x01, 0x55, 0x30, 0x81, 0xFB, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x30,
+0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x34, 0x31, 0x32, 0x30,
+0x30, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x29, 0x75, 0x75, 0x69, 0x64, 0x3A, 0x33, 0x32, 0x33,
+0x32, 0x33, 0x32, 0x33, 0x32, 0x2D, 0x33, 0x32, 0x33, 0x32, 0x2D, 0x33, 0x32, 0x33, 0x32, 0x2D,
+0x33, 0x32, 0x33, 0x32, 0x2D, 0x33, 0x32, 0x33, 0x32, 0x33, 0x32, 0x33, 0x32, 0x33, 0x32, 0x33,
+0x32, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x36, 0x30, 0x37, 0x32, 0x36, 0x31, 0x34, 0x31, 0x32, 0x32,
+0x31, 0x5A, 0x17, 0x0D, 0x31, 0x37, 0x30, 0x31, 0x30, 0x31, 0x32, 0x32, 0x30, 0x30, 0x30, 0x30,
+0x5A, 0x30, 0x34, 0x31, 0x32, 0x30, 0x30, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x29, 0x75, 0x75,
+0x69, 0x64, 0x3A, 0x33, 0x32, 0x33, 0x32, 0x33, 0x32, 0x33, 0x32, 0x2D, 0x33, 0x32, 0x33, 0x32,
+0x2D, 0x33, 0x32, 0x33, 0x32, 0x2D, 0x33, 0x32, 0x33, 0x32, 0x2D, 0x33, 0x32, 0x33, 0x32, 0x33,
+0x32, 0x33, 0x32, 0x33, 0x32, 0x33, 0x32, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48,
+0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42,
+0x00, 0x04, 0x19, 0x1D, 0x6B, 0x4A, 0x12, 0xA7, 0x20, 0xF1, 0x95, 0xC6, 0x6D, 0x2A, 0xD7, 0x3B,
+0xFA, 0x90, 0x8C, 0x52, 0xEB, 0x75, 0x67, 0xFF, 0x0A, 0x3F, 0xF2, 0xDF, 0x8D, 0x81, 0x44, 0xC7,
+0xC8, 0x84, 0x60, 0xD4, 0x07, 0x57, 0xB1, 0x96, 0xAF, 0x5E, 0x00, 0xA5, 0xED, 0xA1, 0x48, 0x3F,
+0x88, 0x43, 0x8D, 0x15, 0x81, 0x0A, 0x21, 0x9B, 0x6C, 0xD3, 0xBD, 0x85, 0x86, 0xE1, 0xA6, 0xDA,
+0xC5, 0xCE, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x03, 0x49,
+0x00, 0x30, 0x46, 0x02, 0x21, 0x00, 0xF7, 0x8E, 0x43, 0x19, 0xD2, 0x86, 0xF9, 0x21, 0x84, 0x66,
+0x23, 0x4B, 0x18, 0x7C, 0x56, 0x18, 0x37, 0x48, 0xDF, 0x16, 0x3B, 0x70, 0x52, 0x26, 0x62, 0xB3,
+0xAA, 0xD8, 0x3D, 0xE9, 0x43, 0xC3, 0x02, 0x21, 0x00, 0xD0, 0x16, 0xA4, 0x33, 0x7A, 0xE3, 0x7C,
+0x62, 0x88, 0x88, 0x7B, 0x76, 0x99, 0xBF, 0x2D, 0xDF, 0x6C, 0xF5, 0xD0, 0x5F, 0xBE, 0x4B, 0xAE,
+0xBA, 0xE5, 0xC0, 0x05, 0x26, 0xBC, 0x8B, 0x20, 0x84
+};
+const unsigned char ca_key[] = {
+0x30, 0x81, 0x93, 0x02, 0x01, 0x00, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02,
+0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x04, 0x79, 0x30, 0x77, 0x02,
+0x01, 0x01, 0x04, 0x20, 0xe9, 0xe4, 0x27, 0xb2, 0x5c, 0xe1, 0xe9, 0xc4, 0x9d, 0x23, 0x55, 0x67,
+0x08, 0x66, 0x0c, 0xe5, 0x83, 0xa9, 0xf1, 0xe2, 0x09, 0xfb, 0x89, 0xea, 0xa8, 0xe4, 0x46, 0x6e,
+0x76, 0xff, 0x75, 0x02, 0xa0, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07,
+0xa1, 0x44, 0x03, 0x42, 0x00, 0x04, 0x19, 0x1d, 0x6b, 0x4a, 0x12, 0xa7, 0x20, 0xf1, 0x95, 0xc6,
+0x6d, 0x2a, 0xd7, 0x3b, 0xfa, 0x90, 0x8c, 0x52, 0xeb, 0x75, 0x67, 0xff, 0x0a, 0x3f, 0xf2, 0xdf,
+0x8d, 0x81, 0x44, 0xc7, 0xc8, 0x84, 0x60, 0xd4, 0x07, 0x57, 0xb1, 0x96, 0xaf, 0x5e, 0x00, 0xa5,
+0xed, 0xa1, 0x48, 0x3f, 0x88, 0x43, 0x8d, 0x15, 0x81, 0x0a, 0x21, 0x9b, 0x6c, 0xd3, 0xbd, 0x85,
+0x86, 0xe1, 0xa6, 0xda, 0xc5, 0xce
+};
+void GetDerOwnCert(OicSecCert_t * crt)
+{
+    crt->data = OICMalloc(sizeof(own_cert));
+    memcpy(crt->data, own_cert, sizeof(own_cert));
+    crt->len = sizeof(own_cert);
+    return;
+}
+void GetDerCaCert(OicSecCert_t * crt)
+{
+    OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
+    VERIFY_NON_NULL(TAG, crt, ERROR);
+    if (NULL == gCred)
+    {
+        VERIFY_SUCCESS(TAG, OC_STACK_OK == InitCredResource(), ERROR);
+    }
+
+    OicUuid_t  subject;
+    OCStackResult ret = ConvertStrToUuid(CA_SUBJECT_ID, &subject);
+    VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
+
+    OicSecCred_t * cred  = GetCredResourceData(&subject);
+    VERIFY_NON_NULL(TAG, cred, ERROR);
+
+    INIT_BYTE_ARRAY(*crt);
+    crt->data = (uint8_t *) OICCalloc(1, cred->publicData.len);
+    VERIFY_NON_NULL(TAG, cred, ERROR);
+
+    memcpy(crt->data, cred->publicData.data, cred->publicData.len);
+    crt->len = cred->publicData.len;
+
+exit:
+    OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
+}
+void GetDerKey(ByteArray * key)
+{
+    key->data = OICMalloc(sizeof(ca_key));
+    memcpy(key->data, ca_key, sizeof(ca_key));
+    key->len = sizeof(ca_key);
+    return;
+}
+#endif
index aa4252c..a8b4fd8 100644 (file)
 #include "doxmresource.h"
 #include "ocpayload.h"
 #include "oic_malloc.h"
-#ifdef __WITH_X509__
 #include "crlresource.h"
 #include "crl.h"
-#endif /* __WITH_X509__ */
 
 #define TAG  "SRM-CRL"
 
index e9e515f..e7ef882 100644 (file)
@@ -245,12 +245,16 @@ bool DPGenerateQuery(bool isSecure,
 \r
     static char QPREFIX_COAP[] =  "coap://";\r
     static char QPREFIX_COAPS[] = "coaps://";\r
+    static char QPREFIX_COAP_TCP[] =  "coap+tcp://";\r
+    static char QPREFIX_COAPS_TCP[] = "coaps+tcp://";\r
 \r
     int snRet = 0;\r
     char* prefix = (isSecure == true) ? QPREFIX_COAPS : QPREFIX_COAP;\r
 \r
     switch(connType & CT_MASK_ADAPTER)\r
     {\r
+        case CT_ADAPTER_TCP:\r
+            prefix = (isSecure == true) ? QPREFIX_COAPS_TCP : QPREFIX_COAP_TCP;\r
         case CT_ADAPTER_IP:\r
             switch(connType & CT_MASK_FLAGS & ~CT_FLAG_SECURE)\r
             {\r
@@ -374,7 +378,7 @@ static OCStackApplicationResult DirectPairingFinalizeHandler(void *ctx, OCDoHand
                 OIC_LOG(INFO, TAG, "Fail to close temporary dtls session");\r
             }\r
 \r
-            caResult = CASelectCipherSuite(TLS_NULL_WITH_NULL_NULL);\r
+            caResult = CASelectCipherSuite(TLS_NULL_WITH_NULL_NULL, CA_ADAPTER_IP);\r
             if(CA_STATUS_OK != caResult)\r
             {\r
                 OIC_LOG(ERROR, TAG, "Failed to select TLS_NULL_WITH_NULL_NULL");\r
@@ -614,7 +618,7 @@ static OCStackApplicationResult DirectPairingHandler(void *ctx, OCDoHandle UNUSE
             caresult = CAEnableAnonECDHCipherSuite(false);\r
             VERIFY_SUCCESS(TAG, CA_STATUS_OK == caresult, ERROR);\r
 \r
-            caresult = CASelectCipherSuite(TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256);\r
+            caresult = CASelectCipherSuite(TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256, CA_ADAPTER_IP);\r
             VERIFY_SUCCESS(TAG, CA_STATUS_OK == caresult, ERROR);\r
 \r
             //Register proceeding peer info. & DTLS event handler to catch the dtls event while handshake\r
index 8dd6b1a..ccd98ec 100644 (file)
@@ -797,7 +797,8 @@ static OCEntityHandlerResult HandleDoxmPostRequest(const OCEntityHandlerRequest
 
 #ifdef __WITH_X509__
 #define TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 0xC0AE
-                        CASelectCipherSuite(TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8);
+                        CASelectCipherSuite(TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8,
+                                            ehRequest->devAddr.adapter);
 #endif //__WITH_X509__
 #endif //__WITH_DTLS__
                     }
@@ -830,12 +831,14 @@ static OCEntityHandlerResult HandleDoxmPostRequest(const OCEntityHandlerRequest
                         VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
                         OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED");
 
-                        caRes = CASelectCipherSuite(TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256);
+                        caRes = CASelectCipherSuite(TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256,
+                                                    ehRequest->devAddr.adapter);
                         VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
 
-                        if(previousMsgId != ehRequest->messageID)
+                        char ranPin[OXM_RANDOM_PIN_SIZE + 1] = {0,};
+                         //TODO ehRequest->messageID for copa over TCP always is null. Find reason why.
+                        if(ehRequest->devAddr.adapter == OC_ADAPTER_IP && previousMsgId != ehRequest->messageID)
                         {
-                            char ranPin[OXM_RANDOM_PIN_SIZE + 1] = {0,};
                             if(OC_STACK_OK == GeneratePin(ranPin, OXM_RANDOM_PIN_SIZE + 1))
                             {
                                 //Set the device id to derive temporal PSK
@@ -856,6 +859,31 @@ static OCEntityHandlerResult HandleDoxmPostRequest(const OCEntityHandlerRequest
                                 ehRet = OC_EH_ERROR;
                             }
                         }
+                        else
+                        {
+                            if(OC_STACK_OK == GeneratePin(ranPin, OXM_RANDOM_PIN_SIZE + 1))
+                            {
+                                //Set the device id to derive temporal PSK
+                                SetUuidForRandomPinOxm(&gDoxm->deviceID);
+
+                                /**
+                                 * Since PSK will be used directly by DTLS layer while PIN based ownership transfer,
+                                 * Credential should not be saved into SVR.
+                                 * For this reason, use a temporary get_psk_info callback to random PIN OxM.
+                                 */
+#ifdef __WITH_TLS__
+                                caRes = CAregisterTlsCredentialsHandler(GetDtlsPskForRandomPinOxm);
+#endif
+                                VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
+                                ehRet = OC_EH_OK;
+                            }
+                            else
+                            {
+                                OIC_LOG(ERROR, TAG, "Failed to generate random PIN");
+                                ehRet = OC_EH_ERROR;
+                            }
+
+                        }
 #endif //__WITH_DTLS__
                     }
                     else
index 5f244c8..820021a 100644 (file)
@@ -460,7 +460,7 @@ static OCEntityHandlerResult HandleDpairingPostRequest (const OCEntityHandlerReq
 
             // Prepare to establish a secure channel with Pin-based PSK cipher suite
             if (CA_STATUS_OK != CAEnableAnonECDHCipherSuite(false) ||
-                CA_STATUS_OK != CASelectCipherSuite(TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256))
+                CA_STATUS_OK != CASelectCipherSuite(TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256, CA_ADAPTER_IP))
             {
                 OIC_LOG_V(ERROR, TAG, "Failed to select TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256");
                 goto exit;
index 9806813..c39d463 100644 (file)
@@ -286,7 +286,7 @@ OCStackResult SRMRegisterHandler(CARequestCallback reqHandler,
     gErrorHandler = errHandler;
 
 
-#if defined(__WITH_DTLS__)
+#if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
     CARegisterHandler(SRMRequestHandler, SRMResponseHandler, SRMErrorHandler);
 #else
     CARegisterHandler(reqHandler, respHandler, errHandler);
@@ -323,8 +323,15 @@ OCStackResult SRMInitSecureResources()
         OIC_LOG(ERROR, TAG, "Failed to revert DTLS credential handler.");
         ret = OC_STACK_ERROR;
     }
-
-#endif // (__WITH_DTLS__)
+#endif
+#ifdef __WITH_TLS__
+    if(CA_STATUS_OK != CAregisterTlsCredentialsHandler(GetDtlsPskCredentials))
+    {
+        OIC_LOG(ERROR, TAG, "Failed to revert TLS credential handler.");
+        ret = OC_STACK_ERROR;
+    }
+    CAregisterPkixInfoHandler(GetPkixInfo);
+#endif
 #if defined(__WITH_X509__)
     CARegisterDTLSX509CredentialsHandler(GetDtlsX509Credentials);
     CARegisterDTLSCrlHandler(GetDerCrl);
index 9bb9569..6c3c995 100644 (file)
@@ -32,6 +32,7 @@ tools_env.PrependUnique(CPPPATH = ['../../../../extlibs/cjson',
                                   '../../logger/include',
                                   '../../../oc_logger/include',
                                   '../../connectivity/api',
+                                  '../../connectivity/inc/pkix',
                                   '../include',
                                   '../include/internal',
                                   '../../connectivity/lib/libcoap-4.1.1',
index 2f273cb..3e4c594 100644 (file)
@@ -33,6 +33,7 @@ target_os = srmtest_env.get('TARGET_OS')
 srmtest_env.PrependUnique(CPPPATH = [
                '../../../c_common/oic_malloc/include',
                '../../connectivity/inc',
+               '../../connectivity/inc/pkix',
                '../../connectivity/api',
                '../../connectivity/external/inc',
                '../../connectivity/lib/libcoap-4.1.1',
@@ -55,6 +56,9 @@ srmtest_env.PrependUnique(LIBS = ['ocsrm',
 
 if srmtest_env.get('SECURED') == '1':
     srmtest_env.AppendUnique(LIBS = ['tinydtls', 'timer'])
+    
+if srmtest_env.get('WITH_TCP') == True:
+               srmtest_env.AppendUnique(LIBS = ['mbedtls', 'mbedx509','mbedcrypto'])
 
 if srmtest_env.get('LOGGING') == '1':
        srmtest_env.AppendUnique(CPPDEFINES = ['TB_LOG'])
index 39fb08e..8f9d6fd 100644 (file)
@@ -48,7 +48,10 @@ else:
        samples_env.PrependUnique(LIBS = ['m'])
 samples_env.PrependUnique(LIBS = ['octbstack', 'connectivity_abstraction', 'coap'])
 if env.get('SECURED') == '1':
-    samples_env.AppendUnique(LIBS = ['tinydtls'])
+       samples_env.AppendUnique(LIBS = ['tinydtls'])
+       if env.get('WITH_TCP') == True:
+               samples_env.AppendUnique(LIBS = ['mbedtls', 'mbedx509','mbedcrypto'])
+
 
 if target_os == 'android':
        samples_env.AppendUnique(CXXFLAGS = ['-frtti', '-fexceptions'])
index 9eca9ab..714d075 100644 (file)
@@ -49,6 +49,7 @@ static int UnicastDiscovery = 0;
 static int TestCase = 0;
 static int ConnType = 0;
 static int DevOwner = 0;
+static int WithTcp = 0;
 
 static char DISCOVERY_QUERY[] = "%s/oic/res";
 OCConnectivityType discoveryReqConnType = CT_ADAPTER_IP;
@@ -105,6 +106,8 @@ static void PrintUsage()
     OIC_LOG(INFO, TAG, "-c 1 : IP Connectivity Type");
     OIC_LOG(INFO, TAG, "-d 0 : Client as Non Device Owner");
     OIC_LOG(INFO, TAG, "-d 1 : Client as Device Owner");
+    OIC_LOG(INFO, TAG, "-p 0 : Use UDP protocol");
+    OIC_LOG(INFO, TAG, "-p 1 : Use TCP protocol");
 }
 
 OCStackResult InvokeOCDoResource(std::ostringstream &query,
@@ -222,6 +225,10 @@ int InitPutRequest(OCQualityOfService qos)
     OIC_LOG_V(INFO, TAG, "Executing %s", __func__);
     std::ostringstream query;
     query << coapServerResource;
+    if(WithTcp)
+    {
+        endpoint.adapter = OC_ADAPTER_TCP;
+    }
     endpoint.flags = (OCTransportFlags)(endpoint.flags|OC_SECURE);
     return (InvokeOCDoResource(query, OC_REST_PUT, &endpoint,
             ((qos == OC_HIGH_QOS) ? OC_HIGH_QOS: OC_LOW_QOS), putReqCB, NULL, 0));
@@ -333,7 +340,7 @@ int main(int argc, char* argv[])
     struct timespec timeout;
     OCPersistentStorage ps;
 
-    while ((opt = getopt(argc, argv, "u:t:c:d:")) != -1)
+    while ((opt = getopt(argc, argv, "u:t:c:d:p:")) != -1)
     {
         switch(opt)
         {
@@ -349,6 +356,16 @@ int main(int argc, char* argv[])
             case 'd':
                 DevOwner = atoi(optarg);
                 break;
+            case 'p':
+            {
+                WithTcp = atoi(optarg);
+                if(WithTcp > 1)
+                {
+                    PrintUsage();
+                    return -1;
+                }
+            }
+                break;
             default:
                 PrintUsage();
                 return -1;
@@ -443,8 +460,18 @@ int parseClientResponse(OCClientResponse * clientResponse)
         }
         if (res->secure)
         {
-            OIC_LOG_V(INFO,TAG,"SECUREPORT: %d",res->port);
-            endpoint.port = res->port;
+            if(WithTcp)
+            {
+#ifdef TCP_ADAPTER
+                OIC_LOG_V(INFO,TAG,"SECUREPORT tcp: %d",res->tcpPort);
+                endpoint.port = res->tcpPort;
+#endif
+            }
+            else
+            {
+                OIC_LOG_V(INFO,TAG,"SECUREPORT udp: %d",res->port);
+                endpoint.port = res->port;
+            }
             coapSecureResource = 1;
         }
 
index b62199f..88e5677 100644 (file)
@@ -138,6 +138,7 @@ static bool gRASetInfo = false;
 OCDeviceEntityHandler defaultDeviceHandler;
 void* defaultDeviceHandlerCallbackParameter = NULL;
 static const char COAP_TCP[] = "coap+tcp:";
+static const char COAPS_TCP[] = "coaps+tcp:";
 static const char CORESPEC[] = "core";
 
 //-----------------------------------------------------------------------------
@@ -2361,6 +2362,8 @@ CAMessageType_t qualityOfServiceToMessageType(OCQualityOfService qos)
  *  optionally one of
  *      CoAP over UDP prefix    "coap://"
  *      CoAP over TCP prefix    "coap+tcp://"
+ *      CoAP over DTLS prefix   "coaps://"
+ *      CoAP over TLS prefix    "coaps+tcp://"
  *  optionally one of
  *      IPv6 address            "[1234::5678]"
  *      IPv4 address            "192.168.1.1"
@@ -2415,7 +2418,8 @@ static OCStackResult ParseRequestUri(const char *fullUri,
     bool istcp = false;
     if (prefixLen)
     {
-        if ((prefixLen == sizeof(COAP_TCP) - 1) && (!strncmp(fullUri, COAP_TCP, prefixLen)))
+        if (((prefixLen == sizeof(COAP_TCP) - 1) && (!strncmp(fullUri, COAP_TCP, prefixLen)))
+        || ((prefixLen == sizeof(COAPS_TCP) - 1) && (!strncmp(fullUri, COAPS_TCP, prefixLen))))
         {
             istcp = true;
         }
@@ -2510,7 +2514,7 @@ static OCStackResult ParseRequestUri(const char *fullUri,
         da->port = port;
         da->adapter = adapter;
         da->flags = flags;
-        if (!strncmp(fullUri, "coaps:", 6))
+        if (!strncmp(fullUri, "coaps", 5))
         {
             da->flags = (OCTransportFlags)(da->flags|CA_SECURE);
         }
index e759fe8..82e6ab3 100644 (file)
@@ -37,6 +37,7 @@ stacktest_env.PrependUnique(CPPPATH = [
                '../../stack/include',
                '../../stack/include/internal',
                '../../connectivity/api',
+               '../../connectivity/inc/pkix',
                '../../connectivity/external/inc',
                '../../extlibs/cjson',
                '../../../oc_logger/include',
@@ -51,7 +52,9 @@ if target_os != 'darwin':
     stacktest_env.PrependUnique(LIBS = ['oc_logger'])
 
 if stacktest_env.get('SECURED') == '1':
-    stacktest_env.AppendUnique(LIBS = ['tinydtls'])
+       stacktest_env.AppendUnique(LIBS = ['tinydtls'])
+       if stacktest_env.get('WITH_TCP') == True:
+               stacktest_env.AppendUnique(LIBS = ['mbedtls', 'mbedx509','mbedcrypto'])
 
 if stacktest_env.get('LOGGING'):
        stacktest_env.AppendUnique(CPPDEFINES = ['TB_LOG'])
index dbc895c..2151b29 100644 (file)
@@ -31,6 +31,9 @@ csdktest_env.PrependUnique(CPPPATH = [
 csdktest_env.PrependUnique(LIBS = [
     'octbstack',
 ])
+if env.get('SECURED') == '1':
+       if env.get('WITH_TCP') == True:
+               csdktest_env.AppendUnique(LIBS = ['mbedtls', 'mbedx509','mbedcrypto'])
 
 csdktest_env.AppendUnique(LIBPATH = [
     csdktest_env.get('BUILD_DIR'),
index a6f7d31..d8cf349 100644 (file)
@@ -32,6 +32,7 @@ ocprovision_env.AppendUnique(CPPPATH = [
                '../oc_logger/include',
                '../csdk/connectivity/api',
                '../csdk/security/include',
+               '../csdk/connectivity/inc/pkix',
                '../csdk/security/provisioning/include',
                '../csdk/security/provisioning/include/oxm',
                '../csdk/security/provisioning/include/internal',
index 38593ae..09f2057 100644 (file)
@@ -42,6 +42,7 @@ examples_env.AppendUnique(CPPPATH = [
         '../../csdk/logger/include',
         '../../oc_logger/include',
         '../../csdk/connectivity/api',
+        '../../csdk/connectivity/inc/pkix',
         '../../csdk/security/include',
         '../../csdk/security/include/internal',
         '../../csdk/security/provisioning/include',
index 5e335a1..e40ca11 100755 (executable)
@@ -42,6 +42,7 @@ provisiontests_env.PrependUnique(CPPPATH = [
                '../../csdk/security/provisioning/include/internal',
                '../../csdk/stack/include/internal',
                '../../csdk/connectivity/api',
+               '../../csdk/connectivity/inc/pkix',
                '../../csdk/connectivity/external/inc',
                '../../csdk/ocsocket/include',
                '../../csdk/ocrandom/include',
@@ -71,8 +72,11 @@ else :
                provisiontests_env.AppendUnique(LIBS = ['ra_xmpp'])
 
 if provisiontests_env.get('SECURED') == '1':
-    provisiontests_env.AppendUnique(LIBS = ['tinydtls'])
-    provisiontests_env.AppendUnique(LIBS = ['timer'])
+       provisiontests_env.AppendUnique(LIBS = ['tinydtls'])
+       provisiontests_env.AppendUnique(LIBS = ['timer'])
+       if provisiontests_env.get('WITH_TCP') == True:
+               provisiontests_env.AppendUnique(LIBS = ['mbedtls', 'mbedx509','mbedcrypto'])
+
 if provisiontests_env.get('DTLS_WITH_X509') == '1':
        provisiontests_env.AppendUnique(LIBS = ['CKManager'])
        provisiontests_env.AppendUnique(LIBS = ['asn1'])
index e11ff13..dc9907f 100644 (file)
@@ -57,6 +57,8 @@ unittests_env.PrependUnique(LIBS = [
 
 if unittests_env.get('SECURED') == '1':
        unittests_env.AppendUnique(LIBS = ['tinydtls'])
+       if unittests_env.get('WITH_TCP') == True:
+               unittests_env.AppendUnique(LIBS = ['mbedtls', 'mbedx509','mbedcrypto'])
 
 if unittests_env.get('LOGGING'):
        unittests_env.AppendUnique(CPPDEFINES = ['TB_LOG'])