diff --git a/library/x509.c b/library/x509.c index 2764ba6006..5025d774b4 100644 --- a/library/x509.c +++ b/library/x509.c @@ -810,6 +810,12 @@ int mbedtls_x509_get_ext(unsigned char **p, const unsigned char *end, return 0; } +/* Converts only the 4 least significant bits */ +static char x509_int_to_hexdigit(int i) +{ + return (i < 10) ? (i | 0x30) : ((i - 9) | 0x40); +} + /* * Store the name in printable form into buf; no more * than size characters will be written @@ -857,9 +863,9 @@ int mbedtls_x509_dn_gets(char *buf, size_t size, const mbedtls_x509_name *dn) 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 (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; } @@ -867,7 +873,14 @@ int mbedtls_x509_dn_gets(char *buf, size_t size, const mbedtls_x509_name *dn) } } if (c < 32 || c >= 127) { - s[j] = '?'; + 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++] = x509_int_to_hexdigit(highbits); + s[j] = x509_int_to_hexdigit(lowbits); } else { s[j] = c; } diff --git a/library/x509_create.c b/library/x509_create.c index 170a6bc29c..9652a20c6d 100644 --- a/library/x509_create.c +++ b/library/x509_create.c @@ -123,6 +123,16 @@ static const x509_attr_descriptor_t *x509_attr_descr_from_name(const char *name, return cur; } +static int x509_is_char_hex(char c) +{ + return ('0' <= c && c <= '9') || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F'); +} + +static int x509_hex_to_int(char c) +{ + return ((c & 0x40) ? (c + 9) : c) & 0x0F; +} + int mbedtls_x509_string_to_names(mbedtls_asn1_named_data **head, const char *name) { int ret = MBEDTLS_ERR_X509_INVALID_NAME; @@ -131,6 +141,7 @@ int mbedtls_x509_string_to_names(mbedtls_asn1_named_data **head, const char *nam const char *oid = NULL; const x509_attr_descriptor_t *attr_descr = NULL; int in_tag = 1; + int hexpair = 0; char data[MBEDTLS_X509_MAX_DN_NAME_SIZE]; char *d = data; @@ -154,7 +165,11 @@ int mbedtls_x509_string_to_names(mbedtls_asn1_named_data **head, const char *nam c++; /* Check for valid escaped characters in RFC 4514 in Section 3*/ - if (c == end || !strchr(" ,=+<>#;\"\\+", *c)) { + 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; } @@ -182,7 +197,7 @@ int mbedtls_x509_string_to_names(mbedtls_asn1_named_data **head, const char *nam ret = 0; } - if (!in_tag && s != c + 1) { + if (!hexpair && !in_tag && s != c + 1) { *(d++) = *c; if (d - data == MBEDTLS_X509_MAX_DN_NAME_SIZE) { @@ -191,6 +206,7 @@ int mbedtls_x509_string_to_names(mbedtls_asn1_named_data **head, const char *nam } } + hexpair = 0; c++; } diff --git a/tests/suites/test_suite_x509write.data b/tests/suites/test_suite_x509write.data index e50f590dbc..0987faef2a 100644 --- a/tests/suites/test_suite_x509write.data +++ b/tests/suites/test_suite_x509write.data @@ -196,5 +196,14 @@ mbedtls_x509_string_to_names:"C=NL, O=#Offspark#, OU=PolarSSL":"C=NL, O=\\#Offsp X509 String to Names #10 (Escape ' ' at beginning and end of string) mbedtls_x509_string_to_names:"C=NL, O= Off spark , OU=PolarSSL":"C=NL, O=\\ Off spark\\ , OU=PolarSSL":0 +X509 String to Names #11 (Escape ascii hexpairs) +mbedtls_x509_string_to_names:"C=NL, O=Of\\66spark, OU=PolarSSL":"C=NL, O=Offspark, OU=PolarSSL":0 + +X509 String to Names #12 (Escape non-ascii hexpairs) +mbedtls_x509_string_to_names:"C=NL, O=Of\\00spark, OU=PolarSSL":"C=NL, O=Of\\00spark, OU=PolarSSL":0 + +X509 String to Names #13 (Invalid hexpairs) +mbedtls_x509_string_to_names:"C=NL, O=Of\\flspark, OU=PolarSSL":"":MBEDTLS_ERR_X509_INVALID_NAME + Check max serial length x509_set_serial_check: