Não pode escolher mais do que 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

ssl_ecdh.c 17 KiB

Implement draft-ietf-tls-curve25519-01 in C. The new curve is not enabled by default. As EC_GROUP/EC_POINT is a bit too complex for X25519, this introduces an SSL_ECDH_METHOD abstraction which wraps just the raw ECDH operation. It also tidies up some of the curve code which kept converting back and force between NIDs and curve IDs. Now everything transits as curve IDs except for API entry points (SSL_set1_curves) which take NIDs. Those convert immediately and act on curve IDs from then on. Note that, like the Go implementation, this slightly tweaks the order of operations. The client sees the server public key before sending its own. To keep the abstraction simple, SSL_ECDH_METHOD expects to generate a keypair before consuming the peer's public key. Instead, the client handshake stashes the serialized peer public value and defers parsing it until it comes time to send ClientKeyExchange. (This is analogous to what it was doing before where it stashed the parsed peer public value instead.) It still uses TLS 1.2 terminology everywhere, but this abstraction should also be compatible with TLS 1.3 which unifies (EC)DH-style key exchanges. (Accordingly, this abstraction intentionally does not handle parsing the ClientKeyExchange/ServerKeyExchange framing or attempt to handle asynchronous plain RSA or the authentication bits.) BUG=571231 Change-Id: Iba09dddee5bcdfeb2b70185308e8ab0632717932 Reviewed-on: https://boringssl-review.googlesource.com/6780 Reviewed-by: Adam Langley <agl@google.com>
há 8 anos
Implement draft-ietf-tls-curve25519-01 in C. The new curve is not enabled by default. As EC_GROUP/EC_POINT is a bit too complex for X25519, this introduces an SSL_ECDH_METHOD abstraction which wraps just the raw ECDH operation. It also tidies up some of the curve code which kept converting back and force between NIDs and curve IDs. Now everything transits as curve IDs except for API entry points (SSL_set1_curves) which take NIDs. Those convert immediately and act on curve IDs from then on. Note that, like the Go implementation, this slightly tweaks the order of operations. The client sees the server public key before sending its own. To keep the abstraction simple, SSL_ECDH_METHOD expects to generate a keypair before consuming the peer's public key. Instead, the client handshake stashes the serialized peer public value and defers parsing it until it comes time to send ClientKeyExchange. (This is analogous to what it was doing before where it stashed the parsed peer public value instead.) It still uses TLS 1.2 terminology everywhere, but this abstraction should also be compatible with TLS 1.3 which unifies (EC)DH-style key exchanges. (Accordingly, this abstraction intentionally does not handle parsing the ClientKeyExchange/ServerKeyExchange framing or attempt to handle asynchronous plain RSA or the authentication bits.) BUG=571231 Change-Id: Iba09dddee5bcdfeb2b70185308e8ab0632717932 Reviewed-on: https://boringssl-review.googlesource.com/6780 Reviewed-by: Adam Langley <agl@google.com>
há 8 anos
Implement draft-ietf-tls-curve25519-01 in C. The new curve is not enabled by default. As EC_GROUP/EC_POINT is a bit too complex for X25519, this introduces an SSL_ECDH_METHOD abstraction which wraps just the raw ECDH operation. It also tidies up some of the curve code which kept converting back and force between NIDs and curve IDs. Now everything transits as curve IDs except for API entry points (SSL_set1_curves) which take NIDs. Those convert immediately and act on curve IDs from then on. Note that, like the Go implementation, this slightly tweaks the order of operations. The client sees the server public key before sending its own. To keep the abstraction simple, SSL_ECDH_METHOD expects to generate a keypair before consuming the peer's public key. Instead, the client handshake stashes the serialized peer public value and defers parsing it until it comes time to send ClientKeyExchange. (This is analogous to what it was doing before where it stashed the parsed peer public value instead.) It still uses TLS 1.2 terminology everywhere, but this abstraction should also be compatible with TLS 1.3 which unifies (EC)DH-style key exchanges. (Accordingly, this abstraction intentionally does not handle parsing the ClientKeyExchange/ServerKeyExchange framing or attempt to handle asynchronous plain RSA or the authentication bits.) BUG=571231 Change-Id: Iba09dddee5bcdfeb2b70185308e8ab0632717932 Reviewed-on: https://boringssl-review.googlesource.com/6780 Reviewed-by: Adam Langley <agl@google.com>
há 8 anos
Implement draft-ietf-tls-curve25519-01 in C. The new curve is not enabled by default. As EC_GROUP/EC_POINT is a bit too complex for X25519, this introduces an SSL_ECDH_METHOD abstraction which wraps just the raw ECDH operation. It also tidies up some of the curve code which kept converting back and force between NIDs and curve IDs. Now everything transits as curve IDs except for API entry points (SSL_set1_curves) which take NIDs. Those convert immediately and act on curve IDs from then on. Note that, like the Go implementation, this slightly tweaks the order of operations. The client sees the server public key before sending its own. To keep the abstraction simple, SSL_ECDH_METHOD expects to generate a keypair before consuming the peer's public key. Instead, the client handshake stashes the serialized peer public value and defers parsing it until it comes time to send ClientKeyExchange. (This is analogous to what it was doing before where it stashed the parsed peer public value instead.) It still uses TLS 1.2 terminology everywhere, but this abstraction should also be compatible with TLS 1.3 which unifies (EC)DH-style key exchanges. (Accordingly, this abstraction intentionally does not handle parsing the ClientKeyExchange/ServerKeyExchange framing or attempt to handle asynchronous plain RSA or the authentication bits.) BUG=571231 Change-Id: Iba09dddee5bcdfeb2b70185308e8ab0632717932 Reviewed-on: https://boringssl-review.googlesource.com/6780 Reviewed-by: Adam Langley <agl@google.com>
há 8 anos
Implement draft-ietf-tls-curve25519-01 in C. The new curve is not enabled by default. As EC_GROUP/EC_POINT is a bit too complex for X25519, this introduces an SSL_ECDH_METHOD abstraction which wraps just the raw ECDH operation. It also tidies up some of the curve code which kept converting back and force between NIDs and curve IDs. Now everything transits as curve IDs except for API entry points (SSL_set1_curves) which take NIDs. Those convert immediately and act on curve IDs from then on. Note that, like the Go implementation, this slightly tweaks the order of operations. The client sees the server public key before sending its own. To keep the abstraction simple, SSL_ECDH_METHOD expects to generate a keypair before consuming the peer's public key. Instead, the client handshake stashes the serialized peer public value and defers parsing it until it comes time to send ClientKeyExchange. (This is analogous to what it was doing before where it stashed the parsed peer public value instead.) It still uses TLS 1.2 terminology everywhere, but this abstraction should also be compatible with TLS 1.3 which unifies (EC)DH-style key exchanges. (Accordingly, this abstraction intentionally does not handle parsing the ClientKeyExchange/ServerKeyExchange framing or attempt to handle asynchronous plain RSA or the authentication bits.) BUG=571231 Change-Id: Iba09dddee5bcdfeb2b70185308e8ab0632717932 Reviewed-on: https://boringssl-review.googlesource.com/6780 Reviewed-by: Adam Langley <agl@google.com>
há 8 anos
Implement draft-ietf-tls-curve25519-01 in C. The new curve is not enabled by default. As EC_GROUP/EC_POINT is a bit too complex for X25519, this introduces an SSL_ECDH_METHOD abstraction which wraps just the raw ECDH operation. It also tidies up some of the curve code which kept converting back and force between NIDs and curve IDs. Now everything transits as curve IDs except for API entry points (SSL_set1_curves) which take NIDs. Those convert immediately and act on curve IDs from then on. Note that, like the Go implementation, this slightly tweaks the order of operations. The client sees the server public key before sending its own. To keep the abstraction simple, SSL_ECDH_METHOD expects to generate a keypair before consuming the peer's public key. Instead, the client handshake stashes the serialized peer public value and defers parsing it until it comes time to send ClientKeyExchange. (This is analogous to what it was doing before where it stashed the parsed peer public value instead.) It still uses TLS 1.2 terminology everywhere, but this abstraction should also be compatible with TLS 1.3 which unifies (EC)DH-style key exchanges. (Accordingly, this abstraction intentionally does not handle parsing the ClientKeyExchange/ServerKeyExchange framing or attempt to handle asynchronous plain RSA or the authentication bits.) BUG=571231 Change-Id: Iba09dddee5bcdfeb2b70185308e8ab0632717932 Reviewed-on: https://boringssl-review.googlesource.com/6780 Reviewed-by: Adam Langley <agl@google.com>
há 8 anos
Implement draft-ietf-tls-curve25519-01 in C. The new curve is not enabled by default. As EC_GROUP/EC_POINT is a bit too complex for X25519, this introduces an SSL_ECDH_METHOD abstraction which wraps just the raw ECDH operation. It also tidies up some of the curve code which kept converting back and force between NIDs and curve IDs. Now everything transits as curve IDs except for API entry points (SSL_set1_curves) which take NIDs. Those convert immediately and act on curve IDs from then on. Note that, like the Go implementation, this slightly tweaks the order of operations. The client sees the server public key before sending its own. To keep the abstraction simple, SSL_ECDH_METHOD expects to generate a keypair before consuming the peer's public key. Instead, the client handshake stashes the serialized peer public value and defers parsing it until it comes time to send ClientKeyExchange. (This is analogous to what it was doing before where it stashed the parsed peer public value instead.) It still uses TLS 1.2 terminology everywhere, but this abstraction should also be compatible with TLS 1.3 which unifies (EC)DH-style key exchanges. (Accordingly, this abstraction intentionally does not handle parsing the ClientKeyExchange/ServerKeyExchange framing or attempt to handle asynchronous plain RSA or the authentication bits.) BUG=571231 Change-Id: Iba09dddee5bcdfeb2b70185308e8ab0632717932 Reviewed-on: https://boringssl-review.googlesource.com/6780 Reviewed-by: Adam Langley <agl@google.com>
há 8 anos
Implement draft-ietf-tls-curve25519-01 in C. The new curve is not enabled by default. As EC_GROUP/EC_POINT is a bit too complex for X25519, this introduces an SSL_ECDH_METHOD abstraction which wraps just the raw ECDH operation. It also tidies up some of the curve code which kept converting back and force between NIDs and curve IDs. Now everything transits as curve IDs except for API entry points (SSL_set1_curves) which take NIDs. Those convert immediately and act on curve IDs from then on. Note that, like the Go implementation, this slightly tweaks the order of operations. The client sees the server public key before sending its own. To keep the abstraction simple, SSL_ECDH_METHOD expects to generate a keypair before consuming the peer's public key. Instead, the client handshake stashes the serialized peer public value and defers parsing it until it comes time to send ClientKeyExchange. (This is analogous to what it was doing before where it stashed the parsed peer public value instead.) It still uses TLS 1.2 terminology everywhere, but this abstraction should also be compatible with TLS 1.3 which unifies (EC)DH-style key exchanges. (Accordingly, this abstraction intentionally does not handle parsing the ClientKeyExchange/ServerKeyExchange framing or attempt to handle asynchronous plain RSA or the authentication bits.) BUG=571231 Change-Id: Iba09dddee5bcdfeb2b70185308e8ab0632717932 Reviewed-on: https://boringssl-review.googlesource.com/6780 Reviewed-by: Adam Langley <agl@google.com>
há 8 anos
Implement draft-ietf-tls-curve25519-01 in C. The new curve is not enabled by default. As EC_GROUP/EC_POINT is a bit too complex for X25519, this introduces an SSL_ECDH_METHOD abstraction which wraps just the raw ECDH operation. It also tidies up some of the curve code which kept converting back and force between NIDs and curve IDs. Now everything transits as curve IDs except for API entry points (SSL_set1_curves) which take NIDs. Those convert immediately and act on curve IDs from then on. Note that, like the Go implementation, this slightly tweaks the order of operations. The client sees the server public key before sending its own. To keep the abstraction simple, SSL_ECDH_METHOD expects to generate a keypair before consuming the peer's public key. Instead, the client handshake stashes the serialized peer public value and defers parsing it until it comes time to send ClientKeyExchange. (This is analogous to what it was doing before where it stashed the parsed peer public value instead.) It still uses TLS 1.2 terminology everywhere, but this abstraction should also be compatible with TLS 1.3 which unifies (EC)DH-style key exchanges. (Accordingly, this abstraction intentionally does not handle parsing the ClientKeyExchange/ServerKeyExchange framing or attempt to handle asynchronous plain RSA or the authentication bits.) BUG=571231 Change-Id: Iba09dddee5bcdfeb2b70185308e8ab0632717932 Reviewed-on: https://boringssl-review.googlesource.com/6780 Reviewed-by: Adam Langley <agl@google.com>
há 8 anos
Implement draft-ietf-tls-curve25519-01 in C. The new curve is not enabled by default. As EC_GROUP/EC_POINT is a bit too complex for X25519, this introduces an SSL_ECDH_METHOD abstraction which wraps just the raw ECDH operation. It also tidies up some of the curve code which kept converting back and force between NIDs and curve IDs. Now everything transits as curve IDs except for API entry points (SSL_set1_curves) which take NIDs. Those convert immediately and act on curve IDs from then on. Note that, like the Go implementation, this slightly tweaks the order of operations. The client sees the server public key before sending its own. To keep the abstraction simple, SSL_ECDH_METHOD expects to generate a keypair before consuming the peer's public key. Instead, the client handshake stashes the serialized peer public value and defers parsing it until it comes time to send ClientKeyExchange. (This is analogous to what it was doing before where it stashed the parsed peer public value instead.) It still uses TLS 1.2 terminology everywhere, but this abstraction should also be compatible with TLS 1.3 which unifies (EC)DH-style key exchanges. (Accordingly, this abstraction intentionally does not handle parsing the ClientKeyExchange/ServerKeyExchange framing or attempt to handle asynchronous plain RSA or the authentication bits.) BUG=571231 Change-Id: Iba09dddee5bcdfeb2b70185308e8ab0632717932 Reviewed-on: https://boringssl-review.googlesource.com/6780 Reviewed-by: Adam Langley <agl@google.com>
há 8 anos
Implement draft-ietf-tls-curve25519-01 in C. The new curve is not enabled by default. As EC_GROUP/EC_POINT is a bit too complex for X25519, this introduces an SSL_ECDH_METHOD abstraction which wraps just the raw ECDH operation. It also tidies up some of the curve code which kept converting back and force between NIDs and curve IDs. Now everything transits as curve IDs except for API entry points (SSL_set1_curves) which take NIDs. Those convert immediately and act on curve IDs from then on. Note that, like the Go implementation, this slightly tweaks the order of operations. The client sees the server public key before sending its own. To keep the abstraction simple, SSL_ECDH_METHOD expects to generate a keypair before consuming the peer's public key. Instead, the client handshake stashes the serialized peer public value and defers parsing it until it comes time to send ClientKeyExchange. (This is analogous to what it was doing before where it stashed the parsed peer public value instead.) It still uses TLS 1.2 terminology everywhere, but this abstraction should also be compatible with TLS 1.3 which unifies (EC)DH-style key exchanges. (Accordingly, this abstraction intentionally does not handle parsing the ClientKeyExchange/ServerKeyExchange framing or attempt to handle asynchronous plain RSA or the authentication bits.) BUG=571231 Change-Id: Iba09dddee5bcdfeb2b70185308e8ab0632717932 Reviewed-on: https://boringssl-review.googlesource.com/6780 Reviewed-by: Adam Langley <agl@google.com>
há 8 anos
Implement draft-ietf-tls-curve25519-01 in C. The new curve is not enabled by default. As EC_GROUP/EC_POINT is a bit too complex for X25519, this introduces an SSL_ECDH_METHOD abstraction which wraps just the raw ECDH operation. It also tidies up some of the curve code which kept converting back and force between NIDs and curve IDs. Now everything transits as curve IDs except for API entry points (SSL_set1_curves) which take NIDs. Those convert immediately and act on curve IDs from then on. Note that, like the Go implementation, this slightly tweaks the order of operations. The client sees the server public key before sending its own. To keep the abstraction simple, SSL_ECDH_METHOD expects to generate a keypair before consuming the peer's public key. Instead, the client handshake stashes the serialized peer public value and defers parsing it until it comes time to send ClientKeyExchange. (This is analogous to what it was doing before where it stashed the parsed peer public value instead.) It still uses TLS 1.2 terminology everywhere, but this abstraction should also be compatible with TLS 1.3 which unifies (EC)DH-style key exchanges. (Accordingly, this abstraction intentionally does not handle parsing the ClientKeyExchange/ServerKeyExchange framing or attempt to handle asynchronous plain RSA or the authentication bits.) BUG=571231 Change-Id: Iba09dddee5bcdfeb2b70185308e8ab0632717932 Reviewed-on: https://boringssl-review.googlesource.com/6780 Reviewed-by: Adam Langley <agl@google.com>
há 8 anos
Implement draft-ietf-tls-curve25519-01 in C. The new curve is not enabled by default. As EC_GROUP/EC_POINT is a bit too complex for X25519, this introduces an SSL_ECDH_METHOD abstraction which wraps just the raw ECDH operation. It also tidies up some of the curve code which kept converting back and force between NIDs and curve IDs. Now everything transits as curve IDs except for API entry points (SSL_set1_curves) which take NIDs. Those convert immediately and act on curve IDs from then on. Note that, like the Go implementation, this slightly tweaks the order of operations. The client sees the server public key before sending its own. To keep the abstraction simple, SSL_ECDH_METHOD expects to generate a keypair before consuming the peer's public key. Instead, the client handshake stashes the serialized peer public value and defers parsing it until it comes time to send ClientKeyExchange. (This is analogous to what it was doing before where it stashed the parsed peer public value instead.) It still uses TLS 1.2 terminology everywhere, but this abstraction should also be compatible with TLS 1.3 which unifies (EC)DH-style key exchanges. (Accordingly, this abstraction intentionally does not handle parsing the ClientKeyExchange/ServerKeyExchange framing or attempt to handle asynchronous plain RSA or the authentication bits.) BUG=571231 Change-Id: Iba09dddee5bcdfeb2b70185308e8ab0632717932 Reviewed-on: https://boringssl-review.googlesource.com/6780 Reviewed-by: Adam Langley <agl@google.com>
há 8 anos
Implement draft-ietf-tls-curve25519-01 in C. The new curve is not enabled by default. As EC_GROUP/EC_POINT is a bit too complex for X25519, this introduces an SSL_ECDH_METHOD abstraction which wraps just the raw ECDH operation. It also tidies up some of the curve code which kept converting back and force between NIDs and curve IDs. Now everything transits as curve IDs except for API entry points (SSL_set1_curves) which take NIDs. Those convert immediately and act on curve IDs from then on. Note that, like the Go implementation, this slightly tweaks the order of operations. The client sees the server public key before sending its own. To keep the abstraction simple, SSL_ECDH_METHOD expects to generate a keypair before consuming the peer's public key. Instead, the client handshake stashes the serialized peer public value and defers parsing it until it comes time to send ClientKeyExchange. (This is analogous to what it was doing before where it stashed the parsed peer public value instead.) It still uses TLS 1.2 terminology everywhere, but this abstraction should also be compatible with TLS 1.3 which unifies (EC)DH-style key exchanges. (Accordingly, this abstraction intentionally does not handle parsing the ClientKeyExchange/ServerKeyExchange framing or attempt to handle asynchronous plain RSA or the authentication bits.) BUG=571231 Change-Id: Iba09dddee5bcdfeb2b70185308e8ab0632717932 Reviewed-on: https://boringssl-review.googlesource.com/6780 Reviewed-by: Adam Langley <agl@google.com>
há 8 anos
Implement draft-ietf-tls-curve25519-01 in C. The new curve is not enabled by default. As EC_GROUP/EC_POINT is a bit too complex for X25519, this introduces an SSL_ECDH_METHOD abstraction which wraps just the raw ECDH operation. It also tidies up some of the curve code which kept converting back and force between NIDs and curve IDs. Now everything transits as curve IDs except for API entry points (SSL_set1_curves) which take NIDs. Those convert immediately and act on curve IDs from then on. Note that, like the Go implementation, this slightly tweaks the order of operations. The client sees the server public key before sending its own. To keep the abstraction simple, SSL_ECDH_METHOD expects to generate a keypair before consuming the peer's public key. Instead, the client handshake stashes the serialized peer public value and defers parsing it until it comes time to send ClientKeyExchange. (This is analogous to what it was doing before where it stashed the parsed peer public value instead.) It still uses TLS 1.2 terminology everywhere, but this abstraction should also be compatible with TLS 1.3 which unifies (EC)DH-style key exchanges. (Accordingly, this abstraction intentionally does not handle parsing the ClientKeyExchange/ServerKeyExchange framing or attempt to handle asynchronous plain RSA or the authentication bits.) BUG=571231 Change-Id: Iba09dddee5bcdfeb2b70185308e8ab0632717932 Reviewed-on: https://boringssl-review.googlesource.com/6780 Reviewed-by: Adam Langley <agl@google.com>
há 8 anos
Implement draft-ietf-tls-curve25519-01 in C. The new curve is not enabled by default. As EC_GROUP/EC_POINT is a bit too complex for X25519, this introduces an SSL_ECDH_METHOD abstraction which wraps just the raw ECDH operation. It also tidies up some of the curve code which kept converting back and force between NIDs and curve IDs. Now everything transits as curve IDs except for API entry points (SSL_set1_curves) which take NIDs. Those convert immediately and act on curve IDs from then on. Note that, like the Go implementation, this slightly tweaks the order of operations. The client sees the server public key before sending its own. To keep the abstraction simple, SSL_ECDH_METHOD expects to generate a keypair before consuming the peer's public key. Instead, the client handshake stashes the serialized peer public value and defers parsing it until it comes time to send ClientKeyExchange. (This is analogous to what it was doing before where it stashed the parsed peer public value instead.) It still uses TLS 1.2 terminology everywhere, but this abstraction should also be compatible with TLS 1.3 which unifies (EC)DH-style key exchanges. (Accordingly, this abstraction intentionally does not handle parsing the ClientKeyExchange/ServerKeyExchange framing or attempt to handle asynchronous plain RSA or the authentication bits.) BUG=571231 Change-Id: Iba09dddee5bcdfeb2b70185308e8ab0632717932 Reviewed-on: https://boringssl-review.googlesource.com/6780 Reviewed-by: Adam Langley <agl@google.com>
há 8 anos
Implement draft-ietf-tls-curve25519-01 in C. The new curve is not enabled by default. As EC_GROUP/EC_POINT is a bit too complex for X25519, this introduces an SSL_ECDH_METHOD abstraction which wraps just the raw ECDH operation. It also tidies up some of the curve code which kept converting back and force between NIDs and curve IDs. Now everything transits as curve IDs except for API entry points (SSL_set1_curves) which take NIDs. Those convert immediately and act on curve IDs from then on. Note that, like the Go implementation, this slightly tweaks the order of operations. The client sees the server public key before sending its own. To keep the abstraction simple, SSL_ECDH_METHOD expects to generate a keypair before consuming the peer's public key. Instead, the client handshake stashes the serialized peer public value and defers parsing it until it comes time to send ClientKeyExchange. (This is analogous to what it was doing before where it stashed the parsed peer public value instead.) It still uses TLS 1.2 terminology everywhere, but this abstraction should also be compatible with TLS 1.3 which unifies (EC)DH-style key exchanges. (Accordingly, this abstraction intentionally does not handle parsing the ClientKeyExchange/ServerKeyExchange framing or attempt to handle asynchronous plain RSA or the authentication bits.) BUG=571231 Change-Id: Iba09dddee5bcdfeb2b70185308e8ab0632717932 Reviewed-on: https://boringssl-review.googlesource.com/6780 Reviewed-by: Adam Langley <agl@google.com>
há 8 anos
Implement draft-ietf-tls-curve25519-01 in C. The new curve is not enabled by default. As EC_GROUP/EC_POINT is a bit too complex for X25519, this introduces an SSL_ECDH_METHOD abstraction which wraps just the raw ECDH operation. It also tidies up some of the curve code which kept converting back and force between NIDs and curve IDs. Now everything transits as curve IDs except for API entry points (SSL_set1_curves) which take NIDs. Those convert immediately and act on curve IDs from then on. Note that, like the Go implementation, this slightly tweaks the order of operations. The client sees the server public key before sending its own. To keep the abstraction simple, SSL_ECDH_METHOD expects to generate a keypair before consuming the peer's public key. Instead, the client handshake stashes the serialized peer public value and defers parsing it until it comes time to send ClientKeyExchange. (This is analogous to what it was doing before where it stashed the parsed peer public value instead.) It still uses TLS 1.2 terminology everywhere, but this abstraction should also be compatible with TLS 1.3 which unifies (EC)DH-style key exchanges. (Accordingly, this abstraction intentionally does not handle parsing the ClientKeyExchange/ServerKeyExchange framing or attempt to handle asynchronous plain RSA or the authentication bits.) BUG=571231 Change-Id: Iba09dddee5bcdfeb2b70185308e8ab0632717932 Reviewed-on: https://boringssl-review.googlesource.com/6780 Reviewed-by: Adam Langley <agl@google.com>
há 8 anos
Implement draft-ietf-tls-curve25519-01 in C. The new curve is not enabled by default. As EC_GROUP/EC_POINT is a bit too complex for X25519, this introduces an SSL_ECDH_METHOD abstraction which wraps just the raw ECDH operation. It also tidies up some of the curve code which kept converting back and force between NIDs and curve IDs. Now everything transits as curve IDs except for API entry points (SSL_set1_curves) which take NIDs. Those convert immediately and act on curve IDs from then on. Note that, like the Go implementation, this slightly tweaks the order of operations. The client sees the server public key before sending its own. To keep the abstraction simple, SSL_ECDH_METHOD expects to generate a keypair before consuming the peer's public key. Instead, the client handshake stashes the serialized peer public value and defers parsing it until it comes time to send ClientKeyExchange. (This is analogous to what it was doing before where it stashed the parsed peer public value instead.) It still uses TLS 1.2 terminology everywhere, but this abstraction should also be compatible with TLS 1.3 which unifies (EC)DH-style key exchanges. (Accordingly, this abstraction intentionally does not handle parsing the ClientKeyExchange/ServerKeyExchange framing or attempt to handle asynchronous plain RSA or the authentication bits.) BUG=571231 Change-Id: Iba09dddee5bcdfeb2b70185308e8ab0632717932 Reviewed-on: https://boringssl-review.googlesource.com/6780 Reviewed-by: Adam Langley <agl@google.com>
há 8 anos
Implement draft-ietf-tls-curve25519-01 in C. The new curve is not enabled by default. As EC_GROUP/EC_POINT is a bit too complex for X25519, this introduces an SSL_ECDH_METHOD abstraction which wraps just the raw ECDH operation. It also tidies up some of the curve code which kept converting back and force between NIDs and curve IDs. Now everything transits as curve IDs except for API entry points (SSL_set1_curves) which take NIDs. Those convert immediately and act on curve IDs from then on. Note that, like the Go implementation, this slightly tweaks the order of operations. The client sees the server public key before sending its own. To keep the abstraction simple, SSL_ECDH_METHOD expects to generate a keypair before consuming the peer's public key. Instead, the client handshake stashes the serialized peer public value and defers parsing it until it comes time to send ClientKeyExchange. (This is analogous to what it was doing before where it stashed the parsed peer public value instead.) It still uses TLS 1.2 terminology everywhere, but this abstraction should also be compatible with TLS 1.3 which unifies (EC)DH-style key exchanges. (Accordingly, this abstraction intentionally does not handle parsing the ClientKeyExchange/ServerKeyExchange framing or attempt to handle asynchronous plain RSA or the authentication bits.) BUG=571231 Change-Id: Iba09dddee5bcdfeb2b70185308e8ab0632717932 Reviewed-on: https://boringssl-review.googlesource.com/6780 Reviewed-by: Adam Langley <agl@google.com>
há 8 anos
Implement draft-ietf-tls-curve25519-01 in C. The new curve is not enabled by default. As EC_GROUP/EC_POINT is a bit too complex for X25519, this introduces an SSL_ECDH_METHOD abstraction which wraps just the raw ECDH operation. It also tidies up some of the curve code which kept converting back and force between NIDs and curve IDs. Now everything transits as curve IDs except for API entry points (SSL_set1_curves) which take NIDs. Those convert immediately and act on curve IDs from then on. Note that, like the Go implementation, this slightly tweaks the order of operations. The client sees the server public key before sending its own. To keep the abstraction simple, SSL_ECDH_METHOD expects to generate a keypair before consuming the peer's public key. Instead, the client handshake stashes the serialized peer public value and defers parsing it until it comes time to send ClientKeyExchange. (This is analogous to what it was doing before where it stashed the parsed peer public value instead.) It still uses TLS 1.2 terminology everywhere, but this abstraction should also be compatible with TLS 1.3 which unifies (EC)DH-style key exchanges. (Accordingly, this abstraction intentionally does not handle parsing the ClientKeyExchange/ServerKeyExchange framing or attempt to handle asynchronous plain RSA or the authentication bits.) BUG=571231 Change-Id: Iba09dddee5bcdfeb2b70185308e8ab0632717932 Reviewed-on: https://boringssl-review.googlesource.com/6780 Reviewed-by: Adam Langley <agl@google.com>
há 8 anos
Implement draft-ietf-tls-curve25519-01 in C. The new curve is not enabled by default. As EC_GROUP/EC_POINT is a bit too complex for X25519, this introduces an SSL_ECDH_METHOD abstraction which wraps just the raw ECDH operation. It also tidies up some of the curve code which kept converting back and force between NIDs and curve IDs. Now everything transits as curve IDs except for API entry points (SSL_set1_curves) which take NIDs. Those convert immediately and act on curve IDs from then on. Note that, like the Go implementation, this slightly tweaks the order of operations. The client sees the server public key before sending its own. To keep the abstraction simple, SSL_ECDH_METHOD expects to generate a keypair before consuming the peer's public key. Instead, the client handshake stashes the serialized peer public value and defers parsing it until it comes time to send ClientKeyExchange. (This is analogous to what it was doing before where it stashed the parsed peer public value instead.) It still uses TLS 1.2 terminology everywhere, but this abstraction should also be compatible with TLS 1.3 which unifies (EC)DH-style key exchanges. (Accordingly, this abstraction intentionally does not handle parsing the ClientKeyExchange/ServerKeyExchange framing or attempt to handle asynchronous plain RSA or the authentication bits.) BUG=571231 Change-Id: Iba09dddee5bcdfeb2b70185308e8ab0632717932 Reviewed-on: https://boringssl-review.googlesource.com/6780 Reviewed-by: Adam Langley <agl@google.com>
há 8 anos
Implement draft-ietf-tls-curve25519-01 in C. The new curve is not enabled by default. As EC_GROUP/EC_POINT is a bit too complex for X25519, this introduces an SSL_ECDH_METHOD abstraction which wraps just the raw ECDH operation. It also tidies up some of the curve code which kept converting back and force between NIDs and curve IDs. Now everything transits as curve IDs except for API entry points (SSL_set1_curves) which take NIDs. Those convert immediately and act on curve IDs from then on. Note that, like the Go implementation, this slightly tweaks the order of operations. The client sees the server public key before sending its own. To keep the abstraction simple, SSL_ECDH_METHOD expects to generate a keypair before consuming the peer's public key. Instead, the client handshake stashes the serialized peer public value and defers parsing it until it comes time to send ClientKeyExchange. (This is analogous to what it was doing before where it stashed the parsed peer public value instead.) It still uses TLS 1.2 terminology everywhere, but this abstraction should also be compatible with TLS 1.3 which unifies (EC)DH-style key exchanges. (Accordingly, this abstraction intentionally does not handle parsing the ClientKeyExchange/ServerKeyExchange framing or attempt to handle asynchronous plain RSA or the authentication bits.) BUG=571231 Change-Id: Iba09dddee5bcdfeb2b70185308e8ab0632717932 Reviewed-on: https://boringssl-review.googlesource.com/6780 Reviewed-by: Adam Langley <agl@google.com>
há 8 anos
Implement draft-ietf-tls-curve25519-01 in C. The new curve is not enabled by default. As EC_GROUP/EC_POINT is a bit too complex for X25519, this introduces an SSL_ECDH_METHOD abstraction which wraps just the raw ECDH operation. It also tidies up some of the curve code which kept converting back and force between NIDs and curve IDs. Now everything transits as curve IDs except for API entry points (SSL_set1_curves) which take NIDs. Those convert immediately and act on curve IDs from then on. Note that, like the Go implementation, this slightly tweaks the order of operations. The client sees the server public key before sending its own. To keep the abstraction simple, SSL_ECDH_METHOD expects to generate a keypair before consuming the peer's public key. Instead, the client handshake stashes the serialized peer public value and defers parsing it until it comes time to send ClientKeyExchange. (This is analogous to what it was doing before where it stashed the parsed peer public value instead.) It still uses TLS 1.2 terminology everywhere, but this abstraction should also be compatible with TLS 1.3 which unifies (EC)DH-style key exchanges. (Accordingly, this abstraction intentionally does not handle parsing the ClientKeyExchange/ServerKeyExchange framing or attempt to handle asynchronous plain RSA or the authentication bits.) BUG=571231 Change-Id: Iba09dddee5bcdfeb2b70185308e8ab0632717932 Reviewed-on: https://boringssl-review.googlesource.com/6780 Reviewed-by: Adam Langley <agl@google.com>
há 8 anos
Implement draft-ietf-tls-curve25519-01 in C. The new curve is not enabled by default. As EC_GROUP/EC_POINT is a bit too complex for X25519, this introduces an SSL_ECDH_METHOD abstraction which wraps just the raw ECDH operation. It also tidies up some of the curve code which kept converting back and force between NIDs and curve IDs. Now everything transits as curve IDs except for API entry points (SSL_set1_curves) which take NIDs. Those convert immediately and act on curve IDs from then on. Note that, like the Go implementation, this slightly tweaks the order of operations. The client sees the server public key before sending its own. To keep the abstraction simple, SSL_ECDH_METHOD expects to generate a keypair before consuming the peer's public key. Instead, the client handshake stashes the serialized peer public value and defers parsing it until it comes time to send ClientKeyExchange. (This is analogous to what it was doing before where it stashed the parsed peer public value instead.) It still uses TLS 1.2 terminology everywhere, but this abstraction should also be compatible with TLS 1.3 which unifies (EC)DH-style key exchanges. (Accordingly, this abstraction intentionally does not handle parsing the ClientKeyExchange/ServerKeyExchange framing or attempt to handle asynchronous plain RSA or the authentication bits.) BUG=571231 Change-Id: Iba09dddee5bcdfeb2b70185308e8ab0632717932 Reviewed-on: https://boringssl-review.googlesource.com/6780 Reviewed-by: Adam Langley <agl@google.com>
há 8 anos
Implement draft-ietf-tls-curve25519-01 in C. The new curve is not enabled by default. As EC_GROUP/EC_POINT is a bit too complex for X25519, this introduces an SSL_ECDH_METHOD abstraction which wraps just the raw ECDH operation. It also tidies up some of the curve code which kept converting back and force between NIDs and curve IDs. Now everything transits as curve IDs except for API entry points (SSL_set1_curves) which take NIDs. Those convert immediately and act on curve IDs from then on. Note that, like the Go implementation, this slightly tweaks the order of operations. The client sees the server public key before sending its own. To keep the abstraction simple, SSL_ECDH_METHOD expects to generate a keypair before consuming the peer's public key. Instead, the client handshake stashes the serialized peer public value and defers parsing it until it comes time to send ClientKeyExchange. (This is analogous to what it was doing before where it stashed the parsed peer public value instead.) It still uses TLS 1.2 terminology everywhere, but this abstraction should also be compatible with TLS 1.3 which unifies (EC)DH-style key exchanges. (Accordingly, this abstraction intentionally does not handle parsing the ClientKeyExchange/ServerKeyExchange framing or attempt to handle asynchronous plain RSA or the authentication bits.) BUG=571231 Change-Id: Iba09dddee5bcdfeb2b70185308e8ab0632717932 Reviewed-on: https://boringssl-review.googlesource.com/6780 Reviewed-by: Adam Langley <agl@google.com>
há 8 anos
Implement draft-ietf-tls-curve25519-01 in C. The new curve is not enabled by default. As EC_GROUP/EC_POINT is a bit too complex for X25519, this introduces an SSL_ECDH_METHOD abstraction which wraps just the raw ECDH operation. It also tidies up some of the curve code which kept converting back and force between NIDs and curve IDs. Now everything transits as curve IDs except for API entry points (SSL_set1_curves) which take NIDs. Those convert immediately and act on curve IDs from then on. Note that, like the Go implementation, this slightly tweaks the order of operations. The client sees the server public key before sending its own. To keep the abstraction simple, SSL_ECDH_METHOD expects to generate a keypair before consuming the peer's public key. Instead, the client handshake stashes the serialized peer public value and defers parsing it until it comes time to send ClientKeyExchange. (This is analogous to what it was doing before where it stashed the parsed peer public value instead.) It still uses TLS 1.2 terminology everywhere, but this abstraction should also be compatible with TLS 1.3 which unifies (EC)DH-style key exchanges. (Accordingly, this abstraction intentionally does not handle parsing the ClientKeyExchange/ServerKeyExchange framing or attempt to handle asynchronous plain RSA or the authentication bits.) BUG=571231 Change-Id: Iba09dddee5bcdfeb2b70185308e8ab0632717932 Reviewed-on: https://boringssl-review.googlesource.com/6780 Reviewed-by: Adam Langley <agl@google.com>
há 8 anos
Implement draft-ietf-tls-curve25519-01 in C. The new curve is not enabled by default. As EC_GROUP/EC_POINT is a bit too complex for X25519, this introduces an SSL_ECDH_METHOD abstraction which wraps just the raw ECDH operation. It also tidies up some of the curve code which kept converting back and force between NIDs and curve IDs. Now everything transits as curve IDs except for API entry points (SSL_set1_curves) which take NIDs. Those convert immediately and act on curve IDs from then on. Note that, like the Go implementation, this slightly tweaks the order of operations. The client sees the server public key before sending its own. To keep the abstraction simple, SSL_ECDH_METHOD expects to generate a keypair before consuming the peer's public key. Instead, the client handshake stashes the serialized peer public value and defers parsing it until it comes time to send ClientKeyExchange. (This is analogous to what it was doing before where it stashed the parsed peer public value instead.) It still uses TLS 1.2 terminology everywhere, but this abstraction should also be compatible with TLS 1.3 which unifies (EC)DH-style key exchanges. (Accordingly, this abstraction intentionally does not handle parsing the ClientKeyExchange/ServerKeyExchange framing or attempt to handle asynchronous plain RSA or the authentication bits.) BUG=571231 Change-Id: Iba09dddee5bcdfeb2b70185308e8ab0632717932 Reviewed-on: https://boringssl-review.googlesource.com/6780 Reviewed-by: Adam Langley <agl@google.com>
há 8 anos
Implement draft-ietf-tls-curve25519-01 in C. The new curve is not enabled by default. As EC_GROUP/EC_POINT is a bit too complex for X25519, this introduces an SSL_ECDH_METHOD abstraction which wraps just the raw ECDH operation. It also tidies up some of the curve code which kept converting back and force between NIDs and curve IDs. Now everything transits as curve IDs except for API entry points (SSL_set1_curves) which take NIDs. Those convert immediately and act on curve IDs from then on. Note that, like the Go implementation, this slightly tweaks the order of operations. The client sees the server public key before sending its own. To keep the abstraction simple, SSL_ECDH_METHOD expects to generate a keypair before consuming the peer's public key. Instead, the client handshake stashes the serialized peer public value and defers parsing it until it comes time to send ClientKeyExchange. (This is analogous to what it was doing before where it stashed the parsed peer public value instead.) It still uses TLS 1.2 terminology everywhere, but this abstraction should also be compatible with TLS 1.3 which unifies (EC)DH-style key exchanges. (Accordingly, this abstraction intentionally does not handle parsing the ClientKeyExchange/ServerKeyExchange framing or attempt to handle asynchronous plain RSA or the authentication bits.) BUG=571231 Change-Id: Iba09dddee5bcdfeb2b70185308e8ab0632717932 Reviewed-on: https://boringssl-review.googlesource.com/6780 Reviewed-by: Adam Langley <agl@google.com>
há 8 anos
Implement draft-ietf-tls-curve25519-01 in C. The new curve is not enabled by default. As EC_GROUP/EC_POINT is a bit too complex for X25519, this introduces an SSL_ECDH_METHOD abstraction which wraps just the raw ECDH operation. It also tidies up some of the curve code which kept converting back and force between NIDs and curve IDs. Now everything transits as curve IDs except for API entry points (SSL_set1_curves) which take NIDs. Those convert immediately and act on curve IDs from then on. Note that, like the Go implementation, this slightly tweaks the order of operations. The client sees the server public key before sending its own. To keep the abstraction simple, SSL_ECDH_METHOD expects to generate a keypair before consuming the peer's public key. Instead, the client handshake stashes the serialized peer public value and defers parsing it until it comes time to send ClientKeyExchange. (This is analogous to what it was doing before where it stashed the parsed peer public value instead.) It still uses TLS 1.2 terminology everywhere, but this abstraction should also be compatible with TLS 1.3 which unifies (EC)DH-style key exchanges. (Accordingly, this abstraction intentionally does not handle parsing the ClientKeyExchange/ServerKeyExchange framing or attempt to handle asynchronous plain RSA or the authentication bits.) BUG=571231 Change-Id: Iba09dddee5bcdfeb2b70185308e8ab0632717932 Reviewed-on: https://boringssl-review.googlesource.com/6780 Reviewed-by: Adam Langley <agl@google.com>
há 8 anos
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629
  1. /* Copyright (c) 2015, Google Inc.
  2. *
  3. * Permission to use, copy, modify, and/or distribute this software for any
  4. * purpose with or without fee is hereby granted, provided that the above
  5. * copyright notice and this permission notice appear in all copies.
  6. *
  7. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  8. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  9. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
  10. * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  11. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  12. * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  13. * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
  14. #include <openssl/ssl.h>
  15. #include <assert.h>
  16. #include <string.h>
  17. #include <openssl/bn.h>
  18. #include <openssl/bytestring.h>
  19. #include <openssl/curve25519.h>
  20. #include <openssl/ec.h>
  21. #include <openssl/err.h>
  22. #include <openssl/mem.h>
  23. #include <openssl/newhope.h>
  24. #include <openssl/nid.h>
  25. #include "internal.h"
  26. #include "../crypto/internal.h"
  27. /* |EC_POINT| implementation. */
  28. static void ssl_ec_point_cleanup(SSL_ECDH_CTX *ctx) {
  29. BIGNUM *private_key = (BIGNUM *)ctx->data;
  30. BN_clear_free(private_key);
  31. }
  32. static int ssl_ec_point_offer(SSL_ECDH_CTX *ctx, CBB *out) {
  33. assert(ctx->data == NULL);
  34. BIGNUM *private_key = BN_new();
  35. if (private_key == NULL) {
  36. return 0;
  37. }
  38. ctx->data = private_key;
  39. /* Set up a shared |BN_CTX| for all operations. */
  40. BN_CTX *bn_ctx = BN_CTX_new();
  41. if (bn_ctx == NULL) {
  42. return 0;
  43. }
  44. BN_CTX_start(bn_ctx);
  45. int ret = 0;
  46. EC_POINT *public_key = NULL;
  47. EC_GROUP *group = EC_GROUP_new_by_curve_name(ctx->method->nid);
  48. if (group == NULL) {
  49. goto err;
  50. }
  51. /* Generate a private key. */
  52. if (!BN_rand_range_ex(private_key, 1, EC_GROUP_get0_order(group))) {
  53. goto err;
  54. }
  55. /* Compute the corresponding public key and serialize it. */
  56. public_key = EC_POINT_new(group);
  57. if (public_key == NULL ||
  58. !EC_POINT_mul(group, public_key, private_key, NULL, NULL, bn_ctx) ||
  59. !EC_POINT_point2cbb(out, group, public_key, POINT_CONVERSION_UNCOMPRESSED,
  60. bn_ctx)) {
  61. goto err;
  62. }
  63. ret = 1;
  64. err:
  65. EC_GROUP_free(group);
  66. EC_POINT_free(public_key);
  67. BN_CTX_end(bn_ctx);
  68. BN_CTX_free(bn_ctx);
  69. return ret;
  70. }
  71. static int ssl_ec_point_finish(SSL_ECDH_CTX *ctx, uint8_t **out_secret,
  72. size_t *out_secret_len, uint8_t *out_alert,
  73. const uint8_t *peer_key, size_t peer_key_len) {
  74. BIGNUM *private_key = (BIGNUM *)ctx->data;
  75. assert(private_key != NULL);
  76. *out_alert = SSL_AD_INTERNAL_ERROR;
  77. /* Set up a shared |BN_CTX| for all operations. */
  78. BN_CTX *bn_ctx = BN_CTX_new();
  79. if (bn_ctx == NULL) {
  80. return 0;
  81. }
  82. BN_CTX_start(bn_ctx);
  83. int ret = 0;
  84. EC_GROUP *group = EC_GROUP_new_by_curve_name(ctx->method->nid);
  85. EC_POINT *peer_point = NULL, *result = NULL;
  86. uint8_t *secret = NULL;
  87. if (group == NULL) {
  88. goto err;
  89. }
  90. /* Compute the x-coordinate of |peer_key| * |private_key|. */
  91. peer_point = EC_POINT_new(group);
  92. result = EC_POINT_new(group);
  93. if (peer_point == NULL || result == NULL) {
  94. goto err;
  95. }
  96. BIGNUM *x = BN_CTX_get(bn_ctx);
  97. if (x == NULL) {
  98. goto err;
  99. }
  100. if (!EC_POINT_oct2point(group, peer_point, peer_key, peer_key_len, bn_ctx)) {
  101. *out_alert = SSL_AD_DECODE_ERROR;
  102. goto err;
  103. }
  104. if (!EC_POINT_mul(group, result, NULL, peer_point, private_key, bn_ctx) ||
  105. !EC_POINT_get_affine_coordinates_GFp(group, result, x, NULL, bn_ctx)) {
  106. goto err;
  107. }
  108. /* Encode the x-coordinate left-padded with zeros. */
  109. size_t secret_len = (EC_GROUP_get_degree(group) + 7) / 8;
  110. secret = OPENSSL_malloc(secret_len);
  111. if (secret == NULL || !BN_bn2bin_padded(secret, secret_len, x)) {
  112. goto err;
  113. }
  114. *out_secret = secret;
  115. *out_secret_len = secret_len;
  116. secret = NULL;
  117. ret = 1;
  118. err:
  119. EC_GROUP_free(group);
  120. EC_POINT_free(peer_point);
  121. EC_POINT_free(result);
  122. BN_CTX_end(bn_ctx);
  123. BN_CTX_free(bn_ctx);
  124. OPENSSL_free(secret);
  125. return ret;
  126. }
  127. static int ssl_ec_point_accept(SSL_ECDH_CTX *ctx, CBB *out_public_key,
  128. uint8_t **out_secret, size_t *out_secret_len,
  129. uint8_t *out_alert, const uint8_t *peer_key,
  130. size_t peer_key_len) {
  131. *out_alert = SSL_AD_INTERNAL_ERROR;
  132. if (!ssl_ec_point_offer(ctx, out_public_key) ||
  133. !ssl_ec_point_finish(ctx, out_secret, out_secret_len, out_alert, peer_key,
  134. peer_key_len)) {
  135. return 0;
  136. }
  137. return 1;
  138. }
  139. /* X25119 implementation. */
  140. static void ssl_x25519_cleanup(SSL_ECDH_CTX *ctx) {
  141. if (ctx->data == NULL) {
  142. return;
  143. }
  144. OPENSSL_cleanse(ctx->data, 32);
  145. OPENSSL_free(ctx->data);
  146. }
  147. static int ssl_x25519_offer(SSL_ECDH_CTX *ctx, CBB *out) {
  148. assert(ctx->data == NULL);
  149. ctx->data = OPENSSL_malloc(32);
  150. if (ctx->data == NULL) {
  151. OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
  152. return 0;
  153. }
  154. uint8_t public_key[32];
  155. X25519_keypair(public_key, (uint8_t *)ctx->data);
  156. return CBB_add_bytes(out, public_key, sizeof(public_key));
  157. }
  158. static int ssl_x25519_finish(SSL_ECDH_CTX *ctx, uint8_t **out_secret,
  159. size_t *out_secret_len, uint8_t *out_alert,
  160. const uint8_t *peer_key, size_t peer_key_len) {
  161. assert(ctx->data != NULL);
  162. *out_alert = SSL_AD_INTERNAL_ERROR;
  163. uint8_t *secret = OPENSSL_malloc(32);
  164. if (secret == NULL) {
  165. return 0;
  166. }
  167. if (peer_key_len != 32 ||
  168. !X25519(secret, (uint8_t *)ctx->data, peer_key)) {
  169. OPENSSL_free(secret);
  170. *out_alert = SSL_AD_DECODE_ERROR;
  171. OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ECPOINT);
  172. return 0;
  173. }
  174. *out_secret = secret;
  175. *out_secret_len = 32;
  176. return 1;
  177. }
  178. static int ssl_x25519_accept(SSL_ECDH_CTX *ctx, CBB *out_public_key,
  179. uint8_t **out_secret, size_t *out_secret_len,
  180. uint8_t *out_alert, const uint8_t *peer_key,
  181. size_t peer_key_len) {
  182. *out_alert = SSL_AD_INTERNAL_ERROR;
  183. if (!ssl_x25519_offer(ctx, out_public_key) ||
  184. !ssl_x25519_finish(ctx, out_secret, out_secret_len, out_alert, peer_key,
  185. peer_key_len)) {
  186. return 0;
  187. }
  188. return 1;
  189. }
  190. /* Combined X25119 + New Hope (post-quantum) implementation. */
  191. typedef struct {
  192. uint8_t x25519_key[32];
  193. NEWHOPE_POLY *newhope_sk;
  194. } cecpq1_data;
  195. #define CECPQ1_OFFERMSG_LENGTH (32 + NEWHOPE_OFFERMSG_LENGTH)
  196. #define CECPQ1_ACCEPTMSG_LENGTH (32 + NEWHOPE_ACCEPTMSG_LENGTH)
  197. #define CECPQ1_SECRET_LENGTH (32 + SHA256_DIGEST_LENGTH)
  198. static void ssl_cecpq1_cleanup(SSL_ECDH_CTX *ctx) {
  199. if (ctx->data == NULL) {
  200. return;
  201. }
  202. cecpq1_data *data = ctx->data;
  203. NEWHOPE_POLY_free(data->newhope_sk);
  204. OPENSSL_cleanse(data, sizeof(cecpq1_data));
  205. OPENSSL_free(data);
  206. }
  207. static int ssl_cecpq1_offer(SSL_ECDH_CTX *ctx, CBB *out) {
  208. assert(ctx->data == NULL);
  209. cecpq1_data *data = OPENSSL_malloc(sizeof(cecpq1_data));
  210. if (data == NULL) {
  211. OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
  212. return 0;
  213. }
  214. ctx->data = data;
  215. data->newhope_sk = NEWHOPE_POLY_new();
  216. if (data->newhope_sk == NULL) {
  217. OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
  218. return 0;
  219. }
  220. uint8_t x25519_public_key[32];
  221. X25519_keypair(x25519_public_key, data->x25519_key);
  222. uint8_t newhope_offermsg[NEWHOPE_OFFERMSG_LENGTH];
  223. NEWHOPE_offer(newhope_offermsg, data->newhope_sk);
  224. if (!CBB_add_bytes(out, x25519_public_key, sizeof(x25519_public_key)) ||
  225. !CBB_add_bytes(out, newhope_offermsg, sizeof(newhope_offermsg))) {
  226. return 0;
  227. }
  228. return 1;
  229. }
  230. static int ssl_cecpq1_accept(SSL_ECDH_CTX *ctx, CBB *cbb, uint8_t **out_secret,
  231. size_t *out_secret_len, uint8_t *out_alert,
  232. const uint8_t *peer_key, size_t peer_key_len) {
  233. if (peer_key_len != CECPQ1_OFFERMSG_LENGTH) {
  234. *out_alert = SSL_AD_DECODE_ERROR;
  235. return 0;
  236. }
  237. *out_alert = SSL_AD_INTERNAL_ERROR;
  238. assert(ctx->data == NULL);
  239. cecpq1_data *data = OPENSSL_malloc(sizeof(cecpq1_data));
  240. if (data == NULL) {
  241. OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
  242. return 0;
  243. }
  244. data->newhope_sk = NULL;
  245. ctx->data = data;
  246. uint8_t *secret = OPENSSL_malloc(CECPQ1_SECRET_LENGTH);
  247. if (secret == NULL) {
  248. OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
  249. return 0;
  250. }
  251. /* Generate message to server, and secret key, at once. */
  252. uint8_t x25519_public_key[32];
  253. X25519_keypair(x25519_public_key, data->x25519_key);
  254. if (!X25519(secret, data->x25519_key, peer_key)) {
  255. *out_alert = SSL_AD_DECODE_ERROR;
  256. OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ECPOINT);
  257. goto err;
  258. }
  259. uint8_t newhope_acceptmsg[NEWHOPE_ACCEPTMSG_LENGTH];
  260. if (!NEWHOPE_accept(secret + 32, newhope_acceptmsg, peer_key + 32,
  261. NEWHOPE_OFFERMSG_LENGTH)) {
  262. *out_alert = SSL_AD_DECODE_ERROR;
  263. goto err;
  264. }
  265. if (!CBB_add_bytes(cbb, x25519_public_key, sizeof(x25519_public_key)) ||
  266. !CBB_add_bytes(cbb, newhope_acceptmsg, sizeof(newhope_acceptmsg))) {
  267. goto err;
  268. }
  269. *out_secret = secret;
  270. *out_secret_len = CECPQ1_SECRET_LENGTH;
  271. return 1;
  272. err:
  273. OPENSSL_cleanse(secret, CECPQ1_SECRET_LENGTH);
  274. OPENSSL_free(secret);
  275. return 0;
  276. }
  277. static int ssl_cecpq1_finish(SSL_ECDH_CTX *ctx, uint8_t **out_secret,
  278. size_t *out_secret_len, uint8_t *out_alert,
  279. const uint8_t *peer_key, size_t peer_key_len) {
  280. if (peer_key_len != CECPQ1_ACCEPTMSG_LENGTH) {
  281. *out_alert = SSL_AD_DECODE_ERROR;
  282. return 0;
  283. }
  284. *out_alert = SSL_AD_INTERNAL_ERROR;
  285. assert(ctx->data != NULL);
  286. cecpq1_data *data = ctx->data;
  287. uint8_t *secret = OPENSSL_malloc(CECPQ1_SECRET_LENGTH);
  288. if (secret == NULL) {
  289. OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
  290. return 0;
  291. }
  292. if (!X25519(secret, data->x25519_key, peer_key)) {
  293. *out_alert = SSL_AD_DECODE_ERROR;
  294. OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ECPOINT);
  295. goto err;
  296. }
  297. if (!NEWHOPE_finish(secret + 32, data->newhope_sk, peer_key + 32,
  298. NEWHOPE_ACCEPTMSG_LENGTH)) {
  299. *out_alert = SSL_AD_DECODE_ERROR;
  300. goto err;
  301. }
  302. *out_secret = secret;
  303. *out_secret_len = CECPQ1_SECRET_LENGTH;
  304. return 1;
  305. err:
  306. OPENSSL_cleanse(secret, CECPQ1_SECRET_LENGTH);
  307. OPENSSL_free(secret);
  308. return 0;
  309. }
  310. /* Legacy DHE-based implementation. */
  311. static void ssl_dhe_cleanup(SSL_ECDH_CTX *ctx) {
  312. DH_free((DH *)ctx->data);
  313. }
  314. static int ssl_dhe_offer(SSL_ECDH_CTX *ctx, CBB *out) {
  315. DH *dh = (DH *)ctx->data;
  316. /* The group must have been initialized already, but not the key. */
  317. assert(dh != NULL);
  318. assert(dh->priv_key == NULL);
  319. /* Due to a bug in yaSSL, the public key must be zero padded to the size of
  320. * the prime. */
  321. return DH_generate_key(dh) &&
  322. BN_bn2cbb_padded(out, BN_num_bytes(dh->p), dh->pub_key);
  323. }
  324. static int ssl_dhe_finish(SSL_ECDH_CTX *ctx, uint8_t **out_secret,
  325. size_t *out_secret_len, uint8_t *out_alert,
  326. const uint8_t *peer_key, size_t peer_key_len) {
  327. DH *dh = (DH *)ctx->data;
  328. assert(dh != NULL);
  329. assert(dh->priv_key != NULL);
  330. *out_alert = SSL_AD_INTERNAL_ERROR;
  331. int secret_len = 0;
  332. uint8_t *secret = NULL;
  333. BIGNUM *peer_point = BN_bin2bn(peer_key, peer_key_len, NULL);
  334. if (peer_point == NULL) {
  335. goto err;
  336. }
  337. secret = OPENSSL_malloc(DH_size(dh));
  338. if (secret == NULL) {
  339. goto err;
  340. }
  341. secret_len = DH_compute_key(secret, peer_point, dh);
  342. if (secret_len <= 0) {
  343. goto err;
  344. }
  345. *out_secret = secret;
  346. *out_secret_len = (size_t)secret_len;
  347. BN_free(peer_point);
  348. return 1;
  349. err:
  350. if (secret_len > 0) {
  351. OPENSSL_cleanse(secret, (size_t)secret_len);
  352. }
  353. OPENSSL_free(secret);
  354. BN_free(peer_point);
  355. return 0;
  356. }
  357. static int ssl_dhe_accept(SSL_ECDH_CTX *ctx, CBB *out_public_key,
  358. uint8_t **out_secret, size_t *out_secret_len,
  359. uint8_t *out_alert, const uint8_t *peer_key,
  360. size_t peer_key_len) {
  361. *out_alert = SSL_AD_INTERNAL_ERROR;
  362. if (!ssl_dhe_offer(ctx, out_public_key) ||
  363. !ssl_dhe_finish(ctx, out_secret, out_secret_len, out_alert, peer_key,
  364. peer_key_len)) {
  365. return 0;
  366. }
  367. return 1;
  368. }
  369. static const SSL_ECDH_METHOD kDHEMethod = {
  370. NID_undef, 0, "",
  371. ssl_dhe_cleanup,
  372. ssl_dhe_offer,
  373. ssl_dhe_accept,
  374. ssl_dhe_finish,
  375. CBS_get_u16_length_prefixed,
  376. CBB_add_u16_length_prefixed,
  377. };
  378. static const SSL_ECDH_METHOD kCECPQ1Method = {
  379. NID_undef, 0, "",
  380. ssl_cecpq1_cleanup,
  381. ssl_cecpq1_offer,
  382. ssl_cecpq1_accept,
  383. ssl_cecpq1_finish,
  384. CBS_get_u16_length_prefixed,
  385. CBB_add_u16_length_prefixed,
  386. };
  387. static const SSL_ECDH_METHOD kMethods[] = {
  388. {
  389. NID_X9_62_prime256v1,
  390. SSL_CURVE_SECP256R1,
  391. "P-256",
  392. ssl_ec_point_cleanup,
  393. ssl_ec_point_offer,
  394. ssl_ec_point_accept,
  395. ssl_ec_point_finish,
  396. CBS_get_u8_length_prefixed,
  397. CBB_add_u8_length_prefixed,
  398. },
  399. {
  400. NID_secp384r1,
  401. SSL_CURVE_SECP384R1,
  402. "P-384",
  403. ssl_ec_point_cleanup,
  404. ssl_ec_point_offer,
  405. ssl_ec_point_accept,
  406. ssl_ec_point_finish,
  407. CBS_get_u8_length_prefixed,
  408. CBB_add_u8_length_prefixed,
  409. },
  410. {
  411. NID_secp521r1,
  412. SSL_CURVE_SECP521R1,
  413. "P-521",
  414. ssl_ec_point_cleanup,
  415. ssl_ec_point_offer,
  416. ssl_ec_point_accept,
  417. ssl_ec_point_finish,
  418. CBS_get_u8_length_prefixed,
  419. CBB_add_u8_length_prefixed,
  420. },
  421. {
  422. NID_X25519,
  423. SSL_CURVE_X25519,
  424. "X25519",
  425. ssl_x25519_cleanup,
  426. ssl_x25519_offer,
  427. ssl_x25519_accept,
  428. ssl_x25519_finish,
  429. CBS_get_u8_length_prefixed,
  430. CBB_add_u8_length_prefixed,
  431. },
  432. };
  433. static const SSL_ECDH_METHOD *method_from_group_id(uint16_t group_id) {
  434. for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kMethods); i++) {
  435. if (kMethods[i].group_id == group_id) {
  436. return &kMethods[i];
  437. }
  438. }
  439. return NULL;
  440. }
  441. static const SSL_ECDH_METHOD *method_from_nid(int nid) {
  442. for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kMethods); i++) {
  443. if (kMethods[i].nid == nid) {
  444. return &kMethods[i];
  445. }
  446. }
  447. return NULL;
  448. }
  449. static const SSL_ECDH_METHOD *method_from_name(const char *name, size_t len) {
  450. for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kMethods); i++) {
  451. if (len == strlen(kMethods[i].name) &&
  452. !strncmp(kMethods[i].name, name, len)) {
  453. return &kMethods[i];
  454. }
  455. }
  456. return NULL;
  457. }
  458. const char* SSL_get_curve_name(uint16_t group_id) {
  459. const SSL_ECDH_METHOD *method = method_from_group_id(group_id);
  460. if (method == NULL) {
  461. return NULL;
  462. }
  463. return method->name;
  464. }
  465. int ssl_nid_to_group_id(uint16_t *out_group_id, int nid) {
  466. const SSL_ECDH_METHOD *method = method_from_nid(nid);
  467. if (method == NULL) {
  468. return 0;
  469. }
  470. *out_group_id = method->group_id;
  471. return 1;
  472. }
  473. int ssl_name_to_group_id(uint16_t *out_group_id, const char *name, size_t len) {
  474. const SSL_ECDH_METHOD *method = method_from_name(name, len);
  475. if (method == NULL) {
  476. return 0;
  477. }
  478. *out_group_id = method->group_id;
  479. return 1;
  480. }
  481. int SSL_ECDH_CTX_init(SSL_ECDH_CTX *ctx, uint16_t group_id) {
  482. SSL_ECDH_CTX_cleanup(ctx);
  483. const SSL_ECDH_METHOD *method = method_from_group_id(group_id);
  484. if (method == NULL) {
  485. OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_ELLIPTIC_CURVE);
  486. return 0;
  487. }
  488. ctx->method = method;
  489. return 1;
  490. }
  491. void SSL_ECDH_CTX_init_for_dhe(SSL_ECDH_CTX *ctx, DH *params) {
  492. SSL_ECDH_CTX_cleanup(ctx);
  493. ctx->method = &kDHEMethod;
  494. ctx->data = params;
  495. }
  496. void SSL_ECDH_CTX_init_for_cecpq1(SSL_ECDH_CTX *ctx) {
  497. SSL_ECDH_CTX_cleanup(ctx);
  498. ctx->method = &kCECPQ1Method;
  499. }
  500. void SSL_ECDH_CTX_cleanup(SSL_ECDH_CTX *ctx) {
  501. if (ctx->method == NULL) {
  502. return;
  503. }
  504. ctx->method->cleanup(ctx);
  505. ctx->method = NULL;
  506. ctx->data = NULL;
  507. }
  508. uint16_t SSL_ECDH_CTX_get_id(const SSL_ECDH_CTX *ctx) {
  509. return ctx->method->group_id;
  510. }
  511. int SSL_ECDH_CTX_get_key(SSL_ECDH_CTX *ctx, CBS *cbs, CBS *out) {
  512. if (ctx->method == NULL) {
  513. return 0;
  514. }
  515. return ctx->method->get_key(cbs, out);
  516. }
  517. int SSL_ECDH_CTX_add_key(SSL_ECDH_CTX *ctx, CBB *cbb, CBB *out_contents) {
  518. if (ctx->method == NULL) {
  519. return 0;
  520. }
  521. return ctx->method->add_key(cbb, out_contents);
  522. }
  523. int SSL_ECDH_CTX_offer(SSL_ECDH_CTX *ctx, CBB *out_public_key) {
  524. return ctx->method->offer(ctx, out_public_key);
  525. }
  526. int SSL_ECDH_CTX_accept(SSL_ECDH_CTX *ctx, CBB *out_public_key,
  527. uint8_t **out_secret, size_t *out_secret_len,
  528. uint8_t *out_alert, const uint8_t *peer_key,
  529. size_t peer_key_len) {
  530. return ctx->method->accept(ctx, out_public_key, out_secret, out_secret_len,
  531. out_alert, peer_key, peer_key_len);
  532. }
  533. int SSL_ECDH_CTX_finish(SSL_ECDH_CTX *ctx, uint8_t **out_secret,
  534. size_t *out_secret_len, uint8_t *out_alert,
  535. const uint8_t *peer_key, size_t peer_key_len) {
  536. return ctx->method->finish(ctx, out_secret, out_secret_len, out_alert,
  537. peer_key, peer_key_len);
  538. }