Do not expect KeyIDs to be unique
Closed, ResolvedPublic

Description

The DFN-PKI has re-issued its own certificate and all the hundreds of
certificates of its sub-CAs, switching from SHA-1 hashes to SHA-2 hashes due to
a requirement by Microsoft, see https://www.pki.dfn.de/faqpki/faqpki-sha2/ (in
German). Because only hash method and validity have been changed, the gpgsm "key
grip" did not change.

This breaks gpgsm if both old and new certificate of any of these CAs are in the
key ring. When e.g. signing an e-mail, dirmngr is called to check CRLs. dirmng
sends an SENDCERT inquiry back to gpgsm to get the certificate of the CA.

dirmngr[12092.0]: no CRL available for issuer id
A52EFAEFBC86EF98C5E9AA92B3ECEC4101080F0A
gpgsm: certificate not found: Ambiguous name
dirmngr[12092.0]: assuan_inquire(SENDCERT) failed: IPC call has been cancelled
dirmngr[12092.0]: error fetching certificate by subject: No data
dirmngr[12092.0]: crl_parse_insert failed: Missing certificate dirmngr[12092.0]:
crl_cache_insert via DP failed: Missing certificate
dirmngr[12092.0]: command ISVALID failed: Missing certificate
gpgsm: certificate
#1700BFBB98F74B/1.2.840.113549.1.9.1=#636140756E692D6D75656E737465722E6465,CN=Zertifizierungsstelle
Universitaet Muenster - G02,O=Universitaet Muenster,C=DE
gpgsm: checking the CRL failed: Not found
gpgsm: can't sign using `&7CF2C58D823C0ED461ED6B1FD13F9E96B6F7C436': Not found

The error "Ambiguous name" is set in gnupg-2.0.22/sm/certlist.c line 543. The
comment at line 518 says:
/* [...] Note, that it is somehwat reasonable to assume that a specification of
a KEYID won't lead to ambiguous names. */
That is now proven to be false by real life.

In the current situation with the DFN-PKI re-issued certificates, it does not
matter whether the old certificate or the new one is returned to dirmngr on this
inquire, but one of them must be returned. I see two possible ways:

1st way: make dirmngr to use the fingerprint instead of the keygrip or any other
string in the SENDCERT inquire.

2nd way: make gpgsm to send the first certificate found on the inquire. (This
would be not so good because there is a chance that the wrong one is returned.)

Because the user has no way at all to avoid that both old and new certificate
get into the keyring, gpgsm/dirmngr must handle this situation gracefully.

I set the priority to critical because this breaks the central webmailers of one
of the biggest universities in Germany.

Issue 1633 might be a duplicate of this issue.

perske set Version to 2.0.22.May 22 2014, 2:03 PM
perske added a subscriber: perske.
perske renamed this task from Do not expect KeyIDs to be unique to Do not expect KeyGrip to be unique.May 22 2014, 2:06 PM

Deeper analysis showed that not the keygrip but the DN is misinterpreted as
unique identifyer for a certificate when used in the SENDCERT inquire by
dirmngr. So I correct the title again.

The distinguished name distinguishes human beings or network end points but
neither certificates nor key pairs. For valid reasons, there can be multiple
certificates with the same DN and these certificates may contain the same or
different public keys. The GnuPG suite has to learn to handle this situation.

Using gpgsm with the options --disable-dirmngr --disable-crl-checks made our
webmailer work again, but places all users at inacceptable higher risk. So I
keep the priority setting "critical".

perske renamed this task from Do not expect KeyGrip to be unique to Do not expect KeyIDs to be unique.May 23 2014, 7:05 PM
werner added a subscriber: werner.

It is not the keygrip but the authority key identifier based lookup
which fails. Quite obvious if they do that stupid re-issuing. The
problem with dirmngr is only a side-effect of gpg not using the proper
certificate form the chain. Though, the question is which is the
proper certificate? They are both correct. I solved that my looking
for all matching certificates and using the latest one. That should
match reality better. Below is a log using a certificate store with
both DFN certificates. I have not done any Dirmngr tests, though.

The old certificate:

    ID: 0xFFFFFFFFA3EFE945
   S/N: 00C7
Issuer: /CN=Deutsche Telekom Root CA 2/OU=T-TeleSec Trust

Center/O=Deutsche Telekom AG/C=DE

  Subject: /CN=DFN-Verein PCA Global - G01/OU=DFN-PKI/O=DFN-Verein/C=DE
 validity: 2006-12-19 10:29:00 through 2019-06-30 23:59:00
 key type: 2048 bit RSA
key usage: certSign crlSign

chain length: 2

  fingerprint: F0:28:8F:DA:C6:3A:F7:9A:31:9A:E9:72:F3:95:09:0E:A3:EF:E9:45

The re-issued one:

    ID: 0x55715DB8
   S/N: 0089901115583E879B
Issuer: /CN=Deutsche Telekom Root CA 2/OU=T-TeleSec Trust

Center/O=Deutsche Telekom AG/C=DE

  Subject: /CN=DFN-Verein PCA Global - G01/OU=DFN-PKI/O=DFN-Verein/C=DE
 validity: 2014-02-11 13:11:45 through 2019-07-09 23:59:00
 key type: 2048 bit RSA
key usage: certSign crlSign

chain length: 2

  fingerprint: 2E:EF:D9:C0:99:A2:BB:1C:2B:AC:52:97:BD:FF:D8:C8:55:71:5D:B8

Use gpgsm --dump-cert to see the other info. By deleting one or the
other certificate and importing them in a different order, it is
possible to verify that the latest certificate is use.

$ echo hallo | ~/b/gnupg/sm/gpgsm -ea --disable-crl-checks --debug 1 -r Schnarre
gpgsm: used in a production environment or with production keys!
gpgsm: enabled debug flags: x509
gpgsm: DBG: BEGIN Certificate 'target':
gpgsm: DBG: serial: 13F7C661A329F4
gpgsm: DBG: notBefore: 2012-06-13 08:01:21
gpgsm: DBG: notAfter: 2015-06-13 08:01:21
gpgsm: DBG: issuer:
1.2.840.113549.1.9.1=#706B692D63614062756E6465737461672E6465,CN=Deutscher
Bundestag CA - G01,OU=Deutscher Bundestag,O=Deutscher Bundestag,C=DE
gpgsm: DBG: subject:
1.2.840.113549.1.9.1=#736162696E652E6C657574686575737365722D7363686E617272656E6265726765724062756E6465737461672E6465,CN=Sabine
Leutheusser-Schnarrenberger,OU=MdB,O=Deutscher Bundestag,C=DE
gpgsm: DBG: hash algo: 1.2.840.113549.1.1.5
gpgsm: DBG: SHA1 Fingerprint:
73:99:B8:58:93:E5:F8:E0:D7:7C:BE:7F:D8:4C:14:86:78:A1:E8:03
gpgsm: DBG: END Certificate
gpgsm: failed to open '/home/wk/.gnupg/policies.txt': No such file or directory
gpgsm: note: non-critical certificate policy not allowed
gpgsm: DBG: looking for parent certificate
gpgsm: DBG: found via authid and keyid
gpgsm: DBG: got issuer's certificate:
gpgsm: DBG: BEGIN Certificate 'issuer':
gpgsm: DBG: serial: 0D688CAF
gpgsm: DBG: notBefore: 2008-12-17 14:39:27
gpgsm: DBG: notAfter: 2019-06-30 00:00:00
gpgsm: DBG: issuer: CN=DFN-Verein PCA Global - G01,OU=DFN-PKI,O=DFN-Verein,C=DE
gpgsm: DBG: subject:
1.2.840.113549.1.9.1=#706B692D63614062756E6465737461672E6465,CN=Deutscher
Bundestag CA - G01,OU=Deutscher Bundestag,O=Deutscher Bundestag,C=DE
gpgsm: DBG: hash algo: 1.2.840.113549.1.1.5
gpgsm: DBG: SHA1 Fingerprint:
0A:0D:87:72:EE:E7:B9:47:AE:A7:FC:58:C5:47:90:7F:75:F9:50:62
gpgsm: DBG: END Certificate
gpgsm: DBG: gcry_pk_verify: Success
gpgsm: certificate is good
gpgsm: DBG: looking for parent certificate
gpgsm: DBG: found via authid and keyid
gpgsm: DBG: got issuer's certificate:
gpgsm: DBG: BEGIN Certificate 'issuer':
gpgsm: DBG: serial: 0089901115583E879B
gpgsm: DBG: notBefore: 2014-02-11 13:11:45
gpgsm: DBG: notAfter: 2019-07-09 23:59:00
gpgsm: DBG: issuer: CN=Deutsche Telekom Root CA 2,OU=T-TeleSec Trust
Center,O=Deutsche Telekom AG,C=DE
gpgsm: DBG: subject: CN=DFN-Verein PCA Global - G01,OU=DFN-PKI,O=DFN-Verein,C=DE
gpgsm: DBG: hash algo: 1.2.840.113549.1.1.11
gpgsm: DBG: SHA1 Fingerprint:
2E:EF:D9:C0:99:A2:BB:1C:2B:AC:52:97:BD:FF:D8:C8:55:71:5D:B8
gpgsm: DBG: END Certificate
gpgsm: DBG: gcry_pk_verify: Success
gpgsm: intermediate certificate is good
gpgsm: DBG: looking for parent certificate
gpgsm: DBG: found via authid and keyid
gpgsm: DBG: got issuer's certificate:
gpgsm: DBG: BEGIN Certificate 'issuer':
gpgsm: DBG: serial: 26
gpgsm: DBG: notBefore: 1999-07-09 12:11:00
gpgsm: DBG: notAfter: 2019-07-09 23:59:00
gpgsm: DBG: issuer: CN=Deutsche Telekom Root CA 2,OU=T-TeleSec Trust
Center,O=Deutsche Telekom AG,C=DE
gpgsm: DBG: subject: CN=Deutsche Telekom Root CA 2,OU=T-TeleSec Trust
Center,O=Deutsche Telekom AG,C=DE
gpgsm: DBG: hash algo: 1.2.840.113549.1.1.5
gpgsm: DBG: SHA1 Fingerprint:
85:A4:08:C0:9C:19:3E:5D:51:58:7D:CD:D6:13:30:FD:8C:DE:37:BF
gpgsm: DBG: END Certificate
gpgsm: DBG: gcry_pk_verify: Success
gpgsm: root certificate is good
gpgsm: CRLs not checked due to --disable-crl-checks option
gpgsm: validation model used: shell
gpgsm: encrypted data created

werner added a project: S/MIME.
werner closed this task as Resolved.
werner claimed this task.

Fixed in 2.0.23.

Sorry, the fix does not remove the bug:

[/home/permail/RHEL5/devel/gpgfamily/bin/gpgsm] [--no-greeting] [--yes]
[--auto-issuer-key-retrieve] [--batch] [--no-tty] [--homedir]
[/home/p/perske/.perMail/gnupghome] [--base64] [--detach] [--local-user]
[&7CF2C58D823C0ED461ED6B1FD13F9E96B6F7C436] [--status-fd] [8] [--output]
[/index/permail/RHEL5/devel/sso/work/pgp.89542620000040ef.out] [--sign]
[/index/permail/RHEL5/devel/sso/work/pgp.89542620000040ef.dat]
(using a self-written pinentry replacement)

gpgsm: note: non-critical certificate policy not allowed
dirmngr[25485.0]: permanently loaded certificates: 0
dirmngr[25485.0]: runtime cached certificates: 0
dirmngr[25485.0]: no CRL available for issuer id
A52EFAEFBC86EF98C5E9AA92B3ECEC4101080F0A
gpgsm: certificate not found: Ambiguous name
dirmngr[25485.0]: assuan_inquire(SENDCERT) failed: IPC call has been cancelled
dirmngr[25485.0]: error fetching certificate by subject: No data
dirmngr[25485.0]: crl_parse_insert failed: Missing certificate
dirmngr[25485.0]: crl_cache_insert via DP failed: Missing certificate
dirmngr[25485.0]: command ISVALID failed: Missing certificate
gpgsm: certificate
#1700BFBB98F74B/1.2.840.113549.1.9.1=#636140756E692D6D75656E737465722E6465,CN=Zertifizierungsstelle
Universitaet Muenster - G02,O=Universitaet Muenster,C=DE
gpgsm: checking the CRL failed: Not found
gpgsm: can't sign using `&7CF2C58D823C0ED461ED6B1FD13F9E96B6F7C436': Not found

Currently used versions:

dirmngr-1.1.1.tar.bz2
dirmngr-1.1.1-pth-fix.patch
gnupg-1.4.17.tar.bz2
gnupg-2.0.24.tar.bz2
libassuan-2.1.1.tar.bz2
libgcrypt-1.6.1.tar.bz2
libgpg-error-1.13.tar.bz2
libksba-1.3.0.tar.bz2
pinentry-0.8.3.tar.bz2
pth-2.0.7.tar.gz
(my own) pinentry.c

The assuan_inquire(SENDCERT) above requests a certificate by distinguished name,
not by authority key identifier (see T1644 (perske on May 23 2014, 07:05 PM / Roundup)), thus it does not matter that the
certificates re-issued by the DFN-PKI kept their authority key identifiers; the
problem is triggered by (correctly) keeping the Distinguished Name.

(I did not yet analyze your bugfix.)

perske reopened this task as Open.Jul 1 2014, 11:10 AM

Can you please try with 2.1.2 ?

perske added a comment.Mar 3 2015, 7:38 PM

I really want to try, but I cannot compile 2.1.2 due to T1862.

werner lowered the priority of this task from Unbreak Now! to Normal.Mar 16 2015, 3:06 PM

With 2.1.2, the bug still exists:

[/home/permail/RHEL5/devel/gpgfamily/bin/gpgsm] [--no-greeting] [--yes]
[--auto-issuer-key-retrieve] [--batch] [--no-tty] [--homedir]
[/home/p/perske/.perMail/gnupghome] [--base64] [--detach] [--local-user]
[&7CF2C58D823C0ED461ED6B1FD13F9E96B6F7C436] [--status-fd] [8] [--output]
[/index/permail/RHEL5/devel/sso/work/pgp.fe5316b600000e8a.out] [--sign]
[/index/permail/RHEL5/devel/sso/work/pgp.fe5316b600000e8a.dat]
(using a self-written pinentry replacement)

Output is now reduced, but basically unchanged:

gpgsm: Note: non-critical certificate policy not allowed
gpgsm: certificate not found: Ambiguous name
gpgsm: certificate
#1700BFBB98F74B/1.2.840.113549.1.9.1=#636140756E692D6D75656E737465722E6465,CN=Zertifizierungsstelle
Universitaet Muenster - G02,O=Universitaet Muenster,C=DE
gpgsm: checking the CRL failed: Not found
gpgsm: can't sign using '&7CF2C58D823C0ED461ED6B1FD13F9E96B6F7C436': Not found

Currently used versions:

gnupg-1.4.18.tar.bz2
gnupg-2.1.2.tar.bz2 (build process patched according to T1862)
libassuan-2.2.0.tar.bz2
libgcrypt-1.6.2.tar.bz2
libgpg-error-1.18.tar.bz2
libksba-1.3.2.tar.bz2
npth-1.1.tar.bz2
pinentry-0.9.0.tar.bz2
(my own) pinentry.c

perske changed Version from 2.0.22 to 2.0.22, 2.1.2.Apr 27 2015, 2:05 PM

The error "Ambiguous Name" is generated in "sm/certlist.c" in gpgsm_find_cert().

Arguments to this function are:

name:

"/1.2.840.113549.1.9.1=#636140756E692D6D75656E737465722E6465,CN=Zertifizierungsstelle
Universitaet Muenster - G02,O=Universitaet Muenster,C=DE"

keyid: NULL

Caller is the function inq_certificate() in "sm/call-dirmngr.c".
Argument to this function is:

line: "SENDCERT

/1.2.840.113549.1.9.1=#636140756E692D6D75656E737465722E6465,CN=Zertifizierungsstelle
Universitaet Muenster - G02,O=Universitaet Muenster,C=DE"
This is caused in function gpgsm_dirmngr_isvalid() in "sm/call-dirmngr.c" by
calling assuan_transact() with

  line: "ISVALID A52EFAEFBC86EF98C5E9AA92B3ECEC4101080F0A.1700BFBB98F74B"

When looking up the CRL, GnuPG assumes that there is only one certificate with
the Distinguished Name of the Certification Authority.
But that is not true: Distinguished Names distinguish identities, not
certificates. The same identity can hold multiple certificates at the same time.
So GnuPG must be fixed to allow multiple valid certificates with the same
Distinguished Name.
Wenn looking up a CRL, GnuPG may use any of these certificates.
My proposal: Perhaps you could implement and use a dirmngr function "SENDANYCERT"?

perske changed Version from 2.0.22, 2.1.2 to 2.0.22, 2.1.3.Apr 30 2015, 8:16 PM

I propose to implement a partly solution as a start: Add a 4th parameter
"allow_ambiguous" to gpgsm_find_cert() in "sm/certlist.c".

When called from "sm/gpgsm.c" or "sm/server.c" or anywhere else, set this
parameter to 0. Then gpgsm_find_cert() will behave like before.

When called by inq_certificate() in "sm/call-dirmngr.c", set this parameter to

  1. Then gpgsm_find_cert() will not bail out an ambiguous certificates, but

return the newest one of the matching certificates (according to
validity.notBefore).

(I am not sure what to pass when called by run_command_inq_cb() in
"sm/call-dirmngr.c" because I did not yet understand in which situation this
callback is used.)

As far as I can see, this change never hurts, but it helps when there are
multiple certificates for intermediate CAs with identical subject and identical
key by allowing to use "gpgsm" without "--disable-crl-checs --disable-dirmngr".

See attached patch.

(A complete solution probably requires call-dirmngr to return all matching
certificates and dirmngr to try each of the returned certificates in a loop.)

With T1590 irrelevant, issues 1862, 1970, and 2336 resolved (very special
thanks to everyone who helped in fixing them!), this is the only problem left in
version 2.1.14 that forces me to use a patched version of gpgsm for my webmailer.

My patch from 2014-04-30 works, but by mistake ("if (cmp < 0)" in place of "if
(cmp > 0)" it selects not the newest but the oldest one of the ambiguous
certificates what is bad in the DFN PKI because an older one of the certificates
is revoked, so I attach a new patch against 2.1.14.

@perske, may I ask you to send a DCO and an possible updated patch against 2.2 to gnupg-devel@ ? I would like to add it to 2.2.2. Sorry for the delays.

werner moved this task from gpg20 to gpg21 on the gnupg board.Oct 20 2017, 1:16 PM
werner edited projects, added gnupg (gpg21); removed gnupg, gnupg (gpg20).

I am preparing the patch I am using against 2.2.0. What is DCO?

werner moved this task from gpg21 to gpg22 on the gnupg board.Oct 20 2017, 1:41 PM
werner edited projects, added gnupg (gpg22); removed gnupg (gpg21).

Thanks.

DCO = Developer's Certificate of Origin. See gnupg/doc/HACKING under "** License Policy" .

werner closed this task as Resolved.Oct 24 2017, 5:51 PM