Committer:
leothedragon
Date:
Sun Apr 18 15:20:23 2021 +0000
Revision:
0:25fa8795676b
DS

Who changed what in which revision?

UserRevisionLine numberNew contents of line
leothedragon 0:25fa8795676b 1 // ----------------------------------------------------------------------------
leothedragon 0:25fa8795676b 2 // Copyright 2016-2017 ARM Ltd.
leothedragon 0:25fa8795676b 3 //
leothedragon 0:25fa8795676b 4 // SPDX-License-Identifier: Apache-2.0
leothedragon 0:25fa8795676b 5 //
leothedragon 0:25fa8795676b 6 // Licensed under the Apache License, Version 2.0 (the "License");
leothedragon 0:25fa8795676b 7 // you may not use this file except in compliance with the License.
leothedragon 0:25fa8795676b 8 // You may obtain a copy of the License at
leothedragon 0:25fa8795676b 9 //
leothedragon 0:25fa8795676b 10 // http://www.apache.org/licenses/LICENSE-2.0
leothedragon 0:25fa8795676b 11 //
leothedragon 0:25fa8795676b 12 // Unless required by applicable law or agreed to in writing, software
leothedragon 0:25fa8795676b 13 // distributed under the License is distributed on an "AS IS" BASIS,
leothedragon 0:25fa8795676b 14 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
leothedragon 0:25fa8795676b 15 // See the License for the specific language governing permissions and
leothedragon 0:25fa8795676b 16 // limitations under the License.
leothedragon 0:25fa8795676b 17 // ----------------------------------------------------------------------------
leothedragon 0:25fa8795676b 18
leothedragon 0:25fa8795676b 19 // fixup the compilation on ARMCC for PRId32
leothedragon 0:25fa8795676b 20 #define __STDC_FORMAT_MACROS
leothedragon 0:25fa8795676b 21 #include <inttypes.h>
leothedragon 0:25fa8795676b 22
leothedragon 0:25fa8795676b 23 #include "include/ConnectorClient.h"
leothedragon 0:25fa8795676b 24 #include "include/CloudClientStorage.h"
leothedragon 0:25fa8795676b 25 #include "include/CertificateParser.h"
leothedragon 0:25fa8795676b 26
leothedragon 0:25fa8795676b 27 #ifndef MBED_CLIENT_DISABLE_EST_FEATURE
leothedragon 0:25fa8795676b 28 #include "include/EstClient.h"
leothedragon 0:25fa8795676b 29 #endif // !MBED_CLIENT_DISABLE_EST_FEATURE
leothedragon 0:25fa8795676b 30
leothedragon 0:25fa8795676b 31 #include "MbedCloudClient.h"
leothedragon 0:25fa8795676b 32 #include "mbed-client/m2mconstants.h"
leothedragon 0:25fa8795676b 33 #include "mbed-client/m2minterfacefactory.h"
leothedragon 0:25fa8795676b 34 #include "mbed-client/m2mdevice.h"
leothedragon 0:25fa8795676b 35 #include "mbed-client/m2mconstants.h"
leothedragon 0:25fa8795676b 36 #include "mbed-trace/mbed_trace.h"
leothedragon 0:25fa8795676b 37 #include "factory_configurator_client.h"
leothedragon 0:25fa8795676b 38 #include "key_config_manager.h"
leothedragon 0:25fa8795676b 39 #include "mbed-client/uriqueryparser.h"
leothedragon 0:25fa8795676b 40 #include "randLIB.h"
leothedragon 0:25fa8795676b 41
leothedragon 0:25fa8795676b 42 #include <assert.h>
leothedragon 0:25fa8795676b 43 #include <string.h>
leothedragon 0:25fa8795676b 44 #include <stdio.h>
leothedragon 0:25fa8795676b 45
leothedragon 0:25fa8795676b 46 #include "ns_hal_init.h"
leothedragon 0:25fa8795676b 47
leothedragon 0:25fa8795676b 48 #ifdef MBED_CONF_MBED_CLIENT_EVENT_LOOP_SIZE
leothedragon 0:25fa8795676b 49 #define MBED_CLIENT_EVENT_LOOP_SIZE MBED_CONF_MBED_CLIENT_EVENT_LOOP_SIZE
leothedragon 0:25fa8795676b 50 #else
leothedragon 0:25fa8795676b 51 #define MBED_CLIENT_EVENT_LOOP_SIZE 1024
leothedragon 0:25fa8795676b 52 #endif
leothedragon 0:25fa8795676b 53
leothedragon 0:25fa8795676b 54 #define TRACE_GROUP "mClt"
leothedragon 0:25fa8795676b 55
leothedragon 0:25fa8795676b 56 #define INTERNAL_ENDPOINT_PARAM "&iep="
leothedragon 0:25fa8795676b 57 #define DEFAULT_ENDPOINT "endpoint"
leothedragon 0:25fa8795676b 58 #define INTERFACE_ERROR "Client interface is not created. Restart"
leothedragon 0:25fa8795676b 59 #define CREDENTIAL_ERROR "Failed to read credentials from storage"
leothedragon 0:25fa8795676b 60 #define DEVICE_NOT_PROVISIONED "Device not provisioned"
leothedragon 0:25fa8795676b 61 #define CONNECTOR_ERROR_NO_MEMORY "Not enough memory to store LWM2M credentials"
leothedragon 0:25fa8795676b 62 #define CONNECTOR_BOOTSTRAP_AGAIN "Re-bootstrapping"
leothedragon 0:25fa8795676b 63
leothedragon 0:25fa8795676b 64 #ifndef MBED_CLIENT_DISABLE_EST_FEATURE
leothedragon 0:25fa8795676b 65 #define ERROR_EST_ENROLLMENT_REQUEST_FAILED "EST enrollment request failed"
leothedragon 0:25fa8795676b 66 #define LWM2M_CSR_SUBJECT_FORMAT "L=%s,OU=%s,CN=%s"
leothedragon 0:25fa8795676b 67 #endif // !MBED_CLIENT_DISABLE_EST_FEATURE
leothedragon 0:25fa8795676b 68
leothedragon 0:25fa8795676b 69 #define MAX_REBOOTSTRAP_TIMEOUT 21600 // 6 hours
leothedragon 0:25fa8795676b 70
leothedragon 0:25fa8795676b 71 // XXX: nothing here yet
leothedragon 0:25fa8795676b 72 class EventData {
leothedragon 0:25fa8795676b 73
leothedragon 0:25fa8795676b 74 };
leothedragon 0:25fa8795676b 75
leothedragon 0:25fa8795676b 76 static int read_callback_helper(const char *key, void *buffer, size_t *buffer_len)
leothedragon 0:25fa8795676b 77 {
leothedragon 0:25fa8795676b 78 size_t cert_size = 0;
leothedragon 0:25fa8795676b 79 if (strcmp(key, g_fcc_lwm2m_device_private_key_name) == 0 ||
leothedragon 0:25fa8795676b 80 strcmp(key, g_fcc_bootstrap_device_private_key_name) == 0) {
leothedragon 0:25fa8795676b 81 if (ccs_item_size(key, buffer_len, CCS_PRIVATE_KEY_ITEM) != CCS_STATUS_SUCCESS) {
leothedragon 0:25fa8795676b 82 *buffer_len = 0;
leothedragon 0:25fa8795676b 83 return CCS_STATUS_ERROR;
leothedragon 0:25fa8795676b 84 }
leothedragon 0:25fa8795676b 85
leothedragon 0:25fa8795676b 86 if (ccs_get_item(key, (uint8_t*)buffer, *buffer_len, &cert_size, CCS_PRIVATE_KEY_ITEM) != CCS_STATUS_SUCCESS) {
leothedragon 0:25fa8795676b 87 *buffer_len = 0;
leothedragon 0:25fa8795676b 88 return CCS_STATUS_ERROR;
leothedragon 0:25fa8795676b 89 }
leothedragon 0:25fa8795676b 90 } else {
leothedragon 0:25fa8795676b 91 if (ccs_item_size(key, buffer_len, CCS_CERTIFICATE_ITEM) != CCS_STATUS_SUCCESS) {
leothedragon 0:25fa8795676b 92 *buffer_len = 0;
leothedragon 0:25fa8795676b 93 return CCS_STATUS_ERROR;
leothedragon 0:25fa8795676b 94 }
leothedragon 0:25fa8795676b 95
leothedragon 0:25fa8795676b 96 if (ccs_get_item(key, (uint8_t*)buffer, *buffer_len, &cert_size, CCS_CERTIFICATE_ITEM) != CCS_STATUS_SUCCESS) {
leothedragon 0:25fa8795676b 97 *buffer_len = 0;
leothedragon 0:25fa8795676b 98 return CCS_STATUS_ERROR;
leothedragon 0:25fa8795676b 99 }
leothedragon 0:25fa8795676b 100 }
leothedragon 0:25fa8795676b 101
leothedragon 0:25fa8795676b 102 *buffer_len = cert_size;
leothedragon 0:25fa8795676b 103
leothedragon 0:25fa8795676b 104 return CCS_STATUS_SUCCESS;
leothedragon 0:25fa8795676b 105 }
leothedragon 0:25fa8795676b 106
leothedragon 0:25fa8795676b 107 static bool write_security_object_data_to_kcm(const M2MResourceBase& resource, const uint8_t *buffer, const size_t buffer_size, void */*client_args*/)
leothedragon 0:25fa8795676b 108 {
leothedragon 0:25fa8795676b 109 ccs_status_e status = CCS_STATUS_ERROR;
leothedragon 0:25fa8795676b 110 uint32_t resource_id = resource.name_id();
leothedragon 0:25fa8795676b 111 uint16_t object_instance_id = resource.object_instance_id();
leothedragon 0:25fa8795676b 112
leothedragon 0:25fa8795676b 113 switch (resource_id) {
leothedragon 0:25fa8795676b 114 case M2MSecurity::PublicKey:
leothedragon 0:25fa8795676b 115 if (object_instance_id == M2MSecurity::Bootstrap) {
leothedragon 0:25fa8795676b 116 ccs_delete_item(g_fcc_bootstrap_device_certificate_name, CCS_CERTIFICATE_ITEM);
leothedragon 0:25fa8795676b 117 status = ccs_set_item(g_fcc_bootstrap_device_certificate_name, buffer, buffer_size, CCS_CERTIFICATE_ITEM);
leothedragon 0:25fa8795676b 118 } else {
leothedragon 0:25fa8795676b 119 ccs_delete_item(g_fcc_lwm2m_device_certificate_name, CCS_CERTIFICATE_ITEM);
leothedragon 0:25fa8795676b 120 status = ccs_set_item(g_fcc_lwm2m_device_certificate_name, buffer, buffer_size, CCS_CERTIFICATE_ITEM);
leothedragon 0:25fa8795676b 121 }
leothedragon 0:25fa8795676b 122 break;
leothedragon 0:25fa8795676b 123
leothedragon 0:25fa8795676b 124 case M2MSecurity::ServerPublicKey:
leothedragon 0:25fa8795676b 125 if (object_instance_id == M2MSecurity::Bootstrap) {
leothedragon 0:25fa8795676b 126 ccs_delete_item(g_fcc_bootstrap_server_ca_certificate_name, CCS_CERTIFICATE_ITEM);
leothedragon 0:25fa8795676b 127 status = ccs_set_item(g_fcc_bootstrap_server_ca_certificate_name, buffer, buffer_size, CCS_CERTIFICATE_ITEM);
leothedragon 0:25fa8795676b 128 } else {
leothedragon 0:25fa8795676b 129 ccs_delete_item(g_fcc_lwm2m_server_ca_certificate_name, CCS_CERTIFICATE_ITEM);
leothedragon 0:25fa8795676b 130 status = ccs_set_item(g_fcc_lwm2m_server_ca_certificate_name, buffer, buffer_size, CCS_CERTIFICATE_ITEM);
leothedragon 0:25fa8795676b 131 }
leothedragon 0:25fa8795676b 132 break;
leothedragon 0:25fa8795676b 133
leothedragon 0:25fa8795676b 134 case M2MSecurity::Secretkey:
leothedragon 0:25fa8795676b 135 if (object_instance_id == M2MSecurity::Bootstrap) {
leothedragon 0:25fa8795676b 136 ccs_delete_item(g_fcc_bootstrap_device_private_key_name, CCS_PRIVATE_KEY_ITEM);
leothedragon 0:25fa8795676b 137 status = ccs_set_item(g_fcc_bootstrap_device_private_key_name, buffer, buffer_size, CCS_PRIVATE_KEY_ITEM);
leothedragon 0:25fa8795676b 138 } else {
leothedragon 0:25fa8795676b 139 ccs_delete_item(g_fcc_lwm2m_device_private_key_name, CCS_PRIVATE_KEY_ITEM);
leothedragon 0:25fa8795676b 140 status = ccs_set_item(g_fcc_lwm2m_device_private_key_name, buffer, buffer_size, CCS_PRIVATE_KEY_ITEM);
leothedragon 0:25fa8795676b 141 }
leothedragon 0:25fa8795676b 142 break;
leothedragon 0:25fa8795676b 143
leothedragon 0:25fa8795676b 144 default:
leothedragon 0:25fa8795676b 145 break;
leothedragon 0:25fa8795676b 146 }
leothedragon 0:25fa8795676b 147
leothedragon 0:25fa8795676b 148 return (status == CCS_STATUS_SUCCESS) ? true : false;
leothedragon 0:25fa8795676b 149 }
leothedragon 0:25fa8795676b 150
leothedragon 0:25fa8795676b 151 static int read_security_object_data_from_kcm(const M2MResourceBase& resource, void *buffer, size_t *buffer_len, void */*client_args*/)
leothedragon 0:25fa8795676b 152 {
leothedragon 0:25fa8795676b 153 uint32_t resource_id = resource.name_id();
leothedragon 0:25fa8795676b 154 uint16_t object_instance_id = resource.object_instance_id();
leothedragon 0:25fa8795676b 155 switch (resource_id) {
leothedragon 0:25fa8795676b 156 case M2MSecurity::PublicKey:
leothedragon 0:25fa8795676b 157 if (object_instance_id == M2MSecurity::Bootstrap) {
leothedragon 0:25fa8795676b 158 return read_callback_helper(g_fcc_bootstrap_device_certificate_name, buffer, buffer_len);
leothedragon 0:25fa8795676b 159 } else {
leothedragon 0:25fa8795676b 160 return read_callback_helper(g_fcc_lwm2m_device_certificate_name, buffer, buffer_len);
leothedragon 0:25fa8795676b 161 }
leothedragon 0:25fa8795676b 162
leothedragon 0:25fa8795676b 163 case M2MSecurity::ServerPublicKey:
leothedragon 0:25fa8795676b 164 if (object_instance_id == M2MSecurity::Bootstrap) {
leothedragon 0:25fa8795676b 165 return read_callback_helper(g_fcc_bootstrap_server_ca_certificate_name, buffer, buffer_len);
leothedragon 0:25fa8795676b 166 } else {
leothedragon 0:25fa8795676b 167 return read_callback_helper(g_fcc_lwm2m_server_ca_certificate_name, buffer, buffer_len);
leothedragon 0:25fa8795676b 168 }
leothedragon 0:25fa8795676b 169
leothedragon 0:25fa8795676b 170 case M2MSecurity::Secretkey:
leothedragon 0:25fa8795676b 171 if (object_instance_id == M2MSecurity::Bootstrap) {
leothedragon 0:25fa8795676b 172 return read_callback_helper(g_fcc_bootstrap_device_private_key_name, buffer, buffer_len);
leothedragon 0:25fa8795676b 173 } else {
leothedragon 0:25fa8795676b 174 return read_callback_helper(g_fcc_lwm2m_device_private_key_name, buffer, buffer_len);
leothedragon 0:25fa8795676b 175 }
leothedragon 0:25fa8795676b 176
leothedragon 0:25fa8795676b 177 default:
leothedragon 0:25fa8795676b 178 break;
leothedragon 0:25fa8795676b 179 }
leothedragon 0:25fa8795676b 180
leothedragon 0:25fa8795676b 181 return CCS_STATUS_ERROR;
leothedragon 0:25fa8795676b 182 }
leothedragon 0:25fa8795676b 183
leothedragon 0:25fa8795676b 184 static int open_certificate_chain_callback(const M2MResourceBase& resource, void */*buffer*/, size_t *chain_size, void *client_args)
leothedragon 0:25fa8795676b 185 {
leothedragon 0:25fa8795676b 186 void *handle = NULL;
leothedragon 0:25fa8795676b 187 uint16_t object_instance_id = resource.object_instance_id();
leothedragon 0:25fa8795676b 188 ConnectorClient *client = (ConnectorClient*)client_args;
leothedragon 0:25fa8795676b 189 if (object_instance_id == M2MSecurity::Bootstrap) {
leothedragon 0:25fa8795676b 190 handle = ccs_open_certificate_chain(g_fcc_bootstrap_device_certificate_name, chain_size);
leothedragon 0:25fa8795676b 191 client->set_certificate_chain_handle(handle);
leothedragon 0:25fa8795676b 192 } else {
leothedragon 0:25fa8795676b 193 handle = ccs_open_certificate_chain(g_fcc_lwm2m_device_certificate_name, chain_size);
leothedragon 0:25fa8795676b 194 client->set_certificate_chain_handle(handle);
leothedragon 0:25fa8795676b 195 }
leothedragon 0:25fa8795676b 196
leothedragon 0:25fa8795676b 197 return (handle) ? CCS_STATUS_SUCCESS : CCS_STATUS_ERROR;
leothedragon 0:25fa8795676b 198 }
leothedragon 0:25fa8795676b 199
leothedragon 0:25fa8795676b 200 static int read_certificate_chain_callback(const M2MResourceBase& /*resource*/, void *buffer, size_t *buffer_len, void *client_args)
leothedragon 0:25fa8795676b 201 {
leothedragon 0:25fa8795676b 202 ConnectorClient *client = (ConnectorClient*) client_args;
leothedragon 0:25fa8795676b 203 ccs_status_e status = CCS_STATUS_ERROR;
leothedragon 0:25fa8795676b 204 if (client->certificate_chain_handle()) {
leothedragon 0:25fa8795676b 205 status = ccs_get_next_cert_chain(client->certificate_chain_handle(), buffer, buffer_len);
leothedragon 0:25fa8795676b 206 }
leothedragon 0:25fa8795676b 207
leothedragon 0:25fa8795676b 208 return status;
leothedragon 0:25fa8795676b 209 }
leothedragon 0:25fa8795676b 210
leothedragon 0:25fa8795676b 211 static int close_certificate_chain_callback(const M2MResourceBase& /*resource*/, void */*buffer*/, size_t *, void *client_args)
leothedragon 0:25fa8795676b 212 {
leothedragon 0:25fa8795676b 213 ccs_status_e status = CCS_STATUS_ERROR;
leothedragon 0:25fa8795676b 214 ConnectorClient *client = (ConnectorClient*) client_args;
leothedragon 0:25fa8795676b 215 if (client->certificate_chain_handle()) {
leothedragon 0:25fa8795676b 216 status = ccs_close_certificate_chain(client->certificate_chain_handle());
leothedragon 0:25fa8795676b 217 client->set_certificate_chain_handle(NULL);
leothedragon 0:25fa8795676b 218 }
leothedragon 0:25fa8795676b 219 return status;
leothedragon 0:25fa8795676b 220 }
leothedragon 0:25fa8795676b 221
leothedragon 0:25fa8795676b 222 ConnectorClient::ConnectorClient(ConnectorClientCallback* callback)
leothedragon 0:25fa8795676b 223 : _callback(callback),
leothedragon 0:25fa8795676b 224 _current_state(State_Bootstrap_Start),
leothedragon 0:25fa8795676b 225 _event_generated(false), _state_engine_running(false),
leothedragon 0:25fa8795676b 226 _setup_complete(false),
leothedragon 0:25fa8795676b 227 _interface(NULL), _security(NULL),
leothedragon 0:25fa8795676b 228 _endpoint_info(M2MSecurity::Certificate), _client_objs(NULL),
leothedragon 0:25fa8795676b 229 _rebootstrap_timer(*this), _bootstrap_security_instance(1),
leothedragon 0:25fa8795676b 230 _lwm2m_security_instance(0), _certificate_chain_handle(NULL)
leothedragon 0:25fa8795676b 231 #ifndef MBED_CLIENT_DISABLE_EST_FEATURE
leothedragon 0:25fa8795676b 232 ,_est_client(*this)
leothedragon 0:25fa8795676b 233 #endif // !MBED_CLIENT_DISABLE_EST_FEATURE
leothedragon 0:25fa8795676b 234
leothedragon 0:25fa8795676b 235 {
leothedragon 0:25fa8795676b 236 assert(_callback != NULL);
leothedragon 0:25fa8795676b 237
leothedragon 0:25fa8795676b 238 _rebootstrap_time = randLIB_get_random_in_range(1, 10);
leothedragon 0:25fa8795676b 239 }
leothedragon 0:25fa8795676b 240
leothedragon 0:25fa8795676b 241
leothedragon 0:25fa8795676b 242 ConnectorClient::~ConnectorClient()
leothedragon 0:25fa8795676b 243 {
leothedragon 0:25fa8795676b 244 uninitialize_storage();
leothedragon 0:25fa8795676b 245 M2MDevice::delete_instance();
leothedragon 0:25fa8795676b 246 M2MSecurity::delete_instance();
leothedragon 0:25fa8795676b 247 delete _interface;
leothedragon 0:25fa8795676b 248 }
leothedragon 0:25fa8795676b 249
leothedragon 0:25fa8795676b 250 bool ConnectorClient::setup()
leothedragon 0:25fa8795676b 251 {
leothedragon 0:25fa8795676b 252 // the setup() may be called again after connection has been closed so let's avoid leaks
leothedragon 0:25fa8795676b 253 if (_setup_complete == false) {
leothedragon 0:25fa8795676b 254
leothedragon 0:25fa8795676b 255 // The ns_hal_init() needs to be called by someone before create_interface(),
leothedragon 0:25fa8795676b 256 // as it will also initialize the tasklet.
leothedragon 0:25fa8795676b 257 ns_hal_init(NULL, MBED_CLIENT_EVENT_LOOP_SIZE, NULL, NULL);
leothedragon 0:25fa8795676b 258
leothedragon 0:25fa8795676b 259 // Create the lwm2m server security object we need always
leothedragon 0:25fa8795676b 260 M2MSecurity *security = M2MInterfaceFactory::create_security(M2MSecurity::M2MServer);
leothedragon 0:25fa8795676b 261 M2MInterface *interface = M2MInterfaceFactory::create_interface(*this,
leothedragon 0:25fa8795676b 262 DEFAULT_ENDPOINT, // endpoint name string
leothedragon 0:25fa8795676b 263 MBED_CLOUD_CLIENT_ENDPOINT_TYPE, // endpoint type string
leothedragon 0:25fa8795676b 264 MBED_CLOUD_CLIENT_LIFETIME, // lifetime
leothedragon 0:25fa8795676b 265 MBED_CLOUD_CLIENT_LISTEN_PORT, // listen port
leothedragon 0:25fa8795676b 266 _endpoint_info.account_id, // domain string
leothedragon 0:25fa8795676b 267 transport_mode(), // binding mode
leothedragon 0:25fa8795676b 268 M2MInterface::LwIP_IPv4); // network stack
leothedragon 0:25fa8795676b 269
leothedragon 0:25fa8795676b 270 if ((security == NULL) || (interface == NULL)) {
leothedragon 0:25fa8795676b 271 M2MSecurity::delete_instance();
leothedragon 0:25fa8795676b 272 delete interface;
leothedragon 0:25fa8795676b 273 } else {
leothedragon 0:25fa8795676b 274 if (initialize_storage() == CCS_STATUS_SUCCESS) {
leothedragon 0:25fa8795676b 275 _security = security;
leothedragon 0:25fa8795676b 276 _interface = interface;
leothedragon 0:25fa8795676b 277 _setup_complete = true;
leothedragon 0:25fa8795676b 278 }
leothedragon 0:25fa8795676b 279 }
leothedragon 0:25fa8795676b 280 }
leothedragon 0:25fa8795676b 281
leothedragon 0:25fa8795676b 282 return _setup_complete;
leothedragon 0:25fa8795676b 283 }
leothedragon 0:25fa8795676b 284
leothedragon 0:25fa8795676b 285 #ifndef MBED_CLIENT_DISABLE_EST_FEATURE
leothedragon 0:25fa8795676b 286 const EstClient &ConnectorClient::est_client()
leothedragon 0:25fa8795676b 287 {
leothedragon 0:25fa8795676b 288 return _est_client;
leothedragon 0:25fa8795676b 289 }
leothedragon 0:25fa8795676b 290 #endif // !MBED_CLIENT_DISABLE_EST_FEATURE
leothedragon 0:25fa8795676b 291
leothedragon 0:25fa8795676b 292 void ConnectorClient::start_bootstrap()
leothedragon 0:25fa8795676b 293 {
leothedragon 0:25fa8795676b 294 tr_debug("ConnectorClient::start_bootstrap()");
leothedragon 0:25fa8795676b 295
leothedragon 0:25fa8795676b 296 assert(_callback != NULL);
leothedragon 0:25fa8795676b 297 assert(_setup_complete);
leothedragon 0:25fa8795676b 298
leothedragon 0:25fa8795676b 299 init_security_object();
leothedragon 0:25fa8795676b 300 // Stop rebootstrap timer if it was running
leothedragon 0:25fa8795676b 301 _rebootstrap_timer.stop_timer();
leothedragon 0:25fa8795676b 302
leothedragon 0:25fa8795676b 303 if (create_bootstrap_object()) {
leothedragon 0:25fa8795676b 304 _interface->update_endpoint(_endpoint_info.endpoint_name);
leothedragon 0:25fa8795676b 305 _interface->update_domain(_endpoint_info.account_id);
leothedragon 0:25fa8795676b 306 internal_event(State_Bootstrap_Start);
leothedragon 0:25fa8795676b 307 } else {
leothedragon 0:25fa8795676b 308 tr_error("ConnectorClient::start_bootstrap() - bootstrap object fail");
leothedragon 0:25fa8795676b 309 }
leothedragon 0:25fa8795676b 310 state_engine();
leothedragon 0:25fa8795676b 311 }
leothedragon 0:25fa8795676b 312
leothedragon 0:25fa8795676b 313 void ConnectorClient::start_registration(M2MBaseList* client_objs)
leothedragon 0:25fa8795676b 314 {
leothedragon 0:25fa8795676b 315 tr_debug("ConnectorClient::start_registration()");
leothedragon 0:25fa8795676b 316
leothedragon 0:25fa8795676b 317 assert(_callback != NULL);
leothedragon 0:25fa8795676b 318 assert(_setup_complete);
leothedragon 0:25fa8795676b 319
leothedragon 0:25fa8795676b 320 init_security_object();
leothedragon 0:25fa8795676b 321 _client_objs = client_objs;
leothedragon 0:25fa8795676b 322
leothedragon 0:25fa8795676b 323 // XXX: actually this call should be external_event() to match the pattern used in other m2m classes
leothedragon 0:25fa8795676b 324 if (create_register_object()) {
leothedragon 0:25fa8795676b 325 if(_security->get_security_instance_id(M2MSecurity::M2MServer) >= 0) {
leothedragon 0:25fa8795676b 326 _interface->update_endpoint(_endpoint_info.endpoint_name);
leothedragon 0:25fa8795676b 327 _interface->update_domain(_endpoint_info.account_id);
leothedragon 0:25fa8795676b 328 internal_event(State_Registration_Start);
leothedragon 0:25fa8795676b 329 } else {
leothedragon 0:25fa8795676b 330 tr_error("ConnectorClient::start_registration(): failed to create objs");
leothedragon 0:25fa8795676b 331 _callback->connector_error(M2MInterface::InvalidParameters, INTERFACE_ERROR);
leothedragon 0:25fa8795676b 332 }
leothedragon 0:25fa8795676b 333 } else {
leothedragon 0:25fa8795676b 334 tr_error("ConnectorClient::start_registration - failed to read credentials");
leothedragon 0:25fa8795676b 335 _callback->connector_error((M2MInterface::Error)MbedCloudClient::ConnectorFailedToReadCredentials, CREDENTIAL_ERROR);
leothedragon 0:25fa8795676b 336 }
leothedragon 0:25fa8795676b 337 state_engine();
leothedragon 0:25fa8795676b 338 }
leothedragon 0:25fa8795676b 339
leothedragon 0:25fa8795676b 340 M2MInterface * ConnectorClient::m2m_interface()
leothedragon 0:25fa8795676b 341 {
leothedragon 0:25fa8795676b 342 return _interface;
leothedragon 0:25fa8795676b 343 }
leothedragon 0:25fa8795676b 344
leothedragon 0:25fa8795676b 345 void ConnectorClient::update_registration()
leothedragon 0:25fa8795676b 346 {
leothedragon 0:25fa8795676b 347 if(_interface && _security && _security->get_security_instance_id(M2MSecurity::M2MServer) >= 0) {
leothedragon 0:25fa8795676b 348 if (_client_objs != NULL) {
leothedragon 0:25fa8795676b 349 _interface->update_registration(_security, *_client_objs);
leothedragon 0:25fa8795676b 350 }
leothedragon 0:25fa8795676b 351 else {
leothedragon 0:25fa8795676b 352 _interface->update_registration(_security);
leothedragon 0:25fa8795676b 353 }
leothedragon 0:25fa8795676b 354 }
leothedragon 0:25fa8795676b 355 }
leothedragon 0:25fa8795676b 356
leothedragon 0:25fa8795676b 357 // generates an internal event. called from within a state
leothedragon 0:25fa8795676b 358 // function to transition to a new state
leothedragon 0:25fa8795676b 359 void ConnectorClient::internal_event(StartupSubStateRegistration new_state)
leothedragon 0:25fa8795676b 360 {
leothedragon 0:25fa8795676b 361 tr_debug("ConnectorClient::internal_event: state: %d -> %d", _current_state, new_state);
leothedragon 0:25fa8795676b 362 _event_generated = true;
leothedragon 0:25fa8795676b 363 _current_state = new_state;
leothedragon 0:25fa8795676b 364
leothedragon 0:25fa8795676b 365 // Avoid recursive chain which eats too much of stack
leothedragon 0:25fa8795676b 366 if (!_state_engine_running) {
leothedragon 0:25fa8795676b 367 state_engine();
leothedragon 0:25fa8795676b 368 }
leothedragon 0:25fa8795676b 369 }
leothedragon 0:25fa8795676b 370
leothedragon 0:25fa8795676b 371 // the state engine executes the state machine states
leothedragon 0:25fa8795676b 372 void ConnectorClient::state_engine(void)
leothedragon 0:25fa8795676b 373 {
leothedragon 0:25fa8795676b 374 tr_debug("ConnectorClient::state_engine");
leothedragon 0:25fa8795676b 375
leothedragon 0:25fa8795676b 376 // this simple flagging gets rid of recursive calls to this method
leothedragon 0:25fa8795676b 377 _state_engine_running = true;
leothedragon 0:25fa8795676b 378
leothedragon 0:25fa8795676b 379 // while events are being generated keep executing states
leothedragon 0:25fa8795676b 380 while (_event_generated) {
leothedragon 0:25fa8795676b 381 _event_generated = false; // event used up, reset flag
leothedragon 0:25fa8795676b 382
leothedragon 0:25fa8795676b 383 state_function(_current_state);
leothedragon 0:25fa8795676b 384 }
leothedragon 0:25fa8795676b 385
leothedragon 0:25fa8795676b 386 _state_engine_running = false;
leothedragon 0:25fa8795676b 387 }
leothedragon 0:25fa8795676b 388
leothedragon 0:25fa8795676b 389 void ConnectorClient::state_function(StartupSubStateRegistration current_state)
leothedragon 0:25fa8795676b 390 {
leothedragon 0:25fa8795676b 391 switch (current_state) {
leothedragon 0:25fa8795676b 392 case State_Bootstrap_Start:
leothedragon 0:25fa8795676b 393 state_bootstrap_start();
leothedragon 0:25fa8795676b 394 break;
leothedragon 0:25fa8795676b 395 case State_Bootstrap_Started:
leothedragon 0:25fa8795676b 396 state_bootstrap_started();
leothedragon 0:25fa8795676b 397 break;
leothedragon 0:25fa8795676b 398 case State_Bootstrap_Success:
leothedragon 0:25fa8795676b 399 state_bootstrap_success();
leothedragon 0:25fa8795676b 400 break;
leothedragon 0:25fa8795676b 401 case State_Bootstrap_Failure:
leothedragon 0:25fa8795676b 402 state_bootstrap_failure();
leothedragon 0:25fa8795676b 403 break;
leothedragon 0:25fa8795676b 404 #ifndef MBED_CLIENT_DISABLE_EST_FEATURE
leothedragon 0:25fa8795676b 405 case State_EST_Start:
leothedragon 0:25fa8795676b 406 state_est_start();
leothedragon 0:25fa8795676b 407 break;
leothedragon 0:25fa8795676b 408 case State_EST_Started:
leothedragon 0:25fa8795676b 409 state_est_started();
leothedragon 0:25fa8795676b 410 break;
leothedragon 0:25fa8795676b 411 case State_EST_Success:
leothedragon 0:25fa8795676b 412 state_est_success();
leothedragon 0:25fa8795676b 413 break;
leothedragon 0:25fa8795676b 414 case State_EST_Failure:
leothedragon 0:25fa8795676b 415 state_est_failure();
leothedragon 0:25fa8795676b 416 break;
leothedragon 0:25fa8795676b 417 #endif // !MBED_CLIENT_DISABLE_EST_FEATURE
leothedragon 0:25fa8795676b 418 case State_Registration_Start:
leothedragon 0:25fa8795676b 419 state_registration_start();
leothedragon 0:25fa8795676b 420 break;
leothedragon 0:25fa8795676b 421 case State_Registration_Started:
leothedragon 0:25fa8795676b 422 state_registration_started();
leothedragon 0:25fa8795676b 423 break;
leothedragon 0:25fa8795676b 424 case State_Registration_Success:
leothedragon 0:25fa8795676b 425 state_registration_success();
leothedragon 0:25fa8795676b 426 break;
leothedragon 0:25fa8795676b 427 case State_Registration_Failure:
leothedragon 0:25fa8795676b 428 state_registration_failure();
leothedragon 0:25fa8795676b 429 break;
leothedragon 0:25fa8795676b 430 case State_Unregistered:
leothedragon 0:25fa8795676b 431 state_unregistered();
leothedragon 0:25fa8795676b 432 break;
leothedragon 0:25fa8795676b 433 default:
leothedragon 0:25fa8795676b 434 break;
leothedragon 0:25fa8795676b 435 }
leothedragon 0:25fa8795676b 436 }
leothedragon 0:25fa8795676b 437
leothedragon 0:25fa8795676b 438 /*
leothedragon 0:25fa8795676b 439 * Creates register server object with mbed device server address and other parameters
leothedragon 0:25fa8795676b 440 * required for client to connect to mbed device server.
leothedragon 0:25fa8795676b 441 */
leothedragon 0:25fa8795676b 442 bool ConnectorClient::create_register_object()
leothedragon 0:25fa8795676b 443 {
leothedragon 0:25fa8795676b 444 tr_debug("ConnectorClient::create_register_object()");
leothedragon 0:25fa8795676b 445 int32_t m2m_id = _security->get_security_instance_id(M2MSecurity::M2MServer);
leothedragon 0:25fa8795676b 446 if (m2m_id == -1) {
leothedragon 0:25fa8795676b 447 init_security_object();
leothedragon 0:25fa8795676b 448 }
leothedragon 0:25fa8795676b 449
leothedragon 0:25fa8795676b 450 m2m_id = _security->get_security_instance_id(M2MSecurity::M2MServer);
leothedragon 0:25fa8795676b 451 if (m2m_id == -1) {
leothedragon 0:25fa8795676b 452 tr_error("ConnectorClient::create_register_object() - failed to read security object!");
leothedragon 0:25fa8795676b 453 return false;
leothedragon 0:25fa8795676b 454 }
leothedragon 0:25fa8795676b 455
leothedragon 0:25fa8795676b 456 // Allocate scratch buffer, this will be used to copy parameters from storage to security object
leothedragon 0:25fa8795676b 457 const int max_size = MAX_CERTIFICATE_SIZE;
leothedragon 0:25fa8795676b 458 uint8_t *buffer = (uint8_t*)malloc(max_size);
leothedragon 0:25fa8795676b 459 size_t real_size = 0;
leothedragon 0:25fa8795676b 460 bool success = false;
leothedragon 0:25fa8795676b 461
leothedragon 0:25fa8795676b 462 if (_security->set_resource_value(M2MSecurity::BootstrapServer, M2MSecurity::M2MServer, m2m_id)) {
leothedragon 0:25fa8795676b 463 success = true;
leothedragon 0:25fa8795676b 464 }
leothedragon 0:25fa8795676b 465
leothedragon 0:25fa8795676b 466 // Add ResourceID's and values to the security ObjectID/ObjectInstance
leothedragon 0:25fa8795676b 467 if (success) {
leothedragon 0:25fa8795676b 468 success = false;
leothedragon 0:25fa8795676b 469 if (_security->set_resource_value(M2MSecurity::SecurityMode, _endpoint_info.mode, m2m_id)) {
leothedragon 0:25fa8795676b 470 success = true;
leothedragon 0:25fa8795676b 471 }
leothedragon 0:25fa8795676b 472 }
leothedragon 0:25fa8795676b 473
leothedragon 0:25fa8795676b 474 if (success && buffer == NULL) {
leothedragon 0:25fa8795676b 475 success = false;
leothedragon 0:25fa8795676b 476 }
leothedragon 0:25fa8795676b 477
leothedragon 0:25fa8795676b 478 // Endpoint
leothedragon 0:25fa8795676b 479 if (success) {
leothedragon 0:25fa8795676b 480 success = false;
leothedragon 0:25fa8795676b 481 char device_id[64];
leothedragon 0:25fa8795676b 482
leothedragon 0:25fa8795676b 483 size_t cert_size = max_size;
leothedragon 0:25fa8795676b 484 uint8_t certificate[MAX_CERTIFICATE_SIZE];
leothedragon 0:25fa8795676b 485 uint8_t *certificate_ptr = (uint8_t*)&certificate;
leothedragon 0:25fa8795676b 486
leothedragon 0:25fa8795676b 487 // TODO! Update to use chain api
leothedragon 0:25fa8795676b 488 if (_security->resource_value_buffer(M2MSecurity::PublicKey, certificate_ptr, m2m_id, &cert_size) == 0) {
leothedragon 0:25fa8795676b 489 real_size = cert_size;
leothedragon 0:25fa8795676b 490 if (extract_field_from_certificate((uint8_t*)certificate, real_size, "CN", device_id)) {
leothedragon 0:25fa8795676b 491 tr_info("ConnectorClient::create_register_object - CN - endpoint_name : %s", device_id);
leothedragon 0:25fa8795676b 492 _endpoint_info.endpoint_name = String(device_id);
leothedragon 0:25fa8795676b 493 success = true;
leothedragon 0:25fa8795676b 494 } else {
leothedragon 0:25fa8795676b 495 tr_error("KEY_ENDPOINT_NAME failed.");
leothedragon 0:25fa8795676b 496 }
leothedragon 0:25fa8795676b 497 }
leothedragon 0:25fa8795676b 498 }
leothedragon 0:25fa8795676b 499
leothedragon 0:25fa8795676b 500 // Connector URL
leothedragon 0:25fa8795676b 501 if (success) {
leothedragon 0:25fa8795676b 502 success = false;
leothedragon 0:25fa8795676b 503 if (ccs_get_item(g_fcc_lwm2m_server_uri_name, buffer, max_size, &real_size, CCS_CONFIG_ITEM) == CCS_STATUS_SUCCESS) {
leothedragon 0:25fa8795676b 504 tr_info("ConnectorClient::create_register_object - M2MServerUri %.*s", (int)real_size, buffer);
leothedragon 0:25fa8795676b 505 if (_security->set_resource_value(M2MSecurity::M2MServerUri, buffer, (uint32_t)real_size, m2m_id)) {
leothedragon 0:25fa8795676b 506 success = true;
leothedragon 0:25fa8795676b 507 }
leothedragon 0:25fa8795676b 508 #ifdef MBED_CLOUD_CLIENT_EDGE_EXTENSION
leothedragon 0:25fa8795676b 509 _endpoint_info.lwm2m_server_uri = _security->resource_value_string(M2MSecurity::M2MServerUri, m2m_id);
leothedragon 0:25fa8795676b 510 #endif
leothedragon 0:25fa8795676b 511 }
leothedragon 0:25fa8795676b 512 else {
leothedragon 0:25fa8795676b 513 tr_error("KEY_CONNECTOR_URL failed.");
leothedragon 0:25fa8795676b 514 }
leothedragon 0:25fa8795676b 515 }
leothedragon 0:25fa8795676b 516
leothedragon 0:25fa8795676b 517 // Try to get internal endpoint name
leothedragon 0:25fa8795676b 518 if (success) {
leothedragon 0:25fa8795676b 519 if (ccs_get_item(KEY_INTERNAL_ENDPOINT, buffer, max_size, &real_size, CCS_CONFIG_ITEM) == CCS_STATUS_SUCCESS) {
leothedragon 0:25fa8795676b 520 _endpoint_info.internal_endpoint_name = String((const char*)buffer, real_size);
leothedragon 0:25fa8795676b 521 tr_info("ConnectorClient::create_register_object - internal endpoint name : %s", _endpoint_info.internal_endpoint_name.c_str());
leothedragon 0:25fa8795676b 522 }
leothedragon 0:25fa8795676b 523 else {
leothedragon 0:25fa8795676b 524 tr_debug("KEY_INTERNAL_ENDPOINT failed.");
leothedragon 0:25fa8795676b 525 }
leothedragon 0:25fa8795676b 526 }
leothedragon 0:25fa8795676b 527
leothedragon 0:25fa8795676b 528 if (success) {
leothedragon 0:25fa8795676b 529 success = false;
leothedragon 0:25fa8795676b 530 if (ccs_get_item(KEY_ACCOUNT_ID, buffer, max_size, &real_size, CCS_CONFIG_ITEM) == CCS_STATUS_SUCCESS) {
leothedragon 0:25fa8795676b 531 tr_info("ConnectorClient::create_register_object - AccountId %.*s", (int)real_size, buffer);
leothedragon 0:25fa8795676b 532 _endpoint_info.account_id = String((const char*)buffer, real_size);
leothedragon 0:25fa8795676b 533 success = true;
leothedragon 0:25fa8795676b 534 } else {
leothedragon 0:25fa8795676b 535 if (ccs_get_item(g_fcc_lwm2m_server_uri_name, buffer, max_size, &real_size, CCS_CONFIG_ITEM) == CCS_STATUS_SUCCESS) {
leothedragon 0:25fa8795676b 536 String address((const char*)buffer, real_size);
leothedragon 0:25fa8795676b 537 if (address.size() > 0) {
leothedragon 0:25fa8795676b 538 const char *aid = NULL;
leothedragon 0:25fa8795676b 539 const int aid_size = parse_query_parameter_value_from_uri((const char*)address.c_str(), QUERY_PARAM_AID, &aid);
leothedragon 0:25fa8795676b 540 if (aid_size > 0) {
leothedragon 0:25fa8795676b 541 _endpoint_info.account_id.clear();
leothedragon 0:25fa8795676b 542 _endpoint_info.account_id.append_raw(aid, aid_size);
leothedragon 0:25fa8795676b 543 if (ccs_set_item(KEY_ACCOUNT_ID,
leothedragon 0:25fa8795676b 544 (const uint8_t*)_endpoint_info.account_id.c_str(),
leothedragon 0:25fa8795676b 545 (size_t)_endpoint_info.account_id.size(), CCS_CONFIG_ITEM) == CCS_STATUS_SUCCESS) {
leothedragon 0:25fa8795676b 546 success = true;
leothedragon 0:25fa8795676b 547 tr_info("ConnectorClient::create_register_object - aid from uri %s", _endpoint_info.account_id.c_str());
leothedragon 0:25fa8795676b 548 } else {
leothedragon 0:25fa8795676b 549 tr_error("ConnectorClient::create_register_object - failed to store aid");
leothedragon 0:25fa8795676b 550 }
leothedragon 0:25fa8795676b 551
leothedragon 0:25fa8795676b 552 }
leothedragon 0:25fa8795676b 553 }
leothedragon 0:25fa8795676b 554 }
leothedragon 0:25fa8795676b 555 }
leothedragon 0:25fa8795676b 556 }
leothedragon 0:25fa8795676b 557
leothedragon 0:25fa8795676b 558 free(buffer);
leothedragon 0:25fa8795676b 559
leothedragon 0:25fa8795676b 560 return success;
leothedragon 0:25fa8795676b 561 }
leothedragon 0:25fa8795676b 562
leothedragon 0:25fa8795676b 563 /*
leothedragon 0:25fa8795676b 564 * Creates bootstrap server object with bootstrap server address and other parameters
leothedragon 0:25fa8795676b 565 * required for connecting to mbed Cloud bootstrap server.
leothedragon 0:25fa8795676b 566 */
leothedragon 0:25fa8795676b 567 bool ConnectorClient::create_bootstrap_object()
leothedragon 0:25fa8795676b 568 {
leothedragon 0:25fa8795676b 569 tr_debug("ConnectorClient::create_bootstrap_object");
leothedragon 0:25fa8795676b 570 bool success = false;
leothedragon 0:25fa8795676b 571
leothedragon 0:25fa8795676b 572 // Check if bootstrap credentials are already stored in KCM
leothedragon 0:25fa8795676b 573 if (bootstrap_credentials_stored_in_kcm() && _security) {
leothedragon 0:25fa8795676b 574 int32_t bs_id = _security->get_security_instance_id(M2MSecurity::Bootstrap);
leothedragon 0:25fa8795676b 575 if (_security->set_resource_value(M2MSecurity::SecurityMode, M2MSecurity::Certificate, bs_id)) {
leothedragon 0:25fa8795676b 576 success = true;
leothedragon 0:25fa8795676b 577 }
leothedragon 0:25fa8795676b 578
leothedragon 0:25fa8795676b 579 tr_info("ConnectorClient::create_bootstrap_object - bs_id = %" PRId32, bs_id);
leothedragon 0:25fa8795676b 580 tr_info("ConnectorClient::create_bootstrap_object - use credentials from storage");
leothedragon 0:25fa8795676b 581
leothedragon 0:25fa8795676b 582 // Allocate scratch buffer, this will be used to copy parameters from storage to security object
leothedragon 0:25fa8795676b 583 size_t real_size = 0;
leothedragon 0:25fa8795676b 584 const int max_size = MAX_CERTIFICATE_SIZE;
leothedragon 0:25fa8795676b 585 uint8_t *buffer = NULL;
leothedragon 0:25fa8795676b 586 if (success) {
leothedragon 0:25fa8795676b 587 success = false;
leothedragon 0:25fa8795676b 588 buffer = (uint8_t*)malloc(max_size);
leothedragon 0:25fa8795676b 589 if (buffer != NULL) {
leothedragon 0:25fa8795676b 590 success = true;
leothedragon 0:25fa8795676b 591 }
leothedragon 0:25fa8795676b 592 }
leothedragon 0:25fa8795676b 593
leothedragon 0:25fa8795676b 594 // Read internal endpoint name if it exists, we need to append
leothedragon 0:25fa8795676b 595 // it to bootstrap uri if device already bootstrapped
leothedragon 0:25fa8795676b 596 uint8_t *iep = NULL;
leothedragon 0:25fa8795676b 597 if (success && ccs_get_string_item(KEY_INTERNAL_ENDPOINT, buffer, max_size, CCS_CONFIG_ITEM) == CCS_STATUS_SUCCESS) {
leothedragon 0:25fa8795676b 598 iep = (uint8_t*)malloc(strlen((const char*)buffer) + strlen(INTERNAL_ENDPOINT_PARAM) + 1);
leothedragon 0:25fa8795676b 599 if (iep != NULL) {
leothedragon 0:25fa8795676b 600 strcpy((char*)iep, INTERNAL_ENDPOINT_PARAM);
leothedragon 0:25fa8795676b 601 strcat((char*)iep, (const char*)buffer);
leothedragon 0:25fa8795676b 602 tr_info("ConnectorClient::create_bootstrap_object - iep: %s", buffer);
leothedragon 0:25fa8795676b 603 }
leothedragon 0:25fa8795676b 604 //TODO: Should handle error if iep exists but allocation fails?
leothedragon 0:25fa8795676b 605 }
leothedragon 0:25fa8795676b 606
leothedragon 0:25fa8795676b 607 // Bootstrap URI
leothedragon 0:25fa8795676b 608 if (success) {
leothedragon 0:25fa8795676b 609 success = false;
leothedragon 0:25fa8795676b 610 if (ccs_get_string_item(g_fcc_bootstrap_server_uri_name, buffer, max_size, CCS_CONFIG_ITEM) == CCS_STATUS_SUCCESS) {
leothedragon 0:25fa8795676b 611 real_size = strlen((const char*)buffer);
leothedragon 0:25fa8795676b 612
leothedragon 0:25fa8795676b 613 // Append iep if we 1. have it 2. it doesn't already exist in uri 3. it fits
leothedragon 0:25fa8795676b 614 if (iep &&
leothedragon 0:25fa8795676b 615 strstr((const char*)buffer, (const char*)iep) == NULL &&
leothedragon 0:25fa8795676b 616 (real_size + strlen((const char*)iep) + 1) <= max_size) {
leothedragon 0:25fa8795676b 617 strcat((char*)buffer, (const char*)iep);
leothedragon 0:25fa8795676b 618 real_size += strlen((const char*)iep) + 1;
leothedragon 0:25fa8795676b 619 }
leothedragon 0:25fa8795676b 620
leothedragon 0:25fa8795676b 621 tr_info("ConnectorClient::create_bootstrap_object - M2MServerUri %.*s", (int)real_size, buffer);
leothedragon 0:25fa8795676b 622 if (_security->set_resource_value(M2MSecurity::M2MServerUri, buffer, real_size, bs_id)) {
leothedragon 0:25fa8795676b 623 success = true;
leothedragon 0:25fa8795676b 624 }
leothedragon 0:25fa8795676b 625 }
leothedragon 0:25fa8795676b 626 }
leothedragon 0:25fa8795676b 627
leothedragon 0:25fa8795676b 628 free(iep);
leothedragon 0:25fa8795676b 629
leothedragon 0:25fa8795676b 630 // Endpoint
leothedragon 0:25fa8795676b 631 if (success) {
leothedragon 0:25fa8795676b 632 success = false;
leothedragon 0:25fa8795676b 633 if (ccs_get_item(g_fcc_endpoint_parameter_name, buffer, max_size, &real_size, CCS_CONFIG_ITEM) == CCS_STATUS_SUCCESS) {
leothedragon 0:25fa8795676b 634 success = true;
leothedragon 0:25fa8795676b 635 _endpoint_info.endpoint_name = String((const char*)buffer, real_size);
leothedragon 0:25fa8795676b 636 tr_info("ConnectorClient::create_bootstrap_object - Endpoint %s", _endpoint_info.endpoint_name.c_str());
leothedragon 0:25fa8795676b 637 }
leothedragon 0:25fa8795676b 638 }
leothedragon 0:25fa8795676b 639
leothedragon 0:25fa8795676b 640 // Account ID, not mandatory
leothedragon 0:25fa8795676b 641 if (success) {
leothedragon 0:25fa8795676b 642 if (ccs_get_item(KEY_ACCOUNT_ID, buffer, max_size, &real_size, CCS_CONFIG_ITEM) == CCS_STATUS_SUCCESS) {
leothedragon 0:25fa8795676b 643 _endpoint_info.account_id = String((const char*)buffer, real_size);
leothedragon 0:25fa8795676b 644 tr_info("ConnectorClient::create_bootstrap_object - AccountId %s", _endpoint_info.account_id.c_str());
leothedragon 0:25fa8795676b 645 }
leothedragon 0:25fa8795676b 646 }
leothedragon 0:25fa8795676b 647
leothedragon 0:25fa8795676b 648 free(buffer);
leothedragon 0:25fa8795676b 649
leothedragon 0:25fa8795676b 650 if (!success) {
leothedragon 0:25fa8795676b 651 tr_error("ConnectorClient::create_bootstrap_object - Failed to read credentials");
leothedragon 0:25fa8795676b 652 _callback->connector_error((M2MInterface::Error)MbedCloudClient::ConnectorFailedToReadCredentials,CREDENTIAL_ERROR);
leothedragon 0:25fa8795676b 653 _security->remove_object_instance(bs_id);
leothedragon 0:25fa8795676b 654 }
leothedragon 0:25fa8795676b 655 } else {
leothedragon 0:25fa8795676b 656 success = true;
leothedragon 0:25fa8795676b 657 tr_info("ConnectorClient::create_bootstrap_object - bootstrap object already done");
leothedragon 0:25fa8795676b 658 }
leothedragon 0:25fa8795676b 659
leothedragon 0:25fa8795676b 660
leothedragon 0:25fa8795676b 661 return success;
leothedragon 0:25fa8795676b 662 }
leothedragon 0:25fa8795676b 663
leothedragon 0:25fa8795676b 664 void ConnectorClient::state_bootstrap_start()
leothedragon 0:25fa8795676b 665 {
leothedragon 0:25fa8795676b 666 tr_info("ConnectorClient::state_bootstrap_start()");
leothedragon 0:25fa8795676b 667 assert(_interface != NULL);
leothedragon 0:25fa8795676b 668 assert(_security != NULL);
leothedragon 0:25fa8795676b 669
leothedragon 0:25fa8795676b 670 _interface->bootstrap(_security);
leothedragon 0:25fa8795676b 671
leothedragon 0:25fa8795676b 672 internal_event(State_Bootstrap_Started);
leothedragon 0:25fa8795676b 673 }
leothedragon 0:25fa8795676b 674
leothedragon 0:25fa8795676b 675 void ConnectorClient::state_bootstrap_started()
leothedragon 0:25fa8795676b 676 {
leothedragon 0:25fa8795676b 677 // this state may be useful only for verifying the callbacks?
leothedragon 0:25fa8795676b 678 }
leothedragon 0:25fa8795676b 679
leothedragon 0:25fa8795676b 680 void ConnectorClient::state_bootstrap_success()
leothedragon 0:25fa8795676b 681 {
leothedragon 0:25fa8795676b 682 assert(_callback != NULL);
leothedragon 0:25fa8795676b 683 // Parse internal endpoint name from mDS cert
leothedragon 0:25fa8795676b 684 _callback->registration_process_result(State_Bootstrap_Success);
leothedragon 0:25fa8795676b 685 }
leothedragon 0:25fa8795676b 686
leothedragon 0:25fa8795676b 687 void ConnectorClient::state_bootstrap_failure()
leothedragon 0:25fa8795676b 688 {
leothedragon 0:25fa8795676b 689 assert(_callback != NULL);
leothedragon 0:25fa8795676b 690 // maybe some additional canceling and/or leanup is needed here?
leothedragon 0:25fa8795676b 691 _callback->registration_process_result(State_Bootstrap_Failure);
leothedragon 0:25fa8795676b 692 }
leothedragon 0:25fa8795676b 693
leothedragon 0:25fa8795676b 694 #ifndef MBED_CLIENT_DISABLE_EST_FEATURE
leothedragon 0:25fa8795676b 695 void ConnectorClient::state_est_start()
leothedragon 0:25fa8795676b 696 {
leothedragon 0:25fa8795676b 697 // - Generate CSR from data during bootstrap phase
leothedragon 0:25fa8795676b 698 // - Call EST enrollment API from InterfaceImpl
leothedragon 0:25fa8795676b 699
leothedragon 0:25fa8795676b 700 // Update the internal endpoint name and account id to endpoint info structure
leothedragon 0:25fa8795676b 701 // as we get those during bootstrap phase
leothedragon 0:25fa8795676b 702 _endpoint_info.internal_endpoint_name = _interface->internal_endpoint_name();
leothedragon 0:25fa8795676b 703
leothedragon 0:25fa8795676b 704 int32_t m2m_id = _security->get_security_instance_id(M2MSecurity::M2MServer);
leothedragon 0:25fa8795676b 705 int32_t sec_mode = M2MSecurity::SecurityNotSet;
leothedragon 0:25fa8795676b 706 if (m2m_id >= 0) {
leothedragon 0:25fa8795676b 707 sec_mode = _security->resource_value_int(M2MSecurity::SecurityMode, m2m_id);
leothedragon 0:25fa8795676b 708
leothedragon 0:25fa8795676b 709 // We need to parse account id from lwm2m server uri query if it is not yet
leothedragon 0:25fa8795676b 710 // set in endpoint info structure
leothedragon 0:25fa8795676b 711 if (_endpoint_info.account_id.length() <= 0) {
leothedragon 0:25fa8795676b 712 String address = _security->resource_value_string(M2MSecurity::M2MServerUri, m2m_id);
leothedragon 0:25fa8795676b 713 tr_debug("ConnectorClient::state_est_start - address: %s", address.c_str());
leothedragon 0:25fa8795676b 714 if (address.size() > 0) {
leothedragon 0:25fa8795676b 715 const char *aid = NULL;
leothedragon 0:25fa8795676b 716 const int aid_size = parse_query_parameter_value_from_uri((const char*)address.c_str(), QUERY_PARAM_AID, &aid);
leothedragon 0:25fa8795676b 717 if (aid_size > 0) {
leothedragon 0:25fa8795676b 718 _endpoint_info.account_id.append_raw(aid, aid_size);
leothedragon 0:25fa8795676b 719 }
leothedragon 0:25fa8795676b 720 }
leothedragon 0:25fa8795676b 721 }
leothedragon 0:25fa8795676b 722 }
leothedragon 0:25fa8795676b 723
leothedragon 0:25fa8795676b 724 tr_debug("ConnectorClient::state_est_start - security instance id: %" PRId32, m2m_id);
leothedragon 0:25fa8795676b 725 tr_debug("ConnectorClient::state_est_start - ep: %s", _endpoint_info.internal_endpoint_name.c_str());
leothedragon 0:25fa8795676b 726 tr_debug("ConnectorClient::state_est_start - iep: %s", _endpoint_info.endpoint_name.c_str());
leothedragon 0:25fa8795676b 727 tr_debug("ConnectorClient::state_est_start - aid: %s", _endpoint_info.account_id.c_str());
leothedragon 0:25fa8795676b 728
leothedragon 0:25fa8795676b 729 // Check EST required parameters are in place
leothedragon 0:25fa8795676b 730 if (m2m_id < 0 ||
leothedragon 0:25fa8795676b 731 _endpoint_info.endpoint_name.length() <= 0 ||
leothedragon 0:25fa8795676b 732 _endpoint_info.internal_endpoint_name.length() <= 0 ||
leothedragon 0:25fa8795676b 733 _endpoint_info.account_id.length() <= 0) {
leothedragon 0:25fa8795676b 734 tr_error("ConnectorClient::state_est_start - Missing parameters for EST enrollment!");
leothedragon 0:25fa8795676b 735 internal_event(State_EST_Failure);
leothedragon 0:25fa8795676b 736 return;
leothedragon 0:25fa8795676b 737 }
leothedragon 0:25fa8795676b 738
leothedragon 0:25fa8795676b 739 uint32_t is_bs_server = _security->resource_value_int(M2MSecurity::BootstrapServer, m2m_id);
leothedragon 0:25fa8795676b 740 size_t public_key_size = MAX_CERTIFICATE_SIZE;
leothedragon 0:25fa8795676b 741 size_t server_key_size = MAX_CERTIFICATE_SIZE;
leothedragon 0:25fa8795676b 742 size_t private_key_size = MAX_CERTIFICATE_SIZE;
leothedragon 0:25fa8795676b 743
leothedragon 0:25fa8795676b 744 // Temp buffer for storing CSR and certificates
leothedragon 0:25fa8795676b 745 uint8_t *buffer = (uint8_t*)malloc(MAX_CERTIFICATE_SIZE);
leothedragon 0:25fa8795676b 746 size_t real_size = 0;
leothedragon 0:25fa8795676b 747 if (buffer == NULL) {
leothedragon 0:25fa8795676b 748 tr_error("ConnectorClient::state_est_start - Allocating temp buffer failed!");
leothedragon 0:25fa8795676b 749 internal_event(State_EST_Failure);
leothedragon 0:25fa8795676b 750 return;
leothedragon 0:25fa8795676b 751 }
leothedragon 0:25fa8795676b 752 uint8_t *buffer_ptr = buffer;
leothedragon 0:25fa8795676b 753
leothedragon 0:25fa8795676b 754 // TODO! Update to use chain api
leothedragon 0:25fa8795676b 755 if (_security->resource_value_buffer(M2MSecurity::PublicKey, buffer_ptr, m2m_id, &public_key_size) != 0) {
leothedragon 0:25fa8795676b 756 public_key_size = 0;
leothedragon 0:25fa8795676b 757 }
leothedragon 0:25fa8795676b 758 if (_security->resource_value_buffer(M2MSecurity::ServerPublicKey, buffer_ptr, m2m_id, &server_key_size) != 0) {
leothedragon 0:25fa8795676b 759 server_key_size = 0;
leothedragon 0:25fa8795676b 760 }
leothedragon 0:25fa8795676b 761 if (_security->resource_value_buffer(M2MSecurity::Secretkey, buffer_ptr, m2m_id, &private_key_size) != 0) {
leothedragon 0:25fa8795676b 762 private_key_size = 0;
leothedragon 0:25fa8795676b 763 }
leothedragon 0:25fa8795676b 764
leothedragon 0:25fa8795676b 765 tr_info("est check - is bs server /0/1: %" PRIu32, is_bs_server);
leothedragon 0:25fa8795676b 766 tr_info("est check - Security Mode /0/2: %" PRIu32, sec_mode);
leothedragon 0:25fa8795676b 767 tr_info("est check - Public key size /0/3: %lu", (unsigned long)public_key_size);
leothedragon 0:25fa8795676b 768 tr_info("est check - Server Public key size /0/4: %lu", (unsigned long)server_key_size);
leothedragon 0:25fa8795676b 769 tr_info("est check - Secret key size /0/5: %lu", (unsigned long)private_key_size);
leothedragon 0:25fa8795676b 770
leothedragon 0:25fa8795676b 771 // Configure CSR params
leothedragon 0:25fa8795676b 772 kcm_csr_params_s csr_params;
leothedragon 0:25fa8795676b 773 int subject_size = snprintf(NULL, 0, LWM2M_CSR_SUBJECT_FORMAT,
leothedragon 0:25fa8795676b 774 _endpoint_info.internal_endpoint_name.c_str(),
leothedragon 0:25fa8795676b 775 _endpoint_info.account_id.c_str(),
leothedragon 0:25fa8795676b 776 _endpoint_info.endpoint_name.c_str());
leothedragon 0:25fa8795676b 777 if (subject_size <= 0) {
leothedragon 0:25fa8795676b 778 tr_error("ConnectorClient::state_est_start - CSR Subject formatting failed!");
leothedragon 0:25fa8795676b 779 free(buffer);
leothedragon 0:25fa8795676b 780 internal_event(State_EST_Failure);
leothedragon 0:25fa8795676b 781 return;
leothedragon 0:25fa8795676b 782 }
leothedragon 0:25fa8795676b 783
leothedragon 0:25fa8795676b 784 // For null-terminator
leothedragon 0:25fa8795676b 785 subject_size++;
leothedragon 0:25fa8795676b 786
leothedragon 0:25fa8795676b 787 csr_params.subject = (char*)malloc(subject_size);
leothedragon 0:25fa8795676b 788 if (csr_params.subject == NULL) {
leothedragon 0:25fa8795676b 789 tr_error("ConnectorClient::state_est_start - CSR Subject formatting failed!");
leothedragon 0:25fa8795676b 790 free(buffer);
leothedragon 0:25fa8795676b 791 internal_event(State_EST_Failure);
leothedragon 0:25fa8795676b 792 return;
leothedragon 0:25fa8795676b 793 }
leothedragon 0:25fa8795676b 794
leothedragon 0:25fa8795676b 795 snprintf(csr_params.subject, subject_size, LWM2M_CSR_SUBJECT_FORMAT,
leothedragon 0:25fa8795676b 796 _endpoint_info.internal_endpoint_name.c_str(),
leothedragon 0:25fa8795676b 797 _endpoint_info.account_id.c_str(),
leothedragon 0:25fa8795676b 798 _endpoint_info.endpoint_name.c_str());
leothedragon 0:25fa8795676b 799
leothedragon 0:25fa8795676b 800 csr_params.md_type = KCM_MD_SHA256;
leothedragon 0:25fa8795676b 801 csr_params.key_usage = KCM_CSR_KU_NONE;
leothedragon 0:25fa8795676b 802 csr_params.ext_key_usage = KCM_CSR_EXT_KU_NONE;
leothedragon 0:25fa8795676b 803
leothedragon 0:25fa8795676b 804 // Delete existing keys
leothedragon 0:25fa8795676b 805 ccs_delete_item(g_fcc_lwm2m_device_certificate_name, CCS_CERTIFICATE_ITEM);
leothedragon 0:25fa8795676b 806 ccs_delete_item(g_fcc_lwm2m_device_private_key_name, CCS_PRIVATE_KEY_ITEM);
leothedragon 0:25fa8795676b 807
leothedragon 0:25fa8795676b 808 kcm_status_e status = kcm_generate_keys_and_csr(KCM_SCHEME_EC_SECP256R1,
leothedragon 0:25fa8795676b 809 (const uint8_t*)g_fcc_lwm2m_device_private_key_name,
leothedragon 0:25fa8795676b 810 strlen(g_fcc_lwm2m_device_private_key_name),
leothedragon 0:25fa8795676b 811 NULL,
leothedragon 0:25fa8795676b 812 0,
leothedragon 0:25fa8795676b 813 false,
leothedragon 0:25fa8795676b 814 &csr_params,
leothedragon 0:25fa8795676b 815 buffer,
leothedragon 0:25fa8795676b 816 MAX_CERTIFICATE_SIZE,
leothedragon 0:25fa8795676b 817 &real_size,
leothedragon 0:25fa8795676b 818 NULL);
leothedragon 0:25fa8795676b 819
leothedragon 0:25fa8795676b 820 free(csr_params.subject);
leothedragon 0:25fa8795676b 821
leothedragon 0:25fa8795676b 822 if (status != KCM_STATUS_SUCCESS) {
leothedragon 0:25fa8795676b 823 tr_error("ConnectorClient::state_est_start - Generating keys and csr failed!");
leothedragon 0:25fa8795676b 824 free(buffer);
leothedragon 0:25fa8795676b 825 internal_event(State_EST_Failure);
leothedragon 0:25fa8795676b 826 return;
leothedragon 0:25fa8795676b 827 }
leothedragon 0:25fa8795676b 828
leothedragon 0:25fa8795676b 829 // Update state and start the enrollment by sending the enroll request
leothedragon 0:25fa8795676b 830 internal_event(State_EST_Started);
leothedragon 0:25fa8795676b 831 est_status_e est_status = _est_client.est_request_enrollment(NULL,
leothedragon 0:25fa8795676b 832 0,
leothedragon 0:25fa8795676b 833 buffer,
leothedragon 0:25fa8795676b 834 real_size,
leothedragon 0:25fa8795676b 835 ConnectorClient::est_enrollment_result,
leothedragon 0:25fa8795676b 836 this);
leothedragon 0:25fa8795676b 837
leothedragon 0:25fa8795676b 838 if (est_status != EST_STATUS_SUCCESS) {
leothedragon 0:25fa8795676b 839 tr_error("ConnectorClient::state_est_start - EST enrollment failed with error %d", (int)est_status);
leothedragon 0:25fa8795676b 840 internal_event(State_EST_Failure);
leothedragon 0:25fa8795676b 841 }
leothedragon 0:25fa8795676b 842
leothedragon 0:25fa8795676b 843 free(buffer);
leothedragon 0:25fa8795676b 844 }
leothedragon 0:25fa8795676b 845
leothedragon 0:25fa8795676b 846 void ConnectorClient::state_est_started()
leothedragon 0:25fa8795676b 847 {
leothedragon 0:25fa8795676b 848 }
leothedragon 0:25fa8795676b 849
leothedragon 0:25fa8795676b 850 void ConnectorClient::state_est_success()
leothedragon 0:25fa8795676b 851 {
leothedragon 0:25fa8795676b 852 tr_info("ConnectorClient::state_est_success()");
leothedragon 0:25fa8795676b 853 _interface->finish_bootstrap();
leothedragon 0:25fa8795676b 854 }
leothedragon 0:25fa8795676b 855
leothedragon 0:25fa8795676b 856 void ConnectorClient::state_est_failure()
leothedragon 0:25fa8795676b 857 {
leothedragon 0:25fa8795676b 858 tr_info("ConnectorClient::state_est_failure()");
leothedragon 0:25fa8795676b 859 internal_event(State_Bootstrap_Failure);
leothedragon 0:25fa8795676b 860 //Failed to store credentials, bootstrap failed
leothedragon 0:25fa8795676b 861 _callback->connector_error(M2MInterface::ESTEnrollmentFailed, ERROR_EST_ENROLLMENT_REQUEST_FAILED); // Translated to error code ConnectMemoryConnectFail
leothedragon 0:25fa8795676b 862 }
leothedragon 0:25fa8795676b 863 #endif /* !MBED_CLIENT_DISABLE_EST_FEATURE */
leothedragon 0:25fa8795676b 864
leothedragon 0:25fa8795676b 865 void ConnectorClient::state_registration_start()
leothedragon 0:25fa8795676b 866 {
leothedragon 0:25fa8795676b 867 tr_info("ConnectorClient::state_registration_start()");
leothedragon 0:25fa8795676b 868 assert(_interface != NULL);
leothedragon 0:25fa8795676b 869 assert(_security != NULL);
leothedragon 0:25fa8795676b 870 _interface->register_object(_security, *_client_objs);
leothedragon 0:25fa8795676b 871 internal_event(State_Registration_Started);
leothedragon 0:25fa8795676b 872 }
leothedragon 0:25fa8795676b 873
leothedragon 0:25fa8795676b 874 void ConnectorClient::state_registration_started()
leothedragon 0:25fa8795676b 875 {
leothedragon 0:25fa8795676b 876 // this state may be useful only for verifying the callbacks?
leothedragon 0:25fa8795676b 877 }
leothedragon 0:25fa8795676b 878
leothedragon 0:25fa8795676b 879 void ConnectorClient::state_registration_success()
leothedragon 0:25fa8795676b 880 {
leothedragon 0:25fa8795676b 881 assert(_callback != NULL);
leothedragon 0:25fa8795676b 882 _endpoint_info.internal_endpoint_name = _interface->internal_endpoint_name();
leothedragon 0:25fa8795676b 883
leothedragon 0:25fa8795676b 884 //The endpoint is maximum 32 character long, we put bigger buffer for future extensions
leothedragon 0:25fa8795676b 885 const int max_size = 64;
leothedragon 0:25fa8795676b 886 uint8_t *buffer = NULL;
leothedragon 0:25fa8795676b 887 buffer = (uint8_t*)malloc(max_size);
leothedragon 0:25fa8795676b 888
leothedragon 0:25fa8795676b 889 if(!buffer) {
leothedragon 0:25fa8795676b 890 _callback->registration_process_result(State_Registration_Failure);
leothedragon 0:25fa8795676b 891 return;
leothedragon 0:25fa8795676b 892 }
leothedragon 0:25fa8795676b 893 bool no_param_update = true;
leothedragon 0:25fa8795676b 894
leothedragon 0:25fa8795676b 895 if(ccs_get_string_item(KEY_INTERNAL_ENDPOINT, buffer, max_size, CCS_CONFIG_ITEM) == CCS_STATUS_SUCCESS) {
leothedragon 0:25fa8795676b 896 if (strcmp((const char*)buffer, _endpoint_info.internal_endpoint_name.c_str()) != 0) {
leothedragon 0:25fa8795676b 897 // Update is required as the stored KCM entry is different than _endpoint_info.internal_endpoint_name.
leothedragon 0:25fa8795676b 898 no_param_update = false;
leothedragon 0:25fa8795676b 899 }
leothedragon 0:25fa8795676b 900 }
leothedragon 0:25fa8795676b 901 free(buffer);
leothedragon 0:25fa8795676b 902
leothedragon 0:25fa8795676b 903 // Update INTERNAL_ENDPOINT setting only if there is no such entry or the value is not matching the
leothedragon 0:25fa8795676b 904 // _endpoint_info.internal_endpoint_name.
leothedragon 0:25fa8795676b 905 if(!no_param_update) {
leothedragon 0:25fa8795676b 906 ccs_delete_item(KEY_INTERNAL_ENDPOINT, CCS_CONFIG_ITEM);
leothedragon 0:25fa8795676b 907 ccs_set_item(KEY_INTERNAL_ENDPOINT, (const uint8_t*)_endpoint_info.internal_endpoint_name.c_str(),
leothedragon 0:25fa8795676b 908 (size_t)_endpoint_info.internal_endpoint_name.size(),
leothedragon 0:25fa8795676b 909 CCS_CONFIG_ITEM);
leothedragon 0:25fa8795676b 910 }
leothedragon 0:25fa8795676b 911
leothedragon 0:25fa8795676b 912 _rebootstrap_time = randLIB_get_random_in_range(1, 10);
leothedragon 0:25fa8795676b 913 _callback->registration_process_result(State_Registration_Success);
leothedragon 0:25fa8795676b 914 }
leothedragon 0:25fa8795676b 915
leothedragon 0:25fa8795676b 916 void ConnectorClient::state_registration_failure()
leothedragon 0:25fa8795676b 917 {
leothedragon 0:25fa8795676b 918 assert(_callback != NULL);
leothedragon 0:25fa8795676b 919 // maybe some additional canceling and/or leanup is needed here?
leothedragon 0:25fa8795676b 920 _callback->registration_process_result(State_Registration_Failure);
leothedragon 0:25fa8795676b 921 }
leothedragon 0:25fa8795676b 922
leothedragon 0:25fa8795676b 923 void ConnectorClient::state_unregistered()
leothedragon 0:25fa8795676b 924 {
leothedragon 0:25fa8795676b 925 assert(_callback != NULL);
leothedragon 0:25fa8795676b 926 _callback->registration_process_result(State_Unregistered);
leothedragon 0:25fa8795676b 927 }
leothedragon 0:25fa8795676b 928
leothedragon 0:25fa8795676b 929 void ConnectorClient::bootstrap_data_ready(M2MSecurity *security_object)
leothedragon 0:25fa8795676b 930 {
leothedragon 0:25fa8795676b 931 tr_info("ConnectorClient::bootstrap_data_ready");
leothedragon 0:25fa8795676b 932 if(security_object) {
leothedragon 0:25fa8795676b 933 // Update bootstrap credentials (we could skip this if we knew whether they were updated)
leothedragon 0:25fa8795676b 934 // This will also update the address in case of first to claim
leothedragon 0:25fa8795676b 935 ccs_status_e status = set_bootstrap_credentials(security_object);
leothedragon 0:25fa8795676b 936 if (status != CCS_STATUS_SUCCESS) {
leothedragon 0:25fa8795676b 937 // TODO: what now?
leothedragon 0:25fa8795676b 938 tr_error("ConnectorClient::bootstrap_data_ready - could not store bootstrap credentials");
leothedragon 0:25fa8795676b 939 }
leothedragon 0:25fa8795676b 940
leothedragon 0:25fa8795676b 941 // Clear the first to claim flag if it's active
leothedragon 0:25fa8795676b 942 if (is_first_to_claim()) {
leothedragon 0:25fa8795676b 943 status = clear_first_to_claim();
leothedragon 0:25fa8795676b 944 if (status != CCS_STATUS_SUCCESS) {
leothedragon 0:25fa8795676b 945 // TODO: what now?
leothedragon 0:25fa8795676b 946 tr_error("ConnectorClient::bootstrap_data_ready - couldn't clear first to claim flag!");
leothedragon 0:25fa8795676b 947 }
leothedragon 0:25fa8795676b 948 }
leothedragon 0:25fa8795676b 949
leothedragon 0:25fa8795676b 950 // Bootstrap might delete m2mserver security object instance completely to force bootstrap
leothedragon 0:25fa8795676b 951 // with new credentials, in that case delete the stored lwm2m credentials as well and re-bootstrap
leothedragon 0:25fa8795676b 952 if (security_object->get_security_instance_id(M2MSecurity::M2MServer) == -1) {
leothedragon 0:25fa8795676b 953 bootstrap_again();
leothedragon 0:25fa8795676b 954 return;
leothedragon 0:25fa8795676b 955 }
leothedragon 0:25fa8795676b 956 // Bootstrap wrote M2MServer credentials, store them and also update first to claim status if it's configured
leothedragon 0:25fa8795676b 957 else {
leothedragon 0:25fa8795676b 958 #ifndef MBED_CLIENT_DISABLE_EST_FEATURE
leothedragon 0:25fa8795676b 959 int32_t m2m_id = _security->get_security_instance_id(M2MSecurity::M2MServer);
leothedragon 0:25fa8795676b 960 if (m2m_id >= 0 &&
leothedragon 0:25fa8795676b 961 _security->resource_value_int(M2MSecurity::SecurityMode, m2m_id) == M2MSecurity::EST) {
leothedragon 0:25fa8795676b 962 // If EST is supported, continue to EST state to start EST enrollment
leothedragon 0:25fa8795676b 963 tr_info("ConnectorClient::bootstrap_data_ready() - Continue to EST enrollment");
leothedragon 0:25fa8795676b 964 internal_event(State_EST_Start);
leothedragon 0:25fa8795676b 965 return;
leothedragon 0:25fa8795676b 966 }
leothedragon 0:25fa8795676b 967 #endif // MBED_CLIENT_DISABLE_EST_FEATURE
leothedragon 0:25fa8795676b 968 // Security mode was not EST, in that case just store the received credentials
leothedragon 0:25fa8795676b 969 tr_info("ConnectorClient::bootstrap_data_ready() - Storing lwm2m credentials");
leothedragon 0:25fa8795676b 970 status = set_connector_credentials(security_object);
leothedragon 0:25fa8795676b 971 }
leothedragon 0:25fa8795676b 972
leothedragon 0:25fa8795676b 973 if (status != CCS_STATUS_SUCCESS) {
leothedragon 0:25fa8795676b 974 internal_event(State_Bootstrap_Failure);
leothedragon 0:25fa8795676b 975 //Failed to store credentials, bootstrap failed
leothedragon 0:25fa8795676b 976 _callback->connector_error(M2MInterface::MemoryFail, CONNECTOR_ERROR_NO_MEMORY); // Translated to error code ConnectMemoryConnectFail
leothedragon 0:25fa8795676b 977 return;
leothedragon 0:25fa8795676b 978 } else {
leothedragon 0:25fa8795676b 979 tr_info("ConnectorClient::bootstrap_data_ready - set_credentials status %d", status);
leothedragon 0:25fa8795676b 980 }
leothedragon 0:25fa8795676b 981 }
leothedragon 0:25fa8795676b 982 }
leothedragon 0:25fa8795676b 983
leothedragon 0:25fa8795676b 984 void ConnectorClient::bootstrap_done(M2MSecurity *security_object)
leothedragon 0:25fa8795676b 985 {
leothedragon 0:25fa8795676b 986 tr_info("ConnectorClient::bootstrap_done");
leothedragon 0:25fa8795676b 987 internal_event(State_Bootstrap_Success);
leothedragon 0:25fa8795676b 988 }
leothedragon 0:25fa8795676b 989
leothedragon 0:25fa8795676b 990 void ConnectorClient::object_registered(M2MSecurity *security_object, const M2MServer &server_object)
leothedragon 0:25fa8795676b 991 {
leothedragon 0:25fa8795676b 992 internal_event(State_Registration_Success);
leothedragon 0:25fa8795676b 993 }
leothedragon 0:25fa8795676b 994
leothedragon 0:25fa8795676b 995 void ConnectorClient::object_unregistered(M2MSecurity *server_object)
leothedragon 0:25fa8795676b 996 {
leothedragon 0:25fa8795676b 997 internal_event(State_Unregistered);
leothedragon 0:25fa8795676b 998 }
leothedragon 0:25fa8795676b 999
leothedragon 0:25fa8795676b 1000 void ConnectorClient::registration_updated(M2MSecurity *security_object, const M2MServer & server_object)
leothedragon 0:25fa8795676b 1001 {
leothedragon 0:25fa8795676b 1002 _callback->registration_process_result(State_Registration_Updated);
leothedragon 0:25fa8795676b 1003 }
leothedragon 0:25fa8795676b 1004
leothedragon 0:25fa8795676b 1005 void ConnectorClient::error(M2MInterface::Error error)
leothedragon 0:25fa8795676b 1006 {
leothedragon 0:25fa8795676b 1007 tr_error("ConnectorClient::error() - error: %d", error);
leothedragon 0:25fa8795676b 1008 assert(_callback != NULL);
leothedragon 0:25fa8795676b 1009
leothedragon 0:25fa8795676b 1010 if (_current_state >= State_Registration_Start &&
leothedragon 0:25fa8795676b 1011 use_bootstrap() &&
leothedragon 0:25fa8795676b 1012 (error == M2MInterface::SecureConnectionFailed ||
leothedragon 0:25fa8795676b 1013 error == M2MInterface::InvalidParameters)) {
leothedragon 0:25fa8795676b 1014 tr_info("ConnectorClient::error() - Error during lwm2m registration");
leothedragon 0:25fa8795676b 1015
leothedragon 0:25fa8795676b 1016 // Delete the lwm2m security instance
leothedragon 0:25fa8795676b 1017 int32_t id = _security->get_security_instance_id(M2MSecurity::M2MServer);
leothedragon 0:25fa8795676b 1018 if (id >= 0) {
leothedragon 0:25fa8795676b 1019 _security->remove_object_instance(id);
leothedragon 0:25fa8795676b 1020 }
leothedragon 0:25fa8795676b 1021
leothedragon 0:25fa8795676b 1022 bootstrap_again();
leothedragon 0:25fa8795676b 1023 }
leothedragon 0:25fa8795676b 1024 else {
leothedragon 0:25fa8795676b 1025 _callback->connector_error(error, _interface->error_description());
leothedragon 0:25fa8795676b 1026 }
leothedragon 0:25fa8795676b 1027 }
leothedragon 0:25fa8795676b 1028
leothedragon 0:25fa8795676b 1029 void ConnectorClient::value_updated(M2MBase *base, M2MBase::BaseType type)
leothedragon 0:25fa8795676b 1030 {
leothedragon 0:25fa8795676b 1031 assert(_callback != NULL);
leothedragon 0:25fa8795676b 1032 _callback->value_updated(base, type);
leothedragon 0:25fa8795676b 1033 }
leothedragon 0:25fa8795676b 1034
leothedragon 0:25fa8795676b 1035 bool ConnectorClient::connector_credentials_available()
leothedragon 0:25fa8795676b 1036 {
leothedragon 0:25fa8795676b 1037 tr_debug("ConnectorClient::connector_credentials_available");
leothedragon 0:25fa8795676b 1038 if (ccs_check_item(g_fcc_lwm2m_server_uri_name, CCS_CONFIG_ITEM) != CCS_STATUS_SUCCESS) {
leothedragon 0:25fa8795676b 1039 return false;
leothedragon 0:25fa8795676b 1040 }
leothedragon 0:25fa8795676b 1041 return true;
leothedragon 0:25fa8795676b 1042 }
leothedragon 0:25fa8795676b 1043
leothedragon 0:25fa8795676b 1044 bool ConnectorClient::use_bootstrap()
leothedragon 0:25fa8795676b 1045 {
leothedragon 0:25fa8795676b 1046 tr_debug("ConnectorClient::use_bootstrap");
leothedragon 0:25fa8795676b 1047 size_t real_size = 0;
leothedragon 0:25fa8795676b 1048 uint8_t data[CONFIG_BOOLEAN_ITEM_SIZE] = {0};
leothedragon 0:25fa8795676b 1049 uint32_t value = 0;
leothedragon 0:25fa8795676b 1050 ccs_status_e status = ccs_get_item(g_fcc_use_bootstrap_parameter_name, data, CONFIG_BOOLEAN_ITEM_SIZE, &real_size, CCS_CONFIG_ITEM);
leothedragon 0:25fa8795676b 1051 if (status == CCS_STATUS_SUCCESS) {
leothedragon 0:25fa8795676b 1052 memcpy(&value, data, CONFIG_BOOLEAN_ITEM_SIZE);
leothedragon 0:25fa8795676b 1053 // Return true if use_bootstrap is set
leothedragon 0:25fa8795676b 1054 if (value == 1) {
leothedragon 0:25fa8795676b 1055 return true;
leothedragon 0:25fa8795676b 1056 }
leothedragon 0:25fa8795676b 1057 }
leothedragon 0:25fa8795676b 1058 return false;
leothedragon 0:25fa8795676b 1059 }
leothedragon 0:25fa8795676b 1060
leothedragon 0:25fa8795676b 1061
leothedragon 0:25fa8795676b 1062 bool ConnectorClient::get_key(const char *key, const char *endpoint, char *&key_name)
leothedragon 0:25fa8795676b 1063 {
leothedragon 0:25fa8795676b 1064 if(key_name) {
leothedragon 0:25fa8795676b 1065 free(key_name);
leothedragon 0:25fa8795676b 1066 key_name = NULL;
leothedragon 0:25fa8795676b 1067 }
leothedragon 0:25fa8795676b 1068
leothedragon 0:25fa8795676b 1069 key_name = (char*)malloc(strlen(key)+strlen(endpoint)+1);
leothedragon 0:25fa8795676b 1070 if(key_name) {
leothedragon 0:25fa8795676b 1071 strcpy(key_name, key);
leothedragon 0:25fa8795676b 1072 strcat(key_name, endpoint);
leothedragon 0:25fa8795676b 1073 tr_debug("key %s", key_name);
leothedragon 0:25fa8795676b 1074 return true;
leothedragon 0:25fa8795676b 1075 }
leothedragon 0:25fa8795676b 1076 return false;
leothedragon 0:25fa8795676b 1077 }
leothedragon 0:25fa8795676b 1078
leothedragon 0:25fa8795676b 1079 ccs_status_e ConnectorClient::set_connector_credentials(M2MSecurity *security)
leothedragon 0:25fa8795676b 1080 {
leothedragon 0:25fa8795676b 1081 tr_debug("ConnectorClient::set_connector_credentials");
leothedragon 0:25fa8795676b 1082 ccs_status_e status = CCS_STATUS_ERROR;
leothedragon 0:25fa8795676b 1083
leothedragon 0:25fa8795676b 1084 int32_t m2m_id = security->get_security_instance_id(M2MSecurity::M2MServer);
leothedragon 0:25fa8795676b 1085 if (m2m_id == -1) {
leothedragon 0:25fa8795676b 1086 return status;
leothedragon 0:25fa8795676b 1087 }
leothedragon 0:25fa8795676b 1088
leothedragon 0:25fa8795676b 1089 size_t buffer_size = MAX_CERTIFICATE_SIZE;
leothedragon 0:25fa8795676b 1090 uint8_t public_key[MAX_CERTIFICATE_SIZE];
leothedragon 0:25fa8795676b 1091 uint8_t *public_key_ptr = (uint8_t*)&public_key;
leothedragon 0:25fa8795676b 1092
leothedragon 0:25fa8795676b 1093 // TODO! Update to use chain api
leothedragon 0:25fa8795676b 1094 if (security->resource_value_buffer(M2MSecurity::PublicKey, public_key_ptr, m2m_id, &buffer_size) != 0) {
leothedragon 0:25fa8795676b 1095 return status;
leothedragon 0:25fa8795676b 1096 }
leothedragon 0:25fa8795676b 1097
leothedragon 0:25fa8795676b 1098 char device_id[64];
leothedragon 0:25fa8795676b 1099 memset(device_id, 0, 64);
leothedragon 0:25fa8795676b 1100 if (extract_field_from_certificate(public_key, buffer_size, "L", device_id)) {
leothedragon 0:25fa8795676b 1101 tr_info("ConnectorClient::set_connector_credentials - L internal_endpoint_name : %s", device_id);
leothedragon 0:25fa8795676b 1102 _endpoint_info.internal_endpoint_name = String(device_id);
leothedragon 0:25fa8795676b 1103 ccs_delete_item(KEY_INTERNAL_ENDPOINT, CCS_CONFIG_ITEM);
leothedragon 0:25fa8795676b 1104 status = ccs_set_item(KEY_INTERNAL_ENDPOINT,(uint8_t*)device_id, strlen(device_id), CCS_CONFIG_ITEM);
leothedragon 0:25fa8795676b 1105 }
leothedragon 0:25fa8795676b 1106
leothedragon 0:25fa8795676b 1107 memset(device_id, 0, 64);
leothedragon 0:25fa8795676b 1108 if (extract_field_from_certificate(public_key, buffer_size, "CN", device_id)) {
leothedragon 0:25fa8795676b 1109 tr_info("ConnectorClient::set_connector_credentials - CN endpoint_name : %s", device_id);
leothedragon 0:25fa8795676b 1110 _endpoint_info.endpoint_name = String(device_id);
leothedragon 0:25fa8795676b 1111 }
leothedragon 0:25fa8795676b 1112
leothedragon 0:25fa8795676b 1113 if(status == CCS_STATUS_SUCCESS) {
leothedragon 0:25fa8795676b 1114 ccs_delete_item(KEY_ACCOUNT_ID, CCS_CONFIG_ITEM);
leothedragon 0:25fa8795676b 1115 // AccountID optional so don't fail if unable to store
leothedragon 0:25fa8795676b 1116 ccs_set_item(KEY_ACCOUNT_ID,
leothedragon 0:25fa8795676b 1117 (const uint8_t*)_endpoint_info.account_id.c_str(),
leothedragon 0:25fa8795676b 1118 (size_t)_endpoint_info.account_id.size(),
leothedragon 0:25fa8795676b 1119 CCS_CONFIG_ITEM);
leothedragon 0:25fa8795676b 1120 }
leothedragon 0:25fa8795676b 1121
leothedragon 0:25fa8795676b 1122 if (status == CCS_STATUS_SUCCESS) {
leothedragon 0:25fa8795676b 1123 #ifdef MBED_CLOUD_CLIENT_EDGE_EXTENSION
leothedragon 0:25fa8795676b 1124 _endpoint_info.lwm2m_server_uri = security->resource_value_string(M2MSecurity::M2MServerUri, m2m_id);
leothedragon 0:25fa8795676b 1125 #endif
leothedragon 0:25fa8795676b 1126 ccs_delete_item(g_fcc_lwm2m_server_uri_name, CCS_CONFIG_ITEM);
leothedragon 0:25fa8795676b 1127 status = ccs_set_item(g_fcc_lwm2m_server_uri_name,
leothedragon 0:25fa8795676b 1128 (const uint8_t*)security->resource_value_string(M2MSecurity::M2MServerUri, m2m_id).c_str(),
leothedragon 0:25fa8795676b 1129 (size_t)security->resource_value_string(M2MSecurity::M2MServerUri, m2m_id).size(),
leothedragon 0:25fa8795676b 1130 CCS_CONFIG_ITEM);
leothedragon 0:25fa8795676b 1131 }
leothedragon 0:25fa8795676b 1132
leothedragon 0:25fa8795676b 1133 M2MDevice *device = M2MInterfaceFactory::create_device();
leothedragon 0:25fa8795676b 1134 if (status == CCS_STATUS_SUCCESS && device) {
leothedragon 0:25fa8795676b 1135 String temp = "";
leothedragon 0:25fa8795676b 1136 uint32_t currenttime = (uint32_t)device->resource_value_int(M2MDevice::CurrentTime, 0);
leothedragon 0:25fa8795676b 1137 uint8_t data[4];
leothedragon 0:25fa8795676b 1138 memcpy(data, &currenttime, 4);
leothedragon 0:25fa8795676b 1139 ccs_delete_item(g_fcc_current_time_parameter_name, CCS_CONFIG_ITEM);
leothedragon 0:25fa8795676b 1140 ccs_set_item(g_fcc_current_time_parameter_name, data, 4, CCS_CONFIG_ITEM);
leothedragon 0:25fa8795676b 1141
leothedragon 0:25fa8795676b 1142 temp = device->resource_value_string(M2MDevice::Timezone, 0);
leothedragon 0:25fa8795676b 1143 if (temp.size() > 0) {
leothedragon 0:25fa8795676b 1144 ccs_delete_item(g_fcc_device_time_zone_parameter_name, CCS_CONFIG_ITEM);
leothedragon 0:25fa8795676b 1145 ccs_set_item(g_fcc_device_time_zone_parameter_name, (const uint8_t*)temp.c_str(), temp.size(), CCS_CONFIG_ITEM);
leothedragon 0:25fa8795676b 1146 }
leothedragon 0:25fa8795676b 1147
leothedragon 0:25fa8795676b 1148 temp = device->resource_value_string(M2MDevice::UTCOffset, 0);
leothedragon 0:25fa8795676b 1149 if (temp.size() > 0) {
leothedragon 0:25fa8795676b 1150 ccs_delete_item(g_fcc_offset_from_utc_parameter_name, CCS_CONFIG_ITEM);
leothedragon 0:25fa8795676b 1151 ccs_set_item(g_fcc_offset_from_utc_parameter_name, (const uint8_t*)temp.c_str(), temp.size(), CCS_CONFIG_ITEM);
leothedragon 0:25fa8795676b 1152 }
leothedragon 0:25fa8795676b 1153
leothedragon 0:25fa8795676b 1154 status = CCS_STATUS_SUCCESS;
leothedragon 0:25fa8795676b 1155 }
leothedragon 0:25fa8795676b 1156 else {
leothedragon 0:25fa8795676b 1157 tr_debug("No device object to store!");
leothedragon 0:25fa8795676b 1158 }
leothedragon 0:25fa8795676b 1159
leothedragon 0:25fa8795676b 1160 return status;
leothedragon 0:25fa8795676b 1161 }
leothedragon 0:25fa8795676b 1162
leothedragon 0:25fa8795676b 1163 ccs_status_e ConnectorClient::set_bootstrap_credentials(M2MSecurity *security)
leothedragon 0:25fa8795676b 1164 {
leothedragon 0:25fa8795676b 1165 tr_debug("ConnectorClient::set_bootstrap_credentials");
leothedragon 0:25fa8795676b 1166 ccs_status_e status = CCS_STATUS_ERROR;
leothedragon 0:25fa8795676b 1167
leothedragon 0:25fa8795676b 1168 size_t uri_size = MAX_CERTIFICATE_SIZE;
leothedragon 0:25fa8795676b 1169 uint8_t bootstrap_uri[MAX_CERTIFICATE_SIZE];
leothedragon 0:25fa8795676b 1170 uint8_t *bootstrap_uri_ptr = (uint8_t*)&bootstrap_uri;
leothedragon 0:25fa8795676b 1171
leothedragon 0:25fa8795676b 1172 int32_t bs_id = security->get_security_instance_id(M2MSecurity::Bootstrap);
leothedragon 0:25fa8795676b 1173 if (bs_id == -1) {
leothedragon 0:25fa8795676b 1174 return status;
leothedragon 0:25fa8795676b 1175 }
leothedragon 0:25fa8795676b 1176
leothedragon 0:25fa8795676b 1177 String bs_uri = security->resource_value_string(M2MSecurity::M2MServerUri, bs_id);
leothedragon 0:25fa8795676b 1178 if (bs_uri.size() <= 0) {
leothedragon 0:25fa8795676b 1179 return status;
leothedragon 0:25fa8795676b 1180 }
leothedragon 0:25fa8795676b 1181
leothedragon 0:25fa8795676b 1182 // Update BS uri only if it has changed.
leothedragon 0:25fa8795676b 1183 // If uri is missing or some other error while reading the item --> return error.
leothedragon 0:25fa8795676b 1184 if (ccs_get_string_item(g_fcc_bootstrap_server_uri_name, bootstrap_uri_ptr, uri_size, CCS_CONFIG_ITEM) == CCS_STATUS_SUCCESS) {
leothedragon 0:25fa8795676b 1185 if (strcmp((const char*)bootstrap_uri_ptr, bs_uri.c_str()) != 0) {
leothedragon 0:25fa8795676b 1186 tr_info("ConnectorClient::set_bootstrap_credentials - update uri from: %s to: %s", (char*)bootstrap_uri_ptr, bs_uri.c_str());
leothedragon 0:25fa8795676b 1187 ccs_delete_item(g_fcc_bootstrap_server_uri_name, CCS_CONFIG_ITEM);
leothedragon 0:25fa8795676b 1188 status = ccs_set_item(g_fcc_bootstrap_server_uri_name,
leothedragon 0:25fa8795676b 1189 (const uint8_t*)bs_uri.c_str(),
leothedragon 0:25fa8795676b 1190 strlen(bs_uri.c_str()),
leothedragon 0:25fa8795676b 1191 CCS_CONFIG_ITEM);
leothedragon 0:25fa8795676b 1192 } else {
leothedragon 0:25fa8795676b 1193 status = CCS_STATUS_SUCCESS;
leothedragon 0:25fa8795676b 1194 }
leothedragon 0:25fa8795676b 1195 }
leothedragon 0:25fa8795676b 1196
leothedragon 0:25fa8795676b 1197 return status;
leothedragon 0:25fa8795676b 1198 }
leothedragon 0:25fa8795676b 1199
leothedragon 0:25fa8795676b 1200 ccs_status_e ConnectorClient::clear_first_to_claim()
leothedragon 0:25fa8795676b 1201 {
leothedragon 0:25fa8795676b 1202 tr_debug("ConnectorClient::clear_first_to_claim");
leothedragon 0:25fa8795676b 1203 return ccs_delete_item(KEY_FIRST_TO_CLAIM, CCS_CONFIG_ITEM);
leothedragon 0:25fa8795676b 1204 }
leothedragon 0:25fa8795676b 1205
leothedragon 0:25fa8795676b 1206
leothedragon 0:25fa8795676b 1207 const ConnectorClientEndpointInfo *ConnectorClient::endpoint_info() const
leothedragon 0:25fa8795676b 1208 {
leothedragon 0:25fa8795676b 1209 return &_endpoint_info;
leothedragon 0:25fa8795676b 1210 }
leothedragon 0:25fa8795676b 1211
leothedragon 0:25fa8795676b 1212 bool ConnectorClient::bootstrap_credentials_stored_in_kcm()
leothedragon 0:25fa8795676b 1213 {
leothedragon 0:25fa8795676b 1214 size_t real_size = 0;
leothedragon 0:25fa8795676b 1215 ccs_status_e success = ccs_item_size(g_fcc_bootstrap_server_uri_name, &real_size, CCS_CONFIG_ITEM);
leothedragon 0:25fa8795676b 1216 // Return true if bootstrap uri exists in KCM
leothedragon 0:25fa8795676b 1217 if ((success == CCS_STATUS_SUCCESS) && real_size > 0) {
leothedragon 0:25fa8795676b 1218 return true;
leothedragon 0:25fa8795676b 1219 } else {
leothedragon 0:25fa8795676b 1220 return false;
leothedragon 0:25fa8795676b 1221 }
leothedragon 0:25fa8795676b 1222 }
leothedragon 0:25fa8795676b 1223
leothedragon 0:25fa8795676b 1224 bool ConnectorClient::is_first_to_claim()
leothedragon 0:25fa8795676b 1225 {
leothedragon 0:25fa8795676b 1226 size_t real_size = 0;
leothedragon 0:25fa8795676b 1227 uint8_t data[CONFIG_BOOLEAN_ITEM_SIZE] = {0};
leothedragon 0:25fa8795676b 1228 uint32_t value = 0;
leothedragon 0:25fa8795676b 1229 ccs_status_e status = ccs_get_item(KEY_FIRST_TO_CLAIM, data, CONFIG_BOOLEAN_ITEM_SIZE, &real_size, CCS_CONFIG_ITEM);
leothedragon 0:25fa8795676b 1230 if (status == CCS_STATUS_SUCCESS) {
leothedragon 0:25fa8795676b 1231 memcpy(&value, data, CONFIG_BOOLEAN_ITEM_SIZE);
leothedragon 0:25fa8795676b 1232 // Return true if first to claim is set
leothedragon 0:25fa8795676b 1233 if (value == 1) {
leothedragon 0:25fa8795676b 1234 return true;
leothedragon 0:25fa8795676b 1235 }
leothedragon 0:25fa8795676b 1236 }
leothedragon 0:25fa8795676b 1237 return false;
leothedragon 0:25fa8795676b 1238 }
leothedragon 0:25fa8795676b 1239
leothedragon 0:25fa8795676b 1240 void ConnectorClient::timer_expired(M2MTimerObserver::Type type)
leothedragon 0:25fa8795676b 1241 {
leothedragon 0:25fa8795676b 1242 if (type == M2MTimerObserver::BootstrapFlowTimer) {
leothedragon 0:25fa8795676b 1243 start_bootstrap();
leothedragon 0:25fa8795676b 1244 }
leothedragon 0:25fa8795676b 1245 }
leothedragon 0:25fa8795676b 1246
leothedragon 0:25fa8795676b 1247 #ifndef MBED_CLIENT_DISABLE_EST_FEATURE
leothedragon 0:25fa8795676b 1248 void ConnectorClient::est_enrollment_result(est_enrollment_result_e result,
leothedragon 0:25fa8795676b 1249 cert_chain_context_s *cert_chain,
leothedragon 0:25fa8795676b 1250 void *context)
leothedragon 0:25fa8795676b 1251 {
leothedragon 0:25fa8795676b 1252 tr_debug("ConnectorClient::est_enrollment_result - %s", result == EST_ENROLLMENT_SUCCESS ? "successful" : "failed");
leothedragon 0:25fa8795676b 1253 if (result == EST_ENROLLMENT_SUCCESS) {
leothedragon 0:25fa8795676b 1254 tr_debug("ConnectorClient::est_enrollment_result - PublicKey size %d", cert_chain->chain_length);
leothedragon 0:25fa8795676b 1255 }
leothedragon 0:25fa8795676b 1256
leothedragon 0:25fa8795676b 1257 ConnectorClient *cc = static_cast<ConnectorClient*>(context);
leothedragon 0:25fa8795676b 1258 assert(cc);
leothedragon 0:25fa8795676b 1259 assert(cc->_security != NULL);
leothedragon 0:25fa8795676b 1260
leothedragon 0:25fa8795676b 1261 int32_t m2m_id = cc->_security->get_security_instance_id(M2MSecurity::M2MServer);
leothedragon 0:25fa8795676b 1262 StartupSubStateRegistration state = State_EST_Failure;
leothedragon 0:25fa8795676b 1263
leothedragon 0:25fa8795676b 1264 if (result == EST_ENROLLMENT_SUCCESS &&
leothedragon 0:25fa8795676b 1265 m2m_id >= 0 &&
leothedragon 0:25fa8795676b 1266 cert_chain != NULL &&
leothedragon 0:25fa8795676b 1267 cert_chain->chain_length > 0)
leothedragon 0:25fa8795676b 1268 {
leothedragon 0:25fa8795676b 1269
leothedragon 0:25fa8795676b 1270 kcm_cert_chain_handle chain_handle;
leothedragon 0:25fa8795676b 1271 kcm_status_e status = kcm_cert_chain_create(&chain_handle,
leothedragon 0:25fa8795676b 1272 (const uint8_t*)g_fcc_lwm2m_device_certificate_name,
leothedragon 0:25fa8795676b 1273 strlen(g_fcc_lwm2m_device_certificate_name),
leothedragon 0:25fa8795676b 1274 cert_chain->chain_length,
leothedragon 0:25fa8795676b 1275 false);
leothedragon 0:25fa8795676b 1276 tr_debug("Cert chain create %d", status);
leothedragon 0:25fa8795676b 1277 if (status == KCM_STATUS_SUCCESS) {
leothedragon 0:25fa8795676b 1278 cert_context_s *cert = cert_chain->certs;
leothedragon 0:25fa8795676b 1279 while (cert != NULL) {
leothedragon 0:25fa8795676b 1280
leothedragon 0:25fa8795676b 1281 // Store certificate
leothedragon 0:25fa8795676b 1282 status = kcm_cert_chain_add_next(chain_handle, cert->cert, cert->cert_length);
leothedragon 0:25fa8795676b 1283 if (status != KCM_STATUS_SUCCESS) {
leothedragon 0:25fa8795676b 1284 break;
leothedragon 0:25fa8795676b 1285 }
leothedragon 0:25fa8795676b 1286
leothedragon 0:25fa8795676b 1287 cert = cert->next;
leothedragon 0:25fa8795676b 1288 }
leothedragon 0:25fa8795676b 1289
leothedragon 0:25fa8795676b 1290 status = kcm_cert_chain_close(chain_handle);
leothedragon 0:25fa8795676b 1291 if (status == KCM_STATUS_SUCCESS) {
leothedragon 0:25fa8795676b 1292 tr_info("ConnectorClient::est_enrollment_result() - Certificates stored successfully");
leothedragon 0:25fa8795676b 1293 tr_info("ConnectorClient::est_enrollment_result() - Storing lwm2m credentials");
leothedragon 0:25fa8795676b 1294 if (cc->set_connector_credentials(cc->_security) == CCS_STATUS_SUCCESS) {
leothedragon 0:25fa8795676b 1295 state = State_EST_Success;
leothedragon 0:25fa8795676b 1296 }
leothedragon 0:25fa8795676b 1297 }
leothedragon 0:25fa8795676b 1298 else {
leothedragon 0:25fa8795676b 1299 tr_error("ConnectorClient::est_enrollment_result - storing certificate chain failed!");
leothedragon 0:25fa8795676b 1300 }
leothedragon 0:25fa8795676b 1301 }
leothedragon 0:25fa8795676b 1302 }
leothedragon 0:25fa8795676b 1303
leothedragon 0:25fa8795676b 1304 // Finally free the certificate chain context
leothedragon 0:25fa8795676b 1305 EstClient::free_cert_chain_context(cert_chain);
leothedragon 0:25fa8795676b 1306
leothedragon 0:25fa8795676b 1307 cc->internal_event(state);
leothedragon 0:25fa8795676b 1308 }
leothedragon 0:25fa8795676b 1309 #endif /* !MBED_CLIENT_DISABLE_EST_FEATURE */
leothedragon 0:25fa8795676b 1310
leothedragon 0:25fa8795676b 1311
leothedragon 0:25fa8795676b 1312 M2MInterface::BindingMode ConnectorClient::transport_mode()
leothedragon 0:25fa8795676b 1313 {
leothedragon 0:25fa8795676b 1314 #ifdef MBED_CLOUD_CLIENT_TRANSPORT_MODE_UDP
leothedragon 0:25fa8795676b 1315 return M2MInterface::UDP;
leothedragon 0:25fa8795676b 1316 #elif defined MBED_CLOUD_CLIENT_TRANSPORT_MODE_TCP
leothedragon 0:25fa8795676b 1317 return M2MInterface::TCP;
leothedragon 0:25fa8795676b 1318 #elif defined MBED_CLOUD_CLIENT_TRANSPORT_MODE_UDP_QUEUE
leothedragon 0:25fa8795676b 1319 return M2MInterface::UDP_QUEUE;
leothedragon 0:25fa8795676b 1320 #elif defined MBED_CLOUD_CLIENT_TRANSPORT_MODE_TCP_QUEUE
leothedragon 0:25fa8795676b 1321 return M2MInterface::TCP_QUEUE;
leothedragon 0:25fa8795676b 1322 #else
leothedragon 0:25fa8795676b 1323 return M2MInterface::UDP;
leothedragon 0:25fa8795676b 1324 #endif
leothedragon 0:25fa8795676b 1325 }
leothedragon 0:25fa8795676b 1326
leothedragon 0:25fa8795676b 1327 void ConnectorClient::init_security_object()
leothedragon 0:25fa8795676b 1328 {
leothedragon 0:25fa8795676b 1329 if (_security) {
leothedragon 0:25fa8795676b 1330 for (int i = 0; i <= M2MSecurity::Bootstrap; i++) {
leothedragon 0:25fa8795676b 1331 // _security->create_object_instance() returns NULL if object already exists
leothedragon 0:25fa8795676b 1332 if (_security->create_object_instance((M2MSecurity::ServerType)i)) {
leothedragon 0:25fa8795676b 1333 M2MResource* res = _security->get_resource(M2MSecurity::ServerPublicKey, i);
leothedragon 0:25fa8795676b 1334 if (res) {
leothedragon 0:25fa8795676b 1335 res->set_resource_read_callback(read_security_object_data_from_kcm, this);
leothedragon 0:25fa8795676b 1336 res->set_resource_write_callback(write_security_object_data_to_kcm, this);
leothedragon 0:25fa8795676b 1337 }
leothedragon 0:25fa8795676b 1338
leothedragon 0:25fa8795676b 1339 res = _security->get_resource(M2MSecurity::PublicKey, i);
leothedragon 0:25fa8795676b 1340 if (res) {
leothedragon 0:25fa8795676b 1341 res->set_resource_read_callback(read_security_object_data_from_kcm, this);
leothedragon 0:25fa8795676b 1342 res->set_resource_write_callback(write_security_object_data_to_kcm, this);
leothedragon 0:25fa8795676b 1343 }
leothedragon 0:25fa8795676b 1344
leothedragon 0:25fa8795676b 1345 res = _security->get_resource(M2MSecurity::Secretkey, i);
leothedragon 0:25fa8795676b 1346 if (res) {
leothedragon 0:25fa8795676b 1347 res->set_resource_read_callback(read_security_object_data_from_kcm, this);
leothedragon 0:25fa8795676b 1348 res->set_resource_write_callback(write_security_object_data_to_kcm, this);
leothedragon 0:25fa8795676b 1349 }
leothedragon 0:25fa8795676b 1350
leothedragon 0:25fa8795676b 1351 res = _security->get_resource(M2MSecurity::OpenCertificateChain, i);
leothedragon 0:25fa8795676b 1352 if (res) {
leothedragon 0:25fa8795676b 1353 res->set_resource_read_callback(open_certificate_chain_callback, this);
leothedragon 0:25fa8795676b 1354 }
leothedragon 0:25fa8795676b 1355
leothedragon 0:25fa8795676b 1356 res = _security->get_resource(M2MSecurity::ReadDeviceCertificateChain, i);
leothedragon 0:25fa8795676b 1357 if (res) {
leothedragon 0:25fa8795676b 1358 res->set_resource_read_callback(read_certificate_chain_callback, this);
leothedragon 0:25fa8795676b 1359 }
leothedragon 0:25fa8795676b 1360
leothedragon 0:25fa8795676b 1361 res = _security->get_resource(M2MSecurity::CloseCertificateChain, i);
leothedragon 0:25fa8795676b 1362 if (res) {
leothedragon 0:25fa8795676b 1363 res->set_resource_read_callback(close_certificate_chain_callback, this);
leothedragon 0:25fa8795676b 1364 }
leothedragon 0:25fa8795676b 1365 }
leothedragon 0:25fa8795676b 1366 }
leothedragon 0:25fa8795676b 1367 }
leothedragon 0:25fa8795676b 1368 }
leothedragon 0:25fa8795676b 1369
leothedragon 0:25fa8795676b 1370 void *ConnectorClient::certificate_chain_handle() const
leothedragon 0:25fa8795676b 1371 {
leothedragon 0:25fa8795676b 1372 return _certificate_chain_handle;
leothedragon 0:25fa8795676b 1373 }
leothedragon 0:25fa8795676b 1374
leothedragon 0:25fa8795676b 1375 void ConnectorClient::set_certificate_chain_handle(void *cert_handle)
leothedragon 0:25fa8795676b 1376 {
leothedragon 0:25fa8795676b 1377 _certificate_chain_handle = cert_handle;
leothedragon 0:25fa8795676b 1378 }
leothedragon 0:25fa8795676b 1379
leothedragon 0:25fa8795676b 1380 void ConnectorClient::bootstrap_again()
leothedragon 0:25fa8795676b 1381 {
leothedragon 0:25fa8795676b 1382 // delete the old connector credentials
leothedragon 0:25fa8795676b 1383 ccs_delete_item(g_fcc_lwm2m_server_uri_name, CCS_CONFIG_ITEM);
leothedragon 0:25fa8795676b 1384 ccs_delete_item(g_fcc_lwm2m_server_ca_certificate_name, CCS_CERTIFICATE_ITEM);
leothedragon 0:25fa8795676b 1385 ccs_delete_item(g_fcc_lwm2m_device_certificate_name, CCS_CERTIFICATE_ITEM);
leothedragon 0:25fa8795676b 1386 ccs_delete_item(g_fcc_lwm2m_device_private_key_name, CCS_PRIVATE_KEY_ITEM);
leothedragon 0:25fa8795676b 1387
leothedragon 0:25fa8795676b 1388 tr_error("ConnectorClient::bootstrap_again in %d seconds", _rebootstrap_time);
leothedragon 0:25fa8795676b 1389
leothedragon 0:25fa8795676b 1390 _rebootstrap_timer.start_timer(_rebootstrap_time * 1000, M2MTimerObserver::BootstrapFlowTimer, true);
leothedragon 0:25fa8795676b 1391 _rebootstrap_time *= 2;
leothedragon 0:25fa8795676b 1392 if (_rebootstrap_time > MAX_REBOOTSTRAP_TIMEOUT) {
leothedragon 0:25fa8795676b 1393 _rebootstrap_time = MAX_REBOOTSTRAP_TIMEOUT;
leothedragon 0:25fa8795676b 1394 }
leothedragon 0:25fa8795676b 1395
leothedragon 0:25fa8795676b 1396 _callback->connector_error(M2MInterface::SecureConnectionFailed, CONNECTOR_BOOTSTRAP_AGAIN);
leothedragon 0:25fa8795676b 1397 }