Directly trusted self-issued end-entity certs - Re: How to rotate cert when only first matching cert been verified

定平袁 pkudingping at gmail.com
Sat Jan 2 06:53:56 UTC 2021


@Michael Wojcik <Michael.Wojcik at microfocus.com>
Thanks for your reply! It makes sense more that you said, the RFC pages are
indeed hard to read...

@David von Oheimb <dev at 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 <dev at ddvo.net> 于2021年1月2日周六 上午5:17写道:

> On 01.01.21 08:07, 定平袁 wrote:
>
> @David von Oheimb <dev at 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 <dev at ddvo.net> 于2020年12月26日周六 下午5:17写道:
>
>> On 25.12.20 00:35, 定平袁 wrote:
>>
>> @David von Oheimb <dev at 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
>>
>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mta.openssl.org/pipermail/openssl-users/attachments/20210102/e3997099/attachment.html>


More information about the openssl-users mailing list