[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 <mcb30@ipxe.org>
siglist
Michael Brown 2025-03-11 11:55:15 +00:00
parent 011c778f06
commit 26a8fed710
2 changed files with 58 additions and 16 deletions

View File

@ -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 data DER data
* @v offset Offset within image * @v len Length of DER data
* @v offset Offset within data
* @v cursor ASN.1 cursor to fill in * @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 * The caller is responsible for eventually calling free() on the
* allocated ASN.1 cursor. * allocated ASN.1 cursor.
*/ */
static int der_asn1 ( struct image *image, size_t offset __unused, int der_asn1 ( userptr_t data, size_t len, size_t offset,
struct asn1_cursor **cursor ) { struct asn1_cursor **cursor ) {
void *data; size_t remaining;
void *raw;
/* Sanity check */
assert ( offset <= len );
remaining = ( len - offset );
/* Allocate cursor and data buffer */ /* Allocate cursor and data buffer */
*cursor = malloc ( sizeof ( **cursor ) + image->len ); *cursor = malloc ( sizeof ( **cursor ) + remaining );
if ( ! *cursor ) if ( ! *cursor )
return -ENOMEM; return -ENOMEM;
data = ( ( ( void * ) *cursor ) + sizeof ( **cursor ) ); raw = ( ( ( void * ) *cursor ) + sizeof ( **cursor ) );
/* Populate cursor and data buffer */ /* Populate cursor and data buffer */
(*cursor)->data = data; (*cursor)->data = raw;
(*cursor)->len = image->len; (*cursor)->len = remaining;
copy_from_user ( data, image->data, 0, image->len ); 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 * @v image DER image
* @ret rc Return status code * @ret rc Return status code
*/ */
static int der_probe ( struct image *image ) { static int der_image_probe ( struct image *image ) {
struct asn1_cursor cursor; struct asn1_cursor cursor;
uint8_t buf[8]; uint8_t buf[8];
size_t extra; size_t extra;
@ -105,9 +114,37 @@ static int der_probe ( struct image *image ) {
return 0; 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 */ /** DER image type */
struct image_type der_image_type __image_type ( PROBE_NORMAL ) = { struct image_type der_image_type __image_type ( PROBE_NORMAL ) = {
.name = "DER", .name = "DER",
.probe = der_probe, .probe = der_image_probe,
.asn1 = der_asn1, .asn1 = der_image_asn1,
}; };

View File

@ -9,8 +9,13 @@
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
#include <ipxe/asn1.h>
#include <ipxe/image.h> #include <ipxe/image.h>
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 ); extern struct image_type der_image_type __image_type ( PROBE_NORMAL );
#endif /* _IPXE_DER_H */ #endif /* _IPXE_DER_H */