diff options
author | 2017-07-28 13:25:02 -0700 | |
---|---|---|
committer | 2017-07-28 18:26:21 -0700 | |
commit | 7001bc279b520b556eb7e8e14fd8c9f87dfe3785 (patch) | |
tree | 5079197f52cb5bd59c72108c1c43438a1ead703d /src/core | |
parent | 433f7bce2d5a6683e9d60a147b528bb9be98baff (diff) |
Add TSI zero-copy frame protector
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/tsi/fake_transport_security.c | 6 | ||||
-rw-r--r-- | src/core/tsi/ssl_transport_security.c | 2 | ||||
-rw-r--r-- | src/core/tsi/transport_security.c | 83 | ||||
-rw-r--r-- | src/core/tsi/transport_security.h | 4 | ||||
-rw-r--r-- | src/core/tsi/transport_security_adapter.c | 7 | ||||
-rw-r--r-- | src/core/tsi/transport_security_grpc.c | 64 | ||||
-rw-r--r-- | src/core/tsi/transport_security_grpc.h | 80 | ||||
-rw-r--r-- | src/core/tsi/transport_security_interface.h | 9 |
8 files changed, 202 insertions, 53 deletions
diff --git a/src/core/tsi/fake_transport_security.c b/src/core/tsi/fake_transport_security.c index 1280680663..b0f5741015 100644 --- a/src/core/tsi/fake_transport_security.c +++ b/src/core/tsi/fake_transport_security.c @@ -25,7 +25,7 @@ #include <grpc/support/log.h> #include <grpc/support/port_platform.h> #include <grpc/support/useful.h> -#include "src/core/tsi/transport_security.h" +#include "src/core/tsi/transport_security_grpc.h" /* --- Constants. ---*/ #define TSI_FAKE_FRAME_HEADER_SIZE 4 @@ -407,8 +407,10 @@ static void fake_handshaker_result_destroy(tsi_handshaker_result *self) { static const tsi_handshaker_result_vtable handshaker_result_vtable = { fake_handshaker_result_extract_peer, + NULL, /* create_zero_copy_grpc_protector */ fake_handshaker_result_create_frame_protector, - fake_handshaker_result_get_unused_bytes, fake_handshaker_result_destroy, + fake_handshaker_result_get_unused_bytes, + fake_handshaker_result_destroy, }; static tsi_result fake_handshaker_result_create( diff --git a/src/core/tsi/ssl_transport_security.c b/src/core/tsi/ssl_transport_security.c index 1fd65928f9..c96a508a30 100644 --- a/src/core/tsi/ssl_transport_security.c +++ b/src/core/tsi/ssl_transport_security.c @@ -47,7 +47,7 @@ #include <openssl/x509v3.h> #include "src/core/tsi/ssl_types.h" -#include "src/core/tsi/transport_security.h" +#include "src/core/tsi/transport_security_grpc.h" /* --- Constants. ---*/ diff --git a/src/core/tsi/transport_security.c b/src/core/tsi/transport_security.c index be11d64472..a4be5e14a9 100644 --- a/src/core/tsi/transport_security.c +++ b/src/core/tsi/transport_security.c @@ -74,14 +74,12 @@ tsi_result tsi_frame_protector_protect(tsi_frame_protector *self, size_t *unprotected_bytes_size, unsigned char *protected_output_frames, size_t *protected_output_frames_size) { - if (self == NULL || unprotected_bytes == NULL || + if (self == NULL || self->vtable == NULL || unprotected_bytes == NULL || unprotected_bytes_size == NULL || protected_output_frames == NULL || protected_output_frames_size == NULL) { return TSI_INVALID_ARGUMENT; } - if (self->vtable == NULL || self->vtable->protect == NULL) { - return TSI_UNIMPLEMENTED; - } + if (self->vtable->protect == NULL) return TSI_UNIMPLEMENTED; return self->vtable->protect(self, unprotected_bytes, unprotected_bytes_size, protected_output_frames, protected_output_frames_size); @@ -90,13 +88,11 @@ tsi_result tsi_frame_protector_protect(tsi_frame_protector *self, tsi_result tsi_frame_protector_protect_flush( tsi_frame_protector *self, unsigned char *protected_output_frames, size_t *protected_output_frames_size, size_t *still_pending_size) { - if (self == NULL || protected_output_frames == NULL || + if (self == NULL || self->vtable == NULL || protected_output_frames == NULL || protected_output_frames_size == NULL || still_pending_size == NULL) { return TSI_INVALID_ARGUMENT; } - if (self->vtable == NULL || self->vtable->protect_flush == NULL) { - return TSI_UNIMPLEMENTED; - } + if (self->vtable->protect_flush == NULL) return TSI_UNIMPLEMENTED; return self->vtable->protect_flush(self, protected_output_frames, protected_output_frames_size, still_pending_size); @@ -106,14 +102,12 @@ tsi_result tsi_frame_protector_unprotect( tsi_frame_protector *self, const unsigned char *protected_frames_bytes, size_t *protected_frames_bytes_size, unsigned char *unprotected_bytes, size_t *unprotected_bytes_size) { - if (self == NULL || protected_frames_bytes == NULL || + if (self == NULL || self->vtable == NULL || protected_frames_bytes == NULL || protected_frames_bytes_size == NULL || unprotected_bytes == NULL || unprotected_bytes_size == NULL) { return TSI_INVALID_ARGUMENT; } - if (self->vtable == NULL || self->vtable->unprotect == NULL) { - return TSI_UNIMPLEMENTED; - } + if (self->vtable->unprotect == NULL) return TSI_UNIMPLEMENTED; return self->vtable->unprotect(self, protected_frames_bytes, protected_frames_bytes_size, unprotected_bytes, unprotected_bytes_size); @@ -131,48 +125,46 @@ void tsi_frame_protector_destroy(tsi_frame_protector *self) { tsi_result tsi_handshaker_get_bytes_to_send_to_peer(tsi_handshaker *self, unsigned char *bytes, size_t *bytes_size) { - if (self == NULL || bytes == NULL || bytes_size == NULL) { + if (self == NULL || self->vtable == NULL || bytes == NULL || + bytes_size == NULL) { return TSI_INVALID_ARGUMENT; } if (self->frame_protector_created) return TSI_FAILED_PRECONDITION; - if (self->vtable == NULL || self->vtable->get_bytes_to_send_to_peer == NULL) { - return TSI_UNIMPLEMENTED; - } + if (self->vtable->get_bytes_to_send_to_peer == NULL) return TSI_UNIMPLEMENTED; return self->vtable->get_bytes_to_send_to_peer(self, bytes, bytes_size); } tsi_result tsi_handshaker_process_bytes_from_peer(tsi_handshaker *self, const unsigned char *bytes, size_t *bytes_size) { - if (self == NULL || bytes == NULL || bytes_size == NULL) { + if (self == NULL || self->vtable == NULL || bytes == NULL || + bytes_size == NULL) { return TSI_INVALID_ARGUMENT; } if (self->frame_protector_created) return TSI_FAILED_PRECONDITION; - if (self->vtable == NULL || self->vtable->process_bytes_from_peer == NULL) { - return TSI_UNIMPLEMENTED; - } + if (self->vtable->process_bytes_from_peer == NULL) return TSI_UNIMPLEMENTED; return self->vtable->process_bytes_from_peer(self, bytes, bytes_size); } tsi_result tsi_handshaker_get_result(tsi_handshaker *self) { - if (self == NULL) return TSI_INVALID_ARGUMENT; + if (self == NULL || self->vtable == NULL) return TSI_INVALID_ARGUMENT; if (self->frame_protector_created) return TSI_FAILED_PRECONDITION; - if (self->vtable == NULL || self->vtable->get_result == NULL) { + if (self->vtable->get_result == NULL) { return TSI_UNIMPLEMENTED; } return self->vtable->get_result(self); } tsi_result tsi_handshaker_extract_peer(tsi_handshaker *self, tsi_peer *peer) { - if (self == NULL || peer == NULL) return TSI_INVALID_ARGUMENT; + if (self == NULL || self->vtable == NULL || peer == NULL) { + return TSI_INVALID_ARGUMENT; + } memset(peer, 0, sizeof(tsi_peer)); if (self->frame_protector_created) return TSI_FAILED_PRECONDITION; if (tsi_handshaker_get_result(self) != TSI_OK) { return TSI_FAILED_PRECONDITION; } - if (self->vtable == NULL || self->vtable->extract_peer == NULL) { - return TSI_UNIMPLEMENTED; - } + if (self->vtable->extract_peer == NULL) return TSI_UNIMPLEMENTED; return self->vtable->extract_peer(self, peer); } @@ -180,14 +172,12 @@ tsi_result tsi_handshaker_create_frame_protector( tsi_handshaker *self, size_t *max_protected_frame_size, tsi_frame_protector **protector) { tsi_result result; - if (self == NULL || protector == NULL) return TSI_INVALID_ARGUMENT; - if (self->frame_protector_created) return TSI_FAILED_PRECONDITION; - if (tsi_handshaker_get_result(self) != TSI_OK) { - return TSI_FAILED_PRECONDITION; - } - if (self->vtable == NULL || self->vtable->create_frame_protector == NULL) { - return TSI_UNIMPLEMENTED; + if (self == NULL || self->vtable == NULL || protector == NULL) { + return TSI_INVALID_ARGUMENT; } + if (self->frame_protector_created) return TSI_FAILED_PRECONDITION; + if (tsi_handshaker_get_result(self) != TSI_OK) return TSI_FAILED_PRECONDITION; + if (self->vtable->create_frame_protector == NULL) return TSI_UNIMPLEMENTED; result = self->vtable->create_frame_protector(self, max_protected_frame_size, protector); if (result == TSI_OK) { @@ -201,11 +191,9 @@ tsi_result tsi_handshaker_next( size_t received_bytes_size, unsigned char **bytes_to_send, size_t *bytes_to_send_size, tsi_handshaker_result **handshaker_result, tsi_handshaker_on_next_done_cb cb, void *user_data) { - if (self == NULL) return TSI_INVALID_ARGUMENT; + if (self == NULL || self->vtable == NULL) return TSI_INVALID_ARGUMENT; if (self->handshaker_result_created) return TSI_FAILED_PRECONDITION; - if (self->vtable == NULL || self->vtable->next == NULL) { - return TSI_UNIMPLEMENTED; - } + if (self->vtable->next == NULL) return TSI_UNIMPLEMENTED; return self->vtable->next(self, received_bytes, received_bytes_size, bytes_to_send, bytes_to_send_size, handshaker_result, cb, user_data); @@ -220,21 +208,21 @@ void tsi_handshaker_destroy(tsi_handshaker *self) { tsi_result tsi_handshaker_result_extract_peer(const tsi_handshaker_result *self, tsi_peer *peer) { - if (self == NULL || peer == NULL) return TSI_INVALID_ARGUMENT; - memset(peer, 0, sizeof(tsi_peer)); - if (self->vtable == NULL || self->vtable->extract_peer == NULL) { - return TSI_UNIMPLEMENTED; + if (self == NULL || self->vtable == NULL || peer == NULL) { + return TSI_INVALID_ARGUMENT; } + memset(peer, 0, sizeof(tsi_peer)); + if (self->vtable->extract_peer == NULL) return TSI_UNIMPLEMENTED; return self->vtable->extract_peer(self, peer); } tsi_result tsi_handshaker_result_create_frame_protector( const tsi_handshaker_result *self, size_t *max_protected_frame_size, tsi_frame_protector **protector) { - if (self == NULL || protector == NULL) return TSI_INVALID_ARGUMENT; - if (self->vtable == NULL || self->vtable->create_frame_protector == NULL) { - return TSI_UNIMPLEMENTED; + if (self == NULL || self->vtable == NULL || protector == NULL) { + return TSI_INVALID_ARGUMENT; } + if (self->vtable->create_frame_protector == NULL) return TSI_UNIMPLEMENTED; return self->vtable->create_frame_protector(self, max_protected_frame_size, protector); } @@ -242,12 +230,11 @@ tsi_result tsi_handshaker_result_create_frame_protector( tsi_result tsi_handshaker_result_get_unused_bytes( const tsi_handshaker_result *self, unsigned char **bytes, size_t *bytes_size) { - if (self == NULL || bytes == NULL || bytes_size == NULL) { + if (self == NULL || self->vtable == NULL || bytes == NULL || + bytes_size == NULL) { return TSI_INVALID_ARGUMENT; } - if (self->vtable == NULL || self->vtable->get_unused_bytes == NULL) { - return TSI_UNIMPLEMENTED; - } + if (self->vtable->get_unused_bytes == NULL) return TSI_UNIMPLEMENTED; return self->vtable->get_unused_bytes(self, bytes, bytes_size); } diff --git a/src/core/tsi/transport_security.h b/src/core/tsi/transport_security.h index 4a56c25602..67579f95df 100644 --- a/src/core/tsi/transport_security.h +++ b/src/core/tsi/transport_security.h @@ -86,6 +86,10 @@ struct tsi_handshaker { See transport_security_interface.h for documentation. */ typedef struct { tsi_result (*extract_peer)(const tsi_handshaker_result *self, tsi_peer *peer); + tsi_result (*create_zero_copy_grpc_protector)( + const tsi_handshaker_result *self, + size_t *max_output_protected_frame_size, + tsi_zero_copy_grpc_protector **protector); tsi_result (*create_frame_protector)(const tsi_handshaker_result *self, size_t *max_output_protected_frame_size, tsi_frame_protector **protector); diff --git a/src/core/tsi/transport_security_adapter.c b/src/core/tsi/transport_security_adapter.c index a0564945e4..15823ba335 100644 --- a/src/core/tsi/transport_security_adapter.c +++ b/src/core/tsi/transport_security_adapter.c @@ -66,8 +66,11 @@ static void adapter_result_destroy(tsi_handshaker_result *self) { } static const tsi_handshaker_result_vtable result_vtable = { - adapter_result_extract_peer, adapter_result_create_frame_protector, - adapter_result_get_unused_bytes, adapter_result_destroy, + adapter_result_extract_peer, + NULL, /* create_zero_copy_grpc_protector */ + adapter_result_create_frame_protector, + adapter_result_get_unused_bytes, + adapter_result_destroy, }; /* Ownership of wrapped tsi_handshaker is transferred to the result object. */ diff --git a/src/core/tsi/transport_security_grpc.c b/src/core/tsi/transport_security_grpc.c new file mode 100644 index 0000000000..ab2b6ddd54 --- /dev/null +++ b/src/core/tsi/transport_security_grpc.c @@ -0,0 +1,64 @@ +/* + * + * Copyright 2017 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/tsi/transport_security_grpc.h" + +/* This method creates a tsi_zero_copy_grpc_protector object. */ +tsi_result tsi_handshaker_result_create_zero_copy_grpc_protector( + const tsi_handshaker_result *self, size_t *max_protected_frame_size, + tsi_zero_copy_grpc_protector **protector) { + if (self == NULL || self->vtable == NULL || protector == NULL) { + return TSI_INVALID_ARGUMENT; + } + if (self->vtable->create_zero_copy_grpc_protector == NULL) { + return TSI_UNIMPLEMENTED; + } + return self->vtable->create_zero_copy_grpc_protector( + self, max_protected_frame_size, protector); +} + +/* --- tsi_zero_copy_grpc_protector common implementation. --- + + Calls specific implementation after state/input validation. */ + +tsi_result tsi_zero_copy_grpc_protector_protect( + tsi_zero_copy_grpc_protector *self, grpc_slice_buffer *unprotected_slices, + grpc_slice_buffer *protected_slices) { + if (self == NULL || self->vtable == NULL || unprotected_slices == NULL || + protected_slices == NULL) { + return TSI_INVALID_ARGUMENT; + } + if (self->vtable->protect == NULL) return TSI_UNIMPLEMENTED; + return self->vtable->protect(self, unprotected_slices, protected_slices); +} + +tsi_result tsi_zero_copy_grpc_protector_unprotect( + tsi_zero_copy_grpc_protector *self, grpc_slice_buffer *protected_slices, + grpc_slice_buffer *unprotected_slices) { + if (self == NULL || self->vtable == NULL || protected_slices == NULL || + unprotected_slices == NULL) { + return TSI_INVALID_ARGUMENT; + } + if (self->vtable->unprotect == NULL) return TSI_UNIMPLEMENTED; + return self->vtable->unprotect(self, protected_slices, unprotected_slices); +} + +void tsi_zero_copy_grpc_protector_destroy(tsi_zero_copy_grpc_protector *self) { + if (self == NULL) return; + self->vtable->destroy(self); +} diff --git a/src/core/tsi/transport_security_grpc.h b/src/core/tsi/transport_security_grpc.h new file mode 100644 index 0000000000..d80c81f40a --- /dev/null +++ b/src/core/tsi/transport_security_grpc.h @@ -0,0 +1,80 @@ +/* + * + * Copyright 2017 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPC_CORE_TSI_TRANSPORT_SECURITY_GRPC_H +#define GRPC_CORE_TSI_TRANSPORT_SECURITY_GRPC_H + +#include <grpc/slice_buffer.h> +#include "src/core/tsi/transport_security.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* This method creates a tsi_zero_copy_grpc_protector object. It return TSI_OK + assuming there is no fatal error. + The caller is responsible for destroying the protector. */ +tsi_result tsi_handshaker_result_create_zero_copy_grpc_protector( + const tsi_handshaker_result *self, size_t *max_output_protected_frame_size, + tsi_zero_copy_grpc_protector **protector); + +/* -- tsi_zero_copy_grpc_protector object -- */ + +/* Outputs protected frames. + - unprotected_slices is the unprotected data to be protected. + - protected_slices is the protected output frames. One or more frames + may be produced in this protect function. + - This method returns TSI_OK in case of success or a specific error code in + case of failure. */ +tsi_result tsi_zero_copy_groc_protector_protect( + tsi_zero_copy_grpc_protector *self, grpc_slice_buffer *unprotected_slices, + grpc_slice_buffer *protected_slices); + +/* Outputs unprotected bytes. + - protected_slices is the bytes of protected frames. + - unprotected_slices is the unprotected output data. + - This method returns TSI_OK in case of success. Success includes cases where + there is not enough data to output in which case unprotected_slices has 0 + bytes. */ +tsi_result tsi_zero_copy_grpc_protector_unprotect( + tsi_zero_copy_grpc_protector *self, grpc_slice_buffer *protected_slices, + grpc_slice_buffer *unprotected_slices); + +/* Destroys the tsi_zero_copy_grpc_protector object. */ +void tsi_zero_copy_grpc_protector_destroy(tsi_zero_copy_grpc_protector *self); + +/* Base for tsi_zero_copy_grpc_protector implementations. */ +typedef struct { + tsi_result (*protect)(tsi_zero_copy_grpc_protector *self, + grpc_slice_buffer *unprotected_slices, + grpc_slice_buffer *protected_slices); + tsi_result (*unprotect)(tsi_zero_copy_grpc_protector *self, + grpc_slice_buffer *protected_slices, + grpc_slice_buffer *unprotected_slices); + void (*destroy)(tsi_zero_copy_grpc_protector *self); +} tsi_zero_copy_grpc_protector_vtable; + +struct tsi_zero_copy_grpc_protector { + const tsi_zero_copy_grpc_protector_vtable *vtable; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* GRPC_CORE_TSI_TRANSPORT_SECURITY_GRPC_H */ diff --git a/src/core/tsi/transport_security_interface.h b/src/core/tsi/transport_security_interface.h index 137f8ee5c3..ed5acdcd37 100644 --- a/src/core/tsi/transport_security_interface.h +++ b/src/core/tsi/transport_security_interface.h @@ -62,6 +62,15 @@ const char *tsi_result_to_string(tsi_result result); extern grpc_tracer_flag tsi_tracing_enabled; +/* -- tsi_zero_copy_grpc_protector object -- + + This object protects and unprotects grpc slice buffers with zero or minimized + memory copy once the handshake is done. Implementations of this object must be + thread compatible. This object depends on grpc and the details of this object + is defined in transport_security_grpc.h. */ + +typedef struct tsi_zero_copy_grpc_protector tsi_zero_copy_grpc_protector; + /* --- tsi_frame_protector object --- This object protects and unprotects buffers once the handshake is done. |