openssl: X.509 certificate extended key usage (EKU) is checked very loosely

When opening for instance a TLS connection, one would expect that the EKU extension (if present) of the server cert allows for X509_PURPOSE_SSL_SERVER and the EKU extension (if present) of the client cert (if present) allows for X509_PURPOSE_SSL_CLIENT, but barely any such checks are done by OpenSSL.

Its this just for compatibility with broken certs or because people don’t care much about (extended) key usage restrictions?

There are very few uses of X509_check_purpose(), and this function even has been undocumented for long time until October 2019.

Update: I meanwhile found that ssl_verify_cert_chain() in ssl/ssl_cert.c, which is called for both the client and server side during TLS connection, does set up a default purpose X509_PURPOSE_SSL_{SERVER,CLIENT} to be checked:

    /*
     * We need to inherit the verify parameters. These can be determined by
     * the context: if its a server it will verify SSL client certificates or
     * vice versa.
     */

    X509_STORE_CTX_set_default(ctx, s->server ? "ssl_client" : "ssl_server");
    /*
     * Anything non-default in "s->param" should overwrite anything in the ctx.
     */
    X509_VERIFY_PARAM_set1(param, s->param);

~I wonder why apparently there is not at least some strictness option (-x509_strict and -strict come to mind) that would lead to X509_check_purpose(cert, X509_PURPOSE_SSL_SERVER, 0) or X509_check_purpose(cert, X509_PURPOSE_SSL_CLIENT, 0) being called during TLS handshake.~

BTW, the documentation of -strict (SSL_CERT_FLAG_TLS_STRICT) is ridiculous:

enables strict mode protocol handling. 
Equivalent to setting B<SSL_CERT_FLAG_TLS_STRICT>.

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Comments: 46 (46 by maintainers)

Most upvoted comments

So what OpenSSL simply ~does~ maybe should do - for good reasons - is to support those EKUs without assuming any meaning for them. This of course shifts the responsibility how to use them and when to check them to the users - which makes sense.

Update: Meanwhile I’d like to withdraw this whole statement of mine - see below.

Sorry for the slow response. It would absolutely be harmful to default to serverAuth/clientAuth, because TLS is used in so many more places than just the Web!

This is true even if we constrain ourselves to RFC 5280:

   The following key usage purposes are defined:

   anyExtendedKeyUsage OBJECT IDENTIFIER ::= { id-ce-extKeyUsage 0 }

   id-kp OBJECT IDENTIFIER ::= { id-pkix 3 }

   id-kp-serverAuth             OBJECT IDENTIFIER ::= { id-kp 1 }
   -- TLS WWW server authentication
   -- Key usage bits that may be consistent: digitalSignature,
   -- keyEncipherment or keyAgreement

The id-kp-serverAuth extended key usage, which corresponds to our X509_PURPOSE_SSL_SERVER, is for Web TLS server authentication.

The fact that OpenSSL includes built-in logic for checking id-kp-serverAuth/id-kp-clientAuth but makes the user jump through several hoops to use a different extendedKeyUsage makes it harder for me as IETF Security Area Director to help direct (non-Web) TLS-using protocols towards allocating a dedicated extendedKeyUsage for their certificates, since it’s so much easier to just reuse the builtin ones. This, in turn, ends up negating a lot of the value that extendedKeyUsage itself was supposed to provide! To make the Web extended key usage values the default in OpenSSL would just make it even harder for non-Web protocols to operate properly. OpenSSL does not and cannot know a priori what context a TLS connection is being established in, and guessing will be harmful. We make it fairly easy for applications to request verification of the Web key usages, but IMO that is as far as we should go towards default policy. I would even say that we should make it easier to request enforcement of an extendedKeyUsage value just by OID, without needing to (e.g.) specify an app_verify_callback" or the more-correct-but-more-complicated X509_PURPOSE_add()` approach, as described at https://mailarchive.ietf.org/arch/msg/dtn/G2qi9Qwz09kkuzRbdEWrDqoHLwc/

BTW, what do you think about #14218?

I’m happy to see work in this space, and thank you for putting it together! I haven’t had an opportunity yet to actually review it carefully, though.

If differentiating various flavors of TLS client/servers certs was deemed important there should have been specific EKU OIDs for those since long.

Well, anybody can mint an EKU value – it’s just an OID. What’s perhaps relevant is getting a CA you want to use to start issuing certificate using that EKU OID, and that’s up to their own policy and purpose as a CA. For the Web PKI, there is no reason to use other EKU OIDs, since the existing WWW/Web OIDs are exactly what is correct. This gets into the point that Rich mentioned (maybe on #14199 vs here) about there being many PKIs and Ryan Sleevi’s remarks thereto. At present, people are (ab)using the Web PKI for SMTP usage and in that sense are stuck inheriting the policy (including on EKU OID issuance) of the Web PKI CAs. Should there be a separate PKI for SMTP usage? Arguably – there’s a lot different about the ways they use TLS, and Viktor can (and has) share details of the differences. Those even extend to what name you use to validate the certificate against, namely the email address domain name vs. the DNS name of the actual SMTP server.

Yet this has not happened, at least not in any public, standardized way.

It depends on what protocols you are considering. https://www.iana.org/assignments/smi-numbers/smi-numbers.xhtml#smi-numbers-1.3.6.1.5.5.7.3 lists a number of public, standard, EKU assignments in an IANA-controlled arc, but there is no requirement that EKU values are only obtained in this OID arc.

If differentiating various flavors of TLS client/servers certs was deemed important there should have been specific EKU OIDs for those since long. Yet this has not happened, at least not in any public, standardized way.

So the whole situation whether id-kp-{client,server}Auth is restricted to WWW use has been unclear for many years and this will not change before RFC 5280 is updated or replaced.

The errata set there because the IETF was loathe to open up 5280 for anything for a very long time. Until something is done, an errata is just one person’s opinion.

Note that there is the LAMPS working group (https://datatracker.ietf.org/wg/lamps/documents/) is undergoing a re-charter, and one of the items being considered is updating 5280 (https://mailarchive.ietf.org/arch/msg/spasm/wf148GFEMZlM-1M2AYaM8AFnEig/ starts the thread; there’s several messages about 5280 in particular).

If 5280 gets revised it will be, my estimate, at least two years. Perhaps it would be worthwhile to close this and open a generic issue “track 5280bis” Shrug.

I’ve meanwhile removed the bug report label from this issue because I now see that the bug is in RFC 5280 😉

I just found that RFC 5280 has the - so far unhandled - following errata entry: https://www.rfc-editor.org/errata/eid5802

Errata ID: 5802 Status: Reported Type: Technical Publication Format(s) : TEXT Reported By: Nikos Mavrogiannopoulos Date Reported: 2019-08-06

Section 4.2.1.12 says:

id-kp-serverAuth OBJECT IDENTIFIER ::= { id-kp 1 } – TLS WWW server authentication – Key usage bits that may be consistent: digitalSignature, – keyEncipherment or keyAgreement

id-kp-clientAuth OBJECT IDENTIFIER ::= { id-kp 2 } – TLS WWW client authentication – Key usage bits that may be consistent: digitalSignature – and/or keyAgreement

It should say:

id-kp-serverAuth OBJECT IDENTIFIER ::= { id-kp 1 } – TLS server authentication – Key usage bits that may be consistent: digitalSignature, – keyEncipherment or keyAgreement

id-kp-clientAuth OBJECT IDENTIFIER ::= { id-kp 2 } – TLS client authentication – Key usage bits that may be consistent: digitalSignature – and/or keyAgreement

Notes:

The proposed change removes the WWW part of the description. In practice these object identifiers are used for server and client applications, but not necessarily web applications. In particular:

  • openssl verification considers them unconditionally even if the server is not a web server or the client a web client
  • There is no object identifier that can be used for protocols like SMTP, IMAP, POP3, LDAP, radius, …; in practice all these protocols are deployed with the identifiers for WWW
  • Standards like common criteria assume that these object identifiers are for generic server and clients [0].

[0]. https://www.niap-ccevs.org/MMO/PP/-442-/#FCS_TLSC_EXT.1.1

Apparently most users do not really care and take those EKUs for any TLS client/server use.

Welcome to the real world. 😃

Full and strict RFC compliance rarely exists, and limiting what OpenSSL does to do that would be a really bad idea.

I do not see a problem in making -purpose sslserver the default for s_client

And how do you turn it off? Yet another flag?

Yet even using them:

openssl s_client -connect www.google.com:443 -purpose smimeencrypt -strict

one does get connected with just a little warning saying

Verify return code: 26 (unsupported certificate purpose)

I consider this a bug, not a feature.

This is NOT a bug. You have to use -verify_return_error for any certificate verification error to abort the connection.