[tbb-commits] [tor-browser/tor-browser-31.2.0esr-4.5-1] squash! Bug #11955 Backport certificate pinning

mikeperry at torproject.org mikeperry at torproject.org
Fri Nov 7 21:25:25 UTC 2014


commit 2822ccdb6d00b563413a285fe63488ab2ca7b460
Author: Camilo Viecco <cviecco at mozilla.com>
Date:   Thu Nov 6 10:30:37 2014 -0800

    squash! Bug #11955 Backport certificate pinning
    
    Bug #13684: Backport Mozilla's Bug 1066190
---
 security/certverifier/CertVerifier.cpp |   48 ++++++++++++++++++++++++++++++++
 1 file changed, 48 insertions(+)

diff --git a/security/certverifier/CertVerifier.cpp b/security/certverifier/CertVerifier.cpp
index b2db9fc..1af728e 100644
--- a/security/certverifier/CertVerifier.cpp
+++ b/security/certverifier/CertVerifier.cpp
@@ -197,6 +197,36 @@ SECStatus chainValidationCallback(void* state, const CERTCertList* certList,
   return SECSuccess;
 }
 
+// This always returns secfailure but its objective is to replate
+// the PR_Error
+static void
+tryWorsenPRErrorInCallback(CERTCertificate* cert,
+                           ChainValidationCallbackState* callbackState) {
+  ScopedCERTCertificate certCopy(CERT_DupCertificate(cert));
+  if (!certCopy) {
+    return;
+  }
+  ScopedCERTCertList certList(CERT_NewCertList());
+  if (!certList) {
+    return;
+  }
+  SECStatus srv = CERT_AddCertToListTail(certList.get(), certCopy.get());
+  if (srv != SECSuccess) {
+    return;
+  }
+  certCopy.release(); // now owned by certList
+  PRBool chainOK = false;
+  srv = chainValidationCallback(&callbackState, certList.get(), &chainOK);
+  if (srv != SECSuccess) {
+    return;
+  }
+  if (!chainOK) {
+    PR_SetError(SEC_ERROR_APPLICATION_CALLBACK_ERROR, 0); // same as libpkix
+    return ;
+  }
+  return; // no change in PR_error
+}
+
 static SECStatus
 ClassicVerifyCert(CERTCertificate* cert,
                   const SECCertificateUsage usage,
@@ -276,6 +306,12 @@ ClassicVerifyCert(CERTCertificate* cert,
         return SECFailure;
       }
     }
+
+    // If there is an error we may need to worsen to error to be a pinning failure
+    if (rv != SECSuccess && usage == certificateUsageSSLServer) {
+      tryWorsenPRErrorInCallback(cert, callbackState);
+    }
+
     if (rv == SECSuccess && validationChain) {
       *validationChain = certChain.release();
     }
@@ -545,6 +581,12 @@ CertVerifier::MozillaPKIXVerifyCert(
       return SECFailure;
   }
 
+  // If there is an error we may need to worsen to error to be a pinning failure
+  if (rv != SECSuccess && usage == certificateUsageSSLServer &&
+      PR_GetError() != SEC_ERROR_APPLICATION_CALLBACK_ERROR) {
+    tryWorsenPRErrorInCallback(cert, callbackState);
+  }
+
   if (validationChain && rv == SECSuccess) {
     *validationChain = builtChain.release();
   }
@@ -876,6 +918,12 @@ CertVerifier::VerifyCert(CERTCertificate* cert,
   rv = CERT_PKIXVerifyCert(cert, usage, cvin, cvout, pinArg);
 
 pkix_done:
+  // If there is an error we may need to worsen to error to be a pinning failure
+  if (rv != SECSuccess && usage == certificateUsageSSLServer &&
+      PR_GetError() != SEC_ERROR_APPLICATION_CALLBACK_ERROR) {
+    tryWorsenPRErrorInCallback(cert, &callbackState);
+  }
+
   if (validationChain) {
     PR_LOG(gCertVerifierLog, PR_LOG_DEBUG, ("VerifyCert: validation chain requested\n"));
     ScopedCERTCertificate trustAnchor(cvout[validationTrustAnchorLocation].value.pointer.cert);



More information about the tbb-commits mailing list