Index: net/cert/cert_verify_proc_nss.cc |
diff --git a/net/cert/cert_verify_proc_nss.cc b/net/cert/cert_verify_proc_nss.cc |
index 1236f41dda43036f5a76343710f1cc8938bafaaa..02a584fe9837a6803af0a86934ab45b3f055b81e 100644 |
--- a/net/cert/cert_verify_proc_nss.cc |
+++ b/net/cert/cert_verify_proc_nss.cc |
@@ -33,6 +33,10 @@ |
#include "net/cert/x509_util_ios.h" |
#endif // defined(OS_IOS) |
+#if defined(USE_NSS_CERTS) |
+#include <dlfcn.h> |
+#endif |
+ |
namespace net { |
namespace { |
@@ -756,7 +760,14 @@ CERTCertList* CertificateListToCERTCertList(const CertificateList& list) { |
} // namespace |
-CertVerifyProcNSS::CertVerifyProcNSS() {} |
+CertVerifyProcNSS::CertVerifyProcNSS() |
+#if defined(USE_NSS_CERTS) |
+ : cache_ocsp_response_from_side_channel_( |
+ reinterpret_cast<CacheOCSPResponseFromSideChannelFunction>( |
+ dlsym(RTLD_DEFAULT, "CERT_CacheOCSPResponseFromSideChannel"))) |
+#endif |
+{ |
+} |
CertVerifyProcNSS::~CertVerifyProcNSS() {} |
@@ -764,9 +775,19 @@ bool CertVerifyProcNSS::SupportsAdditionalTrustAnchors() const { |
return true; |
} |
+bool CertVerifyProcNSS::SupportsOCSPStapling() const { |
+#if defined(USE_NSS_CERTS) |
+ return cache_ocsp_response_from_side_channel_; |
+#else |
+ // TODO(davidben): Support OCSP stapling on iOS. |
+ return false; |
+#endif |
+} |
+ |
int CertVerifyProcNSS::VerifyInternalImpl( |
X509Certificate* cert, |
const std::string& hostname, |
+ const std::string& ocsp_response, |
int flags, |
CRLSet* crl_set, |
const CertificateList& additional_trust_anchors, |
@@ -781,6 +802,21 @@ int CertVerifyProcNSS::VerifyInternalImpl( |
CERTCertificate* cert_handle = cert->os_cert_handle(); |
#endif // defined(OS_IOS) |
+#if defined(USE_NSS_CERTS) |
+ if (!ocsp_response.empty() && cache_ocsp_response_from_side_channel_) { |
+ // Note: NSS uses a thread-safe global hash table, so this call will |
+ // affect any concurrent verification operations on |cert| or copies of |
+ // the same certificate. This is an unavoidable limitation of NSS's OCSP |
+ // API. |
+ SECItem ocsp_response_item; |
+ ocsp_response_item.data = reinterpret_cast<unsigned char*>( |
+ const_cast<char*>(ocsp_response.data())); |
+ ocsp_response_item.len = ocsp_response.size(); |
+ cache_ocsp_response_from_side_channel_(CERT_GetDefaultCertDB(), cert_handle, |
+ PR_Now(), &ocsp_response_item, NULL); |
+ } |
+#endif // defined(USE_NSS_CERTS) |
+ |
if (!cert->VerifyNameMatch(hostname, |
&verify_result->common_name_fallback_used)) { |
verify_result->cert_status |= CERT_STATUS_COMMON_NAME_INVALID; |
@@ -928,14 +964,12 @@ int CertVerifyProcNSS::VerifyInternalImpl( |
int CertVerifyProcNSS::VerifyInternal( |
X509Certificate* cert, |
const std::string& hostname, |
+ const std::string& ocsp_response, |
int flags, |
CRLSet* crl_set, |
const CertificateList& additional_trust_anchors, |
CertVerifyResult* verify_result) { |
- return VerifyInternalImpl(cert, |
- hostname, |
- flags, |
- crl_set, |
+ return VerifyInternalImpl(cert, hostname, ocsp_response, flags, crl_set, |
additional_trust_anchors, |
NULL, // chain_verify_callback |
verify_result); |