--- /dev/null
+#******************************************************************
+#
+# 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)
+
+
+
--- /dev/null
+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 */
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'])
'connectivity/lib/libcoap-4.1.1',
'connectivity/common/inc',
'connectivity/inc',
+ 'connectivity/inc/pkix',
'connectivity/api',
'connectivity/external/inc',
'security/include',
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'])
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;
/**
#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
* 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.
#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
* @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.
#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" */
--- /dev/null
+/* *****************************************************************
+ *
+ * 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_ */
+
+
#endif /* CA_ADAPTER_INTERFACE_H_ */
+
{
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;
/**
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')])
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':
--- /dev/null
+/******************************************************************
+ *
+ * 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;
+}
#ifdef TCP_ADAPTER
#include "catcpadapter.h"
+#ifdef __WITH_TLS__
+#include "ca_adapter_net_tls.h"
+#endif
#endif
CAGlobals_t caglobals = { .clientFlags = 0,
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);
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)
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,
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);
#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.
}
}
+#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)
{
CATCPSetPacketReceiveCallback(CATCPPacketReceivedCB);
CATCPSetErrorHandler(CATCPErrorHandler);
+#ifdef __WITH_TLS__
+ CAinitTlsAdapter();
+ CAsetTlsAdapterCallbacks(CATCPPacketReceivedCB, CATCPPacketSendCB, 0);
+#endif
+
CAConnectivityHandler_t tcpHandler = {
.startAdapter = CAStartTCP,
.startListenServer = CAStartTCPListeningServer,
//Re-initializing the Globals to start them again
CAInitializeTCPGlobals();
+#ifdef __WITH_TLS__
+ CAdeinitTlsAdapter();
+#endif
+
return CA_STATUS_OK;
}
}
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);
}
#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.
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)
}
}
+#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.
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;
}
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)
{
}
}
- // #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
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)
{
shutdown(svritem->fd, SHUT_RDWR);
close(svritem->fd);
- OICFree(svritem->recvData);
+
+ OICFree(svritem->data);
+ svritem->data = NULL;
}
}
u_arraylist_destroy(caglobals.tcp.svrlist);
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;
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'])
'../connectivity/lib/libcoap-4.1.1',
'../connectivity/external/inc',
'../connectivity/common/inc',
+ '../connectivity/inc/pkix',
'../connectivity/inc',
'../connectivity/api',
'../security/include',
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
* @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.
*/
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
#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"
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.
//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
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
'../../../../extlibs/cjson/',
'../../../../extlibs/tinydtls/',
'../../connectivity/inc',
+ '../../connectivity/inc/pkix',
'../../connectivity/external/inc',
'../../connectivity/common/inc',
'../../connectivity/lib/libcoap-4.1.1',
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. **/
#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.
'../../../../../extlibs/cjson',
'../../../../../extlibs/base64',
'../../../connectivity/inc',
+ '../../../connectivity/inc/pkix',
'../../../connectivity/common/inc',
'../../../connectivity/lib/libcoap-4.1.1',
'../../../connectivity/api'
#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
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);
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;
}
// 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;
}
// 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;
}
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");
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");
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:
//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.");
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))
//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");
* 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");
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)
{
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;
}
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");
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;
}
* 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.");
}
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");
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.");
* 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));
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)
*
* @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);
ptr->securePort = securePort;
+#ifdef __WITH_TLS__
+ ptr->tcpPort = tcpPort;
+#endif
+
return OC_STACK_OK;
}
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)
{
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.");
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)
{
//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;
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)
'../../../../../extlibs/cjson',
'../../../../../extlibs/base64',
'../../../connectivity/inc',
+ '../../../connectivity/inc/pkix',
'../../../connectivity/common/inc',
'../../../connectivity/lib/libcoap-4.1.1',
'../../../connectivity/api',
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'])
#endif
//Clean PublicData
-#ifdef __WITH_X509__
+#if defined(__WITH_X509__) || defined(WITH_TLS)
OICFree(cred->publicData.data);
#endif
return OC_STACK_OK;
}
-#ifdef __WITH_DTLS__
+#if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
/**
* Internal function to fill private data of owner PSK.
*
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)
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.");
}
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;
return result;
}
-const OicSecCred_t* GetCredResourceData(const OicUuid_t* subject)
+OicSecCred_t* GetCredResourceData(const OicUuid_t* subject)
{
OicSecCred_t *cred = NULL;
}
-#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)
}
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
#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"
\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
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
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
#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__
}
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
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
// 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;
gErrorHandler = errHandler;
-#if defined(__WITH_DTLS__)
+#if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
CARegisterHandler(SRMRequestHandler, SRMResponseHandler, SRMErrorHandler);
#else
CARegisterHandler(reqHandler, respHandler, errHandler);
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);
'../../logger/include',
'../../../oc_logger/include',
'../../connectivity/api',
+ '../../connectivity/inc/pkix',
'../include',
'../include/internal',
'../../connectivity/lib/libcoap-4.1.1',
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',
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'])
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'])
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;
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,
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));
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)
{
case 'd':
DevOwner = atoi(optarg);
break;
+ case 'p':
+ {
+ WithTcp = atoi(optarg);
+ if(WithTcp > 1)
+ {
+ PrintUsage();
+ return -1;
+ }
+ }
+ break;
default:
PrintUsage();
return -1;
}
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;
}
OCDeviceEntityHandler defaultDeviceHandler;
void* defaultDeviceHandlerCallbackParameter = NULL;
static const char COAP_TCP[] = "coap+tcp:";
+static const char COAPS_TCP[] = "coaps+tcp:";
static const char CORESPEC[] = "core";
//-----------------------------------------------------------------------------
* 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"
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;
}
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);
}
'../../stack/include',
'../../stack/include/internal',
'../../connectivity/api',
+ '../../connectivity/inc/pkix',
'../../connectivity/external/inc',
'../../extlibs/cjson',
'../../../oc_logger/include',
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'])
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'),
'../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',
'../../csdk/logger/include',
'../../oc_logger/include',
'../../csdk/connectivity/api',
+ '../../csdk/connectivity/inc/pkix',
'../../csdk/security/include',
'../../csdk/security/include/internal',
'../../csdk/security/provisioning/include',
'../../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',
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'])
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'])