Add mbedtls_x509_dn_gets hexstring output

If the data is a bitstring or an octet string, instead use the hexstring
of the BER encoding (RFC 4514 Section 2.4)

Signed-off-by: Agathiyan Bragadeesh <agathiyan.bragadeesh2@arm.com>
diff --git a/library/x509.c b/library/x509.c
index b36e27a..5298693 100644
--- a/library/x509.c
+++ b/library/x509.c
@@ -43,6 +43,10 @@
 #include "mbedtls/pem.h"
 #endif
 
+#if defined(MBEDTLS_ASN1_WRITE_C)
+#include "mbedtls/asn1write.h"
+#endif
+
 #include "mbedtls/platform.h"
 
 #if defined(MBEDTLS_HAVE_TIME)
@@ -822,11 +826,16 @@
 int mbedtls_x509_dn_gets(char *buf, size_t size, const mbedtls_x509_name *dn)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    size_t i, j, n;
+    size_t i, j, n, asn1_len_size;
+    unsigned char asn1_len_buf[5];
+    int asn1_len_start;
+    unsigned char *asn1_len_p;
     unsigned char c, merge = 0;
     const mbedtls_x509_name *name;
     const char *short_name = NULL;
+    char numericoid[MBEDTLS_X509_MAX_DN_NAME_SIZE];
     char s[MBEDTLS_X509_MAX_DN_NAME_SIZE], *p;
+    int is_numericoid = 0;
 
     memset(s, 0, sizeof(s));
 
@@ -845,43 +854,82 @@
             MBEDTLS_X509_SAFE_SNPRINTF;
         }
 
-        ret = mbedtls_oid_get_attr_short_name(&name->oid, &short_name);
+        is_numericoid = (name->val.tag == MBEDTLS_ASN1_BIT_STRING) || (name->val.tag == MBEDTLS_ASN1_OCTET_STRING);
 
-        if (ret == 0) {
-            ret = mbedtls_snprintf(p, n, "%s=", short_name);
-        } else {
-            ret = mbedtls_snprintf(p, n, "\?\?=");
+        if(is_numericoid) {
+            ret = mbedtls_oid_get_numeric_string(numericoid,MBEDTLS_X509_MAX_DN_NAME_SIZE,&name->oid);
+            if (ret > 0) {
+                ret = mbedtls_snprintf(p, n, "%s=", numericoid);
+            } else {
+                ret = mbedtls_snprintf(p, n, "\?\?=");
+            }
+            MBEDTLS_X509_SAFE_SNPRINTF;
         }
-        MBEDTLS_X509_SAFE_SNPRINTF;
-
-        for (i = 0, j = 0; i < name->val.len; i++, j++) {
-            if (j >= sizeof(s) - 1) {
-                return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
+        else {
+            ret = mbedtls_oid_get_attr_short_name(&name->oid, &short_name);
+            if (ret == 0) {
+                ret = mbedtls_snprintf(p, n, "%s=", short_name);
+            } else {
+                ret = mbedtls_snprintf(p, n, "\?\?=");
             }
+            MBEDTLS_X509_SAFE_SNPRINTF;
+        }
 
-            c = name->val.p[i];
-            // Special characters requiring escaping, RFC 4514 Section 2.4
-            if (c) {
-                if (strchr(",=+<>;\"\\+", c) ||
-                    ((i == 0) && strchr("# ", c)) ||
-                    ((i == name->val.len-1) && (c == ' '))) {
-                    if (j + 1 >= sizeof(s) - 1) {
-                        return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
-                    }
-                    s[j++] = '\\';
-                }
-            }
-            if (c < 32 || c >= 127) {
-                if (j + 3 >= sizeof(s) - 1) {
+        if(is_numericoid) {
+            s[0] = '#';
+            c = name->val.tag;
+            char lowbits = (c & 0x0F);
+            char highbits = c>>4;
+            s[1] = nibble_to_hex_digit(highbits);
+            s[2] = nibble_to_hex_digit(lowbits);
+            asn1_len_p = asn1_len_buf+5;
+            asn1_len_size = mbedtls_asn1_write_len(&asn1_len_p,asn1_len_buf,name->val.len);
+            asn1_len_start = 5 - asn1_len_size;
+            for (i = 0, j = 3; i < asn1_len_size + name->val.len; i++, j++) {
+                if (j + 1 >= sizeof(s) - 1) {
                     return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
                 }
-                s[j++] = '\\';
+                if(i < asn1_len_size) {
+                    c = asn1_len_buf[asn1_len_start+i];
+                }
+                else {
+                    c = name->val.p[i-asn1_len_size];
+                }
                 char lowbits = (c & 0x0F);
                 char highbits = c>>4;
                 s[j++] = nibble_to_hex_digit(highbits);
                 s[j] = nibble_to_hex_digit(lowbits);
-            } else {
-                s[j] = c;
+            }
+        } else {
+            for (i = 0, j = 0; i < name->val.len; i++, j++) {
+                if (j >= sizeof(s) - 1) {
+                    return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
+                }
+
+                c = name->val.p[i];
+                // Special characters requiring escaping, RFC 4514 Section 2.4
+                if (c) {
+                    if (strchr(",=+<>;\"\\+", c) ||
+                        ((i == 0) && strchr("# ", c)) ||
+                        ((i == name->val.len-1) && (c == ' '))) {
+                        if (j + 1 >= sizeof(s) - 1) {
+                            return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
+                        }
+                        s[j++] = '\\';
+                    }
+                }
+                if (c < 32 || c >= 127) {
+                    if (j + 3 >= sizeof(s) - 1) {
+                        return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
+                    }
+                    s[j++] = '\\';
+                    char lowbits = (c & 0x0F);
+                    char highbits = c>>4;
+                    s[j++] = nibble_to_hex_digit(highbits);
+                    s[j] = nibble_to_hex_digit(lowbits);
+                } else {
+                    s[j] = c;
+                }
             }
         }
         s[j] = '\0';