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