Browse Source

cert patches

Frank-Rainer Grahl 2 years ago
parent
commit
70d44b7a6a
2 changed files with 378 additions and 0 deletions
  1. 347 0
      frg/cert-patches/1738501-1-cc-913.patch
  2. 31 0
      frg/cert-patches/1738501-2-cc-913.patch

+ 347 - 0
frg/cert-patches/1738501-1-cc-913.patch

@@ -0,0 +1,347 @@
+# HG changeset patch
+# User Kai Engert <kaie@kuix.de>
+# Date 1635510554 0
+# Node ID 54507526da8284d344d215b0beef02d1dea6c53c
+# Parent  94f885688ff1e57b8a87b156221d42771f0819eb
+Bug 1738501 - Add check using mozilla::pkix to some more scenarios. r=mkmelin a=wsmwk
+
+Differential Revision: https://phabricator.services.mozilla.com/D129953
+
+diff --git a/mailnews/mime/src/nsCMS.cpp b/mailnews/mime/src/nsCMS.cpp
+--- a/mailnews/mime/src/nsCMS.cpp
++++ b/mailnews/mime/src/nsCMS.cpp
+@@ -19,16 +19,17 @@
+ #include "nsISupports.h"
+ #include "nsIX509CertDB.h"
+ #include "nsNSSCertificate.h"
+ #include "nsNSSComponent.h"
+ #include "nsNSSHelper.h"
+ #include "nsServiceManagerUtils.h"
+ #include "mozpkix/Result.h"
+ #include "mozpkix/pkixtypes.h"
++#include "secerr.h"
+ #include "smime.h"
+ #include "mozilla/StaticMutex.h"
+ 
+ using namespace mozilla;
+ using namespace mozilla::psm;
+ using namespace mozilla::pkix;
+ 
+ extern mozilla::LazyLogModule gPIPNSSLog;
+@@ -172,24 +173,256 @@ NS_IMETHODIMP nsCMSMessage::GetEncryptio
+ NS_IMETHODIMP nsCMSMessage::VerifyDetachedSignature(unsigned char* aDigestData, uint32_t aDigestDataLen)
+ {
+   if (!aDigestData || !aDigestDataLen)
+     return NS_ERROR_FAILURE;
+ 
+   return CommonVerifySignature(aDigestData, aDigestDataLen);
+ }
+ 
++// This is an exact copy of NSS_CMSArray_Count from NSS' cmsarray.c,
++// temporarily necessary, see below for for justification.
++static int myNSS_CMSArray_Count(void** array) {
++  int n = 0;
++
++  if (array == NULL) return 0;
++
++  while (*array++ != NULL) n++;
++
++  return n;
++}
++
++// This is an exact copy of NSS_CMSArray_Add from NSS' cmsarray.c,
++// temporarily necessary, see below for for justification.
++static SECStatus myNSS_CMSArray_Add(PLArenaPool* poolp, void*** array,
++                                    void* obj) {
++  void** p;
++  int n;
++  void** dest;
++
++  PORT_Assert(array != NULL);
++  if (array == NULL) return SECFailure;
++
++  if (*array == NULL) {
++    dest = (void**)PORT_ArenaAlloc(poolp, 2 * sizeof(void*));
++    n = 0;
++  } else {
++    n = 0;
++    p = *array;
++    while (*p++) n++;
++    dest = (void**)PORT_ArenaGrow(poolp, *array, (n + 1) * sizeof(void*),
++                                  (n + 2) * sizeof(void*));
++  }
++
++  if (dest == NULL) return SECFailure;
++
++  dest[n] = obj;
++  dest[n + 1] = NULL;
++  *array = dest;
++  return SECSuccess;
++}
++
++// This is an exact copy of NSS_CMSArray_Add from NSS' cmsarray.c,
++// temporarily necessary, see below for for justification.
++static SECStatus myNSS_CMSSignedData_AddTempCertificate(NSSCMSSignedData* sigd,
++                                                        CERTCertificate* cert) {
++  CERTCertificate* c;
++  SECStatus rv;
++
++  if (!sigd || !cert) {
++    PORT_SetError(SEC_ERROR_INVALID_ARGS);
++    return SECFailure;
++  }
++
++  c = CERT_DupCertificate(cert);
++  rv = myNSS_CMSArray_Add(sigd->cmsg->poolp, (void***)&(sigd->tempCerts),
++                          (void*)c);
++  return rv;
++}
++
++typedef SECStatus (*extraVerificationOnCertFn)(CERTCertificate* cert,
++                                               SECCertUsage certusage);
++
++static SECStatus myExtraVerificationOnCert(CERTCertificate* cert,
++                                           SECCertUsage certusage) {
++  RefPtr<SharedCertVerifier> certVerifier;
++  certVerifier = GetDefaultCertVerifier();
++  if (!certVerifier) {
++    return SECFailure;
++  }
++
++  SECCertificateUsage usageForPkix;
++
++  switch (certusage) {
++    case certUsageEmailSigner:
++      usageForPkix = certificateUsageEmailSigner;
++      break;
++    case certUsageEmailRecipient:
++      usageForPkix = certificateUsageEmailRecipient;
++      break;
++    default:
++      return SECFailure;
++  }
++
++  UniqueCERTCertList builtChain;
++  mozilla::pkix::Result result = certVerifier->VerifyCert(
++      cert, usageForPkix, Now(), nullptr /*XXX pinarg*/, nullptr /*hostname*/,
++      builtChain);
++      // Needed for Bug 1500003 but not for our level right now.
++      // Only local checks can run on the main thread.
++      // CertVerifier::FLAG_LOCAL_ONLY);
++  if (result != mozilla::pkix::Success) {
++    return SECFailure;
++  }
++
++  return SECSuccess;
++}
++
++// This is a temporary copy of NSS_CMSSignedData_ImportCerts, which
++// performs additional verifications prior to import.
++// The copy is almost identical to the original.
++//
++// The ONLY DIFFERENCE is the addition of parameter extraVerifyFn,
++// and the call to it - plus a non-null check.
++//
++// NSS should add this or a similar API in the future,
++// and then these temporary functions should be removed, including
++// the ones above. Request is tracked in bugzilla 1738592.
++static SECStatus myNSS_CMSSignedData_ImportCerts(
++    NSSCMSSignedData* sigd, CERTCertDBHandle* certdb, SECCertUsage certusage,
++    PRBool keepcerts, extraVerificationOnCertFn extraVerifyFn) {
++  int certcount;
++  CERTCertificate** certArray = NULL;
++  CERTCertList* certList = NULL;
++  CERTCertListNode* node;
++  SECStatus rv;
++  SECItem** rawArray;
++  int i;
++  PRTime now;
++
++  if (!sigd) {
++    PORT_SetError(SEC_ERROR_INVALID_ARGS);
++    return SECFailure;
++  }
++
++  certcount = myNSS_CMSArray_Count((void**)sigd->rawCerts);
++
++  /* get the certs in the temp DB */
++  rv = CERT_ImportCerts(certdb, certusage, certcount, sigd->rawCerts,
++                        &certArray, PR_FALSE, PR_FALSE, NULL);
++  if (rv != SECSuccess) {
++    goto loser;
++  }
++
++  /* save the certs so they don't get destroyed */
++  for (i = 0; i < certcount; i++) {
++    CERTCertificate* cert = certArray[i];
++    if (cert) myNSS_CMSSignedData_AddTempCertificate(sigd, cert);
++  }
++
++  if (!keepcerts) {
++    goto done;
++  }
++
++  /* build a CertList for filtering */
++  certList = CERT_NewCertList();
++  if (certList == NULL) {
++    rv = SECFailure;
++    goto loser;
++  }
++  for (i = 0; i < certcount; i++) {
++    CERTCertificate* cert = certArray[i];
++    if (cert) cert = CERT_DupCertificate(cert);
++    if (cert) CERT_AddCertToListTail(certList, cert);
++  }
++
++  /* filter out the certs we don't want */
++  rv = CERT_FilterCertListByUsage(certList, certusage, PR_FALSE);
++  if (rv != SECSuccess) {
++    goto loser;
++  }
++
++  /* go down the remaining list of certs and verify that they have
++   * valid chains, then import them.
++   */
++  now = PR_Now();
++  for (node = CERT_LIST_HEAD(certList); !CERT_LIST_END(node, certList);
++       node = CERT_LIST_NEXT(node)) {
++    CERTCertificateList* certChain;
++
++    if (!node->cert) {
++      continue;
++    }
++
++    if (extraVerifyFn) {
++      if ((*extraVerifyFn)(node->cert, certusage) != SECSuccess) {
++        continue;
++      }
++    }
++
++    if (CERT_VerifyCert(certdb, node->cert, PR_TRUE, certusage, now, NULL,
++                        NULL) != SECSuccess) {
++      continue;
++    }
++
++    certChain = CERT_CertChainFromCert(node->cert, certusage, PR_FALSE);
++    if (!certChain) {
++      continue;
++    }
++
++    /*
++     * CertChain returns an array of SECItems, import expects an array of
++     * SECItem pointers. Create the SECItem Pointers from the array of
++     * SECItems.
++     */
++    rawArray = (SECItem**)PORT_Alloc(certChain->len * sizeof(SECItem*));
++    if (!rawArray) {
++      CERT_DestroyCertificateList(certChain);
++      continue;
++    }
++    for (i = 0; i < certChain->len; i++) {
++      rawArray[i] = &certChain->certs[i];
++    }
++    (void)CERT_ImportCerts(certdb, certusage, certChain->len, rawArray, NULL,
++                           keepcerts, PR_FALSE, NULL);
++    PORT_Free(rawArray);
++    CERT_DestroyCertificateList(certChain);
++  }
++
++  rv = SECSuccess;
++
++  /* XXX CRL handling */
++
++done:
++  if (sigd->signerInfos != NULL) {
++    /* fill in all signerinfo's certs */
++    for (i = 0; sigd->signerInfos[i] != NULL; i++)
++      (void)NSS_CMSSignerInfo_GetSigningCertificate(sigd->signerInfos[i],
++                                                    certdb);
++  }
++
++loser:
++  /* now free everything */
++  if (certArray) {
++    CERT_DestroyCertArray(certArray, certcount);
++  }
++  if (certList) {
++    CERT_DestroyCertList(certList);
++  }
++
++  return rv;
++}
++
+ nsresult nsCMSMessage::CommonVerifySignature(unsigned char* aDigestData, uint32_t aDigestDataLen)
+ {
+   MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("nsCMSMessage::CommonVerifySignature, content level count %d\n", NSS_CMSMessage_ContentLevelCount(m_cmsMsg)));
+   NSSCMSContentInfo *cinfo = nullptr;
+   NSSCMSSignedData *sigd = nullptr;
+   NSSCMSSignerInfo *si;
+   int32_t nsigners;
+-  RefPtr<SharedCertVerifier> certVerifier;
+   nsresult rv = NS_ERROR_FAILURE;
+ 
+   if (!NSS_CMSMessage_IsSigned(m_cmsMsg)) {
+     MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("nsCMSMessage::CommonVerifySignature - not signed\n"));
+     return NS_ERROR_CMS_VERIFY_NOT_SIGNED;
+   }
+ 
+   cinfo = NSS_CMSMessage_ContentLevel(m_cmsMsg, 0);
+@@ -213,46 +446,38 @@ nsresult nsCMSMessage::CommonVerifySigna
+     if (NSS_CMSSignedData_SetDigestValue(sigd, SEC_OID_SHA1, &digest)) {
+       MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("nsCMSMessage::CommonVerifySignature - bad digest\n"));
+       rv = NS_ERROR_CMS_VERIFY_BAD_DIGEST;
+       goto loser;
+     }
+   }
+ 
+   // Import certs. Note that import failure is not a signature verification failure. //
+-  if (NSS_CMSSignedData_ImportCerts(sigd, CERT_GetDefaultCertDB(), certUsageEmailRecipient, true) != SECSuccess) {
++  if (myNSS_CMSSignedData_ImportCerts(
++          sigd, CERT_GetDefaultCertDB(), certUsageEmailRecipient, true,
++          myExtraVerificationOnCert) != SECSuccess) {
+     MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("nsCMSMessage::CommonVerifySignature - can not import certs\n"));
+   }
+ 
+   nsigners = NSS_CMSSignedData_SignerInfoCount(sigd);
+   PR_ASSERT(nsigners > 0);
+   NS_ENSURE_TRUE(nsigners > 0, NS_ERROR_UNEXPECTED);
+   si = NSS_CMSSignedData_GetSignerInfo(sigd, 0);
+ 
++  NS_ENSURE_TRUE(si, NS_ERROR_UNEXPECTED);
++  NS_ENSURE_TRUE(si->cert, NS_ERROR_UNEXPECTED);
++
+   // See bug 324474. We want to make sure the signing cert is
+   // still valid at the current time.
+-
+-  certVerifier = GetDefaultCertVerifier();
+-  NS_ENSURE_TRUE(certVerifier, NS_ERROR_UNEXPECTED);
+-
+-  {
+-    UniqueCERTCertList builtChain;
+-    mozilla::pkix::Result result =
+-      certVerifier->VerifyCert(si->cert,
+-                               certificateUsageEmailSigner,
+-                               Now(),
+-                               nullptr /*XXX pinarg*/,
+-                               nullptr /*hostname*/,
+-                               builtChain);
+-    if (result != mozilla::pkix::Success) {
+-      MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
+-             ("nsCMSMessage::CommonVerifySignature - signing cert not trusted now\n"));
+-      rv = NS_ERROR_CMS_VERIFY_UNTRUSTED;
+-      goto loser;
+-    }
++  if (myExtraVerificationOnCert(si->cert, certUsageEmailSigner) != SECSuccess) {
++    MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
++            ("nsCMSMessage::CommonVerifySignature - signing cert not trusted "
++             "now"));
++    rv = NS_ERROR_CMS_VERIFY_UNTRUSTED;
++    goto loser;
+   }
+ 
+   // We verify the first signer info,  only //
+   // XXX: NSS_CMSSignedData_VerifySignerInfo calls CERT_VerifyCert, which
+   // requires NSS's certificate verification configuration to be done in
+   // order to work well (e.g. honoring OCSP preferences and proxy settings
+   // for OCSP requests), but Gecko stopped doing that configuration. Something
+   // similar to what was done for Gecko bug 1028643 needs to be done here too.

+ 31 - 0
frg/cert-patches/1738501-2-cc-913.patch

@@ -0,0 +1,31 @@
+# HG changeset patch
+# User Kai Engert <kaie@kuix.de>
+# Date 1635800263 14400
+# Node ID bea1eb4e98a3aa0624fcf83d4ddb32855e9563f8
+# Parent  ac45effefbdeaac9d1794818f139c341e64329c9
+Bug 1738501 - Follow-up: Fix unresolved NSS symbols on macOS/Windows. r+a=rjl
+
+diff --git a/mailnews/nss-extra.symbols b/mailnews/nss-extra.symbols
+--- a/mailnews/nss-extra.symbols
++++ b/mailnews/nss-extra.symbols
+@@ -1,9 +1,10 @@
+ CERT_GetCertNicknames
++CERT_VerifyCert
+ NSSBase64Decoder_Create_Util
+ NSSBase64Decoder_Destroy_Util
+ NSSBase64Decoder_Update_Util
+ NSSBase64Encoder_Create_Util
+ NSSBase64Encoder_Destroy_Util
+ NSSBase64Encoder_Update_Util
+ NSS_CMSContentInfo_GetBulkKey
+ NSS_CMSContentInfo_GetBulkKeySize
+@@ -46,8 +47,9 @@ NSS_CMSSignerInfo_AddSigningTime
+ NSS_CMSSignerInfo_AddSMIMECaps
+ NSS_CMSSignerInfo_AddSMIMEEncKeyPrefs
+ NSS_CMSSignerInfo_Create
+ NSS_CMSSignerInfo_GetSignerCommonName
+ NSS_CMSSignerInfo_GetSignerEmailAddress
+ NSS_CMSSignerInfo_GetVerificationStatus
+ NSS_CMSSignerInfo_IncludeCerts
+ NSS_CMSUtil_VerificationStatusToString
++PORT_ArenaGrow