Package: ca-certificates
Version: 20260601~24.04.1
Severity: important
Tags: upstream
X-Debbugs-CC: [email protected]

Summary
=======

mozilla/certdata2pem.py inspects only CKA_TRUST_SERVER_AUTH when deciding
whether to emit a root as a .crt file.  Any root Mozilla marks as
CKT_NSS_MUST_VERIFY_TRUST for TLS is silently dropped from the
ca-certificates output, even if Mozilla still marks it as
CKT_NSS_TRUSTED_DELEGATOR for CKA_TRUST_EMAIL_PROTECTION or
CKA_TRUST_CODE_SIGNING.

Mozilla now uses this asymmetric trust state as its standard mechanism
for the *gradual retirement* of legacy roots (TLS distrusted first,
S/MIME and code-signing retained for a further period).  Debian's
converter collapses that graceful retirement into a total removal,
silently breaking S/MIME verification for cert chains that Mozilla
explicitly still trusts.

Reproducer
==========

Trust state Mozilla actually shipped for "DigiCert Assured ID Root CA"
in the NSS bundle imported by 20260601 (from the source tarball,
mozilla/certdata.txt):

  # Trust for "DigiCert Assured ID Root CA"
  CKA_TRUST_SERVER_AUTH      CK_TRUST CKT_NSS_MUST_VERIFY_TRUST   <-- TLS 
distrusted
  CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_TRUSTED_DELEGATOR   <-- S/MIME 
still trusted
  CKA_TRUST_CODE_SIGNING     CK_TRUST CKT_NSS_MUST_VERIFY_TRUST

Post-build state on the installed system:

  $ ls /usr/share/ca-certificates/mozilla/ | grep DigiCert_Assured_ID
  DigiCert_Assured_ID_Root_G2.crt
  DigiCert_Assured_ID_Root_G3.crt          # G1 file removed entirely

  $ grep Assured_ID_Root_CA /etc/ca-certificates.conf
  !mozilla/DigiCert_Assured_ID_Root_CA.crt  # explicitly disabled

  $ grep -c "CN = DigiCert Assured ID Root CA$" 
/etc/ssl/certs/ca-certificates.crt
  0                                          # absent from system trust bundle

Root cause is in mozilla/certdata2pem.py, lines 108-118 of
20260601~24.04.1:

  elif obj['CKA_TRUST_SERVER_AUTH'] == 'CKT_NSS_TRUSTED_DELEGATOR':
      trust[obj['CKA_LABEL']] = True                       # emit
  elif obj['CKA_TRUST_SERVER_AUTH'] == 'CKT_NSS_NOT_TRUSTED':
      print("UNTRUSTED BUT NOT BLACKLISTED CERTIFICATE FOUND: %s" % ...)
  else:
      print("Ignoring certificate %s.  SAUTH=%s, EPROT=%s" % \
            (obj['CKA_LABEL'], obj['CKA_TRUST_SERVER_AUTH'],
             obj['CKA_TRUST_EMAIL_PROTECTION']))            # silently dropped

The else branch even echoes EPROT to stderr, showing awareness of the
email trust value -- but never acts on it.  Any root Mozilla marks
CKT_NSS_MUST_VERIFY_TRUST for TLS is discarded regardless of its email
or code-signing trust state.

End-user impact reproduced:

  $ openssl verify -purpose smimesign -CApath /etc/ssl/certs \
      -untrusted verokey_intermediate.pem verokey_leaf.pem
  C = AU, O = Verokey, CN = Verokey Secure Email G2
  error 20 at 1 depth lookup: unable to get local issuer certificate
  error verokey_leaf.pem: verification failed

  $ openssl verify -purpose smimesign \
      -CAfile digicert_assured_id_root_ca.pem \
      -untrusted verokey_intermediate.pem verokey_leaf.pem
  verokey_leaf.pem: OK

Impact
======

In the 20260601 upload alone, this affects at least the three DigiCert
G1 roots that the debian/changelog claims were "removed":

  - DigiCert Assured ID Root CA
  - DigiCert Global Root CA
  - DigiCert High Assurance EV Root CA

Per DigiCert's public advisory
<https://knowledge.digicert.com/general-information/digicert-root-and-intermediate-ca-certificate-updates-2023>
these roots were distrusted by Mozilla and Google Chrome for TLS on
15 April 2026, but Mozilla is not scheduled to distrust them for S/MIME
until 15 April 2029.  The changelog wording ("removed") is misleading:
Mozilla did not remove them; it downgraded TLS trust while retaining
S/MIME trust.  Debian silently converts that to a full removal.

This will keep recurring.  Every future graceful CA retirement by
Mozilla (which is now the standard pattern under the CA/Browser Forum
S/MIME Baseline Requirements) will hit the same converter defect.

Downstream Ubuntu is affected identically; the same 20260601~24.04.1
upload has landed as a noble-security update and the extracted trust
bundle is byte-for-byte the result of running this script.
LP: #2156786 references this batch on the Ubuntu side.

The user-visible effects on a Debian/Ubuntu system:

  - openssl / gnutls / anything reading /etc/ssl/certs/ca-certificates.crt:
    cannot validate S/MIME signatures issued under these roots.
  - p11-kit-trust (fed by /usr/share/ca-certificates/trust-source/):
    same -- the root is gone from its input.
  - Applications that use the libnssckbi.so shipped by libnss3 directly
    (Thunderbird embeds its own copy; some Evolution / camel-smime
    configurations): behaviour depends on the libnss3 build path and
    whether the application resolves the "Mozilla Root Certs" module to
    the real Mozilla builtins or to p11-kit-trust.

Suggested fixes
===============

Not the simplest change:

1. Preserve trust distinctions in the output.  p11-kit-trust's native
   trust-source/ format can encode per-purpose trust flags in .p11-kit
   anchor files.  Emit these instead of / in addition to the flat .crt
   extract when a root has asymmetric trust (see p11-kit's
   pem-directory-hash extractor and trust extract --purpose= selectors).
   This is the "correct" fix and matches what Fedora / RHEL do.

2. At minimum, emit the .crt file into /usr/share/ca-certificates/mozilla/
   unconditionally, but keep it commented out in
   /etc/ca-certificates.conf unless *any* trust purpose is
   TRUSTED_DELEGATOR.  That preserves the raw material for downstream
   consumers (Thunderbird, NSS-based apps) without adding it to the flat
   TLS bundle.  The current behaviour deletes the source .crt file too,
   leaving nowhere to recover from.

3. Emit a separate email trust bundle -- e.g.
   /etc/ssl/certs/email-trust.crt -- for consumers that want S/MIME-only
   anchors distinct from TLS.

Attachment: smime.p7s
Description: S/MIME cryptographic signature

Reply via email to