diff --git a/modules/libpref/init/StaticPrefList.yaml b/modules/libpref/init/StaticPrefList.yaml index 50dce4059679..14bb4a1f14a7 100644 --- a/modules/libpref/init/StaticPrefList.yaml +++ b/modules/libpref/init/StaticPrefList.yaml @@ -10506,6 +10506,18 @@ value: true mirror: always +# Partition the OCSP cache by the partitionKey. +- name: privacy.partition.network_state.ocsp_cache + type: RelaxedAtomicBool + value: @IS_NIGHTLY_BUILD@ + mirror: always + +# Partition the OCSP cache by the partitionKey for private browsing mode. +- name: privacy.partition.network_state.ocsp_cache.pbmode + type: RelaxedAtomicBool + value: true + mirror: always + - name: privacy.partition.bloburl_per_agent_cluster type: RelaxedAtomicBool value: false diff --git a/security/certverifier/OCSPCache.cpp b/security/certverifier/OCSPCache.cpp index 2036c0e20238..b9d057470616 100644 --- a/security/certverifier/OCSPCache.cpp +++ b/security/certverifier/OCSPCache.cpp @@ -28,6 +28,7 @@ #include "NSSCertDBTrustDomain.h" #include "pk11pub.h" +#include "mozilla/StaticPrefs_privacy.h" #include "mozpkix/pkixnss.h" #include "ScopedNSSTypes.h" #include "secerr.h" @@ -63,8 +64,11 @@ static SECStatus DigestLength(UniquePK11Context& context, uint32_t length) { // It is only non-empty when "privacy.firstParty.isolate" is enabled, in order // to isolate OCSP cache by first party. // Let firstPartyDomainLen be the number of bytes of firstPartyDomain. +// Let partitionKey be the partition key of originAttributes. +// Let partitionKeyLen be the number of bytes of partitionKey. // The value calculated is SHA384(derIssuer || derPublicKey || serialNumberLen -// || serialNumber || firstPartyDomainLen || firstPartyDomain). +// || serialNumber || firstPartyDomainLen || firstPartyDomain || partitionKeyLen +// || partitionKey). // Because the DER encodings include the length of the data encoded, and we also // include the length of serialNumber and originAttributes, there do not exist // A(derIssuerA, derPublicKeyA, serialNumberLenA, serialNumberA, @@ -108,17 +112,36 @@ static SECStatus CertIDHash(SHA384Buffer& buf, const CertID& certID, return rv; } - // OCSP should not be isolated by containers. - NS_ConvertUTF16toUTF8 firstPartyDomain(originAttributes.mFirstPartyDomain); - if (!firstPartyDomain.IsEmpty()) { - rv = DigestLength(context, firstPartyDomain.Length()); + auto populateOriginAttributesKey = [&context](const nsString& aKey) { + NS_ConvertUTF16toUTF8 key(aKey); + + if (key.IsEmpty()) { + return SECSuccess; + } + + SECStatus rv = DigestLength(context, key.Length()); if (rv != SECSuccess) { return rv; } - rv = - PK11_DigestOp(context.get(), - BitwiseCast(firstPartyDomain.get()), - firstPartyDomain.Length()); + + return PK11_DigestOp(context.get(), + BitwiseCast(key.get()), + key.Length()); + }; + + // OCSP should be isolated by firstPartyDomain and partitionKey, but not + // by containers. + rv = populateOriginAttributesKey(originAttributes.mFirstPartyDomain); + if (rv != SECSuccess) { + return rv; + } + + bool isolateByPartitionKey = + originAttributes.mPrivateBrowsingId > 0 + ? StaticPrefs::privacy_partition_network_state_ocsp_cache_pbmode() + : StaticPrefs::privacy_partition_network_state_ocsp_cache(); + if (isolateByPartitionKey) { + rv = populateOriginAttributesKey(originAttributes.mPartitionKey); if (rv != SECSuccess) { return rv; } @@ -174,9 +197,11 @@ bool OCSPCache::FindInternal(const CertID& aCertID, static inline void LogWithCertID(const char* aMessage, const CertID& aCertID, const OriginAttributes& aOriginAttributes) { - NS_ConvertUTF16toUTF8 firstPartyDomain(aOriginAttributes.mFirstPartyDomain); + nsAutoString info = u"firstPartyDomain: "_ns + + aOriginAttributes.mFirstPartyDomain + + u", partitionKey: "_ns + aOriginAttributes.mPartitionKey; MOZ_LOG(gCertVerifierLog, LogLevel::Debug, - (aMessage, &aCertID, firstPartyDomain.get())); + (aMessage, &aCertID, NS_ConvertUTF16toUTF8(info).get())); } void OCSPCache::MakeMostRecentlyUsed(size_t aIndex,