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/gprpp/crash.h"
32 #include "src/core/lib/iomgr/exec_ctx.h"
33 #include "src/core/tsi/transport_security_grpc.h"
34
35 namespace {
36
37 // Main struct for local TSI zero-copy frame protector.
38 typedef struct local_zero_copy_grpc_protector {
39 tsi_zero_copy_grpc_protector base;
40 } local_zero_copy_grpc_protector;
41
42 // Main struct for local TSI handshaker result.
43 typedef struct local_tsi_handshaker_result {
44 tsi_handshaker_result base;
45 unsigned char* unused_bytes;
46 size_t unused_bytes_size;
47 } local_tsi_handshaker_result;
48
49 // Main struct for local TSI handshaker.
50 typedef struct local_tsi_handshaker {
51 tsi_handshaker base;
52 } local_tsi_handshaker;
53
54 // --- tsi_handshaker_result methods implementation. ---
55
handshaker_result_extract_peer(const tsi_handshaker_result *,tsi_peer *)56 tsi_result handshaker_result_extract_peer(const tsi_handshaker_result* /*self*/,
57 tsi_peer* /*peer*/) {
58 return TSI_OK;
59 }
60
handshaker_result_get_frame_protector_type(const tsi_handshaker_result *,tsi_frame_protector_type * frame_protector_type)61 tsi_result handshaker_result_get_frame_protector_type(
62 const tsi_handshaker_result* /*self*/,
63 tsi_frame_protector_type* frame_protector_type) {
64 *frame_protector_type = TSI_FRAME_PROTECTOR_NONE;
65 return TSI_OK;
66 }
67
handshaker_result_get_unused_bytes(const tsi_handshaker_result * self,const unsigned char ** bytes,size_t * bytes_size)68 tsi_result handshaker_result_get_unused_bytes(const tsi_handshaker_result* self,
69 const unsigned char** bytes,
70 size_t* bytes_size) {
71 if (self == nullptr || bytes == nullptr || bytes_size == nullptr) {
72 gpr_log(GPR_ERROR, "Invalid arguments to get_unused_bytes()");
73 return TSI_INVALID_ARGUMENT;
74 }
75 auto* result = reinterpret_cast<local_tsi_handshaker_result*>(
76 const_cast<tsi_handshaker_result*>(self));
77 *bytes_size = result->unused_bytes_size;
78 *bytes = result->unused_bytes;
79 return TSI_OK;
80 }
81
handshaker_result_destroy(tsi_handshaker_result * self)82 void handshaker_result_destroy(tsi_handshaker_result* self) {
83 if (self == nullptr) {
84 return;
85 }
86 local_tsi_handshaker_result* result =
87 reinterpret_cast<local_tsi_handshaker_result*>(
88 const_cast<tsi_handshaker_result*>(self));
89 gpr_free(result->unused_bytes);
90 gpr_free(result);
91 }
92
93 const tsi_handshaker_result_vtable result_vtable = {
94 handshaker_result_extract_peer,
95 handshaker_result_get_frame_protector_type,
96 nullptr, // handshaker_result_create_zero_copy_grpc_protector
97 nullptr, // handshaker_result_create_frame_protector
98 handshaker_result_get_unused_bytes,
99 handshaker_result_destroy};
100
create_handshaker_result(const unsigned char * received_bytes,size_t received_bytes_size,tsi_handshaker_result ** self)101 tsi_result create_handshaker_result(const unsigned char* received_bytes,
102 size_t received_bytes_size,
103 tsi_handshaker_result** self) {
104 if (self == nullptr) {
105 gpr_log(GPR_ERROR, "Invalid arguments to create_handshaker_result()");
106 return TSI_INVALID_ARGUMENT;
107 }
108 local_tsi_handshaker_result* result =
109 grpc_core::Zalloc<local_tsi_handshaker_result>();
110 if (received_bytes_size > 0) {
111 result->unused_bytes =
112 static_cast<unsigned char*>(gpr_malloc(received_bytes_size));
113 memcpy(result->unused_bytes, received_bytes, received_bytes_size);
114 }
115 result->unused_bytes_size = received_bytes_size;
116 result->base.vtable = &result_vtable;
117 *self = &result->base;
118 return TSI_OK;
119 }
120
121 // --- tsi_handshaker methods implementation. ---
122
handshaker_next(tsi_handshaker * self,const unsigned char * received_bytes,size_t received_bytes_size,const unsigned char **,size_t * bytes_to_send_size,tsi_handshaker_result ** result,tsi_handshaker_on_next_done_cb,void *,std::string * error)123 tsi_result handshaker_next(tsi_handshaker* self,
124 const unsigned char* received_bytes,
125 size_t received_bytes_size,
126 const unsigned char** /*bytes_to_send*/,
127 size_t* bytes_to_send_size,
128 tsi_handshaker_result** result,
129 tsi_handshaker_on_next_done_cb /*cb*/,
130 void* /*user_data*/, std::string* error) {
131 if (self == nullptr) {
132 gpr_log(GPR_ERROR, "Invalid arguments to handshaker_next()");
133 if (error != nullptr) *error = "invalid argument";
134 return TSI_INVALID_ARGUMENT;
135 }
136 // Note that there is no interaction between TSI peers, and all operations are
137 // local.
138 //
139 *bytes_to_send_size = 0;
140 create_handshaker_result(received_bytes, received_bytes_size, result);
141 return TSI_OK;
142 }
143
handshaker_destroy(tsi_handshaker * self)144 void handshaker_destroy(tsi_handshaker* self) {
145 if (self == nullptr) {
146 return;
147 }
148 local_tsi_handshaker* handshaker =
149 reinterpret_cast<local_tsi_handshaker*>(self);
150 gpr_free(handshaker);
151 }
152
153 const tsi_handshaker_vtable handshaker_vtable = {
154 nullptr, // get_bytes_to_send_to_peer -- deprecated
155 nullptr, // process_bytes_from_peer -- deprecated
156 nullptr, // get_result -- deprecated
157 nullptr, // extract_peer -- deprecated
158 nullptr, // create_frame_protector -- deprecated
159 handshaker_destroy,
160 handshaker_next,
161 nullptr, // shutdown
162 };
163
164 } // namespace
165
tsi_local_handshaker_create(tsi_handshaker ** self)166 tsi_result tsi_local_handshaker_create(tsi_handshaker** self) {
167 if (self == nullptr) {
168 gpr_log(GPR_ERROR, "Invalid arguments to local_tsi_handshaker_create()");
169 return TSI_INVALID_ARGUMENT;
170 }
171 local_tsi_handshaker* handshaker = grpc_core::Zalloc<local_tsi_handshaker>();
172 handshaker->base.vtable = &handshaker_vtable;
173 *self = &handshaker->base;
174 return TSI_OK;
175 }
176