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 <mykhailo.sopiha@linaro.org>
diff --git a/include/mbedtls/asn1.h b/include/mbedtls/asn1.h
index 1a76111..1c6683f 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,14 +255,33 @@
  *              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 @@
  * \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 9824146..0bce28e 100644
--- a/include/mbedtls/asn1write.h
+++ b/include/mbedtls/asn1write.h
@@ -193,6 +193,21 @@
 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 412259e..87e7aa9 100644
--- a/library/asn1parse.c
+++ b/library/asn1parse.c
@@ -139,17 +139,20 @@
     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 @@
     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 a138d0b..b3a3ad5 100644
--- a/library/asn1write.c
+++ b/library/asn1write.c
@@ -231,7 +231,7 @@
     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 @@
     }
 
     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 )
 {