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, ¶ms ), 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