@Michael Wojcik <michael.woj...@microfocus.com> Thanks for your reply! It makes sense more that you said, the RFC pages are indeed hard to read...
@David von Oheimb <d...@ddvo.net> thanks for the clarification! Sorry for my misunderstanding, also thanks for your fix, I will follow up on that too. BTW, OpenSSL is such a friendly community. Regards, Dingping David von Oheimb <d...@ddvo.net> 于2021年1月2日周六 上午5:17写道: > On 01.01.21 08:07, 定平袁 wrote: > > @David von Oheimb <d...@ddvo.net> > Thank you so much for your deep investigation! > > My pleasure! > > With subjectKeyIdentifier and authorityKeyIdentifier extensions, it works > like a charm! > > Good to hear. > I've meanwhile submitted a pull request that fixed the behavior also in > case no SKID and AKID are included in the certs > and briefly mentioned your use case there: > https://github.com/openssl/openssl/pull/13748 > > So, the former statements I found on this page > <https://www.openssl.org/docs/man1.0.2/man3/SSL_CTX_load_verify_locations.html> > only applies to CA cert, not EE cert. > How to pick up cert from trust store(or cert container as you say) > is decided by different implementation themselves, do I understand > correctly? > > It looks like my explanations were a bit mistakable. > Although self-signed (and more generally, self-issued) EE certs are out of > scope of RFC 5280, OpenSSL still tries to build a cert chain for them and > then to verify it. > Please also note that I did not write "cert container", but that these > certs are essentially just a convenient container *for a public key*. > In other words, they have the *format* of an X.509 certificate, but the > only thing that really matters in such a cert is the public key. > Yet since they look like a certificate, they can be used where a > certificate is expected, e.g., in TLS handshake and in trust stores. > > Since GnuTls and golang could pick up the right cert in this kind of > scenario, > they must implement their own logic to pick up the right cert, do you > think OpenSSL > will implement this logic too? Or it's a more appropriate approach to just > use the extensions you suggested? > > With the fix mentioned above, chain building and verification will always > succeed, > regardless how the cert looks like because in this case it is sufficient > to find the target certificate in the trust store, > without having to check and further data that may be included in it. > Although not required by RFC 5280 for such a cert, OpenSSL does check for > its expiration > (and may check policy restrictions etc.) because this is helpful in most > application scenarios. > > Regards, > > David > > > David von Oheimb <d...@ddvo.net> 于2020年12月26日周六 下午5:17写道: > >> On 25.12.20 00:35, 定平袁 wrote: >> >> @David von Oheimb <d...@ddvo.net> I will update to a new version and try >> again. >> >> Good. Ideally try also a current 3.0.0 alpha release because there have >> been some changes to cert chain building and verification recently. >> >> To append cert is to make sure new cert and old cert both exist in trust >> store, thus when server switches cert, it can be trusted by client. >> >> Understood, but my point was on a different aspect: >> The chain building will take the first matching cert, so if you want to >> prefer the new cert, it must be in the list *before* the old one - >> in other words, prepend the new cert to the list rather than appending to >> it. >> >> @Jochen actually, the certs have different SN, which indeed is not >> consistent with the man doc >> >> Different certs with the same issuer indeed *must* have different SNs >> (except in the special case I mention below). >> See also RFC 5280 section 4.1.2.2 >> https://tools.ietf.org/html/rfc5280#section-4.1.2.2: >> >> It MUST be unique for each certificate issued by a given CA >> (i.e., the issuer name and serial number identify a unique certificate). >> >> >> Yet there is a different inconsistency in what you write: >> >> The thing that confuses me is that CURL (compiled with gnutls) and Golang >> works. >> below is my ca.crt file, I am not sure where it went wrong, maybe just my >> wrong behavior? >> >> You refer to them as CA certs, but they are not: they do no have a >> basicConstraints field with the cA bit set. >> And as far as I understand your scenario, they are not used to issue >> other certs but by some (TLS) server, >> so they really are end-entity (EE) certs, not CA certs, and it looks like >> this is correct in your application scenario. >> >> Directly trusted self-issued EE certs (which may be self-signed or not) >> are a special situation. >> This has been clarified in RFC 6818 (which updates RFC 5280) >> https://tools.ietf.org/html/rfc6818#section-2: >> >> | Consistent with Section 3.4.61 >> <https://tools.ietf.org/html/rfc6818#section-3.4.61> of X.509 (11/2008) >> [X.509 <https://tools.ietf.org/html/rfc6818#ref-X.509>], we note >> | that use of self-issued certificates and self-signed certificates >> | issued by entities other than CAs are outside the scope of this >> | specification. Thus, for example, a web server or client might >> | generate a self-signed certificate to identify itself. These >> | certificates and how a relying party uses them to authenticate >> | asserted identities are both outside the scope of RFC 5280 >> <https://tools.ietf.org/html/rfc5280>. >> >> So the path building and verification, as well as other checks defined >> RFC 5280, does not apply to them at all! >> They are essentially just a convenient container for a public key, where >> it is optional to check expiration etc. >> >> >> Unfortunately, when using such certs for TLS connections etc., still >> verification is done on them, which may fail. >> After renaming your ca.crt file to ee.crt for clarity and extracting the >> first cert in ee1.crt and the second one in ee2.crt, >> when verifying these directly trusted certs one gets the problem you >> reported: >> >> openssl verify -x509_strict -trusted ee.crt ee1.crt >> ee1.crt: OK >> >> openssl verify -x509_strict -trusted ee.crt ee2.crt >> C = US, ST = CA, L = Palo Alto, O = VMware, CN = >> nsxmanager.pks.vmware.local >> error 18 at 0 depth lookup: self signed certificate >> error ee2.crt: verification failed >> >> So as I wrote before, unfortunately the path building picks up the first >> matching cert from ee.crt, >> which is the one in ee1.crt (i.e., your old one), and does not try the >> second one (i.e., your new one). >> This happens also with the latest OpenSSL pre-3.0.0 master. >> >> >> A solution is to add both the subjectKeyIdentifier and >> authorityKeyIdentifier extensions to your certs, >> for instance like this: >> >> echo >ee.cnf " >> prompt = no >> distinguished_name = my_server >> x509_extensions = my_exts >> [my_server] >> commonName = test >> [my_exts] >> basicConstraints = CA:false >> subjectKeyIdentifier=hash >> authorityKeyIdentifier = keyid" >> >> openssl req -config ee.cnf -new -x509 -out ee1.crt -nodes -keyout ee1.pem >> openssl req -config ee.cnf -new -x509 -out ee2.crt -nodes -keyout ee2.pem >> cat ee1.crt ee2.crt >ee.crt >> >> The subjectKeyIdentifier and authorityKeyIdentifier extensions are >> generally recommend >> (and actually required to add for certs that are RFC 5280 compliant) >> because they help for correct chain building, and indeed also in this >> case they do: >> >> openssl verify -x509_strict -trusted ee.crt ee1.crt >> ee1.crt: OK >> openssl verify -x509_strict -trusted ee.crt ee2.crt >> ee2.crt: OK >> >> Regards, >> >> David >> >>