From 26a8fed710900be439e7548308ecca910a9b683c Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 11 Mar 2025 11:55:15 +0000 Subject: [PATCH] [crypto] Allow for parsing of DER data separate from DER images We currently provide pem_asn1() to allow for parsing of PEM data that is not necessarily contained in an image. Provide an equivalent function der_asn1() to allow for similar parsing of DER data. Signed-off-by: Michael Brown --- src/image/der.c | 69 ++++++++++++++++++++++++++++++++---------- src/include/ipxe/der.h | 5 +++ 2 files changed, 58 insertions(+), 16 deletions(-) diff --git a/src/image/der.c b/src/image/der.c index 9d31c253b..ac4992336 100644 --- a/src/image/der.c +++ b/src/image/der.c @@ -38,32 +38,41 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); */ /** - * Extract ASN.1 object from image + * Extract ASN.1 object from DER data * - * @v image DER image - * @v offset Offset within image + * @v data DER data + * @v len Length of DER data + * @v offset Offset within data * @v cursor ASN.1 cursor to fill in - * @ret next Offset to next image, or negative error + * @ret next Offset to next object, or negative error * * The caller is responsible for eventually calling free() on the * allocated ASN.1 cursor. */ -static int der_asn1 ( struct image *image, size_t offset __unused, - struct asn1_cursor **cursor ) { - void *data; +int der_asn1 ( userptr_t data, size_t len, size_t offset, + struct asn1_cursor **cursor ) { + size_t remaining; + void *raw; + + /* Sanity check */ + assert ( offset <= len ); + remaining = ( len - offset ); /* Allocate cursor and data buffer */ - *cursor = malloc ( sizeof ( **cursor ) + image->len ); + *cursor = malloc ( sizeof ( **cursor ) + remaining ); if ( ! *cursor ) return -ENOMEM; - data = ( ( ( void * ) *cursor ) + sizeof ( **cursor ) ); + raw = ( ( ( void * ) *cursor ) + sizeof ( **cursor ) ); /* Populate cursor and data buffer */ - (*cursor)->data = data; - (*cursor)->len = image->len; - copy_from_user ( data, image->data, 0, image->len ); + (*cursor)->data = raw; + (*cursor)->len = remaining; + copy_from_user ( raw, data, offset, remaining ); - return image->len; + /* Shrink cursor */ + asn1_shrink_any ( *cursor ); + + return ( offset + (*cursor)->len ); } /** @@ -72,7 +81,7 @@ static int der_asn1 ( struct image *image, size_t offset __unused, * @v image DER image * @ret rc Return status code */ -static int der_probe ( struct image *image ) { +static int der_image_probe ( struct image *image ) { struct asn1_cursor cursor; uint8_t buf[8]; size_t extra; @@ -105,9 +114,37 @@ static int der_probe ( struct image *image ) { return 0; } +/** + * Extract ASN.1 object from DER image + * + * @v image DER image + * @v offset Offset within image + * @v cursor ASN.1 cursor to fill in + * @ret next Offset to next image, or negative error + * + * The caller is responsible for eventually calling free() on the + * allocated ASN.1 cursor. + */ +static int der_image_asn1 ( struct image *image, size_t offset, + struct asn1_cursor **cursor ) { + int next; + int rc; + + /* Extract ASN.1 object */ + if ( ( next = der_asn1 ( image->data, image->len, offset, + cursor ) ) < 0 ) { + rc = next; + DBGC ( image, "DER %s could not extract ASN.1: %s\n", + image->name, strerror ( rc ) ); + return rc; + } + + return next; +} + /** DER image type */ struct image_type der_image_type __image_type ( PROBE_NORMAL ) = { .name = "DER", - .probe = der_probe, - .asn1 = der_asn1, + .probe = der_image_probe, + .asn1 = der_image_asn1, }; diff --git a/src/include/ipxe/der.h b/src/include/ipxe/der.h index c63bd9751..983aeb23c 100644 --- a/src/include/ipxe/der.h +++ b/src/include/ipxe/der.h @@ -9,8 +9,13 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); +#include +#include #include +extern int der_asn1 ( userptr_t data, size_t len, size_t offset, + struct asn1_cursor **cursor ); + extern struct image_type der_image_type __image_type ( PROBE_NORMAL ); #endif /* _IPXE_DER_H */