- Added verification callback in certificate verification chain in order to allow external blacklisting

diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index 11d50ac..a0be84f 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -1404,7 +1404,8 @@
         }
 
         ret = x509parse_verify( ssl->peer_cert, ssl->ca_chain, ssl->ca_crl,
-                                ssl->peer_cn,  &ssl->verify_result );
+                                ssl->peer_cn,  &ssl->verify_result,
+                                ssl->f_vrfy, ssl->p_vrfy );
 
         if( ret != 0 )
             SSL_DEBUG_RET( 1, "x509_verify_cert", ret );
@@ -1725,6 +1726,14 @@
     ssl->authmode   = authmode;
 }
 
+void ssl_set_verify( ssl_context *ssl,
+                     int (*f_vrfy)(void *, x509_cert *, int, int),
+                     void *p_vrfy )
+{
+    ssl->f_vrfy      = f_vrfy;
+    ssl->p_vrfy      = p_vrfy;
+}
+
 void ssl_set_rng( ssl_context *ssl,
                   int (*f_rng)(void *),
                   void *p_rng )
diff --git a/library/x509parse.c b/library/x509parse.c
index e48ed94..ec7e218 100644
--- a/library/x509parse.c
+++ b/library/x509parse.c
@@ -2335,7 +2335,9 @@
 int x509parse_verify( x509_cert *crt,
                       x509_cert *trust_ca,
                       x509_crl *ca_crl,
-                      const char *cn, int *flags )
+                      const char *cn, int *flags,
+                      int (*f_vrfy)(void *, x509_cert *, int, int),
+                      void *p_vrfy )
 {
     int cn_len;
     int hash_id;
@@ -2380,6 +2382,8 @@
 
     while( cur != NULL && cur->version != 0 )
     {
+        int verify_ok = 1;
+
         if( cur->ca_istrue == 0 ||
             crt->issuer_raw.len != cur->subject_raw.len ||
             memcmp( crt->issuer_raw.p, cur->subject_raw.p,
@@ -2395,7 +2399,15 @@
 
         if( rsa_pkcs1_verify( &cur->rsa, RSA_PUBLIC, hash_id,
                               0, hash, crt->sig.p ) != 0 )
+            verify_ok = 0;
+
+        /* crt is verified to be a child of the parent cur, call verify callback */
+        if( NULL != f_vrfy ) {
+            if ( f_vrfy( p_vrfy, crt, pathlen-1, verify_ok ) != 0 )
+                return( POLARSSL_ERR_X509_CERT_VERIFY_FAILED );
+        } else if ( verify_ok == 0 ) {
             return( POLARSSL_ERR_X509_CERT_VERIFY_FAILED );
+        }
 
         pathlen++;
 
@@ -2495,6 +2507,13 @@
     if( *flags != 0 )
         return( POLARSSL_ERR_X509_CERT_VERIFY_FAILED );
 
+
+    /* Verification succeeded, call callback on top cert */
+    if( NULL != f_vrfy ) {
+        if ( f_vrfy(p_vrfy, crt, pathlen - 1, 1) != 0 )
+            return( POLARSSL_ERR_X509_CERT_VERIFY_FAILED );
+    }
+
     return( 0 );
 }
 
@@ -2676,7 +2695,7 @@
     if( verbose != 0 )
         printf( "passed\n  X.509 signature verify: ");
 
-    ret = x509parse_verify( &clicert, &cacert, NULL, "PolarSSL Client 2", &i );
+    ret = x509parse_verify( &clicert, &cacert, NULL, "PolarSSL Client 2", &i, NULL, NULL );
     if( ret != 0 )
     {
         if( verbose != 0 )