diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h index a95c47eef..81934c5bb 100644 --- a/include/openssl/ssl.h +++ b/include/openssl/ssl.h @@ -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_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 *out, - size_t *out_record_len, - uint8_t *out_alert, - Span 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 out_prefix, - Span out, Span out_suffix, - Span in); - // *** EXPERIMENTAL — DO NOT USE WITHOUT CHECKING *** // diff --git a/ssl/ssl_test.cc b/ssl/ssl_test.cc index 2627362da..3709a4694 100644 --- a/ssl/ssl_test.cc +++ b/ssl/ssl_test.cc @@ -4838,157 +4838,6 @@ TEST(SSLTest, SelectNextProto) { EXPECT_EQ(Bytes("x"), Bytes(result, result_len)); } -TEST(SSLTest, SealRecord) { - bssl::UniquePtr client_ctx(SSL_CTX_new(TLSv1_2_method())), - server_ctx(CreateContextWithTestCertificate(TLSv1_2_method())); - ASSERT_TRUE(client_ctx); - ASSERT_TRUE(server_ctx); - - bssl::UniquePtr client, server; - ASSERT_TRUE(ConnectClientAndServer(&client, &server, client_ctx.get(), - server_ctx.get())); - - const std::vector record = {1, 2, 3, 4, 5}; - std::vector 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 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 sealed_copy = sealed; - - bssl::Span 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 client_ctx(SSL_CTX_new(TLSv1_2_method())), - server_ctx(CreateContextWithTestCertificate(TLSv1_2_method())); - ASSERT_TRUE(client_ctx); - ASSERT_TRUE(server_ctx); - - bssl::UniquePtr client, server; - ASSERT_TRUE(ConnectClientAndServer(&client, &server, client_ctx.get(), - server_ctx.get())); - - const std::vector plaintext = {1, 2, 3, 4, 5}; - std::vector record = plaintext; - std::vector 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 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 client_ctx(SSL_CTX_new(TLSv1_2_method())), - server_ctx(CreateContextWithTestCertificate(TLSv1_2_method())); - ASSERT_TRUE(client_ctx); - ASSERT_TRUE(server_ctx); - - bssl::UniquePtr client, server; - ASSERT_TRUE(ConnectClientAndServer(&client, &server, client_ctx.get(), - server_ctx.get())); - - const std::vector plaintext = {1, 2, 3, 4, 5}; - std::vector record = plaintext; - std::vector 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 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 client_ctx(SSL_CTX_new(TLSv1_2_method())), - server_ctx(CreateContextWithTestCertificate(TLSv1_2_method())); - ASSERT_TRUE(client_ctx); - ASSERT_TRUE(server_ctx); - - bssl::UniquePtr client, server; - ASSERT_TRUE(ConnectClientAndServer(&client, &server, client_ctx.get(), - server_ctx.get())); - - std::vector record = {1, 2, 3, 4, 5}; - std::vector 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. TEST(SSLTest, NoCiphersAvailable) { bssl::UniquePtr ctx(SSL_CTX_new(TLS_method())); diff --git a/ssl/tls_record.cc b/ssl/tls_record.cc index 88b8ef9ae..395b9a483 100644 --- a/ssl/tls_record.cc +++ b/ssl/tls_record.cc @@ -600,86 +600,6 @@ enum ssl_open_record_t ssl_process_alert(SSL *ssl, uint8_t *out_alert, return ssl_open_record_error; } -OpenRecordResult OpenRecord(SSL *ssl, Span *out, - size_t *out_record_len, uint8_t *out_alert, - const Span 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 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 out_prefix, - const Span out, Span out_suffix, - const Span 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 using namespace bssl;