Page MenuHome GnuPG

"User ID" (Subject, subjectAltName) validity is inaccurate in gpgsm with sample certs.
Closed, ResolvedPublic

Description

Using LAMPS sample certs, gpgsm 2.2.19 doesn't appear to calculate the expected validity of the "user IDs" (in X.509, this appears to mean the Subject DN and the subjectAltName X.509v3 extension).

Here's me marking the sample CA as trusted, importing both certs, and inspecting the validity:

0 $ mkdir -m 0700 testdir
0 $ cafpr=4D:E0:FF:63:C0:E9:EC:01:29:11:C8:7A:EE:DA:3A:9A:7F:6E:C1:0D
0 $ echo "$cafpr" S relax > testdir/trustlist.txt
0 $ export GNUPGHOME=$(pwd)/testdir
0 $ cat ca.crt alice.pem | gpgsm --import
gpgsm: keybox '/home/dkg/testdir/pubring.kbx' created
gpgsm: total number processed: 2
gpgsm:               imported: 2
0 $ gpgsm --with-colons --list-keys
/home/dkg/testdir/pubring.kbx
------------------------------------------------------
crt:u:2048:1:EEDA3A9A7F6EC10D:20191120T065418:20520927T065418:2D770D5C62366D9A77F2C57B705E957107E7283C::CN=Sample LAMPS Certificate Authority::cC::::::23:
fpr:::::::::4DE0FF63C0E9EC012911C87AEEDA3A9A7F6EC10D:::4DE0FF63C0E9EC012911C87AEEDA3A9A7F6EC10D:
grp:::::::::7289595444406308E7C700F983039B4D38D4491A:
uid:u::::::::CN=Sample LAMPS Certificate Authority::
crt::2048:1:5FFC8A7DE2057DEB:20191120T065418:20520927T065418:6782B45973524BC1F47147196AF0FD118AAA4C0B::CN=Sample LAMPS Certificate Authority::esES::::::23:
fpr:::::::::702BA4B157F1E2B7D16B0C6A5FFC8A7DE2057DEB:::4DE0FF63C0E9EC012911C87AEEDA3A9A7F6EC10D:
grp:::::::::254CF0EDE5036291BB28C72AF096312BC45B120F:
uid:::::::::CN=Alice Lovelace::
uid:::::::::<alice@smime.example>::
0 $

DETAILS says of field 2:

For X.509 certificates a 'u' is used for a trusted root certificate (i.e. for the trust anchor) and an 'f' for all other valid certificates.

So i expect f in field 2 for the crt and uid lines in the second group of output lines, but instead i see the empty string.

To double-check, i confirmed that the certificate should be valid using other tools. Here is me demonstrating with GnuTLS's certtool that the cert in question correctly validates for the e-mail address alice@smime.example:

0 $ certtool --verify  --load-ca-certificate ca.crt --verify-email alice@smime.example --verify-profile ultra < alice.pem 
Loaded CAs (1 available)
	Subject: CN=Alice Lovelace
	Issuer: CN=Sample LAMPS Certificate Authority
	Checked against: CN=Sample LAMPS Certificate Authority
	Signature algorithm: RSA-SHA512
	Output: Verified. The certificate is trusted. 

Chain verification output: Verified. The certificate is trusted. 

0 $

here are the certs i'm using:

Details

Version
2.2.19

Event Timeline

Add --with-validation to check the validity of a certificate in a listing.

i didn't know that, thanks. i'm now seeing i (which i think means "invalid") in the same configuration:

0 $ gpgsm --with-validation --with-colons --list-keys
/home/dkg/testdir/pubring.kbx
------------------------------------------------------
crt:u:2048:1:EEDA3A9A7F6EC10D:20191120T065418:20520927T065418:2D770D5C62366D9A77F2C57B705E957107E7283C::CN=Sample LAMPS Certificate Authority::cC::::::23:
fpr:::::::::4DE0FF63C0E9EC012911C87AEEDA3A9A7F6EC10D:::4DE0FF63C0E9EC012911C87AEEDA3A9A7F6EC10D:
grp:::::::::7289595444406308E7C700F983039B4D38D4491A:
uid:u::::::::CN=Sample LAMPS Certificate Authority::
crt:i:2048:1:5FFC8A7DE2057DEB:20191120T065418:20520927T065418:6782B45973524BC1F47147196AF0FD118AAA4C0B::CN=Sample LAMPS Certificate Authority::esES::::::23:
fpr:::::::::702BA4B157F1E2B7D16B0C6A5FFC8A7DE2057DEB:::4DE0FF63C0E9EC012911C87AEEDA3A9A7F6EC10D:
grp:::::::::254CF0EDE5036291BB28C72AF096312BC45B120F:
uid:i::::::::CN=Alice Lovelace::
uid:i::::::::<alice@smime.example>::
0 $

Do you see something different?

Aha, i can get it to say f if i use --disable-crl-checks:

0 $ gpgsm --with-colons --disable-crl-checks --with-validation --list-keys
/home/dkg/src/gnupg/gpgsm-validity/testdir/pubring.kbx
------------------------------------------------------
crt:u:2048:1:EEDA3A9A7F6EC10D:20191120T065418:20520927T065418:2D770D5C62366D9A77F2C57B705E957107E7283C::CN=Sample LAMPS Certificate Authority::cC::::::23:
fpr:::::::::4DE0FF63C0E9EC012911C87AEEDA3A9A7F6EC10D:::4DE0FF63C0E9EC012911C87AEEDA3A9A7F6EC10D:
grp:::::::::7289595444406308E7C700F983039B4D38D4491A:
uid:u::::::::CN=Sample LAMPS Certificate Authority::
crt:f:2048:1:5FFC8A7DE2057DEB:20191120T065418:20520927T065418:6782B45973524BC1F47147196AF0FD118AAA4C0B::CN=Sample LAMPS Certificate Authority::esES::::::23:
fpr:::::::::702BA4B157F1E2B7D16B0C6A5FFC8A7DE2057DEB:::4DE0FF63C0E9EC012911C87AEEDA3A9A7F6EC10D:
grp:::::::::254CF0EDE5036291BB28C72AF096312BC45B120F:
uid:f::::::::CN=Alice Lovelace::
uid:f::::::::<alice@smime.example>::
0 $

without --with-colons --disable-crl-checks i get this:

[checking the CRL failed: Not supported]
[certificate is bad: Not supported]

Note that neither certificate has a CRL.

I thought i'd try with other certificates. I started with the one from this website. It also fails to validate unless i supply --disable-crl-checks, apparently because the immediate issuer (the Let's Encrypt CA) doesn't offer CRLs, only OCSP responders. Perhaps --disable-crl-checks should be the default, or at least if there is no CRL available there shouldn't be a failure by default:

0 dkg@alice:/tmp/cdtemp.XnyqF4$ rm -rf testdir
0 dkg@alice:/tmp/cdtemp.XnyqF4$ mkdir -m 0700 testdir
0 dkg@alice:/tmp/cdtemp.XnyqF4$ cafpr=DA:C9:02:4F:54:D8:F6:DF:94:93:5F:B1:73:26:38:CA:6A:D7:7C:13
0 dkg@alice:/tmp/cdtemp.XnyqF4$ echo "$cafpr S relax" > testdir/trustlist.txt
0 dkg@alice:/tmp/cdtemp.XnyqF4$ export GNUPGHOME=$(pwd)/testdir
0 dkg@alice:/tmp/cdtemp.XnyqF4$ gpgsm --import < ~/Downloads/dev-gnupg-org-chain.pem 
gpgsm: keybox '/tmp/cdtemp.XnyqF4/testdir/pubring.kbx' created
gpgsm: dirmngr cache-only key lookup failed: Not found
gpgsm: issuer certificate {A84A6A63047DDDBAE6D139B7A64565EFF3A8ECA1} not found using authorityKeyIdentifier
gpgsm: dirmngr cache-only key lookup failed: Not found
gpgsm: issuer certificate (#/CN=Let's Encrypt Authority X3,O=Let's Encrypt,C=US) not found
gpgsm: dirmngr cache-only key lookup failed: Not found
gpgsm: issuer certificate {A84A6A63047DDDBAE6D139B7A64565EFF3A8ECA1} not found using authorityKeyIdentifier
gpgsm: dirmngr cache-only key lookup failed: Not found
gpgsm: total number processed: 3
gpgsm:               imported: 2
gpgsm:              unchanged: 1
0 dkg@alice:/tmp/cdtemp.XnyqF4$ gpgsm --with-validation --list-keys
/tmp/cdtemp.XnyqF4/testdir/pubring.kbx
--------------------------------------
           ID: 0x5D4A4479
          S/N: 030D826A028329A1610C4743C34C6986C650
       Issuer: /CN=Let's Encrypt Authority X3/O=Let's Encrypt/C=US
      Subject: /CN=dev.gnupg.org
          aka: (dns-name bugs.gnupg.org)
          aka: (dns-name dev.gnupg.org)
          aka: (dns-name files.gnupg.net)
     validity: 2020-02-27 10:09:41 through 2020-05-27 10:09:41
     key type: 2048 bit RSA
    key usage: digitalSignature keyEncipherment
ext key usage: serverAuth (suggested), clientAuth (suggested)
     policies: 2.23.140.1.2.1:N:,1.3.6.1.4.1.44947.1.1.1:N:
  fingerprint: 23:1D:E2:B7:75:8C:80:95:87:C0:17:A6:B1:CD:3D:51:5D:4A:44:79
  [Note: non-critical certificate policy not allowed]
  [checking the CRL failed: Not supported]
  [certificate is bad: Not supported]

           ID: 0x6AD77C13
          S/N: 44AFB080D6A327BA893039862EF8406B
       Issuer: /CN=DST Root CA X3/O=Digital Signature Trust Co.
      Subject: /CN=DST Root CA X3/O=Digital Signature Trust Co.
     validity: 2000-09-30 21:12:19 through 2021-09-30 14:01:15
     key type: 2048 bit RSA
    key usage: certSign crlSign
 chain length: unlimited
  fingerprint: DA:C9:02:4F:54:D8:F6:DF:94:93:5F:B1:73:26:38:CA:6A:D7:7C:13
  [certificate is good]

           ID: 0xD5956CCB
          S/N: 0A0141420000015385736A0B85ECA708
       Issuer: /CN=DST Root CA X3/O=Digital Signature Trust Co.
      Subject: /CN=Let's Encrypt Authority X3/O=Let's Encrypt/C=US
     validity: 2016-03-17 16:40:46 through 2021-03-17 16:40:46
     key type: 2048 bit RSA
    key usage: digitalSignature certSign crlSign
     policies: 2.23.140.1.2.1:N:,1.3.6.1.4.1.44947.1.1.1:N:
 chain length: 0
  fingerprint: E6:A3:B4:5B:06:2D:50:9B:33:82:28:2D:19:6E:FE:97:D5:95:6C:CB
  [Note: non-critical certificate policy not allowed]
  [certificate is good]

0 dkg@alice:/tmp/cdtemp.XnyqF4$ gpgsm --disable-crl-checks --with-validation --list-keys
/tmp/cdtemp.XnyqF4/testdir/pubring.kbx
--------------------------------------
           ID: 0x5D4A4479
          S/N: 030D826A028329A1610C4743C34C6986C650
       Issuer: /CN=Let's Encrypt Authority X3/O=Let's Encrypt/C=US
      Subject: /CN=dev.gnupg.org
          aka: (dns-name bugs.gnupg.org)
          aka: (dns-name dev.gnupg.org)
          aka: (dns-name files.gnupg.net)
     validity: 2020-02-27 10:09:41 through 2020-05-27 10:09:41
     key type: 2048 bit RSA
    key usage: digitalSignature keyEncipherment
ext key usage: serverAuth (suggested), clientAuth (suggested)
     policies: 2.23.140.1.2.1:N:,1.3.6.1.4.1.44947.1.1.1:N:
  fingerprint: 23:1D:E2:B7:75:8C:80:95:87:C0:17:A6:B1:CD:3D:51:5D:4A:44:79
  [Note: non-critical certificate policy not allowed]
  [Note: non-critical certificate policy not allowed]
  [certificate is good]

           ID: 0x6AD77C13
          S/N: 44AFB080D6A327BA893039862EF8406B
       Issuer: /CN=DST Root CA X3/O=Digital Signature Trust Co.
      Subject: /CN=DST Root CA X3/O=Digital Signature Trust Co.
     validity: 2000-09-30 21:12:19 through 2021-09-30 14:01:15
     key type: 2048 bit RSA
    key usage: certSign crlSign
 chain length: unlimited
  fingerprint: DA:C9:02:4F:54:D8:F6:DF:94:93:5F:B1:73:26:38:CA:6A:D7:7C:13
  [certificate is good]

           ID: 0xD5956CCB
          S/N: 0A0141420000015385736A0B85ECA708
       Issuer: /CN=DST Root CA X3/O=Digital Signature Trust Co.
      Subject: /CN=Let's Encrypt Authority X3/O=Let's Encrypt/C=US
     validity: 2016-03-17 16:40:46 through 2021-03-17 16:40:46
     key type: 2048 bit RSA
    key usage: digitalSignature certSign crlSign
     policies: 2.23.140.1.2.1:N:,1.3.6.1.4.1.44947.1.1.1:N:
 chain length: 0
  fingerprint: E6:A3:B4:5B:06:2D:50:9B:33:82:28:2D:19:6E:FE:97:D5:95:6C:CB
  [Note: non-critical certificate policy not allowed]
  [certificate is good]

0 dkg@alice:/tmp/cdtemp.XnyqF4$

If you want OCSP you need to enable it. CRLs or OCSP are a MUST under the profile we developed gpgsm. This is why --disable-crl-checks by default is not possible. There are lot of interesting things you will come across if you start to use S/MIME. For example you also need to care about the algorithms used for intermediate certificates used to sign CRLs - they need to comply to the policy as well. Or the rarely used PSS padding we encounter sometimes and which is not supported and will probably not be supported

If CRLs or OCSP are a MUST in a given profile, and the cert chain has OCSP but no CRL, it seems like that profile should then try OCSP, rather than failing.

Instead, the default profile for gpgsm appears to be "MUST CRL".

Trying to think about this more broadly, i think the main questions for a profile about revocation-checking (or "freshness") are:

  • which certificates do we care about doing freshness checks on? (end entities, intermediates, root certs? should we consider a certificate with a validity window of 5 days differently than a cert with a 5 year validity window?)
  • what kinds of freshness checks are acceptable? (CRL and OCSP are the only two options i'm aware of)
  • how long should any freshness check be considered valid for (cached for)?
  • if multiple kinds of freshness checks are available for a given cert, how should we prioritize among them?
  • if a cert has no acceptable freshness checks listed (that is, none listed in the cert itself), should it count as "not fresh" (and therefore invalid)?
  • if a cert has acceptable freshness checks listed, but none are reachable over the network, should it count as "not fresh"? (and how long should the timeout be?)
  • if a cert has acceptable freshness checks listed, but the app has *no network access available* (e.g. the device is offline, the app is in "offline mode", or the system's own network connection is clearly down), should it count as "not fresh"?

It sounds to me like the GnuPG default freshness policy is:

  • check freshness on all certs, and do not treat short-lived certs differently than long-lived certs
  • CRL checks are acceptable, OCSP are not by default
  • no need to prioritize between CRL and OCSP since OCSP is disabled; but if the user enables both, OCSP will take priority
  • (i don't know whether there is a limit on how long CRLs or OCSP responses can be cached for)
  • if a cert has no acceptable freshness checks listed, the cert is invalid
  • if a cert has only unreachable freshness checks, the cert is invalid
  • if a cert has listed freshness checks, but we are offline, the cert is invalid

is that right?

OCSP can't be the default because it enables a web bug. The responder immediately sees when a signature is verified or a data is encrypted to a certificate.

I'm aware of the metadata leakage risks of OCSP, and i share your concerns about them.

fwiw, if i'm a CA and i want to implement a web bug via CRLs, i can mint a different CRL Distribution point for each cert i issue, right?

Is my description above about GnuPG's intended default freshness policy accurate?

werner claimed this task.

The CRL states how long it is valid and we cache it for about that time.
OCSP responses are by definition not cachable but we allow for a clock skew of 10 minutes.

Since 2.2.21 cert which specify no CRL DP or OCSP are considered valid. It is matter of the root CA to issue correct certificates and whether you trust that root CA to issue suitablle certs.

For the chain validation model (i.e. qualified digital signatures) OCSP checks are mandatory and thus verification of such signatures require that tan OCSP responder has been specified.

Your other points are correct.