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