diff --git a/include/mbedtls/x509.h b/include/mbedtls/x509.h index 6a6fd028b1..e6781b699d 100644 --- a/include/mbedtls/x509.h +++ b/include/mbedtls/x509.h @@ -303,6 +303,9 @@ int mbedtls_x509_get_time( unsigned char **p, const unsigned char *end, mbedtls_x509_time *t ); int mbedtls_x509_get_serial( unsigned char **p, const unsigned char *end, mbedtls_x509_buf *serial ); +int mbedtls_x509_name_cmp( const mbedtls_x509_name *a, + const mbedtls_x509_name *b ); +int mbedtls_x509_memcasecmp( const void *s1, const void *s2, size_t len ); int mbedtls_x509_get_ext( unsigned char **p, const unsigned char *end, mbedtls_x509_buf *ext, int tag ); diff --git a/library/x509.c b/library/x509.c index 58cd871bed..fd9274743f 100644 --- a/library/x509.c +++ b/library/x509.c @@ -484,6 +484,105 @@ int mbedtls_x509_get_name( unsigned char **p, const unsigned char *end, return( 0 ); } +/* + * Like memcmp, but case-insensitive and always returns -1 if different + */ +int mbedtls_x509_memcasecmp( const void *s1, const void *s2, size_t len ) +{ + size_t i; + unsigned char diff; + const unsigned char *n1 = s1, *n2 = s2; + + for( i = 0; i < len; i++ ) + { + diff = n1[i] ^ n2[i]; + + if( diff == 0 ) + continue; + + if( diff == 32 && + ( ( n1[i] >= 'a' && n1[i] <= 'z' ) || + ( n1[i] >= 'A' && n1[i] <= 'Z' ) ) ) + { + continue; + } + + return( -1 ); + } + + return( 0 ); +} + +/* + * Compare two X.509 strings, case-insensitive, and allowing for some encoding + * variations (but not all). + * + * Return 0 if equal, -1 otherwise. + */ +static int x509_string_cmp( const mbedtls_x509_buf *a, + const mbedtls_x509_buf *b ) +{ + if( a->tag == b->tag && + a->len == b->len && + memcmp( a->p, b->p, b->len ) == 0 ) + { + return( 0 ); + } + + if( ( a->tag == MBEDTLS_ASN1_UTF8_STRING || a->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) && + ( b->tag == MBEDTLS_ASN1_UTF8_STRING || b->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) && + a->len == b->len && + mbedtls_x509_memcasecmp( a->p, b->p, b->len ) == 0 ) + { + return( 0 ); + } + + return( -1 ); +} + +/* + * Compare two X.509 Names (aka rdnSequence). + * + * See RFC 5280 section 7.1, though we don't implement the whole algorithm: + * we sometimes return unequal when the full algorithm would return equal, + * but never the other way. (In particular, we don't do Unicode normalisation + * or space folding.) + * + * Return 0 if equal, -1 otherwise. + */ +int mbedtls_x509_name_cmp( const mbedtls_x509_name *a, + const mbedtls_x509_name *b ) +{ + /* Avoid recursion, it might not be optimised by the compiler */ + while( a != NULL || b != NULL ) + { + if( a == NULL || b == NULL ) + return( -1 ); + + /* type */ + if( a->oid.tag != b->oid.tag || + a->oid.len != b->oid.len || + memcmp( a->oid.p, b->oid.p, b->oid.len ) != 0 ) + { + return( -1 ); + } + + /* value */ + if( x509_string_cmp( &a->val, &b->val ) != 0 ) + return( -1 ); + + /* structure of the list of sets */ + if( a->next_merged != b->next_merged ) + return( -1 ); + + a = a->next; + b = b->next; + } + + /* a == NULL == b */ + return( 0 ); +} + static int x509_parse_int( unsigned char **p, size_t n, int *res ) { *res = 0; diff --git a/library/x509_crt.c b/library/x509_crt.c index f1f5473ff6..6bec4d024f 100644 --- a/library/x509_crt.c +++ b/library/x509_crt.c @@ -227,35 +227,6 @@ static int x509_profile_check_key( const mbedtls_x509_crt_profile *profile, return( -1 ); } -/* - * Like memcmp, but case-insensitive and always returns -1 if different - */ -static int x509_memcasecmp( const void *s1, const void *s2, size_t len ) -{ - size_t i; - unsigned char diff; - const unsigned char *n1 = s1, *n2 = s2; - - for( i = 0; i < len; i++ ) - { - diff = n1[i] ^ n2[i]; - - if( diff == 0 ) - continue; - - if( diff == 32 && - ( ( n1[i] >= 'a' && n1[i] <= 'z' ) || - ( n1[i] >= 'A' && n1[i] <= 'Z' ) ) ) - { - continue; - } - - return( -1 ); - } - - return( 0 ); -} - /* * Return 0 if name matches wildcard, -1 otherwise */ @@ -281,7 +252,7 @@ static int x509_check_wildcard( const char *cn, const mbedtls_x509_buf *name ) return( -1 ); if( cn_len - cn_idx == name->len - 1 && - x509_memcasecmp( name->p + 1, cn + cn_idx, name->len - 1 ) == 0 ) + mbedtls_x509_memcasecmp( name->p + 1, cn + cn_idx, name->len - 1 ) == 0 ) { return( 0 ); } @@ -289,74 +260,6 @@ static int x509_check_wildcard( const char *cn, const mbedtls_x509_buf *name ) return( -1 ); } -/* - * Compare two X.509 strings, case-insensitive, and allowing for some encoding - * variations (but not all). - * - * Return 0 if equal, -1 otherwise. - */ -static int x509_string_cmp( const mbedtls_x509_buf *a, const mbedtls_x509_buf *b ) -{ - if( a->tag == b->tag && - a->len == b->len && - memcmp( a->p, b->p, b->len ) == 0 ) - { - return( 0 ); - } - - if( ( a->tag == MBEDTLS_ASN1_UTF8_STRING || a->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) && - ( b->tag == MBEDTLS_ASN1_UTF8_STRING || b->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) && - a->len == b->len && - x509_memcasecmp( a->p, b->p, b->len ) == 0 ) - { - return( 0 ); - } - - return( -1 ); -} - -/* - * Compare two X.509 Names (aka rdnSequence). - * - * See RFC 5280 section 7.1, though we don't implement the whole algorithm: - * we sometimes return unequal when the full algorithm would return equal, - * but never the other way. (In particular, we don't do Unicode normalisation - * or space folding.) - * - * Return 0 if equal, -1 otherwise. - */ -static int x509_name_cmp( const mbedtls_x509_name *a, const mbedtls_x509_name *b ) -{ - /* Avoid recursion, it might not be optimised by the compiler */ - while( a != NULL || b != NULL ) - { - if( a == NULL || b == NULL ) - return( -1 ); - - /* type */ - if( a->oid.tag != b->oid.tag || - a->oid.len != b->oid.len || - memcmp( a->oid.p, b->oid.p, b->oid.len ) != 0 ) - { - return( -1 ); - } - - /* value */ - if( x509_string_cmp( &a->val, &b->val ) != 0 ) - return( -1 ); - - /* structure of the list of sets */ - if( a->next_merged != b->next_merged ) - return( -1 ); - - a = a->next; - b = b->next; - } - - /* a == NULL == b */ - return( 0 ); -} - /* * Reset (init or clear) a verify_chain */ @@ -1838,7 +1741,7 @@ static int x509_crt_verifycrl( mbedtls_x509_crt *crt, mbedtls_x509_crt *ca, while( crl_list != NULL ) { if( crl_list->version == 0 || - x509_name_cmp( &crl_list->issuer, &ca->subject ) != 0 ) + mbedtls_x509_name_cmp( &crl_list->issuer, &ca->subject ) != 0 ) { crl_list = crl_list->next; continue; @@ -1959,7 +1862,7 @@ static int x509_crt_check_parent( const mbedtls_x509_crt *child, int need_ca_bit; /* Parent must be the issuer */ - if( x509_name_cmp( &child->issuer, &parent->subject ) != 0 ) + if( mbedtls_x509_name_cmp( &child->issuer, &parent->subject ) != 0 ) return( -1 ); /* Parent must have the basicConstraints CA bit set as a general rule */ @@ -2225,7 +2128,7 @@ static int x509_crt_check_ee_locally_trusted( mbedtls_x509_crt *cur; /* must be self-issued */ - if( x509_name_cmp( &crt->issuer, &crt->subject ) != 0 ) + if( mbedtls_x509_name_cmp( &crt->issuer, &crt->subject ) != 0 ) return( -1 ); /* look for an exact match with trusted cert */ @@ -2390,7 +2293,7 @@ find_parent: * These can occur with some strategies for key rollover, see [SIRO], * and should be excluded from max_pathlen checks. */ if( ver_chain->len != 1 && - x509_name_cmp( &child->issuer, &child->subject ) == 0 ) + mbedtls_x509_name_cmp( &child->issuer, &child->subject ) == 0 ) { self_cnt++; } @@ -2435,7 +2338,7 @@ static int x509_crt_check_cn( const mbedtls_x509_buf *name, { /* try exact match */ if( name->len == cn_len && - x509_memcasecmp( cn, name->p, cn_len ) == 0 ) + mbedtls_x509_memcasecmp( cn, name->p, cn_len ) == 0 ) { return( 0 ); }