|  | @@ -29,6 +29,20 @@ FILE_LICENCE ( GPL2_OR_LATER );
 | 
		
	
		
			
			| 29 | 29 |   *
 | 
		
	
		
			
			| 30 | 30 |   */
 | 
		
	
		
			
			| 31 | 31 |  
 | 
		
	
		
			
			|  | 32 | +/* Disambiguate the various error causes */
 | 
		
	
		
			
			|  | 33 | +#define EINVAL_ASN1_EMPTY \
 | 
		
	
		
			
			|  | 34 | +	__einfo_error ( EINFO_EINVAL_ASN1_EMPTY )
 | 
		
	
		
			
			|  | 35 | +#define EINFO_EINVAL_ASN1_EMPTY \
 | 
		
	
		
			
			|  | 36 | +	__einfo_uniqify ( EINFO_EINVAL, 0x01, "Empty or underlength cursor" )
 | 
		
	
		
			
			|  | 37 | +#define EINVAL_ASN1_LEN_LEN \
 | 
		
	
		
			
			|  | 38 | +	__einfo_error ( EINFO_EINVAL_ASN1_LEN_LEN )
 | 
		
	
		
			
			|  | 39 | +#define EINFO_EINVAL_ASN1_LEN_LEN \
 | 
		
	
		
			
			|  | 40 | +	__einfo_uniqify ( EINFO_EINVAL, 0x02, "Length field overruns cursor" )
 | 
		
	
		
			
			|  | 41 | +#define EINVAL_ASN1_LEN \
 | 
		
	
		
			
			|  | 42 | +	__einfo_error ( EINFO_EINVAL_ASN1_LEN )
 | 
		
	
		
			
			|  | 43 | +#define EINFO_EINVAL_ASN1_LEN \
 | 
		
	
		
			
			|  | 44 | +	__einfo_uniqify ( EINFO_EINVAL, 0x03, "Field overruns cursor" )
 | 
		
	
		
			
			|  | 45 | +
 | 
		
	
		
			
			| 32 | 46 |  /**
 | 
		
	
		
			
			| 33 | 47 |   * Start parsing ASN.1 object
 | 
		
	
		
			
			| 34 | 48 |   *
 | 
		
	
	
		
			
			|  | @@ -40,32 +54,23 @@ FILE_LICENCE ( GPL2_OR_LATER );
 | 
		
	
		
			
			| 40 | 54 |   * object body (i.e. the first byte following the length byte(s)), and
 | 
		
	
		
			
			| 41 | 55 |   * the length of the object body (i.e. the number of bytes until the
 | 
		
	
		
			
			| 42 | 56 |   * following object tag, if any) is returned.
 | 
		
	
		
			
			| 43 |  | - *
 | 
		
	
		
			
			| 44 |  | - * If any error occurs (i.e. if the object is not of the expected
 | 
		
	
		
			
			| 45 |  | - * type, or if we overflow beyond the end of the ASN.1 object), then
 | 
		
	
		
			
			| 46 |  | - * the cursor will be invalidated and a negative value will be
 | 
		
	
		
			
			| 47 |  | - * returned.
 | 
		
	
		
			
			| 48 | 57 |   */
 | 
		
	
		
			
			| 49 |  | -static int asn1_start ( struct asn1_cursor *cursor,
 | 
		
	
		
			
			| 50 |  | -			       unsigned int type ) {
 | 
		
	
		
			
			|  | 58 | +static int asn1_start ( struct asn1_cursor *cursor, unsigned int type ) {
 | 
		
	
		
			
			| 51 | 59 |  	unsigned int len_len;
 | 
		
	
		
			
			| 52 | 60 |  	unsigned int len;
 | 
		
	
		
			
			| 53 |  | -	int rc;
 | 
		
	
		
			
			| 54 | 61 |  
 | 
		
	
		
			
			| 55 | 62 |  	/* Sanity check */
 | 
		
	
		
			
			| 56 | 63 |  	if ( cursor->len < 2 /* Tag byte and first length byte */ ) {
 | 
		
	
		
			
			| 57 | 64 |  		if ( cursor->len )
 | 
		
	
		
			
			| 58 | 65 |  			DBGC ( cursor, "ASN1 %p too short\n", cursor );
 | 
		
	
		
			
			| 59 |  | -		rc = -EINVAL;
 | 
		
	
		
			
			| 60 |  | -		goto notfound;
 | 
		
	
		
			
			|  | 66 | +		return -EINVAL_ASN1_EMPTY;
 | 
		
	
		
			
			| 61 | 67 |  	}
 | 
		
	
		
			
			| 62 | 68 |  
 | 
		
	
		
			
			| 63 | 69 |  	/* Check the tag byte */
 | 
		
	
		
			
			| 64 | 70 |  	if ( *( ( uint8_t * ) cursor->data ) != type ) {
 | 
		
	
		
			
			| 65 | 71 |  		DBGC ( cursor, "ASN1 %p type mismatch (expected %d, got %d)\n",
 | 
		
	
		
			
			| 66 | 72 |  		       cursor, type, *( ( uint8_t * ) cursor->data ) );
 | 
		
	
		
			
			| 67 |  | -		rc = -ENXIO;
 | 
		
	
		
			
			| 68 |  | -		goto notfound;
 | 
		
	
		
			
			|  | 73 | +		return -ENXIO;
 | 
		
	
		
			
			| 69 | 74 |  	}
 | 
		
	
		
			
			| 70 | 75 |  	cursor->data++;
 | 
		
	
		
			
			| 71 | 76 |  	cursor->len--;
 | 
		
	
	
		
			
			|  | @@ -82,8 +87,7 @@ static int asn1_start ( struct asn1_cursor *cursor,
 | 
		
	
		
			
			| 82 | 87 |  	if ( cursor->len < len_len ) {
 | 
		
	
		
			
			| 83 | 88 |  		DBGC ( cursor, "ASN1 %p bad length field length %d (max "
 | 
		
	
		
			
			| 84 | 89 |  		       "%zd)\n", cursor, len_len, cursor->len );
 | 
		
	
		
			
			| 85 |  | -		rc = -EINVAL;
 | 
		
	
		
			
			| 86 |  | -		goto notfound;
 | 
		
	
		
			
			|  | 90 | +		return -EINVAL_ASN1_LEN_LEN;
 | 
		
	
		
			
			| 87 | 91 |  	}
 | 
		
	
		
			
			| 88 | 92 |  
 | 
		
	
		
			
			| 89 | 93 |  	/* Extract the length and sanity check */
 | 
		
	
	
		
			
			|  | @@ -96,16 +100,10 @@ static int asn1_start ( struct asn1_cursor *cursor,
 | 
		
	
		
			
			| 96 | 100 |  	if ( cursor->len < len ) {
 | 
		
	
		
			
			| 97 | 101 |  		DBGC ( cursor, "ASN1 %p bad length %d (max %zd)\n",
 | 
		
	
		
			
			| 98 | 102 |  		       cursor, len, cursor->len );
 | 
		
	
		
			
			| 99 |  | -		rc = -EINVAL;
 | 
		
	
		
			
			| 100 |  | -		goto notfound;
 | 
		
	
		
			
			|  | 103 | +		return -EINVAL_ASN1_LEN;
 | 
		
	
		
			
			| 101 | 104 |  	}
 | 
		
	
		
			
			| 102 | 105 |  
 | 
		
	
		
			
			| 103 | 106 |  	return len;
 | 
		
	
		
			
			| 104 |  | -
 | 
		
	
		
			
			| 105 |  | - notfound:
 | 
		
	
		
			
			| 106 |  | -	cursor->data = NULL;
 | 
		
	
		
			
			| 107 |  | -	cursor->len = 0;
 | 
		
	
		
			
			| 108 |  | -	return rc;
 | 
		
	
		
			
			| 109 | 107 |  }
 | 
		
	
		
			
			| 110 | 108 |  
 | 
		
	
		
			
			| 111 | 109 |  /**
 | 
		
	
	
		
			
			|  | @@ -123,8 +121,10 @@ int asn1_enter ( struct asn1_cursor *cursor, unsigned int type ) {
 | 
		
	
		
			
			| 123 | 121 |  	int len;
 | 
		
	
		
			
			| 124 | 122 |  
 | 
		
	
		
			
			| 125 | 123 |  	len = asn1_start ( cursor, type );
 | 
		
	
		
			
			| 126 |  | -	if ( len < 0 )
 | 
		
	
		
			
			|  | 124 | +	if ( len < 0 ) {
 | 
		
	
		
			
			|  | 125 | +		asn1_invalidate_cursor ( cursor );
 | 
		
	
		
			
			| 127 | 126 |  		return len;
 | 
		
	
		
			
			|  | 127 | +	}
 | 
		
	
		
			
			| 128 | 128 |  
 | 
		
	
		
			
			| 129 | 129 |  	cursor->len = len;
 | 
		
	
		
			
			| 130 | 130 |  	DBGC ( cursor, "ASN1 %p entered object type %02x (len %x)\n",
 | 
		
	
	
		
			
			|  | @@ -134,17 +134,17 @@ int asn1_enter ( struct asn1_cursor *cursor, unsigned int type ) {
 | 
		
	
		
			
			| 134 | 134 |  }
 | 
		
	
		
			
			| 135 | 135 |  
 | 
		
	
		
			
			| 136 | 136 |  /**
 | 
		
	
		
			
			| 137 |  | - * Skip ASN.1 object
 | 
		
	
		
			
			|  | 137 | + * Skip ASN.1 object if present
 | 
		
	
		
			
			| 138 | 138 |   *
 | 
		
	
		
			
			| 139 | 139 |   * @v cursor		ASN.1 object cursor
 | 
		
	
		
			
			| 140 | 140 |   * @v type		Expected type
 | 
		
	
		
			
			| 141 | 141 |   * @ret rc		Return status code
 | 
		
	
		
			
			| 142 | 142 |   *
 | 
		
	
		
			
			| 143 | 143 |   * The object cursor will be updated to point to the next ASN.1
 | 
		
	
		
			
			| 144 |  | - * object.  If any error occurs, the object cursor will be
 | 
		
	
		
			
			| 145 |  | - * invalidated.
 | 
		
	
		
			
			|  | 144 | + * object.  If any error occurs, the object cursor will not be
 | 
		
	
		
			
			|  | 145 | + * modified.
 | 
		
	
		
			
			| 146 | 146 |   */
 | 
		
	
		
			
			| 147 |  | -int asn1_skip ( struct asn1_cursor *cursor, unsigned int type ) {
 | 
		
	
		
			
			|  | 147 | +int asn1_skip_if_exists ( struct asn1_cursor *cursor, unsigned int type ) {
 | 
		
	
		
			
			| 148 | 148 |  	int len;
 | 
		
	
		
			
			| 149 | 149 |  
 | 
		
	
		
			
			| 150 | 150 |  	len = asn1_start ( cursor, type );
 | 
		
	
	
		
			
			|  | @@ -158,9 +158,30 @@ int asn1_skip ( struct asn1_cursor *cursor, unsigned int type ) {
 | 
		
	
		
			
			| 158 | 158 |  
 | 
		
	
		
			
			| 159 | 159 |  	if ( ! cursor->len ) {
 | 
		
	
		
			
			| 160 | 160 |  		DBGC ( cursor, "ASN1 %p reached end of object\n", cursor );
 | 
		
	
		
			
			| 161 |  | -		cursor->data = NULL;
 | 
		
	
		
			
			| 162 | 161 |  		return -ENOENT;
 | 
		
	
		
			
			| 163 | 162 |  	}
 | 
		
	
		
			
			| 164 | 163 |  
 | 
		
	
		
			
			| 165 | 164 |  	return 0;
 | 
		
	
		
			
			| 166 | 165 |  }
 | 
		
	
		
			
			|  | 166 | +
 | 
		
	
		
			
			|  | 167 | +/**
 | 
		
	
		
			
			|  | 168 | + * Skip ASN.1 object
 | 
		
	
		
			
			|  | 169 | + *
 | 
		
	
		
			
			|  | 170 | + * @v cursor		ASN.1 object cursor
 | 
		
	
		
			
			|  | 171 | + * @v type		Expected type
 | 
		
	
		
			
			|  | 172 | + * @ret rc		Return status code
 | 
		
	
		
			
			|  | 173 | + *
 | 
		
	
		
			
			|  | 174 | + * The object cursor will be updated to point to the next ASN.1
 | 
		
	
		
			
			|  | 175 | + * object.  If any error occurs, the object cursor will be
 | 
		
	
		
			
			|  | 176 | + * invalidated.
 | 
		
	
		
			
			|  | 177 | + */
 | 
		
	
		
			
			|  | 178 | +int asn1_skip ( struct asn1_cursor *cursor, unsigned int type ) {
 | 
		
	
		
			
			|  | 179 | +	int rc;
 | 
		
	
		
			
			|  | 180 | +
 | 
		
	
		
			
			|  | 181 | +	if ( ( rc = asn1_skip_if_exists ( cursor, type ) ) < 0 ) {
 | 
		
	
		
			
			|  | 182 | +		asn1_invalidate_cursor ( cursor );
 | 
		
	
		
			
			|  | 183 | +		return rc;
 | 
		
	
		
			
			|  | 184 | +	}
 | 
		
	
		
			
			|  | 185 | +
 | 
		
	
		
			
			|  | 186 | +	return 0;
 | 
		
	
		
			
			|  | 187 | +}
 |