Skip to content

Commit c527796

Browse files
Merge pull request #6392 from davidhorstmann-arm/2.28-fix-x509-get-name-cleanup
[Backport 2.28] Fix `mbedtls_x509_get_name()` cleanup
2 parents 9abd098 + 6c4226c commit c527796

File tree

4 files changed

+116
-4
lines changed

4 files changed

+116
-4
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Bugfix
2+
* Fix memory leak in ssl_parse_certificate_request() caused by
3+
mbedtls_x509_get_name() not freeing allocated objects in case of error.
4+
Change mbedtls_x509_get_name() to clean up allocated objects on error.

library/x509.c

+37-4
Original file line numberDiff line numberDiff line change
@@ -415,13 +415,20 @@ static int x509_get_attr_type_value( unsigned char **p,
415415
* For the general case we still use a flat list, but we mark elements of the
416416
* same set so that they are "merged" together in the functions that consume
417417
* this list, eg mbedtls_x509_dn_gets().
418+
*
419+
* On success, this function may allocate a linked list starting at cur->next
420+
* that must later be free'd by the caller using mbedtls_free(). In error
421+
* cases, this function frees all allocated memory internally and the caller
422+
* has no freeing responsibilities.
418423
*/
419424
int mbedtls_x509_get_name( unsigned char **p, const unsigned char *end,
420425
mbedtls_x509_name *cur )
421426
{
422427
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
423428
size_t set_len;
424429
const unsigned char *end_set;
430+
mbedtls_x509_name *head = cur;
431+
mbedtls_x509_name *prev, *allocated;
425432

426433
/* don't use recursion, we'd risk stack overflow if not optimized */
427434
while( 1 )
@@ -431,14 +438,17 @@ int mbedtls_x509_get_name( unsigned char **p, const unsigned char *end,
431438
*/
432439
if( ( ret = mbedtls_asn1_get_tag( p, end, &set_len,
433440
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET ) ) != 0 )
434-
return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_NAME, ret ) );
441+
{
442+
ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_NAME, ret );
443+
goto error;
444+
}
435445

436446
end_set = *p + set_len;
437447

438448
while( 1 )
439449
{
440450
if( ( ret = x509_get_attr_type_value( p, end_set, cur ) ) != 0 )
441-
return( ret );
451+
goto error;
442452

443453
if( *p == end_set )
444454
break;
@@ -449,7 +459,10 @@ int mbedtls_x509_get_name( unsigned char **p, const unsigned char *end,
449459
cur->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_name ) );
450460

451461
if( cur->next == NULL )
452-
return( MBEDTLS_ERR_X509_ALLOC_FAILED );
462+
{
463+
ret = MBEDTLS_ERR_X509_ALLOC_FAILED;
464+
goto error;
465+
}
453466

454467
cur = cur->next;
455468
}
@@ -463,10 +476,30 @@ int mbedtls_x509_get_name( unsigned char **p, const unsigned char *end,
463476
cur->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_name ) );
464477

465478
if( cur->next == NULL )
466-
return( MBEDTLS_ERR_X509_ALLOC_FAILED );
479+
{
480+
ret = MBEDTLS_ERR_X509_ALLOC_FAILED;
481+
goto error;
482+
}
467483

468484
cur = cur->next;
469485
}
486+
487+
error:
488+
/* Skip the first element as we did not allocate it */
489+
allocated = head->next;
490+
491+
while( allocated != NULL )
492+
{
493+
prev = allocated;
494+
allocated = allocated->next;
495+
496+
mbedtls_platform_zeroize( prev, sizeof( *prev ) );
497+
mbedtls_free( prev );
498+
}
499+
500+
mbedtls_platform_zeroize( head, sizeof( *head ) );
501+
502+
return( ret );
470503
}
471504

472505
static int x509_parse_int( unsigned char **p, size_t n, int *res )

tests/suites/test_suite_x509parse.data

+40
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,46 @@ X509 Get Modified DN #5 Name exactly 255 bytes, ending with comma requiring esca
427427
depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_SHA1_C
428428
mbedtls_x509_dn_gets_subject_replace:"data_files/server1.crt":"12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234,":"":MBEDTLS_ERR_X509_BUFFER_TOO_SMALL
429429

430+
# Parse the following valid DN:
431+
#
432+
# 31 0B <- Set of
433+
# 30 09 <- Sequence of
434+
# 06 03 55 04 06 <- OID 2.5.4.6 countryName (C)
435+
# 13 02 4E 4C <- PrintableString "NL"
436+
# 31 11 <- Set of
437+
# 30 0F <- Sequence of
438+
# 06 03 55 04 0A <- OID 2.5.4.10 organizationName (O)
439+
# 0C 08 50 6F 6C 61 72 53 53 4C <- UTF8String "PolarSSL"
440+
# 31 19 <- Set of
441+
# 30 17 <- Sequence of
442+
# 06 03 55 04 03 <- OID 2.5.4.3 commonName (CN)
443+
# 0C 10 50 6F 6C 61 72 53 53 4C 20 54 65 73 74 20 43 41 <- UTF8String "PolarSSL Test CA"
444+
#
445+
X509 Get Name Valid DN
446+
mbedtls_x509_get_name:"310B3009060355040613024E4C3111300F060355040A0C08506F6C617253534C3119301706035504030C10506F6C617253534C2054657374204341":0
447+
448+
# Parse the following corrupted DN:
449+
#
450+
# 31 0B <- Set of
451+
# 30 09 <- Sequence of
452+
# 06 03 55 04 06 <- OID 2.5.4.6 countryName (C)
453+
# 13 02 4E 4C <- PrintableString "NL"
454+
# 31 11 <- Set of
455+
# 30 0F <- Sequence of
456+
# 06 03 55 04 0A <- OID 2.5.4.10 organizationName (O)
457+
# 0C 08 50 6F 6C 61 72 53 53 4C <- UTF8String "PolarSSL"
458+
# 30 19 <- Sequence of (corrupted)
459+
# 30 17 <- Sequence of
460+
# 06 03 55 04 03 <- OID 2.5.4.3 commonName (CN)
461+
# 0C 10 50 6F 6C 61 72 53 53 4C 20 54 65 73 74 20 43 41 <- UTF8String "PolarSSL Test CA"
462+
#
463+
# The third 'Set of' is corrupted to instead be a 'Sequence of', causing an
464+
# error and forcing mbedtls_x509_get_name() to clean up the names it has
465+
# already allocated.
466+
#
467+
X509 Get Name Corrupted DN Mem Leak
468+
mbedtls_x509_get_name:"310B3009060355040613024E4C3111300F060355040A0C08506F6C617253534C3019301706035504030C10506F6C617253534C2054657374204341":MBEDTLS_ERR_X509_INVALID_NAME + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG
469+
430470
X509 Time Expired #1
431471
depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_HAVE_TIME_DATE:MBEDTLS_SHA1_C
432472
mbedtls_x509_time_is_past:"data_files/server1.crt":"valid_from":1

tests/suites/test_suite_x509parse.function

+35
Original file line numberDiff line numberDiff line change
@@ -799,6 +799,41 @@ exit:
799799
}
800800
/* END_CASE */
801801

802+
/* BEGIN_CASE depends_on:MBEDTLS_X509_CRT_PARSE_C */
803+
void mbedtls_x509_get_name( char * rdn_sequence, int exp_ret )
804+
{
805+
unsigned char *name;
806+
unsigned char *p;
807+
size_t name_len;
808+
mbedtls_x509_name head;
809+
mbedtls_x509_name *allocated, *prev;
810+
int ret;
811+
812+
memset( &head, 0, sizeof( head ) );
813+
814+
name = mbedtls_test_unhexify_alloc( rdn_sequence, &name_len );
815+
p = name;
816+
817+
ret = mbedtls_x509_get_name( &p, ( name + name_len ), &head );
818+
if( ret == 0 )
819+
{
820+
allocated = head.next;
821+
822+
while( allocated != NULL )
823+
{
824+
prev = allocated;
825+
allocated = allocated->next;
826+
827+
mbedtls_free( prev );
828+
}
829+
}
830+
831+
TEST_EQUAL( ret, exp_ret );
832+
833+
mbedtls_free( name );
834+
}
835+
/* END_CASE */
836+
802837
/* BEGIN_CASE depends_on:MBEDTLS_FS_IO:MBEDTLS_X509_CRT_PARSE_C */
803838
void mbedtls_x509_time_is_past( char * crt_file, char * entity, int result )
804839
{

0 commit comments

Comments
 (0)