Skip to content

Commit 3c25ddd

Browse files
author
Hanno Becker
committed
ASN.1: Add ASN.1 SEQUENCE traversal API
1 parent 155fd3b commit 3c25ddd

File tree

2 files changed

+104
-0
lines changed

2 files changed

+104
-0
lines changed

include/mbedtls/asn1.h

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,58 @@ int mbedtls_asn1_get_sequence_of( unsigned char **p,
316316
mbedtls_asn1_sequence *cur,
317317
int tag);
318318

319+
/**
320+
* \brief Traverse an ASN.1 SEQUENCE container and
321+
* call a callback for each entry.
322+
*
323+
* \warning This function is still experimental and may change
324+
* at any time.
325+
*
326+
* \param p The address of the pointer to the beginning of
327+
* the ASN.1 SEQUENCE header. This is updated to
328+
* point to the end of the ASN.1 SEQUENCE container
329+
* on a successful invocation.
330+
* \param end The end of the ASN.1 SEQUENCE container.
331+
* \param tag_must_mask A mask to be applied to the ASN.1 tags found within
332+
* the SEQUENCE before comparing to \p tag_must_value.
333+
* \param tag_must_val The required value of each ASN.1 tag found in the
334+
* SEQUENCE, after masking with \p tag_must_mask.
335+
* Mismatching tags lead to an error.
336+
* For example, a value of \c 0 for both \p tag_must_mask
337+
* and \p tag_must_val means that every tag is allowed,
338+
* while a value of \c 0xFF for \p tag_must_mask means
339+
* that \p tag_must_val is the only allowed tag.
340+
* \param tag_may_mask A mask to be applied to the ASN.1 tags found within
341+
* the SEQUENCE before comparing to \p tag_may_value.
342+
* \param tag_may_val The desired value of each ASN.1 tag found in the
343+
* SEQUENCE, after masking with \p tag_may_mask.
344+
* Mismatching tags will be silently ignored.
345+
* For example, a value of \c 0 for \p tag_may_mask and
346+
* \p tag_may_val means that any tag will be considered,
347+
* while a value of \c 0xFF for \p tag_may_mask means
348+
* that all tags with value different from \p tag_may_val
349+
* will be ignored.
350+
* \param cb The callback to trigger for each component
351+
* in the ASN.1 SEQUENCE. If the callback returns
352+
* a non-zero value, the function stops immediately,
353+
* forwarding the callback's return value.
354+
* \param ctx The context to be passed to the callback \p cb.
355+
*
356+
* \return \c 0 if successful the entire ASN.1 SEQUENCE
357+
* was traversed without parsing or callback errors.
358+
* \return A negative ASN.1 error code on a parsing failure.
359+
* \return A non-zero error code forwarded from the callback
360+
* \p cb in case the latter returns a non-zero value.
361+
*/
362+
int mbedtls_asn1_traverse_sequence_of(
363+
unsigned char **p,
364+
const unsigned char *end,
365+
uint8_t tag_must_mask, uint8_t tag_must_val,
366+
uint8_t tag_may_mask, uint8_t tag_may_val,
367+
int (*cb)( void *ctx, int tag,
368+
unsigned char* start, size_t len ),
369+
void *ctx );
370+
319371
#if defined(MBEDTLS_BIGNUM_C)
320372
/**
321373
* \brief Retrieve a MPI value from an integer ASN.1 tag.

library/asn1parse.c

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,58 @@ int mbedtls_asn1_get_bitstring( unsigned char **p, const unsigned char *end,
212212
return( 0 );
213213
}
214214

215+
/*
216+
* Traverse an ASN.1 "SEQUENCE OF <tag>"
217+
* and call a callback for each entry found.
218+
*/
219+
int mbedtls_asn1_traverse_sequence_of(
220+
unsigned char **p,
221+
const unsigned char *end,
222+
uint8_t tag_must_mask, uint8_t tag_must_val,
223+
uint8_t tag_may_mask, uint8_t tag_may_val,
224+
int (*cb)( void *ctx, int tag,
225+
unsigned char *start, size_t len ),
226+
void *ctx )
227+
{
228+
int ret;
229+
size_t len;
230+
231+
/* Get main sequence tag */
232+
if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
233+
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
234+
{
235+
return( ret );
236+
}
237+
238+
if( *p + len != end )
239+
return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
240+
241+
while( *p < end )
242+
{
243+
unsigned char const tag = *(*p)++;
244+
245+
if( ( tag & tag_must_mask ) != tag_must_val )
246+
return( MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
247+
248+
if( ( ret = mbedtls_asn1_get_len( p, end, &len ) ) != 0 )
249+
return( ret );
250+
251+
if( ( tag & tag_may_mask ) == tag_may_val )
252+
{
253+
if( cb != NULL )
254+
{
255+
ret = cb( ctx, tag, *p, len );
256+
if( ret != 0 )
257+
return( ret );
258+
}
259+
}
260+
261+
*p += len;
262+
}
263+
264+
return( 0 );
265+
}
266+
215267
/*
216268
* Get a bit string without unused bits
217269
*/

0 commit comments

Comments
 (0)