Commit 1cd9a264 authored by Vlad Tsyrklevich's avatar Vlad Tsyrklevich Committed by Commit Bot

net/cert: Deprecate use of base::ProtectedMemory

base::ProtectedMemory is being deprecated because it's not widely used
enough to make a security impact and justify its maintenance burden.
Replace use of base::ProtectedMemory with raw function pointers and add
an attribute to disable CFI-icall checking.

Bug: 1018834
Change-Id: Ia79aa823ab42e89b7103b8b89e65cda0c24dbb3b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1885010
Commit-Queue: Vlad Tsyrklevich <vtsyrklevich@chromium.org>
Reviewed-by: default avatarRyan Sleevi <rsleevi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#710618}
parent 4fb387e0
...@@ -15,10 +15,9 @@ ...@@ -15,10 +15,9 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "base/compiler_specific.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/protected_memory.h"
#include "base/memory/protected_memory_cfi.h"
#include "base/stl_util.h" #include "base/stl_util.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "crypto/nss_util.h" #include "crypto/nss_util.h"
...@@ -49,22 +48,6 @@ using CacheOCSPResponseFunction = SECStatus (*)(CERTCertDBHandle* handle, ...@@ -49,22 +48,6 @@ using CacheOCSPResponseFunction = SECStatus (*)(CERTCertDBHandle* handle,
const SECItem* encodedResponse, const SECItem* encodedResponse,
void* pwArg); void* pwArg);
static PROTECTED_MEMORY_SECTION base::ProtectedMemory<CacheOCSPResponseFunction>
g_cache_ocsp_response;
// The function pointer for CERT_CacheOCSPResponseFromSideChannel is saved to
// read-only memory after being dynamically resolved as a security mitigation to
// prevent the pointer from being tampered with. See crbug.com/771365 for
// details.
const base::ProtectedMemory<CacheOCSPResponseFunction>&
ResolveCacheOCSPResponse() {
static base::ProtectedMemory<CacheOCSPResponseFunction>::Initializer init(
&g_cache_ocsp_response,
reinterpret_cast<CacheOCSPResponseFunction>(
dlsym(RTLD_DEFAULT, "CERT_CacheOCSPResponseFromSideChannel")));
return g_cache_ocsp_response;
}
typedef std::unique_ptr< typedef std::unique_ptr<
CERTCertificatePolicies, CERTCertificatePolicies,
crypto::NSSDestroyer<CERTCertificatePolicies, crypto::NSSDestroyer<CERTCertificatePolicies,
...@@ -826,6 +809,7 @@ bool CertVerifyProcNSS::SupportsAdditionalTrustAnchors() const { ...@@ -826,6 +809,7 @@ bool CertVerifyProcNSS::SupportsAdditionalTrustAnchors() const {
return true; return true;
} }
NO_SANITIZE("cfi-icall")
int CertVerifyProcNSS::VerifyInternalImpl( int CertVerifyProcNSS::VerifyInternalImpl(
X509Certificate* cert, X509Certificate* cert,
const std::string& hostname, const std::string& hostname,
...@@ -851,7 +835,10 @@ int CertVerifyProcNSS::VerifyInternalImpl( ...@@ -851,7 +835,10 @@ int CertVerifyProcNSS::VerifyInternalImpl(
} }
CERTCertificate* cert_handle = input_chain[0].get(); CERTCertificate* cert_handle = input_chain[0].get();
if (!ocsp_response.empty() && *ResolveCacheOCSPResponse() != nullptr) { static CacheOCSPResponseFunction cache_ocsp_response_from_side_channel =
reinterpret_cast<CacheOCSPResponseFunction>(
dlsym(RTLD_DEFAULT, "CERT_CacheOCSPResponseFromSideChannel"));
if (!ocsp_response.empty() && cache_ocsp_response_from_side_channel) {
// Note: NSS uses a thread-safe global hash table, so this call will // Note: NSS uses a thread-safe global hash table, so this call will
// affect any concurrent verification operations on |cert| or copies of // affect any concurrent verification operations on |cert| or copies of
// the same certificate. This is an unavoidable limitation of NSS's OCSP // the same certificate. This is an unavoidable limitation of NSS's OCSP
...@@ -860,9 +847,9 @@ int CertVerifyProcNSS::VerifyInternalImpl( ...@@ -860,9 +847,9 @@ int CertVerifyProcNSS::VerifyInternalImpl(
ocsp_response_item.data = reinterpret_cast<unsigned char*>( ocsp_response_item.data = reinterpret_cast<unsigned char*>(
const_cast<char*>(ocsp_response.data())); const_cast<char*>(ocsp_response.data()));
ocsp_response_item.len = ocsp_response.size(); ocsp_response_item.len = ocsp_response.size();
UnsanitizedCfiCall(ResolveCacheOCSPResponse())( cache_ocsp_response_from_side_channel(CERT_GetDefaultCertDB(), cert_handle,
CERT_GetDefaultCertDB(), cert_handle, PR_Now(), &ocsp_response_item, PR_Now(), &ocsp_response_item,
nullptr); nullptr);
} }
// Setup a callback to call into CheckChainRevocationWithCRLSet with the // Setup a callback to call into CheckChainRevocationWithCRLSet with the
......
...@@ -11,8 +11,7 @@ ...@@ -11,8 +11,7 @@
#include <memory> #include <memory>
#include "base/memory/protected_memory.h" #include "base/compiler_specific.h"
#include "base/memory/protected_memory_cfi.h"
#include "crypto/nss_util_internal.h" #include "crypto/nss_util_internal.h"
#include "net/base/hash_value.h" #include "net/base/hash_value.h"
#include "net/cert/x509_util_nss.h" #include "net/cert/x509_util_nss.h"
...@@ -30,31 +29,20 @@ using PK11HasAttributeSetFunction = CK_BBOOL (*)(PK11SlotInfo* slot, ...@@ -30,31 +29,20 @@ using PK11HasAttributeSetFunction = CK_BBOOL (*)(PK11SlotInfo* slot,
CK_OBJECT_HANDLE id, CK_OBJECT_HANDLE id,
CK_ATTRIBUTE_TYPE type, CK_ATTRIBUTE_TYPE type,
PRBool haslock); PRBool haslock);
static PROTECTED_MEMORY_SECTION
base::ProtectedMemory<PK11HasAttributeSetFunction>
g_pk11_has_attribute_set;
// The function pointer for PK11_HasAttributeSet is saved to read-only memory
// after being dynamically resolved as a security mitigation to prevent the
// pointer from being tampered with. See https://crbug.com/771365 for details.
const base::ProtectedMemory<PK11HasAttributeSetFunction>&
ResolvePK11HasAttributeSet() {
static base::ProtectedMemory<PK11HasAttributeSetFunction>::Initializer init(
&g_pk11_has_attribute_set,
reinterpret_cast<PK11HasAttributeSetFunction>(
dlsym(RTLD_DEFAULT, "PK11_HasAttributeSet")));
return g_pk11_has_attribute_set;
}
} // namespace } // namespace
// IsKnownRoot returns true if the given certificate is one that we believe // IsKnownRoot returns true if the given certificate is one that we believe
// is a standard (as opposed to user-installed) root. // is a standard (as opposed to user-installed) root.
NO_SANITIZE("cfi-icall")
bool IsKnownRoot(CERTCertificate* root) { bool IsKnownRoot(CERTCertificate* root) {
if (!root || !root->slot) if (!root || !root->slot)
return false; return false;
if (*ResolvePK11HasAttributeSet() != nullptr) { static PK11HasAttributeSetFunction pk11_has_attribute_set =
reinterpret_cast<PK11HasAttributeSetFunction>(
dlsym(RTLD_DEFAULT, "PK11_HasAttributeSet"));
if (pk11_has_attribute_set) {
// Historically, the set of root certs was determined based on whether or // Historically, the set of root certs was determined based on whether or
// not it was part of nssckbi.[so,dll], the read-only PKCS#11 module that // not it was part of nssckbi.[so,dll], the read-only PKCS#11 module that
// exported the certs with trust settings. However, some distributions, // exported the certs with trust settings. However, some distributions,
...@@ -76,9 +64,9 @@ bool IsKnownRoot(CERTCertificate* root) { ...@@ -76,9 +64,9 @@ bool IsKnownRoot(CERTCertificate* root) {
if (PK11_IsPresent(slot) && PK11_HasRootCerts(slot)) { if (PK11_IsPresent(slot) && PK11_HasRootCerts(slot)) {
CK_OBJECT_HANDLE handle = PK11_FindCertInSlot(slot, root, nullptr); CK_OBJECT_HANDLE handle = PK11_FindCertInSlot(slot, root, nullptr);
if (handle != CK_INVALID_HANDLE && if (handle != CK_INVALID_HANDLE &&
UnsanitizedCfiCall(ResolvePK11HasAttributeSet())( pk11_has_attribute_set(root->slot, handle,
root->slot, handle, CKA_NSS_MOZILLA_CA_POLICY, PR_FALSE) == CKA_NSS_MOZILLA_CA_POLICY,
CK_TRUE) { PR_FALSE) == CK_TRUE) {
return true; return true;
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment