[crypto] Reject indefinite and unrepresentable length encodings

An indefinite length encoding will currently be parsed as having a
length of zero, and an encoded length that exceeds the range of an
unsigned int will be truncated.

Tighten up the parsing of lengths to explicitly reject indefinite
length encodings or unrepresentable lengths.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
Michael Brown
2026-09-04 16:51:54 +01:00
parent de04e79ae5
commit 3a62e9ded4
+13 -5
View File
@@ -175,6 +175,7 @@ FILE_SECBOOT ( PERMITTED );
static int asn1_start ( struct asn1_cursor *cursor, unsigned int type ) {
unsigned int len_len;
unsigned int len;
uint8_t high_byte;
/* Sanity check */
if ( cursor->len < 2 /* Tag byte and first length byte */ ) {
@@ -202,22 +203,29 @@ static int asn1_start ( struct asn1_cursor *cursor, unsigned int type ) {
} else {
len_len = 1;
}
if ( cursor->len < len_len ) {
DBGC ( cursor, "ASN1 %p bad length field length %d (max "
"%zd)\n", cursor, len_len, cursor->len );
if ( ( len_len == 0 ) || ( cursor->len < len_len ) ) {
DBGC ( cursor, "ASN1 %p bad length field length %d (min 0, "
"max %zd)\n", cursor, len_len, cursor->len );
asn1_invalidate_cursor ( cursor );
return -EINVAL_ASN1_LEN_LEN;
}
/* Extract the length and sanity check */
for ( len = 0 ; len_len ; len_len-- ) {
high_byte = ( len >> ( 8 * ( sizeof ( len ) - 1 ) ) );
if ( high_byte ) {
DBGC ( cursor, "ASN1 %p unrepresentable length\n",
cursor );
asn1_invalidate_cursor ( cursor );
return -EINVAL_ASN1_LEN;
}
len <<= 8;
len |= *( ( uint8_t * ) cursor->data );
cursor->data++;
cursor->len--;
}
if ( cursor->len < len ) {
DBGC ( cursor, "ASN1 %p bad length %d (max %zd)\n",
if ( ( cursor->len < len ) || ( ( ( int ) len ) < 0 ) ) {
DBGC ( cursor, "ASN1 %p bad length %d (min 0, max %zd)\n",
cursor, len, cursor->len );
asn1_invalidate_cursor ( cursor );
return -EINVAL_ASN1_LEN;