Remove the experimental in-place record APIs.

We never ended up using these, or making them work with TLS 1.3 (which
has KeyUpdates and NewSessionTickets). It'd still be nice to have an
in-place API, but for now unwind these ones until we have time to give
it another go. Supporting TLS 1.3's post-handshake messages will
probably require a slightly more involved design.

(I suspect some of the seal_scatter bits in tls_record.cc can also be
simplified with these removed, but I've left them alone here.)

Update-Note: Removed some unused, experimental APIs.
Change-Id: Iad1245fa467cc6e599d20561f5db44d236219e06
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/54527
Reviewed-by: Bob Beck <bbe@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
chromium-5359
David Benjamin 2 years ago committed by Boringssl LUCI CQ
parent 32013e8147
commit 80eb8141a2
  1. 56
      include/openssl/ssl.h
  2. 151
      ssl/ssl_test.cc
  3. 80
      ssl/tls_record.cc

@ -5353,62 +5353,6 @@ BORINGSSL_MAKE_UP_REF(SSL_ECH_KEYS, SSL_ECH_KEYS_up_ref)
BORINGSSL_MAKE_DELETER(SSL_SESSION, SSL_SESSION_free) BORINGSSL_MAKE_DELETER(SSL_SESSION, SSL_SESSION_free)
BORINGSSL_MAKE_UP_REF(SSL_SESSION, SSL_SESSION_up_ref) BORINGSSL_MAKE_UP_REF(SSL_SESSION, SSL_SESSION_up_ref)
enum class OpenRecordResult {
kOK,
kDiscard,
kIncompleteRecord,
kAlertCloseNotify,
kError,
};
// *** EXPERIMENTAL -- DO NOT USE ***
//
// OpenRecord decrypts the first complete SSL record from |in| in-place, sets
// |out| to the decrypted application data, and |out_record_len| to the length
// of the encrypted record. Returns:
// - kOK if an application-data record was successfully decrypted and verified.
// - kDiscard if a record was sucessfully processed, but should be discarded.
// - kIncompleteRecord if |in| did not contain a complete record.
// - kAlertCloseNotify if a record was successfully processed but is a
// close_notify alert.
// - kError if an error occurred or the record is invalid. |*out_alert| will be
// set to an alert to emit, or zero if no alert should be emitted.
OPENSSL_EXPORT OpenRecordResult OpenRecord(SSL *ssl, Span<uint8_t> *out,
size_t *out_record_len,
uint8_t *out_alert,
Span<uint8_t> in);
OPENSSL_EXPORT size_t SealRecordPrefixLen(const SSL *ssl, size_t plaintext_len);
// SealRecordSuffixLen returns the length of the suffix written by |SealRecord|.
//
// |plaintext_len| must be equal to the size of the plaintext passed to
// |SealRecord|.
//
// |plaintext_len| must not exceed |SSL3_RT_MAX_PLAINTEXT_LENGTH|. The returned
// suffix length will not exceed |SSL3_RT_MAX_ENCRYPTED_OVERHEAD|.
OPENSSL_EXPORT size_t SealRecordSuffixLen(const SSL *ssl, size_t plaintext_len);
// *** EXPERIMENTAL -- DO NOT USE ***
//
// SealRecord encrypts the cleartext of |in| and scatters the resulting TLS
// application data record between |out_prefix|, |out|, and |out_suffix|. It
// returns true on success or false if an error occurred.
//
// The length of |out_prefix| must equal |SealRecordPrefixLen|. The length of
// |out| must equal the length of |in|, which must not exceed
// |SSL3_RT_MAX_PLAINTEXT_LENGTH|. The length of |out_suffix| must equal
// |SealRecordSuffixLen|.
//
// If enabled, |SealRecord| may perform TLS 1.0 CBC 1/n-1 record splitting.
// |SealRecordPrefixLen| accounts for the required overhead if that is the case.
//
// |out| may equal |in| to encrypt in-place but may not otherwise alias.
// |out_prefix| and |out_suffix| may not alias anything.
OPENSSL_EXPORT bool SealRecord(SSL *ssl, Span<uint8_t> out_prefix,
Span<uint8_t> out, Span<uint8_t> out_suffix,
Span<const uint8_t> in);
// *** EXPERIMENTAL — DO NOT USE WITHOUT CHECKING *** // *** EXPERIMENTAL — DO NOT USE WITHOUT CHECKING ***
// //

@ -4838,157 +4838,6 @@ TEST(SSLTest, SelectNextProto) {
EXPECT_EQ(Bytes("x"), Bytes(result, result_len)); EXPECT_EQ(Bytes("x"), Bytes(result, result_len));
} }
TEST(SSLTest, SealRecord) {
bssl::UniquePtr<SSL_CTX> client_ctx(SSL_CTX_new(TLSv1_2_method())),
server_ctx(CreateContextWithTestCertificate(TLSv1_2_method()));
ASSERT_TRUE(client_ctx);
ASSERT_TRUE(server_ctx);
bssl::UniquePtr<SSL> client, server;
ASSERT_TRUE(ConnectClientAndServer(&client, &server, client_ctx.get(),
server_ctx.get()));
const std::vector<uint8_t> record = {1, 2, 3, 4, 5};
std::vector<uint8_t> prefix(
bssl::SealRecordPrefixLen(client.get(), record.size())),
body(record.size()),
suffix(bssl::SealRecordSuffixLen(client.get(), record.size()));
ASSERT_TRUE(bssl::SealRecord(client.get(), bssl::MakeSpan(prefix),
bssl::MakeSpan(body), bssl::MakeSpan(suffix),
record));
std::vector<uint8_t> sealed;
sealed.insert(sealed.end(), prefix.begin(), prefix.end());
sealed.insert(sealed.end(), body.begin(), body.end());
sealed.insert(sealed.end(), suffix.begin(), suffix.end());
std::vector<uint8_t> sealed_copy = sealed;
bssl::Span<uint8_t> plaintext;
size_t record_len;
uint8_t alert = 255;
EXPECT_EQ(bssl::OpenRecord(server.get(), &plaintext, &record_len, &alert,
bssl::MakeSpan(sealed)),
bssl::OpenRecordResult::kOK);
EXPECT_EQ(record_len, sealed.size());
EXPECT_EQ(plaintext, record);
EXPECT_EQ(255, alert);
}
TEST(SSLTest, SealRecordInPlace) {
bssl::UniquePtr<SSL_CTX> client_ctx(SSL_CTX_new(TLSv1_2_method())),
server_ctx(CreateContextWithTestCertificate(TLSv1_2_method()));
ASSERT_TRUE(client_ctx);
ASSERT_TRUE(server_ctx);
bssl::UniquePtr<SSL> client, server;
ASSERT_TRUE(ConnectClientAndServer(&client, &server, client_ctx.get(),
server_ctx.get()));
const std::vector<uint8_t> plaintext = {1, 2, 3, 4, 5};
std::vector<uint8_t> record = plaintext;
std::vector<uint8_t> prefix(
bssl::SealRecordPrefixLen(client.get(), record.size())),
suffix(bssl::SealRecordSuffixLen(client.get(), record.size()));
ASSERT_TRUE(bssl::SealRecord(client.get(), bssl::MakeSpan(prefix),
bssl::MakeSpan(record), bssl::MakeSpan(suffix),
record));
record.insert(record.begin(), prefix.begin(), prefix.end());
record.insert(record.end(), suffix.begin(), suffix.end());
bssl::Span<uint8_t> result;
size_t record_len;
uint8_t alert;
EXPECT_EQ(bssl::OpenRecord(server.get(), &result, &record_len, &alert,
bssl::MakeSpan(record)),
bssl::OpenRecordResult::kOK);
EXPECT_EQ(record_len, record.size());
EXPECT_EQ(plaintext, result);
}
TEST(SSLTest, SealRecordTrailingData) {
bssl::UniquePtr<SSL_CTX> client_ctx(SSL_CTX_new(TLSv1_2_method())),
server_ctx(CreateContextWithTestCertificate(TLSv1_2_method()));
ASSERT_TRUE(client_ctx);
ASSERT_TRUE(server_ctx);
bssl::UniquePtr<SSL> client, server;
ASSERT_TRUE(ConnectClientAndServer(&client, &server, client_ctx.get(),
server_ctx.get()));
const std::vector<uint8_t> plaintext = {1, 2, 3, 4, 5};
std::vector<uint8_t> record = plaintext;
std::vector<uint8_t> prefix(
bssl::SealRecordPrefixLen(client.get(), record.size())),
suffix(bssl::SealRecordSuffixLen(client.get(), record.size()));
ASSERT_TRUE(bssl::SealRecord(client.get(), bssl::MakeSpan(prefix),
bssl::MakeSpan(record), bssl::MakeSpan(suffix),
record));
record.insert(record.begin(), prefix.begin(), prefix.end());
record.insert(record.end(), suffix.begin(), suffix.end());
record.insert(record.end(), {5, 4, 3, 2, 1});
bssl::Span<uint8_t> result;
size_t record_len;
uint8_t alert;
EXPECT_EQ(bssl::OpenRecord(server.get(), &result, &record_len, &alert,
bssl::MakeSpan(record)),
bssl::OpenRecordResult::kOK);
EXPECT_EQ(record_len, record.size() - 5);
EXPECT_EQ(plaintext, result);
}
TEST(SSLTest, SealRecordInvalidSpanSize) {
bssl::UniquePtr<SSL_CTX> client_ctx(SSL_CTX_new(TLSv1_2_method())),
server_ctx(CreateContextWithTestCertificate(TLSv1_2_method()));
ASSERT_TRUE(client_ctx);
ASSERT_TRUE(server_ctx);
bssl::UniquePtr<SSL> client, server;
ASSERT_TRUE(ConnectClientAndServer(&client, &server, client_ctx.get(),
server_ctx.get()));
std::vector<uint8_t> record = {1, 2, 3, 4, 5};
std::vector<uint8_t> prefix(
bssl::SealRecordPrefixLen(client.get(), record.size())),
body(record.size()),
suffix(bssl::SealRecordSuffixLen(client.get(), record.size()));
auto expect_err = []() {
int err = ERR_get_error();
EXPECT_EQ(ERR_GET_LIB(err), ERR_LIB_SSL);
EXPECT_EQ(ERR_GET_REASON(err), SSL_R_BUFFER_TOO_SMALL);
ERR_clear_error();
};
EXPECT_FALSE(bssl::SealRecord(
client.get(), bssl::MakeSpan(prefix.data(), prefix.size() - 1),
bssl::MakeSpan(record), bssl::MakeSpan(suffix), record));
expect_err();
EXPECT_FALSE(bssl::SealRecord(
client.get(), bssl::MakeSpan(prefix.data(), prefix.size() + 1),
bssl::MakeSpan(record), bssl::MakeSpan(suffix), record));
expect_err();
EXPECT_FALSE(
bssl::SealRecord(client.get(), bssl::MakeSpan(prefix),
bssl::MakeSpan(record.data(), record.size() - 1),
bssl::MakeSpan(suffix), record));
expect_err();
EXPECT_FALSE(
bssl::SealRecord(client.get(), bssl::MakeSpan(prefix),
bssl::MakeSpan(record.data(), record.size() + 1),
bssl::MakeSpan(suffix), record));
expect_err();
EXPECT_FALSE(bssl::SealRecord(
client.get(), bssl::MakeSpan(prefix), bssl::MakeSpan(record),
bssl::MakeSpan(suffix.data(), suffix.size() - 1), record));
expect_err();
EXPECT_FALSE(bssl::SealRecord(
client.get(), bssl::MakeSpan(prefix), bssl::MakeSpan(record),
bssl::MakeSpan(suffix.data(), suffix.size() + 1), record));
expect_err();
}
// The client should gracefully handle no suitable ciphers being enabled. // The client should gracefully handle no suitable ciphers being enabled.
TEST(SSLTest, NoCiphersAvailable) { TEST(SSLTest, NoCiphersAvailable) {
bssl::UniquePtr<SSL_CTX> ctx(SSL_CTX_new(TLS_method())); bssl::UniquePtr<SSL_CTX> ctx(SSL_CTX_new(TLS_method()));

@ -600,86 +600,6 @@ enum ssl_open_record_t ssl_process_alert(SSL *ssl, uint8_t *out_alert,
return ssl_open_record_error; return ssl_open_record_error;
} }
OpenRecordResult OpenRecord(SSL *ssl, Span<uint8_t> *out,
size_t *out_record_len, uint8_t *out_alert,
const Span<uint8_t> in) {
// This API is a work in progress and currently only works for TLS 1.2 servers
// and below.
if (SSL_in_init(ssl) ||
SSL_is_dtls(ssl) ||
ssl_protocol_version(ssl) > TLS1_2_VERSION) {
assert(false);
*out_alert = SSL_AD_INTERNAL_ERROR;
return OpenRecordResult::kError;
}
Span<uint8_t> plaintext;
uint8_t type = 0;
const ssl_open_record_t result = tls_open_record(
ssl, &type, &plaintext, out_record_len, out_alert, in);
switch (result) {
case ssl_open_record_success:
if (type != SSL3_RT_APPLICATION_DATA && type != SSL3_RT_ALERT) {
*out_alert = SSL_AD_UNEXPECTED_MESSAGE;
return OpenRecordResult::kError;
}
*out = plaintext;
return OpenRecordResult::kOK;
case ssl_open_record_discard:
return OpenRecordResult::kDiscard;
case ssl_open_record_partial:
return OpenRecordResult::kIncompleteRecord;
case ssl_open_record_close_notify:
return OpenRecordResult::kAlertCloseNotify;
case ssl_open_record_error:
return OpenRecordResult::kError;
}
assert(false);
return OpenRecordResult::kError;
}
size_t SealRecordPrefixLen(const SSL *ssl, const size_t record_len) {
return tls_seal_scatter_prefix_len(ssl, SSL3_RT_APPLICATION_DATA, record_len);
}
size_t SealRecordSuffixLen(const SSL *ssl, const size_t plaintext_len) {
assert(plaintext_len <= SSL3_RT_MAX_PLAIN_LENGTH);
size_t suffix_len;
if (!tls_seal_scatter_suffix_len(ssl, &suffix_len, SSL3_RT_APPLICATION_DATA,
plaintext_len)) {
assert(false);
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
return 0;
}
assert(suffix_len <= SSL3_RT_MAX_ENCRYPTED_OVERHEAD);
return suffix_len;
}
bool SealRecord(SSL *ssl, const Span<uint8_t> out_prefix,
const Span<uint8_t> out, Span<uint8_t> out_suffix,
const Span<const uint8_t> in) {
// This API is a work in progress and currently only works for TLS 1.2 servers
// and below.
if (SSL_in_init(ssl) ||
SSL_is_dtls(ssl) ||
ssl_protocol_version(ssl) > TLS1_2_VERSION) {
assert(false);
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
return false;
}
if (out_prefix.size() != SealRecordPrefixLen(ssl, in.size()) ||
out.size() != in.size() ||
out_suffix.size() != SealRecordSuffixLen(ssl, in.size())) {
OPENSSL_PUT_ERROR(SSL, SSL_R_BUFFER_TOO_SMALL);
return false;
}
return tls_seal_scatter_record(ssl, out_prefix.data(), out.data(),
out_suffix.data(), SSL3_RT_APPLICATION_DATA,
in.data(), in.size());
}
BSSL_NAMESPACE_END BSSL_NAMESPACE_END
using namespace bssl; using namespace bssl;

Loading…
Cancel
Save