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