5 #include "sw/device/silicon_creator/lib/cert/asn1.h"
14 #define RETURN_IF_ASN1_ERROR(state) \
16 if ((state)->error != kErrorOk) { \
26 #define RAISE_ASN1_ERROR(state, error_code) \
28 (state)->error = (error_code); \
32 void asn1_clear_error(
asn1_state_t *state) { state->error = kErrorOk; }
34 rom_error_t asn1_start(
asn1_state_t *new_state, uint8_t *buffer,
size_t size) {
36 if (new_state == NULL || buffer == NULL || size > PTRDIFF_MAX) {
37 return kErrorAsn1StartInvalidArgument;
39 new_state->buffer = buffer;
40 new_state->size = size;
41 new_state->offset = 0;
42 asn1_clear_error(new_state);
46 rom_error_t asn1_finish(
asn1_state_t *state,
size_t *out_size) {
47 rom_error_t result = state->error;
48 *out_size = state->offset;
52 asn1_clear_error(state);
57 asn1_push_bytes(state, &
byte, 1);
60 void asn1_push_bytes(
asn1_state_t *state,
const uint8_t *bytes,
size_t size) {
61 RETURN_IF_ASN1_ERROR(state);
64 if (size > PTRDIFF_MAX || state->offset > PTRDIFF_MAX) {
65 RAISE_ASN1_ERROR(state, kErrorAsn1PushBytesInvalidArgument);
67 if (state->offset + size > state->size) {
68 RAISE_ASN1_ERROR(state, kErrorAsn1BufferExhausted);
70 memcpy(state->buffer + state->offset, bytes, size);
71 state->offset += size;
75 new_tag->state = NULL;
76 RETURN_IF_ASN1_ERROR(state);
78 new_tag->state = state;
79 asn1_push_byte(state,
id);
80 RETURN_IF_ASN1_ERROR(state);
81 new_tag->len_offset = state->offset;
86 asn1_push_byte(state, 0);
87 RETURN_IF_ASN1_ERROR(state);
88 new_tag->len_size = 1;
92 if (tag->state == NULL)
94 RETURN_IF_ASN1_ERROR(tag->state);
96 if (tag->len_size != 1) {
97 RAISE_ASN1_ERROR(tag->state, kErrorAsn1Internal);
100 size_t length = tag->state->offset - tag->len_offset - tag->len_size;
102 size_t final_len_size;
103 if (length <= 0x7f) {
106 }
else if (length <= 0xff) {
110 }
else if (length <= 0xffff) {
116 RAISE_ASN1_ERROR(tag->state, kErrorAsn1Internal);
120 if (tag->len_size != final_len_size) {
122 size_t new_buffer_size =
123 tag->state->offset + final_len_size - tag->len_size;
124 if (new_buffer_size > tag->state->size) {
125 RAISE_ASN1_ERROR(tag->state, kErrorAsn1BufferExhausted);
128 for (
size_t i = 0; i < length; i++) {
129 tag->state->buffer[tag->len_offset + final_len_size + length - 1 - i] =
130 tag->state->buffer[tag->len_offset + tag->len_size + length - 1 - i];
134 if (length <= 0x7f) {
135 tag->state->buffer[tag->len_offset] = (uint8_t)length;
136 }
else if (length <= 0xff) {
137 tag->state->buffer[tag->len_offset + 0] = 0x81;
138 tag->state->buffer[tag->len_offset + 1] = (uint8_t)length;
139 }
else if (length <= 0xffff) {
140 tag->state->buffer[tag->len_offset + 0] = 0x82;
141 tag->state->buffer[tag->len_offset + 1] = (uint8_t)(length >> 8);
142 tag->state->buffer[tag->len_offset + 2] = (uint8_t)(length & 0xff);
145 RAISE_ASN1_ERROR(tag->state, kErrorAsn1Internal);
148 tag->state->offset += final_len_size - tag->len_size;
155 void asn1_push_bool(
asn1_state_t *state, uint8_t tag,
bool value) {
157 asn1_start_tag(state, &tag_st, tag);
158 asn1_push_byte(state, value ? 0xff : 0);
159 asn1_finish_tag(&tag_st);
162 void asn1_push_int32(
asn1_state_t *state, uint8_t tag, int32_t value) {
163 uint32_t u_value = (uint32_t)value;
164 uint8_t bigint[4] = {
166 (u_value >> 16) & 0xff,
167 (u_value >> 8) & 0xff,
170 asn1_push_integer(state, tag,
true, bigint,
sizeof(bigint));
173 void asn1_push_uint32(
asn1_state_t *state, uint8_t tag, uint32_t value) {
174 uint8_t bigint[4] = {
176 (value >> 16) & 0xff,
180 asn1_push_integer(state, tag,
false, bigint,
sizeof(bigint));
183 void asn1_push_integer(
asn1_state_t *state, uint8_t tag,
bool is_signed,
184 const uint8_t *bytes_be,
size_t size) {
185 RETURN_IF_ASN1_ERROR(state);
186 if (size == 0 || (bytes_be == NULL && size > 0)) {
187 RAISE_ASN1_ERROR(state, kErrorAsn1PushIntegerInvalidArgument);
190 asn1_start_tag(state, &tag_st, tag);
195 while (size >= 2 && bytes_be[0] == 0 && (bytes_be[1] >> 7) == 0) {
203 while (size >= 2 && bytes_be[0] == 0xff && (bytes_be[1] >> 7) == 1) {
209 if ((bytes_be[0] >> 7) == 1) {
210 asn1_push_byte(state, 0);
213 asn1_push_bytes(state, bytes_be, size);
214 asn1_finish_tag(&tag_st);
217 void asn1_push_integer_pad(
asn1_state_t *state,
bool is_signed,
218 const uint8_t *bytes_be,
size_t size,
219 size_t padded_size) {
220 RETURN_IF_ASN1_ERROR(state);
221 if (size == 0 || size > padded_size) {
222 RAISE_ASN1_ERROR(state, kErrorAsn1PushIntegerPadInvalidArgument);
226 if (is_signed && (bytes_be[0] >> 7) == 1) {
230 while (padded_size-- > size) {
231 asn1_push_byte(state, padding);
233 asn1_push_bytes(state, bytes_be, size);
236 void asn1_push_oid_raw(
asn1_state_t *state,
const uint8_t *bytes,
size_t size) {
238 asn1_start_tag(state, &tag, kAsn1TagNumberOid);
239 asn1_push_bytes(state, bytes, size);
240 asn1_finish_tag(&tag);
243 void asn1_push_string(
asn1_state_t *state, uint8_t
id,
const char *str,
246 asn1_start_tag(state, &tag,
id);
247 while (max_len > 0 && str[0] != 0) {
248 asn1_push_byte(state, (uint8_t)str[0]);
252 asn1_finish_tag(&tag);
255 static const char kLowercaseHexChars[16] = {
'0',
'1',
'2',
'3',
'4',
'5',
256 '6',
'7',
'8',
'9',
'a',
'b',
259 void asn1_push_hexstring(
asn1_state_t *state, uint8_t
id,
const uint8_t *bytes,
262 asn1_start_tag(state, &tag,
id);
264 asn1_push_byte(state, (uint8_t)kLowercaseHexChars[bytes[0] >> 4]);
265 asn1_push_byte(state, (uint8_t)kLowercaseHexChars[bytes[0] & 0xf]);
269 asn1_finish_tag(&tag);
274 out_bitstring->state = NULL;
275 RETURN_IF_ASN1_ERROR(state);
276 out_bitstring->state = state;
277 out_bitstring->unused_bits_offset = state->offset;
278 out_bitstring->used_bits = 0;
279 out_bitstring->current_byte = 0;
282 asn1_push_byte(state, 0);
286 if (bitstring->state == NULL)
288 RETURN_IF_ASN1_ERROR(bitstring->state);
291 bitstring->current_byte |= 1 << (7 - bitstring->used_bits);
294 bitstring->used_bits++;
295 if (bitstring->used_bits == 8) {
296 asn1_push_byte(bitstring->state, bitstring->current_byte);
297 bitstring->current_byte = 0;
298 bitstring->used_bits = 0;
303 if (bitstring->state == NULL)
305 RETURN_IF_ASN1_ERROR(bitstring->state);
306 if (bitstring->used_bits >= 8) {
308 bitstring->state = NULL;
309 RAISE_ASN1_ERROR(state, kErrorAsn1FinishBitstringInvalidArgument);
315 if (bitstring->used_bits != 0) {
316 asn1_push_byte(bitstring->state, bitstring->current_byte);
318 bitstring->state->buffer[bitstring->unused_bits_offset] =
319 8 - (uint8_t)bitstring->used_bits;
322 bitstring->state = NULL;