From 59e2b03e6ac842d0e69bc4f757bf6da452fca074 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 7 Aug 2024 13:18:47 +0100 Subject: [crypto] Extend asn1_enter() to handle partial object cursors Handling large ASN.1 objects such as encrypted CMS files will require the ability to use the asn1_enter() and asn1_skip() family of functions on partial object cursors, where a defined additional length is known to exist after the end of the data buffer pointed to by the ASN.1 object cursor. We already have support for partial object cursors in the underlying asn1_start() operation used by both asn1_enter() and asn1_skip(), and this is used by the DER image probe routine to check that the potential DER file comprises a single ASN.1 SEQUENCE object. Add asn1_enter_partial() to formalise the process of entering an ASN.1 partial object, and refactor the DER image probe routine to use this instead of open-coding calls to the underlying asn1_start() operation. There is no need for an equivalent asn1_skip_partial() function, since only objects that are wholly contained within the partial cursor may be successfully skipped. Signed-off-by: Michael Brown --- src/crypto/asn1.c | 46 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 37 insertions(+), 9 deletions(-) (limited to 'src/crypto/asn1.c') diff --git a/src/crypto/asn1.c b/src/crypto/asn1.c index 90619dc0e..e66da45b9 100644 --- a/src/crypto/asn1.c +++ b/src/crypto/asn1.c @@ -99,7 +99,8 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); * modified. If any other error occurs, the object cursor will be * invalidated. */ -int asn1_start ( struct asn1_cursor *cursor, unsigned int type, size_t extra ) { +static int asn1_start ( struct asn1_cursor *cursor, unsigned int type, + size_t extra ) { unsigned int len_len; unsigned int len; @@ -154,33 +155,58 @@ int asn1_start ( struct asn1_cursor *cursor, unsigned int type, size_t extra ) { } /** - * Enter ASN.1 object + * Enter ASN.1 partial object * * @v cursor ASN.1 object cursor * @v type Expected type, or ASN1_ANY + * @v extra Additional length beyond partial object * @ret rc Return status code * - * The object cursor will be updated to point to the body of the - * current ASN.1 object. + * The object cursor and additional length will be updated to point to + * the body of the current ASN.1 object. * * If any error occurs, the object cursor will be invalidated. */ -int asn1_enter ( struct asn1_cursor *cursor, unsigned int type ) { +int asn1_enter_partial ( struct asn1_cursor *cursor, unsigned int type, + size_t *extra ) { int len; - len = asn1_start ( cursor, type, 0 ); + /* Parse current object */ + len = asn1_start ( cursor, type, *extra ); if ( len < 0 ) { asn1_invalidate_cursor ( cursor ); return len; } - cursor->len = len; + /* Update cursor and additional length */ + if ( ( ( size_t ) len ) <= cursor->len ) + cursor->len = len; + assert ( ( len - cursor->len ) <= *extra ); + *extra = ( len - cursor->len ); + DBGC ( cursor, "ASN1 %p entered object type %02x (len %x)\n", cursor, type, len ); - return 0; } +/** + * Enter ASN.1 object + * + * @v cursor ASN.1 object cursor + * @v type Expected type, or ASN1_ANY + * @ret rc Return status code + * + * The object cursor will be updated to point to the body of the + * current ASN.1 object. + * + * If any error occurs, the object cursor will be invalidated. + */ +int asn1_enter ( struct asn1_cursor *cursor, unsigned int type ) { + static size_t no_extra = 0; + + return asn1_enter_partial ( cursor, type, &no_extra ); +} + /** * Skip ASN.1 object if present * @@ -198,15 +224,17 @@ int asn1_enter ( struct asn1_cursor *cursor, unsigned int type ) { int asn1_skip_if_exists ( struct asn1_cursor *cursor, unsigned int type ) { int len; + /* Parse current object */ len = asn1_start ( cursor, type, 0 ); if ( len < 0 ) return len; + /* Update cursor */ cursor->data += len; cursor->len -= len; + DBGC ( cursor, "ASN1 %p skipped object type %02x (len %x)\n", cursor, type, len ); - return 0; } -- cgit