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.

key_agreement.go 14 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 年之前
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 年之前
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 年之前
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 年之前
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 年之前
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 年之前
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 年之前
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 年之前
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 年之前
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 年之前
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 年之前
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 年之前
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 年之前
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 年之前
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 年之前
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473
  1. // Copyright 2010 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/elliptic"
  9. "crypto/md5"
  10. "crypto/rsa"
  11. "crypto/sha1"
  12. "crypto/x509"
  13. "encoding/asn1"
  14. "errors"
  15. "io"
  16. "math/big"
  17. "golang_org/x/crypto/curve25519"
  18. )
  19. var errClientKeyExchange = errors.New("tls: invalid ClientKeyExchange message")
  20. var errServerKeyExchange = errors.New("tls: invalid ServerKeyExchange message")
  21. // rsaKeyAgreement implements the standard TLS key agreement where the client
  22. // encrypts the pre-master secret to the server's public key.
  23. type rsaKeyAgreement struct{}
  24. func (ka rsaKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
  25. return nil, nil
  26. }
  27. func (ka rsaKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) {
  28. if len(ckx.ciphertext) < 2 {
  29. return nil, errClientKeyExchange
  30. }
  31. ciphertext := ckx.ciphertext
  32. if version != VersionSSL30 {
  33. ciphertextLen := int(ckx.ciphertext[0])<<8 | int(ckx.ciphertext[1])
  34. if ciphertextLen != len(ckx.ciphertext)-2 {
  35. return nil, errClientKeyExchange
  36. }
  37. ciphertext = ckx.ciphertext[2:]
  38. }
  39. priv, ok := cert.PrivateKey.(crypto.Decrypter)
  40. if !ok {
  41. return nil, errors.New("tls: certificate private key does not implement crypto.Decrypter")
  42. }
  43. // Perform constant time RSA PKCS#1 v1.5 decryption
  44. preMasterSecret, err := priv.Decrypt(config.rand(), ciphertext, &rsa.PKCS1v15DecryptOptions{SessionKeyLen: 48})
  45. if err != nil {
  46. return nil, err
  47. }
  48. // We don't check the version number in the premaster secret. For one,
  49. // by checking it, we would leak information about the validity of the
  50. // encrypted pre-master secret. Secondly, it provides only a small
  51. // benefit against a downgrade attack and some implementations send the
  52. // wrong version anyway. See the discussion at the end of section
  53. // 7.4.7.1 of RFC 4346.
  54. return preMasterSecret, nil
  55. }
  56. func (ka rsaKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error {
  57. return errors.New("tls: unexpected ServerKeyExchange")
  58. }
  59. func (ka rsaKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) {
  60. preMasterSecret := make([]byte, 48)
  61. preMasterSecret[0] = byte(clientHello.vers >> 8)
  62. preMasterSecret[1] = byte(clientHello.vers)
  63. _, err := io.ReadFull(config.rand(), preMasterSecret[2:])
  64. if err != nil {
  65. return nil, nil, err
  66. }
  67. encrypted, err := rsa.EncryptPKCS1v15(config.rand(), cert.PublicKey.(*rsa.PublicKey), preMasterSecret)
  68. if err != nil {
  69. return nil, nil, err
  70. }
  71. ckx := new(clientKeyExchangeMsg)
  72. ckx.ciphertext = make([]byte, len(encrypted)+2)
  73. ckx.ciphertext[0] = byte(len(encrypted) >> 8)
  74. ckx.ciphertext[1] = byte(len(encrypted))
  75. copy(ckx.ciphertext[2:], encrypted)
  76. return preMasterSecret, ckx, nil
  77. }
  78. // sha1Hash calculates a SHA1 hash over the given byte slices.
  79. func sha1Hash(slices [][]byte) []byte {
  80. hsha1 := sha1.New()
  81. for _, slice := range slices {
  82. hsha1.Write(slice)
  83. }
  84. return hsha1.Sum(nil)
  85. }
  86. // md5SHA1Hash implements TLS 1.0's hybrid hash function which consists of the
  87. // concatenation of an MD5 and SHA1 hash.
  88. func md5SHA1Hash(slices [][]byte) []byte {
  89. md5sha1 := make([]byte, md5.Size+sha1.Size)
  90. hmd5 := md5.New()
  91. for _, slice := range slices {
  92. hmd5.Write(slice)
  93. }
  94. copy(md5sha1, hmd5.Sum(nil))
  95. copy(md5sha1[md5.Size:], sha1Hash(slices))
  96. return md5sha1
  97. }
  98. // hashForServerKeyExchange hashes the given slices and returns their digest
  99. // and the identifier of the hash function used. The sigAndHash argument is
  100. // only used for >= TLS 1.2 and precisely identifies the hash function to use.
  101. func hashForServerKeyExchange(sigAndHash signatureAndHash, version uint16, slices ...[]byte) ([]byte, crypto.Hash, error) {
  102. if version >= VersionTLS12 {
  103. if !isSupportedSignatureAndHash(sigAndHash, supportedSignatureAlgorithms) {
  104. return nil, crypto.Hash(0), errors.New("tls: unsupported hash function used by peer")
  105. }
  106. hashFunc, err := lookupTLSHash(sigAndHash.hash)
  107. if err != nil {
  108. return nil, crypto.Hash(0), err
  109. }
  110. h := hashFunc.New()
  111. for _, slice := range slices {
  112. h.Write(slice)
  113. }
  114. digest := h.Sum(nil)
  115. return digest, hashFunc, nil
  116. }
  117. if sigAndHash.signature == signatureECDSA {
  118. return sha1Hash(slices), crypto.SHA1, nil
  119. }
  120. return md5SHA1Hash(slices), crypto.MD5SHA1, nil
  121. }
  122. // pickTLS12HashForSignature returns a TLS 1.2 hash identifier for signing a
  123. // ServerKeyExchange given the signature type being used and the client's
  124. // advertised list of supported signature and hash combinations.
  125. func pickTLS12HashForSignature(sigType uint8, clientList []signatureAndHash) (uint8, error) {
  126. if len(clientList) == 0 {
  127. // If the client didn't specify any signature_algorithms
  128. // extension then we can assume that it supports SHA1. See
  129. // http://tools.ietf.org/html/rfc5246#section-7.4.1.4.1
  130. return hashSHA1, nil
  131. }
  132. for _, sigAndHash := range clientList {
  133. if sigAndHash.signature != sigType {
  134. continue
  135. }
  136. if isSupportedSignatureAndHash(sigAndHash, supportedSignatureAlgorithms) {
  137. return sigAndHash.hash, nil
  138. }
  139. }
  140. return 0, errors.New("tls: client doesn't support any common hash functions")
  141. }
  142. func curveForCurveID(id CurveID) (elliptic.Curve, bool) {
  143. switch id {
  144. case CurveP256:
  145. return elliptic.P256(), true
  146. case CurveP384:
  147. return elliptic.P384(), true
  148. case CurveP521:
  149. return elliptic.P521(), true
  150. default:
  151. return nil, false
  152. }
  153. }
  154. // ecdheRSAKeyAgreement implements a TLS key agreement where the server
  155. // generates a ephemeral EC public/private key pair and signs it. The
  156. // pre-master secret is then calculated using ECDH. The signature may
  157. // either be ECDSA or RSA.
  158. type ecdheKeyAgreement struct {
  159. version uint16
  160. sigType uint8
  161. privateKey []byte
  162. curveid CurveID
  163. // publicKey is used to store the peer's public value when X25519 is
  164. // being used.
  165. publicKey []byte
  166. // x and y are used to store the peer's public value when one of the
  167. // NIST curves is being used.
  168. x, y *big.Int
  169. }
  170. func (ka *ecdheKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
  171. preferredCurves := config.curvePreferences()
  172. NextCandidate:
  173. for _, candidate := range preferredCurves {
  174. for _, c := range clientHello.supportedCurves {
  175. if candidate == c {
  176. ka.curveid = c
  177. break NextCandidate
  178. }
  179. }
  180. }
  181. if ka.curveid == 0 {
  182. return nil, errors.New("tls: no supported elliptic curves offered")
  183. }
  184. var ecdhePublic []byte
  185. if ka.curveid == X25519 {
  186. var scalar, public [32]byte
  187. if _, err := io.ReadFull(config.rand(), scalar[:]); err != nil {
  188. return nil, err
  189. }
  190. curve25519.ScalarBaseMult(&public, &scalar)
  191. ka.privateKey = scalar[:]
  192. ecdhePublic = public[:]
  193. } else {
  194. curve, ok := curveForCurveID(ka.curveid)
  195. if !ok {
  196. return nil, errors.New("tls: preferredCurves includes unsupported curve")
  197. }
  198. var x, y *big.Int
  199. var err error
  200. ka.privateKey, x, y, err = elliptic.GenerateKey(curve, config.rand())
  201. if err != nil {
  202. return nil, err
  203. }
  204. ecdhePublic = elliptic.Marshal(curve, x, y)
  205. }
  206. // http://tools.ietf.org/html/rfc4492#section-5.4
  207. serverECDHParams := make([]byte, 1+2+1+len(ecdhePublic))
  208. serverECDHParams[0] = 3 // named curve
  209. serverECDHParams[1] = byte(ka.curveid >> 8)
  210. serverECDHParams[2] = byte(ka.curveid)
  211. serverECDHParams[3] = byte(len(ecdhePublic))
  212. copy(serverECDHParams[4:], ecdhePublic)
  213. sigAndHash := signatureAndHash{signature: ka.sigType}
  214. if ka.version >= VersionTLS12 {
  215. var err error
  216. if sigAndHash.hash, err = pickTLS12HashForSignature(ka.sigType, clientHello.signatureAndHashes); err != nil {
  217. return nil, err
  218. }
  219. }
  220. digest, hashFunc, err := hashForServerKeyExchange(sigAndHash, ka.version, clientHello.random, hello.random, serverECDHParams)
  221. if err != nil {
  222. return nil, err
  223. }
  224. priv, ok := cert.PrivateKey.(crypto.Signer)
  225. if !ok {
  226. return nil, errors.New("tls: certificate private key does not implement crypto.Signer")
  227. }
  228. var sig []byte
  229. switch ka.sigType {
  230. case signatureECDSA:
  231. _, ok := priv.Public().(*ecdsa.PublicKey)
  232. if !ok {
  233. return nil, errors.New("tls: ECDHE ECDSA requires an ECDSA server key")
  234. }
  235. case signatureRSA:
  236. _, ok := priv.Public().(*rsa.PublicKey)
  237. if !ok {
  238. return nil, errors.New("tls: ECDHE RSA requires a RSA server key")
  239. }
  240. default:
  241. return nil, errors.New("tls: unknown ECDHE signature algorithm")
  242. }
  243. sig, err = priv.Sign(config.rand(), digest, hashFunc)
  244. if err != nil {
  245. return nil, errors.New("tls: failed to sign ECDHE parameters: " + err.Error())
  246. }
  247. skx := new(serverKeyExchangeMsg)
  248. sigAndHashLen := 0
  249. if ka.version >= VersionTLS12 {
  250. sigAndHashLen = 2
  251. }
  252. skx.key = make([]byte, len(serverECDHParams)+sigAndHashLen+2+len(sig))
  253. copy(skx.key, serverECDHParams)
  254. k := skx.key[len(serverECDHParams):]
  255. if ka.version >= VersionTLS12 {
  256. k[0] = sigAndHash.hash
  257. k[1] = sigAndHash.signature
  258. k = k[2:]
  259. }
  260. k[0] = byte(len(sig) >> 8)
  261. k[1] = byte(len(sig))
  262. copy(k[2:], sig)
  263. return skx, nil
  264. }
  265. func (ka *ecdheKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) {
  266. if len(ckx.ciphertext) == 0 || int(ckx.ciphertext[0]) != len(ckx.ciphertext)-1 {
  267. return nil, errClientKeyExchange
  268. }
  269. if ka.curveid == X25519 {
  270. if len(ckx.ciphertext) != 1+32 {
  271. return nil, errClientKeyExchange
  272. }
  273. var theirPublic, sharedKey, scalar [32]byte
  274. copy(theirPublic[:], ckx.ciphertext[1:])
  275. copy(scalar[:], ka.privateKey)
  276. curve25519.ScalarMult(&sharedKey, &scalar, &theirPublic)
  277. return sharedKey[:], nil
  278. }
  279. curve, ok := curveForCurveID(ka.curveid)
  280. if !ok {
  281. panic("internal error")
  282. }
  283. x, y := elliptic.Unmarshal(curve, ckx.ciphertext[1:])
  284. if x == nil {
  285. return nil, errClientKeyExchange
  286. }
  287. if !curve.IsOnCurve(x, y) {
  288. return nil, errClientKeyExchange
  289. }
  290. x, _ = curve.ScalarMult(x, y, ka.privateKey)
  291. preMasterSecret := make([]byte, (curve.Params().BitSize+7)>>3)
  292. xBytes := x.Bytes()
  293. copy(preMasterSecret[len(preMasterSecret)-len(xBytes):], xBytes)
  294. return preMasterSecret, nil
  295. }
  296. func (ka *ecdheKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error {
  297. if len(skx.key) < 4 {
  298. return errServerKeyExchange
  299. }
  300. if skx.key[0] != 3 { // named curve
  301. return errors.New("tls: server selected unsupported curve")
  302. }
  303. ka.curveid = CurveID(skx.key[1])<<8 | CurveID(skx.key[2])
  304. publicLen := int(skx.key[3])
  305. if publicLen+4 > len(skx.key) {
  306. return errServerKeyExchange
  307. }
  308. serverECDHParams := skx.key[:4+publicLen]
  309. publicKey := serverECDHParams[4:]
  310. sig := skx.key[4+publicLen:]
  311. if len(sig) < 2 {
  312. return errServerKeyExchange
  313. }
  314. if ka.curveid == X25519 {
  315. if len(publicKey) != 32 {
  316. return errors.New("tls: bad X25519 public value")
  317. }
  318. ka.publicKey = publicKey
  319. } else {
  320. curve, ok := curveForCurveID(ka.curveid)
  321. if !ok {
  322. return errors.New("tls: server selected unsupported curve")
  323. }
  324. ka.x, ka.y = elliptic.Unmarshal(curve, publicKey)
  325. if ka.x == nil {
  326. return errServerKeyExchange
  327. }
  328. if !curve.IsOnCurve(ka.x, ka.y) {
  329. return errServerKeyExchange
  330. }
  331. }
  332. sigAndHash := signatureAndHash{signature: ka.sigType}
  333. if ka.version >= VersionTLS12 {
  334. // handle SignatureAndHashAlgorithm
  335. sigAndHash = signatureAndHash{hash: sig[0], signature: sig[1]}
  336. if sigAndHash.signature != ka.sigType {
  337. return errServerKeyExchange
  338. }
  339. sig = sig[2:]
  340. if len(sig) < 2 {
  341. return errServerKeyExchange
  342. }
  343. }
  344. sigLen := int(sig[0])<<8 | int(sig[1])
  345. if sigLen+2 != len(sig) {
  346. return errServerKeyExchange
  347. }
  348. sig = sig[2:]
  349. digest, hashFunc, err := hashForServerKeyExchange(sigAndHash, ka.version, clientHello.random, serverHello.random, serverECDHParams)
  350. if err != nil {
  351. return err
  352. }
  353. switch ka.sigType {
  354. case signatureECDSA:
  355. pubKey, ok := cert.PublicKey.(*ecdsa.PublicKey)
  356. if !ok {
  357. return errors.New("tls: ECDHE ECDSA requires a ECDSA server public key")
  358. }
  359. ecdsaSig := new(ecdsaSignature)
  360. if _, err := asn1.Unmarshal(sig, ecdsaSig); err != nil {
  361. return err
  362. }
  363. if ecdsaSig.R.Sign() <= 0 || ecdsaSig.S.Sign() <= 0 {
  364. return errors.New("tls: ECDSA signature contained zero or negative values")
  365. }
  366. if !ecdsa.Verify(pubKey, digest, ecdsaSig.R, ecdsaSig.S) {
  367. return errors.New("tls: ECDSA verification failure")
  368. }
  369. case signatureRSA:
  370. pubKey, ok := cert.PublicKey.(*rsa.PublicKey)
  371. if !ok {
  372. return errors.New("tls: ECDHE RSA requires a RSA server public key")
  373. }
  374. if err := rsa.VerifyPKCS1v15(pubKey, hashFunc, digest, sig); err != nil {
  375. return err
  376. }
  377. default:
  378. return errors.New("tls: unknown ECDHE signature algorithm")
  379. }
  380. return nil
  381. }
  382. func (ka *ecdheKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) {
  383. if ka.curveid == 0 {
  384. return nil, nil, errors.New("tls: missing ServerKeyExchange message")
  385. }
  386. var serialized, preMasterSecret []byte
  387. if ka.curveid == X25519 {
  388. var ourPublic, theirPublic, sharedKey, scalar [32]byte
  389. if _, err := io.ReadFull(config.rand(), scalar[:]); err != nil {
  390. return nil, nil, err
  391. }
  392. copy(theirPublic[:], ka.publicKey)
  393. curve25519.ScalarBaseMult(&ourPublic, &scalar)
  394. curve25519.ScalarMult(&sharedKey, &scalar, &theirPublic)
  395. serialized = ourPublic[:]
  396. preMasterSecret = sharedKey[:]
  397. } else {
  398. curve, ok := curveForCurveID(ka.curveid)
  399. if !ok {
  400. panic("internal error")
  401. }
  402. priv, mx, my, err := elliptic.GenerateKey(curve, config.rand())
  403. if err != nil {
  404. return nil, nil, err
  405. }
  406. x, _ := curve.ScalarMult(ka.x, ka.y, priv)
  407. preMasterSecret = make([]byte, (curve.Params().BitSize+7)>>3)
  408. xBytes := x.Bytes()
  409. copy(preMasterSecret[len(preMasterSecret)-len(xBytes):], xBytes)
  410. serialized = elliptic.Marshal(curve, mx, my)
  411. }
  412. ckx := new(clientKeyExchangeMsg)
  413. ckx.ciphertext = make([]byte, 1+len(serialized))
  414. ckx.ciphertext[0] = byte(len(serialized))
  415. copy(ckx.ciphertext[1:], serialized)
  416. return preMasterSecret, ckx, nil
  417. }