7575#define MBEDTLS_ASN1_OCTET_STRING 0x04
7676#define MBEDTLS_ASN1_NULL 0x05
7777#define MBEDTLS_ASN1_OID 0x06
78+ #define MBEDTLS_ASN1_ENUMERATED 0x0A
7879#define MBEDTLS_ASN1_UTF8_STRING 0x0C
7980#define MBEDTLS_ASN1_SEQUENCE 0x10
8081#define MBEDTLS_ASN1_SET 0x11
8990#define MBEDTLS_ASN1_CONSTRUCTED 0x20
9091#define MBEDTLS_ASN1_CONTEXT_SPECIFIC 0x80
9192
93+ /* Slightly smaller way to check if tag is a string tag
94+ * compared to canonical implementation. */
95+ #define MBEDTLS_ASN1_IS_STRING_TAG ( tag ) \
96+ ( ( tag ) < 32u && ( \
97+ ( ( 1u << ( tag ) ) & ( ( 1u << MBEDTLS_ASN1_BMP_STRING ) | \
98+ ( 1u << MBEDTLS_ASN1_UTF8_STRING ) | \
99+ ( 1u << MBEDTLS_ASN1_T61_STRING ) | \
100+ ( 1u << MBEDTLS_ASN1_IA5_STRING ) | \
101+ ( 1u << MBEDTLS_ASN1_UNIVERSAL_STRING ) | \
102+ ( 1u << MBEDTLS_ASN1_PRINTABLE_STRING ) | \
103+ ( 1u << MBEDTLS_ASN1_BIT_STRING ) ) ) != 0 ) )
104+
92105/*
93106 * Bit masks for each of the components of an ASN.1 tag as specified in
94107 * ITU X.690 (08/2015), section 8.1 "General rules for encoding",
119132 ( ( MBEDTLS_OID_SIZE(oid_str) != (oid_buf)->len ) || \
120133 memcmp( (oid_str), (oid_buf)->p, (oid_buf)->len) != 0 )
121134
135+ #define MBEDTLS_OID_CMP_RAW (oid_str , oid_buf , oid_buf_len ) \
136+ ( ( MBEDTLS_OID_SIZE(oid_str) != (oid_buf_len) ) || \
137+ memcmp( (oid_str), (oid_buf), (oid_buf_len) ) != 0 )
138+
122139#ifdef __cplusplus
123140extern "C" {
124141#endif
@@ -254,13 +271,32 @@ int mbedtls_asn1_get_bool( unsigned char **p,
254271 * a valid ASN.1 INTEGER.
255272 * \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the parsed value does
256273 * not fit in an \c int.
257- * \return An ASN.1 error code if the input does not start with
258- * a valid ASN.1 INTEGER.
259274 */
260275int mbedtls_asn1_get_int ( unsigned char * * p ,
261276 const unsigned char * end ,
262277 int * val );
263278
279+ /**
280+ * \brief Retrieve an enumerated ASN.1 tag and its value.
281+ * Updates the pointer to immediately behind the full tag.
282+ *
283+ * \param p On entry, \c *p points to the start of the ASN.1 element.
284+ * On successful completion, \c *p points to the first byte
285+ * beyond the ASN.1 element.
286+ * On error, the value of \c *p is undefined.
287+ * \param end End of data.
288+ * \param val On success, the parsed value.
289+ *
290+ * \return 0 if successful.
291+ * \return An ASN.1 error code if the input does not start with
292+ * a valid ASN.1 ENUMERATED.
293+ * \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the parsed value does
294+ * not fit in an \c int.
295+ */
296+ int mbedtls_asn1_get_enum ( unsigned char * * p ,
297+ const unsigned char * end ,
298+ int * val );
299+
264300/**
265301 * \brief Retrieve a bitstring ASN.1 tag and its value.
266302 * Updates the pointer to immediately behind the full tag.
@@ -307,6 +343,9 @@ int mbedtls_asn1_get_bitstring_null( unsigned char **p,
307343 * \brief Parses and splits an ASN.1 "SEQUENCE OF <tag>".
308344 * Updates the pointer to immediately behind the full sequence tag.
309345 *
346+ * This function allocates memory for the sequence elements. You can free
347+ * the allocated memory with mbedtls_asn1_sequence_free().
348+ *
310349 * \note On error, this function may return a partial list in \p cur.
311350 * You must set `cur->next = NULL` before calling this function!
312351 * Otherwise it is impossible to distinguish a previously non-null
@@ -340,14 +379,133 @@ int mbedtls_asn1_get_bitstring_null( unsigned char **p,
340379 * \return 0 if successful.
341380 * \return #MBEDTLS_ERR_ASN1_LENGTH_MISMATCH if the input contains
342381 * extra data after a valid SEQUENCE OF \p tag.
382+ * \return #MBEDTLS_ERR_ASN1_UNEXPECTED_TAG if the input starts with
383+ * an ASN.1 SEQUENCE in which an element has a tag that
384+ * is different from \p tag.
343385 * \return #MBEDTLS_ERR_ASN1_ALLOC_FAILED if a memory allocation failed.
344386 * \return An ASN.1 error code if the input does not start with
345- * a valid ASN.1 BIT STRING .
387+ * a valid ASN.1 SEQUENCE .
346388 */
347389int mbedtls_asn1_get_sequence_of ( unsigned char * * p ,
348390 const unsigned char * end ,
349391 mbedtls_asn1_sequence * cur ,
350392 int tag );
393+ /**
394+ * \brief Free a heap-allocated linked list presentation of
395+ * an ASN.1 sequence, including the first element.
396+ *
397+ * There are two common ways to manage the memory used for the representation
398+ * of a parsed ASN.1 sequence:
399+ * - Allocate a head node `mbedtls_asn1_sequence *head` with mbedtls_calloc().
400+ * Pass this node as the `cur` argument to mbedtls_asn1_get_sequence_of().
401+ * When you have finished processing the sequence,
402+ * call mbedtls_asn1_sequence_free() on `head`.
403+ * - Allocate a head node `mbedtls_asn1_sequence *head` in any manner,
404+ * for example on the stack. Make sure that `head->next == NULL`.
405+ * Pass `head` as the `cur` argument to mbedtls_asn1_get_sequence_of().
406+ * When you have finished processing the sequence,
407+ * call mbedtls_asn1_sequence_free() on `head->cur`,
408+ * then free `head` itself in the appropriate manner.
409+ *
410+ * \param seq The address of the first sequence component. This may
411+ * be \c NULL, in which case this functions returns
412+ * immediately.
413+ */
414+ void mbedtls_asn1_sequence_free ( mbedtls_asn1_sequence * seq );
415+
416+ /**
417+ * \brief Traverse an ASN.1 SEQUENCE container and
418+ * call a callback for each entry.
419+ *
420+ * This function checks that the input is a SEQUENCE of elements that
421+ * each have a "must" tag, and calls a callback function on the elements
422+ * that have a "may" tag.
423+ *
424+ * For example, to validate that the input is a SEQUENCE of `tag1` and call
425+ * `cb` on each element, use
426+ * ```
427+ * mbedtls_asn1_traverse_sequence_of(&p, end, 0xff, tag1, 0, 0, cb, ctx);
428+ * ```
429+ *
430+ * To validate that the input is a SEQUENCE of ANY and call `cb` on
431+ * each element, use
432+ * ```
433+ * mbedtls_asn1_traverse_sequence_of(&p, end, 0, 0, 0, 0, cb, ctx);
434+ * ```
435+ *
436+ * To validate that the input is a SEQUENCE of CHOICE {NULL, OCTET STRING}
437+ * and call `cb` on each element that is an OCTET STRING, use
438+ * ```
439+ * mbedtls_asn1_traverse_sequence_of(&p, end, 0xfe, 0x04, 0xff, 0x04, cb, ctx);
440+ * ```
441+ *
442+ * The callback is called on the elements with a "may" tag from left to
443+ * right. If the input is not a valid SEQUENCE of elements with a "must" tag,
444+ * the callback is called on the elements up to the leftmost point where
445+ * the input is invalid.
446+ *
447+ * \warning This function is still experimental and may change
448+ * at any time.
449+ *
450+ * \param p The address of the pointer to the beginning of
451+ * the ASN.1 SEQUENCE header. This is updated to
452+ * point to the end of the ASN.1 SEQUENCE container
453+ * on a successful invocation.
454+ * \param end The end of the ASN.1 SEQUENCE container.
455+ * \param tag_must_mask A mask to be applied to the ASN.1 tags found within
456+ * the SEQUENCE before comparing to \p tag_must_value.
457+ * \param tag_must_val The required value of each ASN.1 tag found in the
458+ * SEQUENCE, after masking with \p tag_must_mask.
459+ * Mismatching tags lead to an error.
460+ * For example, a value of \c 0 for both \p tag_must_mask
461+ * and \p tag_must_val means that every tag is allowed,
462+ * while a value of \c 0xFF for \p tag_must_mask means
463+ * that \p tag_must_val is the only allowed tag.
464+ * \param tag_may_mask A mask to be applied to the ASN.1 tags found within
465+ * the SEQUENCE before comparing to \p tag_may_value.
466+ * \param tag_may_val The desired value of each ASN.1 tag found in the
467+ * SEQUENCE, after masking with \p tag_may_mask.
468+ * Mismatching tags will be silently ignored.
469+ * For example, a value of \c 0 for \p tag_may_mask and
470+ * \p tag_may_val means that any tag will be considered,
471+ * while a value of \c 0xFF for \p tag_may_mask means
472+ * that all tags with value different from \p tag_may_val
473+ * will be ignored.
474+ * \param cb The callback to trigger for each component
475+ * in the ASN.1 SEQUENCE that matches \p tag_may_val.
476+ * The callback function is called with the following
477+ * parameters:
478+ * - \p ctx.
479+ * - The tag of the current element.
480+ * - A pointer to the start of the current element's
481+ * content inside the input.
482+ * - The length of the content of the current element.
483+ * If the callback returns a non-zero value,
484+ * the function stops immediately,
485+ * forwarding the callback's return value.
486+ * \param ctx The context to be passed to the callback \p cb.
487+ *
488+ * \return \c 0 if successful the entire ASN.1 SEQUENCE
489+ * was traversed without parsing or callback errors.
490+ * \return #MBEDTLS_ERR_ASN1_LENGTH_MISMATCH if the input
491+ * contains extra data after a valid SEQUENCE
492+ * of elements with an accepted tag.
493+ * \return #MBEDTLS_ERR_ASN1_UNEXPECTED_TAG if the input starts
494+ * with an ASN.1 SEQUENCE in which an element has a tag
495+ * that is not accepted.
496+ * \return An ASN.1 error code if the input does not start with
497+ * a valid ASN.1 SEQUENCE.
498+ * \return A non-zero error code forwarded from the callback
499+ * \p cb in case the latter returns a non-zero value.
500+ */
501+ int mbedtls_asn1_traverse_sequence_of (
502+ unsigned char * * p ,
503+ const unsigned char * end ,
504+ unsigned char tag_must_mask , unsigned char tag_must_val ,
505+ unsigned char tag_may_mask , unsigned char tag_may_val ,
506+ int (* cb )( void * ctx , int tag ,
507+ unsigned char * start , size_t len ),
508+ void * ctx );
351509
352510#if defined(MBEDTLS_BIGNUM_C )
353511/**
@@ -367,8 +525,6 @@ int mbedtls_asn1_get_sequence_of( unsigned char **p,
367525 * \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the parsed value does
368526 * not fit in an \c int.
369527 * \return An MPI error code if the parsed value is too large.
370- * \return An ASN.1 error code if the input does not start with
371- * a valid ASN.1 INTEGER.
372528 */
373529int mbedtls_asn1_get_mpi ( unsigned char * * p ,
374530 const unsigned char * end ,
0 commit comments