blob: e2a2b9ffb7859928a90d7f377eb4c590614f5b05 [file] [log] [blame]
Gilles Peskine27d806f2019-03-01 18:02:53 +01001/* BEGIN_HEADER */
2#include <errno.h>
3#include <stdlib.h>
4#include <limits.h>
5
6#include "mbedtls/bignum.h"
7#include "mbedtls/asn1.h"
8#if defined(MBEDTLS_ASN1_WRITE_C)
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02009# include "mbedtls/asn1write.h"
Gilles Peskine27d806f2019-03-01 18:02:53 +010010#endif
11
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020012/* Used internally to report an error that indicates a bug in a parsing
13 * function. */
Gilles Peskine27d806f2019-03-01 18:02:53 +010014#define ERR_PARSE_INCONSISTENCY INT_MAX
15
Gilles Peskine95c893d2020-01-21 21:26:36 +010016/* Use this magic value in some tests to indicate that the expected result
17 * should not be checked. */
18#define UNPREDICTABLE_RESULT 0x5552
19
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020020static int nested_parse(unsigned char **const p, const unsigned char *const end)
Gilles Peskine27d806f2019-03-01 18:02:53 +010021{
22 int ret;
23 size_t len = 0;
24 size_t len2 = 0;
25 unsigned char *const start = *p;
26 unsigned char *content_start;
27 unsigned char tag;
28
29 /* First get the length, skipping over the tag. */
30 content_start = start + 1;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020031 ret = mbedtls_asn1_get_len(&content_start, end, &len);
32 TEST_ASSERT(content_start <= end);
33 if (ret != 0)
34 return ret;
Gilles Peskine27d806f2019-03-01 18:02:53 +010035
36 /* Since we have a valid element start (tag and length), retrieve and
37 * check the tag. */
38 tag = start[0];
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020039 TEST_EQUAL(mbedtls_asn1_get_tag(p, end, &len2, tag ^ 1),
40 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
Gilles Peskine27d806f2019-03-01 18:02:53 +010041 *p = start;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020042 TEST_EQUAL(mbedtls_asn1_get_tag(p, end, &len2, tag), 0);
43 TEST_EQUAL(len, len2);
44 TEST_ASSERT(*p == content_start);
Gilles Peskine27d806f2019-03-01 18:02:53 +010045 *p = content_start;
46
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020047 switch (tag & 0x1f) {
Gilles Peskine27d806f2019-03-01 18:02:53 +010048 case MBEDTLS_ASN1_BOOLEAN:
Gilles Peskine27d806f2019-03-01 18:02:53 +010049 {
50 int val = -257;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020051 *p = start;
52 ret = mbedtls_asn1_get_bool(p, end, &val);
53 if (ret == 0)
54 TEST_ASSERT(val == 0 || val == 1);
55 break;
Gilles Peskine27d806f2019-03-01 18:02:53 +010056 }
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020057
58 case MBEDTLS_ASN1_INTEGER:
59 {
60#if defined(MBEDTLS_BIGNUM_C)
61 mbedtls_mpi mpi;
62 mbedtls_mpi_init(&mpi);
63 *p = start;
64 ret = mbedtls_asn1_get_mpi(p, end, &mpi);
65 mbedtls_mpi_free(&mpi);
66#else
67 *p = start + 1;
68 ret = mbedtls_asn1_get_len(p, end, &len);
69 *p += len;
70#endif
71 /* If we're sure that the number fits in an int, also
72 * call mbedtls_asn1_get_int(). */
73 if (ret == 0 && len < sizeof(int)) {
74 int val = -257;
75 unsigned char *q = start;
76 ret = mbedtls_asn1_get_int(&q, end, &val);
77 TEST_ASSERT(*p == q);
78 }
79 break;
80 }
Gilles Peskine27d806f2019-03-01 18:02:53 +010081
82 case MBEDTLS_ASN1_BIT_STRING:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020083 {
84 mbedtls_asn1_bitstring bs;
85 *p = start;
86 ret = mbedtls_asn1_get_bitstring(p, end, &bs);
87 break;
88 }
Gilles Peskine27d806f2019-03-01 18:02:53 +010089
90 case MBEDTLS_ASN1_SEQUENCE:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020091 {
92 while (*p <= end && *p < content_start + len && ret == 0)
93 ret = nested_parse(p, content_start + len);
94 break;
95 }
Gilles Peskine27d806f2019-03-01 18:02:53 +010096
97 case MBEDTLS_ASN1_OCTET_STRING:
98 case MBEDTLS_ASN1_NULL:
99 case MBEDTLS_ASN1_OID:
100 case MBEDTLS_ASN1_UTF8_STRING:
101 case MBEDTLS_ASN1_SET:
102 case MBEDTLS_ASN1_PRINTABLE_STRING:
103 case MBEDTLS_ASN1_T61_STRING:
104 case MBEDTLS_ASN1_IA5_STRING:
105 case MBEDTLS_ASN1_UTC_TIME:
106 case MBEDTLS_ASN1_GENERALIZED_TIME:
107 case MBEDTLS_ASN1_UNIVERSAL_STRING:
108 case MBEDTLS_ASN1_BMP_STRING:
109 default:
110 /* No further testing implemented for this tag. */
111 *p += len;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200112 return 0;
Gilles Peskine27d806f2019-03-01 18:02:53 +0100113 }
114
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200115 TEST_ASSERT(*p <= end);
116 return ret;
Gilles Peskine27d806f2019-03-01 18:02:53 +0100117
118exit:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200119 return ERR_PARSE_INCONSISTENCY;
Gilles Peskine27d806f2019-03-01 18:02:53 +0100120}
121
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200122int get_len_step(const data_t *input, size_t buffer_size, size_t actual_length)
Gilles Peskine27d806f2019-03-01 18:02:53 +0100123{
124 unsigned char *buf = NULL;
125 unsigned char *p = NULL;
Gilles Peskine42a1acf2020-01-21 16:12:07 +0100126 unsigned char *end;
Gilles Peskine27d806f2019-03-01 18:02:53 +0100127 size_t parsed_length;
128 int ret;
129
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200130 mbedtls_test_set_step(buffer_size);
Gilles Peskine27d806f2019-03-01 18:02:53 +0100131 /* Allocate a new buffer of exactly the length to parse each time.
132 * This gives memory sanitizers a chance to catch buffer overreads. */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200133 if (buffer_size == 0) {
134 ASSERT_ALLOC(buf, 1);
Gilles Peskine42a1acf2020-01-21 16:12:07 +0100135 end = buf + 1;
136 p = end;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200137 } else {
138 ASSERT_ALLOC_WEAK(buf, buffer_size);
139 if (buffer_size > input->len) {
140 memcpy(buf, input->x, input->len);
141 memset(buf + input->len, 'A', buffer_size - input->len);
142 } else {
143 memcpy(buf, input->x, buffer_size);
Gilles Peskine27d806f2019-03-01 18:02:53 +0100144 }
145 p = buf;
Gilles Peskine42a1acf2020-01-21 16:12:07 +0100146 end = buf + buffer_size;
Gilles Peskine27d806f2019-03-01 18:02:53 +0100147 }
148
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200149 ret = mbedtls_asn1_get_len(&p, end, &parsed_length);
Gilles Peskine27d806f2019-03-01 18:02:53 +0100150
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200151 if (buffer_size >= input->len + actual_length) {
152 TEST_EQUAL(ret, 0);
153 TEST_ASSERT(p == buf + input->len);
154 TEST_EQUAL(parsed_length, actual_length);
155 } else {
156 TEST_EQUAL(ret, MBEDTLS_ERR_ASN1_OUT_OF_DATA);
Gilles Peskine27d806f2019-03-01 18:02:53 +0100157 }
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200158 mbedtls_free(buf);
159 return 1;
Gilles Peskine27d806f2019-03-01 18:02:53 +0100160
161exit:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200162 mbedtls_free(buf);
163 return 0;
Gilles Peskine27d806f2019-03-01 18:02:53 +0100164}
165
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200166typedef struct {
Hanno Becker199b7092019-09-11 14:21:26 +0100167 const unsigned char *input_start;
168 const char *description;
169} traverse_state_t;
170
171/* Value returned by traverse_callback if description runs out. */
172#define RET_TRAVERSE_STOP 1
173/* Value returned by traverse_callback if description has an invalid format
174 * (see traverse_sequence_of). */
175#define RET_TRAVERSE_ERROR 2
176
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200177static int
178traverse_callback(void *ctx, int tag, unsigned char *content, size_t len)
Hanno Becker199b7092019-09-11 14:21:26 +0100179{
180 traverse_state_t *state = ctx;
181 size_t offset;
182 const char *rest = state->description;
183 unsigned long n;
184
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200185 TEST_ASSERT(content > state->input_start);
Hanno Becker199b7092019-09-11 14:21:26 +0100186 offset = content - state->input_start;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200187 mbedtls_test_set_step(offset);
Hanno Becker199b7092019-09-11 14:21:26 +0100188
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200189 if (*rest == 0)
190 return RET_TRAVERSE_STOP;
191 n = strtoul(rest, (char **)&rest, 0);
192 TEST_EQUAL(n, offset);
193 TEST_EQUAL(*rest, ',');
Hanno Becker199b7092019-09-11 14:21:26 +0100194 ++rest;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200195 n = strtoul(rest, (char **)&rest, 0);
196 TEST_EQUAL(n, (unsigned)tag);
197 TEST_EQUAL(*rest, ',');
Hanno Becker199b7092019-09-11 14:21:26 +0100198 ++rest;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200199 n = strtoul(rest, (char **)&rest, 0);
200 TEST_EQUAL(n, len);
201 if (*rest == ',')
Hanno Becker199b7092019-09-11 14:21:26 +0100202 ++rest;
203
204 state->description = rest;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200205 return 0;
Hanno Becker199b7092019-09-11 14:21:26 +0100206
207exit:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200208 return RET_TRAVERSE_ERROR;
Hanno Becker199b7092019-09-11 14:21:26 +0100209}
210
Gilles Peskine27d806f2019-03-01 18:02:53 +0100211/* END_HEADER */
212
213/* BEGIN_DEPENDENCIES
214 * depends_on:MBEDTLS_ASN1_PARSE_C
215 * END_DEPENDENCIES
216 */
217
218/* BEGIN_CASE */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200219void parse_prefixes(const data_t *input, int full_result, int overfull_result)
Gilles Peskine27d806f2019-03-01 18:02:53 +0100220{
Gilles Peskine95c893d2020-01-21 21:26:36 +0100221 /* full_result: expected result from parsing the given string. */
222 /* overfull_result: expected_result from parsing the given string plus
223 * some trailing garbage. This may be UNPREDICTABLE_RESULT to accept
224 * any result: use this for invalid inputs that may or may not become
225 * valid depending on what the trailing garbage is. */
226
Gilles Peskine27d806f2019-03-01 18:02:53 +0100227 unsigned char *buf = NULL;
228 unsigned char *p = NULL;
229 size_t buffer_size;
230 int ret;
231
Gilles Peskineef418382020-01-21 18:56:27 +0100232 /* Test every prefix of the input, except the empty string.
233 * The first byte of the string is the tag. Without a tag byte,
234 * we wouldn't know what to parse the input as.
Gilles Peskine95c893d2020-01-21 21:26:36 +0100235 * Also test the input followed by an extra byte.
Gilles Peskineef418382020-01-21 18:56:27 +0100236 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200237 for (buffer_size = 1; buffer_size <= input->len + 1; buffer_size++) {
238 mbedtls_test_set_step(buffer_size);
Gilles Peskine27d806f2019-03-01 18:02:53 +0100239 /* Allocate a new buffer of exactly the length to parse each time.
240 * This gives memory sanitizers a chance to catch buffer overreads. */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200241 ASSERT_ALLOC(buf, buffer_size);
242 memcpy(buf, input->x, buffer_size);
Gilles Peskine27d806f2019-03-01 18:02:53 +0100243 p = buf;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200244 ret = nested_parse(&p, buf + buffer_size);
Gilles Peskine95c893d2020-01-21 21:26:36 +0100245
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200246 if (ret == ERR_PARSE_INCONSISTENCY)
Gilles Peskine27d806f2019-03-01 18:02:53 +0100247 goto exit;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200248 if (buffer_size < input->len) {
249 TEST_EQUAL(ret, MBEDTLS_ERR_ASN1_OUT_OF_DATA);
250 } else if (buffer_size == input->len) {
251 TEST_EQUAL(ret, full_result);
252 } else /* ( buffer_size > input->len ) */
Gilles Peskine27d806f2019-03-01 18:02:53 +0100253 {
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200254 if (overfull_result != UNPREDICTABLE_RESULT)
255 TEST_EQUAL(ret, overfull_result);
Gilles Peskine27d806f2019-03-01 18:02:53 +0100256 }
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200257 if (ret == 0)
258 TEST_ASSERT(p == buf + input->len);
Gilles Peskine95c893d2020-01-21 21:26:36 +0100259
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200260 mbedtls_free(buf);
Gilles Peskine27d806f2019-03-01 18:02:53 +0100261 buf = NULL;
262 }
263
264exit:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200265 mbedtls_free(buf);
Gilles Peskine27d806f2019-03-01 18:02:53 +0100266}
267/* END_CASE */
268
269/* BEGIN_CASE */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200270void get_len(const data_t *input, int actual_length_arg)
Gilles Peskine27d806f2019-03-01 18:02:53 +0100271{
272 size_t actual_length = actual_length_arg;
273 size_t buffer_size;
274
Gilles Peskineef418382020-01-21 18:56:27 +0100275 /* Test prefixes of a buffer containing the given length string
276 * followed by `actual_length` bytes of payload. To save a bit of
277 * time, we skip some "boring" prefixes: we don't test prefixes where
278 * the payload is truncated more than one byte away from either end,
279 * and we only test the empty string on a 1-byte input.
280 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200281 for (buffer_size = 1; buffer_size <= input->len + 1; buffer_size++) {
282 if (!get_len_step(input, buffer_size, actual_length))
Gilles Peskine27d806f2019-03-01 18:02:53 +0100283 goto exit;
284 }
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200285 if (!get_len_step(input, input->len + actual_length - 1, actual_length))
Gilles Peskine27d806f2019-03-01 18:02:53 +0100286 goto exit;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200287 if (!get_len_step(input, input->len + actual_length, actual_length))
Gilles Peskine27d806f2019-03-01 18:02:53 +0100288 goto exit;
289}
290/* END_CASE */
291
292/* BEGIN_CASE */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200293void get_boolean(const data_t *input, int expected_value, int expected_result)
Gilles Peskine27d806f2019-03-01 18:02:53 +0100294{
295 unsigned char *p = input->x;
296 int val;
297 int ret;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200298 ret = mbedtls_asn1_get_bool(&p, input->x + input->len, &val);
299 TEST_EQUAL(ret, expected_result);
300 if (expected_result == 0) {
301 TEST_EQUAL(val, expected_value);
302 TEST_ASSERT(p == input->x + input->len);
Gilles Peskine27d806f2019-03-01 18:02:53 +0100303 }
304}
305/* END_CASE */
306
307/* BEGIN_CASE */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200308void empty_integer(const data_t *input)
Gilles Peskine321adb22019-10-10 19:18:21 +0200309{
310 unsigned char *p;
311#if defined(MBEDTLS_BIGNUM_C)
312 mbedtls_mpi actual_mpi;
313#endif
314 int val;
315
316#if defined(MBEDTLS_BIGNUM_C)
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200317 mbedtls_mpi_init(&actual_mpi);
Gilles Peskine321adb22019-10-10 19:18:21 +0200318#endif
319
320 /* An INTEGER with no content is not valid. */
321 p = input->x;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200322 TEST_EQUAL(mbedtls_asn1_get_int(&p, input->x + input->len, &val),
323 MBEDTLS_ERR_ASN1_INVALID_LENGTH);
Gilles Peskine321adb22019-10-10 19:18:21 +0200324
325#if defined(MBEDTLS_BIGNUM_C)
326 /* INTEGERs are sometimes abused as bitstrings, so the library accepts
327 * an INTEGER with empty content and gives it the value 0. */
328 p = input->x;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200329 TEST_EQUAL(mbedtls_asn1_get_mpi(&p, input->x + input->len, &actual_mpi), 0);
330 TEST_EQUAL(mbedtls_mpi_cmp_int(&actual_mpi, 0), 0);
Gilles Peskine321adb22019-10-10 19:18:21 +0200331#endif
332
333exit:
334#if defined(MBEDTLS_BIGNUM_C)
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200335 mbedtls_mpi_free(&actual_mpi);
Gilles Peskine321adb22019-10-10 19:18:21 +0200336#endif
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200337 /*empty cleanup in some configurations*/;
Gilles Peskine321adb22019-10-10 19:18:21 +0200338}
339/* END_CASE */
340
341/* BEGIN_CASE */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200342void get_integer(const data_t *input,
343 const char *expected_hex,
344 int expected_result)
Gilles Peskine27d806f2019-03-01 18:02:53 +0100345{
346 unsigned char *p;
347#if defined(MBEDTLS_BIGNUM_C)
348 mbedtls_mpi expected_mpi;
349 mbedtls_mpi actual_mpi;
Gilles Peskine970dcbf2019-10-10 19:21:12 +0200350 mbedtls_mpi complement;
Gilles Peskine03c165e2019-10-10 19:15:18 +0200351 int expected_result_for_mpi = expected_result;
Gilles Peskine27d806f2019-03-01 18:02:53 +0100352#endif
353 long expected_value;
354 int expected_result_for_int = expected_result;
Gilles Peskine27d806f2019-03-01 18:02:53 +0100355 int val;
356 int ret;
357
358#if defined(MBEDTLS_BIGNUM_C)
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200359 mbedtls_mpi_init(&expected_mpi);
360 mbedtls_mpi_init(&actual_mpi);
361 mbedtls_mpi_init(&complement);
Gilles Peskine27d806f2019-03-01 18:02:53 +0100362#endif
363
364 errno = 0;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200365 expected_value = strtol(expected_hex, NULL, 16);
366 if (expected_result == 0 &&
367 (errno == ERANGE
Gilles Peskine27d806f2019-03-01 18:02:53 +0100368#if LONG_MAX > INT_MAX
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200369 || expected_value > INT_MAX || expected_value < INT_MIN
Gilles Peskine27d806f2019-03-01 18:02:53 +0100370#endif
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200371 )) {
Gilles Peskine970dcbf2019-10-10 19:21:12 +0200372 /* The library returns the dubious error code INVALID_LENGTH
373 * for integers that are out of range. */
374 expected_result_for_int = MBEDTLS_ERR_ASN1_INVALID_LENGTH;
375 }
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200376 if (expected_result == 0 && expected_value < 0) {
Gilles Peskine970dcbf2019-10-10 19:21:12 +0200377 /* The library does not support negative INTEGERs and
378 * returns the dubious error code INVALID_LENGTH.
379 * Test that we preserve the historical behavior. If we
380 * decide to change the behavior, we'll also change this test. */
Gilles Peskine27d806f2019-03-01 18:02:53 +0100381 expected_result_for_int = MBEDTLS_ERR_ASN1_INVALID_LENGTH;
382 }
383
384 p = input->x;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200385 ret = mbedtls_asn1_get_int(&p, input->x + input->len, &val);
386 TEST_EQUAL(ret, expected_result_for_int);
387 if (ret == 0) {
388 TEST_EQUAL(val, expected_value);
389 TEST_ASSERT(p == input->x + input->len);
Gilles Peskine27d806f2019-03-01 18:02:53 +0100390 }
391
392#if defined(MBEDTLS_BIGNUM_C)
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200393 ret = mbedtls_test_read_mpi(&expected_mpi, 16, expected_hex);
394 TEST_ASSERT(ret == 0 || ret == MBEDTLS_ERR_MPI_BAD_INPUT_DATA);
395 if (ret == MBEDTLS_ERR_MPI_BAD_INPUT_DATA) {
Gilles Peskine27d806f2019-03-01 18:02:53 +0100396 /* The data overflows the maximum MPI size. */
397 expected_result_for_mpi = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
398 }
399 p = input->x;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200400 ret = mbedtls_asn1_get_mpi(&p, input->x + input->len, &actual_mpi);
401 TEST_EQUAL(ret, expected_result_for_mpi);
402 if (ret == 0) {
403 if (expected_value >= 0) {
404 TEST_ASSERT(mbedtls_mpi_cmp_mpi(&actual_mpi, &expected_mpi) == 0);
405 } else {
Gilles Peskine970dcbf2019-10-10 19:21:12 +0200406 /* The library ignores the sign bit in ASN.1 INTEGERs
407 * (which makes sense insofar as INTEGERs are sometimes
408 * abused as bit strings), so the result of parsing them
409 * is a positive integer such that expected_mpi +
410 * actual_mpi = 2^n where n is the length of the content
411 * of the INTEGER. (Leading ff octets don't matter for the
412 * expected value, but they matter for the actual value.)
413 * Test that we don't change from this behavior. If we
414 * decide to fix the library to change the behavior on
415 * negative INTEGERs, we'll fix this test code. */
416 unsigned char *q = input->x + 1;
417 size_t len;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200418 TEST_ASSERT(mbedtls_asn1_get_len(&q, input->x + input->len, &len) ==
419 0);
420 TEST_ASSERT(mbedtls_mpi_lset(&complement, 1) == 0);
421 TEST_ASSERT(mbedtls_mpi_shift_l(&complement, len * 8) == 0);
422 TEST_ASSERT(mbedtls_mpi_add_mpi(&complement, &complement,
423 &expected_mpi) == 0);
424 TEST_ASSERT(mbedtls_mpi_cmp_mpi(&complement, &actual_mpi) == 0);
Gilles Peskine970dcbf2019-10-10 19:21:12 +0200425 }
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200426 TEST_ASSERT(p == input->x + input->len);
Gilles Peskine27d806f2019-03-01 18:02:53 +0100427 }
428#endif
429
430exit:
431#if defined(MBEDTLS_BIGNUM_C)
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200432 mbedtls_mpi_free(&expected_mpi);
433 mbedtls_mpi_free(&actual_mpi);
434 mbedtls_mpi_free(&complement);
Gilles Peskine27d806f2019-03-01 18:02:53 +0100435#endif
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200436 /*empty cleanup in some configurations*/;
Gilles Peskine27d806f2019-03-01 18:02:53 +0100437}
438/* END_CASE */
439
Mykhailo Sopiha6af7bf92019-10-31 15:55:16 +0200440/* BEGIN_CASE */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200441void get_enum(const data_t *input,
442 const char *expected_hex,
443 int expected_result)
Mykhailo Sopiha6af7bf92019-10-31 15:55:16 +0200444{
445 unsigned char *p;
446 long expected_value;
447 int expected_result_for_enum = expected_result;
448 int val;
449 int ret;
450
451 errno = 0;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200452 expected_value = strtol(expected_hex, NULL, 16);
453 if (expected_result == 0 &&
454 (errno == ERANGE
Mykhailo Sopiha6af7bf92019-10-31 15:55:16 +0200455#if LONG_MAX > INT_MAX
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200456 || expected_value > INT_MAX || expected_value < INT_MIN
Mykhailo Sopiha6af7bf92019-10-31 15:55:16 +0200457#endif
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200458 )) {
Mykhailo Sopiha6af7bf92019-10-31 15:55:16 +0200459 /* The library returns the dubious error code INVALID_LENGTH
460 * for integers that are out of range. */
461 expected_result_for_enum = MBEDTLS_ERR_ASN1_INVALID_LENGTH;
462 }
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200463 if (expected_result == 0 && expected_value < 0) {
Mykhailo Sopiha6af7bf92019-10-31 15:55:16 +0200464 /* The library does not support negative INTEGERs and
465 * returns the dubious error code INVALID_LENGTH.
466 * Test that we preserve the historical behavior. If we
467 * decide to change the behavior, we'll also change this test. */
468 expected_result_for_enum = MBEDTLS_ERR_ASN1_INVALID_LENGTH;
469 }
470
471 p = input->x;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200472 ret = mbedtls_asn1_get_enum(&p, input->x + input->len, &val);
473 TEST_EQUAL(ret, expected_result_for_enum);
474 if (ret == 0) {
475 TEST_EQUAL(val, expected_value);
476 TEST_ASSERT(p == input->x + input->len);
Mykhailo Sopiha6af7bf92019-10-31 15:55:16 +0200477 }
478}
479/* END_CASE */
480
Gilles Peskine27d806f2019-03-01 18:02:53 +0100481/* BEGIN_CASE depends_on:MBEDTLS_BIGNUM_C */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200482void get_mpi_too_large()
Gilles Peskine27d806f2019-03-01 18:02:53 +0100483{
484 unsigned char *buf = NULL;
485 unsigned char *p;
486 mbedtls_mpi actual_mpi;
487 size_t too_many_octets =
488 MBEDTLS_MPI_MAX_LIMBS * sizeof(mbedtls_mpi_uint) + 1;
489 size_t size = too_many_octets + 6;
490
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200491 mbedtls_mpi_init(&actual_mpi);
Gilles Peskine27d806f2019-03-01 18:02:53 +0100492
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200493 ASSERT_ALLOC(buf, size);
Gilles Peskine27d806f2019-03-01 18:02:53 +0100494 buf[0] = 0x02; /* tag: INTEGER */
495 buf[1] = 0x84; /* 4-octet length */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200496 buf[2] = (too_many_octets >> 24) & 0xff;
497 buf[3] = (too_many_octets >> 16) & 0xff;
498 buf[4] = (too_many_octets >> 8) & 0xff;
Gilles Peskine27d806f2019-03-01 18:02:53 +0100499 buf[5] = too_many_octets & 0xff;
500 buf[6] = 0x01; /* most significant octet */
501
502 p = buf;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200503 TEST_EQUAL(mbedtls_asn1_get_mpi(&p, buf + size, &actual_mpi),
504 MBEDTLS_ERR_MPI_ALLOC_FAILED);
Gilles Peskine27d806f2019-03-01 18:02:53 +0100505
506exit:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200507 mbedtls_mpi_free(&actual_mpi);
508 mbedtls_free(buf);
Gilles Peskine27d806f2019-03-01 18:02:53 +0100509}
510/* END_CASE */
511
512/* BEGIN_CASE */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200513void get_bitstring(const data_t *input,
514 int expected_length,
515 int expected_unused_bits,
516 int expected_result,
517 int expected_result_null)
Gilles Peskine27d806f2019-03-01 18:02:53 +0100518{
519 mbedtls_asn1_bitstring bs = { 0xdead, 0x21, NULL };
520 unsigned char *p = input->x;
521
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200522 TEST_EQUAL(mbedtls_asn1_get_bitstring(&p, input->x + input->len, &bs),
523 expected_result);
524 if (expected_result == 0) {
525 TEST_EQUAL(bs.len, (size_t)expected_length);
526 TEST_EQUAL(bs.unused_bits, expected_unused_bits);
527 TEST_ASSERT(bs.p != NULL);
528 TEST_EQUAL(bs.p - input->x + bs.len, input->len);
529 TEST_ASSERT(p == input->x + input->len);
Gilles Peskine27d806f2019-03-01 18:02:53 +0100530 }
531
532 p = input->x;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200533 TEST_EQUAL(mbedtls_asn1_get_bitstring_null(&p, input->x + input->len,
534 &bs.len),
535 expected_result_null);
536 if (expected_result_null == 0) {
537 TEST_EQUAL(bs.len, (size_t)expected_length);
538 if (expected_result == 0)
539 TEST_ASSERT(p == input->x + input->len - bs.len);
Gilles Peskine27d806f2019-03-01 18:02:53 +0100540 }
541}
542/* END_CASE */
543
544/* BEGIN_CASE */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200545void get_sequence_of(const data_t *input,
546 int tag,
547 const char *description,
548 int expected_result)
Gilles Peskine27d806f2019-03-01 18:02:53 +0100549{
Hanno Becker199b7092019-09-11 14:21:26 +0100550 /* The description string is a comma-separated list of integers.
551 * For each element in the SEQUENCE in input, description contains
552 * two integers: the offset of the element (offset from the start
553 * of input to the tag of the element) and the length of the
554 * element's contents.
555 * "offset1,length1,..." */
556
Gilles Peskine27d806f2019-03-01 18:02:53 +0100557 mbedtls_asn1_sequence head = { { 0, 0, NULL }, NULL };
Hanno Becker12ae27d2019-09-11 14:20:09 +0100558 mbedtls_asn1_sequence *cur;
Gilles Peskine27d806f2019-03-01 18:02:53 +0100559 unsigned char *p = input->x;
560 const char *rest = description;
561 unsigned long n;
Chris Jones567e0ad2021-02-03 12:07:01 +0000562 unsigned int step = 0;
Gilles Peskine27d806f2019-03-01 18:02:53 +0100563
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200564 TEST_EQUAL(mbedtls_asn1_get_sequence_of(&p, input->x + input->len, &head,
565 tag),
566 expected_result);
567 if (expected_result == 0) {
568 TEST_ASSERT(p == input->x + input->len);
Gilles Peskine27d806f2019-03-01 18:02:53 +0100569
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200570 if (!*rest) {
571 TEST_EQUAL(head.buf.tag, 0);
572 TEST_ASSERT(head.buf.p == NULL);
573 TEST_EQUAL(head.buf.len, 0);
574 TEST_ASSERT(head.next == NULL);
575 } else {
Gilles Peskine27d806f2019-03-01 18:02:53 +0100576 cur = &head;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200577 while (*rest) {
578 mbedtls_test_set_step(step);
579 TEST_ASSERT(cur != NULL);
580 TEST_EQUAL(cur->buf.tag, tag);
581 n = strtoul(rest, (char **)&rest, 0);
582 TEST_EQUAL(n, (size_t)(cur->buf.p - input->x));
Gilles Peskine27d806f2019-03-01 18:02:53 +0100583 ++rest;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200584 n = strtoul(rest, (char **)&rest, 0);
585 TEST_EQUAL(n, cur->buf.len);
586 if (*rest)
Gilles Peskine27d806f2019-03-01 18:02:53 +0100587 ++rest;
588 cur = cur->next;
Chris Jones567e0ad2021-02-03 12:07:01 +0000589 ++step;
Gilles Peskine27d806f2019-03-01 18:02:53 +0100590 }
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200591 TEST_ASSERT(cur == NULL);
Gilles Peskine27d806f2019-03-01 18:02:53 +0100592 }
593 }
594
595exit:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200596 mbedtls_asn1_sequence_free(head.next);
Gilles Peskine27d806f2019-03-01 18:02:53 +0100597}
598/* END_CASE */
599
600/* BEGIN_CASE */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200601void traverse_sequence_of(const data_t *input,
602 int tag_must_mask,
603 int tag_must_val,
604 int tag_may_mask,
605 int tag_may_val,
606 const char *description,
607 int expected_result)
Hanno Becker199b7092019-09-11 14:21:26 +0100608{
609 /* The description string is a comma-separated list of integers.
610 * For each element in the SEQUENCE in input, description contains
611 * three integers: the offset of the element's content (offset from
612 * the start of input to the content of the element), the element's tag,
613 * and the length of the element's contents.
614 * "offset1,tag1,length1,..." */
615
616 unsigned char *p = input->x;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200617 traverse_state_t traverse_state = { input->x, description };
Hanno Becker199b7092019-09-11 14:21:26 +0100618 int ret;
619
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200620 ret = mbedtls_asn1_traverse_sequence_of(
621 &p, input->x + input->len, (uint8_t)tag_must_mask,
622 (uint8_t)tag_must_val, (uint8_t)tag_may_mask, (uint8_t)tag_may_val,
623 traverse_callback, &traverse_state);
624 if (ret == RET_TRAVERSE_ERROR)
Hanno Becker199b7092019-09-11 14:21:26 +0100625 goto exit;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200626 TEST_EQUAL(ret, expected_result);
627 TEST_EQUAL(*traverse_state.description, 0);
Hanno Becker199b7092019-09-11 14:21:26 +0100628}
629/* END_CASE */
630
631/* BEGIN_CASE */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200632void get_alg(const data_t *input,
633 int oid_offset,
634 int oid_length,
635 int params_tag,
636 int params_offset,
637 int params_length,
638 int total_length,
639 int expected_result)
Gilles Peskine27d806f2019-03-01 18:02:53 +0100640{
641 mbedtls_asn1_buf oid = { -1, 0, NULL };
642 mbedtls_asn1_buf params = { -1, 0, NULL };
643 unsigned char *p = input->x;
644 int ret;
645
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200646 TEST_EQUAL(mbedtls_asn1_get_alg(&p, input->x + input->len, &oid, &params),
647 expected_result);
648 if (expected_result == 0) {
649 TEST_EQUAL(oid.tag, MBEDTLS_ASN1_OID);
650 TEST_EQUAL(oid.p - input->x, oid_offset);
651 TEST_EQUAL(oid.len, (size_t)oid_length);
652 TEST_EQUAL(params.tag, params_tag);
653 if (params_offset != 0)
654 TEST_EQUAL(params.p - input->x, params_offset);
Gilles Peskine27d806f2019-03-01 18:02:53 +0100655 else
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200656 TEST_ASSERT(params.p == NULL);
657 TEST_EQUAL(params.len, (size_t)params_length);
658 TEST_EQUAL(p - input->x, total_length);
Gilles Peskine27d806f2019-03-01 18:02:53 +0100659 }
660
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200661 ret = mbedtls_asn1_get_alg_null(&p, input->x + input->len, &oid);
662 if (expected_result == 0 && params_offset == 0) {
663 TEST_EQUAL(oid.tag, MBEDTLS_ASN1_OID);
664 TEST_EQUAL(oid.p - input->x, oid_offset);
665 TEST_EQUAL(oid.len, (size_t)oid_length);
666 TEST_EQUAL(p - input->x, total_length);
667 } else
668 TEST_ASSERT(ret != 0);
Gilles Peskine27d806f2019-03-01 18:02:53 +0100669}
670/* END_CASE */
671
672/* BEGIN_CASE */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200673void find_named_data(data_t *oid0,
674 data_t *oid1,
675 data_t *oid2,
676 data_t *oid3,
677 data_t *needle,
678 int from,
679 int position)
Gilles Peskine27d806f2019-03-01 18:02:53 +0100680{
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200681 mbedtls_asn1_named_data nd[] = {
682 { { 0x06, oid0->len, oid0->x }, { 0, 0, NULL }, NULL, 0 },
683 { { 0x06, oid1->len, oid1->x }, { 0, 0, NULL }, NULL, 0 },
684 { { 0x06, oid2->len, oid2->x }, { 0, 0, NULL }, NULL, 0 },
685 { { 0x06, oid3->len, oid3->x }, { 0, 0, NULL }, NULL, 0 },
Gilles Peskine27d806f2019-03-01 18:02:53 +0100686 };
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200687 mbedtls_asn1_named_data *pointers[ARRAY_LENGTH(nd) + 1];
Gilles Peskine27d806f2019-03-01 18:02:53 +0100688 size_t i;
Mateusz Starzyk59961cf2021-01-26 13:57:43 +0100689 const mbedtls_asn1_named_data *found;
Gilles Peskine27d806f2019-03-01 18:02:53 +0100690
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200691 for (i = 0; i < ARRAY_LENGTH(nd); i++)
Gilles Peskine27d806f2019-03-01 18:02:53 +0100692 pointers[i] = &nd[i];
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200693 pointers[ARRAY_LENGTH(nd)] = NULL;
694 for (i = 0; i < ARRAY_LENGTH(nd); i++)
695 nd[i].next = pointers[i + 1];
Gilles Peskine27d806f2019-03-01 18:02:53 +0100696
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200697 found = mbedtls_asn1_find_named_data(
698 (const mbedtls_asn1_named_data *)pointers[from],
699 (const char *)needle->x, needle->len);
700 TEST_ASSERT(found == pointers[position]);
Gilles Peskine27d806f2019-03-01 18:02:53 +0100701}
702/* END_CASE */
703
704/* BEGIN_CASE */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200705void free_named_data_null()
Gilles Peskine27d806f2019-03-01 18:02:53 +0100706{
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200707 mbedtls_asn1_free_named_data(NULL);
Gilles Peskine27d806f2019-03-01 18:02:53 +0100708 goto exit; /* Silence unused label warning */
709}
710/* END_CASE */
711
712/* BEGIN_CASE */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200713void free_named_data(int with_oid, int with_val, int with_next)
Gilles Peskine27d806f2019-03-01 18:02:53 +0100714{
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200715 mbedtls_asn1_named_data next = { { 0x06, 0, NULL },
716 { 0, 0xcafe, NULL },
717 NULL,
718 0 };
719 mbedtls_asn1_named_data head = { { 0x06, 0, NULL },
720 { 0, 0, NULL },
721 NULL,
722 0 };
Gilles Peskine27d806f2019-03-01 18:02:53 +0100723
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200724 if (with_oid)
725 ASSERT_ALLOC(head.oid.p, 1);
726 if (with_val)
727 ASSERT_ALLOC(head.val.p, 1);
728 if (with_next)
Gilles Peskine27d806f2019-03-01 18:02:53 +0100729 head.next = &next;
730
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200731 mbedtls_asn1_free_named_data(&head);
732 TEST_ASSERT(head.oid.p == NULL);
733 TEST_ASSERT(head.val.p == NULL);
734 TEST_ASSERT(head.next == NULL);
735 TEST_ASSERT(next.val.len == 0xcafe);
Gilles Peskine27d806f2019-03-01 18:02:53 +0100736
737exit:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200738 mbedtls_free(head.oid.p);
739 mbedtls_free(head.val.p);
Gilles Peskine27d806f2019-03-01 18:02:53 +0100740}
741/* END_CASE */
742
743/* BEGIN_CASE */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200744void free_named_data_list(int length)
Gilles Peskine27d806f2019-03-01 18:02:53 +0100745{
746 mbedtls_asn1_named_data *head = NULL;
747 int i;
748
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200749 for (i = 0; i < length; i++) {
Gilles Peskine27d806f2019-03-01 18:02:53 +0100750 mbedtls_asn1_named_data *new = NULL;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200751 ASSERT_ALLOC(new, sizeof(mbedtls_asn1_named_data));
Gilles Peskine88f136f2019-09-20 21:06:27 +0200752 new->next = head;
Gilles Peskine27d806f2019-03-01 18:02:53 +0100753 head = new;
754 }
755
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200756 mbedtls_asn1_free_named_data_list(&head);
757 TEST_ASSERT(head == NULL);
Gilles Peskine27d806f2019-03-01 18:02:53 +0100758 /* Most of the point of the test is that it doesn't leak memory.
759 * So this test is only really useful under a memory leak detection
760 * framework. */
761exit:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200762 mbedtls_asn1_free_named_data_list(&head);
Gilles Peskine27d806f2019-03-01 18:02:53 +0100763}
764/* END_CASE */