|
|
|
/* Copyright (c) 2015, Google Inc.
|
|
|
|
*
|
|
|
|
* Permission to use, copy, modify, and/or distribute this software for any
|
|
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
|
|
* copyright notice and this permission notice appear in all copies.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
|
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
|
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
|
|
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
|
|
|
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
|
|
|
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
|
|
|
|
|
|
|
#include <openssl/ssl.h>
|
|
|
|
|
|
|
|
#include <assert.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include <utility>
|
|
|
|
|
|
|
|
#include <openssl/bn.h>
|
|
|
|
#include <openssl/bytestring.h>
|
|
|
|
#include <openssl/curve25519.h>
|
|
|
|
#include <openssl/ec.h>
|
|
|
|
#include <openssl/err.h>
|
|
|
|
#include <openssl/hrss.h>
|
|
|
|
#include <openssl/mem.h>
|
|
|
|
#include <openssl/nid.h>
|
|
|
|
#include <openssl/rand.h>
|
|
|
|
|
|
|
|
#include "internal.h"
|
|
|
|
#include "../crypto/internal.h"
|
|
|
|
|
|
|
|
BSSL_NAMESPACE_BEGIN
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
class ECKeyShare : public SSLKeyShare {
|
|
|
|
public:
|
|
|
|
ECKeyShare(int nid, uint16_t group_id)
|
|
|
|
: group_(EC_GROUP_new_by_curve_name(nid)), group_id_(group_id) {}
|
|
|
|
|
|
|
|
uint16_t GroupID() const override { return group_id_; }
|
|
|
|
|
Use KEM terminology in TLS ECDHE and key_share abstractions
TLS 1.2 ECDHE and TLS 1.3 key shares were originally designed around
Diffie-Hellman-like primitives and use language based on that.
Post-quantum replacements do not look like Diffie-Hellman, where each
part exchanges a public key, but schemes that work differently can still
slot in without protocol changes.
We previously came up with our own Offer/Accept/Finish abstraction for
early post-quantum experiments, but the NIST constructions are all
expressed as KEMs: First, the recipient generates a keypair and sends
the public key. Then the sender encapsulates a symmetric secret and
sends the ciphertext. Finally, the recipient decapsulates the ciphertext
to get the secret.
Align our C++ and Go abstractions to this terminology. The functions are
now called Generate/Encap/Decap, and the output of Encap is called
"ciphertext", which seems to align with what most folks use. (RFC 9180
uses "enc" for "encapsulated key", but they staple a KEM to an AEAD, so
"ciphertext" would be ambiguous.)
Where variable names refer to parts of the protocol, rather than the
the underlying KEM-like construction, I've kept variable names matching
the protocol mechanism, so we still talk about "curves" and "key
shares", but, when using the post-quantum replacements, the terminology
is no longer quite accurate.
I've also not yet renamed SSLKeyShare yet, though the name is now
inaccurate. Also ideally we'd touch that up so the stateful object is
just a KEM private key, for SSLKEMKey. Though at that point, we maybe
should just add EVP_KEM and EVP_KEM_KEY APIs to libcrypto.
Change-Id: Icbcc1840c5d2dfad210ef4caad2a7c4bf8146553
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/57726
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2 years ago
|
|
|
bool Generate(CBB *out) override {
|
|
|
|
assert(!private_key_);
|
|
|
|
// Generate a private key.
|
|
|
|
private_key_.reset(BN_new());
|
|
|
|
if (!group_ || !private_key_ ||
|
|
|
|
!BN_rand_range_ex(private_key_.get(), 1,
|
|
|
|
EC_GROUP_get0_order(group_))) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Compute the corresponding public key and serialize it.
|
|
|
|
UniquePtr<EC_POINT> public_key(EC_POINT_new(group_));
|
|
|
|
if (!public_key ||
|
|
|
|
!EC_POINT_mul(group_, public_key.get(), private_key_.get(),
|
|
|
|
nullptr, nullptr, /*ctx=*/nullptr) ||
|
|
|
|
!EC_POINT_point2cbb(out, group_, public_key.get(),
|
|
|
|
POINT_CONVERSION_UNCOMPRESSED, /*ctx=*/nullptr)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
Use KEM terminology in TLS ECDHE and key_share abstractions
TLS 1.2 ECDHE and TLS 1.3 key shares were originally designed around
Diffie-Hellman-like primitives and use language based on that.
Post-quantum replacements do not look like Diffie-Hellman, where each
part exchanges a public key, but schemes that work differently can still
slot in without protocol changes.
We previously came up with our own Offer/Accept/Finish abstraction for
early post-quantum experiments, but the NIST constructions are all
expressed as KEMs: First, the recipient generates a keypair and sends
the public key. Then the sender encapsulates a symmetric secret and
sends the ciphertext. Finally, the recipient decapsulates the ciphertext
to get the secret.
Align our C++ and Go abstractions to this terminology. The functions are
now called Generate/Encap/Decap, and the output of Encap is called
"ciphertext", which seems to align with what most folks use. (RFC 9180
uses "enc" for "encapsulated key", but they staple a KEM to an AEAD, so
"ciphertext" would be ambiguous.)
Where variable names refer to parts of the protocol, rather than the
the underlying KEM-like construction, I've kept variable names matching
the protocol mechanism, so we still talk about "curves" and "key
shares", but, when using the post-quantum replacements, the terminology
is no longer quite accurate.
I've also not yet renamed SSLKeyShare yet, though the name is now
inaccurate. Also ideally we'd touch that up so the stateful object is
just a KEM private key, for SSLKEMKey. Though at that point, we maybe
should just add EVP_KEM and EVP_KEM_KEY APIs to libcrypto.
Change-Id: Icbcc1840c5d2dfad210ef4caad2a7c4bf8146553
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/57726
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2 years ago
|
|
|
bool Encap(CBB *out_ciphertext, Array<uint8_t> *out_secret,
|
|
|
|
uint8_t *out_alert, Span<const uint8_t> peer_key) override {
|
|
|
|
// ECDH may be fit into a KEM-like abstraction by using a second keypair's
|
|
|
|
// public key as the ciphertext.
|
|
|
|
*out_alert = SSL_AD_INTERNAL_ERROR;
|
|
|
|
return Generate(out_ciphertext) && Decap(out_secret, out_alert, peer_key);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Decap(Array<uint8_t> *out_secret, uint8_t *out_alert,
|
|
|
|
Span<const uint8_t> ciphertext) override {
|
|
|
|
assert(group_);
|
|
|
|
assert(private_key_);
|
|
|
|
*out_alert = SSL_AD_INTERNAL_ERROR;
|
|
|
|
|
|
|
|
UniquePtr<EC_POINT> peer_point(EC_POINT_new(group_));
|
|
|
|
UniquePtr<EC_POINT> result(EC_POINT_new(group_));
|
|
|
|
UniquePtr<BIGNUM> x(BN_new());
|
|
|
|
if (!peer_point || !result || !x) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
Use KEM terminology in TLS ECDHE and key_share abstractions
TLS 1.2 ECDHE and TLS 1.3 key shares were originally designed around
Diffie-Hellman-like primitives and use language based on that.
Post-quantum replacements do not look like Diffie-Hellman, where each
part exchanges a public key, but schemes that work differently can still
slot in without protocol changes.
We previously came up with our own Offer/Accept/Finish abstraction for
early post-quantum experiments, but the NIST constructions are all
expressed as KEMs: First, the recipient generates a keypair and sends
the public key. Then the sender encapsulates a symmetric secret and
sends the ciphertext. Finally, the recipient decapsulates the ciphertext
to get the secret.
Align our C++ and Go abstractions to this terminology. The functions are
now called Generate/Encap/Decap, and the output of Encap is called
"ciphertext", which seems to align with what most folks use. (RFC 9180
uses "enc" for "encapsulated key", but they staple a KEM to an AEAD, so
"ciphertext" would be ambiguous.)
Where variable names refer to parts of the protocol, rather than the
the underlying KEM-like construction, I've kept variable names matching
the protocol mechanism, so we still talk about "curves" and "key
shares", but, when using the post-quantum replacements, the terminology
is no longer quite accurate.
I've also not yet renamed SSLKeyShare yet, though the name is now
inaccurate. Also ideally we'd touch that up so the stateful object is
just a KEM private key, for SSLKEMKey. Though at that point, we maybe
should just add EVP_KEM and EVP_KEM_KEY APIs to libcrypto.
Change-Id: Icbcc1840c5d2dfad210ef4caad2a7c4bf8146553
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/57726
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2 years ago
|
|
|
if (ciphertext.empty() || ciphertext[0] != POINT_CONVERSION_UNCOMPRESSED ||
|
|
|
|
!EC_POINT_oct2point(group_, peer_point.get(), ciphertext.data(),
|
|
|
|
ciphertext.size(), /*ctx=*/nullptr)) {
|
|
|
|
OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ECPOINT);
|
|
|
|
*out_alert = SSL_AD_DECODE_ERROR;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Compute the x-coordinate of |peer_key| * |private_key_|.
|
|
|
|
if (!EC_POINT_mul(group_, result.get(), NULL, peer_point.get(),
|
|
|
|
private_key_.get(), /*ctx=*/nullptr) ||
|
|
|
|
!EC_POINT_get_affine_coordinates_GFp(group_, result.get(), x.get(),
|
|
|
|
NULL,
|
|
|
|
/*ctx=*/nullptr)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Encode the x-coordinate left-padded with zeros.
|
|
|
|
Array<uint8_t> secret;
|
|
|
|
if (!secret.Init((EC_GROUP_get_degree(group_) + 7) / 8) ||
|
|
|
|
!BN_bn2bin_padded(secret.data(), secret.size(), x.get())) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
*out_secret = std::move(secret);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SerializePrivateKey(CBB *out) override {
|
|
|
|
assert(group_);
|
|
|
|
assert(private_key_);
|
|
|
|
// Padding is added to avoid leaking the length.
|
|
|
|
size_t len = BN_num_bytes(EC_GROUP_get0_order(group_));
|
|
|
|
return BN_bn2cbb_padded(out, len, private_key_.get());
|
|
|
|
}
|
|
|
|
|
|
|
|
bool DeserializePrivateKey(CBS *in) override {
|
|
|
|
assert(!private_key_);
|
|
|
|
private_key_.reset(BN_bin2bn(CBS_data(in), CBS_len(in), nullptr));
|
|
|
|
return private_key_ != nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
UniquePtr<BIGNUM> private_key_;
|
|
|
|
const EC_GROUP *const group_ = nullptr;
|
|
|
|
uint16_t group_id_;
|
|
|
|
};
|
|
|
|
|
|
|
|
class X25519KeyShare : public SSLKeyShare {
|
|
|
|
public:
|
|
|
|
X25519KeyShare() {}
|
|
|
|
|
|
|
|
uint16_t GroupID() const override { return SSL_CURVE_X25519; }
|
|
|
|
|
Use KEM terminology in TLS ECDHE and key_share abstractions
TLS 1.2 ECDHE and TLS 1.3 key shares were originally designed around
Diffie-Hellman-like primitives and use language based on that.
Post-quantum replacements do not look like Diffie-Hellman, where each
part exchanges a public key, but schemes that work differently can still
slot in without protocol changes.
We previously came up with our own Offer/Accept/Finish abstraction for
early post-quantum experiments, but the NIST constructions are all
expressed as KEMs: First, the recipient generates a keypair and sends
the public key. Then the sender encapsulates a symmetric secret and
sends the ciphertext. Finally, the recipient decapsulates the ciphertext
to get the secret.
Align our C++ and Go abstractions to this terminology. The functions are
now called Generate/Encap/Decap, and the output of Encap is called
"ciphertext", which seems to align with what most folks use. (RFC 9180
uses "enc" for "encapsulated key", but they staple a KEM to an AEAD, so
"ciphertext" would be ambiguous.)
Where variable names refer to parts of the protocol, rather than the
the underlying KEM-like construction, I've kept variable names matching
the protocol mechanism, so we still talk about "curves" and "key
shares", but, when using the post-quantum replacements, the terminology
is no longer quite accurate.
I've also not yet renamed SSLKeyShare yet, though the name is now
inaccurate. Also ideally we'd touch that up so the stateful object is
just a KEM private key, for SSLKEMKey. Though at that point, we maybe
should just add EVP_KEM and EVP_KEM_KEY APIs to libcrypto.
Change-Id: Icbcc1840c5d2dfad210ef4caad2a7c4bf8146553
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/57726
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2 years ago
|
|
|
bool Generate(CBB *out) override {
|
|
|
|
uint8_t public_key[32];
|
|
|
|
X25519_keypair(public_key, private_key_);
|
|
|
|
return !!CBB_add_bytes(out, public_key, sizeof(public_key));
|
|
|
|
}
|
|
|
|
|
Use KEM terminology in TLS ECDHE and key_share abstractions
TLS 1.2 ECDHE and TLS 1.3 key shares were originally designed around
Diffie-Hellman-like primitives and use language based on that.
Post-quantum replacements do not look like Diffie-Hellman, where each
part exchanges a public key, but schemes that work differently can still
slot in without protocol changes.
We previously came up with our own Offer/Accept/Finish abstraction for
early post-quantum experiments, but the NIST constructions are all
expressed as KEMs: First, the recipient generates a keypair and sends
the public key. Then the sender encapsulates a symmetric secret and
sends the ciphertext. Finally, the recipient decapsulates the ciphertext
to get the secret.
Align our C++ and Go abstractions to this terminology. The functions are
now called Generate/Encap/Decap, and the output of Encap is called
"ciphertext", which seems to align with what most folks use. (RFC 9180
uses "enc" for "encapsulated key", but they staple a KEM to an AEAD, so
"ciphertext" would be ambiguous.)
Where variable names refer to parts of the protocol, rather than the
the underlying KEM-like construction, I've kept variable names matching
the protocol mechanism, so we still talk about "curves" and "key
shares", but, when using the post-quantum replacements, the terminology
is no longer quite accurate.
I've also not yet renamed SSLKeyShare yet, though the name is now
inaccurate. Also ideally we'd touch that up so the stateful object is
just a KEM private key, for SSLKEMKey. Though at that point, we maybe
should just add EVP_KEM and EVP_KEM_KEY APIs to libcrypto.
Change-Id: Icbcc1840c5d2dfad210ef4caad2a7c4bf8146553
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/57726
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2 years ago
|
|
|
bool Encap(CBB *out_ciphertext, Array<uint8_t> *out_secret,
|
|
|
|
uint8_t *out_alert, Span<const uint8_t> peer_key) override {
|
|
|
|
// X25519 may be fit into a KEM-like abstraction by using a second keypair's
|
|
|
|
// public key as the ciphertext.
|
|
|
|
*out_alert = SSL_AD_INTERNAL_ERROR;
|
|
|
|
return Generate(out_ciphertext) && Decap(out_secret, out_alert, peer_key);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Decap(Array<uint8_t> *out_secret, uint8_t *out_alert,
|
|
|
|
Span<const uint8_t> ciphertext) override {
|
|
|
|
*out_alert = SSL_AD_INTERNAL_ERROR;
|
|
|
|
|
|
|
|
Array<uint8_t> secret;
|
|
|
|
if (!secret.Init(32)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
Use KEM terminology in TLS ECDHE and key_share abstractions
TLS 1.2 ECDHE and TLS 1.3 key shares were originally designed around
Diffie-Hellman-like primitives and use language based on that.
Post-quantum replacements do not look like Diffie-Hellman, where each
part exchanges a public key, but schemes that work differently can still
slot in without protocol changes.
We previously came up with our own Offer/Accept/Finish abstraction for
early post-quantum experiments, but the NIST constructions are all
expressed as KEMs: First, the recipient generates a keypair and sends
the public key. Then the sender encapsulates a symmetric secret and
sends the ciphertext. Finally, the recipient decapsulates the ciphertext
to get the secret.
Align our C++ and Go abstractions to this terminology. The functions are
now called Generate/Encap/Decap, and the output of Encap is called
"ciphertext", which seems to align with what most folks use. (RFC 9180
uses "enc" for "encapsulated key", but they staple a KEM to an AEAD, so
"ciphertext" would be ambiguous.)
Where variable names refer to parts of the protocol, rather than the
the underlying KEM-like construction, I've kept variable names matching
the protocol mechanism, so we still talk about "curves" and "key
shares", but, when using the post-quantum replacements, the terminology
is no longer quite accurate.
I've also not yet renamed SSLKeyShare yet, though the name is now
inaccurate. Also ideally we'd touch that up so the stateful object is
just a KEM private key, for SSLKEMKey. Though at that point, we maybe
should just add EVP_KEM and EVP_KEM_KEY APIs to libcrypto.
Change-Id: Icbcc1840c5d2dfad210ef4caad2a7c4bf8146553
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/57726
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2 years ago
|
|
|
if (ciphertext.size() != 32 || //
|
|
|
|
!X25519(secret.data(), private_key_, ciphertext.data())) {
|
|
|
|
*out_alert = SSL_AD_DECODE_ERROR;
|
|
|
|
OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ECPOINT);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
*out_secret = std::move(secret);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SerializePrivateKey(CBB *out) override {
|
|
|
|
return CBB_add_bytes(out, private_key_, sizeof(private_key_));
|
|
|
|
}
|
|
|
|
|
|
|
|
bool DeserializePrivateKey(CBS *in) override {
|
|
|
|
if (CBS_len(in) != sizeof(private_key_) ||
|
|
|
|
!CBS_copy_bytes(in, private_key_, sizeof(private_key_))) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
uint8_t private_key_[32];
|
|
|
|
};
|
|
|
|
|
|
|
|
class CECPQ2KeyShare : public SSLKeyShare {
|
|
|
|
public:
|
|
|
|
CECPQ2KeyShare() {}
|
|
|
|
|
|
|
|
uint16_t GroupID() const override { return SSL_CURVE_CECPQ2; }
|
|
|
|
|
Use KEM terminology in TLS ECDHE and key_share abstractions
TLS 1.2 ECDHE and TLS 1.3 key shares were originally designed around
Diffie-Hellman-like primitives and use language based on that.
Post-quantum replacements do not look like Diffie-Hellman, where each
part exchanges a public key, but schemes that work differently can still
slot in without protocol changes.
We previously came up with our own Offer/Accept/Finish abstraction for
early post-quantum experiments, but the NIST constructions are all
expressed as KEMs: First, the recipient generates a keypair and sends
the public key. Then the sender encapsulates a symmetric secret and
sends the ciphertext. Finally, the recipient decapsulates the ciphertext
to get the secret.
Align our C++ and Go abstractions to this terminology. The functions are
now called Generate/Encap/Decap, and the output of Encap is called
"ciphertext", which seems to align with what most folks use. (RFC 9180
uses "enc" for "encapsulated key", but they staple a KEM to an AEAD, so
"ciphertext" would be ambiguous.)
Where variable names refer to parts of the protocol, rather than the
the underlying KEM-like construction, I've kept variable names matching
the protocol mechanism, so we still talk about "curves" and "key
shares", but, when using the post-quantum replacements, the terminology
is no longer quite accurate.
I've also not yet renamed SSLKeyShare yet, though the name is now
inaccurate. Also ideally we'd touch that up so the stateful object is
just a KEM private key, for SSLKEMKey. Though at that point, we maybe
should just add EVP_KEM and EVP_KEM_KEY APIs to libcrypto.
Change-Id: Icbcc1840c5d2dfad210ef4caad2a7c4bf8146553
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/57726
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2 years ago
|
|
|
bool Generate(CBB *out) override {
|
|
|
|
uint8_t x25519_public_key[32];
|
|
|
|
X25519_keypair(x25519_public_key, x25519_private_key_);
|
|
|
|
|
|
|
|
uint8_t hrss_entropy[HRSS_GENERATE_KEY_BYTES];
|
|
|
|
HRSS_public_key hrss_public_key;
|
|
|
|
RAND_bytes(hrss_entropy, sizeof(hrss_entropy));
|
|
|
|
if (!HRSS_generate_key(&hrss_public_key, &hrss_private_key_,
|
|
|
|
hrss_entropy)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t hrss_public_key_bytes[HRSS_PUBLIC_KEY_BYTES];
|
|
|
|
HRSS_marshal_public_key(hrss_public_key_bytes, &hrss_public_key);
|
|
|
|
|
|
|
|
if (!CBB_add_bytes(out, x25519_public_key, sizeof(x25519_public_key)) ||
|
|
|
|
!CBB_add_bytes(out, hrss_public_key_bytes,
|
|
|
|
sizeof(hrss_public_key_bytes))) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
Use KEM terminology in TLS ECDHE and key_share abstractions
TLS 1.2 ECDHE and TLS 1.3 key shares were originally designed around
Diffie-Hellman-like primitives and use language based on that.
Post-quantum replacements do not look like Diffie-Hellman, where each
part exchanges a public key, but schemes that work differently can still
slot in without protocol changes.
We previously came up with our own Offer/Accept/Finish abstraction for
early post-quantum experiments, but the NIST constructions are all
expressed as KEMs: First, the recipient generates a keypair and sends
the public key. Then the sender encapsulates a symmetric secret and
sends the ciphertext. Finally, the recipient decapsulates the ciphertext
to get the secret.
Align our C++ and Go abstractions to this terminology. The functions are
now called Generate/Encap/Decap, and the output of Encap is called
"ciphertext", which seems to align with what most folks use. (RFC 9180
uses "enc" for "encapsulated key", but they staple a KEM to an AEAD, so
"ciphertext" would be ambiguous.)
Where variable names refer to parts of the protocol, rather than the
the underlying KEM-like construction, I've kept variable names matching
the protocol mechanism, so we still talk about "curves" and "key
shares", but, when using the post-quantum replacements, the terminology
is no longer quite accurate.
I've also not yet renamed SSLKeyShare yet, though the name is now
inaccurate. Also ideally we'd touch that up so the stateful object is
just a KEM private key, for SSLKEMKey. Though at that point, we maybe
should just add EVP_KEM and EVP_KEM_KEY APIs to libcrypto.
Change-Id: Icbcc1840c5d2dfad210ef4caad2a7c4bf8146553
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/57726
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2 years ago
|
|
|
bool Encap(CBB *out_ciphertext, Array<uint8_t> *out_secret,
|
|
|
|
uint8_t *out_alert, Span<const uint8_t> peer_key) override {
|
|
|
|
Array<uint8_t> secret;
|
|
|
|
if (!secret.Init(32 + HRSS_KEY_BYTES)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t x25519_public_key[32];
|
|
|
|
X25519_keypair(x25519_public_key, x25519_private_key_);
|
|
|
|
|
|
|
|
HRSS_public_key peer_public_key;
|
|
|
|
if (peer_key.size() != 32 + HRSS_PUBLIC_KEY_BYTES ||
|
|
|
|
!HRSS_parse_public_key(&peer_public_key, peer_key.data() + 32) ||
|
|
|
|
!X25519(secret.data(), x25519_private_key_, peer_key.data())) {
|
|
|
|
*out_alert = SSL_AD_DECODE_ERROR;
|
|
|
|
OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ECPOINT);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t ciphertext[HRSS_CIPHERTEXT_BYTES];
|
|
|
|
uint8_t entropy[HRSS_ENCAP_BYTES];
|
|
|
|
RAND_bytes(entropy, sizeof(entropy));
|
|
|
|
|
|
|
|
if (!HRSS_encap(ciphertext, secret.data() + 32, &peer_public_key,
|
|
|
|
entropy) ||
|
Use KEM terminology in TLS ECDHE and key_share abstractions
TLS 1.2 ECDHE and TLS 1.3 key shares were originally designed around
Diffie-Hellman-like primitives and use language based on that.
Post-quantum replacements do not look like Diffie-Hellman, where each
part exchanges a public key, but schemes that work differently can still
slot in without protocol changes.
We previously came up with our own Offer/Accept/Finish abstraction for
early post-quantum experiments, but the NIST constructions are all
expressed as KEMs: First, the recipient generates a keypair and sends
the public key. Then the sender encapsulates a symmetric secret and
sends the ciphertext. Finally, the recipient decapsulates the ciphertext
to get the secret.
Align our C++ and Go abstractions to this terminology. The functions are
now called Generate/Encap/Decap, and the output of Encap is called
"ciphertext", which seems to align with what most folks use. (RFC 9180
uses "enc" for "encapsulated key", but they staple a KEM to an AEAD, so
"ciphertext" would be ambiguous.)
Where variable names refer to parts of the protocol, rather than the
the underlying KEM-like construction, I've kept variable names matching
the protocol mechanism, so we still talk about "curves" and "key
shares", but, when using the post-quantum replacements, the terminology
is no longer quite accurate.
I've also not yet renamed SSLKeyShare yet, though the name is now
inaccurate. Also ideally we'd touch that up so the stateful object is
just a KEM private key, for SSLKEMKey. Though at that point, we maybe
should just add EVP_KEM and EVP_KEM_KEY APIs to libcrypto.
Change-Id: Icbcc1840c5d2dfad210ef4caad2a7c4bf8146553
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/57726
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2 years ago
|
|
|
!CBB_add_bytes(out_ciphertext, x25519_public_key,
|
|
|
|
sizeof(x25519_public_key)) ||
|
Use KEM terminology in TLS ECDHE and key_share abstractions
TLS 1.2 ECDHE and TLS 1.3 key shares were originally designed around
Diffie-Hellman-like primitives and use language based on that.
Post-quantum replacements do not look like Diffie-Hellman, where each
part exchanges a public key, but schemes that work differently can still
slot in without protocol changes.
We previously came up with our own Offer/Accept/Finish abstraction for
early post-quantum experiments, but the NIST constructions are all
expressed as KEMs: First, the recipient generates a keypair and sends
the public key. Then the sender encapsulates a symmetric secret and
sends the ciphertext. Finally, the recipient decapsulates the ciphertext
to get the secret.
Align our C++ and Go abstractions to this terminology. The functions are
now called Generate/Encap/Decap, and the output of Encap is called
"ciphertext", which seems to align with what most folks use. (RFC 9180
uses "enc" for "encapsulated key", but they staple a KEM to an AEAD, so
"ciphertext" would be ambiguous.)
Where variable names refer to parts of the protocol, rather than the
the underlying KEM-like construction, I've kept variable names matching
the protocol mechanism, so we still talk about "curves" and "key
shares", but, when using the post-quantum replacements, the terminology
is no longer quite accurate.
I've also not yet renamed SSLKeyShare yet, though the name is now
inaccurate. Also ideally we'd touch that up so the stateful object is
just a KEM private key, for SSLKEMKey. Though at that point, we maybe
should just add EVP_KEM and EVP_KEM_KEY APIs to libcrypto.
Change-Id: Icbcc1840c5d2dfad210ef4caad2a7c4bf8146553
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/57726
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2 years ago
|
|
|
!CBB_add_bytes(out_ciphertext, ciphertext, sizeof(ciphertext))) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
*out_secret = std::move(secret);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
Use KEM terminology in TLS ECDHE and key_share abstractions
TLS 1.2 ECDHE and TLS 1.3 key shares were originally designed around
Diffie-Hellman-like primitives and use language based on that.
Post-quantum replacements do not look like Diffie-Hellman, where each
part exchanges a public key, but schemes that work differently can still
slot in without protocol changes.
We previously came up with our own Offer/Accept/Finish abstraction for
early post-quantum experiments, but the NIST constructions are all
expressed as KEMs: First, the recipient generates a keypair and sends
the public key. Then the sender encapsulates a symmetric secret and
sends the ciphertext. Finally, the recipient decapsulates the ciphertext
to get the secret.
Align our C++ and Go abstractions to this terminology. The functions are
now called Generate/Encap/Decap, and the output of Encap is called
"ciphertext", which seems to align with what most folks use. (RFC 9180
uses "enc" for "encapsulated key", but they staple a KEM to an AEAD, so
"ciphertext" would be ambiguous.)
Where variable names refer to parts of the protocol, rather than the
the underlying KEM-like construction, I've kept variable names matching
the protocol mechanism, so we still talk about "curves" and "key
shares", but, when using the post-quantum replacements, the terminology
is no longer quite accurate.
I've also not yet renamed SSLKeyShare yet, though the name is now
inaccurate. Also ideally we'd touch that up so the stateful object is
just a KEM private key, for SSLKEMKey. Though at that point, we maybe
should just add EVP_KEM and EVP_KEM_KEY APIs to libcrypto.
Change-Id: Icbcc1840c5d2dfad210ef4caad2a7c4bf8146553
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/57726
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2 years ago
|
|
|
bool Decap(Array<uint8_t> *out_secret, uint8_t *out_alert,
|
|
|
|
Span<const uint8_t> ciphertext) override {
|
|
|
|
*out_alert = SSL_AD_INTERNAL_ERROR;
|
|
|
|
|
|
|
|
Array<uint8_t> secret;
|
|
|
|
if (!secret.Init(32 + HRSS_KEY_BYTES)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
Use KEM terminology in TLS ECDHE and key_share abstractions
TLS 1.2 ECDHE and TLS 1.3 key shares were originally designed around
Diffie-Hellman-like primitives and use language based on that.
Post-quantum replacements do not look like Diffie-Hellman, where each
part exchanges a public key, but schemes that work differently can still
slot in without protocol changes.
We previously came up with our own Offer/Accept/Finish abstraction for
early post-quantum experiments, but the NIST constructions are all
expressed as KEMs: First, the recipient generates a keypair and sends
the public key. Then the sender encapsulates a symmetric secret and
sends the ciphertext. Finally, the recipient decapsulates the ciphertext
to get the secret.
Align our C++ and Go abstractions to this terminology. The functions are
now called Generate/Encap/Decap, and the output of Encap is called
"ciphertext", which seems to align with what most folks use. (RFC 9180
uses "enc" for "encapsulated key", but they staple a KEM to an AEAD, so
"ciphertext" would be ambiguous.)
Where variable names refer to parts of the protocol, rather than the
the underlying KEM-like construction, I've kept variable names matching
the protocol mechanism, so we still talk about "curves" and "key
shares", but, when using the post-quantum replacements, the terminology
is no longer quite accurate.
I've also not yet renamed SSLKeyShare yet, though the name is now
inaccurate. Also ideally we'd touch that up so the stateful object is
just a KEM private key, for SSLKEMKey. Though at that point, we maybe
should just add EVP_KEM and EVP_KEM_KEY APIs to libcrypto.
Change-Id: Icbcc1840c5d2dfad210ef4caad2a7c4bf8146553
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/57726
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2 years ago
|
|
|
if (ciphertext.size() != 32 + HRSS_CIPHERTEXT_BYTES ||
|
|
|
|
!X25519(secret.data(), x25519_private_key_, ciphertext.data())) {
|
|
|
|
*out_alert = SSL_AD_DECODE_ERROR;
|
|
|
|
OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ECPOINT);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!HRSS_decap(secret.data() + 32, &hrss_private_key_,
|
Use KEM terminology in TLS ECDHE and key_share abstractions
TLS 1.2 ECDHE and TLS 1.3 key shares were originally designed around
Diffie-Hellman-like primitives and use language based on that.
Post-quantum replacements do not look like Diffie-Hellman, where each
part exchanges a public key, but schemes that work differently can still
slot in without protocol changes.
We previously came up with our own Offer/Accept/Finish abstraction for
early post-quantum experiments, but the NIST constructions are all
expressed as KEMs: First, the recipient generates a keypair and sends
the public key. Then the sender encapsulates a symmetric secret and
sends the ciphertext. Finally, the recipient decapsulates the ciphertext
to get the secret.
Align our C++ and Go abstractions to this terminology. The functions are
now called Generate/Encap/Decap, and the output of Encap is called
"ciphertext", which seems to align with what most folks use. (RFC 9180
uses "enc" for "encapsulated key", but they staple a KEM to an AEAD, so
"ciphertext" would be ambiguous.)
Where variable names refer to parts of the protocol, rather than the
the underlying KEM-like construction, I've kept variable names matching
the protocol mechanism, so we still talk about "curves" and "key
shares", but, when using the post-quantum replacements, the terminology
is no longer quite accurate.
I've also not yet renamed SSLKeyShare yet, though the name is now
inaccurate. Also ideally we'd touch that up so the stateful object is
just a KEM private key, for SSLKEMKey. Though at that point, we maybe
should just add EVP_KEM and EVP_KEM_KEY APIs to libcrypto.
Change-Id: Icbcc1840c5d2dfad210ef4caad2a7c4bf8146553
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/57726
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2 years ago
|
|
|
ciphertext.data() + 32, ciphertext.size() - 32)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
*out_secret = std::move(secret);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
uint8_t x25519_private_key_[32];
|
|
|
|
HRSS_private_key hrss_private_key_;
|
|
|
|
};
|
|
|
|
|
|
|
|
class X25519Kyber768KeyShare : public SSLKeyShare {
|
|
|
|
public:
|
|
|
|
X25519Kyber768KeyShare() {}
|
|
|
|
|
|
|
|
uint16_t GroupID() const override { return SSL_CURVE_X25519KYBER768; }
|
|
|
|
|
Use KEM terminology in TLS ECDHE and key_share abstractions
TLS 1.2 ECDHE and TLS 1.3 key shares were originally designed around
Diffie-Hellman-like primitives and use language based on that.
Post-quantum replacements do not look like Diffie-Hellman, where each
part exchanges a public key, but schemes that work differently can still
slot in without protocol changes.
We previously came up with our own Offer/Accept/Finish abstraction for
early post-quantum experiments, but the NIST constructions are all
expressed as KEMs: First, the recipient generates a keypair and sends
the public key. Then the sender encapsulates a symmetric secret and
sends the ciphertext. Finally, the recipient decapsulates the ciphertext
to get the secret.
Align our C++ and Go abstractions to this terminology. The functions are
now called Generate/Encap/Decap, and the output of Encap is called
"ciphertext", which seems to align with what most folks use. (RFC 9180
uses "enc" for "encapsulated key", but they staple a KEM to an AEAD, so
"ciphertext" would be ambiguous.)
Where variable names refer to parts of the protocol, rather than the
the underlying KEM-like construction, I've kept variable names matching
the protocol mechanism, so we still talk about "curves" and "key
shares", but, when using the post-quantum replacements, the terminology
is no longer quite accurate.
I've also not yet renamed SSLKeyShare yet, though the name is now
inaccurate. Also ideally we'd touch that up so the stateful object is
just a KEM private key, for SSLKEMKey. Though at that point, we maybe
should just add EVP_KEM and EVP_KEM_KEY APIs to libcrypto.
Change-Id: Icbcc1840c5d2dfad210ef4caad2a7c4bf8146553
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/57726
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2 years ago
|
|
|
bool Generate(CBB *out) override {
|
|
|
|
// There is no implementation on Kyber in BoringSSL. BoringSSL must be
|
Use KEM terminology in TLS ECDHE and key_share abstractions
TLS 1.2 ECDHE and TLS 1.3 key shares were originally designed around
Diffie-Hellman-like primitives and use language based on that.
Post-quantum replacements do not look like Diffie-Hellman, where each
part exchanges a public key, but schemes that work differently can still
slot in without protocol changes.
We previously came up with our own Offer/Accept/Finish abstraction for
early post-quantum experiments, but the NIST constructions are all
expressed as KEMs: First, the recipient generates a keypair and sends
the public key. Then the sender encapsulates a symmetric secret and
sends the ciphertext. Finally, the recipient decapsulates the ciphertext
to get the secret.
Align our C++ and Go abstractions to this terminology. The functions are
now called Generate/Encap/Decap, and the output of Encap is called
"ciphertext", which seems to align with what most folks use. (RFC 9180
uses "enc" for "encapsulated key", but they staple a KEM to an AEAD, so
"ciphertext" would be ambiguous.)
Where variable names refer to parts of the protocol, rather than the
the underlying KEM-like construction, I've kept variable names matching
the protocol mechanism, so we still talk about "curves" and "key
shares", but, when using the post-quantum replacements, the terminology
is no longer quite accurate.
I've also not yet renamed SSLKeyShare yet, though the name is now
inaccurate. Also ideally we'd touch that up so the stateful object is
just a KEM private key, for SSLKEMKey. Though at that point, we maybe
should just add EVP_KEM and EVP_KEM_KEY APIs to libcrypto.
Change-Id: Icbcc1840c5d2dfad210ef4caad2a7c4bf8146553
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/57726
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2 years ago
|
|
|
// patched for this KEM to be workable. It is not enabled by default.
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
Use KEM terminology in TLS ECDHE and key_share abstractions
TLS 1.2 ECDHE and TLS 1.3 key shares were originally designed around
Diffie-Hellman-like primitives and use language based on that.
Post-quantum replacements do not look like Diffie-Hellman, where each
part exchanges a public key, but schemes that work differently can still
slot in without protocol changes.
We previously came up with our own Offer/Accept/Finish abstraction for
early post-quantum experiments, but the NIST constructions are all
expressed as KEMs: First, the recipient generates a keypair and sends
the public key. Then the sender encapsulates a symmetric secret and
sends the ciphertext. Finally, the recipient decapsulates the ciphertext
to get the secret.
Align our C++ and Go abstractions to this terminology. The functions are
now called Generate/Encap/Decap, and the output of Encap is called
"ciphertext", which seems to align with what most folks use. (RFC 9180
uses "enc" for "encapsulated key", but they staple a KEM to an AEAD, so
"ciphertext" would be ambiguous.)
Where variable names refer to parts of the protocol, rather than the
the underlying KEM-like construction, I've kept variable names matching
the protocol mechanism, so we still talk about "curves" and "key
shares", but, when using the post-quantum replacements, the terminology
is no longer quite accurate.
I've also not yet renamed SSLKeyShare yet, though the name is now
inaccurate. Also ideally we'd touch that up so the stateful object is
just a KEM private key, for SSLKEMKey. Though at that point, we maybe
should just add EVP_KEM and EVP_KEM_KEY APIs to libcrypto.
Change-Id: Icbcc1840c5d2dfad210ef4caad2a7c4bf8146553
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/57726
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2 years ago
|
|
|
bool Encap(CBB *out_ciphertext, Array<uint8_t> *out_secret,
|
|
|
|
uint8_t *out_alert, Span<const uint8_t> peer_key) override {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
Use KEM terminology in TLS ECDHE and key_share abstractions
TLS 1.2 ECDHE and TLS 1.3 key shares were originally designed around
Diffie-Hellman-like primitives and use language based on that.
Post-quantum replacements do not look like Diffie-Hellman, where each
part exchanges a public key, but schemes that work differently can still
slot in without protocol changes.
We previously came up with our own Offer/Accept/Finish abstraction for
early post-quantum experiments, but the NIST constructions are all
expressed as KEMs: First, the recipient generates a keypair and sends
the public key. Then the sender encapsulates a symmetric secret and
sends the ciphertext. Finally, the recipient decapsulates the ciphertext
to get the secret.
Align our C++ and Go abstractions to this terminology. The functions are
now called Generate/Encap/Decap, and the output of Encap is called
"ciphertext", which seems to align with what most folks use. (RFC 9180
uses "enc" for "encapsulated key", but they staple a KEM to an AEAD, so
"ciphertext" would be ambiguous.)
Where variable names refer to parts of the protocol, rather than the
the underlying KEM-like construction, I've kept variable names matching
the protocol mechanism, so we still talk about "curves" and "key
shares", but, when using the post-quantum replacements, the terminology
is no longer quite accurate.
I've also not yet renamed SSLKeyShare yet, though the name is now
inaccurate. Also ideally we'd touch that up so the stateful object is
just a KEM private key, for SSLKEMKey. Though at that point, we maybe
should just add EVP_KEM and EVP_KEM_KEY APIs to libcrypto.
Change-Id: Icbcc1840c5d2dfad210ef4caad2a7c4bf8146553
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/57726
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2 years ago
|
|
|
bool Decap(Array<uint8_t> *out_secret, uint8_t *out_alert,
|
|
|
|
Span<const uint8_t> ciphertext) override {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class P256Kyber768KeyShare : public SSLKeyShare {
|
|
|
|
public:
|
|
|
|
P256Kyber768KeyShare() {}
|
|
|
|
|
|
|
|
uint16_t GroupID() const override { return SSL_CURVE_P256KYBER768; }
|
|
|
|
|
Use KEM terminology in TLS ECDHE and key_share abstractions
TLS 1.2 ECDHE and TLS 1.3 key shares were originally designed around
Diffie-Hellman-like primitives and use language based on that.
Post-quantum replacements do not look like Diffie-Hellman, where each
part exchanges a public key, but schemes that work differently can still
slot in without protocol changes.
We previously came up with our own Offer/Accept/Finish abstraction for
early post-quantum experiments, but the NIST constructions are all
expressed as KEMs: First, the recipient generates a keypair and sends
the public key. Then the sender encapsulates a symmetric secret and
sends the ciphertext. Finally, the recipient decapsulates the ciphertext
to get the secret.
Align our C++ and Go abstractions to this terminology. The functions are
now called Generate/Encap/Decap, and the output of Encap is called
"ciphertext", which seems to align with what most folks use. (RFC 9180
uses "enc" for "encapsulated key", but they staple a KEM to an AEAD, so
"ciphertext" would be ambiguous.)
Where variable names refer to parts of the protocol, rather than the
the underlying KEM-like construction, I've kept variable names matching
the protocol mechanism, so we still talk about "curves" and "key
shares", but, when using the post-quantum replacements, the terminology
is no longer quite accurate.
I've also not yet renamed SSLKeyShare yet, though the name is now
inaccurate. Also ideally we'd touch that up so the stateful object is
just a KEM private key, for SSLKEMKey. Though at that point, we maybe
should just add EVP_KEM and EVP_KEM_KEY APIs to libcrypto.
Change-Id: Icbcc1840c5d2dfad210ef4caad2a7c4bf8146553
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/57726
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2 years ago
|
|
|
bool Generate(CBB *out) override {
|
|
|
|
// There is no implementation on Kyber in BoringSSL. BoringSSL must be
|
Use KEM terminology in TLS ECDHE and key_share abstractions
TLS 1.2 ECDHE and TLS 1.3 key shares were originally designed around
Diffie-Hellman-like primitives and use language based on that.
Post-quantum replacements do not look like Diffie-Hellman, where each
part exchanges a public key, but schemes that work differently can still
slot in without protocol changes.
We previously came up with our own Offer/Accept/Finish abstraction for
early post-quantum experiments, but the NIST constructions are all
expressed as KEMs: First, the recipient generates a keypair and sends
the public key. Then the sender encapsulates a symmetric secret and
sends the ciphertext. Finally, the recipient decapsulates the ciphertext
to get the secret.
Align our C++ and Go abstractions to this terminology. The functions are
now called Generate/Encap/Decap, and the output of Encap is called
"ciphertext", which seems to align with what most folks use. (RFC 9180
uses "enc" for "encapsulated key", but they staple a KEM to an AEAD, so
"ciphertext" would be ambiguous.)
Where variable names refer to parts of the protocol, rather than the
the underlying KEM-like construction, I've kept variable names matching
the protocol mechanism, so we still talk about "curves" and "key
shares", but, when using the post-quantum replacements, the terminology
is no longer quite accurate.
I've also not yet renamed SSLKeyShare yet, though the name is now
inaccurate. Also ideally we'd touch that up so the stateful object is
just a KEM private key, for SSLKEMKey. Though at that point, we maybe
should just add EVP_KEM and EVP_KEM_KEY APIs to libcrypto.
Change-Id: Icbcc1840c5d2dfad210ef4caad2a7c4bf8146553
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/57726
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2 years ago
|
|
|
// patched for this KEM to be workable. It is not enabled by default.
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
Use KEM terminology in TLS ECDHE and key_share abstractions
TLS 1.2 ECDHE and TLS 1.3 key shares were originally designed around
Diffie-Hellman-like primitives and use language based on that.
Post-quantum replacements do not look like Diffie-Hellman, where each
part exchanges a public key, but schemes that work differently can still
slot in without protocol changes.
We previously came up with our own Offer/Accept/Finish abstraction for
early post-quantum experiments, but the NIST constructions are all
expressed as KEMs: First, the recipient generates a keypair and sends
the public key. Then the sender encapsulates a symmetric secret and
sends the ciphertext. Finally, the recipient decapsulates the ciphertext
to get the secret.
Align our C++ and Go abstractions to this terminology. The functions are
now called Generate/Encap/Decap, and the output of Encap is called
"ciphertext", which seems to align with what most folks use. (RFC 9180
uses "enc" for "encapsulated key", but they staple a KEM to an AEAD, so
"ciphertext" would be ambiguous.)
Where variable names refer to parts of the protocol, rather than the
the underlying KEM-like construction, I've kept variable names matching
the protocol mechanism, so we still talk about "curves" and "key
shares", but, when using the post-quantum replacements, the terminology
is no longer quite accurate.
I've also not yet renamed SSLKeyShare yet, though the name is now
inaccurate. Also ideally we'd touch that up so the stateful object is
just a KEM private key, for SSLKEMKey. Though at that point, we maybe
should just add EVP_KEM and EVP_KEM_KEY APIs to libcrypto.
Change-Id: Icbcc1840c5d2dfad210ef4caad2a7c4bf8146553
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/57726
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2 years ago
|
|
|
bool Encap(CBB *out_ciphertext, Array<uint8_t> *out_secret,
|
|
|
|
uint8_t *out_alert, Span<const uint8_t> peer_key) override {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
Use KEM terminology in TLS ECDHE and key_share abstractions
TLS 1.2 ECDHE and TLS 1.3 key shares were originally designed around
Diffie-Hellman-like primitives and use language based on that.
Post-quantum replacements do not look like Diffie-Hellman, where each
part exchanges a public key, but schemes that work differently can still
slot in without protocol changes.
We previously came up with our own Offer/Accept/Finish abstraction for
early post-quantum experiments, but the NIST constructions are all
expressed as KEMs: First, the recipient generates a keypair and sends
the public key. Then the sender encapsulates a symmetric secret and
sends the ciphertext. Finally, the recipient decapsulates the ciphertext
to get the secret.
Align our C++ and Go abstractions to this terminology. The functions are
now called Generate/Encap/Decap, and the output of Encap is called
"ciphertext", which seems to align with what most folks use. (RFC 9180
uses "enc" for "encapsulated key", but they staple a KEM to an AEAD, so
"ciphertext" would be ambiguous.)
Where variable names refer to parts of the protocol, rather than the
the underlying KEM-like construction, I've kept variable names matching
the protocol mechanism, so we still talk about "curves" and "key
shares", but, when using the post-quantum replacements, the terminology
is no longer quite accurate.
I've also not yet renamed SSLKeyShare yet, though the name is now
inaccurate. Also ideally we'd touch that up so the stateful object is
just a KEM private key, for SSLKEMKey. Though at that point, we maybe
should just add EVP_KEM and EVP_KEM_KEY APIs to libcrypto.
Change-Id: Icbcc1840c5d2dfad210ef4caad2a7c4bf8146553
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/57726
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2 years ago
|
|
|
bool Decap(Array<uint8_t> *out_secret, uint8_t *out_alert,
|
|
|
|
Span<const uint8_t> ciphertext) override {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
constexpr NamedGroup kNamedGroups[] = {
|
|
|
|
{NID_secp224r1, SSL_CURVE_SECP224R1, "P-224", "secp224r1"},
|
|
|
|
{NID_X9_62_prime256v1, SSL_CURVE_SECP256R1, "P-256", "prime256v1"},
|
|
|
|
{NID_secp384r1, SSL_CURVE_SECP384R1, "P-384", "secp384r1"},
|
|
|
|
{NID_secp521r1, SSL_CURVE_SECP521R1, "P-521", "secp521r1"},
|
|
|
|
{NID_X25519, SSL_CURVE_X25519, "X25519", "x25519"},
|
|
|
|
{NID_CECPQ2, SSL_CURVE_CECPQ2, "CECPQ2", "CECPQ2"},
|
|
|
|
{NID_X25519Kyber768, SSL_CURVE_X25519KYBER768, "X25519KYBER",
|
|
|
|
"X25519Kyber"},
|
|
|
|
{NID_P256Kyber768, SSL_CURVE_P256KYBER768, "P256KYBER", "P256Kyber"},
|
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
Span<const NamedGroup> NamedGroups() {
|
|
|
|
return MakeConstSpan(kNamedGroups, OPENSSL_ARRAY_SIZE(kNamedGroups));
|
|
|
|
}
|
|
|
|
|
|
|
|
UniquePtr<SSLKeyShare> SSLKeyShare::Create(uint16_t group_id) {
|
|
|
|
switch (group_id) {
|
|
|
|
case SSL_CURVE_SECP224R1:
|
|
|
|
return MakeUnique<ECKeyShare>(NID_secp224r1, SSL_CURVE_SECP224R1);
|
|
|
|
case SSL_CURVE_SECP256R1:
|
|
|
|
return MakeUnique<ECKeyShare>(NID_X9_62_prime256v1, SSL_CURVE_SECP256R1);
|
|
|
|
case SSL_CURVE_SECP384R1:
|
|
|
|
return MakeUnique<ECKeyShare>(NID_secp384r1, SSL_CURVE_SECP384R1);
|
|
|
|
case SSL_CURVE_SECP521R1:
|
|
|
|
return MakeUnique<ECKeyShare>(NID_secp521r1, SSL_CURVE_SECP521R1);
|
|
|
|
case SSL_CURVE_X25519:
|
|
|
|
return MakeUnique<X25519KeyShare>();
|
|
|
|
case SSL_CURVE_CECPQ2:
|
|
|
|
return MakeUnique<CECPQ2KeyShare>();
|
|
|
|
case SSL_CURVE_X25519KYBER768:
|
|
|
|
return MakeUnique<X25519Kyber768KeyShare>();
|
|
|
|
case SSL_CURVE_P256KYBER768:
|
|
|
|
return MakeUnique<P256Kyber768KeyShare>();
|
|
|
|
default:
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ssl_nid_to_group_id(uint16_t *out_group_id, int nid) {
|
|
|
|
for (const auto &group : kNamedGroups) {
|
|
|
|
if (group.nid == nid) {
|
|
|
|
*out_group_id = group.group_id;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ssl_name_to_group_id(uint16_t *out_group_id, const char *name, size_t len) {
|
|
|
|
for (const auto &group : kNamedGroups) {
|
|
|
|
if (len == strlen(group.name) &&
|
|
|
|
!strncmp(group.name, name, len)) {
|
|
|
|
*out_group_id = group.group_id;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if (len == strlen(group.alias) &&
|
|
|
|
!strncmp(group.alias, name, len)) {
|
|
|
|
*out_group_id = group.group_id;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
BSSL_NAMESPACE_END
|
|
|
|
|
|
|
|
using namespace bssl;
|
|
|
|
|
|
|
|
const char* SSL_get_curve_name(uint16_t group_id) {
|
|
|
|
for (const auto &group : kNamedGroups) {
|
|
|
|
if (group.group_id == group_id) {
|
|
|
|
return group.name;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|