1 /* 2 * 3 * Copyright 2018 gRPC authors. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 */ 18 19 #include <grpc/support/port_platform.h> 20 21 #include "src/core/tsi/local_transport_security.h" 22 23 #include <stdio.h> 24 #include <stdlib.h> 25 #include <string.h> 26 27 #include <grpc/support/alloc.h> 28 #include <grpc/support/log.h> 29 #include <grpc/support/string_util.h> 30 31 #include "src/core/lib/iomgr/exec_ctx.h" 32 #include "src/core/tsi/transport_security_grpc.h" 33 34 /* Main struct for local TSI zero-copy frame protector. */ 35 typedef struct local_zero_copy_grpc_protector { 36 tsi_zero_copy_grpc_protector base; 37 } local_zero_copy_grpc_protector; 38 39 /* Main struct for local TSI handshaker result. */ 40 typedef struct local_tsi_handshaker_result { 41 tsi_handshaker_result base; 42 bool is_client; 43 } local_tsi_handshaker_result; 44 45 /* Main struct for local TSI handshaker. */ 46 typedef struct local_tsi_handshaker { 47 tsi_handshaker base; 48 bool is_client; 49 } local_tsi_handshaker; 50 51 /* --- tsi_zero_copy_grpc_protector methods implementation. --- */ 52 53 static tsi_result local_zero_copy_grpc_protector_protect( 54 tsi_zero_copy_grpc_protector* self, grpc_slice_buffer* unprotected_slices, 55 grpc_slice_buffer* protected_slices) { 56 if (self == nullptr || unprotected_slices == nullptr || 57 protected_slices == nullptr) { 58 gpr_log(GPR_ERROR, "Invalid nullptr arguments to zero-copy grpc protect."); 59 return TSI_INVALID_ARGUMENT; 60 } 61 grpc_slice_buffer_move_into(unprotected_slices, protected_slices); 62 return TSI_OK; 63 } 64 65 static tsi_result local_zero_copy_grpc_protector_unprotect( 66 tsi_zero_copy_grpc_protector* self, grpc_slice_buffer* protected_slices, 67 grpc_slice_buffer* unprotected_slices) { 68 if (self == nullptr || unprotected_slices == nullptr || 69 protected_slices == nullptr) { 70 gpr_log(GPR_ERROR, 71 "Invalid nullptr arguments to zero-copy grpc unprotect."); 72 return TSI_INVALID_ARGUMENT; 73 } 74 grpc_slice_buffer_move_into(protected_slices, unprotected_slices); 75 return TSI_OK; 76 } 77 78 static void local_zero_copy_grpc_protector_destroy( 79 tsi_zero_copy_grpc_protector* self) { 80 gpr_free(self); 81 } 82 83 static const tsi_zero_copy_grpc_protector_vtable 84 local_zero_copy_grpc_protector_vtable = { 85 local_zero_copy_grpc_protector_protect, 86 local_zero_copy_grpc_protector_unprotect, 87 local_zero_copy_grpc_protector_destroy}; 88 89 tsi_result local_zero_copy_grpc_protector_create( 90 tsi_zero_copy_grpc_protector** protector) { 91 if (grpc_core::ExecCtx::Get() == nullptr || protector == nullptr) { 92 gpr_log( 93 GPR_ERROR, 94 "Invalid nullptr arguments to local_zero_copy_grpc_protector create."); 95 return TSI_INVALID_ARGUMENT; 96 } 97 local_zero_copy_grpc_protector* impl = 98 static_cast<local_zero_copy_grpc_protector*>(gpr_zalloc(sizeof(*impl))); 99 impl->base.vtable = &local_zero_copy_grpc_protector_vtable; 100 *protector = &impl->base; 101 return TSI_OK; 102 } 103 104 /* --- tsi_handshaker_result methods implementation. --- */ 105 106 static tsi_result handshaker_result_extract_peer( 107 const tsi_handshaker_result* self, tsi_peer* peer) { 108 return TSI_OK; 109 } 110 111 static tsi_result handshaker_result_create_zero_copy_grpc_protector( 112 const tsi_handshaker_result* self, size_t* max_output_protected_frame_size, 113 tsi_zero_copy_grpc_protector** protector) { 114 if (self == nullptr || protector == nullptr) { 115 gpr_log(GPR_ERROR, 116 "Invalid arguments to create_zero_copy_grpc_protector()"); 117 return TSI_INVALID_ARGUMENT; 118 } 119 tsi_result ok = local_zero_copy_grpc_protector_create(protector); 120 if (ok != TSI_OK) { 121 gpr_log(GPR_ERROR, "Failed to create zero-copy grpc protector"); 122 } 123 return ok; 124 } 125 126 static void handshaker_result_destroy(tsi_handshaker_result* self) { 127 if (self == nullptr) { 128 return; 129 } 130 local_tsi_handshaker_result* result = 131 reinterpret_cast<local_tsi_handshaker_result*>( 132 const_cast<tsi_handshaker_result*>(self)); 133 gpr_free(result); 134 } 135 136 static const tsi_handshaker_result_vtable result_vtable = { 137 handshaker_result_extract_peer, 138 handshaker_result_create_zero_copy_grpc_protector, 139 nullptr, /* handshaker_result_create_frame_protector */ 140 nullptr, /* handshaker_result_get_unused_bytes */ 141 handshaker_result_destroy}; 142 143 static tsi_result create_handshaker_result(bool is_client, 144 tsi_handshaker_result** self) { 145 if (self == nullptr) { 146 gpr_log(GPR_ERROR, "Invalid arguments to create_handshaker_result()"); 147 return TSI_INVALID_ARGUMENT; 148 } 149 local_tsi_handshaker_result* result = 150 static_cast<local_tsi_handshaker_result*>(gpr_zalloc(sizeof(*result))); 151 result->is_client = is_client; 152 result->base.vtable = &result_vtable; 153 *self = &result->base; 154 return TSI_OK; 155 } 156 157 /* --- tsi_handshaker methods implementation. --- */ 158 159 static tsi_result handshaker_next( 160 tsi_handshaker* self, const unsigned char* received_bytes, 161 size_t received_bytes_size, const unsigned char** bytes_to_send, 162 size_t* bytes_to_send_size, tsi_handshaker_result** result, 163 tsi_handshaker_on_next_done_cb cb, void* user_data) { 164 if (self == nullptr) { 165 gpr_log(GPR_ERROR, "Invalid arguments to handshaker_next()"); 166 return TSI_INVALID_ARGUMENT; 167 } 168 /* Note that there is no interaction between TSI peers, and all operations are 169 * local. 170 */ 171 local_tsi_handshaker* handshaker = 172 reinterpret_cast<local_tsi_handshaker*>(self); 173 *bytes_to_send_size = 0; 174 create_handshaker_result(handshaker->is_client, result); 175 return TSI_OK; 176 } 177 178 static void handshaker_destroy(tsi_handshaker* self) { 179 if (self == nullptr) { 180 return; 181 } 182 local_tsi_handshaker* handshaker = 183 reinterpret_cast<local_tsi_handshaker*>(self); 184 gpr_free(handshaker); 185 } 186 187 static const tsi_handshaker_vtable handshaker_vtable = { 188 nullptr, /* get_bytes_to_send_to_peer -- deprecated */ 189 nullptr, /* process_bytes_from_peer -- deprecated */ 190 nullptr, /* get_result -- deprecated */ 191 nullptr, /* extract_peer -- deprecated */ 192 nullptr, /* create_frame_protector -- deprecated */ 193 handshaker_destroy, 194 handshaker_next, 195 nullptr, /* shutdown */ 196 }; 197 198 tsi_result local_tsi_handshaker_create(bool is_client, tsi_handshaker** self) { 199 if (self == nullptr) { 200 gpr_log(GPR_ERROR, "Invalid arguments to local_tsi_handshaker_create()"); 201 return TSI_INVALID_ARGUMENT; 202 } 203 local_tsi_handshaker* handshaker = 204 static_cast<local_tsi_handshaker*>(gpr_zalloc(sizeof(*handshaker))); 205 handshaker->is_client = is_client; 206 handshaker->base.vtable = &handshaker_vtable; 207 *self = &handshaker->base; 208 return TSI_OK; 209 } 210