Merge pull request #307 from msopiha-linaro/development

Add ASN.1 ENUMERATED tag support
This commit is contained in:
Gilles Peskine 2019-11-28 10:20:18 +01:00 committed by GitHub
commit 7bb1a7e0bf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 261 additions and 11 deletions

View File

@ -75,6 +75,7 @@
#define MBEDTLS_ASN1_OCTET_STRING 0x04
#define MBEDTLS_ASN1_NULL 0x05
#define MBEDTLS_ASN1_OID 0x06
#define MBEDTLS_ASN1_ENUMERATED 0x0A
#define MBEDTLS_ASN1_UTF8_STRING 0x0C
#define MBEDTLS_ASN1_SEQUENCE 0x10
#define MBEDTLS_ASN1_SET 0x11
@ -254,13 +255,32 @@ int mbedtls_asn1_get_bool( unsigned char **p,
* a valid ASN.1 INTEGER.
* \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the parsed value does
* not fit in an \c int.
* \return An ASN.1 error code if the input does not start with
* a valid ASN.1 INTEGER.
*/
int mbedtls_asn1_get_int( unsigned char **p,
const unsigned char *end,
int *val );
/**
* \brief Retrieve an enumerated ASN.1 tag and its value.
* Updates the pointer to immediately behind the full tag.
*
* \param p On entry, \c *p points to the start of the ASN.1 element.
* On successful completion, \c *p points to the first byte
* beyond the ASN.1 element.
* On error, the value of \c *p is undefined.
* \param end End of data.
* \param val On success, the parsed value.
*
* \return 0 if successful.
* \return An ASN.1 error code if the input does not start with
* a valid ASN.1 ENUMERATED.
* \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the parsed value does
* not fit in an \c int.
*/
int mbedtls_asn1_get_enum( unsigned char **p,
const unsigned char *end,
int *val );
/**
* \brief Retrieve a bitstring ASN.1 tag and its value.
* Updates the pointer to immediately behind the full tag.
@ -367,8 +387,6 @@ int mbedtls_asn1_get_sequence_of( unsigned char **p,
* \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the parsed value does
* not fit in an \c int.
* \return An MPI error code if the parsed value is too large.
* \return An ASN.1 error code if the input does not start with
* a valid ASN.1 INTEGER.
*/
int mbedtls_asn1_get_mpi( unsigned char **p,
const unsigned char *end,

View File

@ -192,6 +192,21 @@ int mbedtls_asn1_write_bool( unsigned char **p, unsigned char *start,
*/
int mbedtls_asn1_write_int( unsigned char **p, unsigned char *start, int val );
/**
* \brief Write an enum tag (#MBEDTLS_ASN1_ENUMERATED) and value
* in ASN.1 format.
*
* \note This function works backwards in data buffer.
*
* \param p The reference to the current position pointer.
* \param start The start of the buffer, for bounds-checking.
* \param val The integer value to write.
*
* \return The number of bytes written to \p p on success.
* \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure.
*/
int mbedtls_asn1_write_enum( unsigned char **p, unsigned char *start, int val );
/**
* \brief Write a string in ASN.1 format using a specific
* string encoding tag.

View File

@ -139,17 +139,20 @@ int mbedtls_asn1_get_bool( unsigned char **p,
return( 0 );
}
int mbedtls_asn1_get_int( unsigned char **p,
const unsigned char *end,
int *val )
static int asn1_get_tagged_int( unsigned char **p,
const unsigned char *end,
int tag, int *val )
{
int ret;
size_t len;
if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 )
if( ( ret = mbedtls_asn1_get_tag( p, end, &len, tag ) ) != 0 )
return( ret );
/* len==0 is malformed (0 must be represented as 020100). */
/*
* len==0 is malformed (0 must be represented as 020100 for INTEGER,
* or 0A0100 for ENUMERATED tags
*/
if( len == 0 )
return( MBEDTLS_ERR_ASN1_INVALID_LENGTH );
/* This is a cryptography library. Reject negative integers. */
@ -180,6 +183,20 @@ int mbedtls_asn1_get_int( unsigned char **p,
return( 0 );
}
int mbedtls_asn1_get_int( unsigned char **p,
const unsigned char *end,
int *val )
{
return( asn1_get_tagged_int( p, end, MBEDTLS_ASN1_INTEGER, val) );
}
int mbedtls_asn1_get_enum( unsigned char **p,
const unsigned char *end,
int *val )
{
return( asn1_get_tagged_int( p, end, MBEDTLS_ASN1_ENUMERATED, val) );
}
#if defined(MBEDTLS_BIGNUM_C)
int mbedtls_asn1_get_mpi( unsigned char **p,
const unsigned char *end,

View File

@ -231,7 +231,7 @@ int mbedtls_asn1_write_bool( unsigned char **p, unsigned char *start, int boolea
return( (int) len );
}
int mbedtls_asn1_write_int( unsigned char **p, unsigned char *start, int val )
static int asn1_write_tagged_int( unsigned char **p, unsigned char *start, int val, int tag )
{
int ret;
size_t len = 0;
@ -255,11 +255,21 @@ int mbedtls_asn1_write_int( unsigned char **p, unsigned char *start, int val )
}
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_INTEGER ) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, tag ) );
return( (int) len );
}
int mbedtls_asn1_write_int( unsigned char **p, unsigned char *start, int val )
{
return( asn1_write_tagged_int( p, start, val, MBEDTLS_ASN1_INTEGER ) );
}
int mbedtls_asn1_write_enum( unsigned char **p, unsigned char *start, int val )
{
return( asn1_write_tagged_int( p, start, val, MBEDTLS_ASN1_ENUMERATED ) );
}
int mbedtls_asn1_write_tagged_string( unsigned char **p, unsigned char *start, int tag,
const char *text, size_t text_len )
{

View File

@ -286,6 +286,90 @@ get_integer:"010101":"":MBEDTLS_ERR_ASN1_UNEXPECTED_TAG
INTEGER too large for mpi
get_mpi_too_large:
ENUMERATED 0
get_enum:"0A0100":"0":0
ENUMERATED 0, extra leading 0
get_enum:"0A020000":"0":0
ENUMERATED 1
get_enum:"0A0101":"1":0
ENUMERATED 1, extra leading 0
get_enum:"0A020001":"1":0
ENUMERATED 0x7f
get_enum:"0A017f":"7f":0
ENUMERATED 0x80
get_enum:"0A020080":"80":0
ENUMERATED 0x80, extra leading 0
get_enum:"0A03000080":"80":0
ENUMERATED 0xff
get_enum:"0A0200ff":"ff":0
ENUMERATED 0x7fff
get_enum:"0A027fff":"7fff":0
ENUMERATED 0x12345678
get_enum:"0A0412345678":"12345678":0
ENUMERATED 0x12345678, extra leading 0
get_enum:"0A050012345678":"12345678":0
ENUMERATED 0x7fffffff
get_enum:"0A047fffffff":"7fffffff":0
ENUMERATED 0x7fffffff, extra leading 0
get_enum:"0A05007fffffff":"7fffffff":0
ENUMERATED 0x80000000
get_enum:"0A050080000000":"80000000":0
ENUMERATED 0xffffffff
get_enum:"0A0500ffffffff":"ffffffff":0
ENUMERATED 0x100000000
get_enum:"0A050100000000":"0100000000":0
ENUMERATED -1
get_enum:"0A01ff":"-1":0
ENUMERATED -1, extra leading ff
get_enum:"0A02ffff":"-1":0
ENUMERATED -0x7f
get_enum:"0A0181":"-7f":0
ENUMERATED -0x80
get_enum:"0A0180":"-80":0
ENUMERATED -0x81
get_enum:"0A02ff7f":"-81":0
ENUMERATED -0xff
get_enum:"0A02ff01":"-ff":0
ENUMERATED -0x100
get_enum:"0A02ff00":"-100":0
ENUMERATED -0x7fffffff
get_enum:"0A0480000001":"-7fffffff":0
ENUMERATED -0x80000000
get_enum:"0A0480000000":"-80000000":0
ENUMERATED -0x80000001
get_enum:"0A05ff7fffffff":"-80000001":0
ENUMERATED -0xffffffff
get_enum:"0A05ff00000001":"-ffffffff":0
ENUMERATED -0x100000000
get_enum:"0A05ff00000000":"-100000000":0
BIT STRING: empty
get_bitstring:"0300":0:0:MBEDTLS_ERR_ASN1_OUT_OF_DATA:MBEDTLS_ERR_ASN1_INVALID_DATA

View File

@ -393,6 +393,49 @@ exit:
}
/* END_CASE */
/* BEGIN_CASE */
void get_enum( const data_t *input,
const char *expected_hex, int expected_result )
{
unsigned char *p;
long expected_value;
int expected_result_for_enum = expected_result;
int val;
int ret;
errno = 0;
expected_value = strtol( expected_hex, NULL, 16 );
if( expected_result == 0 &&
( errno == ERANGE
#if LONG_MAX > INT_MAX
|| expected_value > INT_MAX || expected_value < INT_MIN
#endif
) )
{
/* The library returns the dubious error code INVALID_LENGTH
* for integers that are out of range. */
expected_result_for_enum = MBEDTLS_ERR_ASN1_INVALID_LENGTH;
}
if( expected_result == 0 && expected_value < 0 )
{
/* The library does not support negative INTEGERs and
* returns the dubious error code INVALID_LENGTH.
* Test that we preserve the historical behavior. If we
* decide to change the behavior, we'll also change this test. */
expected_result_for_enum = MBEDTLS_ERR_ASN1_INVALID_LENGTH;
}
p = input->x;
ret = mbedtls_asn1_get_enum( &p, input->x + input->len, &val );
TEST_EQUAL( ret, expected_result_for_enum );
if( ret == 0 )
{
TEST_EQUAL( val, expected_value );
TEST_ASSERT( p == input->x + input->len );
}
}
/* END_CASE */
/* BEGIN_CASE depends_on:MBEDTLS_BIGNUM_C */
void get_mpi_too_large( )
{

View File

@ -49,6 +49,48 @@ mbedtls_asn1_write_int:0x12345678:"020412345678"
ASN.1 Write int 2147483647
mbedtls_asn1_write_int:0x7fffffff:"02047fffffff"
ASN.1 Write enum 0
mbedtls_asn1_write_enum:0:"0A0100"
ASN.1 Write enum 1
mbedtls_asn1_write_enum:1:"0A0101"
ASN.1 Write enum 127
mbedtls_asn1_write_enum:0x7f:"0A017f"
ASN.1 Write enum 128
mbedtls_asn1_write_enum:0x80:"0A020080"
ASN.1 Write enum 255
mbedtls_asn1_write_enum:0xff:"0A0200ff"
ASN.1 Write enum 256
mbedtls_asn1_write_enum:0x100:"0A020100"
ASN.1 Write enum 32767
mbedtls_asn1_write_enum:0x7fff:"0A027fff"
ASN.1 Write enum 32768
mbedtls_asn1_write_enum:0x8000:"0A03008000"
ASN.1 Write enum 65535
mbedtls_asn1_write_enum:0xffff:"0A0300ffff"
ASN.1 Write enum 65536
mbedtls_asn1_write_enum:0x10000:"0A03010000"
ASN.1 Write enum 8388607
mbedtls_asn1_write_enum:0x7fffff:"0A037fffff"
ASN.1 Write enum 8388608
mbedtls_asn1_write_enum:0x800000:"0A0400800000"
ASN.1 Write enum 0x12345678
mbedtls_asn1_write_enum:0x12345678:"0A0412345678"
ASN.1 Write enum 2147483647
mbedtls_asn1_write_enum:0x7fffffff:"0A047fffffff"
#ASN.1 Write mpi 0
#mbedtls_asn1_write_mpi:"00":"020100"

View File

@ -117,6 +117,27 @@ exit:
}
/* END_CASE */
/* BEGIN_CASE */
void mbedtls_asn1_write_enum( int val, data_t *expected )
{
generic_write_data_t data = { NULL, NULL, NULL, NULL, 0 };
int ret;
for( data.size = 0; data.size < expected->len + 1; data.size++ )
{
if( ! generic_write_start_step( &data ) )
goto exit;
ret = mbedtls_asn1_write_enum( &data.p, data.start, val );
if( ! generic_write_finish_step( &data, expected, ret ) )
goto exit;
}
exit:
mbedtls_free( data.output );
}
/* END_CASE */
/* BEGIN_CASE depends_on:MBEDTLS_BIGNUM_C */
void mbedtls_asn1_write_mpi( data_t *val, data_t *expected )
{