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.
EstClient.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 #define __STDC_FORMAT_MACROS 00020 #include <inttypes.h> 00021 00022 #include "include/ConnectorClient.h" 00023 #include "include/EstClient.h" 00024 #include "mbed-trace/mbed_trace.h" 00025 #include "mbed-client-libservice/common_functions.h" 00026 00027 #include <stdio.h> 00028 #include <stdlib.h> 00029 00030 #define TRACE_GROUP "est" 00031 00032 struct enrollment_context_s { 00033 est_enrollment_result_cb result_cb; 00034 uint8_t *data; 00035 size_t data_size; 00036 void* context; 00037 }; 00038 00039 #define EST_SEN_LWM2M "est/sen" 00040 #define EST_SEN_URI_FORMAT "est/%.*s/sen" 00041 00042 #define EST_CERT_CHAIN_VERSION 1 00043 00044 EstClient::EstClient(ConnectorClient& connector_client) 00045 :_connector_client(connector_client) 00046 { 00047 00048 } 00049 00050 00051 EstClient::~EstClient() 00052 { 00053 } 00054 00055 est_status_e EstClient::est_request_enrollment(const char *cert_name, 00056 const size_t cert_name_length, 00057 uint8_t *csr, 00058 const size_t csr_length, 00059 est_enrollment_result_cb result_cb, 00060 void *context) const 00061 { 00062 if (csr == NULL || csr_length == 0 || result_cb == NULL) { 00063 return EST_STATUS_INVALID_PARAMETERS; 00064 } 00065 00066 if (_connector_client.m2m_interface() == NULL) { 00067 return EST_STATUS_INVALID_PARAMETERS; 00068 } 00069 00070 enrollment_context_s *ctx = (enrollment_context_s*)malloc(sizeof(enrollment_context_s)); 00071 if (ctx == NULL) { 00072 return EST_STATUS_MEMORY_ALLOCATION_FAILURE; 00073 } 00074 00075 char *uri = make_est_uri(cert_name, cert_name_length); 00076 if (uri == NULL) { 00077 free(ctx); 00078 return EST_STATUS_MEMORY_ALLOCATION_FAILURE; 00079 } 00080 00081 ctx->result_cb = result_cb; 00082 ctx->context = context; 00083 ctx->data = NULL; 00084 ctx->data_size = 0; 00085 00086 _connector_client.m2m_interface()->post_data_request(uri, 00087 false, 00088 csr_length, 00089 csr, 00090 EstClient::est_post_data_cb, 00091 EstClient::est_post_data_error_cb, 00092 (void*)ctx); 00093 00094 free(uri); 00095 00096 return EST_STATUS_SUCCESS; 00097 } 00098 00099 char* EstClient::make_est_uri(const char *cert_name, 00100 const size_t cert_name_length) 00101 { 00102 char *uri = NULL; 00103 size_t uri_len = 0; 00104 if (cert_name == NULL) { 00105 // LwM2M certificate 00106 uri = (char*)malloc(sizeof(EST_SEN_LWM2M)); 00107 if (uri != NULL) { 00108 strcpy(uri, EST_SEN_LWM2M); 00109 } 00110 } 00111 else { 00112 // User certificate 00113 uri_len = snprintf(NULL, 0, EST_SEN_URI_FORMAT, (int)cert_name_length, cert_name); 00114 uri_len++; // For null terminator 00115 uri = (char*)calloc(uri_len, sizeof(char)); 00116 if (uri != NULL) { 00117 snprintf(uri, uri_len, EST_SEN_URI_FORMAT, (int)cert_name_length, cert_name); 00118 } 00119 } 00120 return uri; 00121 } 00122 00123 void EstClient::est_post_data_cb(const uint8_t *buffer, 00124 size_t buffer_size, 00125 size_t total_size, 00126 bool last_block, 00127 void *context) 00128 { 00129 enrollment_context_s *enrollment_context = static_cast<enrollment_context_s*>(context); 00130 (void)total_size; 00131 assert(enrollment_context); 00132 00133 // Append new buffer to payload 00134 size_t new_size = enrollment_context->data_size + buffer_size; 00135 uint8_t *new_buffer = (uint8_t*)malloc(new_size); 00136 if (!new_buffer) { 00137 // Memory error! 00138 return; 00139 } 00140 00141 // Copy old data to start of buffer 00142 if (enrollment_context->data) { 00143 memcpy(new_buffer, enrollment_context->data, enrollment_context->data_size); 00144 free(enrollment_context->data); 00145 } 00146 00147 // Copy new data to buffer 00148 memcpy(new_buffer + enrollment_context->data_size, buffer, buffer_size); 00149 00150 enrollment_context->data = new_buffer; 00151 enrollment_context->data_size = new_size; 00152 00153 if (last_block) { 00154 cert_chain_context_s *cert_ctx = parse_cert_chain(enrollment_context->data, enrollment_context->data_size); 00155 if (cert_ctx != NULL) { 00156 enrollment_context->result_cb(EST_ENROLLMENT_SUCCESS, cert_ctx, enrollment_context->context); 00157 } 00158 else { 00159 enrollment_context->result_cb(EST_ENROLLMENT_FAILURE, NULL, enrollment_context->context); 00160 } 00161 00162 free(enrollment_context); 00163 } 00164 00165 } 00166 00167 void EstClient::est_post_data_error_cb(get_data_req_error_t error_code, 00168 void *context) 00169 { 00170 enrollment_context_s *enrollment_context = static_cast<enrollment_context_s*>(context); 00171 assert(enrollment_context); 00172 enrollment_context->result_cb(EST_ENROLLMENT_FAILURE, NULL, enrollment_context->context); 00173 free(enrollment_context); 00174 } 00175 00176 cert_chain_context_s* EstClient::parse_cert_chain(uint8_t *cert_chain_data, 00177 uint16_t cert_chain_data_len) 00178 { 00179 assert(cert_chain_data); 00180 assert(cert_chain_data_len > 0); 00181 00182 uint8_t *ptr = cert_chain_data; 00183 cert_chain_context_s *context = (cert_chain_context_s*)malloc(sizeof(cert_chain_context_s)); 00184 00185 if (context != NULL) { 00186 bool success = true; 00187 context->cert_data_context = ptr; 00188 uint8_t version = *ptr++; 00189 context->chain_length = *ptr++; 00190 cert_context_s **next_context_ptr = &context->certs; 00191 00192 // Check if unknown version 00193 if (version != EST_CERT_CHAIN_VERSION) { 00194 success = false; 00195 } 00196 00197 // Check overflow 00198 if (success && ptr - cert_chain_data > cert_chain_data_len) { 00199 success = false; 00200 context->chain_length = 0; 00201 } 00202 00203 if (success) { 00204 for (int i = 0; i < context->chain_length; i++) { 00205 // Parse certificate length (2 bytes) 00206 uint16_t cert_len = common_read_16_bit(ptr); 00207 ptr += 2; 00208 // Check overflow 00209 if (ptr - cert_chain_data > cert_chain_data_len) { 00210 success = false; 00211 break; 00212 } 00213 00214 // Allocate new certificate context 00215 *next_context_ptr = (cert_context_s*)malloc(sizeof(cert_context_s)); 00216 if (*next_context_ptr == NULL) { 00217 // Error 00218 success = false; 00219 break; 00220 } 00221 00222 // Set cert pointer to correct position in data 00223 (*next_context_ptr)->cert_length = cert_len; 00224 (*next_context_ptr)->cert = ptr; 00225 00226 ptr += cert_len; 00227 00228 // Check overflow 00229 if (ptr - cert_chain_data > cert_chain_data_len) { 00230 success = false; 00231 free(*next_context_ptr); 00232 break; 00233 } 00234 00235 next_context_ptr = &((*next_context_ptr)->next); 00236 } 00237 *next_context_ptr = NULL; 00238 } 00239 00240 if (!success) { 00241 free_cert_chain_context(context); 00242 context = NULL; 00243 } 00244 } 00245 00246 return context; 00247 } 00248 00249 void EstClient::free_cert_chain_context(cert_chain_context_s *context) { 00250 if (context) { 00251 cert_context_s *next_cert = context->certs; 00252 while (next_cert != NULL) { 00253 cert_context_s *temp = next_cert->next; 00254 // Free each cert context, no need to free the cert data in 00255 // next_cert->cert because it points inside context->cert_data_context 00256 // which is free'd last 00257 free(next_cert); 00258 next_cert = temp; 00259 } 00260 free(context->cert_data_context); 00261 free(context); 00262 } 00263 }
Generated on Mon Aug 29 2022 19:53:39 by
