mbedtls_x509_csr_info: Add parsing code for v3 csr extensions

Signed-off-by: Przemek Stekiel <przemyslaw.stekiel@mobica.com>
diff --git a/include/mbedtls/x509.h b/include/mbedtls/x509.h
index a98748c..57e0727 100644
--- a/include/mbedtls/x509.h
+++ b/include/mbedtls/x509.h
@@ -379,6 +379,14 @@
 int x509_get_subject_alt_name(unsigned char **p,
                               const unsigned char *end,
                               mbedtls_x509_sequence *subject_alt_name);
+int x509_info_subject_alt_name(char **buf, size_t *size,
+                               const mbedtls_x509_sequence
+                               *subject_alt_name,
+                               const char *prefix);
+int x509_info_cert_type(char **buf, size_t *size,
+                        unsigned char ns_cert_type);
+int x509_info_key_usage(char **buf, size_t *size,
+                        unsigned int key_usage);
 
 #define MBEDTLS_X509_SAFE_SNPRINTF                          \
     do {                                                    \
diff --git a/include/mbedtls/x509_csr.h b/include/mbedtls/x509_csr.h
index 216a0a2..0c204be 100644
--- a/include/mbedtls/x509_csr.h
+++ b/include/mbedtls/x509_csr.h
@@ -62,6 +62,8 @@
     unsigned char ns_cert_type; /**< Optional Netscape certificate type extension value: See the values in x509.h */
     mbedtls_x509_sequence subject_alt_names;    /**< Optional list of raw entries of Subject Alternative Names extension (currently only dNSName and OtherName are listed). */
 
+    int MBEDTLS_PRIVATE(ext_types);              /**< Bit string containing detected and parsed extensions */
+
     mbedtls_x509_buf sig_oid;
     mbedtls_x509_buf MBEDTLS_PRIVATE(sig);
     mbedtls_md_type_t MBEDTLS_PRIVATE(sig_md);       /**< Internal representation of the MD algorithm of the signature algorithm, e.g. MBEDTLS_MD_SHA256 */
diff --git a/library/x509_crt.c b/library/x509_crt.c
index e02d18e..261525d 100644
--- a/library/x509_crt.c
+++ b/library/x509_crt.c
@@ -1849,10 +1849,10 @@
 }
 
 #if !defined(MBEDTLS_X509_REMOVE_INFO)
-static int x509_info_subject_alt_name(char **buf, size_t *size,
-                                      const mbedtls_x509_sequence
-                                      *subject_alt_name,
-                                      const char *prefix)
+int x509_info_subject_alt_name(char **buf, size_t *size,
+                               const mbedtls_x509_sequence
+                               *subject_alt_name,
+                               const char *prefix)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t i;
@@ -1965,8 +1965,8 @@
     if (ns_cert_type & (type))                 \
     PRINT_ITEM(name);
 
-static int x509_info_cert_type(char **buf, size_t *size,
-                               unsigned char ns_cert_type)
+int x509_info_cert_type(char **buf, size_t *size,
+                        unsigned char ns_cert_type)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t n = *size;
@@ -1992,8 +1992,8 @@
     if (key_usage & (code))    \
     PRINT_ITEM(name);
 
-static int x509_info_key_usage(char **buf, size_t *size,
-                               unsigned int key_usage)
+int x509_info_key_usage(char **buf, size_t *size,
+                        unsigned int key_usage)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t n = *size;
diff --git a/library/x509_csr.c b/library/x509_csr.c
index 824d17a..f1c4c66 100644
--- a/library/x509_csr.c
+++ b/library/x509_csr.c
@@ -111,7 +111,19 @@
                    MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
         }
 
-        if (mbedtls_oid_get_x509_ext_type(&extn_oid, &ext_type) == 0) {
+        /*
+         * Detect supported extensions
+         */
+        ret = mbedtls_oid_get_x509_ext_type(&extn_oid, &ext_type);
+
+        if (ret == 0) {
+            /* Forbid repeated extensions */
+            if ((csr->ext_types & ext_type) != 0) {
+                return MBEDTLS_ERR_X509_INVALID_EXTENSIONS;
+            }
+
+            csr->ext_types |= ext_type;
+
             switch (ext_type) {
                 case MBEDTLS_X509_EXT_KEY_USAGE:
                     /* Parse key usage */
@@ -497,6 +509,44 @@
                            (int) mbedtls_pk_get_bitlen(&csr->pk));
     MBEDTLS_X509_SAFE_SNPRINTF;
 
+    /*
+     * Optional extensions
+     */
+
+    if (csr->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME) {
+        ret = mbedtls_snprintf(p, n, "\n%ssubject alt name  :", prefix);
+        MBEDTLS_X509_SAFE_SNPRINTF;
+
+        if ((ret = x509_info_subject_alt_name(&p, &n,
+                                              &csr->subject_alt_names,
+                                              prefix)) != 0) {
+            return ret;
+        }
+    }
+
+    if (csr->ext_types & MBEDTLS_X509_EXT_NS_CERT_TYPE) {
+        ret = mbedtls_snprintf(p, n, "\n%scert. type        : ", prefix);
+        MBEDTLS_X509_SAFE_SNPRINTF;
+
+        if ((ret = x509_info_cert_type(&p, &n, csr->ns_cert_type)) != 0) {
+            return ret;
+        }
+    }
+
+    if (csr->ext_types & MBEDTLS_X509_EXT_KEY_USAGE) {
+        ret = mbedtls_snprintf(p, n, "\n%skey usage         : ", prefix);
+        MBEDTLS_X509_SAFE_SNPRINTF;
+
+        if ((ret = x509_info_key_usage(&p, &n, csr->key_usage)) != 0) {
+            return ret;
+        }
+    }
+
+    if (csr->ext_types != 0) {
+        ret = mbedtls_snprintf(p, n, "\n");
+        MBEDTLS_X509_SAFE_SNPRINTF;
+    }
+
     return (int) (size - n);
 }
 #endif /* MBEDTLS_X509_REMOVE_INFO */