Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

alts: add gRPC TSI frame protector #3873

Merged
merged 9 commits into from
Jul 23, 2018

Conversation

lizan
Copy link
Member

@lizan lizan commented Jul 17, 2018

Signed-off-by: Lizan Zhou zlizan@google.com

Description:
2nd PR for #3429, add frame protector.

Risk Level: Low (not enabled in main)
Testing: bazel test //test/...
Docs Changes: N/A
Release Notes: N/A

Signed-off-by: Lizan Zhou <zlizan@google.com>
@lizan lizan self-assigned this Jul 17, 2018
@lizan lizan requested a review from danzh2010 July 17, 2018 00:37
Copy link
Contributor

@danzh2010 danzh2010 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good overall! Just a few nits. Thanks for this change!


// TODO(lizan): tune size later
unsigned char protected_buffer[16384];
size_t protected_buffer_size = sizeof(protected_buffer);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nits: make this a const and use it to initialize protected_buffer[]

input.drain(processed_message_size);
}

ASSERT(input.length() == 0);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this ASSERT redundant as the while condition guarantees input.length()==0 to exit the loop?


ASSERT(input.length() == 0);
size_t still_pending_size;
do {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nits: can you add some comments about the need of calling tsi_frame_protector_protect_flush()?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this addressed?


// TODO(lizan): Tune the buffer size.
unsigned char unprotected_buffer[16384];
size_t unprotected_buffer_size = sizeof(unprotected_buffer);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto.


while (input.length() > 0) {
auto* message_bytes = reinterpret_cast<unsigned char*>(input.linearize(input.length()));
size_t unprotected_buffer_size_to_send = unprotected_buffer_size;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The name |unprotected_buffer_size_to_send| is a confusing. I think unprotect() should be called on receiving path.


{
Buffer::OwnedImpl input, encrypted;
input.add(std::string(20000, 'a'));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you have a const for protected_buffer_size, you can use a relative larger number here instead of hard coding 20000.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is a coincidence that the frame size generated by fake frame protector is max at 16K and the buffer size is 16K, the hard code here is not reflecting the buffer size.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this test case is testing protect() with |input| size larger than the buffer. So this line can be something more general, like: input.add(std::string(BUFFER_SIZE + 3620, 'a')); Am I misunderstanding?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The frame size of fake frame protector output is define here, it is coincidence that is same as BUFFER_SIZE, but the test should be larger than the frame size, it is not depends on BUFFER_SIZE.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is it testing against frame size which is not our implementation? I thought you meant to test protect() with input larger than |protected_buffer| which I think is worth to add if not covered yet.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant the expected output below (L63) is depends on frame size in fake frame protector, the input here is to exceed the BUFFER_SIZE and they are just happened to be same.

We don't have visibility of BUFFER_SIZE in test.cc so I'll have to define BUFFER_SIZE, input.add(std::string(BUFFER_SIZE + 3620, 'a')) won't work anyway.

input.add("foo");

EXPECT_EQ(TSI_OK, frame_protector_.protect(input, encrypted));
EXPECT_EQ("\x07\0\0\0foo"s, encrypted.toString());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nits: comment where the prefix "\x07\0\0\0" comes from? I guess fake_frame_protector has a contract about how to generate it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is comment at top of this file (L23)

lizan added 4 commits July 17, 2018 17:58
Signed-off-by: Lizan Zhou <zlizan@google.com>
Signed-off-by: Lizan Zhou <zlizan@google.com>
Signed-off-by: Lizan Zhou <zlizan@google.com>
danzh2010
danzh2010 previously approved these changes Jul 19, 2018
Copy link
Contributor

@danzh2010 danzh2010 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@lizan lizan requested a review from alyssawilk July 19, 2018 19:24
Copy link
Contributor

@alyssawilk alyssawilk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sweeet, glad to see this progress! Just a few nits from me


// TSI may buffer some of the input in its internal, flushing its buffer to protected_buffer to
// avoid some of input is not written to socket.
size_t still_pending_size;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// TSI may buffer some of the input internally. Flush its buffer to protected_buffer.
?

auto* message_bytes = reinterpret_cast<unsigned char*>(input.linearize(input.length()));
size_t unprotected_buffer_size = BUFFER_SIZE;
size_t processed_message_size = input.length();
tsi_result result = tsi_frame_protector_unprotect(frame_protector_.get(), message_bytes,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sanity check, there's no flushing problem in this direction?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, there is no tsi_frame_protector_unprotect_flush.


/**
* Wrapper for tsi_frame_protector_protect
* @param input supplies the input buffer, the method will drain it when it is processed.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

input supplies the input buffer -> input supplies the data to protect.

ditto below for unprotect

/**
* Wrapper for tsi_frame_protector_protect
* @param input supplies the input buffer, the method will drain it when it is processed.
* @param output supplies the output buffer
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

output supplies the buffer where the protected data will be stored.

Ditto for unprotect

protected_buffer, &protected_buffer_size);
if (result != TSI_OK) {
ASSERT(result != TSI_INVALID_ARGUMENT && result != TSI_UNIMPLEMENTED);
return result;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

lizan added 2 commits July 19, 2018 14:43
Signed-off-by: Lizan Zhou <zlizan@google.com>
Signed-off-by: Lizan Zhou <zlizan@google.com>
@alyssawilk alyssawilk merged commit a5478ee into envoyproxy:master Jul 23, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants