Alternative TLS implementation in Go
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

handshake_server.go 24 KiB

crypto/tls: decouple handshake signatures from the handshake hash. Prior to TLS 1.2, the handshake had a pleasing property that one could incrementally hash it and, from that, get the needed hashes for both the CertificateVerify and Finished messages. TLS 1.2 introduced negotiation for the signature and hash and it became possible for the handshake hash to be, say, SHA-384, but for the CertificateVerify to sign the handshake with SHA-1. The problem is that one doesn't know in advance which hashes will be needed and thus the handshake needs to be buffered. Go ignored this, always kept a single handshake hash, and any signatures over the handshake had to use that hash. However, there are a set of servers that inspect the client's offered signature hash functions and will abort the handshake if one of the server's certificates is signed with a hash function outside of that set. https://robertsspaceindustries.com/ is an example of such a server. Clearly not a lot of thought happened when that server code was written, but its out there and we have to deal with it. This change decouples the handshake hash from the CertificateVerify hash. This lays the groundwork for advertising support for SHA-384 but doesn't actually make that change in the interests of reviewability. Updating the advertised hash functions will cause changes in many of the testdata/ files and some errors might get lost in the noise. This change only needs to update four testdata/ files: one because a SHA-384-based handshake is now being signed with SHA-256 and the others because the TLS 1.2 CertificateRequest message now includes SHA-1. This change also has the effect of adding support for client-certificates in SSLv3 servers. However, SSLv3 is now disabled by default so this should be moot. It would be possible to avoid much of this change and just support SHA-384 for the ServerKeyExchange as the SKX only signs over the nonces and SKX params (a design mistake in TLS). However, that would leave Go in the odd situation where it advertised support for SHA-384, but would only use the handshake hash when signing client certificates. I fear that'll just cause problems in the future. Much of this code was written by davidben@ for the purposes of testing BoringSSL. Partly addresses #9757 Change-Id: I5137a472b6076812af387a5a69fc62c7373cd485 Reviewed-on: https://go-review.googlesource.com/9415 Run-TryBot: Adam Langley <agl@golang.org> Reviewed-by: Adam Langley <agl@golang.org>
9 jaren geleden
crypto/tls: decouple handshake signatures from the handshake hash. Prior to TLS 1.2, the handshake had a pleasing property that one could incrementally hash it and, from that, get the needed hashes for both the CertificateVerify and Finished messages. TLS 1.2 introduced negotiation for the signature and hash and it became possible for the handshake hash to be, say, SHA-384, but for the CertificateVerify to sign the handshake with SHA-1. The problem is that one doesn't know in advance which hashes will be needed and thus the handshake needs to be buffered. Go ignored this, always kept a single handshake hash, and any signatures over the handshake had to use that hash. However, there are a set of servers that inspect the client's offered signature hash functions and will abort the handshake if one of the server's certificates is signed with a hash function outside of that set. https://robertsspaceindustries.com/ is an example of such a server. Clearly not a lot of thought happened when that server code was written, but its out there and we have to deal with it. This change decouples the handshake hash from the CertificateVerify hash. This lays the groundwork for advertising support for SHA-384 but doesn't actually make that change in the interests of reviewability. Updating the advertised hash functions will cause changes in many of the testdata/ files and some errors might get lost in the noise. This change only needs to update four testdata/ files: one because a SHA-384-based handshake is now being signed with SHA-256 and the others because the TLS 1.2 CertificateRequest message now includes SHA-1. This change also has the effect of adding support for client-certificates in SSLv3 servers. However, SSLv3 is now disabled by default so this should be moot. It would be possible to avoid much of this change and just support SHA-384 for the ServerKeyExchange as the SKX only signs over the nonces and SKX params (a design mistake in TLS). However, that would leave Go in the odd situation where it advertised support for SHA-384, but would only use the handshake hash when signing client certificates. I fear that'll just cause problems in the future. Much of this code was written by davidben@ for the purposes of testing BoringSSL. Partly addresses #9757 Change-Id: I5137a472b6076812af387a5a69fc62c7373cd485 Reviewed-on: https://go-review.googlesource.com/9415 Run-TryBot: Adam Langley <agl@golang.org> Reviewed-by: Adam Langley <agl@golang.org>
9 jaren geleden
crypto/tls: decouple handshake signatures from the handshake hash. Prior to TLS 1.2, the handshake had a pleasing property that one could incrementally hash it and, from that, get the needed hashes for both the CertificateVerify and Finished messages. TLS 1.2 introduced negotiation for the signature and hash and it became possible for the handshake hash to be, say, SHA-384, but for the CertificateVerify to sign the handshake with SHA-1. The problem is that one doesn't know in advance which hashes will be needed and thus the handshake needs to be buffered. Go ignored this, always kept a single handshake hash, and any signatures over the handshake had to use that hash. However, there are a set of servers that inspect the client's offered signature hash functions and will abort the handshake if one of the server's certificates is signed with a hash function outside of that set. https://robertsspaceindustries.com/ is an example of such a server. Clearly not a lot of thought happened when that server code was written, but its out there and we have to deal with it. This change decouples the handshake hash from the CertificateVerify hash. This lays the groundwork for advertising support for SHA-384 but doesn't actually make that change in the interests of reviewability. Updating the advertised hash functions will cause changes in many of the testdata/ files and some errors might get lost in the noise. This change only needs to update four testdata/ files: one because a SHA-384-based handshake is now being signed with SHA-256 and the others because the TLS 1.2 CertificateRequest message now includes SHA-1. This change also has the effect of adding support for client-certificates in SSLv3 servers. However, SSLv3 is now disabled by default so this should be moot. It would be possible to avoid much of this change and just support SHA-384 for the ServerKeyExchange as the SKX only signs over the nonces and SKX params (a design mistake in TLS). However, that would leave Go in the odd situation where it advertised support for SHA-384, but would only use the handshake hash when signing client certificates. I fear that'll just cause problems in the future. Much of this code was written by davidben@ for the purposes of testing BoringSSL. Partly addresses #9757 Change-Id: I5137a472b6076812af387a5a69fc62c7373cd485 Reviewed-on: https://go-review.googlesource.com/9415 Run-TryBot: Adam Langley <agl@golang.org> Reviewed-by: Adam Langley <agl@golang.org>
9 jaren geleden
crypto/tls: decouple handshake signatures from the handshake hash. Prior to TLS 1.2, the handshake had a pleasing property that one could incrementally hash it and, from that, get the needed hashes for both the CertificateVerify and Finished messages. TLS 1.2 introduced negotiation for the signature and hash and it became possible for the handshake hash to be, say, SHA-384, but for the CertificateVerify to sign the handshake with SHA-1. The problem is that one doesn't know in advance which hashes will be needed and thus the handshake needs to be buffered. Go ignored this, always kept a single handshake hash, and any signatures over the handshake had to use that hash. However, there are a set of servers that inspect the client's offered signature hash functions and will abort the handshake if one of the server's certificates is signed with a hash function outside of that set. https://robertsspaceindustries.com/ is an example of such a server. Clearly not a lot of thought happened when that server code was written, but its out there and we have to deal with it. This change decouples the handshake hash from the CertificateVerify hash. This lays the groundwork for advertising support for SHA-384 but doesn't actually make that change in the interests of reviewability. Updating the advertised hash functions will cause changes in many of the testdata/ files and some errors might get lost in the noise. This change only needs to update four testdata/ files: one because a SHA-384-based handshake is now being signed with SHA-256 and the others because the TLS 1.2 CertificateRequest message now includes SHA-1. This change also has the effect of adding support for client-certificates in SSLv3 servers. However, SSLv3 is now disabled by default so this should be moot. It would be possible to avoid much of this change and just support SHA-384 for the ServerKeyExchange as the SKX only signs over the nonces and SKX params (a design mistake in TLS). However, that would leave Go in the odd situation where it advertised support for SHA-384, but would only use the handshake hash when signing client certificates. I fear that'll just cause problems in the future. Much of this code was written by davidben@ for the purposes of testing BoringSSL. Partly addresses #9757 Change-Id: I5137a472b6076812af387a5a69fc62c7373cd485 Reviewed-on: https://go-review.googlesource.com/9415 Run-TryBot: Adam Langley <agl@golang.org> Reviewed-by: Adam Langley <agl@golang.org>
9 jaren geleden
crypto/tls: decouple handshake signatures from the handshake hash. Prior to TLS 1.2, the handshake had a pleasing property that one could incrementally hash it and, from that, get the needed hashes for both the CertificateVerify and Finished messages. TLS 1.2 introduced negotiation for the signature and hash and it became possible for the handshake hash to be, say, SHA-384, but for the CertificateVerify to sign the handshake with SHA-1. The problem is that one doesn't know in advance which hashes will be needed and thus the handshake needs to be buffered. Go ignored this, always kept a single handshake hash, and any signatures over the handshake had to use that hash. However, there are a set of servers that inspect the client's offered signature hash functions and will abort the handshake if one of the server's certificates is signed with a hash function outside of that set. https://robertsspaceindustries.com/ is an example of such a server. Clearly not a lot of thought happened when that server code was written, but its out there and we have to deal with it. This change decouples the handshake hash from the CertificateVerify hash. This lays the groundwork for advertising support for SHA-384 but doesn't actually make that change in the interests of reviewability. Updating the advertised hash functions will cause changes in many of the testdata/ files and some errors might get lost in the noise. This change only needs to update four testdata/ files: one because a SHA-384-based handshake is now being signed with SHA-256 and the others because the TLS 1.2 CertificateRequest message now includes SHA-1. This change also has the effect of adding support for client-certificates in SSLv3 servers. However, SSLv3 is now disabled by default so this should be moot. It would be possible to avoid much of this change and just support SHA-384 for the ServerKeyExchange as the SKX only signs over the nonces and SKX params (a design mistake in TLS). However, that would leave Go in the odd situation where it advertised support for SHA-384, but would only use the handshake hash when signing client certificates. I fear that'll just cause problems in the future. Much of this code was written by davidben@ for the purposes of testing BoringSSL. Partly addresses #9757 Change-Id: I5137a472b6076812af387a5a69fc62c7373cd485 Reviewed-on: https://go-review.googlesource.com/9415 Run-TryBot: Adam Langley <agl@golang.org> Reviewed-by: Adam Langley <agl@golang.org>
9 jaren geleden
crypto/tls: decouple handshake signatures from the handshake hash. Prior to TLS 1.2, the handshake had a pleasing property that one could incrementally hash it and, from that, get the needed hashes for both the CertificateVerify and Finished messages. TLS 1.2 introduced negotiation for the signature and hash and it became possible for the handshake hash to be, say, SHA-384, but for the CertificateVerify to sign the handshake with SHA-1. The problem is that one doesn't know in advance which hashes will be needed and thus the handshake needs to be buffered. Go ignored this, always kept a single handshake hash, and any signatures over the handshake had to use that hash. However, there are a set of servers that inspect the client's offered signature hash functions and will abort the handshake if one of the server's certificates is signed with a hash function outside of that set. https://robertsspaceindustries.com/ is an example of such a server. Clearly not a lot of thought happened when that server code was written, but its out there and we have to deal with it. This change decouples the handshake hash from the CertificateVerify hash. This lays the groundwork for advertising support for SHA-384 but doesn't actually make that change in the interests of reviewability. Updating the advertised hash functions will cause changes in many of the testdata/ files and some errors might get lost in the noise. This change only needs to update four testdata/ files: one because a SHA-384-based handshake is now being signed with SHA-256 and the others because the TLS 1.2 CertificateRequest message now includes SHA-1. This change also has the effect of adding support for client-certificates in SSLv3 servers. However, SSLv3 is now disabled by default so this should be moot. It would be possible to avoid much of this change and just support SHA-384 for the ServerKeyExchange as the SKX only signs over the nonces and SKX params (a design mistake in TLS). However, that would leave Go in the odd situation where it advertised support for SHA-384, but would only use the handshake hash when signing client certificates. I fear that'll just cause problems in the future. Much of this code was written by davidben@ for the purposes of testing BoringSSL. Partly addresses #9757 Change-Id: I5137a472b6076812af387a5a69fc62c7373cd485 Reviewed-on: https://go-review.googlesource.com/9415 Run-TryBot: Adam Langley <agl@golang.org> Reviewed-by: Adam Langley <agl@golang.org>
9 jaren geleden
crypto/tls: decouple handshake signatures from the handshake hash. Prior to TLS 1.2, the handshake had a pleasing property that one could incrementally hash it and, from that, get the needed hashes for both the CertificateVerify and Finished messages. TLS 1.2 introduced negotiation for the signature and hash and it became possible for the handshake hash to be, say, SHA-384, but for the CertificateVerify to sign the handshake with SHA-1. The problem is that one doesn't know in advance which hashes will be needed and thus the handshake needs to be buffered. Go ignored this, always kept a single handshake hash, and any signatures over the handshake had to use that hash. However, there are a set of servers that inspect the client's offered signature hash functions and will abort the handshake if one of the server's certificates is signed with a hash function outside of that set. https://robertsspaceindustries.com/ is an example of such a server. Clearly not a lot of thought happened when that server code was written, but its out there and we have to deal with it. This change decouples the handshake hash from the CertificateVerify hash. This lays the groundwork for advertising support for SHA-384 but doesn't actually make that change in the interests of reviewability. Updating the advertised hash functions will cause changes in many of the testdata/ files and some errors might get lost in the noise. This change only needs to update four testdata/ files: one because a SHA-384-based handshake is now being signed with SHA-256 and the others because the TLS 1.2 CertificateRequest message now includes SHA-1. This change also has the effect of adding support for client-certificates in SSLv3 servers. However, SSLv3 is now disabled by default so this should be moot. It would be possible to avoid much of this change and just support SHA-384 for the ServerKeyExchange as the SKX only signs over the nonces and SKX params (a design mistake in TLS). However, that would leave Go in the odd situation where it advertised support for SHA-384, but would only use the handshake hash when signing client certificates. I fear that'll just cause problems in the future. Much of this code was written by davidben@ for the purposes of testing BoringSSL. Partly addresses #9757 Change-Id: I5137a472b6076812af387a5a69fc62c7373cd485 Reviewed-on: https://go-review.googlesource.com/9415 Run-TryBot: Adam Langley <agl@golang.org> Reviewed-by: Adam Langley <agl@golang.org>
9 jaren geleden
crypto/tls: decouple handshake signatures from the handshake hash. Prior to TLS 1.2, the handshake had a pleasing property that one could incrementally hash it and, from that, get the needed hashes for both the CertificateVerify and Finished messages. TLS 1.2 introduced negotiation for the signature and hash and it became possible for the handshake hash to be, say, SHA-384, but for the CertificateVerify to sign the handshake with SHA-1. The problem is that one doesn't know in advance which hashes will be needed and thus the handshake needs to be buffered. Go ignored this, always kept a single handshake hash, and any signatures over the handshake had to use that hash. However, there are a set of servers that inspect the client's offered signature hash functions and will abort the handshake if one of the server's certificates is signed with a hash function outside of that set. https://robertsspaceindustries.com/ is an example of such a server. Clearly not a lot of thought happened when that server code was written, but its out there and we have to deal with it. This change decouples the handshake hash from the CertificateVerify hash. This lays the groundwork for advertising support for SHA-384 but doesn't actually make that change in the interests of reviewability. Updating the advertised hash functions will cause changes in many of the testdata/ files and some errors might get lost in the noise. This change only needs to update four testdata/ files: one because a SHA-384-based handshake is now being signed with SHA-256 and the others because the TLS 1.2 CertificateRequest message now includes SHA-1. This change also has the effect of adding support for client-certificates in SSLv3 servers. However, SSLv3 is now disabled by default so this should be moot. It would be possible to avoid much of this change and just support SHA-384 for the ServerKeyExchange as the SKX only signs over the nonces and SKX params (a design mistake in TLS). However, that would leave Go in the odd situation where it advertised support for SHA-384, but would only use the handshake hash when signing client certificates. I fear that'll just cause problems in the future. Much of this code was written by davidben@ for the purposes of testing BoringSSL. Partly addresses #9757 Change-Id: I5137a472b6076812af387a5a69fc62c7373cd485 Reviewed-on: https://go-review.googlesource.com/9415 Run-TryBot: Adam Langley <agl@golang.org> Reviewed-by: Adam Langley <agl@golang.org>
9 jaren geleden
crypto/tls: decouple handshake signatures from the handshake hash. Prior to TLS 1.2, the handshake had a pleasing property that one could incrementally hash it and, from that, get the needed hashes for both the CertificateVerify and Finished messages. TLS 1.2 introduced negotiation for the signature and hash and it became possible for the handshake hash to be, say, SHA-384, but for the CertificateVerify to sign the handshake with SHA-1. The problem is that one doesn't know in advance which hashes will be needed and thus the handshake needs to be buffered. Go ignored this, always kept a single handshake hash, and any signatures over the handshake had to use that hash. However, there are a set of servers that inspect the client's offered signature hash functions and will abort the handshake if one of the server's certificates is signed with a hash function outside of that set. https://robertsspaceindustries.com/ is an example of such a server. Clearly not a lot of thought happened when that server code was written, but its out there and we have to deal with it. This change decouples the handshake hash from the CertificateVerify hash. This lays the groundwork for advertising support for SHA-384 but doesn't actually make that change in the interests of reviewability. Updating the advertised hash functions will cause changes in many of the testdata/ files and some errors might get lost in the noise. This change only needs to update four testdata/ files: one because a SHA-384-based handshake is now being signed with SHA-256 and the others because the TLS 1.2 CertificateRequest message now includes SHA-1. This change also has the effect of adding support for client-certificates in SSLv3 servers. However, SSLv3 is now disabled by default so this should be moot. It would be possible to avoid much of this change and just support SHA-384 for the ServerKeyExchange as the SKX only signs over the nonces and SKX params (a design mistake in TLS). However, that would leave Go in the odd situation where it advertised support for SHA-384, but would only use the handshake hash when signing client certificates. I fear that'll just cause problems in the future. Much of this code was written by davidben@ for the purposes of testing BoringSSL. Partly addresses #9757 Change-Id: I5137a472b6076812af387a5a69fc62c7373cd485 Reviewed-on: https://go-review.googlesource.com/9415 Run-TryBot: Adam Langley <agl@golang.org> Reviewed-by: Adam Langley <agl@golang.org>
9 jaren geleden
crypto/tls: decouple handshake signatures from the handshake hash. Prior to TLS 1.2, the handshake had a pleasing property that one could incrementally hash it and, from that, get the needed hashes for both the CertificateVerify and Finished messages. TLS 1.2 introduced negotiation for the signature and hash and it became possible for the handshake hash to be, say, SHA-384, but for the CertificateVerify to sign the handshake with SHA-1. The problem is that one doesn't know in advance which hashes will be needed and thus the handshake needs to be buffered. Go ignored this, always kept a single handshake hash, and any signatures over the handshake had to use that hash. However, there are a set of servers that inspect the client's offered signature hash functions and will abort the handshake if one of the server's certificates is signed with a hash function outside of that set. https://robertsspaceindustries.com/ is an example of such a server. Clearly not a lot of thought happened when that server code was written, but its out there and we have to deal with it. This change decouples the handshake hash from the CertificateVerify hash. This lays the groundwork for advertising support for SHA-384 but doesn't actually make that change in the interests of reviewability. Updating the advertised hash functions will cause changes in many of the testdata/ files and some errors might get lost in the noise. This change only needs to update four testdata/ files: one because a SHA-384-based handshake is now being signed with SHA-256 and the others because the TLS 1.2 CertificateRequest message now includes SHA-1. This change also has the effect of adding support for client-certificates in SSLv3 servers. However, SSLv3 is now disabled by default so this should be moot. It would be possible to avoid much of this change and just support SHA-384 for the ServerKeyExchange as the SKX only signs over the nonces and SKX params (a design mistake in TLS). However, that would leave Go in the odd situation where it advertised support for SHA-384, but would only use the handshake hash when signing client certificates. I fear that'll just cause problems in the future. Much of this code was written by davidben@ for the purposes of testing BoringSSL. Partly addresses #9757 Change-Id: I5137a472b6076812af387a5a69fc62c7373cd485 Reviewed-on: https://go-review.googlesource.com/9415 Run-TryBot: Adam Langley <agl@golang.org> Reviewed-by: Adam Langley <agl@golang.org>
9 jaren geleden
crypto/tls: decouple handshake signatures from the handshake hash. Prior to TLS 1.2, the handshake had a pleasing property that one could incrementally hash it and, from that, get the needed hashes for both the CertificateVerify and Finished messages. TLS 1.2 introduced negotiation for the signature and hash and it became possible for the handshake hash to be, say, SHA-384, but for the CertificateVerify to sign the handshake with SHA-1. The problem is that one doesn't know in advance which hashes will be needed and thus the handshake needs to be buffered. Go ignored this, always kept a single handshake hash, and any signatures over the handshake had to use that hash. However, there are a set of servers that inspect the client's offered signature hash functions and will abort the handshake if one of the server's certificates is signed with a hash function outside of that set. https://robertsspaceindustries.com/ is an example of such a server. Clearly not a lot of thought happened when that server code was written, but its out there and we have to deal with it. This change decouples the handshake hash from the CertificateVerify hash. This lays the groundwork for advertising support for SHA-384 but doesn't actually make that change in the interests of reviewability. Updating the advertised hash functions will cause changes in many of the testdata/ files and some errors might get lost in the noise. This change only needs to update four testdata/ files: one because a SHA-384-based handshake is now being signed with SHA-256 and the others because the TLS 1.2 CertificateRequest message now includes SHA-1. This change also has the effect of adding support for client-certificates in SSLv3 servers. However, SSLv3 is now disabled by default so this should be moot. It would be possible to avoid much of this change and just support SHA-384 for the ServerKeyExchange as the SKX only signs over the nonces and SKX params (a design mistake in TLS). However, that would leave Go in the odd situation where it advertised support for SHA-384, but would only use the handshake hash when signing client certificates. I fear that'll just cause problems in the future. Much of this code was written by davidben@ for the purposes of testing BoringSSL. Partly addresses #9757 Change-Id: I5137a472b6076812af387a5a69fc62c7373cd485 Reviewed-on: https://go-review.googlesource.com/9415 Run-TryBot: Adam Langley <agl@golang.org> Reviewed-by: Adam Langley <agl@golang.org>
9 jaren geleden
crypto/tls: decouple handshake signatures from the handshake hash. Prior to TLS 1.2, the handshake had a pleasing property that one could incrementally hash it and, from that, get the needed hashes for both the CertificateVerify and Finished messages. TLS 1.2 introduced negotiation for the signature and hash and it became possible for the handshake hash to be, say, SHA-384, but for the CertificateVerify to sign the handshake with SHA-1. The problem is that one doesn't know in advance which hashes will be needed and thus the handshake needs to be buffered. Go ignored this, always kept a single handshake hash, and any signatures over the handshake had to use that hash. However, there are a set of servers that inspect the client's offered signature hash functions and will abort the handshake if one of the server's certificates is signed with a hash function outside of that set. https://robertsspaceindustries.com/ is an example of such a server. Clearly not a lot of thought happened when that server code was written, but its out there and we have to deal with it. This change decouples the handshake hash from the CertificateVerify hash. This lays the groundwork for advertising support for SHA-384 but doesn't actually make that change in the interests of reviewability. Updating the advertised hash functions will cause changes in many of the testdata/ files and some errors might get lost in the noise. This change only needs to update four testdata/ files: one because a SHA-384-based handshake is now being signed with SHA-256 and the others because the TLS 1.2 CertificateRequest message now includes SHA-1. This change also has the effect of adding support for client-certificates in SSLv3 servers. However, SSLv3 is now disabled by default so this should be moot. It would be possible to avoid much of this change and just support SHA-384 for the ServerKeyExchange as the SKX only signs over the nonces and SKX params (a design mistake in TLS). However, that would leave Go in the odd situation where it advertised support for SHA-384, but would only use the handshake hash when signing client certificates. I fear that'll just cause problems in the future. Much of this code was written by davidben@ for the purposes of testing BoringSSL. Partly addresses #9757 Change-Id: I5137a472b6076812af387a5a69fc62c7373cd485 Reviewed-on: https://go-review.googlesource.com/9415 Run-TryBot: Adam Langley <agl@golang.org> Reviewed-by: Adam Langley <agl@golang.org>
9 jaren geleden
crypto/tls: decouple handshake signatures from the handshake hash. Prior to TLS 1.2, the handshake had a pleasing property that one could incrementally hash it and, from that, get the needed hashes for both the CertificateVerify and Finished messages. TLS 1.2 introduced negotiation for the signature and hash and it became possible for the handshake hash to be, say, SHA-384, but for the CertificateVerify to sign the handshake with SHA-1. The problem is that one doesn't know in advance which hashes will be needed and thus the handshake needs to be buffered. Go ignored this, always kept a single handshake hash, and any signatures over the handshake had to use that hash. However, there are a set of servers that inspect the client's offered signature hash functions and will abort the handshake if one of the server's certificates is signed with a hash function outside of that set. https://robertsspaceindustries.com/ is an example of such a server. Clearly not a lot of thought happened when that server code was written, but its out there and we have to deal with it. This change decouples the handshake hash from the CertificateVerify hash. This lays the groundwork for advertising support for SHA-384 but doesn't actually make that change in the interests of reviewability. Updating the advertised hash functions will cause changes in many of the testdata/ files and some errors might get lost in the noise. This change only needs to update four testdata/ files: one because a SHA-384-based handshake is now being signed with SHA-256 and the others because the TLS 1.2 CertificateRequest message now includes SHA-1. This change also has the effect of adding support for client-certificates in SSLv3 servers. However, SSLv3 is now disabled by default so this should be moot. It would be possible to avoid much of this change and just support SHA-384 for the ServerKeyExchange as the SKX only signs over the nonces and SKX params (a design mistake in TLS). However, that would leave Go in the odd situation where it advertised support for SHA-384, but would only use the handshake hash when signing client certificates. I fear that'll just cause problems in the future. Much of this code was written by davidben@ for the purposes of testing BoringSSL. Partly addresses #9757 Change-Id: I5137a472b6076812af387a5a69fc62c7373cd485 Reviewed-on: https://go-review.googlesource.com/9415 Run-TryBot: Adam Langley <agl@golang.org> Reviewed-by: Adam Langley <agl@golang.org>
9 jaren geleden
crypto/tls: decouple handshake signatures from the handshake hash. Prior to TLS 1.2, the handshake had a pleasing property that one could incrementally hash it and, from that, get the needed hashes for both the CertificateVerify and Finished messages. TLS 1.2 introduced negotiation for the signature and hash and it became possible for the handshake hash to be, say, SHA-384, but for the CertificateVerify to sign the handshake with SHA-1. The problem is that one doesn't know in advance which hashes will be needed and thus the handshake needs to be buffered. Go ignored this, always kept a single handshake hash, and any signatures over the handshake had to use that hash. However, there are a set of servers that inspect the client's offered signature hash functions and will abort the handshake if one of the server's certificates is signed with a hash function outside of that set. https://robertsspaceindustries.com/ is an example of such a server. Clearly not a lot of thought happened when that server code was written, but its out there and we have to deal with it. This change decouples the handshake hash from the CertificateVerify hash. This lays the groundwork for advertising support for SHA-384 but doesn't actually make that change in the interests of reviewability. Updating the advertised hash functions will cause changes in many of the testdata/ files and some errors might get lost in the noise. This change only needs to update four testdata/ files: one because a SHA-384-based handshake is now being signed with SHA-256 and the others because the TLS 1.2 CertificateRequest message now includes SHA-1. This change also has the effect of adding support for client-certificates in SSLv3 servers. However, SSLv3 is now disabled by default so this should be moot. It would be possible to avoid much of this change and just support SHA-384 for the ServerKeyExchange as the SKX only signs over the nonces and SKX params (a design mistake in TLS). However, that would leave Go in the odd situation where it advertised support for SHA-384, but would only use the handshake hash when signing client certificates. I fear that'll just cause problems in the future. Much of this code was written by davidben@ for the purposes of testing BoringSSL. Partly addresses #9757 Change-Id: I5137a472b6076812af387a5a69fc62c7373cd485 Reviewed-on: https://go-review.googlesource.com/9415 Run-TryBot: Adam Langley <agl@golang.org> Reviewed-by: Adam Langley <agl@golang.org>
9 jaren geleden
crypto/tls: decouple handshake signatures from the handshake hash. Prior to TLS 1.2, the handshake had a pleasing property that one could incrementally hash it and, from that, get the needed hashes for both the CertificateVerify and Finished messages. TLS 1.2 introduced negotiation for the signature and hash and it became possible for the handshake hash to be, say, SHA-384, but for the CertificateVerify to sign the handshake with SHA-1. The problem is that one doesn't know in advance which hashes will be needed and thus the handshake needs to be buffered. Go ignored this, always kept a single handshake hash, and any signatures over the handshake had to use that hash. However, there are a set of servers that inspect the client's offered signature hash functions and will abort the handshake if one of the server's certificates is signed with a hash function outside of that set. https://robertsspaceindustries.com/ is an example of such a server. Clearly not a lot of thought happened when that server code was written, but its out there and we have to deal with it. This change decouples the handshake hash from the CertificateVerify hash. This lays the groundwork for advertising support for SHA-384 but doesn't actually make that change in the interests of reviewability. Updating the advertised hash functions will cause changes in many of the testdata/ files and some errors might get lost in the noise. This change only needs to update four testdata/ files: one because a SHA-384-based handshake is now being signed with SHA-256 and the others because the TLS 1.2 CertificateRequest message now includes SHA-1. This change also has the effect of adding support for client-certificates in SSLv3 servers. However, SSLv3 is now disabled by default so this should be moot. It would be possible to avoid much of this change and just support SHA-384 for the ServerKeyExchange as the SKX only signs over the nonces and SKX params (a design mistake in TLS). However, that would leave Go in the odd situation where it advertised support for SHA-384, but would only use the handshake hash when signing client certificates. I fear that'll just cause problems in the future. Much of this code was written by davidben@ for the purposes of testing BoringSSL. Partly addresses #9757 Change-Id: I5137a472b6076812af387a5a69fc62c7373cd485 Reviewed-on: https://go-review.googlesource.com/9415 Run-TryBot: Adam Langley <agl@golang.org> Reviewed-by: Adam Langley <agl@golang.org>
9 jaren geleden
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842
  1. // Copyright 2009 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package tls
  5. import (
  6. "crypto"
  7. "crypto/ecdsa"
  8. "crypto/rsa"
  9. "crypto/subtle"
  10. "crypto/x509"
  11. "encoding/asn1"
  12. "errors"
  13. "fmt"
  14. "io"
  15. )
  16. // serverHandshakeState contains details of a server handshake in progress.
  17. // It's discarded once the handshake has completed.
  18. type serverHandshakeState struct {
  19. c *Conn
  20. clientHello *clientHelloMsg
  21. hello *serverHelloMsg
  22. suite *cipherSuite
  23. ellipticOk bool
  24. ecdsaOk bool
  25. rsaDecryptOk bool
  26. rsaSignOk bool
  27. sessionState *sessionState
  28. finishedHash finishedHash
  29. masterSecret []byte
  30. certsFromClient [][]byte
  31. cert *Certificate
  32. cachedClientHelloInfo *ClientHelloInfo
  33. }
  34. // serverHandshake performs a TLS handshake as a server.
  35. // c.out.Mutex <= L; c.handshakeMutex <= L.
  36. func (c *Conn) serverHandshake() error {
  37. // If this is the first server handshake, we generate a random key to
  38. // encrypt the tickets with.
  39. c.config.serverInitOnce.Do(c.config.serverInit)
  40. hs := serverHandshakeState{
  41. c: c,
  42. }
  43. isResume, err := hs.readClientHello()
  44. if err != nil {
  45. return err
  46. }
  47. // For an overview of TLS handshaking, see https://tools.ietf.org/html/rfc5246#section-7.3
  48. c.buffering = true
  49. if isResume {
  50. // The client has included a session ticket and so we do an abbreviated handshake.
  51. if err := hs.doResumeHandshake(); err != nil {
  52. return err
  53. }
  54. if err := hs.establishKeys(); err != nil {
  55. return err
  56. }
  57. // ticketSupported is set in a resumption handshake if the
  58. // ticket from the client was encrypted with an old session
  59. // ticket key and thus a refreshed ticket should be sent.
  60. if hs.hello.ticketSupported {
  61. if err := hs.sendSessionTicket(); err != nil {
  62. return err
  63. }
  64. }
  65. if err := hs.sendFinished(c.serverFinished[:]); err != nil {
  66. return err
  67. }
  68. if _, err := c.flush(); err != nil {
  69. return err
  70. }
  71. c.clientFinishedIsFirst = false
  72. if err := hs.readFinished(nil); err != nil {
  73. return err
  74. }
  75. c.didResume = true
  76. } else {
  77. // The client didn't include a session ticket, or it wasn't
  78. // valid so we do a full handshake.
  79. if err := hs.doFullHandshake(); err != nil {
  80. return err
  81. }
  82. if err := hs.establishKeys(); err != nil {
  83. return err
  84. }
  85. if err := hs.readFinished(c.clientFinished[:]); err != nil {
  86. return err
  87. }
  88. c.clientFinishedIsFirst = true
  89. c.buffering = true
  90. if err := hs.sendSessionTicket(); err != nil {
  91. return err
  92. }
  93. if err := hs.sendFinished(nil); err != nil {
  94. return err
  95. }
  96. if _, err := c.flush(); err != nil {
  97. return err
  98. }
  99. }
  100. c.handshakeComplete = true
  101. return nil
  102. }
  103. // readClientHello reads a ClientHello message from the client and decides
  104. // whether we will perform session resumption.
  105. func (hs *serverHandshakeState) readClientHello() (isResume bool, err error) {
  106. c := hs.c
  107. msg, err := c.readHandshake()
  108. if err != nil {
  109. return false, err
  110. }
  111. var ok bool
  112. hs.clientHello, ok = msg.(*clientHelloMsg)
  113. if !ok {
  114. c.sendAlert(alertUnexpectedMessage)
  115. return false, unexpectedMessageError(hs.clientHello, msg)
  116. }
  117. if c.config.GetConfigForClient != nil {
  118. if newConfig, err := c.config.GetConfigForClient(hs.clientHelloInfo()); err != nil {
  119. c.sendAlert(alertInternalError)
  120. return false, err
  121. } else if newConfig != nil {
  122. newConfig.mutex.Lock()
  123. newConfig.originalConfig = c.config
  124. newConfig.mutex.Unlock()
  125. newConfig.serverInitOnce.Do(newConfig.serverInit)
  126. c.config = newConfig
  127. }
  128. }
  129. c.vers, ok = c.config.mutualVersion(hs.clientHello.vers)
  130. if !ok {
  131. c.sendAlert(alertProtocolVersion)
  132. return false, fmt.Errorf("tls: client offered an unsupported, maximum protocol version of %x", hs.clientHello.vers)
  133. }
  134. c.haveVers = true
  135. hs.hello = new(serverHelloMsg)
  136. supportedCurve := false
  137. preferredCurves := c.config.curvePreferences()
  138. Curves:
  139. for _, curve := range hs.clientHello.supportedCurves {
  140. for _, supported := range preferredCurves {
  141. if supported == curve {
  142. supportedCurve = true
  143. break Curves
  144. }
  145. }
  146. }
  147. supportedPointFormat := false
  148. for _, pointFormat := range hs.clientHello.supportedPoints {
  149. if pointFormat == pointFormatUncompressed {
  150. supportedPointFormat = true
  151. break
  152. }
  153. }
  154. hs.ellipticOk = supportedCurve && supportedPointFormat
  155. foundCompression := false
  156. // We only support null compression, so check that the client offered it.
  157. for _, compression := range hs.clientHello.compressionMethods {
  158. if compression == compressionNone {
  159. foundCompression = true
  160. break
  161. }
  162. }
  163. if !foundCompression {
  164. c.sendAlert(alertHandshakeFailure)
  165. return false, errors.New("tls: client does not support uncompressed connections")
  166. }
  167. hs.hello.vers = c.vers
  168. hs.hello.random = make([]byte, 32)
  169. _, err = io.ReadFull(c.config.rand(), hs.hello.random)
  170. if err != nil {
  171. c.sendAlert(alertInternalError)
  172. return false, err
  173. }
  174. if len(hs.clientHello.secureRenegotiation) != 0 {
  175. c.sendAlert(alertHandshakeFailure)
  176. return false, errors.New("tls: initial handshake had non-empty renegotiation extension")
  177. }
  178. hs.hello.secureRenegotiationSupported = hs.clientHello.secureRenegotiationSupported
  179. hs.hello.compressionMethod = compressionNone
  180. if len(hs.clientHello.serverName) > 0 {
  181. c.serverName = hs.clientHello.serverName
  182. }
  183. if len(hs.clientHello.alpnProtocols) > 0 {
  184. if selectedProto, fallback := mutualProtocol(hs.clientHello.alpnProtocols, c.config.NextProtos); !fallback {
  185. hs.hello.alpnProtocol = selectedProto
  186. c.clientProtocol = selectedProto
  187. }
  188. } else {
  189. // Although sending an empty NPN extension is reasonable, Firefox has
  190. // had a bug around this. Best to send nothing at all if
  191. // c.config.NextProtos is empty. See
  192. // https://golang.org/issue/5445.
  193. if hs.clientHello.nextProtoNeg && len(c.config.NextProtos) > 0 {
  194. hs.hello.nextProtoNeg = true
  195. hs.hello.nextProtos = c.config.NextProtos
  196. }
  197. }
  198. hs.cert, err = c.config.getCertificate(hs.clientHelloInfo())
  199. if err != nil {
  200. c.sendAlert(alertInternalError)
  201. return false, err
  202. }
  203. if hs.clientHello.scts {
  204. hs.hello.scts = hs.cert.SignedCertificateTimestamps
  205. }
  206. if priv, ok := hs.cert.PrivateKey.(crypto.Signer); ok {
  207. switch priv.Public().(type) {
  208. case *ecdsa.PublicKey:
  209. hs.ecdsaOk = true
  210. case *rsa.PublicKey:
  211. hs.rsaSignOk = true
  212. default:
  213. c.sendAlert(alertInternalError)
  214. return false, fmt.Errorf("tls: unsupported signing key type (%T)", priv.Public())
  215. }
  216. }
  217. if priv, ok := hs.cert.PrivateKey.(crypto.Decrypter); ok {
  218. switch priv.Public().(type) {
  219. case *rsa.PublicKey:
  220. hs.rsaDecryptOk = true
  221. default:
  222. c.sendAlert(alertInternalError)
  223. return false, fmt.Errorf("tls: unsupported decryption key type (%T)", priv.Public())
  224. }
  225. }
  226. if hs.checkForResumption() {
  227. return true, nil
  228. }
  229. var preferenceList, supportedList []uint16
  230. if c.config.PreferServerCipherSuites {
  231. preferenceList = c.config.cipherSuites()
  232. supportedList = hs.clientHello.cipherSuites
  233. } else {
  234. preferenceList = hs.clientHello.cipherSuites
  235. supportedList = c.config.cipherSuites()
  236. }
  237. for _, id := range preferenceList {
  238. if hs.setCipherSuite(id, supportedList, c.vers) {
  239. break
  240. }
  241. }
  242. if hs.suite == nil {
  243. c.sendAlert(alertHandshakeFailure)
  244. return false, errors.New("tls: no cipher suite supported by both client and server")
  245. }
  246. // See https://tools.ietf.org/html/rfc7507.
  247. for _, id := range hs.clientHello.cipherSuites {
  248. if id == TLS_FALLBACK_SCSV {
  249. // The client is doing a fallback connection.
  250. if hs.clientHello.vers < c.config.maxVersion() {
  251. c.sendAlert(alertInappropriateFallback)
  252. return false, errors.New("tls: client using inappropriate protocol fallback")
  253. }
  254. break
  255. }
  256. }
  257. return false, nil
  258. }
  259. // checkForResumption reports whether we should perform resumption on this connection.
  260. func (hs *serverHandshakeState) checkForResumption() bool {
  261. c := hs.c
  262. if c.config.SessionTicketsDisabled {
  263. return false
  264. }
  265. var ok bool
  266. var sessionTicket = append([]uint8{}, hs.clientHello.sessionTicket...)
  267. if hs.sessionState, ok = c.decryptTicket(sessionTicket); !ok {
  268. return false
  269. }
  270. // Never resume a session for a different TLS version.
  271. if c.vers != hs.sessionState.vers {
  272. return false
  273. }
  274. cipherSuiteOk := false
  275. // Check that the client is still offering the ciphersuite in the session.
  276. for _, id := range hs.clientHello.cipherSuites {
  277. if id == hs.sessionState.cipherSuite {
  278. cipherSuiteOk = true
  279. break
  280. }
  281. }
  282. if !cipherSuiteOk {
  283. return false
  284. }
  285. // Check that we also support the ciphersuite from the session.
  286. if !hs.setCipherSuite(hs.sessionState.cipherSuite, c.config.cipherSuites(), hs.sessionState.vers) {
  287. return false
  288. }
  289. sessionHasClientCerts := len(hs.sessionState.certificates) != 0
  290. needClientCerts := c.config.ClientAuth == RequireAnyClientCert || c.config.ClientAuth == RequireAndVerifyClientCert
  291. if needClientCerts && !sessionHasClientCerts {
  292. return false
  293. }
  294. if sessionHasClientCerts && c.config.ClientAuth == NoClientCert {
  295. return false
  296. }
  297. return true
  298. }
  299. func (hs *serverHandshakeState) doResumeHandshake() error {
  300. c := hs.c
  301. hs.hello.cipherSuite = hs.suite.id
  302. // We echo the client's session ID in the ServerHello to let it know
  303. // that we're doing a resumption.
  304. hs.hello.sessionId = hs.clientHello.sessionId
  305. hs.hello.ticketSupported = hs.sessionState.usedOldKey
  306. hs.finishedHash = newFinishedHash(c.vers, hs.suite)
  307. hs.finishedHash.discardHandshakeBuffer()
  308. hs.finishedHash.Write(hs.clientHello.marshal())
  309. hs.finishedHash.Write(hs.hello.marshal())
  310. if _, err := c.writeRecord(recordTypeHandshake, hs.hello.marshal()); err != nil {
  311. return err
  312. }
  313. if len(hs.sessionState.certificates) > 0 {
  314. if _, err := hs.processCertsFromClient(hs.sessionState.certificates); err != nil {
  315. return err
  316. }
  317. }
  318. hs.masterSecret = hs.sessionState.masterSecret
  319. return nil
  320. }
  321. func (hs *serverHandshakeState) doFullHandshake() error {
  322. c := hs.c
  323. if hs.clientHello.ocspStapling && len(hs.cert.OCSPStaple) > 0 {
  324. hs.hello.ocspStapling = true
  325. }
  326. hs.hello.ticketSupported = hs.clientHello.ticketSupported && !c.config.SessionTicketsDisabled
  327. hs.hello.cipherSuite = hs.suite.id
  328. hs.finishedHash = newFinishedHash(hs.c.vers, hs.suite)
  329. if c.config.ClientAuth == NoClientCert {
  330. // No need to keep a full record of the handshake if client
  331. // certificates won't be used.
  332. hs.finishedHash.discardHandshakeBuffer()
  333. }
  334. hs.finishedHash.Write(hs.clientHello.marshal())
  335. hs.finishedHash.Write(hs.hello.marshal())
  336. if _, err := c.writeRecord(recordTypeHandshake, hs.hello.marshal()); err != nil {
  337. return err
  338. }
  339. certMsg := new(certificateMsg)
  340. certMsg.certificates = hs.cert.Certificate
  341. hs.finishedHash.Write(certMsg.marshal())
  342. if _, err := c.writeRecord(recordTypeHandshake, certMsg.marshal()); err != nil {
  343. return err
  344. }
  345. if hs.hello.ocspStapling {
  346. certStatus := new(certificateStatusMsg)
  347. certStatus.statusType = statusTypeOCSP
  348. certStatus.response = hs.cert.OCSPStaple
  349. hs.finishedHash.Write(certStatus.marshal())
  350. if _, err := c.writeRecord(recordTypeHandshake, certStatus.marshal()); err != nil {
  351. return err
  352. }
  353. }
  354. keyAgreement := hs.suite.ka(c.vers)
  355. skx, err := keyAgreement.generateServerKeyExchange(c.config, hs.cert, hs.clientHello, hs.hello)
  356. if err != nil {
  357. c.sendAlert(alertHandshakeFailure)
  358. return err
  359. }
  360. if skx != nil {
  361. hs.finishedHash.Write(skx.marshal())
  362. if _, err := c.writeRecord(recordTypeHandshake, skx.marshal()); err != nil {
  363. return err
  364. }
  365. }
  366. if c.config.ClientAuth >= RequestClientCert {
  367. // Request a client certificate
  368. certReq := new(certificateRequestMsg)
  369. certReq.certificateTypes = []byte{
  370. byte(certTypeRSASign),
  371. byte(certTypeECDSASign),
  372. }
  373. if c.vers >= VersionTLS12 {
  374. certReq.hasSignatureAndHash = true
  375. certReq.signatureAndHashes = supportedSignatureAlgorithms
  376. }
  377. // An empty list of certificateAuthorities signals to
  378. // the client that it may send any certificate in response
  379. // to our request. When we know the CAs we trust, then
  380. // we can send them down, so that the client can choose
  381. // an appropriate certificate to give to us.
  382. if c.config.ClientCAs != nil {
  383. certReq.certificateAuthorities = c.config.ClientCAs.Subjects()
  384. }
  385. hs.finishedHash.Write(certReq.marshal())
  386. if _, err := c.writeRecord(recordTypeHandshake, certReq.marshal()); err != nil {
  387. return err
  388. }
  389. }
  390. helloDone := new(serverHelloDoneMsg)
  391. hs.finishedHash.Write(helloDone.marshal())
  392. if _, err := c.writeRecord(recordTypeHandshake, helloDone.marshal()); err != nil {
  393. return err
  394. }
  395. if _, err := c.flush(); err != nil {
  396. return err
  397. }
  398. var pub crypto.PublicKey // public key for client auth, if any
  399. msg, err := c.readHandshake()
  400. if err != nil {
  401. return err
  402. }
  403. var ok bool
  404. // If we requested a client certificate, then the client must send a
  405. // certificate message, even if it's empty.
  406. if c.config.ClientAuth >= RequestClientCert {
  407. if certMsg, ok = msg.(*certificateMsg); !ok {
  408. c.sendAlert(alertUnexpectedMessage)
  409. return unexpectedMessageError(certMsg, msg)
  410. }
  411. hs.finishedHash.Write(certMsg.marshal())
  412. if len(certMsg.certificates) == 0 {
  413. // The client didn't actually send a certificate
  414. switch c.config.ClientAuth {
  415. case RequireAnyClientCert, RequireAndVerifyClientCert:
  416. c.sendAlert(alertBadCertificate)
  417. return errors.New("tls: client didn't provide a certificate")
  418. }
  419. }
  420. pub, err = hs.processCertsFromClient(certMsg.certificates)
  421. if err != nil {
  422. return err
  423. }
  424. msg, err = c.readHandshake()
  425. if err != nil {
  426. return err
  427. }
  428. }
  429. // Get client key exchange
  430. ckx, ok := msg.(*clientKeyExchangeMsg)
  431. if !ok {
  432. c.sendAlert(alertUnexpectedMessage)
  433. return unexpectedMessageError(ckx, msg)
  434. }
  435. hs.finishedHash.Write(ckx.marshal())
  436. preMasterSecret, err := keyAgreement.processClientKeyExchange(c.config, hs.cert, ckx, c.vers)
  437. if err != nil {
  438. c.sendAlert(alertHandshakeFailure)
  439. return err
  440. }
  441. hs.masterSecret = masterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.clientHello.random, hs.hello.random)
  442. if err := c.config.writeKeyLog(hs.clientHello.random, hs.masterSecret); err != nil {
  443. c.sendAlert(alertInternalError)
  444. return err
  445. }
  446. // If we received a client cert in response to our certificate request message,
  447. // the client will send us a certificateVerifyMsg immediately after the
  448. // clientKeyExchangeMsg. This message is a digest of all preceding
  449. // handshake-layer messages that is signed using the private key corresponding
  450. // to the client's certificate. This allows us to verify that the client is in
  451. // possession of the private key of the certificate.
  452. if len(c.peerCertificates) > 0 {
  453. msg, err = c.readHandshake()
  454. if err != nil {
  455. return err
  456. }
  457. certVerify, ok := msg.(*certificateVerifyMsg)
  458. if !ok {
  459. c.sendAlert(alertUnexpectedMessage)
  460. return unexpectedMessageError(certVerify, msg)
  461. }
  462. // Determine the signature type.
  463. var signatureAndHash signatureAndHash
  464. if certVerify.hasSignatureAndHash {
  465. signatureAndHash = certVerify.signatureAndHash
  466. if !isSupportedSignatureAndHash(signatureAndHash, supportedSignatureAlgorithms) {
  467. return errors.New("tls: unsupported hash function for client certificate")
  468. }
  469. } else {
  470. // Before TLS 1.2 the signature algorithm was implicit
  471. // from the key type, and only one hash per signature
  472. // algorithm was possible. Leave the hash as zero.
  473. switch pub.(type) {
  474. case *ecdsa.PublicKey:
  475. signatureAndHash.signature = signatureECDSA
  476. case *rsa.PublicKey:
  477. signatureAndHash.signature = signatureRSA
  478. }
  479. }
  480. switch key := pub.(type) {
  481. case *ecdsa.PublicKey:
  482. if signatureAndHash.signature != signatureECDSA {
  483. err = errors.New("tls: bad signature type for client's ECDSA certificate")
  484. break
  485. }
  486. ecdsaSig := new(ecdsaSignature)
  487. if _, err = asn1.Unmarshal(certVerify.signature, ecdsaSig); err != nil {
  488. break
  489. }
  490. if ecdsaSig.R.Sign() <= 0 || ecdsaSig.S.Sign() <= 0 {
  491. err = errors.New("tls: ECDSA signature contained zero or negative values")
  492. break
  493. }
  494. var digest []byte
  495. if digest, _, err = hs.finishedHash.hashForClientCertificate(signatureAndHash, hs.masterSecret); err != nil {
  496. break
  497. }
  498. if !ecdsa.Verify(key, digest, ecdsaSig.R, ecdsaSig.S) {
  499. err = errors.New("tls: ECDSA verification failure")
  500. }
  501. case *rsa.PublicKey:
  502. if signatureAndHash.signature != signatureRSA {
  503. err = errors.New("tls: bad signature type for client's RSA certificate")
  504. break
  505. }
  506. var digest []byte
  507. var hashFunc crypto.Hash
  508. if digest, hashFunc, err = hs.finishedHash.hashForClientCertificate(signatureAndHash, hs.masterSecret); err != nil {
  509. break
  510. }
  511. err = rsa.VerifyPKCS1v15(key, hashFunc, digest, certVerify.signature)
  512. }
  513. if err != nil {
  514. c.sendAlert(alertBadCertificate)
  515. return errors.New("tls: could not validate signature of connection nonces: " + err.Error())
  516. }
  517. hs.finishedHash.Write(certVerify.marshal())
  518. }
  519. hs.finishedHash.discardHandshakeBuffer()
  520. return nil
  521. }
  522. func (hs *serverHandshakeState) establishKeys() error {
  523. c := hs.c
  524. clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV :=
  525. keysFromMasterSecret(c.vers, hs.suite, hs.masterSecret, hs.clientHello.random, hs.hello.random, hs.suite.macLen, hs.suite.keyLen, hs.suite.ivLen)
  526. var clientCipher, serverCipher interface{}
  527. var clientHash, serverHash macFunction
  528. if hs.suite.aead == nil {
  529. clientCipher = hs.suite.cipher(clientKey, clientIV, true /* for reading */)
  530. clientHash = hs.suite.mac(c.vers, clientMAC)
  531. serverCipher = hs.suite.cipher(serverKey, serverIV, false /* not for reading */)
  532. serverHash = hs.suite.mac(c.vers, serverMAC)
  533. } else {
  534. clientCipher = hs.suite.aead(clientKey, clientIV)
  535. serverCipher = hs.suite.aead(serverKey, serverIV)
  536. }
  537. c.in.prepareCipherSpec(c.vers, clientCipher, clientHash)
  538. c.out.prepareCipherSpec(c.vers, serverCipher, serverHash)
  539. return nil
  540. }
  541. func (hs *serverHandshakeState) readFinished(out []byte) error {
  542. c := hs.c
  543. c.readRecord(recordTypeChangeCipherSpec)
  544. if c.in.err != nil {
  545. return c.in.err
  546. }
  547. if hs.hello.nextProtoNeg {
  548. msg, err := c.readHandshake()
  549. if err != nil {
  550. return err
  551. }
  552. nextProto, ok := msg.(*nextProtoMsg)
  553. if !ok {
  554. c.sendAlert(alertUnexpectedMessage)
  555. return unexpectedMessageError(nextProto, msg)
  556. }
  557. hs.finishedHash.Write(nextProto.marshal())
  558. c.clientProtocol = nextProto.proto
  559. }
  560. msg, err := c.readHandshake()
  561. if err != nil {
  562. return err
  563. }
  564. clientFinished, ok := msg.(*finishedMsg)
  565. if !ok {
  566. c.sendAlert(alertUnexpectedMessage)
  567. return unexpectedMessageError(clientFinished, msg)
  568. }
  569. verify := hs.finishedHash.clientSum(hs.masterSecret)
  570. if len(verify) != len(clientFinished.verifyData) ||
  571. subtle.ConstantTimeCompare(verify, clientFinished.verifyData) != 1 {
  572. c.sendAlert(alertHandshakeFailure)
  573. return errors.New("tls: client's Finished message is incorrect")
  574. }
  575. hs.finishedHash.Write(clientFinished.marshal())
  576. copy(out, verify)
  577. return nil
  578. }
  579. func (hs *serverHandshakeState) sendSessionTicket() error {
  580. if !hs.hello.ticketSupported {
  581. return nil
  582. }
  583. c := hs.c
  584. m := new(newSessionTicketMsg)
  585. var err error
  586. state := sessionState{
  587. vers: c.vers,
  588. cipherSuite: hs.suite.id,
  589. masterSecret: hs.masterSecret,
  590. certificates: hs.certsFromClient,
  591. }
  592. m.ticket, err = c.encryptTicket(&state)
  593. if err != nil {
  594. return err
  595. }
  596. hs.finishedHash.Write(m.marshal())
  597. if _, err := c.writeRecord(recordTypeHandshake, m.marshal()); err != nil {
  598. return err
  599. }
  600. return nil
  601. }
  602. func (hs *serverHandshakeState) sendFinished(out []byte) error {
  603. c := hs.c
  604. if _, err := c.writeRecord(recordTypeChangeCipherSpec, []byte{1}); err != nil {
  605. return err
  606. }
  607. finished := new(finishedMsg)
  608. finished.verifyData = hs.finishedHash.serverSum(hs.masterSecret)
  609. hs.finishedHash.Write(finished.marshal())
  610. if _, err := c.writeRecord(recordTypeHandshake, finished.marshal()); err != nil {
  611. return err
  612. }
  613. c.cipherSuite = hs.suite.id
  614. copy(out, finished.verifyData)
  615. return nil
  616. }
  617. // processCertsFromClient takes a chain of client certificates either from a
  618. // Certificates message or from a sessionState and verifies them. It returns
  619. // the public key of the leaf certificate.
  620. func (hs *serverHandshakeState) processCertsFromClient(certificates [][]byte) (crypto.PublicKey, error) {
  621. c := hs.c
  622. hs.certsFromClient = certificates
  623. certs := make([]*x509.Certificate, len(certificates))
  624. var err error
  625. for i, asn1Data := range certificates {
  626. if certs[i], err = x509.ParseCertificate(asn1Data); err != nil {
  627. c.sendAlert(alertBadCertificate)
  628. return nil, errors.New("tls: failed to parse client certificate: " + err.Error())
  629. }
  630. }
  631. if c.config.ClientAuth >= VerifyClientCertIfGiven && len(certs) > 0 {
  632. opts := x509.VerifyOptions{
  633. Roots: c.config.ClientCAs,
  634. CurrentTime: c.config.time(),
  635. Intermediates: x509.NewCertPool(),
  636. KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
  637. }
  638. for _, cert := range certs[1:] {
  639. opts.Intermediates.AddCert(cert)
  640. }
  641. chains, err := certs[0].Verify(opts)
  642. if err != nil {
  643. c.sendAlert(alertBadCertificate)
  644. return nil, errors.New("tls: failed to verify client's certificate: " + err.Error())
  645. }
  646. c.verifiedChains = chains
  647. }
  648. if c.config.VerifyPeerCertificate != nil {
  649. if err := c.config.VerifyPeerCertificate(certificates, c.verifiedChains); err != nil {
  650. c.sendAlert(alertBadCertificate)
  651. return nil, err
  652. }
  653. }
  654. if len(certs) == 0 {
  655. return nil, nil
  656. }
  657. var pub crypto.PublicKey
  658. switch key := certs[0].PublicKey.(type) {
  659. case *ecdsa.PublicKey, *rsa.PublicKey:
  660. pub = key
  661. default:
  662. c.sendAlert(alertUnsupportedCertificate)
  663. return nil, fmt.Errorf("tls: client's certificate contains an unsupported public key of type %T", certs[0].PublicKey)
  664. }
  665. c.peerCertificates = certs
  666. return pub, nil
  667. }
  668. // setCipherSuite sets a cipherSuite with the given id as the serverHandshakeState
  669. // suite if that cipher suite is acceptable to use.
  670. // It returns a bool indicating if the suite was set.
  671. func (hs *serverHandshakeState) setCipherSuite(id uint16, supportedCipherSuites []uint16, version uint16) bool {
  672. for _, supported := range supportedCipherSuites {
  673. if id == supported {
  674. var candidate *cipherSuite
  675. for _, s := range cipherSuites {
  676. if s.id == id {
  677. candidate = s
  678. break
  679. }
  680. }
  681. if candidate == nil {
  682. continue
  683. }
  684. // Don't select a ciphersuite which we can't
  685. // support for this client.
  686. if candidate.flags&suiteECDHE != 0 {
  687. if !hs.ellipticOk {
  688. continue
  689. }
  690. if candidate.flags&suiteECDSA != 0 {
  691. if !hs.ecdsaOk {
  692. continue
  693. }
  694. } else if !hs.rsaSignOk {
  695. continue
  696. }
  697. } else if !hs.rsaDecryptOk {
  698. continue
  699. }
  700. if version < VersionTLS12 && candidate.flags&suiteTLS12 != 0 {
  701. continue
  702. }
  703. hs.suite = candidate
  704. return true
  705. }
  706. }
  707. return false
  708. }
  709. // suppVersArray is the backing array of ClientHelloInfo.SupportedVersions
  710. var suppVersArray = [...]uint16{VersionTLS12, VersionTLS11, VersionTLS10, VersionSSL30}
  711. func (hs *serverHandshakeState) clientHelloInfo() *ClientHelloInfo {
  712. if hs.cachedClientHelloInfo != nil {
  713. return hs.cachedClientHelloInfo
  714. }
  715. var supportedVersions []uint16
  716. if hs.clientHello.vers > VersionTLS12 {
  717. supportedVersions = suppVersArray[:]
  718. } else if hs.clientHello.vers >= VersionSSL30 {
  719. supportedVersions = suppVersArray[VersionTLS12-hs.clientHello.vers:]
  720. }
  721. signatureSchemes := make([]SignatureScheme, 0, len(hs.clientHello.signatureAndHashes))
  722. for _, sah := range hs.clientHello.signatureAndHashes {
  723. signatureSchemes = append(signatureSchemes, SignatureScheme(sah.hash)<<8+SignatureScheme(sah.signature))
  724. }
  725. hs.cachedClientHelloInfo = &ClientHelloInfo{
  726. CipherSuites: hs.clientHello.cipherSuites,
  727. ServerName: hs.clientHello.serverName,
  728. SupportedCurves: hs.clientHello.supportedCurves,
  729. SupportedPoints: hs.clientHello.supportedPoints,
  730. SignatureSchemes: signatureSchemes,
  731. SupportedProtos: hs.clientHello.alpnProtocols,
  732. SupportedVersions: supportedVersions,
  733. Conn: hs.c.conn,
  734. }
  735. return hs.cachedClientHelloInfo
  736. }