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 2018 ARM Ltd.
leothedragon 0:8f0bb79ddd48 3 //
leothedragon 0:8f0bb79ddd48 4 // Licensed under the Apache License, Version 2.0 (the "License");
leothedragon 0:8f0bb79ddd48 5 // you may not use this file except in compliance with the License.
leothedragon 0:8f0bb79ddd48 6 // You may obtain a copy of the License at
leothedragon 0:8f0bb79ddd48 7 //
leothedragon 0:8f0bb79ddd48 8 // http://www.apache.org/licenses/LICENSE-2.0
leothedragon 0:8f0bb79ddd48 9 //
leothedragon 0:8f0bb79ddd48 10 // Unless required by applicable law or agreed to in writing, software
leothedragon 0:8f0bb79ddd48 11 // distributed under the License is distributed on an "AS IS" BASIS,
leothedragon 0:8f0bb79ddd48 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
leothedragon 0:8f0bb79ddd48 13 // See the License for the specific language governing permissions and
leothedragon 0:8f0bb79ddd48 14 // limitations under the License.
leothedragon 0:8f0bb79ddd48 15 // ----------------------------------------------------------------------------
leothedragon 0:8f0bb79ddd48 16
leothedragon 0:8f0bb79ddd48 17
leothedragon 0:8f0bb79ddd48 18 #include <stdbool.h>
leothedragon 0:8f0bb79ddd48 19 #include <stdint.h>
leothedragon 0:8f0bb79ddd48 20 #include <string.h>
leothedragon 0:8f0bb79ddd48 21 #include <stdio.h>
leothedragon 0:8f0bb79ddd48 22
leothedragon 0:8f0bb79ddd48 23 #include "ce_tlv.h"
leothedragon 0:8f0bb79ddd48 24 #include "pv_log.h"
leothedragon 0:8f0bb79ddd48 25 #include "pal_macros.h"
leothedragon 0:8f0bb79ddd48 26 #include "pv_error_handling.h"
leothedragon 0:8f0bb79ddd48 27
leothedragon 0:8f0bb79ddd48 28 #define TYPE_LENGTH_IN_BYTES 2
leothedragon 0:8f0bb79ddd48 29 #define LEN_LENGTH_IN_BYTES 2
leothedragon 0:8f0bb79ddd48 30
leothedragon 0:8f0bb79ddd48 31 // Get the number of bit in a specific variable
leothedragon 0:8f0bb79ddd48 32 #define CE_BITS(var) (sizeof(var) * 8)
leothedragon 0:8f0bb79ddd48 33 // Get the MSB bit number
leothedragon 0:8f0bb79ddd48 34 #define CE_MSB(var) (CE_BITS(var) - 1)
leothedragon 0:8f0bb79ddd48 35
leothedragon 0:8f0bb79ddd48 36
leothedragon 0:8f0bb79ddd48 37 static bool is_element_in_range(const ce_tlv_element_s *element, uint16_t num_of_bytes_to_take)
leothedragon 0:8f0bb79ddd48 38 {
leothedragon 0:8f0bb79ddd48 39 if (element->_end < element->_current) {
leothedragon 0:8f0bb79ddd48 40 return false;
leothedragon 0:8f0bb79ddd48 41 }
leothedragon 0:8f0bb79ddd48 42 if ((element->_end - element->_current) >= num_of_bytes_to_take) {
leothedragon 0:8f0bb79ddd48 43 return true;
leothedragon 0:8f0bb79ddd48 44 }
leothedragon 0:8f0bb79ddd48 45 return false;
leothedragon 0:8f0bb79ddd48 46 }
leothedragon 0:8f0bb79ddd48 47
leothedragon 0:8f0bb79ddd48 48 static ce_tlv_status_e take_16bit_number(ce_tlv_element_s *element, uint16_t *number_out)
leothedragon 0:8f0bb79ddd48 49 {
leothedragon 0:8f0bb79ddd48 50 if (!is_element_in_range(element, sizeof(*number_out))) {
leothedragon 0:8f0bb79ddd48 51 return CE_TLV_STATUS_MALFORMED_TLV;
leothedragon 0:8f0bb79ddd48 52 }
leothedragon 0:8f0bb79ddd48 53
leothedragon 0:8f0bb79ddd48 54 memcpy(number_out, element->_current, sizeof(*number_out));
leothedragon 0:8f0bb79ddd48 55
leothedragon 0:8f0bb79ddd48 56 // Convert from network endianity (big endian) to host endianity in a portable manner
leothedragon 0:8f0bb79ddd48 57 *number_out = (uint16_t)PAL_NTOHS(*number_out);
leothedragon 0:8f0bb79ddd48 58 element->_current += sizeof(*number_out);
leothedragon 0:8f0bb79ddd48 59 return CE_TLV_STATUS_SUCCESS;
leothedragon 0:8f0bb79ddd48 60 }
leothedragon 0:8f0bb79ddd48 61
leothedragon 0:8f0bb79ddd48 62 static ce_tlv_status_e take_bytes(ce_tlv_element_s *element)
leothedragon 0:8f0bb79ddd48 63 {
leothedragon 0:8f0bb79ddd48 64 if (!is_element_in_range(element, element->len)) {
leothedragon 0:8f0bb79ddd48 65 return CE_TLV_STATUS_MALFORMED_TLV;
leothedragon 0:8f0bb79ddd48 66 }
leothedragon 0:8f0bb79ddd48 67
leothedragon 0:8f0bb79ddd48 68 element->val.bytes = element->_current;
leothedragon 0:8f0bb79ddd48 69 element->_current += element->len;
leothedragon 0:8f0bb79ddd48 70 return CE_TLV_STATUS_SUCCESS;
leothedragon 0:8f0bb79ddd48 71 }
leothedragon 0:8f0bb79ddd48 72
leothedragon 0:8f0bb79ddd48 73 bool is_required(const ce_tlv_element_s *element)
leothedragon 0:8f0bb79ddd48 74 {
leothedragon 0:8f0bb79ddd48 75 return element->is_required;
leothedragon 0:8f0bb79ddd48 76 }
leothedragon 0:8f0bb79ddd48 77
leothedragon 0:8f0bb79ddd48 78 static ce_tlv_status_e take_type(ce_tlv_element_s *element)
leothedragon 0:8f0bb79ddd48 79 {
leothedragon 0:8f0bb79ddd48 80 ce_tlv_status_e status = take_16bit_number(element, &element->type);
leothedragon 0:8f0bb79ddd48 81 SA_PV_ERR_RECOVERABLE_RETURN_IF((status != CE_TLV_STATUS_SUCCESS), status, "failed in take_16bit_number()");
leothedragon 0:8f0bb79ddd48 82
leothedragon 0:8f0bb79ddd48 83 // keep order, test "is required" and then clear the type MSB
leothedragon 0:8f0bb79ddd48 84 element->is_required = (((element->type >> CE_MSB(element->type)) & 1) == 1) ? false : true;
leothedragon 0:8f0bb79ddd48 85 element->type &= (uint16_t)(~(1 << CE_MSB(element->type))); // clear the MSB bit
leothedragon 0:8f0bb79ddd48 86 return CE_TLV_STATUS_SUCCESS;
leothedragon 0:8f0bb79ddd48 87 }
leothedragon 0:8f0bb79ddd48 88
leothedragon 0:8f0bb79ddd48 89 static ce_tlv_status_e take_length(ce_tlv_element_s *element)
leothedragon 0:8f0bb79ddd48 90 {
leothedragon 0:8f0bb79ddd48 91 return take_16bit_number(element, &element->len);
leothedragon 0:8f0bb79ddd48 92 }
leothedragon 0:8f0bb79ddd48 93
leothedragon 0:8f0bb79ddd48 94 // Element where element->len is the length of the string
leothedragon 0:8f0bb79ddd48 95 static ce_tlv_status_e take_string(ce_tlv_element_s *element)
leothedragon 0:8f0bb79ddd48 96 {
leothedragon 0:8f0bb79ddd48 97 // Take the bytes
leothedragon 0:8f0bb79ddd48 98 ce_tlv_status_e status = take_bytes(element);
leothedragon 0:8f0bb79ddd48 99 SA_PV_ERR_RECOVERABLE_RETURN_IF((status != CE_TLV_STATUS_SUCCESS), status, "failed in take_bytes()");
leothedragon 0:8f0bb79ddd48 100
leothedragon 0:8f0bb79ddd48 101 // Assert null terminator at the end
leothedragon 0:8f0bb79ddd48 102 if (element->val.bytes[element->len - 1] != '\0') {
leothedragon 0:8f0bb79ddd48 103 return CE_TLV_STATUS_TEXT_NOT_TERMINATED;
leothedragon 0:8f0bb79ddd48 104 }
leothedragon 0:8f0bb79ddd48 105
leothedragon 0:8f0bb79ddd48 106 return CE_TLV_STATUS_SUCCESS;
leothedragon 0:8f0bb79ddd48 107 }
leothedragon 0:8f0bb79ddd48 108
leothedragon 0:8f0bb79ddd48 109 static ce_tlv_status_e take_value(ce_tlv_element_s *element)
leothedragon 0:8f0bb79ddd48 110 {
leothedragon 0:8f0bb79ddd48 111 switch (element->type) {
leothedragon 0:8f0bb79ddd48 112 case CE_TLV_TYPE_CERT_NAME:
leothedragon 0:8f0bb79ddd48 113 return take_string(element);
leothedragon 0:8f0bb79ddd48 114 default:
leothedragon 0:8f0bb79ddd48 115 // Skip next
leothedragon 0:8f0bb79ddd48 116 element->_current += element->len;
leothedragon 0:8f0bb79ddd48 117 break;
leothedragon 0:8f0bb79ddd48 118 }
leothedragon 0:8f0bb79ddd48 119
leothedragon 0:8f0bb79ddd48 120 return CE_TLV_STATUS_SUCCESS;
leothedragon 0:8f0bb79ddd48 121 }
leothedragon 0:8f0bb79ddd48 122
leothedragon 0:8f0bb79ddd48 123
leothedragon 0:8f0bb79ddd48 124 ce_tlv_status_e ce_tlv_parser_init(const uint8_t *tlv_buf, size_t tlv_buf_len, ce_tlv_element_s *element_out)
leothedragon 0:8f0bb79ddd48 125 {
leothedragon 0:8f0bb79ddd48 126 // Null check
leothedragon 0:8f0bb79ddd48 127 SA_PV_ERR_RECOVERABLE_RETURN_IF((tlv_buf == NULL), CE_TLV_STATUS_INVALID_ARG, "Invalid tlv_buf");
leothedragon 0:8f0bb79ddd48 128 SA_PV_ERR_RECOVERABLE_RETURN_IF((element_out == NULL), CE_TLV_STATUS_INVALID_ARG, "Invalid element_out");
leothedragon 0:8f0bb79ddd48 129 SA_PV_ERR_RECOVERABLE_RETURN_IF((tlv_buf_len == 0), CE_TLV_STATUS_INVALID_ARG, "empty tlv_buf_len");
leothedragon 0:8f0bb79ddd48 130
leothedragon 0:8f0bb79ddd48 131 memset(element_out, 0, sizeof(ce_tlv_element_s));
leothedragon 0:8f0bb79ddd48 132
leothedragon 0:8f0bb79ddd48 133 element_out->_current = tlv_buf;
leothedragon 0:8f0bb79ddd48 134 element_out->_end = (tlv_buf + tlv_buf_len);
leothedragon 0:8f0bb79ddd48 135
leothedragon 0:8f0bb79ddd48 136 return CE_TLV_STATUS_SUCCESS;
leothedragon 0:8f0bb79ddd48 137 }
leothedragon 0:8f0bb79ddd48 138
leothedragon 0:8f0bb79ddd48 139 ce_tlv_status_e ce_tlv_parse_next(ce_tlv_element_s *element)
leothedragon 0:8f0bb79ddd48 140 {
leothedragon 0:8f0bb79ddd48 141 ce_tlv_status_e status = CE_TLV_STATUS_SUCCESS;
leothedragon 0:8f0bb79ddd48 142
leothedragon 0:8f0bb79ddd48 143 SA_PV_ERR_RECOVERABLE_RETURN_IF((element == NULL), CE_TLV_STATUS_INVALID_ARG, "Invalid element");
leothedragon 0:8f0bb79ddd48 144
leothedragon 0:8f0bb79ddd48 145 // Check if we are at the end of the buffer
leothedragon 0:8f0bb79ddd48 146 if (element->_current == element->_end) {
leothedragon 0:8f0bb79ddd48 147 return CE_TLV_STATUS_END;
leothedragon 0:8f0bb79ddd48 148 }
leothedragon 0:8f0bb79ddd48 149
leothedragon 0:8f0bb79ddd48 150 // If this is true then there is a bug in the code
leothedragon 0:8f0bb79ddd48 151 // TBD: check if we need to remove this assert
leothedragon 0:8f0bb79ddd48 152 assert(element->_current < element->_end);
leothedragon 0:8f0bb79ddd48 153
leothedragon 0:8f0bb79ddd48 154 // Parse type
leothedragon 0:8f0bb79ddd48 155 status = take_type(element);
leothedragon 0:8f0bb79ddd48 156 SA_PV_ERR_RECOVERABLE_RETURN_IF((status != CE_TLV_STATUS_SUCCESS), status, "failed in take_bytes()");
leothedragon 0:8f0bb79ddd48 157
leothedragon 0:8f0bb79ddd48 158 // Parse length
leothedragon 0:8f0bb79ddd48 159 status = take_length(element);
leothedragon 0:8f0bb79ddd48 160 SA_PV_ERR_RECOVERABLE_RETURN_IF((status != CE_TLV_STATUS_SUCCESS), status, "failed in take_length()");
leothedragon 0:8f0bb79ddd48 161
leothedragon 0:8f0bb79ddd48 162 // Parse value
leothedragon 0:8f0bb79ddd48 163 status = take_value(element);
leothedragon 0:8f0bb79ddd48 164 SA_PV_ERR_RECOVERABLE_RETURN_IF((status != CE_TLV_STATUS_SUCCESS), status, "failed in take_value()");
leothedragon 0:8f0bb79ddd48 165
leothedragon 0:8f0bb79ddd48 166 return CE_TLV_STATUS_SUCCESS;
leothedragon 0:8f0bb79ddd48 167 }
leothedragon 0:8f0bb79ddd48 168
leothedragon 0:8f0bb79ddd48 169 #ifdef CERT_RENEWAL_TEST
leothedragon 0:8f0bb79ddd48 170 static void _append_16bit_number(uint16_t number, ce_tlv_encoder_s *encoder)
leothedragon 0:8f0bb79ddd48 171 {
leothedragon 0:8f0bb79ddd48 172 uint16_t num_buf = (uint16_t)PAL_HTONS(number);
leothedragon 0:8f0bb79ddd48 173
leothedragon 0:8f0bb79ddd48 174 memcpy(encoder->buf + (uint8_t)encoder->encoded_length, &num_buf, sizeof(num_buf));
leothedragon 0:8f0bb79ddd48 175 encoder->encoded_length = (uint16_t)(encoder->encoded_length +sizeof(num_buf));
leothedragon 0:8f0bb79ddd48 176 }
leothedragon 0:8f0bb79ddd48 177
leothedragon 0:8f0bb79ddd48 178 static void _append_value_string(const char *str, uint16_t str_length, ce_tlv_encoder_s *encoder)
leothedragon 0:8f0bb79ddd48 179 {
leothedragon 0:8f0bb79ddd48 180 // str_length should contain the '\0'
leothedragon 0:8f0bb79ddd48 181 memcpy(encoder->buf + encoder->encoded_length, str, str_length);
leothedragon 0:8f0bb79ddd48 182 // FIXME: Cast is needed here, need to check why getting compilation warning in Native GCC (Linux)
leothedragon 0:8f0bb79ddd48 183 encoder->encoded_length = (uint16_t)(str_length + encoder->encoded_length);
leothedragon 0:8f0bb79ddd48 184 }
leothedragon 0:8f0bb79ddd48 185
leothedragon 0:8f0bb79ddd48 186 ce_tlv_status_e tlv_add_str(ce_tlv_type_e type, uint16_t length, const char *value, bool is_tlv_required, ce_tlv_encoder_s *encoder)
leothedragon 0:8f0bb79ddd48 187 {
leothedragon 0:8f0bb79ddd48 188 uint16_t _type = type;
leothedragon 0:8f0bb79ddd48 189
leothedragon 0:8f0bb79ddd48 190 // If out of range - update the length - and return CE_TLV_STATUS_ENCODER_INSUFFICIENT_BUFFER
leothedragon 0:8f0bb79ddd48 191 // Next encoding will do the same and any time we may know how big the buffer must be: encoder->encoded_length
leothedragon 0:8f0bb79ddd48 192 if (encoder->encoded_length + TYPE_LENGTH_IN_BYTES + LEN_LENGTH_IN_BYTES + length > encoder->_buf_size) {
leothedragon 0:8f0bb79ddd48 193 encoder->encoded_length = (uint16_t)(encoder->encoded_length + (TYPE_LENGTH_IN_BYTES + LEN_LENGTH_IN_BYTES + length));
leothedragon 0:8f0bb79ddd48 194 return CE_TLV_STATUS_ENCODER_INSUFFICIENT_BUFFER;
leothedragon 0:8f0bb79ddd48 195 }
leothedragon 0:8f0bb79ddd48 196
leothedragon 0:8f0bb79ddd48 197 // Append type
leothedragon 0:8f0bb79ddd48 198
leothedragon 0:8f0bb79ddd48 199 if (!is_tlv_required) {
leothedragon 0:8f0bb79ddd48 200 // set MSB only if optional
leothedragon 0:8f0bb79ddd48 201 _type |= 1 << CE_MSB(_type);
leothedragon 0:8f0bb79ddd48 202 }
leothedragon 0:8f0bb79ddd48 203 _append_16bit_number(_type, encoder);
leothedragon 0:8f0bb79ddd48 204
leothedragon 0:8f0bb79ddd48 205 // Append length
leothedragon 0:8f0bb79ddd48 206 _append_16bit_number(length, encoder);
leothedragon 0:8f0bb79ddd48 207
leothedragon 0:8f0bb79ddd48 208 // Append value
leothedragon 0:8f0bb79ddd48 209 _append_value_string(value, length, encoder);
leothedragon 0:8f0bb79ddd48 210
leothedragon 0:8f0bb79ddd48 211 return CE_TLV_STATUS_SUCCESS;
leothedragon 0:8f0bb79ddd48 212 }
leothedragon 0:8f0bb79ddd48 213
leothedragon 0:8f0bb79ddd48 214 void ce_tlv_encoder_init(uint8_t *buf, uint16_t buf_size, ce_tlv_encoder_s *encoder)
leothedragon 0:8f0bb79ddd48 215 {
leothedragon 0:8f0bb79ddd48 216 memset(buf, 0, buf_size);
leothedragon 0:8f0bb79ddd48 217 memset(encoder, 0, sizeof(*encoder));
leothedragon 0:8f0bb79ddd48 218 encoder->buf = buf;
leothedragon 0:8f0bb79ddd48 219 encoder->encoded_length = 0; // Explicit assignment for readability
leothedragon 0:8f0bb79ddd48 220 encoder->_buf_size = buf_size;
leothedragon 0:8f0bb79ddd48 221 }
leothedragon 0:8f0bb79ddd48 222
leothedragon 0:8f0bb79ddd48 223 #endif // CERT_RENEWAL_TEST