Bug 1593167 Comment 17 Edit History

Note: The actual edited comment in the bug view page will always show the original commenter’s name and original timestamp.

(In reply to Daiki Ueno [:ueno] from comment #14)

> One thing I noticed is that, in the failed case, Firefox doesn't query CKA_MOZILLA_CA_POLICY. It seems that mozilla::psm::NSSCertDBTrustDomain::FindIssuer couldn't find the issuer of a certain certificate, but I'm not sure what is really happening there.

I dug it further with rr and found that the actual difference seems to be in this code path:
```
NSSCertDBTrustDomain::FindIssuer
  -> CheckCandidates
    -> ShouldSkipSelfSignedNonTrustAnchor
      -> NSSCertDBTrustDomain::GetCertTrust
        -> CERT_GetCertTrust
```
When it fails, `ShouldSkipSelfSignedNonTrustAnchor` reports `true` on the "DigiCert Global Root CA" cert, based on the check with `CERT_GetCertTrust` against a temp certificate created by `CERT_NewTempCertificate`. However, this function for some reason returns a cached certificate, which does not have CERTDB_TRUSTED_CA bit set.

The offending certificate comes from a different thread which reads the cache as below. Now the question is why this could happen. Any ideas?
```
#0  add_certificate_entry (store=0x7f4aeaa16870, cert=0x7f4ae6b56888)
#1  nssCertificateStore_AddLocked (cert=0x7f4ae6b56888, store=0x7f4aeaa16870)
#2  nssCertificateStore_FindOrAdd
#3  0x00007f4b098a018f in NSSCryptoContext_FindOrImportCertificate
    (cc=cc@entry=0x7f4aeaa16830, c=c@entry=0x7f4ae6b56888)
#4  0x00007f4b098859ce in CERT_NewTempCertificate
    (handle=<optimized out>, derCert=derCert@entry=0x7f4af0b7e298, nickname=nickname@entry=0x0, isperm=isperm@entry=0, copyDER=copyDER@entry=1)
#5  0x00007f4b0984a733 in CERT_DecodeCertFromPackage
    (certbuf=0x7f4ae6b3a400 "0\202\003\257\060\202\002\227\240\003\002\001\002\002\020\b;\340V\220BF\261\241uj\311Y\221\307J0\r\006\t*\206H\206\367\r\001\001\005\005", certlen=<optimized out>)
#6  0x00007f4b0476e7c3 in nsNSSCertificate::InitFromDER(char*, int)
    (this=this@entry=0x7f4ae6b23ba0, certDER=<optimized out>, derLen=<optimized out>)
#7  0x00007f4b0476e8fd in nsNSSCertificate::InitFromDER(char*, int)
    (derLen=<optimized out>, certDER=<optimized out>, this=0x7f4ae6b23ba0)
#8  nsNSSCertificate::Read(nsIObjectInputStream*)
    (this=0x7f4ae6b23ba0, aStream=0x7f4ae6b45aa0)
#9  0x00007f4b013d4e6b in nsBinaryInputStream::ReadObject(bool, nsISupports**)
    (this=this@entry=0x7f4ae6b45aa0, aIsStrongRef=aIsStrongRef@entry=true, aObject=0x7f4af0b7e418)
#10 0x00007f4b0475aaae in nsNSSCertList::Read(nsIObjectInputStream*)
    (this=0x7f4ae6b47640, aStream=0x7f4ae6b45aa0)
#11 0x00007f4b013d4e6b in nsBinaryInputStream::ReadObject(bool, nsISupports**)
    (this=0x7f4ae6b45aa0, aIsStrongRef=<optimized out>, aObject=0x7f4af0b7e538)
#12 0x00007f4b0476078d in NS_ReadOptionalObject(nsIObjectInputStream*, bool, nsISupports**) (aResult=0x7f4af0b7e538, aIsStrongRef=true, aStream=0x7f4ae6b45aa0)
#13 NS_ReadOptionalObject(nsIObjectInputStream*, bool, nsISupports**)
    (aResult=0x7f4af0b7e538, aIsStrongRef=true, aStream=0x7f4ae6b45aa0)
#14 mozilla::psm::TransportSecurityInfo::Read(nsIObjectInputStream*)
    (this=0x7f4ae1f36100, aStream=0x7f4ae6b45aa0)
#15 0x00007f4b013d4e6b in nsBinaryInputStream::ReadObject(bool, nsISupports**)
    (this=0x7f4ae6b45aa0, aIsStrongRef=<optimized out>, aObject=0x7f4af0b7e738)
#16 0x00007f4b014e2ea3 in NS_DeserializeObject(nsTSubstring<char> const&, nsISupports**) (str=..., obj=0x7f4af0b7e738)
#17 0x00007f4b016bb425 in mozilla::net::CacheEntry::GetSecurityInfo(nsISupports**) (this=0x7f4ae1f36600, aSecurityInfo=0x7f4ae6b466d8)
#18 0x00007f4b017a9f03 in mozilla::net::nsHttpChannel::OpenCacheInputStream(nsICacheEntry*, bool, bool)
    (this=0x7f4ae6b46000, cacheEntry=0x7f4ae6b458e0, startBuffering=<optimized out>, checkingAppCacheEntry=<optimized out>)
#19 0x00007f4b017c8d11 in mozilla::net::nsHttpChannel::OnCacheEntryCheck(nsICacheEntry*, nsIApplicationCache*, unsigned int*)
    (this=0x7f4ae6b46000, entry=0x7f4ae6b458e0, appCache=<optimized out>, aResult=<optimized out>)
```
(In reply to Daiki Ueno [:ueno] from comment #14)

> One thing I noticed is that, in the failed case, Firefox doesn't query CKA_MOZILLA_CA_POLICY. It seems that mozilla::psm::NSSCertDBTrustDomain::FindIssuer couldn't find the issuer of a certain certificate, but I'm not sure what is really happening there.

I dug it further with rr and found that the actual difference seems to be in this code path:
```
NSSCertDBTrustDomain::FindIssuer
  -> CheckCandidates
    -> ShouldSkipSelfSignedNonTrustAnchor
      -> NSSCertDBTrustDomain::GetCertTrust
        -> CERT_GetCertTrust
```
When it fails, `ShouldSkipSelfSignedNonTrustAnchor` reports `true` on the "DigiCert Global Root CA" cert, based on the check with `CERT_GetCertTrust` against a temp certificate created by `CERT_NewTempCertificate`. However, this function for some reason returns a cached certificate, which does not have CERTDB_TRUSTED_CA bit set.

The offending certificate comes from a different thread which reads the cache as below. Now the question is why this could happen (in particular, more frequently with p11-kit-trust.so). Any ideas?
```
#0  add_certificate_entry (store=0x7f4aeaa16870, cert=0x7f4ae6b56888)
#1  nssCertificateStore_AddLocked (cert=0x7f4ae6b56888, store=0x7f4aeaa16870)
#2  nssCertificateStore_FindOrAdd
#3  0x00007f4b098a018f in NSSCryptoContext_FindOrImportCertificate
    (cc=cc@entry=0x7f4aeaa16830, c=c@entry=0x7f4ae6b56888)
#4  0x00007f4b098859ce in CERT_NewTempCertificate
    (handle=<optimized out>, derCert=derCert@entry=0x7f4af0b7e298, nickname=nickname@entry=0x0, isperm=isperm@entry=0, copyDER=copyDER@entry=1)
#5  0x00007f4b0984a733 in CERT_DecodeCertFromPackage
    (certbuf=0x7f4ae6b3a400 "0\202\003\257\060\202\002\227\240\003\002\001\002\002\020\b;\340V\220BF\261\241uj\311Y\221\307J0\r\006\t*\206H\206\367\r\001\001\005\005", certlen=<optimized out>)
#6  0x00007f4b0476e7c3 in nsNSSCertificate::InitFromDER(char*, int)
    (this=this@entry=0x7f4ae6b23ba0, certDER=<optimized out>, derLen=<optimized out>)
#7  0x00007f4b0476e8fd in nsNSSCertificate::InitFromDER(char*, int)
    (derLen=<optimized out>, certDER=<optimized out>, this=0x7f4ae6b23ba0)
#8  nsNSSCertificate::Read(nsIObjectInputStream*)
    (this=0x7f4ae6b23ba0, aStream=0x7f4ae6b45aa0)
#9  0x00007f4b013d4e6b in nsBinaryInputStream::ReadObject(bool, nsISupports**)
    (this=this@entry=0x7f4ae6b45aa0, aIsStrongRef=aIsStrongRef@entry=true, aObject=0x7f4af0b7e418)
#10 0x00007f4b0475aaae in nsNSSCertList::Read(nsIObjectInputStream*)
    (this=0x7f4ae6b47640, aStream=0x7f4ae6b45aa0)
#11 0x00007f4b013d4e6b in nsBinaryInputStream::ReadObject(bool, nsISupports**)
    (this=0x7f4ae6b45aa0, aIsStrongRef=<optimized out>, aObject=0x7f4af0b7e538)
#12 0x00007f4b0476078d in NS_ReadOptionalObject(nsIObjectInputStream*, bool, nsISupports**) (aResult=0x7f4af0b7e538, aIsStrongRef=true, aStream=0x7f4ae6b45aa0)
#13 NS_ReadOptionalObject(nsIObjectInputStream*, bool, nsISupports**)
    (aResult=0x7f4af0b7e538, aIsStrongRef=true, aStream=0x7f4ae6b45aa0)
#14 mozilla::psm::TransportSecurityInfo::Read(nsIObjectInputStream*)
    (this=0x7f4ae1f36100, aStream=0x7f4ae6b45aa0)
#15 0x00007f4b013d4e6b in nsBinaryInputStream::ReadObject(bool, nsISupports**)
    (this=0x7f4ae6b45aa0, aIsStrongRef=<optimized out>, aObject=0x7f4af0b7e738)
#16 0x00007f4b014e2ea3 in NS_DeserializeObject(nsTSubstring<char> const&, nsISupports**) (str=..., obj=0x7f4af0b7e738)
#17 0x00007f4b016bb425 in mozilla::net::CacheEntry::GetSecurityInfo(nsISupports**) (this=0x7f4ae1f36600, aSecurityInfo=0x7f4ae6b466d8)
#18 0x00007f4b017a9f03 in mozilla::net::nsHttpChannel::OpenCacheInputStream(nsICacheEntry*, bool, bool)
    (this=0x7f4ae6b46000, cacheEntry=0x7f4ae6b458e0, startBuffering=<optimized out>, checkingAppCacheEntry=<optimized out>)
#19 0x00007f4b017c8d11 in mozilla::net::nsHttpChannel::OnCacheEntryCheck(nsICacheEntry*, nsIApplicationCache*, unsigned int*)
    (this=0x7f4ae6b46000, entry=0x7f4ae6b458e0, appCache=<optimized out>, aResult=<optimized out>)
```

Back to Bug 1593167 Comment 17