Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: FXAS21002 FXOS8700Q
m2mconnectionsecuritypimpl.cpp
00001 /* 00002 * Copyright (c) 2015 - 2017 ARM Limited. All rights reserved. 00003 * SPDX-License-Identifier: Apache-2.0 00004 * Licensed under the Apache License, Version 2.0 (the License); you may 00005 * not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an AS IS BASIS, WITHOUT 00012 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00017 // Needed for PRIu64 on FreeRTOS 00018 #include <stdio.h> 00019 // Note: this macro is needed on armcc to get the the limit macros like UINT16_MAX 00020 #ifndef __STDC_LIMIT_MACROS 00021 #define __STDC_LIMIT_MACROS 00022 #endif 00023 00024 // Note: this macro is needed on armcc to get the the PRI*32 macros 00025 // from inttypes.h in a C++ code. 00026 #ifndef __STDC_FORMAT_MACROS 00027 #define __STDC_FORMAT_MACROS 00028 #endif 00029 00030 #include "mbed-client/m2mconnectionhandler.h" 00031 #include "mbed-client-mbedtls/m2mconnectionsecuritypimpl.h" 00032 #include "mbed-client/m2msecurity.h" 00033 #include "mbed-trace/mbed_trace.h" 00034 #include "mbed-client/m2mconstants.h" 00035 #include "pal.h" 00036 #include "m2mdevice.h" 00037 #include "m2minterfacefactory.h" 00038 #include <string.h> 00039 00040 #define TRACE_GROUP "mClt" 00041 00042 M2MConnectionSecurityPimpl::M2MConnectionSecurityPimpl(M2MConnectionSecurity::SecurityMode mode) 00043 :_init_done(M2MConnectionSecurityPimpl::INIT_NOT_STARTED), 00044 _conf(0), 00045 _ssl(0), 00046 _sec_mode(mode) 00047 { 00048 memset(&_entropy, 0, sizeof(entropy_cb)); 00049 memset(&_tls_socket, 0, sizeof(palTLSSocket_t)); 00050 } 00051 00052 M2MConnectionSecurityPimpl::~M2MConnectionSecurityPimpl() 00053 { 00054 if(_ssl) { 00055 pal_freeTLS(&_ssl); 00056 } 00057 if(_conf) { 00058 pal_tlsConfigurationFree(&_conf); 00059 } 00060 } 00061 00062 void M2MConnectionSecurityPimpl::reset() 00063 { 00064 if(_ssl) { 00065 pal_freeTLS(&_ssl); 00066 } 00067 if(_conf) { 00068 pal_tlsConfigurationFree(&_conf); 00069 } 00070 _init_done = M2MConnectionSecurityPimpl::INIT_NOT_STARTED; 00071 } 00072 00073 int M2MConnectionSecurityPimpl::init(const M2MSecurity *security, uint16_t security_instance_id) 00074 { 00075 tr_debug("M2MConnectionSecurityPimpl::init"); 00076 00077 if (!security){ 00078 tr_error("M2MConnectionSecurityPimpl::init - security null"); 00079 return M2MConnectionHandler::ERROR_GENERIC; 00080 } 00081 00082 if (_entropy.entropy_source_ptr) { 00083 if (PAL_SUCCESS != pal_addEntropySource(_entropy.entropy_source_ptr)) { 00084 return M2MConnectionHandler::ERROR_GENERIC; 00085 } 00086 } 00087 00088 palTLSTransportMode_t mode = PAL_DTLS_MODE; 00089 if (_sec_mode == M2MConnectionSecurity::TLS) { 00090 mode = PAL_TLS_MODE; 00091 } 00092 00093 if (PAL_SUCCESS != pal_initTLSConfiguration(&_conf, mode)) { 00094 tr_error("M2MConnectionSecurityPimpl::init - pal_initTLSConfiguration failed"); 00095 return M2MConnectionHandler::ERROR_GENERIC; 00096 } 00097 00098 _init_done = M2MConnectionSecurityPimpl::INIT_CONFIGURING; 00099 00100 00101 if (_sec_mode == M2MConnectionSecurity::DTLS) { 00102 // PAL divides the defined MAX_TIMEOUT by 2 00103 pal_setHandShakeTimeOut(_conf, MBED_CLIENT_DTLS_PEER_MAX_TIMEOUT*2); 00104 } 00105 00106 M2MSecurity::SecurityModeType cert_mode = 00107 (M2MSecurity::SecurityModeType)security->resource_value_int(M2MSecurity::SecurityMode, security_instance_id); 00108 00109 if (cert_mode == M2MSecurity::Certificate || cert_mode == M2MSecurity::EST ) { 00110 00111 palX509_t owncert; 00112 palPrivateKey_t privateKey; 00113 palX509_t caChain; 00114 00115 uint8_t certificate[MAX_CERTIFICATE_SIZE]; 00116 uint8_t *certificate_ptr = (uint8_t *)&certificate; 00117 00118 caChain.size = MAX_CERTIFICATE_SIZE; 00119 int ret_code = security->resource_value_buffer(M2MSecurity::ServerPublicKey, certificate_ptr, security_instance_id, (size_t*)&caChain.size); 00120 caChain.buffer = certificate_ptr; 00121 00122 if (ret_code < 0) { 00123 tr_error("M2MConnectionSecurityPimpl::init - failed to read public key"); 00124 return M2MConnectionHandler::FAILED_TO_READ_CREDENTIALS; 00125 } 00126 00127 if (PAL_SUCCESS != pal_setCAChain(_conf, &caChain, NULL)) { 00128 tr_error("M2MConnectionSecurityPimpl::init - pal_setCAChain failed"); 00129 return M2MConnectionHandler::ERROR_GENERIC; 00130 } 00131 00132 privateKey.size = MAX_CERTIFICATE_SIZE; 00133 ret_code = security->resource_value_buffer(M2MSecurity::Secretkey, certificate_ptr, security_instance_id, (size_t*)&privateKey.size); 00134 privateKey.buffer = certificate_ptr; 00135 00136 if (ret_code < 0) { 00137 tr_error("M2MConnectionSecurityPimpl::init - failed to read secret key"); 00138 return M2MConnectionHandler::FAILED_TO_READ_CREDENTIALS; 00139 } 00140 00141 if (PAL_SUCCESS != pal_setOwnPrivateKey(_conf, &privateKey)) { 00142 tr_error("M2MConnectionSecurityPimpl::init - pal_setOwnPrivateKey failed"); 00143 return M2MConnectionHandler::ERROR_GENERIC; 00144 } 00145 00146 void *dummy; 00147 00148 // Open certificate chain, size parameter contains the depth of certificate chain 00149 size_t cert_chain_size = 0; 00150 if (security->resource_value_buffer(M2MSecurity::OpenCertificateChain, (uint8_t *&)dummy, security_instance_id, &cert_chain_size) < 0) { 00151 tr_error("M2MConnectionSecurityPimpl::init - fail to open certificate chain!"); 00152 return M2MConnectionHandler::FAILED_TO_READ_CREDENTIALS; 00153 } else if (cert_chain_size == 0) { 00154 tr_error("M2MConnectionSecurityPimpl::init - no certificate!"); 00155 security->resource_value_buffer(M2MSecurity::CloseCertificateChain, (uint8_t *&)dummy, security_instance_id, &cert_chain_size); 00156 return M2MConnectionHandler::ERROR_GENERIC; 00157 } else { 00158 tr_info("M2MConnectionSecurityPimpl::init - cert chain length: %lu", (unsigned long)cert_chain_size); 00159 size_t index = 0; 00160 00161 while (index < cert_chain_size) { 00162 owncert.size = MAX_CERTIFICATE_SIZE; 00163 ret_code = security->resource_value_buffer(M2MSecurity::ReadDeviceCertificateChain, certificate_ptr, security_instance_id, (size_t*)&owncert.size); 00164 owncert.buffer = certificate_ptr; 00165 00166 if (ret_code < 0) { 00167 tr_error("M2MConnectionSecurityPimpl::init - failed to read device certificate"); 00168 return M2MConnectionHandler::FAILED_TO_READ_CREDENTIALS; 00169 } 00170 00171 if (PAL_SUCCESS != pal_setOwnCertChain(_conf, &owncert)) { 00172 tr_error("M2MConnectionSecurityPimpl::init - pal_setOwnCertChain failed"); 00173 security->resource_value_buffer(M2MSecurity::CloseCertificateChain, (uint8_t *&)dummy, security_instance_id, &cert_chain_size); 00174 return M2MConnectionHandler::ERROR_GENERIC; 00175 } 00176 00177 index++; 00178 } 00179 security->resource_value_buffer(M2MSecurity::CloseCertificateChain, (uint8_t *&)dummy, security_instance_id, &cert_chain_size); 00180 } 00181 00182 } else if (cert_mode == M2MSecurity::Psk) { 00183 00184 uint8_t identity[MAX_CERTIFICATE_SIZE]; 00185 uint8_t *identity_ptr = (uint8_t *)&identity; 00186 uint32_t identity_len = 0; 00187 uint8_t psk[MAX_CERTIFICATE_SIZE]; 00188 uint8_t *psk_ptr = (uint8_t *)&psk; 00189 uint32_t psk_len = 0; 00190 00191 int ret_code = security->resource_value_buffer(M2MSecurity::PublicKey, identity_ptr, security_instance_id, (size_t*)&identity_len); 00192 if (ret_code < 0) { 00193 tr_error("M2MConnectionSecurityPimpl::init - failed to read PSK identity"); 00194 return M2MConnectionHandler::ERROR_GENERIC; 00195 } 00196 00197 ret_code = security->resource_value_buffer(M2MSecurity::Secretkey, psk_ptr, security_instance_id, (size_t*)&psk_len); 00198 if (ret_code < 0) { 00199 tr_error("M2MConnectionSecurityPimpl::init - failed to read PSK key"); 00200 return M2MConnectionHandler::ERROR_GENERIC;; 00201 } 00202 00203 palStatus_t ret = pal_setPSK(_conf, identity_ptr, identity_len, psk_ptr, psk_len); 00204 00205 if (PAL_SUCCESS != ret) { 00206 tr_error("M2MConnectionSecurityPimpl::init - pal_setPSK failed"); 00207 return M2MConnectionHandler::ERROR_GENERIC;; 00208 } 00209 00210 } else { 00211 tr_error("M2MConnectionSecurityPimpl::init - security mode not set"); 00212 return M2MConnectionHandler::ERROR_GENERIC; 00213 } 00214 00215 if (PAL_SUCCESS != pal_initTLS(_conf, &_ssl)) { 00216 tr_error("M2MConnectionSecurityPimpl::init - pal_initTLS failed"); 00217 return M2MConnectionHandler::ERROR_GENERIC; 00218 } 00219 00220 if (PAL_SUCCESS != pal_tlsSetSocket(_conf, &_tls_socket)) { 00221 tr_error("M2MConnectionSecurityPimpl::init - pal_tlsSetSocket failed"); 00222 return M2MConnectionHandler::ERROR_GENERIC; 00223 } 00224 00225 _init_done = M2MConnectionSecurityPimpl::INIT_DONE; 00226 00227 #if MBED_CONF_MBED_TRACE_ENABLE 00228 // Note: This call is not enough, one also needs the MBEDTLS_DEBUG_C to be defined globally 00229 // on build and if using default mbedtls configuration file, the 00230 // "#undef MBEDTLS_DEBUG_C" -line needs to be removed from mbedtls_mbed_client_config.h 00231 pal_sslSetDebugging(_conf, 1); 00232 #endif 00233 00234 return M2MConnectionHandler::ERROR_NONE; 00235 } 00236 00237 int M2MConnectionSecurityPimpl::start_handshake() 00238 { 00239 tr_debug("M2MConnectionSecurityPimpl::start_handshake"); 00240 00241 palStatus_t ret; 00242 00243 ret = pal_handShake(_ssl, _conf); 00244 00245 if (ret == PAL_ERR_TLS_WANT_READ || ret == PAL_ERR_TLS_WANT_WRITE || ret == PAL_ERR_TIMEOUT_EXPIRED ){ 00246 return M2MConnectionHandler::CONNECTION_ERROR_WANTS_READ; 00247 } 00248 else if (ret == PAL_ERR_TLS_PEER_CLOSE_NOTIFY) { 00249 return M2MConnectionHandler::SSL_PEER_CLOSE_NOTIFY; 00250 } 00251 else if (ret == PAL_ERR_NO_MEMORY ) { 00252 return M2MConnectionHandler::MEMORY_ALLOCATION_FAILED; 00253 } 00254 00255 if (ret != PAL_SUCCESS){ //We loose the original error here! 00256 tr_error("M2MConnectionScurityPimpl::start_handshake pal_handShake() error %" PRIx32, ret); 00257 return M2MConnectionHandler::ERROR_GENERIC; 00258 } 00259 00260 ret = pal_sslGetVerifyResult(_ssl); 00261 if (PAL_SUCCESS != ret){ 00262 tr_error("M2MConnectionSecurityPimpl::start_handshake pal_sslGetVerifyResult() error %" PRIx32, ret); 00263 return M2MConnectionHandler::ERROR_GENERIC; 00264 } 00265 00266 return ret; 00267 } 00268 00269 int M2MConnectionSecurityPimpl::connect(M2MConnectionHandler* connHandler) 00270 { 00271 tr_debug("M2MConnectionSecurityPimpl::connect"); 00272 int ret = M2MConnectionHandler::ERROR_GENERIC; 00273 00274 if (M2MConnectionSecurityPimpl::INIT_DONE != _init_done){ 00275 return ret; 00276 } 00277 00278 ret = start_handshake(); 00279 tr_debug("M2MConnectionSecurityPimpl::connect - handshake ret: %d", ret); 00280 return ret; 00281 } 00282 00283 00284 int M2MConnectionSecurityPimpl::send_message(unsigned char *message, int len) 00285 { 00286 tr_debug("M2MConnectionSecurityPimpl::send_message"); 00287 int ret = M2MConnectionHandler::ERROR_GENERIC; 00288 palStatus_t return_value; 00289 uint32_t len_write; 00290 00291 if (M2MConnectionSecurityPimpl::INIT_DONE != _init_done){ 00292 return ret; 00293 } 00294 00295 if (PAL_SUCCESS == (return_value = pal_sslWrite(_ssl, message, len, &len_write))){ 00296 ret = (int)len_write; 00297 } 00298 else if (return_value == PAL_ERR_TLS_WANT_READ || return_value == PAL_ERR_TIMEOUT_EXPIRED ){ 00299 ret = M2MConnectionHandler::CONNECTION_ERROR_WANTS_READ; 00300 } 00301 else if (return_value == PAL_ERR_TLS_WANT_WRITE) { 00302 ret = M2MConnectionHandler::CONNECTION_ERROR_WANTS_WRITE; 00303 } 00304 else if (return_value == PAL_ERR_TLS_PEER_CLOSE_NOTIFY) { 00305 ret = M2MConnectionHandler::SSL_PEER_CLOSE_NOTIFY; 00306 } 00307 else if (return_value == PAL_ERR_NO_MEMORY ) { 00308 ret = M2MConnectionHandler::MEMORY_ALLOCATION_FAILED; 00309 } 00310 00311 tr_debug("M2MConnectionSecurityPimpl::send_message - ret: %d", ret); 00312 return ret; //bytes written or error 00313 } 00314 00315 int M2MConnectionSecurityPimpl::read(unsigned char* buffer, uint16_t len) 00316 { 00317 int ret = M2MConnectionHandler::ERROR_GENERIC; 00318 palStatus_t return_value; 00319 uint32_t len_read; 00320 00321 if (M2MConnectionSecurityPimpl::INIT_DONE != _init_done){ 00322 tr_error("M2MConnectionSecurityPimpl::read - init not done!"); 00323 return ret; 00324 } 00325 00326 if (PAL_SUCCESS == (return_value = pal_sslRead(_ssl, buffer, len, &len_read))){ 00327 ret = (int)len_read; 00328 } 00329 else if (return_value == PAL_ERR_TLS_WANT_READ || return_value == PAL_ERR_TLS_WANT_WRITE || return_value == PAL_ERR_TIMEOUT_EXPIRED ){ 00330 ret = M2MConnectionHandler::CONNECTION_ERROR_WANTS_READ; 00331 } 00332 else if (return_value == PAL_ERR_TLS_PEER_CLOSE_NOTIFY) { 00333 ret = M2MConnectionHandler::SSL_PEER_CLOSE_NOTIFY; 00334 } 00335 else if (return_value == PAL_ERR_NO_MEMORY ) { 00336 ret = M2MConnectionHandler::MEMORY_ALLOCATION_FAILED; 00337 } 00338 00339 return ret; 00340 } 00341 00342 void M2MConnectionSecurityPimpl::set_random_number_callback(random_number_cb callback) 00343 { 00344 (void)callback; 00345 } 00346 00347 void M2MConnectionSecurityPimpl::set_entropy_callback(entropy_cb callback) 00348 { 00349 00350 _entropy = callback; 00351 00352 } 00353 00354 void M2MConnectionSecurityPimpl::set_socket(palSocket_t socket, palSocketAddress_t *address) 00355 { 00356 _tls_socket.socket = socket; 00357 _tls_socket.socketAddress = address; 00358 _tls_socket.addressLength = sizeof(palSocketAddress_t); 00359 00360 if(_sec_mode == M2MConnectionSecurity::TLS){ 00361 _tls_socket.transportationMode = PAL_TLS_MODE; 00362 } 00363 else{ 00364 _tls_socket.transportationMode = PAL_DTLS_MODE; 00365 } 00366 }
Generated on Tue Jul 12 2022 20:21:00 by
