leo hendrickson / Mbed OS example-Ethernet-mbed-Cloud-connect
Committer:
leothedragon
Date:
Tue May 04 08:55:12 2021 +0000
Revision:
0:8f0bb79ddd48
nmn

Who changed what in which revision?

UserRevisionLine numberNew contents of line
leothedragon 0:8f0bb79ddd48 1 // ----------------------------------------------------------------------------
leothedragon 0:8f0bb79ddd48 2 // Copyright 2016-2017 ARM Ltd.
leothedragon 0:8f0bb79ddd48 3 //
leothedragon 0:8f0bb79ddd48 4 // SPDX-License-Identifier: Apache-2.0
leothedragon 0:8f0bb79ddd48 5 //
leothedragon 0:8f0bb79ddd48 6 // Licensed under the Apache License, Version 2.0 (the "License");
leothedragon 0:8f0bb79ddd48 7 // you may not use this file except in compliance with the License.
leothedragon 0:8f0bb79ddd48 8 // You may obtain a copy of the License at
leothedragon 0:8f0bb79ddd48 9 //
leothedragon 0:8f0bb79ddd48 10 // http://www.apache.org/licenses/LICENSE-2.0
leothedragon 0:8f0bb79ddd48 11 //
leothedragon 0:8f0bb79ddd48 12 // Unless required by applicable law or agreed to in writing, software
leothedragon 0:8f0bb79ddd48 13 // distributed under the License is distributed on an "AS IS" BASIS,
leothedragon 0:8f0bb79ddd48 14 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
leothedragon 0:8f0bb79ddd48 15 // See the License for the specific language governing permissions and
leothedragon 0:8f0bb79ddd48 16 // limitations under the License.
leothedragon 0:8f0bb79ddd48 17 // ----------------------------------------------------------------------------
leothedragon 0:8f0bb79ddd48 18
leothedragon 0:8f0bb79ddd48 19 #define __STDC_FORMAT_MACROS
leothedragon 0:8f0bb79ddd48 20 #include <inttypes.h>
leothedragon 0:8f0bb79ddd48 21
leothedragon 0:8f0bb79ddd48 22 #include "include/ConnectorClient.h"
leothedragon 0:8f0bb79ddd48 23 #include "include/EstClient.h"
leothedragon 0:8f0bb79ddd48 24 #include "mbed-trace/mbed_trace.h"
leothedragon 0:8f0bb79ddd48 25 #include "mbed-client-libservice/common_functions.h"
leothedragon 0:8f0bb79ddd48 26
leothedragon 0:8f0bb79ddd48 27 #include <stdio.h>
leothedragon 0:8f0bb79ddd48 28 #include <stdlib.h>
leothedragon 0:8f0bb79ddd48 29
leothedragon 0:8f0bb79ddd48 30 #define TRACE_GROUP "est"
leothedragon 0:8f0bb79ddd48 31
leothedragon 0:8f0bb79ddd48 32 struct enrollment_context_s {
leothedragon 0:8f0bb79ddd48 33 est_enrollment_result_cb result_cb;
leothedragon 0:8f0bb79ddd48 34 uint8_t *data;
leothedragon 0:8f0bb79ddd48 35 size_t data_size;
leothedragon 0:8f0bb79ddd48 36 void* context;
leothedragon 0:8f0bb79ddd48 37 };
leothedragon 0:8f0bb79ddd48 38
leothedragon 0:8f0bb79ddd48 39 #define EST_SEN_LWM2M "est/sen"
leothedragon 0:8f0bb79ddd48 40 #define EST_SEN_URI_FORMAT "est/%.*s/sen"
leothedragon 0:8f0bb79ddd48 41
leothedragon 0:8f0bb79ddd48 42 #define EST_CERT_CHAIN_VERSION 1
leothedragon 0:8f0bb79ddd48 43
leothedragon 0:8f0bb79ddd48 44 EstClient::EstClient(ConnectorClient& connector_client)
leothedragon 0:8f0bb79ddd48 45 :_connector_client(connector_client)
leothedragon 0:8f0bb79ddd48 46 {
leothedragon 0:8f0bb79ddd48 47
leothedragon 0:8f0bb79ddd48 48 }
leothedragon 0:8f0bb79ddd48 49
leothedragon 0:8f0bb79ddd48 50
leothedragon 0:8f0bb79ddd48 51 EstClient::~EstClient()
leothedragon 0:8f0bb79ddd48 52 {
leothedragon 0:8f0bb79ddd48 53 }
leothedragon 0:8f0bb79ddd48 54
leothedragon 0:8f0bb79ddd48 55 est_status_e EstClient::est_request_enrollment(const char *cert_name,
leothedragon 0:8f0bb79ddd48 56 const size_t cert_name_length,
leothedragon 0:8f0bb79ddd48 57 uint8_t *csr,
leothedragon 0:8f0bb79ddd48 58 const size_t csr_length,
leothedragon 0:8f0bb79ddd48 59 est_enrollment_result_cb result_cb,
leothedragon 0:8f0bb79ddd48 60 void *context) const
leothedragon 0:8f0bb79ddd48 61 {
leothedragon 0:8f0bb79ddd48 62 if (csr == NULL || csr_length == 0 || result_cb == NULL) {
leothedragon 0:8f0bb79ddd48 63 return EST_STATUS_INVALID_PARAMETERS;
leothedragon 0:8f0bb79ddd48 64 }
leothedragon 0:8f0bb79ddd48 65
leothedragon 0:8f0bb79ddd48 66 if (_connector_client.m2m_interface() == NULL) {
leothedragon 0:8f0bb79ddd48 67 return EST_STATUS_INVALID_PARAMETERS;
leothedragon 0:8f0bb79ddd48 68 }
leothedragon 0:8f0bb79ddd48 69
leothedragon 0:8f0bb79ddd48 70 enrollment_context_s *ctx = (enrollment_context_s*)malloc(sizeof(enrollment_context_s));
leothedragon 0:8f0bb79ddd48 71 if (ctx == NULL) {
leothedragon 0:8f0bb79ddd48 72 return EST_STATUS_MEMORY_ALLOCATION_FAILURE;
leothedragon 0:8f0bb79ddd48 73 }
leothedragon 0:8f0bb79ddd48 74
leothedragon 0:8f0bb79ddd48 75 char *uri = make_est_uri(cert_name, cert_name_length);
leothedragon 0:8f0bb79ddd48 76 if (uri == NULL) {
leothedragon 0:8f0bb79ddd48 77 free(ctx);
leothedragon 0:8f0bb79ddd48 78 return EST_STATUS_MEMORY_ALLOCATION_FAILURE;
leothedragon 0:8f0bb79ddd48 79 }
leothedragon 0:8f0bb79ddd48 80
leothedragon 0:8f0bb79ddd48 81 ctx->result_cb = result_cb;
leothedragon 0:8f0bb79ddd48 82 ctx->context = context;
leothedragon 0:8f0bb79ddd48 83 ctx->data = NULL;
leothedragon 0:8f0bb79ddd48 84 ctx->data_size = 0;
leothedragon 0:8f0bb79ddd48 85
leothedragon 0:8f0bb79ddd48 86 _connector_client.m2m_interface()->post_data_request(uri,
leothedragon 0:8f0bb79ddd48 87 false,
leothedragon 0:8f0bb79ddd48 88 csr_length,
leothedragon 0:8f0bb79ddd48 89 csr,
leothedragon 0:8f0bb79ddd48 90 EstClient::est_post_data_cb,
leothedragon 0:8f0bb79ddd48 91 EstClient::est_post_data_error_cb,
leothedragon 0:8f0bb79ddd48 92 (void*)ctx);
leothedragon 0:8f0bb79ddd48 93
leothedragon 0:8f0bb79ddd48 94 free(uri);
leothedragon 0:8f0bb79ddd48 95
leothedragon 0:8f0bb79ddd48 96 return EST_STATUS_SUCCESS;
leothedragon 0:8f0bb79ddd48 97 }
leothedragon 0:8f0bb79ddd48 98
leothedragon 0:8f0bb79ddd48 99 char* EstClient::make_est_uri(const char *cert_name,
leothedragon 0:8f0bb79ddd48 100 const size_t cert_name_length)
leothedragon 0:8f0bb79ddd48 101 {
leothedragon 0:8f0bb79ddd48 102 char *uri = NULL;
leothedragon 0:8f0bb79ddd48 103 size_t uri_len = 0;
leothedragon 0:8f0bb79ddd48 104 if (cert_name == NULL) {
leothedragon 0:8f0bb79ddd48 105 // LwM2M certificate
leothedragon 0:8f0bb79ddd48 106 uri = (char*)malloc(sizeof(EST_SEN_LWM2M));
leothedragon 0:8f0bb79ddd48 107 if (uri != NULL) {
leothedragon 0:8f0bb79ddd48 108 strcpy(uri, EST_SEN_LWM2M);
leothedragon 0:8f0bb79ddd48 109 }
leothedragon 0:8f0bb79ddd48 110 }
leothedragon 0:8f0bb79ddd48 111 else {
leothedragon 0:8f0bb79ddd48 112 // User certificate
leothedragon 0:8f0bb79ddd48 113 uri_len = snprintf(NULL, 0, EST_SEN_URI_FORMAT, (int)cert_name_length, cert_name);
leothedragon 0:8f0bb79ddd48 114 uri_len++; // For null terminator
leothedragon 0:8f0bb79ddd48 115 uri = (char*)calloc(uri_len, sizeof(char));
leothedragon 0:8f0bb79ddd48 116 if (uri != NULL) {
leothedragon 0:8f0bb79ddd48 117 snprintf(uri, uri_len, EST_SEN_URI_FORMAT, (int)cert_name_length, cert_name);
leothedragon 0:8f0bb79ddd48 118 }
leothedragon 0:8f0bb79ddd48 119 }
leothedragon 0:8f0bb79ddd48 120 return uri;
leothedragon 0:8f0bb79ddd48 121 }
leothedragon 0:8f0bb79ddd48 122
leothedragon 0:8f0bb79ddd48 123 void EstClient::est_post_data_cb(const uint8_t *buffer,
leothedragon 0:8f0bb79ddd48 124 size_t buffer_size,
leothedragon 0:8f0bb79ddd48 125 size_t total_size,
leothedragon 0:8f0bb79ddd48 126 bool last_block,
leothedragon 0:8f0bb79ddd48 127 void *context)
leothedragon 0:8f0bb79ddd48 128 {
leothedragon 0:8f0bb79ddd48 129 enrollment_context_s *enrollment_context = static_cast<enrollment_context_s*>(context);
leothedragon 0:8f0bb79ddd48 130 (void)total_size;
leothedragon 0:8f0bb79ddd48 131 assert(enrollment_context);
leothedragon 0:8f0bb79ddd48 132
leothedragon 0:8f0bb79ddd48 133 // Append new buffer to payload
leothedragon 0:8f0bb79ddd48 134 size_t new_size = enrollment_context->data_size + buffer_size;
leothedragon 0:8f0bb79ddd48 135 uint8_t *new_buffer = (uint8_t*)malloc(new_size);
leothedragon 0:8f0bb79ddd48 136 if (!new_buffer) {
leothedragon 0:8f0bb79ddd48 137 // Memory error!
leothedragon 0:8f0bb79ddd48 138 return;
leothedragon 0:8f0bb79ddd48 139 }
leothedragon 0:8f0bb79ddd48 140
leothedragon 0:8f0bb79ddd48 141 // Copy old data to start of buffer
leothedragon 0:8f0bb79ddd48 142 if (enrollment_context->data) {
leothedragon 0:8f0bb79ddd48 143 memcpy(new_buffer, enrollment_context->data, enrollment_context->data_size);
leothedragon 0:8f0bb79ddd48 144 free(enrollment_context->data);
leothedragon 0:8f0bb79ddd48 145 }
leothedragon 0:8f0bb79ddd48 146
leothedragon 0:8f0bb79ddd48 147 // Copy new data to buffer
leothedragon 0:8f0bb79ddd48 148 memcpy(new_buffer + enrollment_context->data_size, buffer, buffer_size);
leothedragon 0:8f0bb79ddd48 149
leothedragon 0:8f0bb79ddd48 150 enrollment_context->data = new_buffer;
leothedragon 0:8f0bb79ddd48 151 enrollment_context->data_size = new_size;
leothedragon 0:8f0bb79ddd48 152
leothedragon 0:8f0bb79ddd48 153 if (last_block) {
leothedragon 0:8f0bb79ddd48 154 cert_chain_context_s *cert_ctx = parse_cert_chain(enrollment_context->data, enrollment_context->data_size);
leothedragon 0:8f0bb79ddd48 155 if (cert_ctx != NULL) {
leothedragon 0:8f0bb79ddd48 156 enrollment_context->result_cb(EST_ENROLLMENT_SUCCESS, cert_ctx, enrollment_context->context);
leothedragon 0:8f0bb79ddd48 157 }
leothedragon 0:8f0bb79ddd48 158 else {
leothedragon 0:8f0bb79ddd48 159 enrollment_context->result_cb(EST_ENROLLMENT_FAILURE, NULL, enrollment_context->context);
leothedragon 0:8f0bb79ddd48 160 }
leothedragon 0:8f0bb79ddd48 161
leothedragon 0:8f0bb79ddd48 162 free(enrollment_context);
leothedragon 0:8f0bb79ddd48 163 }
leothedragon 0:8f0bb79ddd48 164
leothedragon 0:8f0bb79ddd48 165 }
leothedragon 0:8f0bb79ddd48 166
leothedragon 0:8f0bb79ddd48 167 void EstClient::est_post_data_error_cb(get_data_req_error_t error_code,
leothedragon 0:8f0bb79ddd48 168 void *context)
leothedragon 0:8f0bb79ddd48 169 {
leothedragon 0:8f0bb79ddd48 170 enrollment_context_s *enrollment_context = static_cast<enrollment_context_s*>(context);
leothedragon 0:8f0bb79ddd48 171 assert(enrollment_context);
leothedragon 0:8f0bb79ddd48 172 enrollment_context->result_cb(EST_ENROLLMENT_FAILURE, NULL, enrollment_context->context);
leothedragon 0:8f0bb79ddd48 173 free(enrollment_context);
leothedragon 0:8f0bb79ddd48 174 }
leothedragon 0:8f0bb79ddd48 175
leothedragon 0:8f0bb79ddd48 176 cert_chain_context_s* EstClient::parse_cert_chain(uint8_t *cert_chain_data,
leothedragon 0:8f0bb79ddd48 177 uint16_t cert_chain_data_len)
leothedragon 0:8f0bb79ddd48 178 {
leothedragon 0:8f0bb79ddd48 179 assert(cert_chain_data);
leothedragon 0:8f0bb79ddd48 180 assert(cert_chain_data_len > 0);
leothedragon 0:8f0bb79ddd48 181
leothedragon 0:8f0bb79ddd48 182 uint8_t *ptr = cert_chain_data;
leothedragon 0:8f0bb79ddd48 183 cert_chain_context_s *context = (cert_chain_context_s*)malloc(sizeof(cert_chain_context_s));
leothedragon 0:8f0bb79ddd48 184
leothedragon 0:8f0bb79ddd48 185 if (context != NULL) {
leothedragon 0:8f0bb79ddd48 186 bool success = true;
leothedragon 0:8f0bb79ddd48 187 context->cert_data_context = ptr;
leothedragon 0:8f0bb79ddd48 188 uint8_t version = *ptr++;
leothedragon 0:8f0bb79ddd48 189 context->chain_length = *ptr++;
leothedragon 0:8f0bb79ddd48 190 cert_context_s **next_context_ptr = &context->certs;
leothedragon 0:8f0bb79ddd48 191
leothedragon 0:8f0bb79ddd48 192 // Check if unknown version
leothedragon 0:8f0bb79ddd48 193 if (version != EST_CERT_CHAIN_VERSION) {
leothedragon 0:8f0bb79ddd48 194 success = false;
leothedragon 0:8f0bb79ddd48 195 }
leothedragon 0:8f0bb79ddd48 196
leothedragon 0:8f0bb79ddd48 197 // Check overflow
leothedragon 0:8f0bb79ddd48 198 if (success && ptr - cert_chain_data > cert_chain_data_len) {
leothedragon 0:8f0bb79ddd48 199 success = false;
leothedragon 0:8f0bb79ddd48 200 context->chain_length = 0;
leothedragon 0:8f0bb79ddd48 201 }
leothedragon 0:8f0bb79ddd48 202
leothedragon 0:8f0bb79ddd48 203 if (success) {
leothedragon 0:8f0bb79ddd48 204 for (int i = 0; i < context->chain_length; i++) {
leothedragon 0:8f0bb79ddd48 205 // Parse certificate length (2 bytes)
leothedragon 0:8f0bb79ddd48 206 uint16_t cert_len = common_read_16_bit(ptr);
leothedragon 0:8f0bb79ddd48 207 ptr += 2;
leothedragon 0:8f0bb79ddd48 208 // Check overflow
leothedragon 0:8f0bb79ddd48 209 if (ptr - cert_chain_data > cert_chain_data_len) {
leothedragon 0:8f0bb79ddd48 210 success = false;
leothedragon 0:8f0bb79ddd48 211 break;
leothedragon 0:8f0bb79ddd48 212 }
leothedragon 0:8f0bb79ddd48 213
leothedragon 0:8f0bb79ddd48 214 // Allocate new certificate context
leothedragon 0:8f0bb79ddd48 215 *next_context_ptr = (cert_context_s*)malloc(sizeof(cert_context_s));
leothedragon 0:8f0bb79ddd48 216 if (*next_context_ptr == NULL) {
leothedragon 0:8f0bb79ddd48 217 // Error
leothedragon 0:8f0bb79ddd48 218 success = false;
leothedragon 0:8f0bb79ddd48 219 break;
leothedragon 0:8f0bb79ddd48 220 }
leothedragon 0:8f0bb79ddd48 221
leothedragon 0:8f0bb79ddd48 222 // Set cert pointer to correct position in data
leothedragon 0:8f0bb79ddd48 223 (*next_context_ptr)->cert_length = cert_len;
leothedragon 0:8f0bb79ddd48 224 (*next_context_ptr)->cert = ptr;
leothedragon 0:8f0bb79ddd48 225
leothedragon 0:8f0bb79ddd48 226 ptr += cert_len;
leothedragon 0:8f0bb79ddd48 227
leothedragon 0:8f0bb79ddd48 228 // Check overflow
leothedragon 0:8f0bb79ddd48 229 if (ptr - cert_chain_data > cert_chain_data_len) {
leothedragon 0:8f0bb79ddd48 230 success = false;
leothedragon 0:8f0bb79ddd48 231 free(*next_context_ptr);
leothedragon 0:8f0bb79ddd48 232 break;
leothedragon 0:8f0bb79ddd48 233 }
leothedragon 0:8f0bb79ddd48 234
leothedragon 0:8f0bb79ddd48 235 next_context_ptr = &((*next_context_ptr)->next);
leothedragon 0:8f0bb79ddd48 236 }
leothedragon 0:8f0bb79ddd48 237 *next_context_ptr = NULL;
leothedragon 0:8f0bb79ddd48 238 }
leothedragon 0:8f0bb79ddd48 239
leothedragon 0:8f0bb79ddd48 240 if (!success) {
leothedragon 0:8f0bb79ddd48 241 free_cert_chain_context(context);
leothedragon 0:8f0bb79ddd48 242 context = NULL;
leothedragon 0:8f0bb79ddd48 243 }
leothedragon 0:8f0bb79ddd48 244 }
leothedragon 0:8f0bb79ddd48 245
leothedragon 0:8f0bb79ddd48 246 return context;
leothedragon 0:8f0bb79ddd48 247 }
leothedragon 0:8f0bb79ddd48 248
leothedragon 0:8f0bb79ddd48 249 void EstClient::free_cert_chain_context(cert_chain_context_s *context) {
leothedragon 0:8f0bb79ddd48 250 if (context) {
leothedragon 0:8f0bb79ddd48 251 cert_context_s *next_cert = context->certs;
leothedragon 0:8f0bb79ddd48 252 while (next_cert != NULL) {
leothedragon 0:8f0bb79ddd48 253 cert_context_s *temp = next_cert->next;
leothedragon 0:8f0bb79ddd48 254 // Free each cert context, no need to free the cert data in
leothedragon 0:8f0bb79ddd48 255 // next_cert->cert because it points inside context->cert_data_context
leothedragon 0:8f0bb79ddd48 256 // which is free'd last
leothedragon 0:8f0bb79ddd48 257 free(next_cert);
leothedragon 0:8f0bb79ddd48 258 next_cert = temp;
leothedragon 0:8f0bb79ddd48 259 }
leothedragon 0:8f0bb79ddd48 260 free(context->cert_data_context);
leothedragon 0:8f0bb79ddd48 261 free(context);
leothedragon 0:8f0bb79ddd48 262 }
leothedragon 0:8f0bb79ddd48 263 }