1 /*
2 * Copyright (c) 2021, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8 /** \file cc3xx_internal_asn1_util.c
9 *
10 * This file contains the implementation of the internal functions and
11 * utilities to perform parsing of ASN-1 encoded key buffers
12 *
13 */
14
15 #include "cc3xx_internal_asn1_util.h"
16 #include "psa/crypto.h"
17
18 #define CC3XX_ASN1_CHK_ADD(g, f) \
19 do { \
20 if ((ret = (f)) < 0) \
21 return (ret); \
22 else \
23 (g) += ret; \
24 } while (0)
25
26 /**
27 * \ingroup internal_asn1_util
28 */
cc3xx_asn1_write_len(unsigned char ** p,const unsigned char * start,size_t len)29 int cc3xx_asn1_write_len(unsigned char **p, const unsigned char *start,
30 size_t len)
31 {
32 if (len < 0x80) {
33 if (*p - start < 1) {
34 return (PSA_ERROR_BUFFER_TOO_SMALL);
35 }
36
37 *--(*p) = (unsigned char)len;
38 return (1);
39 }
40
41 if (len <= 0xFF) {
42 if (*p - start < 2) {
43 return (PSA_ERROR_BUFFER_TOO_SMALL);
44 }
45
46 *--(*p) = (unsigned char)len;
47 *--(*p) = 0x81;
48 return (2);
49 }
50
51 if (len <= 0xFFFF) {
52 if (*p - start < 3) {
53 return (PSA_ERROR_BUFFER_TOO_SMALL);
54 }
55
56 *--(*p) = (len)&0xFF;
57 *--(*p) = (len >> 8) & 0xFF;
58 *--(*p) = 0x82;
59 return (3);
60 }
61
62 if (len <= 0xFFFFFF) {
63 if (*p - start < 4) {
64 return (PSA_ERROR_BUFFER_TOO_SMALL);
65 }
66
67 *--(*p) = (len)&0xFF;
68 *--(*p) = (len >> 8) & 0xFF;
69 *--(*p) = (len >> 16) & 0xFF;
70 *--(*p) = 0x83;
71 return (4);
72 }
73
74 return PSA_ERROR_GENERIC_ERROR;
75 }
76
77 /**
78 * \ingroup internal_asn1_util
79 */
cc3xx_asn1_write_tag(unsigned char ** p,const unsigned char * start,unsigned char tag)80 int cc3xx_asn1_write_tag(unsigned char **p, const unsigned char *start,
81 unsigned char tag)
82 {
83 if (*p - start < 1) {
84 return (PSA_ERROR_BUFFER_TOO_SMALL);
85 }
86
87 *--(*p) = tag;
88
89 return (1);
90 }
91
92 /**
93 * \ingroup internal_asn1_util
94 */
cc3xx_asn1_write_big_integer(unsigned char ** p,const unsigned char * start,uint8_t * data,size_t data_size)95 int cc3xx_asn1_write_big_integer(unsigned char **p, const unsigned char *start,
96 uint8_t *data, size_t data_size)
97 {
98 int ret = PSA_ERROR_GENERIC_ERROR;
99 size_t len = data_size;
100
101 if (*p < start || (size_t)(*p - start) < len) {
102 return (PSA_ERROR_BUFFER_TOO_SMALL);
103 }
104
105 (*p) -= len;
106 CC_PalMemCopy(*p, data, data_size);
107
108 /* DER format assumes 2s complement for numbers, so the leftmost bit
109 * should be 0 for positive numbers and 1 for negative numbers.
110 *
111 * FIXME: Check if there is any chance that we will use negative numbers. If
112 * so this should be done (was X->s == 1)
113 */
114 if (**p & 0x80) {
115 if (*p - start < 1) {
116 return (PSA_ERROR_BUFFER_TOO_SMALL);
117 }
118
119 *--(*p) = 0x00;
120 len += 1;
121 }
122
123 CC3XX_ASN1_CHK_ADD(len, cc3xx_asn1_write_len(p, start, len));
124 CC3XX_ASN1_CHK_ADD(len,
125 cc3xx_asn1_write_tag(p, start, CC3XX_TAG_ASN1_INTEGER));
126
127 ret = (int)len;
128
129 return (ret);
130 }
131
asn1_write_tagged_int(unsigned char ** p,unsigned char * start,int val,int tag)132 static int asn1_write_tagged_int(unsigned char **p, unsigned char *start,
133 int val, int tag)
134 {
135 int ret; /* This is used by the CC3XX_ASN1_CHK_ADD macro */
136 size_t len = 0;
137
138 do {
139 if (*p - start < 1) {
140 return (PSA_ERROR_BUFFER_TOO_SMALL);
141 }
142 len += 1;
143 *--(*p) = val & 0xff;
144 val >>= 8;
145 } while (val > 0);
146
147 if (**p & 0x80) {
148 if (*p - start < 1) {
149 return (PSA_ERROR_BUFFER_TOO_SMALL);
150 }
151 *--(*p) = 0x00;
152 len += 1;
153 }
154
155 CC3XX_ASN1_CHK_ADD(len, cc3xx_asn1_write_len(p, start, len));
156 CC3XX_ASN1_CHK_ADD(len, cc3xx_asn1_write_tag(p, start, tag));
157
158 return (len);
159 }
160
asn1_get_tagged_int(unsigned char ** p,const unsigned char * end,int tag,int * val)161 static int asn1_get_tagged_int(unsigned char **p, const unsigned char *end,
162 int tag, int *val)
163 {
164 int ret = PSA_ERROR_CORRUPTION_DETECTED;
165 size_t len;
166
167 if ((ret = cc3xx_asn1_get_tag(p, end, &len, tag)) != 0) {
168 return (ret);
169 }
170
171 /*
172 * len==0 is malformed (0 must be represented as 020100 for INTEGER,
173 * or 0A0100 for ENUMERATED tags
174 */
175 if (len == 0) {
176 return (PSA_ERROR_BUFFER_TOO_SMALL);
177 }
178
179 if ((**p & 0x80) != 0) {
180 return (PSA_ERROR_BUFFER_TOO_SMALL);
181 }
182
183 /* Skip leading zeros. */
184 while (len > 0 && **p == 0) {
185 ++(*p);
186 --len;
187 }
188
189 /* Reject integers that don't fit in an int. This code assumes that
190 * the int type has no padding bit. */
191 if (len > sizeof(int)) {
192 return (PSA_ERROR_BUFFER_TOO_SMALL);
193 }
194 if (len == sizeof(int) && (**p & 0x80) != 0) {
195 return (PSA_ERROR_BUFFER_TOO_SMALL);
196 }
197
198 *val = 0;
199 while (len-- > 0) {
200 *val = (*val << 8) | **p;
201 (*p)++;
202 }
203
204 return (PSA_SUCCESS);
205 }
206
207 /** \defgroup internal_asn1_util Internal ASN-1 parsing functions
208 *
209 * Internal functions used by the driver to parse objets in ASN-1 format
210 *
211 * @{
212 */
cc3xx_asn1_get_tag(unsigned char ** p,const unsigned char * end,size_t * len,int tag)213 psa_status_t cc3xx_asn1_get_tag(unsigned char **p, const unsigned char *end,
214 size_t *len, int tag)
215 {
216 if ((end - *p) < 1) {
217 return (PSA_ERROR_BUFFER_TOO_SMALL);
218 }
219
220 if (**p != tag) {
221 return (PSA_ERROR_GENERIC_ERROR);
222 }
223
224 (*p)++;
225
226 return (cc3xx_asn1_get_len(p, end, len));
227 }
228
cc3xx_asn1_get_len(unsigned char ** p,const unsigned char * end,size_t * len)229 psa_status_t cc3xx_asn1_get_len(unsigned char **p, const unsigned char *end,
230 size_t *len)
231 {
232 if ((end - *p) < 1) {
233 return (PSA_ERROR_BUFFER_TOO_SMALL);
234 }
235
236 if ((**p & 0x80) == 0) {
237 *len = *(*p)++;
238 } else {
239 switch (**p & 0x7F) {
240 case 1:
241 if ((end - *p) < 2) {
242 return (PSA_ERROR_BUFFER_TOO_SMALL);
243 }
244
245 *len = (*p)[1];
246 (*p) += 2;
247 break;
248
249 case 2:
250 if ((end - *p) < 3) {
251 return (PSA_ERROR_BUFFER_TOO_SMALL);
252 }
253
254 *len = ((size_t)(*p)[1] << 8) | (*p)[2];
255 (*p) += 3;
256 break;
257
258 case 3:
259 if ((end - *p) < 4) {
260 return (PSA_ERROR_BUFFER_TOO_SMALL);
261 }
262
263 *len = ((size_t)(*p)[1] << 16) | ((size_t)(*p)[2] << 8) | (*p)[3];
264 (*p) += 4;
265 break;
266
267 case 4:
268 if ((end - *p) < 5) {
269 return (PSA_ERROR_BUFFER_TOO_SMALL);
270 }
271
272 *len = ((size_t)(*p)[1] << 24) | ((size_t)(*p)[2] << 16) |
273 ((size_t)(*p)[3] << 8) | (*p)[4];
274 (*p) += 5;
275 break;
276
277 default:
278 return (PSA_ERROR_BUFFER_TOO_SMALL);
279 }
280 }
281
282 if (*len > (size_t)(end - *p)) {
283 return (PSA_ERROR_BUFFER_TOO_SMALL);
284 }
285
286 return (PSA_SUCCESS);
287 }
288
cc3xx_asn1_get_int(unsigned char ** p,const unsigned char * end,int * val)289 psa_status_t cc3xx_asn1_get_int(unsigned char **p, const unsigned char *end,
290 int *val)
291 {
292 return (asn1_get_tagged_int(p, end, CC3XX_TAG_ASN1_INTEGER, val));
293 }
294
cc3xx_asn1_write_int(unsigned char ** p,unsigned char * start,int val)295 int cc3xx_asn1_write_int(unsigned char **p, unsigned char *start, int val)
296 {
297 return (asn1_write_tagged_int(p, start, val, CC3XX_TAG_ASN1_INTEGER));
298 }
299 /** @} */ // end of internal_asn1_util
300