Simulated product dispenser
Fork of mbed-cloud-workshop-connect-HTS221 by
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 Security NULL."); 00079 return -1; 00080 } 00081 00082 if(_entropy.entropy_source_ptr) { 00083 if(PAL_SUCCESS != pal_addEntropySource(_entropy.entropy_source_ptr)){ 00084 return -1; 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("pal_initTLSConfiguration failed"); 00095 return -1; 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 || PAL_SUCCESS != pal_setCAChain(_conf, &caChain, NULL)){ 00123 tr_error("pal_setCAChain failed"); 00124 return -1; 00125 } 00126 00127 privateKey.size = MAX_CERTIFICATE_SIZE; 00128 ret_code = security->resource_value_buffer(M2MSecurity::Secretkey, certificate_ptr, security_instance_id, (size_t*)&privateKey.size); 00129 privateKey.buffer = certificate_ptr; 00130 if (ret_code < 0 || PAL_SUCCESS != pal_setOwnPrivateKey(_conf, &privateKey)) { 00131 tr_error("pal_setOwnPrivateKey failed"); 00132 return -1; 00133 } 00134 00135 void *dummy; 00136 00137 // Open certificate chain, size parameter contains the depth of certificate chain 00138 size_t cert_chain_size = 0; 00139 security->resource_value_buffer(M2MSecurity::OpenCertificateChain, (uint8_t *&)dummy, security_instance_id, &cert_chain_size); 00140 tr_info("M2MConnectionSecurityPimpl::init - cert chain length: %" PRIu32, cert_chain_size); 00141 00142 int index = 0; 00143 while (index < cert_chain_size) { 00144 owncert.size = MAX_CERTIFICATE_SIZE; 00145 ret_code = security->resource_value_buffer(M2MSecurity::ReadDeviceCertificateChain, certificate_ptr, security_instance_id, (size_t*)&owncert.size); 00146 owncert.buffer = certificate_ptr; 00147 00148 if (ret_code < 0 || PAL_SUCCESS != pal_setOwnCertChain(_conf, &owncert)){ 00149 tr_error("pal_setOwnCertChain failed"); 00150 security->resource_value_buffer(M2MSecurity::CloseCertificateChain, (uint8_t *&)dummy, security_instance_id, &cert_chain_size); 00151 return -1; 00152 } 00153 00154 index++; 00155 } 00156 security->resource_value_buffer(M2MSecurity::CloseCertificateChain, (uint8_t *&)dummy, security_instance_id, &cert_chain_size); 00157 00158 } else if (cert_mode == M2MSecurity::Psk){ 00159 00160 uint8_t identity[MAX_CERTIFICATE_SIZE]; 00161 uint8_t *identity_ptr = (uint8_t *)&identity; 00162 uint32_t identity_len; 00163 uint8_t psk[MAX_CERTIFICATE_SIZE]; 00164 uint8_t *psk_ptr = (uint8_t *)&psk; 00165 uint32_t psk_len; 00166 00167 security->resource_value_buffer(M2MSecurity::PublicKey, identity_ptr, security_instance_id, (size_t*)&identity_len); 00168 security->resource_value_buffer(M2MSecurity::Secretkey, psk_ptr, security_instance_id, (size_t*)&psk_len); 00169 palStatus_t ret = pal_setPSK(_conf, identity_ptr, identity_len, psk_ptr, psk_len); 00170 00171 00172 if(PAL_SUCCESS != ret){ 00173 tr_error("pal_setPSK failed"); 00174 return -1; 00175 } 00176 00177 }else{ 00178 tr_error("Security mode not set"); 00179 return -1; 00180 00181 } 00182 00183 if(PAL_SUCCESS != pal_initTLS(_conf, &_ssl)){ 00184 tr_error("pal_initTLS failed"); 00185 return -1; 00186 } 00187 00188 if(PAL_SUCCESS != pal_tlsSetSocket(_conf, &_tls_socket)){ 00189 tr_error("pal_tlsSetSocket failed"); 00190 return -1; 00191 } 00192 00193 _init_done = M2MConnectionSecurityPimpl::INIT_DONE; 00194 00195 #ifdef MBED_CONF_MBED_TRACE_ENABLE 00196 // Note: This call is not enough, one also needs the MBEDTLS_DEBUG_C to be defined globally 00197 // on build and if using default mbedtls configuration file, the 00198 // "#undef MBEDTLS_DEBUG_C" -line needs to be removed from mbedtls_mbed_client_config.h 00199 pal_sslSetDebugging(_conf, 1); 00200 #endif 00201 00202 tr_debug("M2MConnectionSecurityPimpl::init - out"); 00203 return 0; 00204 } 00205 00206 int M2MConnectionSecurityPimpl::start_handshake() 00207 { 00208 tr_debug("M2MConnectionSecurityPimpl::start_handshake"); 00209 00210 palStatus_t ret; 00211 00212 ret = pal_handShake(_ssl, _conf); 00213 00214 if(ret == PAL_ERR_TLS_WANT_READ || ret == PAL_ERR_TLS_WANT_WRITE || ret == PAL_ERR_TIMEOUT_EXPIRED ){ 00215 return M2MConnectionHandler::CONNECTION_ERROR_WANTS_READ; 00216 } 00217 else if(ret == PAL_ERR_TLS_PEER_CLOSE_NOTIFY) { 00218 return M2MConnectionHandler::SSL_PEER_CLOSE_NOTIFY; 00219 } 00220 00221 if(ret != PAL_SUCCESS){ //We loose the original error here! 00222 tr_debug("M2MConnectionSecurityPimpl::start_handshake pal_handShake() error %" PRId32, ret); 00223 return -1; 00224 } 00225 00226 ret = pal_sslGetVerifyResult(_ssl); 00227 if(PAL_SUCCESS != ret){ 00228 tr_debug("M2MConnectionSecurityPimpl::start_handshake pal_sslGetVerifyResult() error %" PRId32, ret); 00229 return -1; 00230 } 00231 00232 return ret; 00233 } 00234 00235 int M2MConnectionSecurityPimpl::connect(M2MConnectionHandler* connHandler) 00236 { 00237 tr_debug("M2MConnectionSecurityPimpl::connect"); 00238 int ret = -1; 00239 00240 if(M2MConnectionSecurityPimpl::INIT_DONE != _init_done){ 00241 return ret; 00242 } 00243 00244 ret = start_handshake(); 00245 tr_debug("M2MConnectionSecurityPimpl::connect - handshake ret: %d", ret); 00246 return ret; 00247 } 00248 00249 00250 int M2MConnectionSecurityPimpl::send_message(unsigned char *message, int len) 00251 { 00252 tr_debug("M2MConnectionSecurityPimpl::send_message"); 00253 int ret = -1; 00254 palStatus_t return_value; 00255 uint32_t len_write; 00256 00257 if(M2MConnectionSecurityPimpl::INIT_DONE != _init_done){ 00258 return ret; 00259 } 00260 00261 00262 if(PAL_SUCCESS == (return_value = pal_sslWrite(_ssl, message, len, &len_write))){ 00263 ret = (int)len_write; 00264 } 00265 else if(return_value == PAL_ERR_TLS_WANT_READ || return_value == PAL_ERR_TIMEOUT_EXPIRED ){ 00266 ret = M2MConnectionHandler::CONNECTION_ERROR_WANTS_READ; 00267 } 00268 else if(return_value == PAL_ERR_TLS_WANT_WRITE) { 00269 ret = M2MConnectionHandler::CONNECTION_ERROR_WANTS_WRITE; 00270 } 00271 else if(return_value == PAL_ERR_TLS_PEER_CLOSE_NOTIFY) { 00272 ret = M2MConnectionHandler::SSL_PEER_CLOSE_NOTIFY; 00273 } 00274 00275 tr_debug("M2MConnectionSecurityPimpl::send_message - ret: %d", ret); 00276 return ret; //bytes written 00277 } 00278 00279 int M2MConnectionSecurityPimpl::read(unsigned char* buffer, uint16_t len) 00280 { 00281 int ret = -1; 00282 palStatus_t return_value; 00283 uint32_t len_read; 00284 00285 if(M2MConnectionSecurityPimpl::INIT_DONE != _init_done){ 00286 tr_error("M2MConnectionSecurityPimpl::read - init not done!"); 00287 return ret; 00288 } 00289 00290 if(PAL_SUCCESS == (return_value = pal_sslRead(_ssl, buffer, len, &len_read))){ 00291 ret = (int)len_read; 00292 } 00293 00294 else if(return_value == PAL_ERR_TLS_WANT_READ || return_value == PAL_ERR_TLS_WANT_WRITE || return_value == PAL_ERR_TIMEOUT_EXPIRED ){ 00295 ret = M2MConnectionHandler::CONNECTION_ERROR_WANTS_READ; 00296 } 00297 00298 else if(return_value == PAL_ERR_TLS_PEER_CLOSE_NOTIFY) { 00299 ret = M2MConnectionHandler::SSL_PEER_CLOSE_NOTIFY; 00300 } 00301 00302 return ret; 00303 } 00304 00305 void M2MConnectionSecurityPimpl::set_random_number_callback(random_number_cb callback) 00306 { 00307 (void)callback; 00308 } 00309 00310 void M2MConnectionSecurityPimpl::set_entropy_callback(entropy_cb callback) 00311 { 00312 00313 _entropy = callback; 00314 00315 } 00316 00317 void M2MConnectionSecurityPimpl::set_socket(palSocket_t socket, palSocketAddress_t *address) 00318 { 00319 _tls_socket.socket = socket; 00320 _tls_socket.socketAddress = address; 00321 _tls_socket.addressLength = sizeof(palSocketAddress_t); 00322 00323 if(_sec_mode == M2MConnectionSecurity::TLS){ 00324 _tls_socket.transportationMode = PAL_TLS_MODE; 00325 } 00326 else{ 00327 _tls_socket.transportationMode = PAL_DTLS_MODE; 00328 } 00329 } 00330 00331 bool M2MConnectionSecurityPimpl::certificate_parse_valid_time(const char *certificate, uint32_t certificate_len, uint64_t *valid_from, uint64_t *valid_to) 00332 { 00333 palX509Handle_t cert = 0; 00334 size_t len; 00335 palStatus_t ret; 00336 00337 tr_debug("certificate_validfrom_time"); 00338 00339 ret = pal_x509Initiate(&cert); 00340 if(PAL_SUCCESS != ret) { 00341 tr_error("certificate_validfrom_time - cert init failed: %u", (int)ret); 00342 pal_x509Free(&cert); 00343 return false; 00344 } 00345 if(PAL_SUCCESS != (ret = pal_x509CertParse(cert, (const unsigned char*)certificate, certificate_len))) { 00346 tr_error("certificate_validfrom_time - cert parse failed: %u", (int)ret); 00347 pal_x509Free(&cert); 00348 return false; 00349 } 00350 if(PAL_SUCCESS != (ret = pal_x509CertGetAttribute(cert, PAL_X509_VALID_FROM, valid_from, sizeof(uint64_t), &len))) { 00351 tr_error("certificate_validfrom_time - cert attr get failed: %u", (int)ret); 00352 pal_x509Free(&cert); 00353 return false; 00354 } 00355 if(PAL_SUCCESS != (ret = pal_x509CertGetAttribute(cert, PAL_X509_VALID_TO, valid_to, sizeof(uint64_t), &len))) { 00356 tr_error("certificate_validto_time - cert attr get failed: %u", (int)ret); 00357 pal_x509Free(&cert); 00358 return false; 00359 } 00360 00361 pal_x509Free(&cert); 00362 return true; 00363 }
Generated on Tue Jul 12 2022 19:12:12 by 1.7.2