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

Improve selection of server certificate and use "signature_algorithms" extension #236

Merged
merged 11 commits into from
Jun 19, 2017
Merged

Conversation

ocheron
Copy link
Contributor

@ocheron ocheron commented Jun 9, 2017

This adds behavior described in #195, with a rework of how cipher/credential code is organized.

I was reluctant to create impacts for something non essential like #195 but see now that supporting EdDSA in the future will require filtering credentials (instead of ciphers like we did before).

On a diagram we need to go from this:

Pub/Priv Key Type <-- Key Exchange Type <-- HashAndSignatureAlg
(credential)      <-- (cipher)          <-- (supported exts)

to this:

Key Exchange Type <--> Pub/Priv Key Type <-- HashAndSignatureAlg
(cipher)          <--> (credential)      <-- (supported exts)

This is because the relation between key exchange and certificate will become n..n:

Key Exchange Public/Private Key
DHE_RSA RSA
DHE_DSS DSA
ECDHE_RSA RSA
ECDHE_ECDSA ECDSA
ECDHE_ECDSA Ed25519
ECDHE_ECDSA Ed448

Changing the design, it is easier to add something like #195. With the fallback mechanism described in TLS 1.3 this is not supposed to restrict handshake possibilities (i.e. the PR does not change test cases). So this looks safe for TLS 1.2 too.

I limited verification to the leaf certificate because a server has no reliable way to know what is the client view of trust anchors.

This is the name chosen in draft-ietf-tls-rfc4492bis-17 and appearing
in TLS HashAlgorithm Registry at IANA.
The code was overly complex because the list of server ciphers
was used twice, once for IDs and once more to get the Cipher
records.

Related to #191.
Embedding the logic to filter server ciphers directly in the parameters
themselves seems convoluted.  Moreover it applies only to server ciphers
and client ciphers do not need the extraCreds.

As credentials need to be filtered based on ClientHello extensions
it's best to move the function getCiphers directly in server code.
Implements a requirement from RFC 5246 section 7.4.2.

Fixes #195.
When client and server do not agree on hash/signature algorithms, ciphers
are not eliminated directly but indirectly through available credentials.

This is necessary for EdDSA certificates: the same cipher key exchange
ECDHE_ECDSA is reused for 3 public key algorithms ECDSA, Ed25519 and Ed448.
And filtering only ciphers does not provide enough granularity anymore.
For example ECDHE_ECDSA may be used with server having both ECDSA and
Ed25519 certificates.  If client supports only plain old ECDSA, the server
should not pick Ed25519 credentials.

The list of credentials 'creds' now becomes two lists 'creds' and
'signatureCreds'.  Function 'getCiphers' uses one of both lists depending
on cipher key-exchange type.
Draft TLS 1.3 section 4.4.2.2:  If the server cannot produce a certificate
chain that is signed only via the indicated supported algorithms, then it
SHOULD continue the handshake by sending the client a certificate chain of
its choice that may include algorithms that are not known to be supported
by the client.
Draft TLS 1.3 section 4.4.2.2:  Certificates that are self-signed or
certificates that are expected to be trust anchors are not validated
as part of the chain and therefore MAY be signed with any algorithm.

This implementation is positional only.  Server does not necessarily
knows what level in the chain the client considers as trust anchor,
so the code evaluates only a leaf certificate that is not self-signed.

Test suite does not use self-signed certificates anymore.
@ocheron
Copy link
Contributor Author

ocheron commented Jun 12, 2017

I think I simplified the fallback condition too much and that may cause failures for some cases not covered by the test suite. I'll need to test more.

@kazu-yamamoto
Copy link
Collaborator

@ocheron I'm busy in this week. So, it would take time to review this PR.

@ocheron
Copy link
Contributor Author

ocheron commented Jun 13, 2017

OK this can wait and I still need to avoid a failure case anyway.

The real interesting part is not #195 but the redesign in 6e553b5.
I noticed you have something similar with credentialsFindForSigning13.
We should find a common solution.

IIUC the full mapping is:

Key Exchange Public/Private Key
DHE_RSA RSA
DHE_DSS DSA
ECDHE_RSA RSA
ECDHE_ECDSA ECDSA, Ed25519, Ed448
TLS13 RSA, ECDSA, Ed25519, Ed448

@ocheron
Copy link
Contributor Author

ocheron commented Jun 16, 2017

It should be safe now.

@kazu-yamamoto kazu-yamamoto self-requested a review June 19, 2017 05:09
@kazu-yamamoto kazu-yamamoto merged commit bfca224 into haskell-tls:master Jun 19, 2017
Copy link
Collaborator

@kazu-yamamoto kazu-yamamoto left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@kazu-yamamoto
Copy link
Collaborator

Merged.

@ocheron
Copy link
Contributor Author

ocheron commented Jun 21, 2017

Thanks.

My experiment about EdDSA went very well, as I have ECDSA/Ed25519/Ed448 working correctly.
Our test suite runs with all three together, Ed25519 certificates generated with OpenSSL work, and Ed25519 handshake interoperates with BoringSSL / OpenSSL.

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

Successfully merging this pull request may close these issues.

None yet

2 participants