blob: 16194dcd66978d9658a95570f56d52b56d742230 [file] [log] [blame]
Manuel Pégourié-Gonnard36178ff2014-05-29 14:26:03 +02001/* BEGIN_HEADER */
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +00002#include "mbedtls/asn1write.h"
Manuel Pégourié-Gonnard36178ff2014-05-29 14:26:03 +02003
4#define GUARD_LEN 4
5#define GUARD_VAL 0x2a
Gilles Peskine3a032c32019-03-01 18:13:36 +01006
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{
Chris Jones9634bb12021-01-20 15:56:42 +000018 mbedtls_test_set_step( data->size );
Gilles Peskine3a032c32019-03-01 18:13:36 +010019 ASSERT_ALLOC( data->output, data->size == 0 ? 1 : data->size );
20 data->end = data->output + data->size;
21 data->p = data->end;
22 data->start = data->end - data->size;
23 return( 1 );
24exit:
25 return( 0 );
26}
27
28int generic_write_finish_step( generic_write_data_t *data,
29 const data_t *expected, int ret )
30{
31 int ok = 0;
32
33 if( data->size < expected->len )
34 {
35 TEST_EQUAL( ret, MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
36 }
37 else
38 {
39 TEST_EQUAL( ret, data->end - data->p );
40 TEST_ASSERT( data->p >= data->start );
41 TEST_ASSERT( data->p <= data->end );
42 ASSERT_COMPARE( data->p, (size_t)( data->end - data->p ),
43 expected->x, expected->len );
44 }
45 ok = 1;
46
47exit:
48 mbedtls_free( data->output );
49 data->output = NULL;
50 return( ok );
51}
52
Manuel Pégourié-Gonnard36178ff2014-05-29 14:26:03 +020053/* END_HEADER */
54
55/* BEGIN_DEPENDENCIES
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020056 * depends_on:MBEDTLS_ASN1_WRITE_C
Manuel Pégourié-Gonnard36178ff2014-05-29 14:26:03 +020057 * END_DEPENDENCIES
58 */
59
60/* BEGIN_CASE */
Gilles Peskine9311cf52019-03-01 20:05:05 +010061void mbedtls_asn1_write_null( data_t *expected )
62{
63 generic_write_data_t data = { NULL, NULL, NULL, NULL, 0 };
64 int ret;
65
Gilles Peskine2c2730a2022-06-10 20:15:44 +020066 for( data.size = 0; data.size <= expected->len + 1; data.size++ )
Gilles Peskine9311cf52019-03-01 20:05:05 +010067 {
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 }
74
75exit:
76 mbedtls_free( data.output );
77}
78/* END_CASE */
79
80/* BEGIN_CASE */
Gilles Peskine3a032c32019-03-01 18:13:36 +010081void mbedtls_asn1_write_bool( int val, data_t *expected )
82{
83 generic_write_data_t data = { NULL, NULL, NULL, NULL, 0 };
84 int ret;
85
Gilles Peskine2c2730a2022-06-10 20:15:44 +020086 for( data.size = 0; data.size <= expected->len + 1; data.size++ )
Gilles Peskine3a032c32019-03-01 18:13:36 +010087 {
88 if( ! generic_write_start_step( &data ) )
89 goto exit;
90 ret = mbedtls_asn1_write_bool( &data.p, data.start, val );
91 if( ! generic_write_finish_step( &data, expected, ret ) )
92 goto exit;
93 }
94
95exit:
96 mbedtls_free( data.output );
97}
98/* END_CASE */
99
100/* BEGIN_CASE */
101void mbedtls_asn1_write_int( int val, data_t *expected )
102{
103 generic_write_data_t data = { NULL, NULL, NULL, NULL, 0 };
104 int ret;
105
Gilles Peskine2c2730a2022-06-10 20:15:44 +0200106 for( data.size = 0; data.size <= expected->len + 1; data.size++ )
Gilles Peskine3a032c32019-03-01 18:13:36 +0100107 {
108 if( ! generic_write_start_step( &data ) )
109 goto exit;
110 ret = mbedtls_asn1_write_int( &data.p, data.start, val );
111 if( ! generic_write_finish_step( &data, expected, ret ) )
112 goto exit;
113 }
114
115exit:
116 mbedtls_free( data.output );
117}
118/* END_CASE */
119
Mykhailo Sopiha6af7bf92019-10-31 15:55:16 +0200120
121/* BEGIN_CASE */
122void mbedtls_asn1_write_enum( int val, data_t *expected )
123{
124 generic_write_data_t data = { NULL, NULL, NULL, NULL, 0 };
125 int ret;
126
Gilles Peskine2c2730a2022-06-10 20:15:44 +0200127 for( data.size = 0; data.size <= expected->len + 1; data.size++ )
Mykhailo Sopiha6af7bf92019-10-31 15:55:16 +0200128 {
129 if( ! generic_write_start_step( &data ) )
130 goto exit;
131 ret = mbedtls_asn1_write_enum( &data.p, data.start, val );
132 if( ! generic_write_finish_step( &data, expected, ret ) )
133 goto exit;
134 }
135
136exit:
137 mbedtls_free( data.output );
138}
139/* END_CASE */
140
Gilles Peskine3a032c32019-03-01 18:13:36 +0100141/* BEGIN_CASE depends_on:MBEDTLS_BIGNUM_C */
142void mbedtls_asn1_write_mpi( data_t *val, data_t *expected )
143{
144 generic_write_data_t data = { NULL, NULL, NULL, NULL, 0 };
145 mbedtls_mpi mpi;
146 int ret;
147
148 mbedtls_mpi_init( &mpi );
149 TEST_ASSERT( mbedtls_mpi_read_binary( &mpi, val->x, val->len ) == 0 );
150
Gilles Peskine2c2730a2022-06-10 20:15:44 +0200151 for( data.size = 0; data.size <= expected->len + 1; data.size++ )
Gilles Peskine3a032c32019-03-01 18:13:36 +0100152 {
153 if( ! generic_write_start_step( &data ) )
154 goto exit;
155 ret = mbedtls_asn1_write_mpi( &data.p, data.start, &mpi );
156 if( ! generic_write_finish_step( &data, expected, ret ) )
157 goto exit;
Gilles Peskine3f37dca2019-03-01 19:30:20 +0100158 if( expected->len > 10 && data.size == 8 )
159 data.size = expected->len - 2;
Gilles Peskine3a032c32019-03-01 18:13:36 +0100160 }
161
162exit:
163 mbedtls_mpi_free( &mpi );
164 mbedtls_free( data.output );
165}
166/* END_CASE */
167
168/* BEGIN_CASE */
Gilles Peskine3f37dca2019-03-01 19:30:20 +0100169void mbedtls_asn1_write_string( int tag, data_t *content, data_t *expected )
Manuel Pégourié-Gonnard36178ff2014-05-29 14:26:03 +0200170{
Gilles Peskine3f37dca2019-03-01 19:30:20 +0100171 generic_write_data_t data = { NULL, NULL, NULL, NULL, 0 };
Manuel Pégourié-Gonnard36178ff2014-05-29 14:26:03 +0200172 int ret;
Manuel Pégourié-Gonnard36178ff2014-05-29 14:26:03 +0200173
Gilles Peskine2c2730a2022-06-10 20:15:44 +0200174 for( data.size = 0; data.size <= expected->len + 1; data.size++ )
Manuel Pégourié-Gonnard36178ff2014-05-29 14:26:03 +0200175 {
Gilles Peskine3f37dca2019-03-01 19:30:20 +0100176 if( ! generic_write_start_step( &data ) )
177 goto exit;
178 switch( tag )
179 {
180 case MBEDTLS_ASN1_OCTET_STRING:
181 ret = mbedtls_asn1_write_octet_string(
182 &data.p, data.start, content->x, content->len );
183 break;
Gilles Peskine9311cf52019-03-01 20:05:05 +0100184 case MBEDTLS_ASN1_OID:
185 ret = mbedtls_asn1_write_oid(
186 &data.p, data.start,
187 (const char *) content->x, content->len );
188 break;
Gilles Peskine3f37dca2019-03-01 19:30:20 +0100189 case MBEDTLS_ASN1_UTF8_STRING:
190 ret = mbedtls_asn1_write_utf8_string(
191 &data.p, data.start,
192 (const char *) content->x, content->len );
193 break;
194 case MBEDTLS_ASN1_PRINTABLE_STRING:
195 ret = mbedtls_asn1_write_printable_string(
196 &data.p, data.start,
197 (const char *) content->x, content->len );
198 break;
199 case MBEDTLS_ASN1_IA5_STRING:
200 ret = mbedtls_asn1_write_ia5_string(
201 &data.p, data.start,
202 (const char *) content->x, content->len );
203 break;
204 default:
205 ret = mbedtls_asn1_write_tagged_string(
206 &data.p, data.start, tag,
207 (const char *) content->x, content->len );
208 }
209 if( ! generic_write_finish_step( &data, expected, ret ) )
210 goto exit;
211 if( expected->len > 10 && data.size == 8 )
212 data.size = expected->len - 2;
Manuel Pégourié-Gonnard36178ff2014-05-29 14:26:03 +0200213 }
214
Gilles Peskine3f37dca2019-03-01 19:30:20 +0100215exit:
216 mbedtls_free( data.output );
Manuel Pégourié-Gonnardc22bb492014-05-29 17:16:45 +0200217}
218/* END_CASE */
Paul Bakkere325db92016-07-14 10:27:36 +0100219
Gilles Peskine9311cf52019-03-01 20:05:05 +0100220/* BEGIN_CASE */
221void mbedtls_asn1_write_algorithm_identifier( data_t *oid,
222 int par_len,
223 data_t *expected )
224{
225 generic_write_data_t data = { NULL, NULL, NULL, NULL, 0 };
226 int ret;
227
Gilles Peskine2c2730a2022-06-10 20:15:44 +0200228 for( data.size = 0; data.size <= expected->len + 1; data.size++ )
Gilles Peskine9311cf52019-03-01 20:05:05 +0100229 {
230 if( ! generic_write_start_step( &data ) )
231 goto exit;
232 ret = mbedtls_asn1_write_algorithm_identifier(
233 &data.p, data.start,
234 (const char *) oid->x, oid->len, par_len );
235 /* If params_len != 0, mbedtls_asn1_write_algorithm_identifier()
236 * assumes that the parameters are already present in the buffer
237 * and returns a length that accounts for this, but our test
238 * data omits the parameters. */
239 if( ret >= 0 )
240 ret -= par_len;
241 if( ! generic_write_finish_step( &data, expected, ret ) )
242 goto exit;
243 }
244
245exit:
246 mbedtls_free( data.output );
247}
248/* END_CASE */
249
Gilles Peskine91d8d022019-03-01 19:34:24 +0100250/* BEGIN_CASE depends_on:MBEDTLS_ASN1_PARSE_C */
Azim Khan5fcca462018-06-29 11:05:32 +0100251void mbedtls_asn1_write_len( int len, data_t * asn1, int buf_len,
Azim Khand30ca132017-06-09 04:32:58 +0100252 int result )
Paul Bakkere325db92016-07-14 10:27:36 +0100253{
254 int ret;
255 unsigned char buf[150];
Paul Bakkere325db92016-07-14 10:27:36 +0100256 unsigned char *p;
Azim Khan90791702017-05-30 00:57:11 +0100257 size_t i;
258 size_t read_len;
Paul Bakkere325db92016-07-14 10:27:36 +0100259
260 memset( buf, GUARD_VAL, sizeof( buf ) );
Paul Bakkere325db92016-07-14 10:27:36 +0100261
Paul Bakker58bfb832016-07-14 11:02:31 +0100262 p = buf + GUARD_LEN + buf_len;
Paul Bakkere325db92016-07-14 10:27:36 +0100263
264 ret = mbedtls_asn1_write_len( &p, buf + GUARD_LEN, (size_t) len );
265
266 TEST_ASSERT( ret == result );
267
268 /* Check for buffer overwrite on both sides */
269 for( i = 0; i < GUARD_LEN; i++ )
270 {
271 TEST_ASSERT( buf[i] == GUARD_VAL );
Paul Bakker58bfb832016-07-14 11:02:31 +0100272 TEST_ASSERT( buf[GUARD_LEN + buf_len + i] == GUARD_VAL );
Paul Bakkere325db92016-07-14 10:27:36 +0100273 }
274
275 if( result >= 0 )
276 {
Azim Khand30ca132017-06-09 04:32:58 +0100277 TEST_ASSERT( p + asn1->len == buf + GUARD_LEN + buf_len );
Paul Bakkere325db92016-07-14 10:27:36 +0100278
Azim Khand30ca132017-06-09 04:32:58 +0100279 TEST_ASSERT( memcmp( p, asn1->x, asn1->len ) == 0 );
Paul Bakker5e8b77c2016-07-14 11:14:54 +0100280
281 /* Read back with mbedtls_asn1_get_len() to check */
282 ret = mbedtls_asn1_get_len( &p, buf + GUARD_LEN + buf_len, &read_len );
283
284 if( len == 0 )
285 {
286 TEST_ASSERT( ret == 0 );
287 }
288 else
289 {
290 /* Return will be MBEDTLS_ERR_ASN1_OUT_OF_DATA because the rest of
291 * the buffer is missing
292 */
293 TEST_ASSERT( ret == MBEDTLS_ERR_ASN1_OUT_OF_DATA );
294 }
295 TEST_ASSERT( read_len == (size_t) len );
296 TEST_ASSERT( p == buf + GUARD_LEN + buf_len );
Paul Bakkere325db92016-07-14 10:27:36 +0100297 }
298}
299/* END_CASE */
Andres Amaya Garcia5d261632018-09-26 10:51:16 +0100300
301/* BEGIN_CASE */
302void test_asn1_write_bitstrings( data_t *bitstring, int bits,
Gilles Peskine3f37dca2019-03-01 19:30:20 +0100303 data_t *expected, int is_named )
Andres Amaya Garcia5d261632018-09-26 10:51:16 +0100304{
Gilles Peskine3f37dca2019-03-01 19:30:20 +0100305 generic_write_data_t data = { NULL, NULL, NULL, NULL, 0 };
Andres Amaya Garcia5d261632018-09-26 10:51:16 +0100306 int ret;
Mateusz Starzyk4e300d02021-01-27 15:37:12 +0100307 int ( *func )( unsigned char **p, const unsigned char *start,
Gilles Peskine3f37dca2019-03-01 19:30:20 +0100308 const unsigned char *buf, size_t bits ) =
309 ( is_named ? mbedtls_asn1_write_named_bitstring :
310 mbedtls_asn1_write_bitstring );
Andres Amaya Garcia5d261632018-09-26 10:51:16 +0100311
Gilles Peskine2c2730a2022-06-10 20:15:44 +0200312 for( data.size = 0; data.size <= expected->len + 1; data.size++ )
Andres Amaya Garcia5d261632018-09-26 10:51:16 +0100313 {
Gilles Peskine3f37dca2019-03-01 19:30:20 +0100314 if( ! generic_write_start_step( &data ) )
315 goto exit;
316 ret = ( *func )( &data.p, data.start, bitstring->x, bits );
317 if( ! generic_write_finish_step( &data, expected, ret ) )
318 goto exit;
Andres Amaya Garcia5d261632018-09-26 10:51:16 +0100319 }
320
Gilles Peskine3f37dca2019-03-01 19:30:20 +0100321exit:
322 mbedtls_free( data.output );
Andres Amaya Garcia5d261632018-09-26 10:51:16 +0100323}
324/* END_CASE */
Gilles Peskinea9023032019-03-01 23:26:05 +0100325
326/* BEGIN_CASE */
327void store_named_data_find( data_t *oid0, data_t *oid1,
328 data_t *oid2, data_t *oid3,
329 data_t *needle, int from, int position )
330{
331 data_t *oid[4] = {oid0, oid1, oid2, oid3};
332 mbedtls_asn1_named_data nd[] ={
333 { {0x06, 0, NULL}, {0, 0, NULL}, NULL, 0 },
334 { {0x06, 0, NULL}, {0, 0, NULL}, NULL, 0 },
335 { {0x06, 0, NULL}, {0, 0, NULL}, NULL, 0 },
336 { {0x06, 0, NULL}, {0, 0, NULL}, NULL, 0 },
337 };
338 mbedtls_asn1_named_data *pointers[ARRAY_LENGTH( nd ) + 1];
339 size_t i;
340 mbedtls_asn1_named_data *head = NULL;
341 mbedtls_asn1_named_data *found = NULL;
342
343 for( i = 0; i < ARRAY_LENGTH( nd ); i++ )
344 pointers[i] = &nd[i];
345 pointers[ARRAY_LENGTH( nd )] = NULL;
346 for( i = 0; i < ARRAY_LENGTH( nd ); i++ )
347 {
348 ASSERT_ALLOC( nd[i].oid.p, oid[i]->len );
349 memcpy( nd[i].oid.p, oid[i]->x, oid[i]->len );
350 nd[i].oid.len = oid[i]->len;
351 nd[i].next = pointers[i+1];
352 }
353
354 head = pointers[from];
355 found = mbedtls_asn1_store_named_data( &head,
356 (const char *) needle->x,
357 needle->len,
358 NULL, 0 );
359
360 /* In any case, the existing list structure must be unchanged. */
361 for( i = 0; i < ARRAY_LENGTH( nd ); i++ )
362 TEST_ASSERT( nd[i].next == pointers[i+1] );
363
364 if( position >= 0 )
365 {
366 /* position should have been found and modified. */
367 TEST_ASSERT( head == pointers[from] );
368 TEST_ASSERT( found == pointers[position] );
369 }
370 else
371 {
372 /* A new entry should have been created. */
373 TEST_ASSERT( found == head );
374 TEST_ASSERT( head->next == pointers[from] );
375 for( i = 0; i < ARRAY_LENGTH( nd ); i++ )
376 TEST_ASSERT( found != &nd[i] );
377 }
378
379exit:
380 if( found != NULL && found == head && found != pointers[from] )
381 {
382 mbedtls_free( found->oid.p );
383 mbedtls_free( found );
384 }
385 for( i = 0; i < ARRAY_LENGTH( nd ); i++ )
386 mbedtls_free( nd[i].oid.p );
387}
388/* END_CASE */
389
390/* BEGIN_CASE */
391void store_named_data_val_found( int old_len, int new_len )
392{
393 mbedtls_asn1_named_data nd =
394 { {0x06, 3, (unsigned char *) "OID"}, {0, 0, NULL}, NULL, 0 };
395 mbedtls_asn1_named_data *head = &nd;
396 mbedtls_asn1_named_data *found = NULL;
397 unsigned char *old_val = NULL;
398 unsigned char *new_val = (unsigned char *) "new value";
399
400 if( old_len != 0 )
401 {
402 ASSERT_ALLOC( nd.val.p, (size_t) old_len );
403 old_val = nd.val.p;
404 nd.val.len = old_len;
405 memset( old_val, 'x', old_len );
406 }
407 if( new_len <= 0 )
408 {
409 new_len = - new_len;
410 new_val = NULL;
411 }
412
413 found = mbedtls_asn1_store_named_data( &head, "OID", 3,
414 new_val, new_len );
415 TEST_ASSERT( head == &nd );
416 TEST_ASSERT( found == head );
417
418 if( new_val != NULL)
419 ASSERT_COMPARE( found->val.p, found->val.len,
420 new_val, (size_t) new_len );
421 if( new_len == 0)
422 TEST_ASSERT( found->val.p == NULL );
423 else if( new_len == old_len )
424 TEST_ASSERT( found->val.p == old_val );
425 else
426 TEST_ASSERT( found->val.p != old_val );
427
428exit:
429 mbedtls_free( nd.val.p );
430}
431/* END_CASE */
432
433/* BEGIN_CASE */
Werner Lewise59a5312022-05-04 09:44:50 +0100434void store_named_data_val_new( int new_len, int set_new_val )
Gilles Peskinea9023032019-03-01 23:26:05 +0100435{
436 mbedtls_asn1_named_data *head = NULL;
437 mbedtls_asn1_named_data *found = NULL;
438 const unsigned char *oid = (unsigned char *) "OID";
439 size_t oid_len = strlen( (const char *) oid );
440 const unsigned char *new_val = (unsigned char *) "new value";
441
Werner Lewise59a5312022-05-04 09:44:50 +0100442 if( set_new_val == 0 )
Gilles Peskinea9023032019-03-01 23:26:05 +0100443 new_val = NULL;
Gilles Peskinea9023032019-03-01 23:26:05 +0100444
445 found = mbedtls_asn1_store_named_data( &head,
446 (const char *) oid, oid_len,
447 new_val, (size_t) new_len );
448 TEST_ASSERT( found != NULL );
449 TEST_ASSERT( found == head );
450 TEST_ASSERT( found->oid.p != oid );
451 ASSERT_COMPARE( found->oid.p, found->oid.len, oid, oid_len );
452 if( new_len == 0 )
453 TEST_ASSERT( found->val.p == NULL );
454 else if( new_val == NULL )
455 TEST_ASSERT( found->val.p != NULL );
456 else
457 {
458 TEST_ASSERT( found->val.p != new_val );
459 ASSERT_COMPARE( found->val.p, found->val.len,
460 new_val, (size_t) new_len );
461 }
462
463exit:
464 if( found != NULL )
465 {
466 mbedtls_free( found->oid.p );
467 mbedtls_free( found->val.p );
468 }
469 mbedtls_free( found );
470}
471/* END_CASE */