Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions fuzz/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,6 @@ fuzzer(read_pem)
fuzzer(server ssl)
fuzzer(session ssl)
fuzzer(spki)
fuzzer(ssl_buffer ssl)
fuzzer(ssl_ctx_api ssl)
fuzzer(ssl_serialization ssl)
158 changes: 158 additions & 0 deletions fuzz/ssl_buffer.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0 OR ISC

#include <openssl/bytestring.h>
#include <openssl/err.h>
#include <openssl/mem.h>
#include <openssl/span.h>
#include "../ssl/internal.h"

extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) {
CBS cbs;
CBS_init(&cbs, buf, len);

bssl::SSLBuffer buffer;

if (!buffer.DoDeserialization(cbs)) {
return 0;
}

// See if we can serialize it back
bssl::ScopedCBB cbb;
CBB_init(cbb.get(), len);
if (!buffer.DoSerialization(*cbb.get())) {
return 1;
}
cbb.Reset();

// If the restore buffer is not empty lets use it
if (!buffer.empty()) {
// Get a view to the written but not discarded data and verify
// we can safely read it all.
auto span = buffer.span();
{
volatile const uint8_t *vp = span.data();
for (size_t i = 0; i < span.size(); i++) {
uint8_t v = vp[i];
(void)v;
}
}
// Now "consume" the content we read which moves offset_ forward and reduces size_ and cap_.
buffer.Consume(span.size());

// Serialize the read span we were using. This is valid and allowed use case
// as the data is still kept until we call discard.
bssl::ScopedCBB spanCBB;
CBB_init(spanCBB.get(), span.size());
if (!buffer.SerializeBufferView(*spanCBB.get(), span)) {
return 1;
}

// Serialize the current buffer state, we should be able to restore it
// and restore the span and use it safely.
CBB_init(cbb.get(), len);
if (!buffer.DoSerialization(*cbb.get())) {
return 1;
}

// Now let's try to fill the rest of the buffer's remaining space
{
// Fill the remaining capacity with 1's
auto remaining = buffer.remaining();
memset(remaining.data(), 1, remaining.size());
buffer.DidWrite(remaining.size());

// Since we told the buffer we wrote remaining.size(), then the
// buffer.span() should now point to that content.
auto remSpan = buffer.span();
if (remSpan.size() != remaining.size()) {
return 1;
}

// Validate we read all 1's
for (size_t i = 0; i < remSpan.size(); i++) {
uint8_t v = remSpan.data()[i];
if (v != 1) {
return 1;
}
}

// Inform that we have now consumed the data
buffer.Consume(remSpan.size());
remaining = buffer.remaining();

// There should be no space left...
if (remaining.size() != 0) {
return 1;
}

// This should cause the buffer to be free'd
buffer.DiscardConsumed();
if (buffer.buf_ptr() != nullptr) {
return 1;
}
}

// Reset to the serialized version before the above writes
CBS_init(&cbs, CBB_data(cbb.get()), CBB_len(cbb.get()));
if (!buffer.DoDeserialization(cbs)) {
return 1;
}

// Restore the span to the earlier data we consumed
CBS_init(&cbs, CBB_data(spanCBB.get()), CBB_len(spanCBB.get()));
if (!buffer.DeserializeBufferView(cbs, span)) {
return 1;
}

// We should still be able to safely read the data the span referred to.
{
volatile const uint8_t *vp = span.data();
for (size_t i = 0; i < span.size(); i++) {
uint8_t v = vp[i];
(void)v;
}
}
}

// let's try to fill the rest of the buffer's remaining space.
// We did this earlier if the buffer was not empty as well.
{
// Fill the remaining capacity with 1's
auto remaining = buffer.remaining();
memset(remaining.data(), 1, remaining.size());
buffer.DidWrite(remaining.size());

// Since we told the buffer we wrote remaining.size(), then the
// buffer.span() should now point to that content.
auto span = buffer.span();
if (span.size() != remaining.size()) {
return 1;
}

// Validate we read all 1's
for (size_t i = 0; i < span.size(); i++) {
uint8_t v = span.data()[i];
if (v != 1) {
return 1;
}
}

// Inform that we have now consumed the data
buffer.Consume(span.size());
remaining = buffer.remaining();

// There should be no space left...
if (remaining.size() != 0) {
return 1;
}

// This should cause the buffer to be free'd
buffer.DiscardConsumed();
if (buffer.buf_ptr() != nullptr) {
return 1;
}
}

return 0;
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
€
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ÿÿÿÿ¨
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0ÿ,ÿ
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ßÿÿ
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@


Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ÿÿÿÿÿÿÿÿÿ…¾
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0F
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0:”
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0ƒ
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ÿ
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ÿÿÿðÿ?
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0ÿÿ
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ÿÿÿÿ
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0Í
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0ÿ,
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ÿÿÿÿÿÿÿÿÿ`
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0ÿ
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@

Š
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ÿÿÿÿ¨
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0#
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0ÿ0
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0ÿ2ÿ
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0ÿ,ÿ
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0ÿ
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
?ÿ½ÿ
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0ÿÿ
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0¢
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
)
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
00
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0ÿ0ÿ^
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0ÿ
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ÿªªªªªªªª
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0ÿ
Binary file not shown.
Binary file not shown.
Binary file not shown.
57 changes: 44 additions & 13 deletions ssl/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -1312,9 +1312,16 @@ void ssl_do_msg_callback(const SSL *ssl, int is_write, int content_type,

// Transport buffers.

enum SSL_BUFFER_SERDE_VERSION {
SSL_BUFFER_SERDE_VERSION_ONE = 1,
SSL_BUFFER_SERDE_VERSION_TWO = 2
};

const unsigned kSSLBufferMaxSerDeVersion = SSL_BUFFER_SERDE_VERSION_TWO;

#define SSLBUFFER_READ_AHEAD_MIN_CAPACITY 512
#define SSLBUFFER_MAX_CAPACITY UINT16_MAX
class SSLBuffer {
#define SSLBUFFER_MAX_CAPACITY INT_MAX
class OPENSSL_EXPORT SSLBuffer {
public:
SSLBuffer() {}
~SSLBuffer() { Clear(); }
Expand Down Expand Up @@ -1358,28 +1365,48 @@ class SSLBuffer {
void DiscardConsumed();

// DoSerialization writes all fields into |cbb|.
bool DoSerialization(CBB *cbb);
bool DoSerialization(CBB &cbb);

// DoDeserialization recovers the states encoded via |DoSerialization|.
bool DoDeserialization(CBS *in);
bool DoDeserialization(CBS &in);

bool SerializeBufferView(CBB &cbb, Span<uint8_t> &view);
bool DeserializeBufferView(CBS &cbb, Span<uint8_t> &view);

private:
// buf_ is the memory allocated for this buffer.
uint8_t *buf_ = nullptr;
// offset_ is the offset into |buf_| which the buffer contents start at.
uint16_t offset_ = 0;
// size_ is the size of the buffer contents from |buf_| + |offset_|.
uint16_t size_ = 0;
// cap_ is how much memory beyond |buf_| + |offset_| is available.
uint16_t cap_ = 0;
// inline_buf_ is a static buffer for short reads.
uint8_t inline_buf_[SSL3_RT_HEADER_LENGTH];
// buf_allocated_ is true if |buf_| points to allocated data and must be freed
// or false if it points into |inline_buf_|.
bool buf_allocated_ = false;
// The total capacity requested for this buffer by |EnsureCap|.
size_t buf_cap_ = 0;
// buf_size_ is how much memory allocated for |buf_|. This is needed by
// |DoSerialization|.
// |DoSerializationV1|. This is the total size of the buffer with the requested capacity + padding.
size_t buf_size_ = 0;
// header length used to calculate initial offset
size_t header_len_ = 0;
// offset_ is the offset into |buf_| which the buffer contents start at, and is moved as contents are consumed
int offset_ = 0;
// size_ is the size of the buffer contents from |buf_| + |offset_|.
int size_ = 0;
// cap_ is how much memory beyond |buf_| + |offset_| is available.
int cap_ = 0;
// inline_buf_ is a static buffer for short reads.
uint8_t inline_buf_[SSL3_RT_HEADER_LENGTH];

// The V1 version has some intricacies were solved in later serialization versions.
// This is mainly to capture if a V1 version was restored and whether it needs to be
// re-serialized as that version.
uint32_t max_serialization_version_ = SSL_BUFFER_SERDE_VERSION_TWO;

bool DoSerializationV1(CBB &cbb);
bool DoSerializationV2(CBB &cbb);

bool DoDeserializationV1(CBS &in);
bool DoDeserializationV2(CBS &in);

bool ValidateBuffersState();
};

// ssl_read_buffer_extend_to extends the read buffer to the desired length. For
Expand Down Expand Up @@ -4136,6 +4163,10 @@ struct ssl_st {
// as will fit in the SSLBuffer from the BIO, or just enough to read the record
// header and then the length of the body
bool enable_read_ahead : 1;

// is_suspended_state indicates that the |SSL| object has been serialized and
// operations should not be performed on the connection.
bool is_suspended_state : 1;
};

struct ssl_session_st {
Expand Down
Loading
Loading