Skip to content
This repository has been archived by the owner on Aug 29, 2024. It is now read-only.

Commit

Permalink
[crypto] Clarify ASN.1 cursor invalidation behaviour
Browse files Browse the repository at this point in the history
Calling asn1_skip_if_exists() on a malformed ASN.1 object may
currently leave the cursor in a partially-updated state, where the tag
byte and one of the length bytes have been stripped.  The cursor is
left with a valid data pointer and length and so no out-of-bounds
access can arise, but the cursor no longer points to the start of an
ASN.1 object.

Ensure that each ASN.1 cursor manipulation code path leads to the
cursor being either fully updated, left unmodified, or invalidated,
and update the function descriptions to reflect this.

Signed-off-by: Michael Brown <[email protected]>
  • Loading branch information
mcb30 committed Aug 7, 2024
1 parent 309ac8f commit 0e73b48
Showing 1 changed file with 21 additions and 8 deletions.
29 changes: 21 additions & 8 deletions src/crypto/asn1.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,10 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
* object body (i.e. the first byte following the length byte(s)), and
* the length of the object body (i.e. the number of bytes until the
* following object tag, if any) is returned.
*
* If the expected type is not found, the object cursor will not be
* 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 ) {
unsigned int len_len;
Expand All @@ -103,6 +107,7 @@ int asn1_start ( struct asn1_cursor *cursor, unsigned int type, size_t extra ) {
if ( cursor->len < 2 /* Tag byte and first length byte */ ) {
if ( cursor->len )
DBGC ( cursor, "ASN1 %p too short\n", cursor );
asn1_invalidate_cursor ( cursor );
return -EINVAL_ASN1_EMPTY;
}

Expand All @@ -127,6 +132,7 @@ int asn1_start ( struct asn1_cursor *cursor, unsigned int type, size_t extra ) {
if ( cursor->len < len_len ) {
DBGC ( cursor, "ASN1 %p bad length field length %d (max "
"%zd)\n", cursor, len_len, cursor->len );
asn1_invalidate_cursor ( cursor );
return -EINVAL_ASN1_LEN_LEN;
}

Expand All @@ -140,6 +146,7 @@ int asn1_start ( struct asn1_cursor *cursor, unsigned int type, size_t extra ) {
if ( ( cursor->len + extra ) < len ) {
DBGC ( cursor, "ASN1 %p bad length %d (max %zd)\n",
cursor, len, ( cursor->len + extra ) );
asn1_invalidate_cursor ( cursor );
return -EINVAL_ASN1_LEN;
}

Expand All @@ -154,8 +161,9 @@ int asn1_start ( struct asn1_cursor *cursor, unsigned int type, size_t extra ) {
* @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.
* 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 len;
Expand All @@ -181,8 +189,11 @@ int asn1_enter ( struct asn1_cursor *cursor, unsigned int type ) {
* @ret rc Return status code
*
* The object cursor will be updated to point to the next ASN.1
* object. If any error occurs, the object cursor will not be
* modified.
* object.
*
* If the expected type is not found, the object cursor will not be
* modified. If any other error occurs, the object cursor will be
* invalidated.
*/
int asn1_skip_if_exists ( struct asn1_cursor *cursor, unsigned int type ) {
int len;
Expand All @@ -207,8 +218,9 @@ int asn1_skip_if_exists ( struct asn1_cursor *cursor, unsigned int type ) {
* @ret rc Return status code
*
* The object cursor will be updated to point to the next ASN.1
* object. If any error occurs, the object cursor will be
* invalidated.
* object.
*
* If any error occurs, the object cursor will be invalidated.
*/
int asn1_skip ( struct asn1_cursor *cursor, unsigned int type ) {
int rc;
Expand All @@ -229,8 +241,9 @@ int asn1_skip ( struct asn1_cursor *cursor, unsigned int type ) {
* @ret rc Return status code
*
* The object cursor will be shrunk to contain only the current ASN.1
* object. If any error occurs, the object cursor will be
* invalidated.
* object.
*
* If any error occurs, the object cursor will be invalidated.
*/
int asn1_shrink ( struct asn1_cursor *cursor, unsigned int type ) {
struct asn1_cursor temp;
Expand Down

0 comments on commit 0e73b48

Please sign in to comment.