Refactor mbedtls_x509_string_to_names
This refactor is to accomodate future support of numericoid/hexstring
attributetype value pairs.
Signed-off-by: Agathiyan Bragadeesh <agathiyan.bragadeesh2@arm.com>
diff --git a/library/x509_create.c b/library/x509_create.c
index 9652a20..8f27cba 100644
--- a/library/x509_create.c
+++ b/library/x509_create.c
@@ -28,6 +28,8 @@
#include <string.h>
+#include "mbedtls/platform.h"
+
/* Structure linking OIDs for X.509 DN AttributeTypes to their
* string representations and default string encodings used by Mbed TLS. */
typedef struct {
@@ -35,7 +37,8 @@
* "CN" or "emailAddress". */
size_t name_len; /* Length of 'name', without trailing 0 byte. */
const char *oid; /* String representation of OID of AttributeType,
- * as per RFC 5280, Appendix A.1. */
+ * as per RFC 5280, Appendix A.1. encoded as per
+ * X.690 */
int default_tag; /* The default character encoding used for the
* given attribute type, e.g.
* MBEDTLS_ASN1_UTF8_STRING for UTF-8. */
@@ -123,27 +126,99 @@
return cur;
}
-static int x509_is_char_hex(char c)
+static const x509_attr_descriptor_t *x509_attr_descr_from_numericoid(const char *numericoid, size_t numericoid_len)
{
- return ('0' <= c && c <= '9') || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F');
+ const x509_attr_descriptor_t *cur;
+ mbedtls_asn1_buf *oid = mbedtls_calloc(1,sizeof(mbedtls_asn1_buf));
+ int ret;
+
+ ret = mbedtls_oid_from_numeric_string(oid, numericoid, numericoid_len);
+ if((ret == MBEDTLS_ERR_X509_ALLOC_FAILED) || (ret == MBEDTLS_ERR_ASN1_INVALID_DATA)) {
+ return NULL;
+ }
+
+ for (cur = x509_attrs; cur->oid != NULL; cur++) {
+ if (sizeof(cur->oid) == oid->len &&
+ strncmp(cur->oid, (const char*) oid->p, oid->len) == 0) {
+ break;
+ }
+ }
+
+ mbedtls_free(oid->p);
+ if (cur->oid == NULL) {
+ return NULL;
+ }
+
+ return cur;
}
-static int x509_hex_to_int(char c)
+static int hex_to_int(char c)
{
- return ((c & 0x40) ? (c + 9) : c) & 0x0F;
+ return ('0' <= c && c <= '9') ? (c - '0') :
+ ('a' <= c && c <= 'f') ? (c - 'a' + 10) :
+ ('A' <= c && c <= 'F') ? (c - 'A' + 10) : -1;
+}
+
+static int hexpair_to_int(char c1, char c2)
+{
+ int n1 = hex_to_int(c1);
+ int n2 = hex_to_int(c2);
+ if (n1 != -1 && n2 != -1) {
+ return (n1 << 4) | n2;
+ } else {
+ return -1;
+ }
+}
+
+static int parse_attribute_value_string(const char *s, int len, char *data, int *data_len) {
+ const char *c = s;
+ const char *end = c + len;
+ int hexpair = 0;
+ char *d = data;
+ int n;
+ while(c < end) {
+ if (*c == '\\') {
+ c++;
+
+ /* Check for valid escaped characters in RFC 4514 in Section 3*/
+ if (c + 1 < end && (n = hexpair_to_int(*c, *(c+1))) != -1) {
+ hexpair = 1;
+ *(d++) = n;
+ c++;
+ } else if (c == end || !strchr(" ,=+<>#;\"\\+", *c)) {
+ return MBEDTLS_ERR_X509_INVALID_NAME;
+ }
+ }
+ if (!hexpair) {
+ *(d++) = *c;
+ }
+ if (d - data == MBEDTLS_X509_MAX_DN_NAME_SIZE) {
+ return MBEDTLS_ERR_X509_INVALID_NAME;
+ }
+
+ hexpair = 0;
+ c++;
+ }
+ *data_len = d - data;
+ return 0;
+}
+
+static int parse_attribute_value_ber_encoded(const char *s, int len, char *data, int *data_len) {
+ return 0;
}
int mbedtls_x509_string_to_names(mbedtls_asn1_named_data **head, const char *name)
{
int ret = MBEDTLS_ERR_X509_INVALID_NAME;
+ int parse_ret = 0;
const char *s = name, *c = s;
const char *end = s + strlen(s);
const char *oid = NULL;
const x509_attr_descriptor_t *attr_descr = NULL;
int in_tag = 1;
- int hexpair = 0;
+ int numericoid = 0;
char data[MBEDTLS_X509_MAX_DN_NAME_SIZE];
- char *d = data;
+ int data_len = 0;
/* Clear existing chain if present */
mbedtls_asn1_free_named_data_list(head);
@@ -151,34 +226,35 @@
while (c <= end) {
if (in_tag && *c == '=') {
if ((attr_descr = x509_attr_descr_from_name(s, c - s)) == NULL) {
- ret = MBEDTLS_ERR_X509_UNKNOWN_OID;
- goto exit;
+ if ((attr_descr = x509_attr_descr_from_numericoid(s, c - s)) == NULL) {
+ return MBEDTLS_ERR_X509_UNKNOWN_OID;
+ } else {
+ numericoid = 1;
+ }
+ } else {
+ numericoid = 0;
}
oid = attr_descr->oid;
s = c + 1;
in_tag = 0;
- d = data;
}
- if (!in_tag && *c == '\\' && c != end) {
- c++;
-
- /* Check for valid escaped characters in RFC 4514 in Section 3*/
- if (c + 1 < end && x509_is_char_hex(*c) && x509_is_char_hex(*(c+1))) {
- hexpair = 1;
- *(d++) = (x509_hex_to_int(*c) << 4) + x509_hex_to_int(*(c+1));
- c++;
- } else if (c == end || !strchr(" ,=+<>#;\"\\+", *c)) {
- ret = MBEDTLS_ERR_X509_INVALID_NAME;
- goto exit;
+ if(!in_tag && ((*c == ',' && *(c-1) != '\\') || c == end)) {
+ if(!numericoid) {
+ if((parse_ret = parse_attribute_value_string(s, c - s, data, &data_len)) != 0) {
+ return MBEDTLS_ERR_X509_INVALID_NAME;
+ }
}
- } else if (!in_tag && (*c == ',' || c == end)) {
+ if(numericoid) {
+ if((parse_ret = parse_attribute_value_ber_encoded(s, c - s, data, &data_len)) != 0) {
+ return MBEDTLS_ERR_X509_INVALID_NAME;
+ }
+ }
mbedtls_asn1_named_data *cur =
mbedtls_asn1_store_named_data(head, oid, strlen(oid),
(unsigned char *) data,
- d - data);
-
+ data_len);
if (cur == NULL) {
return MBEDTLS_ERR_X509_ALLOC_FAILED;
}
@@ -196,22 +272,8 @@
/* Successfully parsed one name, update ret to success */
ret = 0;
}
-
- if (!hexpair && !in_tag && s != c + 1) {
- *(d++) = *c;
-
- if (d - data == MBEDTLS_X509_MAX_DN_NAME_SIZE) {
- ret = MBEDTLS_ERR_X509_INVALID_NAME;
- goto exit;
- }
- }
-
- hexpair = 0;
c++;
}
-
-exit:
-
return ret;
}