x509: Verify ordering of SET OF members

This is also an ASN.1 DER requirement.

Signed-off-by: Demi Marie Obenour <demiobenour@gmail.com>
This commit is contained in:
Demi Marie Obenour 2022-11-26 23:29:10 -05:00
parent 13230a4ad3
commit 9812997bf8

View File

@ -501,8 +501,8 @@ int mbedtls_x509_get_name(unsigned char **p, const unsigned char *end,
mbedtls_x509_name *cur) mbedtls_x509_name *cur)
{ {
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t set_len; size_t set_len, last_len, this_len;
const unsigned char *end_set; const unsigned char *end_set, *last_p, *next_p;
mbedtls_x509_name *head = cur; mbedtls_x509_name *head = cur;
/* don't use recursion, we'd risk stack overflow if not optimized */ /* don't use recursion, we'd risk stack overflow if not optimized */
@ -518,11 +518,29 @@ int mbedtls_x509_get_name(unsigned char **p, const unsigned char *end,
end_set = *p + set_len; end_set = *p + set_len;
last_p = NULL;
while (1) { while (1) {
next_p = *p;
if ((ret = x509_get_attr_type_value(p, end_set, cur)) != 0) { if ((ret = x509_get_attr_type_value(p, end_set, cur)) != 0) {
goto error; goto error;
} }
this_len = (size_t) (*p - next_p);
if (last_p != NULL) {
size_t len_for_compare = this_len <= last_len ? this_len : last_len;
int delta = memcmp(last_p, next_p, len_for_compare);
if (delta > 0 || (delta == 0 && this_len <= last_len)) {
/* unsorted ASN.1 SET OF */
ret = MBEDTLS_ERR_X509_INVALID_NAME;
goto error;
}
}
last_p = next_p;
last_len = this_len;
if (*p == end_set) { if (*p == end_set) {
break; break;
} }