From 12ae27dd0e073ddca62afae953cb0b6a046e3692 Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Wed, 11 Sep 2019 14:20:09 +0100 Subject: [PATCH] ASN.1: Introduce helper function to free ASN.1 sequence --- include/mbedtls/asn1.h | 25 ++++++++++++++++++++++ library/asn1parse.c | 11 +++++++++- tests/suites/test_suite_asn1parse.function | 10 ++------- 3 files changed, 37 insertions(+), 9 deletions(-) diff --git a/include/mbedtls/asn1.h b/include/mbedtls/asn1.h index 5f15ddbe8..43ab9ae4d 100644 --- a/include/mbedtls/asn1.h +++ b/include/mbedtls/asn1.h @@ -343,6 +343,9 @@ int mbedtls_asn1_get_bitstring_null( unsigned char **p, * \brief Parses and splits an ASN.1 "SEQUENCE OF ". * Updates the pointer to immediately behind the full sequence tag. * + * This function allocates memory for the sequence elements. You can free + * the allocated memory with mbedtls_asn1_sequence_free(). + * * \note On error, this function may return a partial list in \p cur. * You must set `cur->next = NULL` before calling this function! * Otherwise it is impossible to distinguish a previously non-null @@ -384,6 +387,28 @@ int mbedtls_asn1_get_sequence_of( unsigned char **p, const unsigned char *end, mbedtls_asn1_sequence *cur, int tag ); +/** + * \brief Free a heap-allocated linked list presentation of + * an ASN.1 sequence, including the first element. + * + * There are two common ways to manage the memory used for the representation + * of a parsed ASN.1 sequence: + * - Allocate a head node `mbedtls_asn1_sequence *head` with mbedtls_calloc(). + * Pass this node as the `cur` argument to mbedtls_asn1_get_sequence_of(). + * When you have finished processing the sequence, + * call mbedtls_asn1_sequence_free() on `head`. + * - Allocate a head node `mbedtls_asn1_sequence *head` in any manner, + * for example on the stack. Make sure that `head->next == NULL`. + * Pass `head` as the `cur` argument to mbedtls_asn1_get_sequence_of(). + * When you have finished processing the sequence, + * call mbedtls_asn1_sequence_free() on `head->cur`, + * then free `head` itself in the appropriate manner. + * + * \param seq The address of the first sequence component. This may + * be \c NULL, in which case this functions returns + * immediately. + */ +void mbedtls_asn1_sequence_free( mbedtls_asn1_sequence *seq ); #if defined(MBEDTLS_BIGNUM_C) /** diff --git a/library/asn1parse.c b/library/asn1parse.c index e7e4d13f6..3105d32b3 100644 --- a/library/asn1parse.c +++ b/library/asn1parse.c @@ -269,7 +269,16 @@ int mbedtls_asn1_get_bitstring_null( unsigned char **p, const unsigned char *end return( 0 ); } - +void mbedtls_asn1_sequence_free( mbedtls_asn1_sequence *seq ) +{ + while( seq != NULL ) + { + mbedtls_asn1_sequence *next = seq->next; + mbedtls_platform_zeroize( seq, sizeof( *seq ) ); + mbedtls_free( seq ); + seq = next; + } +} /* * Parses and splits an ASN.1 "SEQUENCE OF " diff --git a/tests/suites/test_suite_asn1parse.function b/tests/suites/test_suite_asn1parse.function index f07fd409d..898f7297d 100644 --- a/tests/suites/test_suite_asn1parse.function +++ b/tests/suites/test_suite_asn1parse.function @@ -508,7 +508,7 @@ void get_sequence_of( const data_t *input, int tag, int expected_result ) { mbedtls_asn1_sequence head = { { 0, 0, NULL }, NULL }; - mbedtls_asn1_sequence *cur, *next; + mbedtls_asn1_sequence *cur; unsigned char *p = input->x; const char *rest = description; unsigned long n; @@ -549,13 +549,7 @@ void get_sequence_of( const data_t *input, int tag, } exit: - cur = head.next; - while( cur != NULL ) - { - next = cur->next; - mbedtls_free( cur ); - cur = next; - } + mbedtls_asn1_sequence_free( head.next ); } /* END_CASE */