diff --git a/ChangeLog b/ChangeLog index 13847a834..6b2c96996 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,10 @@ PolarSSL ChangeLog = Version 1.2.1 released 2012-11-13 +Changes + * Depth that the certificate verify callback receives is now numbered + bottom-up (Peer cert depth is 0) + Bugfixes * Fixes for MSVC6 * Moved mpi_inv_mod() outside POLARSSL_GENPRIME diff --git a/include/polarssl/x509.h b/include/polarssl/x509.h index 45a8229f1..87151c927 100644 --- a/include/polarssl/x509.h +++ b/include/polarssl/x509.h @@ -680,7 +680,7 @@ int x509parse_time_expired( const x509_time *time ); * (void *parameter, x509_cert *crt, int certificate_depth, * int *flags). With the flags representing current flags for * that specific certificate and the certificate depth from - * the top (Trust CA depth = 0). + * the bottom (Peer cert depth = 0). * * All flags left after returning from the callback * are also returned to the application. The function should diff --git a/library/x509parse.c b/library/x509parse.c index c56451129..e54e0b78d 100644 --- a/library/x509parse.c +++ b/library/x509parse.c @@ -3114,12 +3114,12 @@ int x509_wildcard_verify( const char *cn, x509_buf *name ) static int x509parse_verify_top( x509_cert *child, x509_cert *trust_ca, - x509_crl *ca_crl, int *path_cnt, int *flags, + x509_crl *ca_crl, int path_cnt, int *flags, int (*f_vrfy)(void *, x509_cert *, int, int *), void *p_vrfy ) { int hash_id, ret; - int ca_flags = 0; + int ca_flags = 0, check_path_cnt = path_cnt + 1; unsigned char hash[64]; if( x509parse_time_expired( &child->valid_to ) ) @@ -3141,8 +3141,19 @@ static int x509parse_verify_top( continue; } + /* + * Reduce path_len to check against if top of the chain is + * the same as the trusted CA + */ + if( child->subject_raw.len == trust_ca->subject_raw.len && + memcmp( child->subject_raw.p, trust_ca->subject_raw.p, + child->issuer_raw.len ) == 0 ) + { + check_path_cnt--; + } + if( trust_ca->max_pathlen > 0 && - trust_ca->max_pathlen < *path_cnt ) + trust_ca->max_pathlen < check_path_cnt ) { trust_ca = trust_ca->next; continue; @@ -3166,7 +3177,13 @@ static int x509parse_verify_top( break; } - if( trust_ca != NULL ) + /* + * If top of chain is not the same as the trusted CA + */ + if( trust_ca != NULL && + ( child->subject_raw.len != trust_ca->subject_raw.len || + memcmp( child->subject_raw.p, trust_ca->subject_raw.p, + child->issuer_raw.len ) != 0 ) ) { /* Check trusted CA's CRL for then chain's top crt */ *flags |= x509parse_verifycrl( child, trust_ca, ca_crl ); @@ -3186,7 +3203,7 @@ static int x509parse_verify_top( if( NULL != f_vrfy ) { - if( ( ret = f_vrfy( p_vrfy, trust_ca, 0, &ca_flags ) ) != 0 ) + if( ( ret = f_vrfy( p_vrfy, trust_ca, path_cnt + 1, &ca_flags ) ) != 0 ) return( ret ); } } @@ -3194,12 +3211,10 @@ static int x509parse_verify_top( /* Call callback on top cert */ if( NULL != f_vrfy ) { - if( ( ret = f_vrfy(p_vrfy, child, 1, flags ) ) != 0 ) + if( ( ret = f_vrfy(p_vrfy, child, path_cnt, flags ) ) != 0 ) return( ret ); } - *path_cnt = 2; - *flags |= ca_flags; return( 0 ); @@ -3207,7 +3222,7 @@ static int x509parse_verify_top( static int x509parse_verify_child( x509_cert *child, x509_cert *parent, x509_cert *trust_ca, - x509_crl *ca_crl, int *path_cnt, int *flags, + x509_crl *ca_crl, int path_cnt, int *flags, int (*f_vrfy)(void *, x509_cert *, int, int *), void *p_vrfy ) { @@ -3246,28 +3261,26 @@ static int x509parse_verify_child( break; } - (*path_cnt)++; if( grandparent != NULL ) { /* * Part of the chain */ - ret = x509parse_verify_child( parent, grandparent, trust_ca, ca_crl, path_cnt, &parent_flags, f_vrfy, p_vrfy ); + ret = x509parse_verify_child( parent, grandparent, trust_ca, ca_crl, path_cnt + 1, &parent_flags, f_vrfy, p_vrfy ); if( ret != 0 ) return( ret ); } else { - ret = x509parse_verify_top( parent, trust_ca, ca_crl, path_cnt, &parent_flags, f_vrfy, p_vrfy ); + ret = x509parse_verify_top( parent, trust_ca, ca_crl, path_cnt + 1, &parent_flags, f_vrfy, p_vrfy ); if( ret != 0 ) return( ret ); } /* child is verified to be a child of the parent, call verify callback */ if( NULL != f_vrfy ) - if( ( ret = f_vrfy( p_vrfy, child, *path_cnt, flags ) ) != 0 ) + if( ( ret = f_vrfy( p_vrfy, child, path_cnt, flags ) ) != 0 ) return( ret ); - (*path_cnt)++; *flags |= parent_flags; @@ -3286,7 +3299,7 @@ int x509parse_verify( x509_cert *crt, { size_t cn_len; int ret; - int pathlen = 1; + int pathlen = 0; x509_cert *parent; x509_name *name; x509_sequence *cur = NULL; @@ -3368,13 +3381,13 @@ int x509parse_verify( x509_cert *crt, /* * Part of the chain */ - ret = x509parse_verify_child( crt, parent, trust_ca, ca_crl, &pathlen, flags, f_vrfy, p_vrfy ); + ret = x509parse_verify_child( crt, parent, trust_ca, ca_crl, pathlen, flags, f_vrfy, p_vrfy ); if( ret != 0 ) return( ret ); } else { - ret = x509parse_verify_top( crt, trust_ca, ca_crl, &pathlen, flags, f_vrfy, p_vrfy ); + ret = x509parse_verify_top( crt, trust_ca, ca_crl, pathlen, flags, f_vrfy, p_vrfy ); if( ret != 0 ) return( ret ); }