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