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.
ConnectorClient.cpp
00001 // ---------------------------------------------------------------------------- 00002 // Copyright 2016-2017 ARM Ltd. 00003 // 00004 // SPDX-License-Identifier: Apache-2.0 00005 // 00006 // Licensed under the Apache License, Version 2.0 (the "License"); 00007 // you may not use this file except in compliance with the License. 00008 // You may obtain a copy of the License at 00009 // 00010 // http://www.apache.org/licenses/LICENSE-2.0 00011 // 00012 // Unless required by applicable law or agreed to in writing, software 00013 // distributed under the License is distributed on an "AS IS" BASIS, 00014 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00015 // See the License for the specific language governing permissions and 00016 // limitations under the License. 00017 // ---------------------------------------------------------------------------- 00018 00019 // fixup the compilation on ARMCC for PRId32 00020 #define __STDC_FORMAT_MACROS 00021 #include <inttypes.h> 00022 00023 #include "include/ConnectorClient.h" 00024 #include "include/CloudClientStorage.h" 00025 #include "include/CertificateParser.h" 00026 #include "MbedCloudClient.h" 00027 #include "mbed-client/m2mconstants.h" 00028 #include "mbed-client/m2minterfacefactory.h" 00029 #include "mbed-client/m2mdevice.h" 00030 #include "mbed-client/m2mconstants.h" 00031 #include "mbed-trace/mbed_trace.h" 00032 #include "factory_configurator_client.h" 00033 #include "key_config_manager.h" 00034 #include "mbed-client/uriqueryparser.h" 00035 00036 #include <assert.h> 00037 #include <string> 00038 #include <stdio.h> 00039 00040 #include "ns_hal_init.h" 00041 00042 #ifdef MBED_CONF_MBED_CLIENT_EVENT_LOOP_SIZE 00043 #define MBED_CLIENT_EVENT_LOOP_SIZE MBED_CONF_MBED_CLIENT_EVENT_LOOP_SIZE 00044 #else 00045 #define MBED_CLIENT_EVENT_LOOP_SIZE 1024 00046 #endif 00047 00048 #define TRACE_GROUP "mClt" 00049 00050 #define INTERNAL_ENDPOINT_PARAM "&iep=" 00051 #define DEFAULT_ENDPOINT "endpoint" 00052 #define INTERFACE_ERROR "Client interface is not created. Restart" 00053 #define CREDENTIAL_ERROR "Failed to read credentials from storage" 00054 #define DEVICE_NOT_PROVISIONED "Device not provisioned" 00055 #define ERROR_NO_MEMORY "Not enough memory to store LWM2M credentials" 00056 00057 #ifndef MBED_CLIENT_DISABLE_EST_FEATURE 00058 #define ERROR_EST_ENROLLMENT_REQUEST_FAILED "EST enrollment request failed" 00059 #define LWM2M_CSR_SUBJECT_FORMAT "L=%s,OU=%s,CN=%s" 00060 #endif 00061 00062 // XXX: nothing here yet 00063 class EventData { 00064 00065 }; 00066 00067 static int read_callback_helper(const char *key, void *buffer, size_t *buffer_len) 00068 { 00069 size_t cert_size = 0; 00070 if (strcmp(key, g_fcc_lwm2m_device_private_key_name) == 0 || 00071 strcmp(key, g_fcc_bootstrap_device_private_key_name) == 0) { 00072 if (ccs_item_size(key, buffer_len, CCS_PRIVATE_KEY_ITEM) != CCS_STATUS_SUCCESS) { 00073 *buffer_len = 0; 00074 return CCS_STATUS_ERROR; 00075 } 00076 00077 if (ccs_get_item(key, (uint8_t*)buffer, *buffer_len, &cert_size, CCS_PRIVATE_KEY_ITEM) != CCS_STATUS_SUCCESS) { 00078 *buffer_len = 0; 00079 return CCS_STATUS_ERROR; 00080 } 00081 } else { 00082 if (ccs_item_size(key, buffer_len, CCS_CERTIFICATE_ITEM) != CCS_STATUS_SUCCESS) { 00083 *buffer_len = 0; 00084 return CCS_STATUS_ERROR; 00085 } 00086 00087 if (ccs_get_item(key, (uint8_t*)buffer, *buffer_len, &cert_size, CCS_CERTIFICATE_ITEM) != CCS_STATUS_SUCCESS) { 00088 *buffer_len = 0; 00089 return CCS_STATUS_ERROR; 00090 } 00091 } 00092 00093 *buffer_len = cert_size; 00094 00095 return CCS_STATUS_SUCCESS; 00096 } 00097 00098 static bool write_security_object_data_to_kcm(const M2MResourceBase& resource, const uint8_t *buffer, const size_t buffer_size, void */*client_args*/) 00099 { 00100 ccs_status_e status = CCS_STATUS_ERROR; 00101 uint32_t resource_id = resource.name_id(); 00102 uint16_t object_instance_id = resource.object_instance_id(); 00103 00104 switch (resource_id) { 00105 case M2MSecurity::PublicKey: 00106 if (object_instance_id == M2MSecurity::Bootstrap) { 00107 ccs_delete_item(g_fcc_bootstrap_device_certificate_name, CCS_CERTIFICATE_ITEM); 00108 status = ccs_set_item(g_fcc_bootstrap_device_certificate_name, buffer, buffer_size, CCS_CERTIFICATE_ITEM); 00109 } else { 00110 ccs_delete_item(g_fcc_lwm2m_device_certificate_name, CCS_CERTIFICATE_ITEM); 00111 status = ccs_set_item(g_fcc_lwm2m_device_certificate_name, buffer, buffer_size, CCS_CERTIFICATE_ITEM); 00112 } 00113 break; 00114 00115 case M2MSecurity::ServerPublicKey: 00116 if (object_instance_id == M2MSecurity::Bootstrap) { 00117 ccs_delete_item(g_fcc_bootstrap_server_ca_certificate_name, CCS_CERTIFICATE_ITEM); 00118 status = ccs_set_item(g_fcc_bootstrap_server_ca_certificate_name, buffer, buffer_size, CCS_CERTIFICATE_ITEM); 00119 } else { 00120 ccs_delete_item(g_fcc_lwm2m_server_ca_certificate_name, CCS_CERTIFICATE_ITEM); 00121 status = ccs_set_item(g_fcc_lwm2m_server_ca_certificate_name, buffer, buffer_size, CCS_CERTIFICATE_ITEM); 00122 } 00123 break; 00124 00125 case M2MSecurity::Secretkey: 00126 if (object_instance_id == M2MSecurity::Bootstrap) { 00127 ccs_delete_item(g_fcc_bootstrap_device_private_key_name, CCS_PRIVATE_KEY_ITEM); 00128 status = ccs_set_item(g_fcc_bootstrap_device_private_key_name, buffer, buffer_size, CCS_PRIVATE_KEY_ITEM); 00129 } else { 00130 ccs_delete_item(g_fcc_lwm2m_device_private_key_name, CCS_PRIVATE_KEY_ITEM); 00131 status = ccs_set_item(g_fcc_lwm2m_device_private_key_name, buffer, buffer_size, CCS_PRIVATE_KEY_ITEM); 00132 } 00133 break; 00134 00135 default: 00136 break; 00137 } 00138 00139 return (status == CCS_STATUS_SUCCESS) ? true : false; 00140 } 00141 00142 static int read_security_object_data_from_kcm(const M2MResourceBase& resource, void *buffer, size_t *buffer_len, void */*client_args*/) 00143 { 00144 uint32_t resource_id = resource.name_id(); 00145 uint16_t object_instance_id = resource.object_instance_id(); 00146 switch (resource_id) { 00147 case M2MSecurity::PublicKey: 00148 if (object_instance_id == M2MSecurity::Bootstrap) { 00149 return read_callback_helper(g_fcc_bootstrap_device_certificate_name, buffer, buffer_len); 00150 } else { 00151 return read_callback_helper(g_fcc_lwm2m_device_certificate_name, buffer, buffer_len); 00152 } 00153 00154 case M2MSecurity::ServerPublicKey: 00155 if (object_instance_id == M2MSecurity::Bootstrap) { 00156 return read_callback_helper(g_fcc_bootstrap_server_ca_certificate_name, buffer, buffer_len); 00157 } else { 00158 return read_callback_helper(g_fcc_lwm2m_server_ca_certificate_name, buffer, buffer_len); 00159 } 00160 00161 case M2MSecurity::Secretkey: 00162 if (object_instance_id == M2MSecurity::Bootstrap) { 00163 return read_callback_helper(g_fcc_bootstrap_device_private_key_name, buffer, buffer_len); 00164 } else { 00165 return read_callback_helper(g_fcc_lwm2m_device_private_key_name, buffer, buffer_len); 00166 } 00167 00168 default: 00169 break; 00170 } 00171 00172 return CCS_STATUS_ERROR; 00173 } 00174 00175 static int open_certificate_chain_callback(const M2MResourceBase& resource, void */*buffer*/, size_t *chain_size, void *client_args) 00176 { 00177 void *handle = NULL; 00178 uint16_t object_instance_id = resource.object_instance_id(); 00179 ConnectorClient *client = (ConnectorClient*)client_args; 00180 if (object_instance_id == M2MSecurity::Bootstrap) { 00181 handle = ccs_open_certificate_chain(g_fcc_bootstrap_device_certificate_name, chain_size); 00182 client->set_certificate_chain_handle(handle); 00183 } else { 00184 handle = ccs_open_certificate_chain(g_fcc_lwm2m_device_certificate_name, chain_size); 00185 client->set_certificate_chain_handle(handle); 00186 } 00187 00188 return (handle) ? CCS_STATUS_SUCCESS : CCS_STATUS_ERROR; 00189 } 00190 00191 static int read_certificate_chain_callback(const M2MResourceBase& /*resource*/, void *buffer, size_t *buffer_len, void *client_args) 00192 { 00193 ConnectorClient *client = (ConnectorClient*) client_args; 00194 ccs_status_e status = CCS_STATUS_ERROR; 00195 if (client->certificate_chain_handle()) { 00196 status = ccs_get_next_cert_chain(client->certificate_chain_handle(), buffer, buffer_len); 00197 } 00198 00199 return status; 00200 } 00201 00202 static int close_certificate_chain_callback(const M2MResourceBase& /*resource*/, void */*buffer*/, size_t *, void *client_args) 00203 { 00204 ccs_status_e status = CCS_STATUS_ERROR; 00205 ConnectorClient *client = (ConnectorClient*) client_args; 00206 if (client->certificate_chain_handle()) { 00207 status = ccs_close_certificate_chain(client->certificate_chain_handle()); 00208 client->set_certificate_chain_handle(NULL); 00209 } 00210 return status; 00211 } 00212 00213 ConnectorClient::ConnectorClient(ConnectorClientCallback* callback) 00214 : _callback(callback), 00215 _current_state(State_Bootstrap_Start), 00216 _event_generated(false), _state_engine_running(false), 00217 _interface(NULL), _security(NULL), 00218 _endpoint_info(M2MSecurity::Certificate), _client_objs(NULL), 00219 _rebootstrap_timer(*this), _bootstrap_security_instance(1), _lwm2m_security_instance(0), _certificate_chain_handle(NULL) 00220 { 00221 assert(_callback != NULL); 00222 00223 // XXX: this initialization sequence needs more work, as doing the allocations 00224 // and static initializations from constructor is really troublesome. 00225 // All this needs to be moved to the separate setup() call. 00226 00227 // The ns_hal_init() needs to be called by someone before create_interface(), 00228 // as it will also initialize the tasklet. 00229 ns_hal_init(NULL, MBED_CLIENT_EVENT_LOOP_SIZE, NULL, NULL); 00230 00231 // Create the lwm2m server security object we need always 00232 _security = M2MInterfaceFactory::create_security(M2MSecurity::M2MServer); 00233 _interface = M2MInterfaceFactory::create_interface(*this, 00234 DEFAULT_ENDPOINT, // endpoint name string 00235 MBED_CLOUD_CLIENT_ENDPOINT_TYPE, // endpoint type string 00236 MBED_CLOUD_CLIENT_LIFETIME, // lifetime 00237 MBED_CLOUD_CLIENT_LISTEN_PORT, // listen port 00238 _endpoint_info.account_id, // domain string 00239 transport_mode(), // binding mode 00240 M2MInterface::LwIP_IPv4); // network stack 00241 00242 initialize_storage(); 00243 } 00244 00245 00246 ConnectorClient::~ConnectorClient() 00247 { 00248 uninitialize_storage(); 00249 M2MDevice::delete_instance(); 00250 M2MSecurity::delete_instance(); 00251 delete _interface; 00252 } 00253 00254 void ConnectorClient::start_bootstrap() 00255 { 00256 tr_debug("ConnectorClient::start_bootstrap()"); 00257 assert(_callback != NULL); 00258 init_security_object(); 00259 // Stop rebootstrap timer if it was running 00260 _rebootstrap_timer.stop_timer(); 00261 00262 if (create_bootstrap_object()) { 00263 _interface->update_endpoint(_endpoint_info.endpoint_name); 00264 _interface->update_domain(_endpoint_info.account_id); 00265 internal_event(State_Bootstrap_Start); 00266 } else { 00267 tr_error("ConnectorClient::start_bootstrap() - bootstrap object fail"); 00268 } 00269 state_engine(); 00270 } 00271 00272 void ConnectorClient::start_registration(M2MBaseList* client_objs) 00273 { 00274 tr_debug("ConnectorClient::start_registration()"); 00275 assert(_callback != NULL); 00276 init_security_object(); 00277 _client_objs = client_objs; 00278 00279 // XXX: actually this call should be external_event() to match the pattern used in other m2m classes 00280 create_register_object(); 00281 if(_security->get_security_instance_id(M2MSecurity::M2MServer) >= 0) { 00282 _interface->update_endpoint(_endpoint_info.endpoint_name); 00283 _interface->update_domain(_endpoint_info.account_id); 00284 internal_event(State_Registration_Start); 00285 } else { 00286 tr_error("ConnectorClient::start_registration(): failed to create objs"); 00287 _callback->connector_error(M2MInterface::InvalidParameters, INTERFACE_ERROR); 00288 } 00289 state_engine(); 00290 } 00291 00292 M2MInterface * ConnectorClient::m2m_interface() 00293 { 00294 return _interface; 00295 } 00296 00297 void ConnectorClient::update_registration() 00298 { 00299 if(_interface && _security && _security->get_security_instance_id(M2MSecurity::M2MServer) >= 0) { 00300 if (_client_objs != NULL) { 00301 _interface->update_registration(_security, *_client_objs); 00302 } 00303 else { 00304 _interface->update_registration(_security); 00305 } 00306 } 00307 } 00308 00309 // generates an internal event. called from within a state 00310 // function to transition to a new state 00311 void ConnectorClient::internal_event(StartupSubStateRegistration new_state) 00312 { 00313 tr_debug("ConnectorClient::internal_event: state: %d -> %d", _current_state, new_state); 00314 _event_generated = true; 00315 _current_state = new_state; 00316 00317 // Avoid recursive chain which eats too much of stack 00318 if (!_state_engine_running) { 00319 state_engine(); 00320 } 00321 } 00322 00323 // the state engine executes the state machine states 00324 void ConnectorClient::state_engine(void) 00325 { 00326 tr_debug("ConnectorClient::state_engine"); 00327 00328 // this simple flagging gets rid of recursive calls to this method 00329 _state_engine_running = true; 00330 00331 // while events are being generated keep executing states 00332 while (_event_generated) { 00333 _event_generated = false; // event used up, reset flag 00334 00335 state_function(_current_state); 00336 } 00337 00338 _state_engine_running = false; 00339 } 00340 00341 void ConnectorClient::state_function(StartupSubStateRegistration current_state) 00342 { 00343 switch (current_state) { 00344 case State_Bootstrap_Start: 00345 state_bootstrap_start(); 00346 break; 00347 case State_Bootstrap_Started: 00348 state_bootstrap_started(); 00349 break; 00350 case State_Bootstrap_Success: 00351 state_bootstrap_success(); 00352 break; 00353 case State_Bootstrap_Failure: 00354 state_bootstrap_failure(); 00355 break; 00356 #ifndef MBED_CLIENT_DISABLE_EST_FEATURE 00357 case State_EST_Start: 00358 state_est_start(); 00359 break; 00360 case State_EST_Started: 00361 state_est_started(); 00362 break; 00363 case State_EST_Success: 00364 state_est_success(); 00365 break; 00366 case State_EST_Failure: 00367 state_est_failure(); 00368 break; 00369 #endif // !MBED_CLIENT_DISABLE_EST_FEATURE 00370 case State_Registration_Start: 00371 state_registration_start(); 00372 break; 00373 case State_Registration_Started: 00374 state_registration_started(); 00375 break; 00376 case State_Registration_Success: 00377 state_registration_success(); 00378 break; 00379 case State_Registration_Failure: 00380 state_registration_failure(); 00381 break; 00382 case State_Unregistered: 00383 state_unregistered(); 00384 break; 00385 default: 00386 break; 00387 } 00388 } 00389 00390 /* 00391 * Creates register server object with mbed device server address and other parameters 00392 * required for client to connect to mbed device server. 00393 */ 00394 void ConnectorClient::create_register_object() 00395 { 00396 tr_debug("ConnectorClient::create_register_object()"); 00397 int32_t m2m_id = _security->get_security_instance_id(M2MSecurity::M2MServer); 00398 if (m2m_id == -1) { 00399 init_security_object(); 00400 } 00401 00402 m2m_id = _security->get_security_instance_id(M2MSecurity::M2MServer); 00403 _security->set_resource_value(M2MSecurity::BootstrapServer, M2MSecurity::M2MServer, m2m_id); 00404 00405 // Add ResourceID's and values to the security ObjectID/ObjectInstance 00406 _security->set_resource_value(M2MSecurity::SecurityMode, _endpoint_info.mode, m2m_id); 00407 00408 // Allocate scratch buffer, this will be used to copy parameters from storage to security object 00409 const int max_size = MAX_CERTIFICATE_SIZE; 00410 uint8_t *buffer = (uint8_t*)malloc(max_size); 00411 size_t real_size = 0; 00412 bool success = false; 00413 00414 if (buffer != NULL) { 00415 success = true; 00416 } 00417 else { 00418 tr_error("ConnectorClient::create_register_object - Temporary certificate buffer allocation failed!"); 00419 } 00420 00421 // Endpoint 00422 if (success) { 00423 success = false; 00424 char device_id[64]; 00425 00426 size_t cert_size = max_size; 00427 uint8_t certificate[MAX_CERTIFICATE_SIZE]; 00428 uint8_t *certificate_ptr = (uint8_t*)&certificate; 00429 00430 // TODO! Update to use chain api 00431 _security->resource_value_buffer(M2MSecurity::PublicKey, certificate_ptr, m2m_id, &cert_size); 00432 real_size = cert_size; 00433 if (extract_field_from_certificate((uint8_t*)certificate, real_size, "CN", device_id)) { 00434 tr_info("ConnectorClient::create_register_object - CN - endpoint_name : %s", device_id); 00435 _endpoint_info.endpoint_name = String(device_id); 00436 success = true; 00437 } else { 00438 tr_error("KEY_ENDPOINT_NAME failed."); 00439 } 00440 } 00441 00442 // Connector URL 00443 if (success) { 00444 success = false; 00445 if (ccs_get_item(g_fcc_lwm2m_server_uri_name, buffer, max_size, &real_size, CCS_CONFIG_ITEM) == CCS_STATUS_SUCCESS) { 00446 tr_info("ConnectorClient::create_register_object - M2MServerUri %.*s", (int)real_size, buffer); 00447 success = true; 00448 _security->set_resource_value(M2MSecurity::M2MServerUri, buffer, (uint32_t)real_size, m2m_id); 00449 } 00450 else 00451 tr_error("KEY_CONNECTOR_URL failed."); 00452 } 00453 00454 // Try to get internal endpoint name 00455 if (success) { 00456 if (ccs_get_item(KEY_INTERNAL_ENDPOINT, buffer, max_size, &real_size, CCS_CONFIG_ITEM) == CCS_STATUS_SUCCESS) { 00457 _endpoint_info.internal_endpoint_name = String((const char*)buffer, real_size); 00458 tr_info("ConnectorClient::create_register_object - internal endpoint name : %s", _endpoint_info.internal_endpoint_name.c_str()); 00459 } 00460 else { 00461 tr_debug("KEY_INTERNAL_ENDPOINT failed."); 00462 } 00463 } 00464 00465 // Account ID, not mandatory 00466 if (success) { 00467 if (ccs_get_item(KEY_ACCOUNT_ID, buffer, max_size, &real_size, CCS_CONFIG_ITEM) == CCS_STATUS_SUCCESS) { 00468 tr_info("ConnectorClient::create_register_object - AccountId %.*s", (int)real_size, buffer); 00469 _endpoint_info.account_id = String((const char*)buffer, real_size); 00470 } 00471 else 00472 tr_debug("KEY_ACCOUNT_ID failed."); 00473 } 00474 00475 free(buffer); 00476 if (!success) { 00477 tr_error("ConnectorClient::create_register_object - Failed to read credentials"); 00478 _callback->connector_error((M2MInterface::Error)MbedCloudClient::ConnectorFailedToReadCredentials,CREDENTIAL_ERROR); 00479 // TODO: what to do with the m2mserver security instance 00480 } 00481 } 00482 00483 /* 00484 * Creates bootstrap server object with bootstrap server address and other parameters 00485 * required for connecting to mbed Cloud bootstrap server. 00486 */ 00487 bool ConnectorClient::create_bootstrap_object() 00488 { 00489 tr_debug("ConnectorClient::create_bootstrap_object"); 00490 bool success = false; 00491 00492 // Check if bootstrap credentials are already stored in KCM 00493 if (bootstrap_credentials_stored_in_kcm() && _security) { 00494 int32_t bs_id = _security->get_security_instance_id(M2MSecurity::Bootstrap); 00495 _security->set_resource_value(M2MSecurity::SecurityMode, M2MSecurity::Certificate, bs_id); 00496 00497 tr_info("ConnectorClient::create_bootstrap_object - bs_id = %" PRId32, bs_id); 00498 tr_info("ConnectorClient::create_bootstrap_object - use credentials from storage"); 00499 00500 // Allocate scratch buffer, this will be used to copy parameters from storage to security object 00501 size_t real_size = 0; 00502 const int max_size = MAX_CERTIFICATE_SIZE; 00503 uint8_t *buffer = (uint8_t*)malloc(max_size); 00504 if (buffer != NULL) { 00505 success = true; 00506 } 00507 else { 00508 tr_error("ConnectorClient::create_bootstrap_object - Temporary certificate buffer allocation failed!"); 00509 } 00510 00511 // Read internal endpoint name if it exists, we need to append 00512 // it to bootstrap uri if device already bootstrapped 00513 uint8_t *iep = NULL; 00514 if (success && ccs_get_string_item(KEY_INTERNAL_ENDPOINT, buffer, max_size, CCS_CONFIG_ITEM) == CCS_STATUS_SUCCESS) { 00515 iep = (uint8_t*)malloc(strlen((const char*)buffer) + strlen(INTERNAL_ENDPOINT_PARAM) + 1); 00516 if (iep != NULL) { 00517 strcpy((char*)iep, INTERNAL_ENDPOINT_PARAM); 00518 strcat((char*)iep, (const char*)buffer); 00519 tr_info("ConnectorClient::create_bootstrap_object - iep: %s", buffer); 00520 } 00521 //TODO: Should handle error if iep exists but allocation fails? 00522 } 00523 00524 // Bootstrap URI 00525 if (success) { 00526 success = false; 00527 if (ccs_get_string_item(g_fcc_bootstrap_server_uri_name, buffer, max_size, CCS_CONFIG_ITEM) == CCS_STATUS_SUCCESS) { 00528 success = true; 00529 00530 real_size = strlen((const char*)buffer); 00531 // Append iep if we 1. have it 2. it doesn't already exist in uri 3. it fits 00532 if (iep && 00533 strstr((const char*)buffer, (const char*)iep) == NULL && 00534 (real_size + strlen((const char*)iep) + 1) <= max_size) { 00535 strcat((char*)buffer, (const char*)iep); 00536 real_size += strlen((const char*)iep) + 1; 00537 } 00538 00539 tr_info("ConnectorClient::create_bootstrap_object - M2MServerUri %.*s", (int)real_size, buffer); 00540 _security->set_resource_value(M2MSecurity::M2MServerUri, buffer, real_size, bs_id); 00541 } 00542 } 00543 00544 free(iep); 00545 00546 // Endpoint 00547 if (success) { 00548 success = false; 00549 if (ccs_get_item(g_fcc_endpoint_parameter_name, buffer, max_size, &real_size, CCS_CONFIG_ITEM) == CCS_STATUS_SUCCESS) { 00550 success = true; 00551 _endpoint_info.endpoint_name = String((const char*)buffer, real_size); 00552 tr_info("ConnectorClient::create_bootstrap_object - Endpoint %s", _endpoint_info.endpoint_name.c_str()); 00553 } 00554 } 00555 00556 // Account ID, not mandatory 00557 if (success) { 00558 if (ccs_get_item(KEY_ACCOUNT_ID, buffer, max_size, &real_size, CCS_CONFIG_ITEM) == CCS_STATUS_SUCCESS) { 00559 _endpoint_info.account_id = String((const char*)buffer, real_size); 00560 tr_info("ConnectorClient::create_bootstrap_object - AccountId %s", _endpoint_info.account_id.c_str()); 00561 } 00562 } 00563 00564 free(buffer); 00565 00566 if (!success) { 00567 tr_error("ConnectorClient::create_bootstrap_object - Failed to read credentials"); 00568 _callback->connector_error((M2MInterface::Error)MbedCloudClient::ConnectorFailedToReadCredentials,CREDENTIAL_ERROR); 00569 _security->remove_object_instance(bs_id); 00570 } 00571 } else { 00572 success = true; 00573 tr_info("ConnectorClient::create_bootstrap_object - bootstrap object already done"); 00574 } 00575 00576 00577 return success; 00578 } 00579 00580 void ConnectorClient::state_bootstrap_start() 00581 { 00582 tr_info("ConnectorClient::state_bootstrap_start()"); 00583 assert(_interface != NULL); 00584 assert(_security != NULL); 00585 00586 _interface->bootstrap(_security); 00587 00588 internal_event(State_Bootstrap_Started); 00589 } 00590 00591 void ConnectorClient::state_bootstrap_started() 00592 { 00593 // this state may be useful only for verifying the callbacks? 00594 } 00595 00596 void ConnectorClient::state_bootstrap_success() 00597 { 00598 assert(_callback != NULL); 00599 // Parse internal endpoint name from mDS cert 00600 _callback->registration_process_result(State_Bootstrap_Success); 00601 } 00602 00603 void ConnectorClient::state_bootstrap_failure() 00604 { 00605 assert(_callback != NULL); 00606 // maybe some additional canceling and/or leanup is needed here? 00607 _callback->registration_process_result(State_Bootstrap_Failure); 00608 } 00609 00610 #ifndef MBED_CLIENT_DISABLE_EST_FEATURE 00611 void ConnectorClient::state_est_start() 00612 { 00613 // - Generate CSR from data during bootstrap phase 00614 // - Call EST enrollment API from InterfaceImpl 00615 00616 // Update the internal endpoint name and account id to endpoint info structure 00617 // as we get those during bootstrap phase 00618 _endpoint_info.internal_endpoint_name = _interface->internal_endpoint_name(); 00619 00620 int32_t m2m_id = _security->get_security_instance_id(M2MSecurity::M2MServer); 00621 uint32_t sec_mode = M2MSecurity::SecurityNotSet; 00622 if (m2m_id >= 0) { 00623 sec_mode = _security->resource_value_int(M2MSecurity::SecurityMode, m2m_id); 00624 00625 // We need to parse account id from lwm2m server uri query if it is not yet 00626 // set in endpoint info structure 00627 if (_endpoint_info.account_id.length() <= 0) { 00628 String address = _security->resource_value_string(M2MSecurity::M2MServerUri, m2m_id); 00629 tr_debug("ConnectorClient::state_est_start - address: %s", address.c_str()); 00630 if (address.size() > 0) { 00631 const char *aid = NULL; 00632 const int aid_size = parse_query_parameter_value_from_uri((const char*)address.c_str(), QUERY_PARAM_AID, &aid); 00633 if (aid_size > 0) { 00634 _endpoint_info.account_id.append_raw(aid, aid_size); 00635 } 00636 } 00637 } 00638 } 00639 00640 tr_debug("ConnectorClient::state_est_start - security instance id: %" PRId32, m2m_id); 00641 tr_debug("ConnectorClient::state_est_start - ep: %s", _endpoint_info.internal_endpoint_name.c_str()); 00642 tr_debug("ConnectorClient::state_est_start - iep: %s", _endpoint_info.endpoint_name.c_str()); 00643 tr_debug("ConnectorClient::state_est_start - aid: %s", _endpoint_info.account_id.c_str()); 00644 00645 // Check EST required parameters are in place 00646 if (m2m_id < 0 || 00647 _endpoint_info.endpoint_name.length() <= 0 || 00648 _endpoint_info.internal_endpoint_name.length() <= 0 || 00649 _endpoint_info.account_id.length() <= 0) { 00650 tr_error("ConnectorClient::state_est_start - Missing parameters for EST enrollment!"); 00651 internal_event(State_EST_Failure); 00652 return; 00653 } 00654 00655 uint32_t is_bs_server = _security->resource_value_int(M2MSecurity::BootstrapServer, m2m_id); 00656 size_t public_key_size = MAX_CERTIFICATE_SIZE; 00657 size_t server_key_size = MAX_CERTIFICATE_SIZE; 00658 size_t private_key_size = MAX_CERTIFICATE_SIZE; 00659 00660 // Temp buffer for storing CSR and certificates 00661 uint8_t *buffer = (uint8_t*)malloc(MAX_CERTIFICATE_SIZE); 00662 size_t real_size = 0; 00663 if (buffer == NULL) { 00664 tr_error("ConnectorClient::state_est_start - Allocating temp buffer failed!"); 00665 internal_event(State_EST_Failure); 00666 return; 00667 } 00668 uint8_t *buffer_ptr = buffer; 00669 00670 // TODO! Update to use chain api 00671 if (_security->resource_value_buffer(M2MSecurity::PublicKey, buffer_ptr, m2m_id, &public_key_size) != 0) { 00672 public_key_size = 0; 00673 } 00674 if (_security->resource_value_buffer(M2MSecurity::ServerPublicKey, buffer_ptr, m2m_id, &server_key_size) != 0) { 00675 server_key_size = 0; 00676 } 00677 if (_security->resource_value_buffer(M2MSecurity::Secretkey, buffer_ptr, m2m_id, &private_key_size) != 0) { 00678 private_key_size = 0; 00679 } 00680 00681 tr_info("est check - is bs server /0/1: %" PRIu32, is_bs_server); 00682 tr_info("est check - Security Mode /0/2: %" PRIu32, sec_mode); 00683 tr_info("est check - Public key size /0/3: %" PRIu32, public_key_size); 00684 tr_info("est check - Server Public key size /0/4: %" PRIu32, server_key_size); 00685 tr_info("est check - Secret key size /0/5: %" PRIu32, private_key_size); 00686 00687 // Configure CSR params 00688 kcm_csr_params_s csr_params; 00689 int subject_size = snprintf(NULL, 0, LWM2M_CSR_SUBJECT_FORMAT, 00690 _endpoint_info.internal_endpoint_name.c_str(), 00691 _endpoint_info.account_id.c_str(), 00692 _endpoint_info.endpoint_name.c_str()); 00693 if (subject_size <= 0) { 00694 tr_error("ConnectorClient::state_est_start - CSR Subject formatting failed!"); 00695 free(buffer); 00696 internal_event(State_EST_Failure); 00697 return; 00698 } 00699 00700 // For null-terminator 00701 subject_size++; 00702 00703 csr_params.subject = (char*)malloc(subject_size); 00704 if (csr_params.subject == NULL) { 00705 tr_error("ConnectorClient::state_est_start - CSR Subject formatting failed!"); 00706 free(buffer); 00707 internal_event(State_EST_Failure); 00708 return; 00709 } 00710 00711 snprintf(csr_params.subject, subject_size, LWM2M_CSR_SUBJECT_FORMAT, 00712 _endpoint_info.internal_endpoint_name.c_str(), 00713 _endpoint_info.account_id.c_str(), 00714 _endpoint_info.endpoint_name.c_str()); 00715 00716 tr_debug("est csr subject '%s'", csr_params.subject); 00717 00718 csr_params.md_type = KCM_MD_SHA256; 00719 csr_params.key_usage = KCM_CSR_KU_NONE; 00720 csr_params.ext_key_usage = KCM_CSR_EXT_KU_NONE; 00721 00722 kcm_status_e status = kcm_generate_keys_and_csr(KCM_SCHEME_EC_SECP256R1, 00723 (const uint8_t*)g_fcc_lwm2m_device_private_key_name, 00724 strlen(g_fcc_lwm2m_device_private_key_name), 00725 NULL, 00726 0, 00727 false, 00728 &csr_params, 00729 buffer, 00730 MAX_CERTIFICATE_SIZE, 00731 &real_size, 00732 NULL); 00733 00734 free(csr_params.subject); 00735 00736 if (status != KCM_STATUS_SUCCESS) { 00737 tr_error("ConnectorClient::state_est_start - Generating keys and csr failed!"); 00738 free(buffer); 00739 internal_event(State_EST_Failure); 00740 return; 00741 } 00742 00743 // Update state and start the enrollment by sending the enroll request 00744 internal_event(State_EST_Started); 00745 _interface->post_data_request("est/sen", 00746 false, 00747 real_size, 00748 buffer, 00749 ConnectorClient::est_post_data_cb, 00750 ConnectorClient::est_post_data_error_cb, 00751 this); 00752 00753 free(buffer); 00754 } 00755 00756 void ConnectorClient::state_est_started() 00757 { 00758 } 00759 00760 void ConnectorClient::state_est_success() 00761 { 00762 tr_info("ConnectorClient::state_est_success()"); 00763 _interface->finish_bootstrap(); 00764 } 00765 00766 void ConnectorClient::state_est_failure() 00767 { 00768 tr_info("ConnectorClient::state_est_failure()"); 00769 internal_event(State_Bootstrap_Failure); 00770 //Failed to store credentials, bootstrap failed 00771 _callback->connector_error(M2MInterface::ESTEnrollmentFailed, ERROR_EST_ENROLLMENT_REQUEST_FAILED); // Translated to error code ConnectMemoryConnectFail 00772 } 00773 #endif /* !MBED_CLIENT_DISABLE_EST_FEATURE */ 00774 00775 void ConnectorClient::state_registration_start() 00776 { 00777 tr_info("ConnectorClient::state_registration_start()"); 00778 assert(_interface != NULL); 00779 assert(_security != NULL); 00780 _interface->register_object(_security, *_client_objs); 00781 internal_event(State_Registration_Started); 00782 } 00783 00784 void ConnectorClient::state_registration_started() 00785 { 00786 // this state may be useful only for verifying the callbacks? 00787 } 00788 00789 void ConnectorClient::state_registration_success() 00790 { 00791 assert(_callback != NULL); 00792 _endpoint_info.internal_endpoint_name = _interface->internal_endpoint_name(); 00793 00794 //The endpoint is maximum 32 character long, we put bigger buffer for future extensions 00795 const int max_size = 64; 00796 uint8_t buffer[max_size]; 00797 00798 bool no_param_update = true; 00799 00800 if(ccs_get_string_item(KEY_INTERNAL_ENDPOINT, buffer, max_size, CCS_CONFIG_ITEM) == CCS_STATUS_SUCCESS) { 00801 if (strcmp((const char*)buffer, _endpoint_info.internal_endpoint_name.c_str()) != 0) { 00802 // Update is required as the stored KCM entry is different than _endpoint_info.internal_endpoint_name. 00803 no_param_update = false; 00804 } 00805 } 00806 00807 // Update INTERNAL_ENDPOINT setting only if there is no such entry or the value is not matching the 00808 // _endpoint_info.internal_endpoint_name. 00809 if(!no_param_update) { 00810 ccs_delete_item(KEY_INTERNAL_ENDPOINT, CCS_CONFIG_ITEM); 00811 ccs_set_item(KEY_INTERNAL_ENDPOINT, (const uint8_t*)_endpoint_info.internal_endpoint_name.c_str(), 00812 (size_t)_endpoint_info.internal_endpoint_name.size(), 00813 CCS_CONFIG_ITEM); 00814 } 00815 00816 _callback->registration_process_result(State_Registration_Success); 00817 } 00818 00819 void ConnectorClient::state_registration_failure() 00820 { 00821 assert(_callback != NULL); 00822 // maybe some additional canceling and/or leanup is needed here? 00823 _callback->registration_process_result(State_Registration_Failure); 00824 } 00825 00826 void ConnectorClient::state_unregistered() 00827 { 00828 assert(_callback != NULL); 00829 _callback->registration_process_result(State_Unregistered); 00830 } 00831 00832 void ConnectorClient::bootstrap_data_ready(M2MSecurity *security_object) 00833 { 00834 tr_info("ConnectorClient::bootstrap_data_ready"); 00835 ccs_status_e status = CCS_STATUS_ERROR; 00836 if(security_object) { 00837 // Update bootstrap credentials (we could skip this if we knew whether they were updated) 00838 // This will also update the address in case of first to claim 00839 status = set_bootstrap_credentials(security_object); 00840 if (status != CCS_STATUS_SUCCESS) { 00841 // TODO: what now? 00842 tr_error("ConnectorClient::bootstrap_data_ready - couldn't store bootstrap credentials"); 00843 } 00844 00845 // Clear the first to claim flag if it's active 00846 if (is_first_to_claim()) { 00847 status = clear_first_to_claim(); 00848 if (status != CCS_STATUS_SUCCESS) { 00849 // TODO: what now? 00850 tr_error("ConnectorClient::bootstrap_data_ready - couldn't clear first to claim flag!"); 00851 } 00852 } 00853 00854 // Bootstrap might delete m2mserver security object instance completely to force bootstrap 00855 // with new credentials, in that case delete the stored lwm2m credentials as well and re-bootstrap 00856 if (security_object->get_security_instance_id(M2MSecurity::M2MServer) == -1) { 00857 tr_info("ConnectorClient::bootstrap_data_ready() - Clearing lwm2m credentials"); 00858 // delete the old connector credentials when BS sends re-direction. 00859 ccs_delete_item(g_fcc_lwm2m_server_uri_name, CCS_CONFIG_ITEM); 00860 ccs_delete_item(g_fcc_lwm2m_server_ca_certificate_name, CCS_CERTIFICATE_ITEM); 00861 ccs_delete_item(g_fcc_lwm2m_device_certificate_name, CCS_CERTIFICATE_ITEM); 00862 ccs_delete_item(g_fcc_lwm2m_device_private_key_name, CCS_PRIVATE_KEY_ITEM); 00863 // Start re-bootstrap timer 00864 tr_info("ConnectorClient::bootstrap_data_ready() - Re-directing bootstrap in 100 milliseconds"); 00865 _rebootstrap_timer.start_timer(100, M2MTimerObserver::BootstrapFlowTimer, true); 00866 return; 00867 } 00868 // Bootstrap wrote M2MServer credentials, store them and also update first to claim status if it's configured 00869 else { 00870 #ifndef MBED_CLIENT_DISABLE_EST_FEATURE 00871 int32_t m2m_id = _security->get_security_instance_id(M2MSecurity::M2MServer); 00872 if (m2m_id >= 0 && 00873 _security->resource_value_int(M2MSecurity::SecurityMode, m2m_id) == M2MSecurity::EST) { 00874 // If EST is supported, continue to EST state to start EST enrollment 00875 tr_info("ConnectorClient::bootstrap_data_ready() - Continue to EST enrollment"); 00876 internal_event(State_EST_Start); 00877 return; 00878 } 00879 #endif // MBED_CLIENT_DISABLE_EST_FEATURE 00880 // Security mode was not EST, in that case just store the received credentials 00881 tr_info("ConnectorClient::bootstrap_data_ready() - Storing lwm2m credentials"); 00882 status = set_connector_credentials(security_object); 00883 } 00884 00885 if (status != CCS_STATUS_SUCCESS) { 00886 internal_event(State_Bootstrap_Failure); 00887 //Failed to store credentials, bootstrap failed 00888 _callback->connector_error(M2MInterface::MemoryFail, ERROR_NO_MEMORY); // Translated to error code ConnectMemoryConnectFail 00889 return; 00890 } else { 00891 tr_info("ConnectorClient::bootstrap_data_ready - set_credentials status %d", status); 00892 } 00893 } 00894 } 00895 00896 void ConnectorClient::bootstrap_done(M2MSecurity *security_object) 00897 { 00898 tr_info("ConnectorClient::bootstrap_done"); 00899 internal_event(State_Bootstrap_Success); 00900 } 00901 00902 void ConnectorClient::object_registered(M2MSecurity *security_object, const M2MServer &server_object) 00903 { 00904 internal_event(State_Registration_Success); 00905 } 00906 00907 void ConnectorClient::object_unregistered(M2MSecurity *server_object) 00908 { 00909 internal_event(State_Unregistered); 00910 } 00911 00912 void ConnectorClient::registration_updated(M2MSecurity *security_object, const M2MServer & server_object) 00913 { 00914 _callback->registration_process_result(State_Registration_Updated); 00915 } 00916 00917 void ConnectorClient::error(M2MInterface::Error error) 00918 { 00919 tr_error("ConnectorClient::error() - error: %d", error); 00920 assert(_callback != NULL); 00921 if (_current_state >= State_Registration_Start && 00922 use_bootstrap() && 00923 (error == M2MInterface::SecureConnectionFailed || 00924 error == M2MInterface::InvalidParameters)) { 00925 tr_info("ConnectorClient::error() - Error during lwm2m registration"); 00926 tr_info("ConnectorClient::error() - Clearing lwm2m credentials"); 00927 // delete the old connector credentials when DTLS handshake fails or 00928 // server rejects the registration. 00929 ccs_delete_item(g_fcc_lwm2m_server_uri_name, CCS_CONFIG_ITEM); 00930 ccs_delete_item(g_fcc_lwm2m_server_ca_certificate_name, CCS_CERTIFICATE_ITEM); 00931 ccs_delete_item(g_fcc_lwm2m_device_certificate_name, CCS_CERTIFICATE_ITEM); 00932 ccs_delete_item(g_fcc_lwm2m_device_private_key_name, CCS_PRIVATE_KEY_ITEM); 00933 // Delete the lwm2m security instance 00934 int32_t id = _security->get_security_instance_id(M2MSecurity::M2MServer); 00935 if (id >= 0) { 00936 _security->remove_object_instance(id); 00937 } 00938 // Start re-bootstrap timer 00939 tr_info("ConnectorClient::error() - Re-bootstrapping in 100 milliseconds"); 00940 _rebootstrap_timer.start_timer(100, M2MTimerObserver::BootstrapFlowTimer, true); 00941 } 00942 else { 00943 _callback->connector_error(error, _interface->error_description()); 00944 } 00945 } 00946 00947 void ConnectorClient::value_updated(M2MBase *base, M2MBase::BaseType type) 00948 { 00949 assert(_callback != NULL); 00950 _callback->value_updated(base, type); 00951 } 00952 00953 bool ConnectorClient::connector_credentials_available() 00954 { 00955 tr_debug("ConnectorClient::connector_credentials_available"); 00956 // Read 1 byte of lwm2m private key, should return real_size > 0 if it exists 00957 const int max_size = 1; 00958 uint8_t buffer; 00959 size_t real_size = 0; 00960 ccs_get_item(g_fcc_lwm2m_device_private_key_name, &buffer, max_size, &real_size, CCS_PRIVATE_KEY_ITEM); 00961 if (real_size > 0) { 00962 return true; 00963 } 00964 return false; 00965 } 00966 00967 bool ConnectorClient::use_bootstrap() 00968 { 00969 tr_debug("ConnectorClient::use_bootstrap"); 00970 size_t real_size = 0; 00971 uint8_t data[CONFIG_BOOLEAN_ITEM_SIZE] = {0}; 00972 uint32_t value = 0; 00973 ccs_status_e status = ccs_get_item(g_fcc_use_bootstrap_parameter_name, data, CONFIG_BOOLEAN_ITEM_SIZE, &real_size, CCS_CONFIG_ITEM); 00974 if (status == CCS_STATUS_SUCCESS) { 00975 memcpy(&value, data, CONFIG_BOOLEAN_ITEM_SIZE); 00976 // Return true if use_bootstrap is set 00977 if (value == 1) { 00978 return true; 00979 } 00980 } 00981 return false; 00982 } 00983 00984 00985 bool ConnectorClient::get_key(const char *key, const char *endpoint, char *&key_name) 00986 { 00987 if(key_name) { 00988 free(key_name); 00989 key_name = NULL; 00990 } 00991 00992 key_name = (char*)malloc(strlen(key)+strlen(endpoint)+1); 00993 if(key_name) { 00994 strcpy(key_name, key); 00995 strcat(key_name, endpoint); 00996 tr_debug("key %s", key_name); 00997 return true; 00998 } 00999 return false; 01000 } 01001 01002 ccs_status_e ConnectorClient::set_connector_credentials(M2MSecurity *security) 01003 { 01004 tr_debug("ConnectorClient::set_connector_credentials"); 01005 ccs_status_e status = CCS_STATUS_ERROR; 01006 01007 int32_t m2m_id = security->get_security_instance_id(M2MSecurity::M2MServer); 01008 if (m2m_id == -1) { 01009 return status; 01010 } 01011 01012 size_t buffer_size = MAX_CERTIFICATE_SIZE; 01013 uint8_t public_key[MAX_CERTIFICATE_SIZE]; 01014 uint8_t *public_key_ptr = (uint8_t*)&public_key; 01015 01016 // TODO! Update to use chain api 01017 if (security->resource_value_buffer(M2MSecurity::PublicKey, public_key_ptr, m2m_id, &buffer_size) != 0) { 01018 return status; 01019 } 01020 01021 char device_id[64]; 01022 memset(device_id, 0, 64); 01023 if (extract_field_from_certificate(public_key, buffer_size, "L", device_id)) { 01024 tr_info("ConnectorClient::set_connector_credentials - L internal_endpoint_name : %s", device_id); 01025 _endpoint_info.internal_endpoint_name = String(device_id); 01026 ccs_delete_item(KEY_INTERNAL_ENDPOINT, CCS_CONFIG_ITEM); 01027 status = ccs_set_item(KEY_INTERNAL_ENDPOINT,(uint8_t*)device_id, strlen(device_id), CCS_CONFIG_ITEM); 01028 } 01029 01030 memset(device_id, 0, 64); 01031 if (extract_field_from_certificate(public_key, buffer_size, "CN", device_id)) { 01032 tr_info("ConnectorClient::set_connector_credentials - CN endpoint_name : %s", device_id); 01033 _endpoint_info.endpoint_name = String(device_id); 01034 } 01035 01036 if(status == CCS_STATUS_SUCCESS) { 01037 ccs_status_e check_status = ccs_check_item(KEY_ACCOUNT_ID, CCS_CONFIG_ITEM); 01038 // Do not call delete if KEY does not exist. 01039 if ((check_status == CCS_STATUS_KEY_DOESNT_EXIST) || (check_status == CCS_STATUS_ERROR)) { 01040 tr_debug("No KEY_ACCOUNT_ID stored."); 01041 } else { 01042 ccs_delete_item(KEY_ACCOUNT_ID, CCS_CONFIG_ITEM); 01043 // AccountID optional so don't fail if unable to store 01044 ccs_set_item(KEY_ACCOUNT_ID, 01045 (const uint8_t*)_endpoint_info.account_id.c_str(), 01046 (size_t)_endpoint_info.account_id.size(), 01047 CCS_CONFIG_ITEM); 01048 } 01049 } 01050 01051 if (status == CCS_STATUS_SUCCESS) { 01052 status = ccs_set_item(g_fcc_lwm2m_server_uri_name, 01053 (const uint8_t*)security->resource_value_string(M2MSecurity::M2MServerUri, m2m_id).c_str(), 01054 (size_t)security->resource_value_string(M2MSecurity::M2MServerUri, m2m_id).size(), 01055 CCS_CONFIG_ITEM); 01056 } 01057 01058 M2MDevice *device = M2MInterfaceFactory::create_device(); 01059 if (status == CCS_STATUS_SUCCESS && device) { 01060 String temp = ""; 01061 uint32_t currenttime = (uint32_t)device->resource_value_int(M2MDevice::CurrentTime, 0); 01062 uint8_t data[4]; 01063 memcpy(data, ¤ttime, 4); 01064 ccs_delete_item(g_fcc_current_time_parameter_name, CCS_CONFIG_ITEM); 01065 ccs_set_item(g_fcc_current_time_parameter_name, data, 4, CCS_CONFIG_ITEM); 01066 01067 temp = device->resource_value_string(M2MDevice::Timezone, 0); 01068 if (temp.size() > 0) { 01069 ccs_delete_item(g_fcc_device_time_zone_parameter_name, CCS_CONFIG_ITEM); 01070 ccs_set_item(g_fcc_device_time_zone_parameter_name, (const uint8_t*)temp.c_str(), temp.size(), CCS_CONFIG_ITEM); 01071 } 01072 01073 temp = device->resource_value_string(M2MDevice::UTCOffset, 0); 01074 if (temp.size() > 0) { 01075 ccs_delete_item(g_fcc_offset_from_utc_parameter_name, CCS_CONFIG_ITEM); 01076 ccs_set_item(g_fcc_offset_from_utc_parameter_name, (const uint8_t*)temp.c_str(), temp.size(), CCS_CONFIG_ITEM); 01077 } 01078 01079 status = CCS_STATUS_SUCCESS; 01080 } 01081 else { 01082 tr_debug("No device object to store!"); 01083 } 01084 01085 return status; 01086 } 01087 01088 ccs_status_e ConnectorClient::set_bootstrap_credentials(M2MSecurity *security) 01089 { 01090 tr_debug("ConnectorClient::set_bootstrap_credentials"); 01091 ccs_status_e status = CCS_STATUS_ERROR; 01092 01093 size_t buffer_size = MAX_CERTIFICATE_SIZE; 01094 uint8_t key[MAX_CERTIFICATE_SIZE]; 01095 uint8_t *key_ptr = (uint8_t*)&key; 01096 01097 int32_t bs_id = security->get_security_instance_id(M2MSecurity::Bootstrap); 01098 if (bs_id == -1) { 01099 return status; 01100 } 01101 01102 // TODO! Update to use chain api 01103 if (security->resource_value_buffer(M2MSecurity::PublicKey, key_ptr, bs_id, &buffer_size) != 0) { 01104 return status; 01105 } 01106 01107 if (buffer_size) { 01108 ccs_delete_item(g_fcc_bootstrap_device_certificate_name, CCS_CERTIFICATE_ITEM); 01109 status = ccs_set_item(g_fcc_bootstrap_device_certificate_name, 01110 key_ptr, 01111 buffer_size, 01112 CCS_CERTIFICATE_ITEM); 01113 buffer_size = MAX_CERTIFICATE_SIZE; 01114 } 01115 01116 if (status == CCS_STATUS_SUCCESS) { 01117 if (security->resource_value_buffer(M2MSecurity::Secretkey, key_ptr, bs_id, &buffer_size) != 0) { 01118 status = CCS_STATUS_ERROR; 01119 buffer_size = 0; 01120 } 01121 01122 if(buffer_size) { 01123 ccs_delete_item(g_fcc_bootstrap_device_private_key_name, CCS_PRIVATE_KEY_ITEM); 01124 status = ccs_set_item(g_fcc_bootstrap_device_private_key_name, 01125 key_ptr, 01126 buffer_size, 01127 CCS_PRIVATE_KEY_ITEM); 01128 buffer_size = MAX_CERTIFICATE_SIZE; 01129 } 01130 } 01131 01132 if (status == CCS_STATUS_SUCCESS) { 01133 if (security->resource_value_buffer(M2MSecurity::ServerPublicKey, key_ptr, bs_id, &buffer_size) != 0) { 01134 status = CCS_STATUS_ERROR; 01135 buffer_size = 0; 01136 } 01137 01138 if (buffer_size) { 01139 ccs_delete_item(g_fcc_bootstrap_server_ca_certificate_name, CCS_CERTIFICATE_ITEM); 01140 status = ccs_set_item(g_fcc_bootstrap_server_ca_certificate_name, 01141 key_ptr, 01142 buffer_size, 01143 CCS_CERTIFICATE_ITEM); 01144 } 01145 } 01146 01147 if(status == CCS_STATUS_SUCCESS) { 01148 ccs_delete_item(g_fcc_bootstrap_server_uri_name, CCS_CONFIG_ITEM); 01149 status = ccs_set_item(g_fcc_bootstrap_server_uri_name, 01150 (const uint8_t*)security->resource_value_string(M2MSecurity::M2MServerUri, bs_id).c_str(), 01151 (size_t)security->resource_value_string(M2MSecurity::M2MServerUri, bs_id).size(), 01152 CCS_CONFIG_ITEM); 01153 } 01154 01155 return status; 01156 } 01157 01158 ccs_status_e ConnectorClient::store_bootstrap_address(M2MSecurity *security) 01159 { 01160 tr_debug("ConnectorClient::store_bootstrap_address"); 01161 ccs_status_e status = CCS_STATUS_ERROR; 01162 01163 const uint8_t *srv_address = NULL; 01164 int32_t bs_id = security->get_security_instance_id(M2MSecurity::Bootstrap); 01165 if (bs_id == -1) { 01166 return status; 01167 } 01168 01169 uint32_t srv_address_size = security->resource_value_buffer(M2MSecurity::M2MServerUri, srv_address, bs_id); 01170 01171 if(srv_address) { 01172 ccs_delete_item(g_fcc_bootstrap_server_uri_name, CCS_CONFIG_ITEM); 01173 status = ccs_set_item(g_fcc_bootstrap_server_uri_name, 01174 srv_address, 01175 (size_t)srv_address_size, 01176 CCS_CONFIG_ITEM); 01177 } 01178 01179 return status; 01180 } 01181 01182 ccs_status_e ConnectorClient::clear_first_to_claim() 01183 { 01184 tr_debug("ConnectorClient::clear_first_to_claim"); 01185 return ccs_delete_item(KEY_FIRST_TO_CLAIM, CCS_CONFIG_ITEM); 01186 } 01187 01188 01189 const ConnectorClientEndpointInfo *ConnectorClient::endpoint_info() const 01190 { 01191 return &_endpoint_info; 01192 } 01193 01194 bool ConnectorClient::bootstrap_credentials_stored_in_kcm() 01195 { 01196 size_t real_size = 0; 01197 ccs_status_e success = ccs_item_size(g_fcc_bootstrap_server_uri_name, &real_size, CCS_CONFIG_ITEM); 01198 // Return true if bootstrap uri exists in KCM 01199 if ((success == CCS_STATUS_SUCCESS) && real_size > 0) { 01200 return true; 01201 } else { 01202 return false; 01203 } 01204 } 01205 01206 bool ConnectorClient::is_first_to_claim() 01207 { 01208 size_t real_size = 0; 01209 uint8_t data[CONFIG_BOOLEAN_ITEM_SIZE] = {0}; 01210 uint32_t value = 0; 01211 ccs_status_e status = ccs_get_item(KEY_FIRST_TO_CLAIM, data, CONFIG_BOOLEAN_ITEM_SIZE, &real_size, CCS_CONFIG_ITEM); 01212 if (status == CCS_STATUS_SUCCESS) { 01213 memcpy(&value, data, CONFIG_BOOLEAN_ITEM_SIZE); 01214 // Return true if first to claim is set 01215 if (value == 1) { 01216 return true; 01217 } 01218 } 01219 return false; 01220 } 01221 01222 void ConnectorClient::timer_expired(M2MTimerObserver::Type type) 01223 { 01224 if (type == M2MTimerObserver::BootstrapFlowTimer) { 01225 start_bootstrap(); 01226 } 01227 } 01228 01229 #ifndef MBED_CLIENT_DISABLE_EST_FEATURE 01230 void ConnectorClient::est_enrollment_result(bool success, 01231 const uint8_t *payload_ptr, 01232 const uint16_t payload_len) 01233 { 01234 tr_debug("ConnectorClient::est_enrollment_result - %s", success ? "successful" : "failed"); 01235 tr_debug("ConnectorClient::est_enrollment_result - PublicKey size %d", (int)payload_len); 01236 01237 assert(_security != NULL); 01238 int32_t m2m_id = _security->get_security_instance_id(M2MSecurity::M2MServer); 01239 StartupSubStateRegistration state = State_EST_Failure; 01240 01241 if (success && payload_ptr && payload_len > 0 && m2m_id >= 0) { 01242 const uint8_t *ptr = payload_ptr; 01243 tr_debug("Payload start: %s", tr_array(payload_ptr, 10)); 01244 ccs_status_e ccs_status = ccs_parse_cert_chain_and_store((const uint8_t*)g_fcc_lwm2m_device_certificate_name, 01245 strlen(g_fcc_lwm2m_device_certificate_name), 01246 payload_ptr, 01247 payload_len); 01248 if (ccs_status != CCS_STATUS_SUCCESS) { 01249 tr_error("ConnectorClient::est_enrollment_result - storing certificate chain failed!"); 01250 } 01251 else { 01252 tr_info("ConnectorClient::est_enrollment_result() - Storing lwm2m credentials"); 01253 if (set_connector_credentials(_security) == CCS_STATUS_SUCCESS) { 01254 state = State_EST_Success; 01255 } 01256 } 01257 01258 } 01259 01260 internal_event(state); 01261 } 01262 01263 void ConnectorClient::est_post_data_cb(const uint8_t *buffer, 01264 size_t buffer_size, 01265 size_t total_size, 01266 void *context) 01267 { 01268 ConnectorClient *cc = static_cast<ConnectorClient*>(context); 01269 assert(cc); 01270 cc->est_enrollment_result(true, buffer, buffer_size); 01271 01272 } 01273 01274 void ConnectorClient::est_post_data_error_cb(get_data_req_error_t error_code, 01275 void *context) 01276 { 01277 ConnectorClient *cc = static_cast<ConnectorClient*>(context); 01278 assert(cc); 01279 cc->est_enrollment_result(false, NULL, 0); 01280 } 01281 #endif /* !MBED_CLIENT_DISABLE_EST_FEATURE */ 01282 01283 01284 M2MInterface::BindingMode ConnectorClient::transport_mode() 01285 { 01286 #ifdef MBED_CLOUD_CLIENT_TRANSPORT_MODE_UDP 01287 return M2MInterface::UDP; 01288 #elif defined MBED_CLOUD_CLIENT_TRANSPORT_MODE_TCP 01289 return M2MInterface::TCP; 01290 #elif defined MBED_CLOUD_CLIENT_TRANSPORT_MODE_UDP_QUEUE 01291 return M2MInterface::UDP_QUEUE; 01292 #elif defined MBED_CLOUD_CLIENT_TRANSPORT_MODE_TCP_QUEUE 01293 return M2MInterface::TCP_QUEUE; 01294 #else 01295 return M2MInterface::UDP; 01296 #endif 01297 } 01298 01299 void ConnectorClient::init_security_object() 01300 { 01301 if (_security) { 01302 for (int i = 0; i <= M2MSecurity::Bootstrap; i++) { 01303 // _security->create_object_instance() returns NULL if object already exists 01304 if (_security->create_object_instance((M2MSecurity::ServerType)i)) { 01305 M2MResource* res = _security->get_resource(M2MSecurity::ServerPublicKey, i); 01306 if (res) { 01307 res->set_resource_read_callback(read_security_object_data_from_kcm, this); 01308 res->set_resource_write_callback(write_security_object_data_to_kcm, this); 01309 } 01310 01311 res = _security->get_resource(M2MSecurity::PublicKey, i); 01312 if (res) { 01313 res->set_resource_read_callback(read_security_object_data_from_kcm, this); 01314 res->set_resource_write_callback(write_security_object_data_to_kcm, this); 01315 } 01316 01317 res = _security->get_resource(M2MSecurity::Secretkey, i); 01318 if (res) { 01319 res->set_resource_read_callback(read_security_object_data_from_kcm, this); 01320 res->set_resource_write_callback(write_security_object_data_to_kcm, this); 01321 } 01322 01323 res = _security->get_resource(M2MSecurity::OpenCertificateChain, i); 01324 if (res) { 01325 res->set_resource_read_callback(open_certificate_chain_callback, this); 01326 } 01327 01328 res = _security->get_resource(M2MSecurity::ReadDeviceCertificateChain, i); 01329 if (res) { 01330 res->set_resource_read_callback(read_certificate_chain_callback, this); 01331 } 01332 01333 res = _security->get_resource(M2MSecurity::CloseCertificateChain, i); 01334 if (res) { 01335 res->set_resource_read_callback(close_certificate_chain_callback, this); 01336 } 01337 } 01338 } 01339 } 01340 } 01341 01342 void *ConnectorClient::certificate_chain_handle() const 01343 { 01344 return _certificate_chain_handle; 01345 } 01346 01347 void ConnectorClient::set_certificate_chain_handle(void *cert_handle) 01348 { 01349 _certificate_chain_handle = cert_handle; 01350 }
Generated on Tue Jul 12 2022 16:24:09 by
1.7.2