/* * * Copyright 2018 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 #include "src/core/tsi/local_transport_security.h" #include #include #include #include #include #include #include "src/core/lib/iomgr/exec_ctx.h" #include "src/core/tsi/transport_security_grpc.h" /* Main struct for local TSI zero-copy frame protector. */ typedef struct local_zero_copy_grpc_protector { tsi_zero_copy_grpc_protector base; } local_zero_copy_grpc_protector; /* Main struct for local TSI handshaker result. */ typedef struct local_tsi_handshaker_result { tsi_handshaker_result base; bool is_client; } local_tsi_handshaker_result; /* Main struct for local TSI handshaker. */ typedef struct local_tsi_handshaker { tsi_handshaker base; bool is_client; } local_tsi_handshaker; /* --- tsi_zero_copy_grpc_protector methods implementation. --- */ static tsi_result local_zero_copy_grpc_protector_protect( tsi_zero_copy_grpc_protector* self, grpc_slice_buffer* unprotected_slices, grpc_slice_buffer* protected_slices) { if (self == nullptr || unprotected_slices == nullptr || protected_slices == nullptr) { gpr_log(GPR_ERROR, "Invalid nullptr arguments to zero-copy grpc protect."); return TSI_INVALID_ARGUMENT; } grpc_slice_buffer_move_into(unprotected_slices, protected_slices); return TSI_OK; } static tsi_result local_zero_copy_grpc_protector_unprotect( tsi_zero_copy_grpc_protector* self, grpc_slice_buffer* protected_slices, grpc_slice_buffer* unprotected_slices) { if (self == nullptr || unprotected_slices == nullptr || protected_slices == nullptr) { gpr_log(GPR_ERROR, "Invalid nullptr arguments to zero-copy grpc unprotect."); return TSI_INVALID_ARGUMENT; } grpc_slice_buffer_move_into(protected_slices, unprotected_slices); return TSI_OK; } static void local_zero_copy_grpc_protector_destroy( tsi_zero_copy_grpc_protector* self) { gpr_free(self); } static const tsi_zero_copy_grpc_protector_vtable local_zero_copy_grpc_protector_vtable = { local_zero_copy_grpc_protector_protect, local_zero_copy_grpc_protector_unprotect, local_zero_copy_grpc_protector_destroy}; tsi_result local_zero_copy_grpc_protector_create( tsi_zero_copy_grpc_protector** protector) { if (grpc_core::ExecCtx::Get() == nullptr || protector == nullptr) { gpr_log( GPR_ERROR, "Invalid nullptr arguments to local_zero_copy_grpc_protector create."); return TSI_INVALID_ARGUMENT; } local_zero_copy_grpc_protector* impl = static_cast(gpr_zalloc(sizeof(*impl))); impl->base.vtable = &local_zero_copy_grpc_protector_vtable; *protector = &impl->base; return TSI_OK; } /* --- tsi_handshaker_result methods implementation. --- */ static tsi_result handshaker_result_extract_peer( const tsi_handshaker_result* self, tsi_peer* peer) { return TSI_OK; } static tsi_result 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) { if (self == nullptr || protector == nullptr) { gpr_log(GPR_ERROR, "Invalid arguments to create_zero_copy_grpc_protector()"); return TSI_INVALID_ARGUMENT; } tsi_result ok = local_zero_copy_grpc_protector_create(protector); if (ok != TSI_OK) { gpr_log(GPR_ERROR, "Failed to create zero-copy grpc protector"); } return ok; } static void handshaker_result_destroy(tsi_handshaker_result* self) { if (self == nullptr) { return; } local_tsi_handshaker_result* result = reinterpret_cast( const_cast(self)); gpr_free(result); } static const tsi_handshaker_result_vtable result_vtable = { handshaker_result_extract_peer, handshaker_result_create_zero_copy_grpc_protector, nullptr, /* handshaker_result_create_frame_protector */ nullptr, /* handshaker_result_get_unused_bytes */ handshaker_result_destroy}; static tsi_result create_handshaker_result(bool is_client, tsi_handshaker_result** self) { if (self == nullptr) { gpr_log(GPR_ERROR, "Invalid arguments to create_handshaker_result()"); return TSI_INVALID_ARGUMENT; } local_tsi_handshaker_result* result = static_cast(gpr_zalloc(sizeof(*result))); result->is_client = is_client; result->base.vtable = &result_vtable; *self = &result->base; return TSI_OK; } /* --- tsi_handshaker methods implementation. --- */ static tsi_result handshaker_next( tsi_handshaker* self, const unsigned char* received_bytes, size_t received_bytes_size, const unsigned char** bytes_to_send, size_t* bytes_to_send_size, tsi_handshaker_result** result, tsi_handshaker_on_next_done_cb cb, void* user_data) { if (self == nullptr) { gpr_log(GPR_ERROR, "Invalid arguments to handshaker_next()"); return TSI_INVALID_ARGUMENT; } /* Note that there is no interaction between TSI peers, and all operations are * local. */ local_tsi_handshaker* handshaker = reinterpret_cast(self); *bytes_to_send_size = 0; create_handshaker_result(handshaker->is_client, result); return TSI_OK; } static void handshaker_destroy(tsi_handshaker* self) { if (self == nullptr) { return; } local_tsi_handshaker* handshaker = reinterpret_cast(self); gpr_free(handshaker); } static const tsi_handshaker_vtable handshaker_vtable = { nullptr, /* get_bytes_to_send_to_peer -- deprecated */ nullptr, /* process_bytes_from_peer -- deprecated */ nullptr, /* get_result -- deprecated */ nullptr, /* extract_peer -- deprecated */ nullptr, /* create_frame_protector -- deprecated */ handshaker_destroy, handshaker_next, nullptr, /* shutdown */ }; tsi_result local_tsi_handshaker_create(bool is_client, tsi_handshaker** self) { if (self == nullptr) { gpr_log(GPR_ERROR, "Invalid arguments to local_tsi_handshaker_create()"); return TSI_INVALID_ARGUMENT; } local_tsi_handshaker* handshaker = static_cast(gpr_zalloc(sizeof(*handshaker))); handshaker->is_client = is_client; handshaker->base.vtable = &handshaker_vtable; *self = &handshaker->base; return TSI_OK; }