• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/* BEGIN_HEADER */
2#include "mbedtls/asn1write.h"
3
4#define GUARD_LEN 4
5#define GUARD_VAL 0x2a
6
7typedef struct
8{
9    unsigned char *output;
10    unsigned char *start;
11    unsigned char *end;
12    unsigned char *p;
13    size_t size;
14} generic_write_data_t;
15
16int generic_write_start_step( generic_write_data_t *data )
17{
18    mbedtls_test_set_step( data->size );
19    mbedtls_free( data->output );
20    data->output = NULL;
21    ASSERT_ALLOC( data->output, data->size == 0 ? 1 : data->size );
22    data->end = data->output + data->size;
23    data->p = data->end;
24    data->start = data->end - data->size;
25    return( 1 );
26exit:
27    return( 0 );
28}
29
30int generic_write_finish_step( generic_write_data_t *data,
31                               const data_t *expected, int ret )
32{
33    int ok = 0;
34
35    if( data->size < expected->len )
36    {
37        TEST_EQUAL( ret, MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
38    }
39    else
40    {
41        TEST_EQUAL( ret, data->end - data->p );
42        TEST_ASSERT( data->p >= data->start );
43        TEST_ASSERT( data->p <= data->end );
44        ASSERT_COMPARE( data->p, (size_t)( data->end - data->p ),
45                        expected->x, expected->len );
46    }
47    ok = 1;
48
49exit:
50    return( ok );
51}
52
53/* END_HEADER */
54
55/* BEGIN_DEPENDENCIES
56 * depends_on:MBEDTLS_ASN1_WRITE_C
57 * END_DEPENDENCIES
58 */
59
60/* BEGIN_CASE */
61void mbedtls_asn1_write_null( data_t *expected )
62{
63    generic_write_data_t data = { NULL, NULL, NULL, NULL, 0 };
64    int ret;
65
66    for( data.size = 0; data.size <= expected->len + 1; data.size++ )
67    {
68        if( ! generic_write_start_step( &data ) )
69            goto exit;
70        ret = mbedtls_asn1_write_null( &data.p, data.start );
71        if( ! generic_write_finish_step( &data, expected, ret ) )
72            goto exit;
73        /* There's no parsing function for NULL. */
74    }
75
76exit:
77    mbedtls_free( data.output );
78}
79/* END_CASE */
80
81/* BEGIN_CASE */
82void mbedtls_asn1_write_bool( int val, data_t *expected )
83{
84    generic_write_data_t data = { NULL, NULL, NULL, NULL, 0 };
85    int ret;
86
87    for( data.size = 0; data.size <= expected->len + 1; data.size++ )
88    {
89        if( ! generic_write_start_step( &data ) )
90            goto exit;
91        ret = mbedtls_asn1_write_bool( &data.p, data.start, val );
92        if( ! generic_write_finish_step( &data, expected, ret ) )
93            goto exit;
94#if defined(MBEDTLS_ASN1_PARSE_C)
95        if( ret >= 0 )
96        {
97            int read = 0xdeadbeef;
98            TEST_EQUAL( mbedtls_asn1_get_bool( &data.p, data.end, &read ), 0 );
99            TEST_EQUAL( val, read );
100        }
101#endif /* MBEDTLS_ASN1_PARSE_C */
102    }
103
104exit:
105    mbedtls_free( data.output );
106}
107/* END_CASE */
108
109/* BEGIN_CASE */
110void mbedtls_asn1_write_int( int val, data_t *expected )
111{
112    generic_write_data_t data = { NULL, NULL, NULL, NULL, 0 };
113    int ret;
114
115    for( data.size = 0; data.size <= expected->len + 1; data.size++ )
116    {
117        if( ! generic_write_start_step( &data ) )
118            goto exit;
119        ret = mbedtls_asn1_write_int( &data.p, data.start, val );
120        if( ! generic_write_finish_step( &data, expected, ret ) )
121            goto exit;
122#if defined(MBEDTLS_ASN1_PARSE_C)
123        if( ret >= 0 )
124        {
125            int read = 0xdeadbeef;
126            TEST_EQUAL( mbedtls_asn1_get_int( &data.p, data.end, &read ), 0 );
127            TEST_EQUAL( val, read );
128        }
129#endif /* MBEDTLS_ASN1_PARSE_C */
130    }
131
132exit:
133    mbedtls_free( data.output );
134}
135/* END_CASE */
136
137
138/* BEGIN_CASE */
139void mbedtls_asn1_write_enum( int val, data_t *expected )
140{
141    generic_write_data_t data = { NULL, NULL, NULL, NULL, 0 };
142    int ret;
143
144    for( data.size = 0; data.size <= expected->len + 1; data.size++ )
145    {
146        if( ! generic_write_start_step( &data ) )
147            goto exit;
148        ret = mbedtls_asn1_write_enum( &data.p, data.start, val );
149        if( ! generic_write_finish_step( &data, expected, ret ) )
150            goto exit;
151#if defined(MBEDTLS_ASN1_PARSE_C)
152        if( ret >= 0 )
153        {
154            int read = 0xdeadbeef;
155            TEST_EQUAL( mbedtls_asn1_get_enum( &data.p, data.end, &read ), 0 );
156            TEST_EQUAL( val, read );
157        }
158#endif /* MBEDTLS_ASN1_PARSE_C */
159    }
160
161exit:
162    mbedtls_free( data.output );
163}
164/* END_CASE */
165
166/* BEGIN_CASE depends_on:MBEDTLS_BIGNUM_C */
167void mbedtls_asn1_write_mpi( data_t *val, data_t *expected )
168{
169    generic_write_data_t data = { NULL, NULL, NULL, NULL, 0 };
170    mbedtls_mpi mpi, read;
171    int ret;
172
173    mbedtls_mpi_init( &mpi );
174    mbedtls_mpi_init( &read );
175    TEST_ASSERT( mbedtls_mpi_read_binary( &mpi, val->x, val->len ) == 0 );
176
177    for( data.size = 0; data.size <= expected->len + 1; data.size++ )
178    {
179        if( ! generic_write_start_step( &data ) )
180            goto exit;
181        ret = mbedtls_asn1_write_mpi( &data.p, data.start, &mpi );
182        if( ! generic_write_finish_step( &data, expected, ret ) )
183            goto exit;
184#if defined(MBEDTLS_ASN1_PARSE_C)
185        if( ret >= 0 )
186        {
187            TEST_EQUAL( mbedtls_asn1_get_mpi( &data.p, data.end, &read ), 0 );
188            TEST_EQUAL( 0, mbedtls_mpi_cmp_mpi( &mpi, &read ) );
189        }
190#endif /* MBEDTLS_ASN1_PARSE_C */
191        /* Skip some intermediate lengths, they're boring. */
192        if( expected->len > 10 && data.size == 8 )
193            data.size = expected->len - 2;
194    }
195
196exit:
197    mbedtls_mpi_free( &mpi );
198    mbedtls_mpi_free( &read );
199    mbedtls_free( data.output );
200}
201/* END_CASE */
202
203/* BEGIN_CASE */
204void mbedtls_asn1_write_string( int tag, data_t *content, data_t *expected )
205{
206    generic_write_data_t data = { NULL, NULL, NULL, NULL, 0 };
207    int ret;
208
209    for( data.size = 0; data.size <= expected->len + 1; data.size++ )
210    {
211        if( ! generic_write_start_step( &data ) )
212            goto exit;
213        switch( tag )
214        {
215            case MBEDTLS_ASN1_OCTET_STRING:
216                ret = mbedtls_asn1_write_octet_string(
217                    &data.p, data.start, content->x, content->len );
218                break;
219            case MBEDTLS_ASN1_OID:
220                ret = mbedtls_asn1_write_oid(
221                    &data.p, data.start,
222                    (const char *) content->x, content->len );
223                break;
224            case MBEDTLS_ASN1_UTF8_STRING:
225                ret = mbedtls_asn1_write_utf8_string(
226                    &data.p, data.start,
227                    (const char *) content->x, content->len );
228                break;
229            case MBEDTLS_ASN1_PRINTABLE_STRING:
230                ret = mbedtls_asn1_write_printable_string(
231                    &data.p, data.start,
232                    (const char *) content->x, content->len );
233                break;
234            case MBEDTLS_ASN1_IA5_STRING:
235                ret = mbedtls_asn1_write_ia5_string(
236                    &data.p, data.start,
237                    (const char *) content->x, content->len );
238                break;
239            default:
240                ret = mbedtls_asn1_write_tagged_string(
241                    &data.p, data.start, tag,
242                    (const char *) content->x, content->len );
243        }
244        if( ! generic_write_finish_step( &data, expected, ret ) )
245            goto exit;
246        /* There's no parsing function for octet or character strings. */
247        /* Skip some intermediate lengths, they're boring. */
248        if( expected->len > 10 && data.size == 8 )
249            data.size = expected->len - 2;
250    }
251
252exit:
253    mbedtls_free( data.output );
254}
255/* END_CASE */
256
257/* BEGIN_CASE */
258void mbedtls_asn1_write_algorithm_identifier( data_t *oid,
259                                              int par_len,
260                                              data_t *expected )
261{
262    generic_write_data_t data = { NULL, NULL, NULL, NULL, 0 };
263    int ret;
264#if defined(MBEDTLS_ASN1_PARSE_C)
265    unsigned char *buf_complete = NULL;
266#endif /* MBEDTLS_ASN1_PARSE_C */
267
268    for( data.size = 0; data.size <= expected->len + 1; data.size++ )
269    {
270        if( ! generic_write_start_step( &data ) )
271            goto exit;
272        ret = mbedtls_asn1_write_algorithm_identifier(
273            &data.p, data.start,
274            (const char *) oid->x, oid->len, par_len );
275        /* If params_len != 0, mbedtls_asn1_write_algorithm_identifier()
276         * assumes that the parameters are already present in the buffer
277         * and returns a length that accounts for this, but our test
278         * data omits the parameters. */
279        if( ret >= 0 )
280            ret -= par_len;
281        if( ! generic_write_finish_step( &data, expected, ret ) )
282            goto exit;
283
284#if defined(MBEDTLS_ASN1_PARSE_C)
285        /* Only do a parse-back test if the parameters aren't too large for
286         * a small-heap environment. The boundary is somewhat arbitrary. */
287        if( ret >= 0 && par_len <= 1234 )
288        {
289            mbedtls_asn1_buf alg = {0, 0, NULL};
290            mbedtls_asn1_buf params = {0, 0, NULL};
291            /* The writing function doesn't write the parameters unless
292             * they're null: it only takes their length as input. But the
293             * parsing function requires the parameters to be present.
294             * Thus make up parameters. */
295            size_t data_len = data.end - data.p;
296            size_t len_complete = data_len + par_len;
297            unsigned char expected_params_tag;
298            size_t expected_params_len;
299            ASSERT_ALLOC( buf_complete, len_complete );
300            unsigned char *end_complete = buf_complete + len_complete;
301            memcpy( buf_complete, data.p, data_len );
302            if( par_len == 0 )
303            {
304                /* mbedtls_asn1_write_algorithm_identifier() wrote a NULL */
305                expected_params_tag = 0x05;
306                expected_params_len = 0;
307            }
308            else if( par_len >= 2 && par_len < 2 + 128 )
309            {
310                /* Write an OCTET STRING with a short length encoding */
311                expected_params_tag = buf_complete[data_len] = 0x04;
312                expected_params_len = par_len - 2;
313                buf_complete[data_len + 1] = (unsigned char) expected_params_len;
314            }
315            else if( par_len >= 4 + 128 && par_len < 3 + 256 * 256 )
316            {
317                /* Write an OCTET STRING with a two-byte length encoding */
318                expected_params_tag = buf_complete[data_len] = 0x04;
319                expected_params_len = par_len - 4;
320                buf_complete[data_len + 1] = 0x82;
321                buf_complete[data_len + 2] = (unsigned char) ( expected_params_len >> 8 );
322                buf_complete[data_len + 3] = (unsigned char) ( expected_params_len );
323            }
324            else
325            {
326                TEST_ASSERT( ! "Bad test data: invalid length of ASN.1 element" );
327            }
328            unsigned char *p = buf_complete;
329            TEST_EQUAL( mbedtls_asn1_get_alg( &p, end_complete,
330                                              &alg, &params ), 0 );
331            TEST_EQUAL( alg.tag, MBEDTLS_ASN1_OID );
332            ASSERT_COMPARE( alg.p, alg.len, oid->x, oid->len );
333            TEST_EQUAL( params.tag, expected_params_tag );
334            TEST_EQUAL( params.len, expected_params_len );
335            mbedtls_free( buf_complete );
336            buf_complete = NULL;
337        }
338#endif /* MBEDTLS_ASN1_PARSE_C */
339    }
340
341exit:
342    mbedtls_free( data.output );
343#if defined(MBEDTLS_ASN1_PARSE_C)
344    mbedtls_free( buf_complete );
345#endif /* MBEDTLS_ASN1_PARSE_C */
346}
347/* END_CASE */
348
349/* BEGIN_CASE depends_on:MBEDTLS_ASN1_PARSE_C */
350void mbedtls_asn1_write_len( int len, data_t * asn1, int buf_len,
351                             int result )
352{
353    int ret;
354    unsigned char buf[150];
355    unsigned char *p;
356    size_t i;
357    size_t read_len;
358
359    memset( buf, GUARD_VAL, sizeof( buf ) );
360
361    p = buf + GUARD_LEN + buf_len;
362
363    ret = mbedtls_asn1_write_len( &p, buf + GUARD_LEN, (size_t) len );
364
365    TEST_ASSERT( ret == result );
366
367    /* Check for buffer overwrite on both sides */
368    for( i = 0; i < GUARD_LEN; i++ )
369    {
370        TEST_ASSERT( buf[i] == GUARD_VAL );
371        TEST_ASSERT( buf[GUARD_LEN + buf_len + i] == GUARD_VAL );
372    }
373
374    if( result >= 0 )
375    {
376        TEST_ASSERT( p + asn1->len == buf + GUARD_LEN + buf_len );
377
378        TEST_ASSERT( memcmp( p, asn1->x, asn1->len ) == 0 );
379
380        /* Read back with mbedtls_asn1_get_len() to check */
381        ret = mbedtls_asn1_get_len( &p, buf + GUARD_LEN + buf_len, &read_len );
382
383        if( len == 0 )
384        {
385            TEST_ASSERT( ret == 0 );
386        }
387        else
388        {
389            /* Return will be MBEDTLS_ERR_ASN1_OUT_OF_DATA because the rest of
390             * the buffer is missing
391             */
392            TEST_ASSERT( ret == MBEDTLS_ERR_ASN1_OUT_OF_DATA );
393        }
394        TEST_ASSERT( read_len == (size_t) len );
395        TEST_ASSERT( p == buf + GUARD_LEN + buf_len );
396    }
397}
398/* END_CASE */
399
400/* BEGIN_CASE */
401void test_asn1_write_bitstrings( data_t *bitstring, int bits,
402                                 data_t *expected, int is_named )
403{
404    generic_write_data_t data = { NULL, NULL, NULL, NULL, 0 };
405    int ret;
406    int ( *func )( unsigned char **p, const unsigned char *start,
407                   const unsigned char *buf, size_t bits ) =
408        ( is_named ? mbedtls_asn1_write_named_bitstring :
409          mbedtls_asn1_write_bitstring );
410#if defined(MBEDTLS_ASN1_PARSE_C)
411    unsigned char *masked_bitstring = NULL;
412#endif /* MBEDTLS_ASN1_PARSE_C */
413
414    /* The API expects `bitstring->x` to contain `bits` bits. */
415    size_t byte_length = ( bits + 7 ) / 8;
416    TEST_ASSERT( bitstring->len >= byte_length );
417
418#if defined(MBEDTLS_ASN1_PARSE_C)
419    ASSERT_ALLOC( masked_bitstring, byte_length );
420    if( byte_length != 0 )
421    {
422        memcpy( masked_bitstring, bitstring->x, byte_length );
423        if( bits % 8 != 0 )
424            masked_bitstring[byte_length - 1] &= ~( 0xff >> ( bits % 8 ) );
425    }
426    size_t value_bits = bits;
427    if( is_named )
428    {
429        /* In a named bit string, all trailing 0 bits are removed. */
430        while( byte_length > 0 && masked_bitstring[byte_length - 1] == 0 )
431            --byte_length;
432        value_bits = 8 * byte_length;
433        if( byte_length > 0 )
434        {
435            unsigned char last_byte = masked_bitstring[byte_length - 1];
436            for( unsigned b = 1; b < 0xff && ( last_byte & b ) == 0; b <<= 1 )
437                --value_bits;
438        }
439    }
440#endif /* MBEDTLS_ASN1_PARSE_C */
441
442    for( data.size = 0; data.size <= expected->len + 1; data.size++ )
443    {
444        if( ! generic_write_start_step( &data ) )
445            goto exit;
446        ret = ( *func )( &data.p, data.start, bitstring->x, bits );
447        if( ! generic_write_finish_step( &data, expected, ret ) )
448            goto exit;
449#if defined(MBEDTLS_ASN1_PARSE_C)
450        if( ret >= 0 )
451        {
452            mbedtls_asn1_bitstring read = {0, 0, NULL};
453            TEST_EQUAL( mbedtls_asn1_get_bitstring( &data.p, data.end,
454                                                    &read ), 0 );
455            ASSERT_COMPARE( read.p, read.len,
456                            masked_bitstring, byte_length );
457            TEST_EQUAL( read.unused_bits, 8 * byte_length - value_bits );
458        }
459#endif /* MBEDTLS_ASN1_PARSE_C */
460    }
461
462exit:
463    mbedtls_free( data.output );
464#if defined(MBEDTLS_ASN1_PARSE_C)
465    mbedtls_free( masked_bitstring );
466#endif /* MBEDTLS_ASN1_PARSE_C */
467}
468/* END_CASE */
469
470/* BEGIN_CASE */
471void store_named_data_find( data_t *oid0, data_t *oid1,
472                            data_t *oid2, data_t *oid3,
473                            data_t *needle, int from, int position )
474{
475    data_t *oid[4] = {oid0, oid1, oid2, oid3};
476    mbedtls_asn1_named_data nd[] ={
477        { {0x06, 0, NULL}, {0, 0, NULL}, NULL, 0 },
478        { {0x06, 0, NULL}, {0, 0, NULL}, NULL, 0 },
479        { {0x06, 0, NULL}, {0, 0, NULL}, NULL, 0 },
480        { {0x06, 0, NULL}, {0, 0, NULL}, NULL, 0 },
481    };
482    mbedtls_asn1_named_data *pointers[ARRAY_LENGTH( nd ) + 1];
483    size_t i;
484    mbedtls_asn1_named_data *head = NULL;
485    mbedtls_asn1_named_data *found = NULL;
486
487    for( i = 0; i < ARRAY_LENGTH( nd ); i++ )
488        pointers[i] = &nd[i];
489    pointers[ARRAY_LENGTH( nd )] = NULL;
490    for( i = 0; i < ARRAY_LENGTH( nd ); i++ )
491    {
492        ASSERT_ALLOC( nd[i].oid.p, oid[i]->len );
493        memcpy( nd[i].oid.p, oid[i]->x, oid[i]->len );
494        nd[i].oid.len = oid[i]->len;
495        nd[i].next = pointers[i+1];
496    }
497
498    head = pointers[from];
499    found = mbedtls_asn1_store_named_data( &head,
500                                           (const char *) needle->x,
501                                           needle->len,
502                                           NULL, 0 );
503
504    /* In any case, the existing list structure must be unchanged. */
505    for( i = 0; i < ARRAY_LENGTH( nd ); i++ )
506        TEST_ASSERT( nd[i].next == pointers[i+1] );
507
508    if( position >= 0 )
509    {
510        /* position should have been found and modified. */
511        TEST_ASSERT( head == pointers[from] );
512        TEST_ASSERT( found == pointers[position] );
513    }
514    else
515    {
516        /* A new entry should have been created. */
517        TEST_ASSERT( found == head );
518        TEST_ASSERT( head->next == pointers[from] );
519        for( i = 0; i < ARRAY_LENGTH( nd ); i++ )
520            TEST_ASSERT( found != &nd[i] );
521    }
522
523exit:
524    if( found != NULL && found == head && found != pointers[from] )
525    {
526        mbedtls_free( found->oid.p );
527        mbedtls_free( found );
528    }
529    for( i = 0; i < ARRAY_LENGTH( nd ); i++ )
530        mbedtls_free( nd[i].oid.p );
531}
532/* END_CASE */
533
534/* BEGIN_CASE */
535void store_named_data_val_found( int old_len, int new_len )
536{
537    mbedtls_asn1_named_data nd =
538        { {0x06, 3, (unsigned char *) "OID"}, {0, 0, NULL}, NULL, 0 };
539    mbedtls_asn1_named_data *head = &nd;
540    mbedtls_asn1_named_data *found = NULL;
541    unsigned char *old_val = NULL;
542    unsigned char *new_val = (unsigned char *) "new value";
543
544    if( old_len != 0 )
545    {
546        ASSERT_ALLOC( nd.val.p, (size_t) old_len );
547        old_val = nd.val.p;
548        nd.val.len = old_len;
549        memset( old_val, 'x', old_len );
550    }
551    if( new_len <= 0 )
552    {
553        new_len = - new_len;
554        new_val = NULL;
555    }
556
557    found = mbedtls_asn1_store_named_data( &head, "OID", 3,
558                                           new_val, new_len );
559    TEST_ASSERT( head == &nd );
560    TEST_ASSERT( found == head );
561
562    if( new_val != NULL)
563        ASSERT_COMPARE( found->val.p, found->val.len,
564                        new_val, (size_t) new_len );
565    if( new_len == 0)
566        TEST_ASSERT( found->val.p == NULL );
567    else if( new_len == old_len )
568        TEST_ASSERT( found->val.p == old_val );
569    else
570        TEST_ASSERT( found->val.p != old_val );
571
572exit:
573    mbedtls_free( nd.val.p );
574}
575/* END_CASE */
576
577/* BEGIN_CASE */
578void store_named_data_val_new( int new_len, int set_new_val )
579{
580    mbedtls_asn1_named_data *head = NULL;
581    mbedtls_asn1_named_data *found = NULL;
582    const unsigned char *oid = (unsigned char *) "OID";
583    size_t oid_len = strlen( (const char *) oid );
584    const unsigned char *new_val = (unsigned char *) "new value";
585
586    if( set_new_val == 0 )
587        new_val = NULL;
588
589    found = mbedtls_asn1_store_named_data( &head,
590                                           (const char *) oid, oid_len,
591                                           new_val, (size_t) new_len );
592    TEST_ASSERT( found != NULL );
593    TEST_ASSERT( found == head );
594    TEST_ASSERT( found->oid.p != oid );
595    ASSERT_COMPARE( found->oid.p, found->oid.len, oid, oid_len );
596    if( new_len == 0 )
597        TEST_ASSERT( found->val.p == NULL );
598    else if( new_val == NULL )
599        TEST_ASSERT( found->val.p != NULL );
600    else
601    {
602        TEST_ASSERT( found->val.p != new_val );
603        ASSERT_COMPARE( found->val.p, found->val.len,
604                        new_val, (size_t) new_len );
605    }
606
607exit:
608    if( found != NULL )
609    {
610        mbedtls_free( found->oid.p );
611        mbedtls_free( found->val.p );
612    }
613    mbedtls_free( found );
614}
615/* END_CASE */
616