aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/crypto/asn1.c46
-rw-r--r--src/image/der.c15
-rw-r--r--src/include/ipxe/asn1.h4
3 files changed, 43 insertions, 22 deletions
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,34 +155,59 @@ 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
*
* @v cursor ASN.1 object cursor
@@ -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;
}
diff --git a/src/image/der.c b/src/image/der.c
index fa17e5659..9d31c253b 100644
--- a/src/image/der.c
+++ b/src/image/der.c
@@ -76,8 +76,6 @@ static int der_probe ( struct image *image ) {
struct asn1_cursor cursor;
uint8_t buf[8];
size_t extra;
- size_t total;
- int len;
int rc;
/* Sanity check: no realistic DER image can be smaller than this */
@@ -90,21 +88,16 @@ static int der_probe ( struct image *image ) {
copy_from_user ( buf, image->data, 0, sizeof ( buf ) );
extra = ( image->len - sizeof ( buf ) );
- /* Get length of ASN.1 sequence */
- len = asn1_start ( &cursor, ASN1_SEQUENCE, extra );
- if ( len < 0 ) {
- rc = len;
+ /* Check that image begins with an ASN.1 sequence object */
+ if ( ( rc = asn1_enter_partial ( &cursor, ASN1_SEQUENCE,
+ &extra ) ) != 0 ) {
DBGC ( image, "DER %s is not valid ASN.1: %s\n",
image->name, strerror ( rc ) );
return rc;
}
- /* Add length of tag and length bytes consumed by asn1_start() */
- total = ( len + ( cursor.data - ( ( void * ) buf ) ) );
- assert ( total <= image->len );
-
/* Check that image comprises a single well-formed ASN.1 object */
- if ( total != image->len ) {
+ if ( extra != ( image->len - sizeof ( buf ) ) ) {
DBGC ( image, "DER %s is not single ASN.1\n", image->name );
return -ENOEXEC;
}
diff --git a/src/include/ipxe/asn1.h b/src/include/ipxe/asn1.h
index ac7ea5604..1580c8baf 100644
--- a/src/include/ipxe/asn1.h
+++ b/src/include/ipxe/asn1.h
@@ -404,8 +404,8 @@ asn1_built ( struct asn1_builder *builder ) {
return &u->cursor;
}
-extern int asn1_start ( struct asn1_cursor *cursor, unsigned int type,
- size_t extra );
+extern int asn1_enter_partial ( struct asn1_cursor *cursor, unsigned int type,
+ size_t *extra );
extern int asn1_enter ( struct asn1_cursor *cursor, unsigned int type );
extern int asn1_skip_if_exists ( struct asn1_cursor *cursor,
unsigned int type );