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.
ce_tlv.c
00001 // ---------------------------------------------------------------------------- 00002 // Copyright 2018 ARM Ltd. 00003 // 00004 // Licensed under the Apache License, Version 2.0 (the "License"); 00005 // you may not use this file except in compliance with the License. 00006 // You may obtain a copy of the License at 00007 // 00008 // http://www.apache.org/licenses/LICENSE-2.0 00009 // 00010 // Unless required by applicable law or agreed to in writing, software 00011 // distributed under the License is distributed on an "AS IS" BASIS, 00012 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 // See the License for the specific language governing permissions and 00014 // limitations under the License. 00015 // ---------------------------------------------------------------------------- 00016 00017 00018 #include <stdbool.h> 00019 #include <stdint.h> 00020 #include <string.h> 00021 #include <stdio.h> 00022 00023 #include "ce_tlv.h" 00024 #include "pv_log.h" 00025 #include "pal_macros.h" 00026 #include "pv_error_handling.h" 00027 00028 #define TYPE_LENGTH_IN_BYTES 2 00029 #define LEN_LENGTH_IN_BYTES 2 00030 00031 // Get the number of bit in a specific variable 00032 #define CE_BITS(var) (sizeof(var) * 8) 00033 // Get the MSB bit number 00034 #define CE_MSB(var) (CE_BITS(var) - 1) 00035 00036 00037 static bool is_element_in_range(const ce_tlv_element_s *element, uint16_t num_of_bytes_to_take) 00038 { 00039 if (element->_end < element->_current) { 00040 return false; 00041 } 00042 if ((element->_end - element->_current) >= num_of_bytes_to_take) { 00043 return true; 00044 } 00045 return false; 00046 } 00047 00048 static ce_tlv_status_e take_16bit_number(ce_tlv_element_s *element, uint16_t *number_out) 00049 { 00050 if (!is_element_in_range(element, sizeof(*number_out))) { 00051 return CE_TLV_STATUS_MALFORMED_TLV; 00052 } 00053 00054 memcpy(number_out, element->_current, sizeof(*number_out)); 00055 00056 // Convert from network endianity (big endian) to host endianity in a portable manner 00057 *number_out = (uint16_t)PAL_NTOHS(*number_out); 00058 element->_current += sizeof(*number_out); 00059 return CE_TLV_STATUS_SUCCESS; 00060 } 00061 00062 static ce_tlv_status_e take_bytes(ce_tlv_element_s *element) 00063 { 00064 if (!is_element_in_range(element, element->len)) { 00065 return CE_TLV_STATUS_MALFORMED_TLV; 00066 } 00067 00068 element->val.bytes = element->_current; 00069 element->_current += element->len; 00070 return CE_TLV_STATUS_SUCCESS; 00071 } 00072 00073 bool is_required(const ce_tlv_element_s *element) 00074 { 00075 return element->is_required; 00076 } 00077 00078 static ce_tlv_status_e take_type(ce_tlv_element_s *element) 00079 { 00080 ce_tlv_status_e status = take_16bit_number(element, &element->type); 00081 SA_PV_ERR_RECOVERABLE_RETURN_IF((status != CE_TLV_STATUS_SUCCESS), status, "failed in take_16bit_number()"); 00082 00083 // keep order, test "is required" and then clear the type MSB 00084 element->is_required = (((element->type >> CE_MSB(element->type)) & 1) == 1) ? false : true; 00085 element->type &= (uint16_t)(~(1 << CE_MSB(element->type))); // clear the MSB bit 00086 return CE_TLV_STATUS_SUCCESS; 00087 } 00088 00089 static ce_tlv_status_e take_length(ce_tlv_element_s *element) 00090 { 00091 return take_16bit_number(element, &element->len); 00092 } 00093 00094 // Element where element->len is the length of the string 00095 static ce_tlv_status_e take_string(ce_tlv_element_s *element) 00096 { 00097 // Take the bytes 00098 ce_tlv_status_e status = take_bytes(element); 00099 SA_PV_ERR_RECOVERABLE_RETURN_IF((status != CE_TLV_STATUS_SUCCESS), status, "failed in take_bytes()"); 00100 00101 // Assert null terminator at the end 00102 if (element->val.bytes[element->len - 1] != '\0') { 00103 return CE_TLV_STATUS_TEXT_NOT_TERMINATED; 00104 } 00105 00106 return CE_TLV_STATUS_SUCCESS; 00107 } 00108 00109 static ce_tlv_status_e take_value(ce_tlv_element_s *element) 00110 { 00111 switch (element->type) { 00112 case CE_TLV_TYPE_CERT_NAME: 00113 return take_string(element); 00114 default: 00115 // Skip next 00116 element->_current += element->len; 00117 break; 00118 } 00119 00120 return CE_TLV_STATUS_SUCCESS; 00121 } 00122 00123 00124 ce_tlv_status_e ce_tlv_parser_init(const uint8_t *tlv_buf, size_t tlv_buf_len, ce_tlv_element_s *element_out) 00125 { 00126 // Null check 00127 SA_PV_ERR_RECOVERABLE_RETURN_IF((tlv_buf == NULL), CE_TLV_STATUS_INVALID_ARG, "Invalid tlv_buf"); 00128 SA_PV_ERR_RECOVERABLE_RETURN_IF((element_out == NULL), CE_TLV_STATUS_INVALID_ARG, "Invalid element_out"); 00129 SA_PV_ERR_RECOVERABLE_RETURN_IF((tlv_buf_len == 0), CE_TLV_STATUS_INVALID_ARG, "empty tlv_buf_len"); 00130 00131 memset(element_out, 0, sizeof(ce_tlv_element_s)); 00132 00133 element_out->_current = tlv_buf; 00134 element_out->_end = (tlv_buf + tlv_buf_len); 00135 00136 return CE_TLV_STATUS_SUCCESS; 00137 } 00138 00139 ce_tlv_status_e ce_tlv_parse_next(ce_tlv_element_s *element) 00140 { 00141 ce_tlv_status_e status = CE_TLV_STATUS_SUCCESS; 00142 00143 SA_PV_ERR_RECOVERABLE_RETURN_IF((element == NULL), CE_TLV_STATUS_INVALID_ARG, "Invalid element"); 00144 00145 // Check if we are at the end of the buffer 00146 if (element->_current == element->_end) { 00147 return CE_TLV_STATUS_END; 00148 } 00149 00150 // If this is true then there is a bug in the code 00151 // TBD: check if we need to remove this assert 00152 assert(element->_current < element->_end); 00153 00154 // Parse type 00155 status = take_type(element); 00156 SA_PV_ERR_RECOVERABLE_RETURN_IF((status != CE_TLV_STATUS_SUCCESS), status, "failed in take_bytes()"); 00157 00158 // Parse length 00159 status = take_length(element); 00160 SA_PV_ERR_RECOVERABLE_RETURN_IF((status != CE_TLV_STATUS_SUCCESS), status, "failed in take_length()"); 00161 00162 // Parse value 00163 status = take_value(element); 00164 SA_PV_ERR_RECOVERABLE_RETURN_IF((status != CE_TLV_STATUS_SUCCESS), status, "failed in take_value()"); 00165 00166 return CE_TLV_STATUS_SUCCESS; 00167 } 00168 00169 #ifdef CERT_RENEWAL_TEST 00170 static void _append_16bit_number(uint16_t number, ce_tlv_encoder_s *encoder) 00171 { 00172 uint16_t num_buf = (uint16_t)PAL_HTONS(number); 00173 00174 memcpy(encoder->buf + (uint8_t)encoder->encoded_length, &num_buf, sizeof(num_buf)); 00175 encoder->encoded_length = (uint16_t)(encoder->encoded_length +sizeof(num_buf)); 00176 } 00177 00178 static void _append_value_string(const char *str, uint16_t str_length, ce_tlv_encoder_s *encoder) 00179 { 00180 // str_length should contain the '\0' 00181 memcpy(encoder->buf + encoder->encoded_length, str, str_length); 00182 // FIXME: Cast is needed here, need to check why getting compilation warning in Native GCC (Linux) 00183 encoder->encoded_length = (uint16_t)(str_length + encoder->encoded_length); 00184 } 00185 00186 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) 00187 { 00188 uint16_t _type = type; 00189 00190 // If out of range - update the length - and return CE_TLV_STATUS_ENCODER_INSUFFICIENT_BUFFER 00191 // Next encoding will do the same and any time we may know how big the buffer must be: encoder->encoded_length 00192 if (encoder->encoded_length + TYPE_LENGTH_IN_BYTES + LEN_LENGTH_IN_BYTES + length > encoder->_buf_size) { 00193 encoder->encoded_length = (uint16_t)(encoder->encoded_length + (TYPE_LENGTH_IN_BYTES + LEN_LENGTH_IN_BYTES + length)); 00194 return CE_TLV_STATUS_ENCODER_INSUFFICIENT_BUFFER; 00195 } 00196 00197 // Append type 00198 00199 if (!is_tlv_required) { 00200 // set MSB only if optional 00201 _type |= 1 << CE_MSB(_type); 00202 } 00203 _append_16bit_number(_type, encoder); 00204 00205 // Append length 00206 _append_16bit_number(length, encoder); 00207 00208 // Append value 00209 _append_value_string(value, length, encoder); 00210 00211 return CE_TLV_STATUS_SUCCESS; 00212 } 00213 00214 void ce_tlv_encoder_init(uint8_t *buf, uint16_t buf_size, ce_tlv_encoder_s *encoder) 00215 { 00216 memset(buf, 0, buf_size); 00217 memset(encoder, 0, sizeof(*encoder)); 00218 encoder->buf = buf; 00219 encoder->encoded_length = 0; // Explicit assignment for readability 00220 encoder->_buf_size = buf_size; 00221 } 00222 00223 #endif // CERT_RENEWAL_TEST
Generated on Mon Aug 29 2022 19:53:38 by
