From 20180ca919227c65b9341901452210461be5de95 Mon Sep 17 00:00:00 2001 From: Mykhailo Sopiha Date: Tue, 29 Oct 2019 15:58:10 +0200 Subject: [PATCH] Add ASN.1 ENUMERATED tag support Add ASN.1 ENUMERATED [1] tag to supported tag list. 1. https://tools.ietf.org/html/rfc3641#page-8 Signed-off-by: Mykhailo Sopiha --- include/mbedtls/asn1.h | 26 ++++++++++++++++++++++---- include/mbedtls/asn1write.h | 15 +++++++++++++++ library/asn1parse.c | 27 ++++++++++++++++++++++----- library/asn1write.c | 14 ++++++++++++-- 4 files changed, 71 insertions(+), 11 deletions(-) diff --git a/include/mbedtls/asn1.h b/include/mbedtls/asn1.h index 1a7611168..1c6683f63 100644 --- a/include/mbedtls/asn1.h +++ b/include/mbedtls/asn1.h @@ -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, diff --git a/include/mbedtls/asn1write.h b/include/mbedtls/asn1write.h index 982414626..0bce28ed1 100644 --- a/include/mbedtls/asn1write.h +++ b/include/mbedtls/asn1write.h @@ -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. diff --git a/library/asn1parse.c b/library/asn1parse.c index 412259e35..87e7aa989 100644 --- a/library/asn1parse.c +++ b/library/asn1parse.c @@ -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, diff --git a/library/asn1write.c b/library/asn1write.c index a138d0b75..b3a3ad508 100644 --- a/library/asn1write.c +++ b/library/asn1write.c @@ -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 ) {