Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extended Key Usage: incompatible key usage #846

Closed
tam7t opened this issue Dec 13, 2015 · 14 comments
Closed

Extended Key Usage: incompatible key usage #846

tam7t opened this issue Dec 13, 2015 · 14 comments
Milestone

Comments

@tam7t
Copy link
Contributor

tam7t commented Dec 13, 2015

I'm having difficulty validating certificates generated with the pki backend as described in the documentation.

When I use the pki/root/generate/internal endpoint to generate a root certificate it has the following properties:

X509v3 Extended Key Usage:
        OCSP Signing

and the cert generated from pki/issue/example-dot-com:

X509v3 Extended Key Usage:
        TLS Web Server Authentication, TLS Web Client Authentication

however, the client code

CAPool := x509.NewCertPool()
rootCert, _ := ioutil.ReadFile("root.pem")
CAPool.AppendCertsFromPEM(rootCert)

var tlsConfig = &tls.Config{
  RootCAs: CAPool,
}
s, err := tls.Dial("tcp", "blah.example.com:8080", tlsConfig)

errors with

x509: certificate specifies an incompatible key usage

My understanding is that since the root cert specifies x509.ExtKeyUsageOCSPSigning (but not x509.ExtKeyUsageServerAuth) the validation fails.

I've 'correct' this locally by removing certTemplate.ExtKeyUsage = append(certTemplate.ExtKeyUsage, x509.ExtKeyUsageOCSPSigning) sense it seems that most Root CA's don't have any extended key usage properties set. Another solution might be add a roles parameter to the api, but not sure if there's something I'm doing wrong/don't understand or what solution makes the most sense.

@jefferai
Copy link
Member

Hi @tam7t

At the moment I don't have a good answer for this, for a few reasons:

  1. My understanding (and a quick skimming of the RFC) doesn't indicate that OCSP signing must go along with server auth. I'm not aware of any standard that requires that the signer of an OCSP statement is also the web server; the OCSP request and response is a binary protocol and there's no reason it couldn't be passed through to a separate server for signing. I could be wrong, but I haven't yet found evidence that I am.

  2. If OCSP signing truly required server auth, the Go code creating the certificate ought to validate that. Granted, this would mean that this would be a bug/enhancement to Go, but it generally refuses to issue invalid certificates.

  3. The error you're seeing comes from src/crypto/x509/verify.go, which doesn't actually check for anything OCSP related. What it does check for is the key usages that are requested. -- see https://golang.org/pkg/crypto/x509/#VerifyOptions

  4. Looking through Go's TLS code, any in-built VerifyOptions usage doesn't actually do much in the way of key usage checking. In fact, the only time that code passes in a KeyUsages parameter to VerifyOptions is if it's asked to verify a client cert if given, and in that case it looks only for x509.ExtKeyUsageClientAuth. I also find nothing in the net/http package.

So it's hard to say at this moment what's going on, but, (3) suggests that a missing piece of information is knowing what key usages are actually being requested by the verifying function -- and in fact, I don't know from your output above whether you're seeing this error from your client or from a Golang server. Any chance that code is share-able?

@tam7t
Copy link
Contributor Author

tam7t commented Dec 14, 2015

Sure, here is a gist of the example code with the generated certificates: https://gist.github.com/tam7t/a1e8a1fedabd48caeb97

I believe that the issue occurs because go certificate validations verifies that the signing certs have the requested leaf extended usage. So in this example the leaf wants to use TLS Web Server Authentication but the root only has OCSP Signing usage so the chain fails. I believe this happens here.

@jefferai
Copy link
Member

Oh, @$!%#

// An empty list means ExtKeyUsageServerAuth. Key usage is considered a
// constraint down the chain which mirrors Windows CryptoAPI behaviour,
// but not the spec.

I didn't notice that bit in the comment. One of those things you pass over a million times but don't think about until it becomes a problem.

So I think we're basically both right - the spec doesn't require it, but Go does because it's not spec compliant.

In the short term, if the code is your own, can you set the verify options to ExtKeyUsageAny? For the next release I'll slot flags in to indicate what key usages should be used in the CA. Once the fix is in you'll be notified here so if you need to generate a root cert hopefully it won't be a long wait.

@jefferai jefferai added this to the 0.5.0 milestone Dec 14, 2015
@jefferai
Copy link
Member

So the question now is, should we just add all usages to CA certs, or add toggleable flags. @tam7t @james-masson do you have thoughts on this?

On the one hand it seems like we shouldn't be doing that if it's not necessary especially since not all crypto stacks will behave the way that Go is. On the other hand, if Windows stacks behave this way, and we anticipate many Go clients, without seeing significant downsides we might as well just add all of them. That removes user confusion and/or mistakes from causing an issue down the line.

@jefferai
Copy link
Member

Thinking about it, I'm leaning towards just adding all of them, and in addition, adding all of them to intermediate CAs being signed.

Thoughts?

@tam7t
Copy link
Contributor Author

tam7t commented Dec 14, 2015

That seams reasonable to me

@tam7t
Copy link
Contributor Author

tam7t commented Dec 14, 2015

Well, is there a reason to specify them at all on CA certificates? Since the RFC says In general, this extension will appear only in end entity certificates and it appears that checkChainForKeyUsage treats no usages as 'any': https://golang.org/src/crypto/x509/verify.go#L441

@jefferai
Copy link
Member

@tam7t I'd be worried about other crypto stacks not behaving the same way, and also, I think it's nice for the leaf certs being issued to be able to be constrained for organizations that want a bit of extra security, e.g. it's nice for an org to be able to issue certs for email encryption/signing with a DNS SAN for that user's machine that a user can't then try to put onto a web server on their machine to run unauthorized services. I think we're probably better off forcing an ExtKeyUsageAny value for CAs than dropping back to only using basic keyusage constraints.

Does that make sense/do you agree?

jefferai added a commit that referenced this issue Dec 14, 2015
* Move to one place for both code paths
* Assign ExtKeyUsageAny to CA certs to help with validation with the
  Windows Crypto API and Go's validation logic

Fixes #846
@jefferai
Copy link
Member

@tam7t See what you think of that commit ^ -- any chance you can make sure that fixes your issue?

@tam7t
Copy link
Contributor Author

tam7t commented Dec 14, 2015

👍 yeah that makes sense. I also tried out the branch and its working, thanks!

@jefferai
Copy link
Member

Great!

@iSynaptic
Copy link

Wasted days trying to figure out why Consul health checks wouldn't accept certs generated by Vault. Finally tied what I was seeing to this issue. :( When is the 0.5 release scheduled to be available? Need this fix ASAP. Thx!

@jefferai
Copy link
Member

jefferai commented Jan 11, 2016 via email

@jefferai
Copy link
Member

(edit: oops, wrong issue)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants