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