Alternative TLS implementation in Go
Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

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>
před 9 roky
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>
před 9 roky
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>
před 9 roky
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>
před 9 roky
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>
před 9 roky
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>
před 9 roky
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>
před 9 roky
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>
před 9 roky
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>
před 9 roky
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>
před 9 roky
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>
před 9 roky
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>
před 9 roky
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>
před 9 roky
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>
před 9 roky
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>
před 9 roky
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838
  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(func() { c.config.serverInit(nil) })
  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.serverInitOnce.Do(func() { newConfig.serverInit(c.config) })
  123. c.config = newConfig
  124. }
  125. }
  126. c.vers, ok = c.config.mutualVersion(hs.clientHello.vers)
  127. if !ok {
  128. c.sendAlert(alertProtocolVersion)
  129. return false, fmt.Errorf("tls: client offered an unsupported, maximum protocol version of %x", hs.clientHello.vers)
  130. }
  131. c.haveVers = true
  132. hs.hello = new(serverHelloMsg)
  133. supportedCurve := false
  134. preferredCurves := c.config.curvePreferences()
  135. Curves:
  136. for _, curve := range hs.clientHello.supportedCurves {
  137. for _, supported := range preferredCurves {
  138. if supported == curve {
  139. supportedCurve = true
  140. break Curves
  141. }
  142. }
  143. }
  144. supportedPointFormat := false
  145. for _, pointFormat := range hs.clientHello.supportedPoints {
  146. if pointFormat == pointFormatUncompressed {
  147. supportedPointFormat = true
  148. break
  149. }
  150. }
  151. hs.ellipticOk = supportedCurve && supportedPointFormat
  152. foundCompression := false
  153. // We only support null compression, so check that the client offered it.
  154. for _, compression := range hs.clientHello.compressionMethods {
  155. if compression == compressionNone {
  156. foundCompression = true
  157. break
  158. }
  159. }
  160. if !foundCompression {
  161. c.sendAlert(alertHandshakeFailure)
  162. return false, errors.New("tls: client does not support uncompressed connections")
  163. }
  164. hs.hello.vers = c.vers
  165. hs.hello.random = make([]byte, 32)
  166. _, err = io.ReadFull(c.config.rand(), hs.hello.random)
  167. if err != nil {
  168. c.sendAlert(alertInternalError)
  169. return false, err
  170. }
  171. if len(hs.clientHello.secureRenegotiation) != 0 {
  172. c.sendAlert(alertHandshakeFailure)
  173. return false, errors.New("tls: initial handshake had non-empty renegotiation extension")
  174. }
  175. hs.hello.secureRenegotiationSupported = hs.clientHello.secureRenegotiationSupported
  176. hs.hello.compressionMethod = compressionNone
  177. if len(hs.clientHello.serverName) > 0 {
  178. c.serverName = hs.clientHello.serverName
  179. }
  180. if len(hs.clientHello.alpnProtocols) > 0 {
  181. if selectedProto, fallback := mutualProtocol(hs.clientHello.alpnProtocols, c.config.NextProtos); !fallback {
  182. hs.hello.alpnProtocol = selectedProto
  183. c.clientProtocol = selectedProto
  184. }
  185. } else {
  186. // Although sending an empty NPN extension is reasonable, Firefox has
  187. // had a bug around this. Best to send nothing at all if
  188. // c.config.NextProtos is empty. See
  189. // https://golang.org/issue/5445.
  190. if hs.clientHello.nextProtoNeg && len(c.config.NextProtos) > 0 {
  191. hs.hello.nextProtoNeg = true
  192. hs.hello.nextProtos = c.config.NextProtos
  193. }
  194. }
  195. hs.cert, err = c.config.getCertificate(hs.clientHelloInfo())
  196. if err != nil {
  197. c.sendAlert(alertInternalError)
  198. return false, err
  199. }
  200. if hs.clientHello.scts {
  201. hs.hello.scts = hs.cert.SignedCertificateTimestamps
  202. }
  203. if priv, ok := hs.cert.PrivateKey.(crypto.Signer); ok {
  204. switch priv.Public().(type) {
  205. case *ecdsa.PublicKey:
  206. hs.ecdsaOk = true
  207. case *rsa.PublicKey:
  208. hs.rsaSignOk = true
  209. default:
  210. c.sendAlert(alertInternalError)
  211. return false, fmt.Errorf("tls: unsupported signing key type (%T)", priv.Public())
  212. }
  213. }
  214. if priv, ok := hs.cert.PrivateKey.(crypto.Decrypter); ok {
  215. switch priv.Public().(type) {
  216. case *rsa.PublicKey:
  217. hs.rsaDecryptOk = true
  218. default:
  219. c.sendAlert(alertInternalError)
  220. return false, fmt.Errorf("tls: unsupported decryption key type (%T)", priv.Public())
  221. }
  222. }
  223. if hs.checkForResumption() {
  224. return true, nil
  225. }
  226. var preferenceList, supportedList []uint16
  227. if c.config.PreferServerCipherSuites {
  228. preferenceList = c.config.cipherSuites()
  229. supportedList = hs.clientHello.cipherSuites
  230. } else {
  231. preferenceList = hs.clientHello.cipherSuites
  232. supportedList = c.config.cipherSuites()
  233. }
  234. for _, id := range preferenceList {
  235. if hs.setCipherSuite(id, supportedList, c.vers) {
  236. break
  237. }
  238. }
  239. if hs.suite == nil {
  240. c.sendAlert(alertHandshakeFailure)
  241. return false, errors.New("tls: no cipher suite supported by both client and server")
  242. }
  243. // See https://tools.ietf.org/html/rfc7507.
  244. for _, id := range hs.clientHello.cipherSuites {
  245. if id == TLS_FALLBACK_SCSV {
  246. // The client is doing a fallback connection.
  247. if hs.clientHello.vers < c.config.maxVersion() {
  248. c.sendAlert(alertInappropriateFallback)
  249. return false, errors.New("tls: client using inappropriate protocol fallback")
  250. }
  251. break
  252. }
  253. }
  254. return false, nil
  255. }
  256. // checkForResumption reports whether we should perform resumption on this connection.
  257. func (hs *serverHandshakeState) checkForResumption() bool {
  258. c := hs.c
  259. if c.config.SessionTicketsDisabled {
  260. return false
  261. }
  262. var ok bool
  263. var sessionTicket = append([]uint8{}, hs.clientHello.sessionTicket...)
  264. if hs.sessionState, ok = c.decryptTicket(sessionTicket); !ok {
  265. return false
  266. }
  267. // Never resume a session for a different TLS version.
  268. if c.vers != hs.sessionState.vers {
  269. return false
  270. }
  271. cipherSuiteOk := false
  272. // Check that the client is still offering the ciphersuite in the session.
  273. for _, id := range hs.clientHello.cipherSuites {
  274. if id == hs.sessionState.cipherSuite {
  275. cipherSuiteOk = true
  276. break
  277. }
  278. }
  279. if !cipherSuiteOk {
  280. return false
  281. }
  282. // Check that we also support the ciphersuite from the session.
  283. if !hs.setCipherSuite(hs.sessionState.cipherSuite, c.config.cipherSuites(), hs.sessionState.vers) {
  284. return false
  285. }
  286. sessionHasClientCerts := len(hs.sessionState.certificates) != 0
  287. needClientCerts := c.config.ClientAuth == RequireAnyClientCert || c.config.ClientAuth == RequireAndVerifyClientCert
  288. if needClientCerts && !sessionHasClientCerts {
  289. return false
  290. }
  291. if sessionHasClientCerts && c.config.ClientAuth == NoClientCert {
  292. return false
  293. }
  294. return true
  295. }
  296. func (hs *serverHandshakeState) doResumeHandshake() error {
  297. c := hs.c
  298. hs.hello.cipherSuite = hs.suite.id
  299. // We echo the client's session ID in the ServerHello to let it know
  300. // that we're doing a resumption.
  301. hs.hello.sessionId = hs.clientHello.sessionId
  302. hs.hello.ticketSupported = hs.sessionState.usedOldKey
  303. hs.finishedHash = newFinishedHash(c.vers, hs.suite)
  304. hs.finishedHash.discardHandshakeBuffer()
  305. hs.finishedHash.Write(hs.clientHello.marshal())
  306. hs.finishedHash.Write(hs.hello.marshal())
  307. if _, err := c.writeRecord(recordTypeHandshake, hs.hello.marshal()); err != nil {
  308. return err
  309. }
  310. if len(hs.sessionState.certificates) > 0 {
  311. if _, err := hs.processCertsFromClient(hs.sessionState.certificates); err != nil {
  312. return err
  313. }
  314. }
  315. hs.masterSecret = hs.sessionState.masterSecret
  316. return nil
  317. }
  318. func (hs *serverHandshakeState) doFullHandshake() error {
  319. c := hs.c
  320. if hs.clientHello.ocspStapling && len(hs.cert.OCSPStaple) > 0 {
  321. hs.hello.ocspStapling = true
  322. }
  323. hs.hello.ticketSupported = hs.clientHello.ticketSupported && !c.config.SessionTicketsDisabled
  324. hs.hello.cipherSuite = hs.suite.id
  325. hs.finishedHash = newFinishedHash(hs.c.vers, hs.suite)
  326. if c.config.ClientAuth == NoClientCert {
  327. // No need to keep a full record of the handshake if client
  328. // certificates won't be used.
  329. hs.finishedHash.discardHandshakeBuffer()
  330. }
  331. hs.finishedHash.Write(hs.clientHello.marshal())
  332. hs.finishedHash.Write(hs.hello.marshal())
  333. if _, err := c.writeRecord(recordTypeHandshake, hs.hello.marshal()); err != nil {
  334. return err
  335. }
  336. certMsg := new(certificateMsg)
  337. certMsg.certificates = hs.cert.Certificate
  338. hs.finishedHash.Write(certMsg.marshal())
  339. if _, err := c.writeRecord(recordTypeHandshake, certMsg.marshal()); err != nil {
  340. return err
  341. }
  342. if hs.hello.ocspStapling {
  343. certStatus := new(certificateStatusMsg)
  344. certStatus.statusType = statusTypeOCSP
  345. certStatus.response = hs.cert.OCSPStaple
  346. hs.finishedHash.Write(certStatus.marshal())
  347. if _, err := c.writeRecord(recordTypeHandshake, certStatus.marshal()); err != nil {
  348. return err
  349. }
  350. }
  351. keyAgreement := hs.suite.ka(c.vers)
  352. skx, err := keyAgreement.generateServerKeyExchange(c.config, hs.cert, hs.clientHello, hs.hello)
  353. if err != nil {
  354. c.sendAlert(alertHandshakeFailure)
  355. return err
  356. }
  357. if skx != nil {
  358. hs.finishedHash.Write(skx.marshal())
  359. if _, err := c.writeRecord(recordTypeHandshake, skx.marshal()); err != nil {
  360. return err
  361. }
  362. }
  363. if c.config.ClientAuth >= RequestClientCert {
  364. // Request a client certificate
  365. certReq := new(certificateRequestMsg)
  366. certReq.certificateTypes = []byte{
  367. byte(certTypeRSASign),
  368. byte(certTypeECDSASign),
  369. }
  370. if c.vers >= VersionTLS12 {
  371. certReq.hasSignatureAndHash = true
  372. certReq.signatureAndHashes = supportedSignatureAlgorithms
  373. }
  374. // An empty list of certificateAuthorities signals to
  375. // the client that it may send any certificate in response
  376. // to our request. When we know the CAs we trust, then
  377. // we can send them down, so that the client can choose
  378. // an appropriate certificate to give to us.
  379. if c.config.ClientCAs != nil {
  380. certReq.certificateAuthorities = c.config.ClientCAs.Subjects()
  381. }
  382. hs.finishedHash.Write(certReq.marshal())
  383. if _, err := c.writeRecord(recordTypeHandshake, certReq.marshal()); err != nil {
  384. return err
  385. }
  386. }
  387. helloDone := new(serverHelloDoneMsg)
  388. hs.finishedHash.Write(helloDone.marshal())
  389. if _, err := c.writeRecord(recordTypeHandshake, helloDone.marshal()); err != nil {
  390. return err
  391. }
  392. if _, err := c.flush(); err != nil {
  393. return err
  394. }
  395. var pub crypto.PublicKey // public key for client auth, if any
  396. msg, err := c.readHandshake()
  397. if err != nil {
  398. return err
  399. }
  400. var ok bool
  401. // If we requested a client certificate, then the client must send a
  402. // certificate message, even if it's empty.
  403. if c.config.ClientAuth >= RequestClientCert {
  404. if certMsg, ok = msg.(*certificateMsg); !ok {
  405. c.sendAlert(alertUnexpectedMessage)
  406. return unexpectedMessageError(certMsg, msg)
  407. }
  408. hs.finishedHash.Write(certMsg.marshal())
  409. if len(certMsg.certificates) == 0 {
  410. // The client didn't actually send a certificate
  411. switch c.config.ClientAuth {
  412. case RequireAnyClientCert, RequireAndVerifyClientCert:
  413. c.sendAlert(alertBadCertificate)
  414. return errors.New("tls: client didn't provide a certificate")
  415. }
  416. }
  417. pub, err = hs.processCertsFromClient(certMsg.certificates)
  418. if err != nil {
  419. return err
  420. }
  421. msg, err = c.readHandshake()
  422. if err != nil {
  423. return err
  424. }
  425. }
  426. // Get client key exchange
  427. ckx, ok := msg.(*clientKeyExchangeMsg)
  428. if !ok {
  429. c.sendAlert(alertUnexpectedMessage)
  430. return unexpectedMessageError(ckx, msg)
  431. }
  432. hs.finishedHash.Write(ckx.marshal())
  433. preMasterSecret, err := keyAgreement.processClientKeyExchange(c.config, hs.cert, ckx, c.vers)
  434. if err != nil {
  435. c.sendAlert(alertHandshakeFailure)
  436. return err
  437. }
  438. hs.masterSecret = masterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.clientHello.random, hs.hello.random)
  439. if err := c.config.writeKeyLog(hs.clientHello.random, hs.masterSecret); err != nil {
  440. c.sendAlert(alertInternalError)
  441. return err
  442. }
  443. // If we received a client cert in response to our certificate request message,
  444. // the client will send us a certificateVerifyMsg immediately after the
  445. // clientKeyExchangeMsg. This message is a digest of all preceding
  446. // handshake-layer messages that is signed using the private key corresponding
  447. // to the client's certificate. This allows us to verify that the client is in
  448. // possession of the private key of the certificate.
  449. if len(c.peerCertificates) > 0 {
  450. msg, err = c.readHandshake()
  451. if err != nil {
  452. return err
  453. }
  454. certVerify, ok := msg.(*certificateVerifyMsg)
  455. if !ok {
  456. c.sendAlert(alertUnexpectedMessage)
  457. return unexpectedMessageError(certVerify, msg)
  458. }
  459. // Determine the signature type.
  460. var signatureAndHash signatureAndHash
  461. if certVerify.hasSignatureAndHash {
  462. signatureAndHash = certVerify.signatureAndHash
  463. if !isSupportedSignatureAndHash(signatureAndHash, supportedSignatureAlgorithms) {
  464. return errors.New("tls: unsupported hash function for client certificate")
  465. }
  466. } else {
  467. // Before TLS 1.2 the signature algorithm was implicit
  468. // from the key type, and only one hash per signature
  469. // algorithm was possible. Leave the hash as zero.
  470. switch pub.(type) {
  471. case *ecdsa.PublicKey:
  472. signatureAndHash.signature = signatureECDSA
  473. case *rsa.PublicKey:
  474. signatureAndHash.signature = signatureRSA
  475. }
  476. }
  477. switch key := pub.(type) {
  478. case *ecdsa.PublicKey:
  479. if signatureAndHash.signature != signatureECDSA {
  480. err = errors.New("tls: bad signature type for client's ECDSA certificate")
  481. break
  482. }
  483. ecdsaSig := new(ecdsaSignature)
  484. if _, err = asn1.Unmarshal(certVerify.signature, ecdsaSig); err != nil {
  485. break
  486. }
  487. if ecdsaSig.R.Sign() <= 0 || ecdsaSig.S.Sign() <= 0 {
  488. err = errors.New("tls: ECDSA signature contained zero or negative values")
  489. break
  490. }
  491. var digest []byte
  492. if digest, _, err = hs.finishedHash.hashForClientCertificate(signatureAndHash, hs.masterSecret); err != nil {
  493. break
  494. }
  495. if !ecdsa.Verify(key, digest, ecdsaSig.R, ecdsaSig.S) {
  496. err = errors.New("tls: ECDSA verification failure")
  497. }
  498. case *rsa.PublicKey:
  499. if signatureAndHash.signature != signatureRSA {
  500. err = errors.New("tls: bad signature type for client's RSA certificate")
  501. break
  502. }
  503. var digest []byte
  504. var hashFunc crypto.Hash
  505. if digest, hashFunc, err = hs.finishedHash.hashForClientCertificate(signatureAndHash, hs.masterSecret); err != nil {
  506. break
  507. }
  508. err = rsa.VerifyPKCS1v15(key, hashFunc, digest, certVerify.signature)
  509. }
  510. if err != nil {
  511. c.sendAlert(alertBadCertificate)
  512. return errors.New("tls: could not validate signature of connection nonces: " + err.Error())
  513. }
  514. hs.finishedHash.Write(certVerify.marshal())
  515. }
  516. hs.finishedHash.discardHandshakeBuffer()
  517. return nil
  518. }
  519. func (hs *serverHandshakeState) establishKeys() error {
  520. c := hs.c
  521. clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV :=
  522. keysFromMasterSecret(c.vers, hs.suite, hs.masterSecret, hs.clientHello.random, hs.hello.random, hs.suite.macLen, hs.suite.keyLen, hs.suite.ivLen)
  523. var clientCipher, serverCipher interface{}
  524. var clientHash, serverHash macFunction
  525. if hs.suite.aead == nil {
  526. clientCipher = hs.suite.cipher(clientKey, clientIV, true /* for reading */)
  527. clientHash = hs.suite.mac(c.vers, clientMAC)
  528. serverCipher = hs.suite.cipher(serverKey, serverIV, false /* not for reading */)
  529. serverHash = hs.suite.mac(c.vers, serverMAC)
  530. } else {
  531. clientCipher = hs.suite.aead(clientKey, clientIV)
  532. serverCipher = hs.suite.aead(serverKey, serverIV)
  533. }
  534. c.in.prepareCipherSpec(c.vers, clientCipher, clientHash)
  535. c.out.prepareCipherSpec(c.vers, serverCipher, serverHash)
  536. return nil
  537. }
  538. func (hs *serverHandshakeState) readFinished(out []byte) error {
  539. c := hs.c
  540. c.readRecord(recordTypeChangeCipherSpec)
  541. if c.in.err != nil {
  542. return c.in.err
  543. }
  544. if hs.hello.nextProtoNeg {
  545. msg, err := c.readHandshake()
  546. if err != nil {
  547. return err
  548. }
  549. nextProto, ok := msg.(*nextProtoMsg)
  550. if !ok {
  551. c.sendAlert(alertUnexpectedMessage)
  552. return unexpectedMessageError(nextProto, msg)
  553. }
  554. hs.finishedHash.Write(nextProto.marshal())
  555. c.clientProtocol = nextProto.proto
  556. }
  557. msg, err := c.readHandshake()
  558. if err != nil {
  559. return err
  560. }
  561. clientFinished, ok := msg.(*finishedMsg)
  562. if !ok {
  563. c.sendAlert(alertUnexpectedMessage)
  564. return unexpectedMessageError(clientFinished, msg)
  565. }
  566. verify := hs.finishedHash.clientSum(hs.masterSecret)
  567. if len(verify) != len(clientFinished.verifyData) ||
  568. subtle.ConstantTimeCompare(verify, clientFinished.verifyData) != 1 {
  569. c.sendAlert(alertHandshakeFailure)
  570. return errors.New("tls: client's Finished message is incorrect")
  571. }
  572. hs.finishedHash.Write(clientFinished.marshal())
  573. copy(out, verify)
  574. return nil
  575. }
  576. func (hs *serverHandshakeState) sendSessionTicket() error {
  577. if !hs.hello.ticketSupported {
  578. return nil
  579. }
  580. c := hs.c
  581. m := new(newSessionTicketMsg)
  582. var err error
  583. state := sessionState{
  584. vers: c.vers,
  585. cipherSuite: hs.suite.id,
  586. masterSecret: hs.masterSecret,
  587. certificates: hs.certsFromClient,
  588. }
  589. m.ticket, err = c.encryptTicket(&state)
  590. if err != nil {
  591. return err
  592. }
  593. hs.finishedHash.Write(m.marshal())
  594. if _, err := c.writeRecord(recordTypeHandshake, m.marshal()); err != nil {
  595. return err
  596. }
  597. return nil
  598. }
  599. func (hs *serverHandshakeState) sendFinished(out []byte) error {
  600. c := hs.c
  601. if _, err := c.writeRecord(recordTypeChangeCipherSpec, []byte{1}); err != nil {
  602. return err
  603. }
  604. finished := new(finishedMsg)
  605. finished.verifyData = hs.finishedHash.serverSum(hs.masterSecret)
  606. hs.finishedHash.Write(finished.marshal())
  607. if _, err := c.writeRecord(recordTypeHandshake, finished.marshal()); err != nil {
  608. return err
  609. }
  610. c.cipherSuite = hs.suite.id
  611. copy(out, finished.verifyData)
  612. return nil
  613. }
  614. // processCertsFromClient takes a chain of client certificates either from a
  615. // Certificates message or from a sessionState and verifies them. It returns
  616. // the public key of the leaf certificate.
  617. func (hs *serverHandshakeState) processCertsFromClient(certificates [][]byte) (crypto.PublicKey, error) {
  618. c := hs.c
  619. hs.certsFromClient = certificates
  620. certs := make([]*x509.Certificate, len(certificates))
  621. var err error
  622. for i, asn1Data := range certificates {
  623. if certs[i], err = x509.ParseCertificate(asn1Data); err != nil {
  624. c.sendAlert(alertBadCertificate)
  625. return nil, errors.New("tls: failed to parse client certificate: " + err.Error())
  626. }
  627. }
  628. if c.config.ClientAuth >= VerifyClientCertIfGiven && len(certs) > 0 {
  629. opts := x509.VerifyOptions{
  630. Roots: c.config.ClientCAs,
  631. CurrentTime: c.config.time(),
  632. Intermediates: x509.NewCertPool(),
  633. KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
  634. }
  635. for _, cert := range certs[1:] {
  636. opts.Intermediates.AddCert(cert)
  637. }
  638. chains, err := certs[0].Verify(opts)
  639. if err != nil {
  640. c.sendAlert(alertBadCertificate)
  641. return nil, errors.New("tls: failed to verify client's certificate: " + err.Error())
  642. }
  643. c.verifiedChains = chains
  644. }
  645. if c.config.VerifyPeerCertificate != nil {
  646. if err := c.config.VerifyPeerCertificate(certificates, c.verifiedChains); err != nil {
  647. c.sendAlert(alertBadCertificate)
  648. return nil, err
  649. }
  650. }
  651. if len(certs) == 0 {
  652. return nil, nil
  653. }
  654. var pub crypto.PublicKey
  655. switch key := certs[0].PublicKey.(type) {
  656. case *ecdsa.PublicKey, *rsa.PublicKey:
  657. pub = key
  658. default:
  659. c.sendAlert(alertUnsupportedCertificate)
  660. return nil, fmt.Errorf("tls: client's certificate contains an unsupported public key of type %T", certs[0].PublicKey)
  661. }
  662. c.peerCertificates = certs
  663. return pub, nil
  664. }
  665. // setCipherSuite sets a cipherSuite with the given id as the serverHandshakeState
  666. // suite if that cipher suite is acceptable to use.
  667. // It returns a bool indicating if the suite was set.
  668. func (hs *serverHandshakeState) setCipherSuite(id uint16, supportedCipherSuites []uint16, version uint16) bool {
  669. for _, supported := range supportedCipherSuites {
  670. if id == supported {
  671. var candidate *cipherSuite
  672. for _, s := range cipherSuites {
  673. if s.id == id {
  674. candidate = s
  675. break
  676. }
  677. }
  678. if candidate == nil {
  679. continue
  680. }
  681. // Don't select a ciphersuite which we can't
  682. // support for this client.
  683. if candidate.flags&suiteECDHE != 0 {
  684. if !hs.ellipticOk {
  685. continue
  686. }
  687. if candidate.flags&suiteECDSA != 0 {
  688. if !hs.ecdsaOk {
  689. continue
  690. }
  691. } else if !hs.rsaSignOk {
  692. continue
  693. }
  694. } else if !hs.rsaDecryptOk {
  695. continue
  696. }
  697. if version < VersionTLS12 && candidate.flags&suiteTLS12 != 0 {
  698. continue
  699. }
  700. hs.suite = candidate
  701. return true
  702. }
  703. }
  704. return false
  705. }
  706. // suppVersArray is the backing array of ClientHelloInfo.SupportedVersions
  707. var suppVersArray = [...]uint16{VersionTLS12, VersionTLS11, VersionTLS10, VersionSSL30}
  708. func (hs *serverHandshakeState) clientHelloInfo() *ClientHelloInfo {
  709. if hs.cachedClientHelloInfo != nil {
  710. return hs.cachedClientHelloInfo
  711. }
  712. var supportedVersions []uint16
  713. if hs.clientHello.vers > VersionTLS12 {
  714. supportedVersions = suppVersArray[:]
  715. } else if hs.clientHello.vers >= VersionSSL30 {
  716. supportedVersions = suppVersArray[VersionTLS12-hs.clientHello.vers:]
  717. }
  718. signatureSchemes := make([]SignatureScheme, 0, len(hs.clientHello.signatureAndHashes))
  719. for _, sah := range hs.clientHello.signatureAndHashes {
  720. signatureSchemes = append(signatureSchemes, SignatureScheme(sah.hash)<<8+SignatureScheme(sah.signature))
  721. }
  722. hs.cachedClientHelloInfo = &ClientHelloInfo{
  723. CipherSuites: hs.clientHello.cipherSuites,
  724. ServerName: hs.clientHello.serverName,
  725. SupportedCurves: hs.clientHello.supportedCurves,
  726. SupportedPoints: hs.clientHello.supportedPoints,
  727. SignatureSchemes: signatureSchemes,
  728. SupportedProtos: hs.clientHello.alpnProtocols,
  729. SupportedVersions: supportedVersions,
  730. Conn: hs.c.conn,
  731. }
  732. return hs.cachedClientHelloInfo
  733. }