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
local_zero_copy_grpc_protector_protect(tsi_zero_copy_grpc_protector * self,grpc_slice_buffer * unprotected_slices,grpc_slice_buffer * protected_slices)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
local_zero_copy_grpc_protector_unprotect(tsi_zero_copy_grpc_protector * self,grpc_slice_buffer * protected_slices,grpc_slice_buffer * unprotected_slices)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
local_zero_copy_grpc_protector_destroy(tsi_zero_copy_grpc_protector * self)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
local_zero_copy_grpc_protector_create(tsi_zero_copy_grpc_protector ** protector)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
handshaker_result_extract_peer(const tsi_handshaker_result * self,tsi_peer * peer)106 static tsi_result handshaker_result_extract_peer(
107 const tsi_handshaker_result* self, tsi_peer* peer) {
108 return TSI_OK;
109 }
110
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)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
handshaker_result_destroy(tsi_handshaker_result * self)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
create_handshaker_result(bool is_client,tsi_handshaker_result ** self)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
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)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
handshaker_destroy(tsi_handshaker * self)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
local_tsi_handshaker_create(bool is_client,tsi_handshaker ** self)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