• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/alts/handshaker/alts_tsi_handshaker.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/sync.h>
30 #include <grpc/support/thd_id.h>
31 
32 #include "src/core/lib/gpr/host_port.h"
33 #include "src/core/lib/gprpp/thd.h"
34 #include "src/core/lib/slice/slice_internal.h"
35 #include "src/core/tsi/alts/frame_protector/alts_frame_protector.h"
36 #include "src/core/tsi/alts/handshaker/alts_handshaker_client.h"
37 #include "src/core/tsi/alts/handshaker/alts_tsi_utils.h"
38 #include "src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.h"
39 #include "src/core/tsi/alts_transport_security.h"
40 
41 #define TSI_ALTS_INITIAL_BUFFER_SIZE 256
42 
43 static alts_shared_resource* kSharedResource = alts_get_shared_resource();
44 
45 /* Main struct for ALTS TSI handshaker. */
46 typedef struct alts_tsi_handshaker {
47   tsi_handshaker base;
48   alts_handshaker_client* client;
49   grpc_slice recv_bytes;
50   grpc_slice target_name;
51   unsigned char* buffer;
52   size_t buffer_size;
53   bool is_client;
54   bool has_sent_start_message;
55   grpc_alts_credentials_options* options;
56 } alts_tsi_handshaker;
57 
58 /* Main struct for ALTS TSI handshaker result. */
59 typedef struct alts_tsi_handshaker_result {
60   tsi_handshaker_result base;
61   char* peer_identity;
62   char* key_data;
63   unsigned char* unused_bytes;
64   size_t unused_bytes_size;
65   grpc_slice rpc_versions;
66   bool is_client;
67 } alts_tsi_handshaker_result;
68 
handshaker_result_extract_peer(const tsi_handshaker_result * self,tsi_peer * peer)69 static tsi_result handshaker_result_extract_peer(
70     const tsi_handshaker_result* self, tsi_peer* peer) {
71   if (self == nullptr || peer == nullptr) {
72     gpr_log(GPR_ERROR, "Invalid argument to handshaker_result_extract_peer()");
73     return TSI_INVALID_ARGUMENT;
74   }
75   alts_tsi_handshaker_result* result =
76       reinterpret_cast<alts_tsi_handshaker_result*>(
77           const_cast<tsi_handshaker_result*>(self));
78   GPR_ASSERT(kTsiAltsNumOfPeerProperties == 3);
79   tsi_result ok = tsi_construct_peer(kTsiAltsNumOfPeerProperties, peer);
80   int index = 0;
81   if (ok != TSI_OK) {
82     gpr_log(GPR_ERROR, "Failed to construct tsi peer");
83     return ok;
84   }
85   GPR_ASSERT(&peer->properties[index] != nullptr);
86   ok = tsi_construct_string_peer_property_from_cstring(
87       TSI_CERTIFICATE_TYPE_PEER_PROPERTY, TSI_ALTS_CERTIFICATE_TYPE,
88       &peer->properties[index]);
89   if (ok != TSI_OK) {
90     tsi_peer_destruct(peer);
91     gpr_log(GPR_ERROR, "Failed to set tsi peer property");
92     return ok;
93   }
94   index++;
95   GPR_ASSERT(&peer->properties[index] != nullptr);
96   ok = tsi_construct_string_peer_property_from_cstring(
97       TSI_ALTS_SERVICE_ACCOUNT_PEER_PROPERTY, result->peer_identity,
98       &peer->properties[index]);
99   if (ok != TSI_OK) {
100     tsi_peer_destruct(peer);
101     gpr_log(GPR_ERROR, "Failed to set tsi peer property");
102   }
103   index++;
104   GPR_ASSERT(&peer->properties[index] != nullptr);
105   ok = tsi_construct_string_peer_property(
106       TSI_ALTS_RPC_VERSIONS,
107       reinterpret_cast<char*>(GRPC_SLICE_START_PTR(result->rpc_versions)),
108       GRPC_SLICE_LENGTH(result->rpc_versions), &peer->properties[2]);
109   if (ok != TSI_OK) {
110     tsi_peer_destruct(peer);
111     gpr_log(GPR_ERROR, "Failed to set tsi peer property");
112   }
113   GPR_ASSERT(++index == kTsiAltsNumOfPeerProperties);
114   return ok;
115 }
116 
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)117 static tsi_result handshaker_result_create_zero_copy_grpc_protector(
118     const tsi_handshaker_result* self, size_t* max_output_protected_frame_size,
119     tsi_zero_copy_grpc_protector** protector) {
120   if (self == nullptr || protector == nullptr) {
121     gpr_log(GPR_ERROR,
122             "Invalid arguments to create_zero_copy_grpc_protector()");
123     return TSI_INVALID_ARGUMENT;
124   }
125   alts_tsi_handshaker_result* result =
126       reinterpret_cast<alts_tsi_handshaker_result*>(
127           const_cast<tsi_handshaker_result*>(self));
128   tsi_result ok = alts_zero_copy_grpc_protector_create(
129       reinterpret_cast<const uint8_t*>(result->key_data),
130       kAltsAes128GcmRekeyKeyLength, /*is_rekey=*/true, result->is_client,
131       /*is_integrity_only=*/false, /*enable_extra_copy=*/false,
132       max_output_protected_frame_size, protector);
133   if (ok != TSI_OK) {
134     gpr_log(GPR_ERROR, "Failed to create zero-copy grpc protector");
135   }
136   return ok;
137 }
138 
handshaker_result_create_frame_protector(const tsi_handshaker_result * self,size_t * max_output_protected_frame_size,tsi_frame_protector ** protector)139 static tsi_result handshaker_result_create_frame_protector(
140     const tsi_handshaker_result* self, size_t* max_output_protected_frame_size,
141     tsi_frame_protector** protector) {
142   if (self == nullptr || protector == nullptr) {
143     gpr_log(GPR_ERROR,
144             "Invalid arguments to handshaker_result_create_frame_protector()");
145     return TSI_INVALID_ARGUMENT;
146   }
147   alts_tsi_handshaker_result* result =
148       reinterpret_cast<alts_tsi_handshaker_result*>(
149           const_cast<tsi_handshaker_result*>(self));
150   tsi_result ok = alts_create_frame_protector(
151       reinterpret_cast<const uint8_t*>(result->key_data),
152       kAltsAes128GcmRekeyKeyLength, result->is_client, /*is_rekey=*/true,
153       max_output_protected_frame_size, protector);
154   if (ok != TSI_OK) {
155     gpr_log(GPR_ERROR, "Failed to create frame protector");
156   }
157   return ok;
158 }
159 
handshaker_result_get_unused_bytes(const tsi_handshaker_result * self,const unsigned char ** bytes,size_t * bytes_size)160 static tsi_result handshaker_result_get_unused_bytes(
161     const tsi_handshaker_result* self, const unsigned char** bytes,
162     size_t* bytes_size) {
163   if (self == nullptr || bytes == nullptr || bytes_size == nullptr) {
164     gpr_log(GPR_ERROR,
165             "Invalid arguments to handshaker_result_get_unused_bytes()");
166     return TSI_INVALID_ARGUMENT;
167   }
168   alts_tsi_handshaker_result* result =
169       reinterpret_cast<alts_tsi_handshaker_result*>(
170           const_cast<tsi_handshaker_result*>(self));
171   *bytes = result->unused_bytes;
172   *bytes_size = result->unused_bytes_size;
173   return TSI_OK;
174 }
175 
handshaker_result_destroy(tsi_handshaker_result * self)176 static void handshaker_result_destroy(tsi_handshaker_result* self) {
177   if (self == nullptr) {
178     return;
179   }
180   alts_tsi_handshaker_result* result =
181       reinterpret_cast<alts_tsi_handshaker_result*>(
182           const_cast<tsi_handshaker_result*>(self));
183   gpr_free(result->peer_identity);
184   gpr_free(result->key_data);
185   gpr_free(result->unused_bytes);
186   grpc_slice_unref_internal(result->rpc_versions);
187   gpr_free(result);
188 }
189 
190 static const tsi_handshaker_result_vtable result_vtable = {
191     handshaker_result_extract_peer,
192     handshaker_result_create_zero_copy_grpc_protector,
193     handshaker_result_create_frame_protector,
194     handshaker_result_get_unused_bytes, handshaker_result_destroy};
195 
create_handshaker_result(grpc_gcp_handshaker_resp * resp,bool is_client,tsi_handshaker_result ** self)196 static tsi_result create_handshaker_result(grpc_gcp_handshaker_resp* resp,
197                                            bool is_client,
198                                            tsi_handshaker_result** self) {
199   if (self == nullptr || resp == nullptr) {
200     gpr_log(GPR_ERROR, "Invalid arguments to create_handshaker_result()");
201     return TSI_INVALID_ARGUMENT;
202   }
203   grpc_slice* key = static_cast<grpc_slice*>(resp->result.key_data.arg);
204   GPR_ASSERT(key != nullptr);
205   grpc_slice* identity =
206       static_cast<grpc_slice*>(resp->result.peer_identity.service_account.arg);
207   if (identity == nullptr) {
208     gpr_log(GPR_ERROR, "Invalid service account");
209     return TSI_FAILED_PRECONDITION;
210   }
211   if (GRPC_SLICE_LENGTH(*key) < kAltsAes128GcmRekeyKeyLength) {
212     gpr_log(GPR_ERROR, "Bad key length");
213     return TSI_FAILED_PRECONDITION;
214   }
215   alts_tsi_handshaker_result* result =
216       static_cast<alts_tsi_handshaker_result*>(gpr_zalloc(sizeof(*result)));
217   result->key_data =
218       static_cast<char*>(gpr_zalloc(kAltsAes128GcmRekeyKeyLength));
219   memcpy(result->key_data, GRPC_SLICE_START_PTR(*key),
220          kAltsAes128GcmRekeyKeyLength);
221   result->peer_identity = grpc_slice_to_c_string(*identity);
222   if (!resp->result.has_peer_rpc_versions) {
223     gpr_log(GPR_ERROR, "Peer does not set RPC protocol versions.");
224     return TSI_FAILED_PRECONDITION;
225   }
226   if (!grpc_gcp_rpc_protocol_versions_encode(&resp->result.peer_rpc_versions,
227                                              &result->rpc_versions)) {
228     gpr_log(GPR_ERROR, "Failed to serialize peer's RPC protocol versions.");
229     return TSI_FAILED_PRECONDITION;
230   }
231   result->is_client = is_client;
232   result->base.vtable = &result_vtable;
233   *self = &result->base;
234   return TSI_OK;
235 }
236 
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)237 static tsi_result handshaker_next(
238     tsi_handshaker* self, const unsigned char* received_bytes,
239     size_t received_bytes_size, const unsigned char** bytes_to_send,
240     size_t* bytes_to_send_size, tsi_handshaker_result** result,
241     tsi_handshaker_on_next_done_cb cb, void* user_data) {
242   if (self == nullptr || cb == nullptr) {
243     gpr_log(GPR_ERROR, "Invalid arguments to handshaker_next()");
244     return TSI_INVALID_ARGUMENT;
245   }
246   if (self->handshake_shutdown) {
247     gpr_log(GPR_ERROR, "TSI handshake shutdown");
248     return TSI_HANDSHAKE_SHUTDOWN;
249   }
250   alts_tsi_handshaker* handshaker =
251       reinterpret_cast<alts_tsi_handshaker*>(self);
252   tsi_result ok = TSI_OK;
253   alts_tsi_event* event = nullptr;
254   ok = alts_tsi_event_create(handshaker, cb, user_data, handshaker->options,
255                              handshaker->target_name, &event);
256   if (ok != TSI_OK) {
257     gpr_log(GPR_ERROR, "Failed to create ALTS TSI event");
258     return ok;
259   }
260   grpc_slice slice = (received_bytes == nullptr || received_bytes_size == 0)
261                          ? grpc_empty_slice()
262                          : grpc_slice_from_copied_buffer(
263                                reinterpret_cast<const char*>(received_bytes),
264                                received_bytes_size);
265   if (!handshaker->has_sent_start_message) {
266     ok = handshaker->is_client
267              ? alts_handshaker_client_start_client(handshaker->client, event)
268              : alts_handshaker_client_start_server(handshaker->client, event,
269                                                    &slice);
270     handshaker->has_sent_start_message = true;
271   } else {
272     if (!GRPC_SLICE_IS_EMPTY(handshaker->recv_bytes)) {
273       grpc_slice_unref_internal(handshaker->recv_bytes);
274     }
275     handshaker->recv_bytes = grpc_slice_ref(slice);
276     ok = alts_handshaker_client_next(handshaker->client, event, &slice);
277   }
278   grpc_slice_unref_internal(slice);
279   if (ok != TSI_OK) {
280     gpr_log(GPR_ERROR, "Failed to schedule ALTS handshaker requests");
281     return ok;
282   }
283   return TSI_ASYNC;
284 }
285 
handshaker_shutdown(tsi_handshaker * self)286 static void handshaker_shutdown(tsi_handshaker* self) {
287   GPR_ASSERT(self != nullptr);
288   if (self->handshake_shutdown) {
289     return;
290   }
291   alts_tsi_handshaker* handshaker =
292       reinterpret_cast<alts_tsi_handshaker*>(self);
293   alts_handshaker_client_shutdown(handshaker->client);
294 }
295 
handshaker_destroy(tsi_handshaker * self)296 static void handshaker_destroy(tsi_handshaker* self) {
297   if (self == nullptr) {
298     return;
299   }
300   alts_tsi_handshaker* handshaker =
301       reinterpret_cast<alts_tsi_handshaker*>(self);
302   alts_handshaker_client_destroy(handshaker->client);
303   grpc_slice_unref_internal(handshaker->recv_bytes);
304   grpc_slice_unref_internal(handshaker->target_name);
305   grpc_alts_credentials_options_destroy(handshaker->options);
306   gpr_free(handshaker->buffer);
307   gpr_free(handshaker);
308 }
309 
310 static const tsi_handshaker_vtable handshaker_vtable = {
311     nullptr,         nullptr,
312     nullptr,         nullptr,
313     nullptr,         handshaker_destroy,
314     handshaker_next, handshaker_shutdown};
315 
thread_worker(void * arg)316 static void thread_worker(void* arg) {
317   while (true) {
318     grpc_event event = grpc_completion_queue_next(
319         kSharedResource->cq, gpr_inf_future(GPR_CLOCK_REALTIME), nullptr);
320     GPR_ASSERT(event.type != GRPC_QUEUE_TIMEOUT);
321     if (event.type == GRPC_QUEUE_SHUTDOWN) {
322       /* signal alts_tsi_shutdown() to destroy completion queue. */
323       grpc_tsi_alts_signal_for_cq_destroy();
324       break;
325     }
326     /* event.type == GRPC_OP_COMPLETE. */
327     alts_tsi_event* alts_event = static_cast<alts_tsi_event*>(event.tag);
328     alts_tsi_event_dispatch_to_handshaker(alts_event, event.success);
329     alts_tsi_event_destroy(alts_event);
330   }
331 }
332 
init_shared_resources(const char * handshaker_service_url)333 static void init_shared_resources(const char* handshaker_service_url) {
334   GPR_ASSERT(handshaker_service_url != nullptr);
335   gpr_mu_lock(&kSharedResource->mu);
336   if (kSharedResource->channel == nullptr) {
337     gpr_cv_init(&kSharedResource->cv);
338     kSharedResource->channel =
339         grpc_insecure_channel_create(handshaker_service_url, nullptr, nullptr);
340     kSharedResource->cq = grpc_completion_queue_create_for_next(nullptr);
341     kSharedResource->thread =
342         grpc_core::Thread("alts_tsi_handshaker", &thread_worker, nullptr);
343     kSharedResource->thread.Start();
344   }
345   gpr_mu_unlock(&kSharedResource->mu);
346 }
347 
alts_tsi_handshaker_create(const grpc_alts_credentials_options * options,const char * target_name,const char * handshaker_service_url,bool is_client,tsi_handshaker ** self)348 tsi_result alts_tsi_handshaker_create(
349     const grpc_alts_credentials_options* options, const char* target_name,
350     const char* handshaker_service_url, bool is_client, tsi_handshaker** self) {
351   if (handshaker_service_url == nullptr || self == nullptr ||
352       options == nullptr || (is_client && target_name == nullptr)) {
353     gpr_log(GPR_ERROR, "Invalid arguments to alts_tsi_handshaker_create()");
354     return TSI_INVALID_ARGUMENT;
355   }
356   init_shared_resources(handshaker_service_url);
357   alts_handshaker_client* client = alts_grpc_handshaker_client_create(
358       kSharedResource->channel, kSharedResource->cq, handshaker_service_url);
359   if (client == nullptr) {
360     gpr_log(GPR_ERROR, "Failed to create ALTS handshaker client");
361     return TSI_FAILED_PRECONDITION;
362   }
363   alts_tsi_handshaker* handshaker =
364       static_cast<alts_tsi_handshaker*>(gpr_zalloc(sizeof(*handshaker)));
365   handshaker->client = client;
366   handshaker->buffer_size = TSI_ALTS_INITIAL_BUFFER_SIZE;
367   handshaker->buffer =
368       static_cast<unsigned char*>(gpr_zalloc(handshaker->buffer_size));
369   handshaker->is_client = is_client;
370   handshaker->has_sent_start_message = false;
371   handshaker->target_name = target_name == nullptr
372                                 ? grpc_empty_slice()
373                                 : grpc_slice_from_static_string(target_name);
374   handshaker->options = grpc_alts_credentials_options_copy(options);
375   handshaker->base.vtable = &handshaker_vtable;
376   *self = &handshaker->base;
377   return TSI_OK;
378 }
379 
is_handshake_finished_properly(grpc_gcp_handshaker_resp * resp)380 static bool is_handshake_finished_properly(grpc_gcp_handshaker_resp* resp) {
381   GPR_ASSERT(resp != nullptr);
382   if (resp->has_result) {
383     return true;
384   }
385   return false;
386 }
387 
set_unused_bytes(tsi_handshaker_result * self,grpc_slice * recv_bytes,size_t bytes_consumed)388 static void set_unused_bytes(tsi_handshaker_result* self,
389                              grpc_slice* recv_bytes, size_t bytes_consumed) {
390   GPR_ASSERT(recv_bytes != nullptr && self != nullptr);
391   if (GRPC_SLICE_LENGTH(*recv_bytes) == bytes_consumed) {
392     return;
393   }
394   alts_tsi_handshaker_result* result =
395       reinterpret_cast<alts_tsi_handshaker_result*>(self);
396   result->unused_bytes_size = GRPC_SLICE_LENGTH(*recv_bytes) - bytes_consumed;
397   result->unused_bytes =
398       static_cast<unsigned char*>(gpr_zalloc(result->unused_bytes_size));
399   memcpy(result->unused_bytes,
400          GRPC_SLICE_START_PTR(*recv_bytes) + bytes_consumed,
401          result->unused_bytes_size);
402 }
403 
alts_tsi_handshaker_handle_response(alts_tsi_handshaker * handshaker,grpc_byte_buffer * recv_buffer,grpc_status_code status,grpc_slice * details,tsi_handshaker_on_next_done_cb cb,void * user_data,bool is_ok)404 void alts_tsi_handshaker_handle_response(alts_tsi_handshaker* handshaker,
405                                          grpc_byte_buffer* recv_buffer,
406                                          grpc_status_code status,
407                                          grpc_slice* details,
408                                          tsi_handshaker_on_next_done_cb cb,
409                                          void* user_data, bool is_ok) {
410   /* Invalid input check. */
411   if (cb == nullptr) {
412     gpr_log(GPR_ERROR,
413             "cb is nullptr in alts_tsi_handshaker_handle_response()");
414     return;
415   }
416   if (handshaker == nullptr || recv_buffer == nullptr) {
417     gpr_log(GPR_ERROR,
418             "Invalid arguments to alts_tsi_handshaker_handle_response()");
419     cb(TSI_INTERNAL_ERROR, user_data, nullptr, 0, nullptr);
420     return;
421   }
422   if (handshaker->base.handshake_shutdown) {
423     gpr_log(GPR_ERROR, "TSI handshake shutdown");
424     cb(TSI_HANDSHAKE_SHUTDOWN, user_data, nullptr, 0, nullptr);
425     return;
426   }
427   /* Failed grpc call check. */
428   if (!is_ok || status != GRPC_STATUS_OK) {
429     gpr_log(GPR_ERROR, "grpc call made to handshaker service failed");
430     if (details != nullptr) {
431       char* error_details = grpc_slice_to_c_string(*details);
432       gpr_log(GPR_ERROR, "error details:%s", error_details);
433       gpr_free(error_details);
434     }
435     cb(TSI_INTERNAL_ERROR, user_data, nullptr, 0, nullptr);
436     return;
437   }
438   grpc_gcp_handshaker_resp* resp =
439       alts_tsi_utils_deserialize_response(recv_buffer);
440   /* Invalid handshaker response check. */
441   if (resp == nullptr) {
442     gpr_log(GPR_ERROR, "alts_tsi_utils_deserialize_response() failed");
443     cb(TSI_DATA_CORRUPTED, user_data, nullptr, 0, nullptr);
444     return;
445   }
446   grpc_slice* slice = static_cast<grpc_slice*>(resp->out_frames.arg);
447   unsigned char* bytes_to_send = nullptr;
448   size_t bytes_to_send_size = 0;
449   if (slice != nullptr) {
450     bytes_to_send_size = GRPC_SLICE_LENGTH(*slice);
451     while (bytes_to_send_size > handshaker->buffer_size) {
452       handshaker->buffer_size *= 2;
453       handshaker->buffer = static_cast<unsigned char*>(
454           gpr_realloc(handshaker->buffer, handshaker->buffer_size));
455     }
456     memcpy(handshaker->buffer, GRPC_SLICE_START_PTR(*slice),
457            bytes_to_send_size);
458     bytes_to_send = handshaker->buffer;
459   }
460   tsi_handshaker_result* result = nullptr;
461   if (is_handshake_finished_properly(resp)) {
462     create_handshaker_result(resp, handshaker->is_client, &result);
463     set_unused_bytes(result, &handshaker->recv_bytes, resp->bytes_consumed);
464   }
465   grpc_status_code code = static_cast<grpc_status_code>(resp->status.code);
466   if (code != GRPC_STATUS_OK) {
467     grpc_slice* details = static_cast<grpc_slice*>(resp->status.details.arg);
468     if (details != nullptr) {
469       char* error_details = grpc_slice_to_c_string(*details);
470       gpr_log(GPR_ERROR, "Error from handshaker service:%s", error_details);
471       gpr_free(error_details);
472     }
473   }
474   grpc_gcp_handshaker_resp_destroy(resp);
475   cb(alts_tsi_utils_convert_to_tsi_result(code), user_data, bytes_to_send,
476      bytes_to_send_size, result);
477 }
478 
479 namespace grpc_core {
480 namespace internal {
481 
alts_tsi_handshaker_get_has_sent_start_message_for_testing(alts_tsi_handshaker * handshaker)482 bool alts_tsi_handshaker_get_has_sent_start_message_for_testing(
483     alts_tsi_handshaker* handshaker) {
484   GPR_ASSERT(handshaker != nullptr);
485   return handshaker->has_sent_start_message;
486 }
487 
alts_tsi_handshaker_get_is_client_for_testing(alts_tsi_handshaker * handshaker)488 bool alts_tsi_handshaker_get_is_client_for_testing(
489     alts_tsi_handshaker* handshaker) {
490   GPR_ASSERT(handshaker != nullptr);
491   return handshaker->is_client;
492 }
493 
alts_tsi_handshaker_set_recv_bytes_for_testing(alts_tsi_handshaker * handshaker,grpc_slice * slice)494 void alts_tsi_handshaker_set_recv_bytes_for_testing(
495     alts_tsi_handshaker* handshaker, grpc_slice* slice) {
496   GPR_ASSERT(handshaker != nullptr && slice != nullptr);
497   handshaker->recv_bytes = grpc_slice_ref(*slice);
498 }
499 
alts_tsi_handshaker_get_recv_bytes_for_testing(alts_tsi_handshaker * handshaker)500 grpc_slice alts_tsi_handshaker_get_recv_bytes_for_testing(
501     alts_tsi_handshaker* handshaker) {
502   GPR_ASSERT(handshaker != nullptr);
503   return handshaker->recv_bytes;
504 }
505 
alts_tsi_handshaker_set_client_for_testing(alts_tsi_handshaker * handshaker,alts_handshaker_client * client)506 void alts_tsi_handshaker_set_client_for_testing(
507     alts_tsi_handshaker* handshaker, alts_handshaker_client* client) {
508   GPR_ASSERT(handshaker != nullptr && client != nullptr);
509   alts_handshaker_client_destroy(handshaker->client);
510   handshaker->client = client;
511 }
512 
alts_tsi_handshaker_get_client_for_testing(alts_tsi_handshaker * handshaker)513 alts_handshaker_client* alts_tsi_handshaker_get_client_for_testing(
514     alts_tsi_handshaker* handshaker) {
515   return handshaker->client;
516 }
517 
518 }  // namespace internal
519 }  // namespace grpc_core
520