1 #include "cert.h"
2 #include <stdio.h>
3
cert_field_get(const uint8_t * data,uint32_t length,uint16_t * field_type,const uint8_t ** contents,uint32_t * field_size)4 int cert_field_get(const uint8_t *data, uint32_t length, uint16_t *field_type, const uint8_t **contents, uint32_t *field_size) {
5 uint16_t field_id;
6 uint32_t field_len;
7 uint32_t additional_len;
8
9 /* sanity checks. */
10 if (data == NULL) {
11 return 1;
12 }
13 if (field_type == NULL && contents == NULL && field_size == NULL) {
14 return 1;
15 }
16 if (length < 2) {
17 return 1;
18 }
19
20 /* retrieve field id and number of additional bytes we need to read for the field's size */
21 field_id = (((uint16_t)data[0]) << 8) | data[1];
22 if (field_id == 0xFFFF) {
23 return 1;
24 }
25
26 switch (field_id & 0xF) {
27 case 0xD: additional_len = 1; break;
28 case 0xE: additional_len = 2; break;
29 case 0xF: additional_len = 4; break;
30 default: additional_len = 0; break;
31 }
32
33 if (length < 2 + additional_len) {
34 return 1;
35 }
36
37 /* retrieve data size of field. */
38 switch (field_id & 0xF) {
39 case 0xD:
40 field_len = (uint32_t)data[2];
41 break;
42
43 case 0xE:
44 field_len = (((uint32_t)data[2]) << 8) | data[3];
45 break;
46
47 case 0xF:
48 field_len = (((uint32_t)data[2]) << 24) | (((uint32_t)data[3]) << 16) | (((uint32_t)data[4]) << 8) | data[5];
49 break;
50
51 default:
52 field_len = field_id & 0xF;
53 break;
54 }
55
56 if (length < 2 + additional_len + field_len) {
57 return 1;
58 }
59
60 if (field_type != NULL) {
61 /* don't mask out the size indication, it may be useful to the user. */
62 *field_type = field_id;
63 }
64 if (contents != NULL) {
65 *contents = data + 2 + additional_len;
66 }
67 if (field_size != NULL) {
68 *field_size = field_len;
69 }
70
71 return 0;
72 }
73
cert_field_next(const uint8_t ** data,uint32_t * length)74 int cert_field_next(const uint8_t **data, uint32_t *length) {
75 int ret;
76 const uint8_t * contents;
77 uint32_t field_size;
78
79 /* sanity checks. */
80 if (data == NULL) {
81 return 1;
82 }
83 if (length == NULL) {
84 return 1;
85 }
86
87 ret = cert_field_get(*data, *length, NULL, &contents, &field_size);
88 if (!ret) {
89 *length -= contents + field_size - *data;
90 *data = contents + field_size;
91 }
92
93 return ret;
94 }
95
cert_field_find(const uint8_t * data,uint32_t length,uint16_t field_type,const uint8_t ** contents,uint32_t * field_size)96 int cert_field_find(const uint8_t *data, uint32_t length, uint16_t field_type, const uint8_t **contents, uint32_t *field_size) {
97 int ret = 0;
98 uint16_t ft;
99
100 /* sanity checks. */
101 if (data == NULL) {
102 return 1;
103 }
104 if (length < 2) {
105 return 1;
106 }
107
108 /* mask out the size indication, it is harmful for finding a field */
109 field_type &= 0xFFF0;
110 ft = 0xFFFF;
111
112 while (!ret && ft != field_type) {
113 ret = cert_field_get(data, length, &ft, contents, field_size);
114 ft &= 0xFFF0;
115 if (!ret) {
116 ret = cert_field_next(&data, &length);
117 }
118 }
119
120 return ret;
121 }
122
cert_field_find_path(const uint8_t * data,uint32_t length,const uint16_t * field_path,uint16_t field_path_len,const uint8_t ** contents,uint32_t * field_size)123 int cert_field_find_path(const uint8_t *data, uint32_t length, const uint16_t *field_path, uint16_t field_path_len, const uint8_t **contents, uint32_t *field_size) {
124 int ret = 0;
125
126 /* sanity checks. */
127 if (data == NULL) {
128 return 1;
129 }
130 if (field_path == NULL) {
131 return 1;
132 }
133 if (length < 2) {
134 return 1;
135 }
136 if (field_path_len == 0) {
137 return 1;
138 }
139
140 while (field_path_len != 0 && !ret) {
141 ret = cert_field_find(data, length, *field_path, &data, &length);
142 field_path++;
143 field_path_len--;
144 if (contents != NULL) {
145 *contents = data;
146 }
147 if (field_size != NULL) {
148 *field_size = length;
149 }
150 }
151
152 return ret;
153 }
154