From 34d8dbcc6d256cc6fbdc0266dbc80ae8d9f7d77f Mon Sep 17 00:00:00 2001
From: Paul Bakker
Date: Wed, 14 Nov 2012 12:11:38 +0000
Subject: [PATCH] - Depth that the certificate verify callback receives is
now numbered bottom-up (Peer cert depth is 0)
---
ChangeLog | 4 ++++
include/polarssl/x509.h | 2 +-
library/x509parse.c | 47 ++++++++++++++++++++++++++---------------
3 files changed, 35 insertions(+), 18 deletions(-)
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 );
}