blob: 3419f03b552b85e50ccbeea883d480e95c0e4e9c [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)
9#include "mbedtls/asn1write.h"
10#endif
11
12#define ERR_PARSE_INCONSISTENCY INT_MAX
13
14static int nested_parse( unsigned char **const p,
15 const unsigned char *const end )
16{
17 int ret;
18 size_t len = 0;
19 size_t len2 = 0;
20 unsigned char *const start = *p;
21 unsigned char *content_start;
22 unsigned char tag;
23
24 /* First get the length, skipping over the tag. */
25 content_start = start + 1;
26 ret = mbedtls_asn1_get_len( &content_start, end, &len );
27 TEST_ASSERT( content_start <= end );
28 if( ret != 0 )
29 return( ret );
30
31 /* Since we have a valid element start (tag and length), retrieve and
32 * check the tag. */
33 tag = start[0];
34 TEST_EQUAL( mbedtls_asn1_get_tag( p, end, &len2, tag ^ 1 ),
35 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
36 *p = start;
37 TEST_EQUAL( mbedtls_asn1_get_tag( p, end, &len2, tag ), 0 );
38 TEST_EQUAL( len, len2 );
39 TEST_ASSERT( *p == content_start );
40 *p = content_start;
41
42 switch( tag & 0x1f )
43 {
44 case MBEDTLS_ASN1_BOOLEAN:
45 {
46 int val = -257;
47 *p = start;
48 ret = mbedtls_asn1_get_bool( p, end, &val );
49 if( ret == 0 )
50 TEST_ASSERT( val == 0 || val == 1 );
51 break;
52 }
53
54 case MBEDTLS_ASN1_INTEGER:
55 {
56#if defined(MBEDTLS_BIGNUM_C)
57 mbedtls_mpi mpi;
58 mbedtls_mpi_init( &mpi );
59 *p = start;
60 ret = mbedtls_asn1_get_mpi( p, end, &mpi );
61 mbedtls_mpi_free( &mpi );
Gilles Peskine03c165e2019-10-10 19:15:18 +020062#else
63 *p = start + 1;
64 ret = mbedtls_asn1_get_len( p, end, &len );
65 *p += len;
Gilles Peskine27d806f2019-03-01 18:02:53 +010066#endif
67 /* If we're sure that the number fits in an int, also
68 * call mbedtls_asn1_get_int(). */
69 if( ret == 0 && len < sizeof( int ) )
70 {
71 int val = -257;
72 unsigned char *q = start;
73 ret = mbedtls_asn1_get_int( &q, end, &val );
74 TEST_ASSERT( *p == q );
75 }
76 break;
77 }
78
79 case MBEDTLS_ASN1_BIT_STRING:
80 {
81 mbedtls_asn1_bitstring bs;
82 *p = start;
83 ret = mbedtls_asn1_get_bitstring( p, end, &bs );
84 break;
85 }
86
87 case MBEDTLS_ASN1_SEQUENCE:
88 {
89 while( *p <= end && *p < content_start + len && ret == 0 )
90 ret = nested_parse( p, content_start + len );
91 break;
92 }
93
94 case MBEDTLS_ASN1_OCTET_STRING:
95 case MBEDTLS_ASN1_NULL:
96 case MBEDTLS_ASN1_OID:
97 case MBEDTLS_ASN1_UTF8_STRING:
98 case MBEDTLS_ASN1_SET:
99 case MBEDTLS_ASN1_PRINTABLE_STRING:
100 case MBEDTLS_ASN1_T61_STRING:
101 case MBEDTLS_ASN1_IA5_STRING:
102 case MBEDTLS_ASN1_UTC_TIME:
103 case MBEDTLS_ASN1_GENERALIZED_TIME:
104 case MBEDTLS_ASN1_UNIVERSAL_STRING:
105 case MBEDTLS_ASN1_BMP_STRING:
106 default:
107 /* No further testing implemented for this tag. */
108 *p += len;
109 return( 0 );
110 }
111
112 TEST_ASSERT( *p <= end );
113 return( ret );
114
115exit:
116 return( ERR_PARSE_INCONSISTENCY );
117}
118
119int get_len_step( const data_t *input, size_t buffer_size,
120 size_t actual_length )
121{
122 unsigned char *buf = NULL;
123 unsigned char *p = NULL;
Gilles Peskine42a1acf2020-01-21 16:12:07 +0100124 unsigned char *end;
Gilles Peskine27d806f2019-03-01 18:02:53 +0100125 size_t parsed_length;
126 int ret;
127
128 test_set_step( buffer_size );
129 /* Allocate a new buffer of exactly the length to parse each time.
130 * This gives memory sanitizers a chance to catch buffer overreads. */
131 if( buffer_size == 0 )
132 {
133 ASSERT_ALLOC( buf, 1 );
Gilles Peskine42a1acf2020-01-21 16:12:07 +0100134 end = buf + 1;
135 p = end;
Gilles Peskine27d806f2019-03-01 18:02:53 +0100136 }
137 else
138 {
Gilles Peskine2cd8ecc2019-03-04 17:13:43 +0100139 ASSERT_ALLOC_WEAK( buf, buffer_size );
Gilles Peskine27d806f2019-03-01 18:02:53 +0100140 if( buffer_size > input->len )
141 {
142 memcpy( buf, input->x, input->len );
143 memset( buf + input->len, 'A', buffer_size - input->len );
144 }
145 else
146 {
147 memcpy( buf, input->x, buffer_size );
148 }
149 p = buf;
Gilles Peskine42a1acf2020-01-21 16:12:07 +0100150 end = buf + buffer_size;
Gilles Peskine27d806f2019-03-01 18:02:53 +0100151 }
152
Gilles Peskine42a1acf2020-01-21 16:12:07 +0100153 ret = mbedtls_asn1_get_len( &p, end, &parsed_length );
Gilles Peskine27d806f2019-03-01 18:02:53 +0100154
155 if( buffer_size >= input->len + actual_length )
156 {
157 TEST_EQUAL( ret, 0 );
158 TEST_ASSERT( p == buf + input->len );
159 TEST_EQUAL( parsed_length, actual_length );
160 }
161 else
162 {
163 TEST_EQUAL( ret, MBEDTLS_ERR_ASN1_OUT_OF_DATA );
164 }
165 mbedtls_free( buf );
166 return( 1 );
167
168exit:
Gilles Peskine27d806f2019-03-01 18:02:53 +0100169 mbedtls_free( buf );
170 return( 0 );
171}
172
Hanno Becker199b7092019-09-11 14:21:26 +0100173typedef struct
174{
175 const unsigned char *input_start;
176 const char *description;
177} traverse_state_t;
178
179/* Value returned by traverse_callback if description runs out. */
180#define RET_TRAVERSE_STOP 1
181/* Value returned by traverse_callback if description has an invalid format
182 * (see traverse_sequence_of). */
183#define RET_TRAVERSE_ERROR 2
184
185
186static int traverse_callback( void *ctx, int tag,
187 unsigned char *content, size_t len )
188{
189 traverse_state_t *state = ctx;
190 size_t offset;
191 const char *rest = state->description;
192 unsigned long n;
193
194 TEST_ASSERT( content > state->input_start );
195 offset = content - state->input_start;
196 test_set_step( offset );
197
198 if( *rest == 0 )
199 return( RET_TRAVERSE_STOP );
200 n = strtoul( rest, (char **) &rest, 0 );
201 TEST_EQUAL( n, offset );
202 TEST_EQUAL( *rest, ',' );
203 ++rest;
204 n = strtoul( rest, (char **) &rest, 0 );
205 TEST_EQUAL( n, (unsigned) tag );
206 TEST_EQUAL( *rest, ',' );
207 ++rest;
208 n = strtoul( rest, (char **) &rest, 0 );
209 TEST_EQUAL( n, len );
210 if( *rest == ',' )
211 ++rest;
212
213 state->description = rest;
214 return( 0 );
215
216exit:
217 return( RET_TRAVERSE_ERROR );
218}
219
Gilles Peskine27d806f2019-03-01 18:02:53 +0100220/* END_HEADER */
221
222/* BEGIN_DEPENDENCIES
223 * depends_on:MBEDTLS_ASN1_PARSE_C
224 * END_DEPENDENCIES
225 */
226
227/* BEGIN_CASE */
228void parse_prefixes( const data_t *input,
229 int actual_length_arg,
230 int last_result )
231{
232 size_t actual_length = actual_length_arg;
233 unsigned char *buf = NULL;
234 unsigned char *p = NULL;
235 size_t buffer_size;
236 int ret;
237
238 for( buffer_size = 1; buffer_size <= input->len; buffer_size++ )
239 {
240 test_set_step( buffer_size );
241 /* Allocate a new buffer of exactly the length to parse each time.
242 * This gives memory sanitizers a chance to catch buffer overreads. */
243 ASSERT_ALLOC( buf, buffer_size );
244 memcpy( buf, input->x, buffer_size );
245 p = buf;
246 ret = nested_parse( &p, buf + buffer_size );
247 if( ret == ERR_PARSE_INCONSISTENCY )
248 goto exit;
249 if( actual_length > 0 && buffer_size >= actual_length )
250 {
251 TEST_EQUAL( ret, last_result );
252 if( ret == 0 )
253 TEST_ASSERT( p == buf + actual_length );
254 }
255 else
256 {
257 TEST_EQUAL( ret, MBEDTLS_ERR_ASN1_OUT_OF_DATA );
258 }
259 mbedtls_free( buf );
260 buf = NULL;
261 }
262
263exit:
264 mbedtls_free( buf );
265}
266/* END_CASE */
267
268/* BEGIN_CASE */
269void get_len( const data_t *input, int actual_length_arg )
270{
271 size_t actual_length = actual_length_arg;
272 size_t buffer_size;
273
274 for( buffer_size = 1; buffer_size <= input->len + 1; buffer_size++ )
275 {
276 if( ! get_len_step( input, buffer_size, actual_length ) )
277 goto exit;
278 }
279 if( ! get_len_step( input, input->len + actual_length - 1, actual_length ) )
280 goto exit;
281 if( ! get_len_step( input, input->len + actual_length, actual_length ) )
282 goto exit;
283}
284/* END_CASE */
285
286/* BEGIN_CASE */
287void get_boolean( const data_t *input,
288 int expected_value, int expected_result )
289{
290 unsigned char *p = input->x;
291 int val;
292 int ret;
293 ret = mbedtls_asn1_get_bool( &p, input->x + input->len, &val );
294 TEST_EQUAL( ret, expected_result );
295 if( expected_result == 0 )
296 {
297 TEST_EQUAL( val, expected_value );
298 TEST_ASSERT( p == input->x + input->len );
299 }
300}
301/* END_CASE */
302
303/* BEGIN_CASE */
Gilles Peskine321adb22019-10-10 19:18:21 +0200304void empty_integer( const data_t *input )
305{
306 unsigned char *p;
307#if defined(MBEDTLS_BIGNUM_C)
308 mbedtls_mpi actual_mpi;
309#endif
310 int val;
311
312#if defined(MBEDTLS_BIGNUM_C)
313 mbedtls_mpi_init( & actual_mpi );
314#endif
315
316 /* An INTEGER with no content is not valid. */
317 p = input->x;
318 TEST_EQUAL( mbedtls_asn1_get_int( &p, input->x + input->len, &val ),
319 MBEDTLS_ERR_ASN1_INVALID_LENGTH );
320
321#if defined(MBEDTLS_BIGNUM_C)
322 /* INTEGERs are sometimes abused as bitstrings, so the library accepts
323 * an INTEGER with empty content and gives it the value 0. */
324 p = input->x;
325 TEST_EQUAL( mbedtls_asn1_get_mpi( &p, input->x + input->len, &actual_mpi ),
326 0 );
327 TEST_EQUAL( mbedtls_mpi_cmp_int( &actual_mpi, 0 ), 0 );
328#endif
329
330exit:
331#if defined(MBEDTLS_BIGNUM_C)
332 mbedtls_mpi_free( &actual_mpi );
333#endif
334 /*empty cleanup in some configurations*/ ;
335}
336/* END_CASE */
337
338/* BEGIN_CASE */
Gilles Peskine27d806f2019-03-01 18:02:53 +0100339void get_integer( const data_t *input,
340 const char *expected_hex, int expected_result )
341{
342 unsigned char *p;
343#if defined(MBEDTLS_BIGNUM_C)
344 mbedtls_mpi expected_mpi;
345 mbedtls_mpi actual_mpi;
Gilles Peskine970dcbf2019-10-10 19:21:12 +0200346 mbedtls_mpi complement;
Gilles Peskine03c165e2019-10-10 19:15:18 +0200347 int expected_result_for_mpi = expected_result;
Gilles Peskine27d806f2019-03-01 18:02:53 +0100348#endif
349 long expected_value;
350 int expected_result_for_int = expected_result;
Gilles Peskine27d806f2019-03-01 18:02:53 +0100351 int val;
352 int ret;
353
354#if defined(MBEDTLS_BIGNUM_C)
355 mbedtls_mpi_init( &expected_mpi );
356 mbedtls_mpi_init( &actual_mpi );
Gilles Peskine970dcbf2019-10-10 19:21:12 +0200357 mbedtls_mpi_init( &complement );
Gilles Peskine27d806f2019-03-01 18:02:53 +0100358#endif
359
360 errno = 0;
361 expected_value = strtol( expected_hex, NULL, 16 );
362 if( expected_result == 0 &&
363 ( errno == ERANGE
364#if LONG_MAX > INT_MAX
365 || expected_value > INT_MAX || expected_value < INT_MIN
366#endif
367 ) )
368 {
Gilles Peskine970dcbf2019-10-10 19:21:12 +0200369 /* The library returns the dubious error code INVALID_LENGTH
370 * for integers that are out of range. */
371 expected_result_for_int = MBEDTLS_ERR_ASN1_INVALID_LENGTH;
372 }
373 if( expected_result == 0 && expected_value < 0 )
374 {
375 /* The library does not support negative INTEGERs and
376 * returns the dubious error code INVALID_LENGTH.
377 * Test that we preserve the historical behavior. If we
378 * decide to change the behavior, we'll also change this test. */
Gilles Peskine27d806f2019-03-01 18:02:53 +0100379 expected_result_for_int = MBEDTLS_ERR_ASN1_INVALID_LENGTH;
380 }
381
382 p = input->x;
383 ret = mbedtls_asn1_get_int( &p, input->x + input->len, &val );
384 TEST_EQUAL( ret, expected_result_for_int );
385 if( ret == 0 )
386 {
387 TEST_EQUAL( val, expected_value );
388 TEST_ASSERT( p == input->x + input->len );
389 }
390
391#if defined(MBEDTLS_BIGNUM_C)
392 ret = mbedtls_mpi_read_string( &expected_mpi, 16, expected_hex );
393 TEST_ASSERT( ret == 0 || ret == MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
394 if( ret == MBEDTLS_ERR_MPI_BAD_INPUT_DATA )
395 {
396 /* The data overflows the maximum MPI size. */
397 expected_result_for_mpi = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
398 }
399 p = input->x;
400 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 {
Gilles Peskine970dcbf2019-10-10 19:21:12 +0200404 if( expected_value >= 0 )
405 {
406 TEST_ASSERT( mbedtls_mpi_cmp_mpi( &actual_mpi,
407 &expected_mpi ) == 0 );
408 }
409 else
410 {
411 /* The library ignores the sign bit in ASN.1 INTEGERs
412 * (which makes sense insofar as INTEGERs are sometimes
413 * abused as bit strings), so the result of parsing them
414 * is a positive integer such that expected_mpi +
415 * actual_mpi = 2^n where n is the length of the content
416 * of the INTEGER. (Leading ff octets don't matter for the
417 * expected value, but they matter for the actual value.)
418 * Test that we don't change from this behavior. If we
419 * decide to fix the library to change the behavior on
420 * negative INTEGERs, we'll fix this test code. */
421 unsigned char *q = input->x + 1;
422 size_t len;
423 TEST_ASSERT( mbedtls_asn1_get_len( &q, input->x + input->len,
424 &len ) == 0 );
425 TEST_ASSERT( mbedtls_mpi_lset( &complement, 1 ) == 0 );
426 TEST_ASSERT( mbedtls_mpi_shift_l( &complement, len * 8 ) == 0 );
427 TEST_ASSERT( mbedtls_mpi_add_mpi( &complement, &complement,
428 &expected_mpi ) == 0 );
429 TEST_ASSERT( mbedtls_mpi_cmp_mpi( &complement,
430 &actual_mpi ) == 0 );
431 }
Gilles Peskine27d806f2019-03-01 18:02:53 +0100432 TEST_ASSERT( p == input->x + input->len );
433 }
434#endif
435
436exit:
437#if defined(MBEDTLS_BIGNUM_C)
438 mbedtls_mpi_free( &expected_mpi );
439 mbedtls_mpi_free( &actual_mpi );
Gilles Peskine970dcbf2019-10-10 19:21:12 +0200440 mbedtls_mpi_free( &complement );
Gilles Peskine27d806f2019-03-01 18:02:53 +0100441#endif
Gilles Peskine03c165e2019-10-10 19:15:18 +0200442 /*empty cleanup in some configurations*/ ;
Gilles Peskine27d806f2019-03-01 18:02:53 +0100443}
444/* END_CASE */
445
Mykhailo Sopiha6af7bf92019-10-31 15:55:16 +0200446/* BEGIN_CASE */
447void get_enum( const data_t *input,
448 const char *expected_hex, int expected_result )
449{
450 unsigned char *p;
451 long expected_value;
452 int expected_result_for_enum = expected_result;
453 int val;
454 int ret;
455
456 errno = 0;
457 expected_value = strtol( expected_hex, NULL, 16 );
458 if( expected_result == 0 &&
459 ( errno == ERANGE
460#if LONG_MAX > INT_MAX
461 || expected_value > INT_MAX || expected_value < INT_MIN
462#endif
463 ) )
464 {
465 /* The library returns the dubious error code INVALID_LENGTH
466 * for integers that are out of range. */
467 expected_result_for_enum = MBEDTLS_ERR_ASN1_INVALID_LENGTH;
468 }
469 if( expected_result == 0 && expected_value < 0 )
470 {
471 /* The library does not support negative INTEGERs and
472 * returns the dubious error code INVALID_LENGTH.
473 * Test that we preserve the historical behavior. If we
474 * decide to change the behavior, we'll also change this test. */
475 expected_result_for_enum = MBEDTLS_ERR_ASN1_INVALID_LENGTH;
476 }
477
478 p = input->x;
479 ret = mbedtls_asn1_get_enum( &p, input->x + input->len, &val );
480 TEST_EQUAL( ret, expected_result_for_enum );
481 if( ret == 0 )
482 {
483 TEST_EQUAL( val, expected_value );
484 TEST_ASSERT( p == input->x + input->len );
485 }
486}
487/* END_CASE */
488
Gilles Peskine27d806f2019-03-01 18:02:53 +0100489/* BEGIN_CASE depends_on:MBEDTLS_BIGNUM_C */
490void get_mpi_too_large( )
491{
492 unsigned char *buf = NULL;
493 unsigned char *p;
494 mbedtls_mpi actual_mpi;
495 size_t too_many_octets =
496 MBEDTLS_MPI_MAX_LIMBS * sizeof(mbedtls_mpi_uint) + 1;
497 size_t size = too_many_octets + 6;
498
499 mbedtls_mpi_init( &actual_mpi );
500
501 ASSERT_ALLOC( buf, size );
502 buf[0] = 0x02; /* tag: INTEGER */
503 buf[1] = 0x84; /* 4-octet length */
504 buf[2] = ( too_many_octets >> 24 ) & 0xff;
505 buf[3] = ( too_many_octets >> 16 ) & 0xff;
506 buf[4] = ( too_many_octets >> 8 ) & 0xff;
507 buf[5] = too_many_octets & 0xff;
508 buf[6] = 0x01; /* most significant octet */
509
510 p = buf;
511 TEST_EQUAL( mbedtls_asn1_get_mpi( &p, buf + size, &actual_mpi ),
512 MBEDTLS_ERR_MPI_ALLOC_FAILED );
513
514exit:
515 mbedtls_mpi_free( &actual_mpi );
516 mbedtls_free( buf );
517}
518/* END_CASE */
519
520/* BEGIN_CASE */
521void get_bitstring( const data_t *input,
522 int expected_length, int expected_unused_bits,
523 int expected_result, int expected_result_null )
524{
525 mbedtls_asn1_bitstring bs = { 0xdead, 0x21, NULL };
526 unsigned char *p = input->x;
527
528 TEST_EQUAL( mbedtls_asn1_get_bitstring( &p, input->x + input->len, &bs ),
529 expected_result );
530 if( expected_result == 0 )
531 {
532 TEST_EQUAL( bs.len, (size_t) expected_length );
533 TEST_EQUAL( bs.unused_bits, expected_unused_bits );
534 TEST_ASSERT( bs.p != NULL );
535 TEST_EQUAL( bs.p - input->x + bs.len, input->len );
536 TEST_ASSERT( p == input->x + input->len );
537 }
538
539 p = input->x;
540 TEST_EQUAL( mbedtls_asn1_get_bitstring_null( &p, input->x + input->len,
541 &bs.len ),
542 expected_result_null );
543 if( expected_result_null == 0 )
544 {
545 TEST_EQUAL( bs.len, (size_t) expected_length );
546 if( expected_result == 0 )
547 TEST_ASSERT( p == input->x + input->len - bs.len );
548 }
549}
550/* END_CASE */
551
552/* BEGIN_CASE */
553void get_sequence_of( const data_t *input, int tag,
554 const char *description,
555 int expected_result )
556{
Hanno Becker199b7092019-09-11 14:21:26 +0100557 /* The description string is a comma-separated list of integers.
558 * For each element in the SEQUENCE in input, description contains
559 * two integers: the offset of the element (offset from the start
560 * of input to the tag of the element) and the length of the
561 * element's contents.
562 * "offset1,length1,..." */
563
Gilles Peskine27d806f2019-03-01 18:02:53 +0100564 mbedtls_asn1_sequence head = { { 0, 0, NULL }, NULL };
Hanno Becker12ae27d2019-09-11 14:20:09 +0100565 mbedtls_asn1_sequence *cur;
Gilles Peskine27d806f2019-03-01 18:02:53 +0100566 unsigned char *p = input->x;
567 const char *rest = description;
568 unsigned long n;
569
570 TEST_EQUAL( mbedtls_asn1_get_sequence_of( &p, input->x + input->len,
571 &head, tag ),
572 expected_result );
573 if( expected_result == 0 )
574 {
575 TEST_ASSERT( p == input->x + input->len );
576
577 if( ! *rest )
578 {
579 TEST_EQUAL( head.buf.tag, 0 );
580 TEST_ASSERT( head.buf.p == NULL );
581 TEST_EQUAL( head.buf.len, 0 );
582 TEST_ASSERT( head.next == NULL );
583 }
584 else
585 {
586 cur = &head;
587 while( *rest )
588 {
589 ++test_info.step;
590 TEST_ASSERT( cur != NULL );
591 TEST_EQUAL( cur->buf.tag, tag );
592 n = strtoul( rest, (char **) &rest, 0 );
593 TEST_EQUAL( n, (size_t)( cur->buf.p - input->x ) );
594 ++rest;
595 n = strtoul( rest, (char **) &rest, 0 );
596 TEST_EQUAL( n, cur->buf.len );
597 if( *rest )
598 ++rest;
599 cur = cur->next;
600 }
601 TEST_ASSERT( cur == NULL );
602 }
603 }
604
605exit:
Hanno Becker12ae27d2019-09-11 14:20:09 +0100606 mbedtls_asn1_sequence_free( head.next );
Gilles Peskine27d806f2019-03-01 18:02:53 +0100607}
608/* END_CASE */
609
610/* BEGIN_CASE */
Hanno Becker199b7092019-09-11 14:21:26 +0100611void traverse_sequence_of( const data_t *input,
612 int tag_must_mask, int tag_must_val,
613 int tag_may_mask, int tag_may_val,
614 const char *description,
615 int expected_result )
616{
617 /* The description string is a comma-separated list of integers.
618 * For each element in the SEQUENCE in input, description contains
619 * three integers: the offset of the element's content (offset from
620 * the start of input to the content of the element), the element's tag,
621 * and the length of the element's contents.
622 * "offset1,tag1,length1,..." */
623
624 unsigned char *p = input->x;
625 traverse_state_t traverse_state = {input->x, description};
626 int ret;
627
628 ret = mbedtls_asn1_traverse_sequence_of( &p, input->x + input->len,
629 (uint8_t) tag_must_mask, (uint8_t) tag_must_val,
630 (uint8_t) tag_may_mask, (uint8_t) tag_may_val,
631 traverse_callback, &traverse_state );
632 if( ret == RET_TRAVERSE_ERROR )
633 goto exit;
634 TEST_EQUAL( ret, expected_result );
635 TEST_EQUAL( *traverse_state.description, 0 );
636}
637/* END_CASE */
638
639/* BEGIN_CASE */
Gilles Peskine27d806f2019-03-01 18:02:53 +0100640void get_alg( const data_t *input,
641 int oid_offset, int oid_length,
642 int params_tag, int params_offset, int params_length,
643 int total_length,
644 int expected_result )
645{
646 mbedtls_asn1_buf oid = { -1, 0, NULL };
647 mbedtls_asn1_buf params = { -1, 0, NULL };
648 unsigned char *p = input->x;
649 int ret;
650
651 TEST_EQUAL( mbedtls_asn1_get_alg( &p, input->x + input->len,
652 &oid, &params ),
653 expected_result );
654 if( expected_result == 0 )
655 {
656 TEST_EQUAL( oid.tag, MBEDTLS_ASN1_OID );
657 TEST_EQUAL( oid.p - input->x, oid_offset );
658 TEST_EQUAL( oid.len, (size_t) oid_length );
659 TEST_EQUAL( params.tag, params_tag );
660 if( params_offset != 0 )
661 TEST_EQUAL( params.p - input->x, params_offset );
662 else
663 TEST_ASSERT( params.p == NULL );
664 TEST_EQUAL( params.len, (size_t) params_length );
665 TEST_EQUAL( p - input->x, total_length );
666 }
667
668 ret = mbedtls_asn1_get_alg_null( &p, input->x + input->len, &oid );
669 if( expected_result == 0 && params_offset == 0 )
670 {
671 TEST_EQUAL( oid.tag, MBEDTLS_ASN1_OID );
672 TEST_EQUAL( oid.p - input->x, oid_offset );
673 TEST_EQUAL( oid.len, (size_t) oid_length );
674 TEST_EQUAL( p - input->x, total_length );
675 }
676 else
677 TEST_ASSERT( ret != 0 );
678}
679/* END_CASE */
680
681/* BEGIN_CASE */
682void find_named_data( data_t *oid0, data_t *oid1, data_t *oid2, data_t *oid3,
683 data_t *needle, int from, int position )
684{
685 mbedtls_asn1_named_data nd[] ={
686 { {0x06, oid0->len, oid0->x}, {0, 0, NULL}, NULL, 0 },
687 { {0x06, oid1->len, oid1->x}, {0, 0, NULL}, NULL, 0 },
688 { {0x06, oid2->len, oid2->x}, {0, 0, NULL}, NULL, 0 },
689 { {0x06, oid3->len, oid3->x}, {0, 0, NULL}, NULL, 0 },
690 };
691 mbedtls_asn1_named_data *pointers[ARRAY_LENGTH( nd ) + 1];
692 size_t i;
693 mbedtls_asn1_named_data *found;
694
695 for( i = 0; i < ARRAY_LENGTH( nd ); i++ )
696 pointers[i] = &nd[i];
697 pointers[ARRAY_LENGTH( nd )] = NULL;
698 for( i = 0; i < ARRAY_LENGTH( nd ); i++ )
699 nd[i].next = pointers[i+1];
700
701 found = mbedtls_asn1_find_named_data( pointers[from],
702 (const char *) needle->x,
703 needle->len );
704 TEST_ASSERT( found == pointers[position] );
705}
706/* END_CASE */
707
708/* BEGIN_CASE */
709void free_named_data_null( )
710{
711 mbedtls_asn1_free_named_data( NULL );
712 goto exit; /* Silence unused label warning */
713}
714/* END_CASE */
715
716/* BEGIN_CASE */
717void free_named_data( int with_oid, int with_val, int with_next )
718{
719 mbedtls_asn1_named_data next =
720 { {0x06, 0, NULL}, {0, 0xcafe, NULL}, NULL, 0 };
721 mbedtls_asn1_named_data head =
722 { {0x06, 0, NULL}, {0, 0, NULL}, NULL, 0 };
723
724 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 )
729 head.next = &next;
730
731 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 );
736
737exit:
738 mbedtls_free( head.oid.p );
739 mbedtls_free( head.val.p );
740}
741/* END_CASE */
742
743/* BEGIN_CASE */
744void free_named_data_list( int length )
745{
746 mbedtls_asn1_named_data *head = NULL;
747 int i;
748
749 for( i = 0; i < length; i++ )
750 {
751 mbedtls_asn1_named_data *new = NULL;
752 ASSERT_ALLOC( new, sizeof( mbedtls_asn1_named_data ) );
Gilles Peskine88f136f2019-09-20 21:06:27 +0200753 new->next = head;
Gilles Peskine27d806f2019-03-01 18:02:53 +0100754 head = new;
755 }
756
757 mbedtls_asn1_free_named_data_list( &head );
758 TEST_ASSERT( head == NULL );
759 /* Most of the point of the test is that it doesn't leak memory.
760 * So this test is only really useful under a memory leak detection
761 * framework. */
762exit:
763 mbedtls_asn1_free_named_data_list( &head );
764}
765/* END_CASE */