Built motion from commit 6a09e18b.|2.6.11
[motion2.git] / legacy-libs / grpc-cloned / deps / grpc / src / core / tsi / alts / handshaker / alts_tsi_handshaker.cc
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/string_util.h>
30 #include <grpc/support/sync.h>
31 #include <grpc/support/thd_id.h>
32
33 #include "src/core/lib/gprpp/thd.h"
34 #include "src/core/lib/iomgr/closure.h"
35 #include "src/core/lib/slice/slice_internal.h"
36 #include "src/core/tsi/alts/frame_protector/alts_frame_protector.h"
37 #include "src/core/tsi/alts/handshaker/alts_handshaker_client.h"
38 #include "src/core/tsi/alts/handshaker/alts_shared_resource.h"
39 #include "src/core/tsi/alts/handshaker/alts_tsi_utils.h"
40 #include "src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.h"
41
42 /* Main struct for ALTS TSI handshaker. */
43 struct alts_tsi_handshaker {
44   tsi_handshaker base;
45   alts_handshaker_client* client;
46   grpc_slice target_name;
47   bool is_client;
48   bool has_sent_start_message;
49   bool has_created_handshaker_client;
50   char* handshaker_service_url;
51   grpc_pollset_set* interested_parties;
52   grpc_alts_credentials_options* options;
53   alts_handshaker_client_vtable* client_vtable_for_testing;
54   grpc_channel* channel;
55 };
56
57 /* Main struct for ALTS TSI handshaker result. */
58 typedef struct alts_tsi_handshaker_result {
59   tsi_handshaker_result base;
60   char* peer_identity;
61   char* key_data;
62   unsigned char* unused_bytes;
63   size_t unused_bytes_size;
64   grpc_slice rpc_versions;
65   bool is_client;
66 } alts_tsi_handshaker_result;
67
68 static tsi_result handshaker_result_extract_peer(
69     const tsi_handshaker_result* self, tsi_peer* peer) {
70   if (self == nullptr || peer == nullptr) {
71     gpr_log(GPR_ERROR, "Invalid argument to handshaker_result_extract_peer()");
72     return TSI_INVALID_ARGUMENT;
73   }
74   alts_tsi_handshaker_result* result =
75       reinterpret_cast<alts_tsi_handshaker_result*>(
76           const_cast<tsi_handshaker_result*>(self));
77   GPR_ASSERT(kTsiAltsNumOfPeerProperties == 3);
78   tsi_result ok = tsi_construct_peer(kTsiAltsNumOfPeerProperties, peer);
79   int index = 0;
80   if (ok != TSI_OK) {
81     gpr_log(GPR_ERROR, "Failed to construct tsi peer");
82     return ok;
83   }
84   GPR_ASSERT(&peer->properties[index] != nullptr);
85   ok = tsi_construct_string_peer_property_from_cstring(
86       TSI_CERTIFICATE_TYPE_PEER_PROPERTY, TSI_ALTS_CERTIFICATE_TYPE,
87       &peer->properties[index]);
88   if (ok != TSI_OK) {
89     tsi_peer_destruct(peer);
90     gpr_log(GPR_ERROR, "Failed to set tsi peer property");
91     return ok;
92   }
93   index++;
94   GPR_ASSERT(&peer->properties[index] != nullptr);
95   ok = tsi_construct_string_peer_property_from_cstring(
96       TSI_ALTS_SERVICE_ACCOUNT_PEER_PROPERTY, result->peer_identity,
97       &peer->properties[index]);
98   if (ok != TSI_OK) {
99     tsi_peer_destruct(peer);
100     gpr_log(GPR_ERROR, "Failed to set tsi peer property");
101   }
102   index++;
103   GPR_ASSERT(&peer->properties[index] != nullptr);
104   ok = tsi_construct_string_peer_property(
105       TSI_ALTS_RPC_VERSIONS,
106       reinterpret_cast<char*>(GRPC_SLICE_START_PTR(result->rpc_versions)),
107       GRPC_SLICE_LENGTH(result->rpc_versions), &peer->properties[2]);
108   if (ok != TSI_OK) {
109     tsi_peer_destruct(peer);
110     gpr_log(GPR_ERROR, "Failed to set tsi peer property");
111   }
112   GPR_ASSERT(++index == kTsiAltsNumOfPeerProperties);
113   return ok;
114 }
115
116 static tsi_result handshaker_result_create_zero_copy_grpc_protector(
117     const tsi_handshaker_result* self, size_t* max_output_protected_frame_size,
118     tsi_zero_copy_grpc_protector** protector) {
119   if (self == nullptr || protector == nullptr) {
120     gpr_log(GPR_ERROR,
121             "Invalid arguments to create_zero_copy_grpc_protector()");
122     return TSI_INVALID_ARGUMENT;
123   }
124   alts_tsi_handshaker_result* result =
125       reinterpret_cast<alts_tsi_handshaker_result*>(
126           const_cast<tsi_handshaker_result*>(self));
127   tsi_result ok = alts_zero_copy_grpc_protector_create(
128       reinterpret_cast<const uint8_t*>(result->key_data),
129       kAltsAes128GcmRekeyKeyLength, /*is_rekey=*/true, result->is_client,
130       /*is_integrity_only=*/false, /*enable_extra_copy=*/false,
131       max_output_protected_frame_size, protector);
132   if (ok != TSI_OK) {
133     gpr_log(GPR_ERROR, "Failed to create zero-copy grpc protector");
134   }
135   return ok;
136 }
137
138 static tsi_result handshaker_result_create_frame_protector(
139     const tsi_handshaker_result* self, size_t* max_output_protected_frame_size,
140     tsi_frame_protector** protector) {
141   if (self == nullptr || protector == nullptr) {
142     gpr_log(GPR_ERROR,
143             "Invalid arguments to handshaker_result_create_frame_protector()");
144     return TSI_INVALID_ARGUMENT;
145   }
146   alts_tsi_handshaker_result* result =
147       reinterpret_cast<alts_tsi_handshaker_result*>(
148           const_cast<tsi_handshaker_result*>(self));
149   tsi_result ok = alts_create_frame_protector(
150       reinterpret_cast<const uint8_t*>(result->key_data),
151       kAltsAes128GcmRekeyKeyLength, result->is_client, /*is_rekey=*/true,
152       max_output_protected_frame_size, protector);
153   if (ok != TSI_OK) {
154     gpr_log(GPR_ERROR, "Failed to create frame protector");
155   }
156   return ok;
157 }
158
159 static tsi_result handshaker_result_get_unused_bytes(
160     const tsi_handshaker_result* self, const unsigned char** bytes,
161     size_t* bytes_size) {
162   if (self == nullptr || bytes == nullptr || bytes_size == nullptr) {
163     gpr_log(GPR_ERROR,
164             "Invalid arguments to handshaker_result_get_unused_bytes()");
165     return TSI_INVALID_ARGUMENT;
166   }
167   alts_tsi_handshaker_result* result =
168       reinterpret_cast<alts_tsi_handshaker_result*>(
169           const_cast<tsi_handshaker_result*>(self));
170   *bytes = result->unused_bytes;
171   *bytes_size = result->unused_bytes_size;
172   return TSI_OK;
173 }
174
175 static void handshaker_result_destroy(tsi_handshaker_result* self) {
176   if (self == nullptr) {
177     return;
178   }
179   alts_tsi_handshaker_result* result =
180       reinterpret_cast<alts_tsi_handshaker_result*>(
181           const_cast<tsi_handshaker_result*>(self));
182   gpr_free(result->peer_identity);
183   gpr_free(result->key_data);
184   gpr_free(result->unused_bytes);
185   grpc_slice_unref_internal(result->rpc_versions);
186   gpr_free(result);
187 }
188
189 static const tsi_handshaker_result_vtable result_vtable = {
190     handshaker_result_extract_peer,
191     handshaker_result_create_zero_copy_grpc_protector,
192     handshaker_result_create_frame_protector,
193     handshaker_result_get_unused_bytes, handshaker_result_destroy};
194
195 tsi_result alts_tsi_handshaker_result_create(grpc_gcp_HandshakerResp* resp,
196                                              bool is_client,
197                                              tsi_handshaker_result** self) {
198   if (self == nullptr || resp == nullptr) {
199     gpr_log(GPR_ERROR, "Invalid arguments to create_handshaker_result()");
200     return TSI_INVALID_ARGUMENT;
201   }
202   const grpc_gcp_HandshakerResult* hresult =
203       grpc_gcp_HandshakerResp_result(resp);
204   const grpc_gcp_Identity* identity =
205       grpc_gcp_HandshakerResult_peer_identity(hresult);
206   if (identity == nullptr) {
207     gpr_log(GPR_ERROR, "Invalid identity");
208     return TSI_FAILED_PRECONDITION;
209   }
210   upb_strview service_account = grpc_gcp_Identity_service_account(identity);
211   if (service_account.size == 0) {
212     gpr_log(GPR_ERROR, "Invalid service account");
213     return TSI_FAILED_PRECONDITION;
214   }
215   upb_strview key_data = grpc_gcp_HandshakerResult_key_data(hresult);
216   if (key_data.size < kAltsAes128GcmRekeyKeyLength) {
217     gpr_log(GPR_ERROR, "Bad key length");
218     return TSI_FAILED_PRECONDITION;
219   }
220   const grpc_gcp_RpcProtocolVersions* peer_rpc_version =
221       grpc_gcp_HandshakerResult_peer_rpc_versions(hresult);
222   if (peer_rpc_version == nullptr) {
223     gpr_log(GPR_ERROR, "Peer does not set RPC protocol versions.");
224     return TSI_FAILED_PRECONDITION;
225   }
226   alts_tsi_handshaker_result* result =
227       static_cast<alts_tsi_handshaker_result*>(gpr_zalloc(sizeof(*result)));
228   result->key_data =
229       static_cast<char*>(gpr_zalloc(kAltsAes128GcmRekeyKeyLength));
230   memcpy(result->key_data, key_data.data, kAltsAes128GcmRekeyKeyLength);
231   result->peer_identity =
232       static_cast<char*>(gpr_zalloc(service_account.size + 1));
233   memcpy(result->peer_identity, service_account.data, service_account.size);
234   upb::Arena arena;
235   bool serialized = grpc_gcp_rpc_protocol_versions_encode(
236       peer_rpc_version, arena.ptr(), &result->rpc_versions);
237   if (!serialized) {
238     gpr_log(GPR_ERROR, "Failed to serialize peer's RPC protocol versions.");
239     return TSI_FAILED_PRECONDITION;
240   }
241   result->is_client = is_client;
242   result->base.vtable = &result_vtable;
243   *self = &result->base;
244   return TSI_OK;
245 }
246
247 /* gRPC provided callback used when gRPC thread model is applied. */
248 static void on_handshaker_service_resp_recv(void* arg, grpc_error* error) {
249   alts_handshaker_client* client = static_cast<alts_handshaker_client*>(arg);
250   if (client == nullptr) {
251     gpr_log(GPR_ERROR, "ALTS handshaker client is nullptr");
252     return;
253   }
254   bool success = true;
255   if (error != GRPC_ERROR_NONE) {
256     gpr_log(GPR_ERROR,
257             "ALTS handshaker on_handshaker_service_resp_recv error: %s",
258             grpc_error_string(error));
259     success = false;
260   }
261   alts_handshaker_client_handle_response(client, success);
262 }
263
264 /* gRPC provided callback used when dedicatd CQ and thread are used.
265  * It serves to safely bring the control back to application. */
266 static void on_handshaker_service_resp_recv_dedicated(void* arg,
267                                                       grpc_error* error) {
268   alts_shared_resource_dedicated* resource =
269       grpc_alts_get_shared_resource_dedicated();
270   grpc_cq_end_op(resource->cq, arg, GRPC_ERROR_NONE,
271                  [](void* done_arg, grpc_cq_completion* storage) {}, nullptr,
272                  &resource->storage);
273 }
274
275 static tsi_result handshaker_next(
276     tsi_handshaker* self, const unsigned char* received_bytes,
277     size_t received_bytes_size, const unsigned char** bytes_to_send,
278     size_t* bytes_to_send_size, tsi_handshaker_result** result,
279     tsi_handshaker_on_next_done_cb cb, void* user_data) {
280   if (self == nullptr || cb == nullptr) {
281     gpr_log(GPR_ERROR, "Invalid arguments to handshaker_next()");
282     return TSI_INVALID_ARGUMENT;
283   }
284   if (self->handshake_shutdown) {
285     gpr_log(GPR_ERROR, "TSI handshake shutdown");
286     return TSI_HANDSHAKE_SHUTDOWN;
287   }
288   alts_tsi_handshaker* handshaker =
289       reinterpret_cast<alts_tsi_handshaker*>(self);
290   tsi_result ok = TSI_OK;
291   if (!handshaker->has_created_handshaker_client) {
292     if (handshaker->channel == nullptr) {
293       grpc_alts_shared_resource_dedicated_start(
294           handshaker->handshaker_service_url);
295       handshaker->interested_parties =
296           grpc_alts_get_shared_resource_dedicated()->interested_parties;
297       GPR_ASSERT(handshaker->interested_parties != nullptr);
298     }
299     grpc_iomgr_cb_func grpc_cb = handshaker->channel == nullptr
300                                      ? on_handshaker_service_resp_recv_dedicated
301                                      : on_handshaker_service_resp_recv;
302     grpc_channel* channel =
303         handshaker->channel == nullptr
304             ? grpc_alts_get_shared_resource_dedicated()->channel
305             : handshaker->channel;
306     handshaker->client = alts_grpc_handshaker_client_create(
307         handshaker, channel, handshaker->handshaker_service_url,
308         handshaker->interested_parties, handshaker->options,
309         handshaker->target_name, grpc_cb, cb, user_data,
310         handshaker->client_vtable_for_testing, handshaker->is_client);
311     if (handshaker->client == nullptr) {
312       gpr_log(GPR_ERROR, "Failed to create ALTS handshaker client");
313       return TSI_FAILED_PRECONDITION;
314     }
315     handshaker->has_created_handshaker_client = true;
316   }
317   if (handshaker->channel == nullptr &&
318       handshaker->client_vtable_for_testing == nullptr) {
319     GPR_ASSERT(grpc_cq_begin_op(grpc_alts_get_shared_resource_dedicated()->cq,
320                                 handshaker->client));
321   }
322   grpc_slice slice = (received_bytes == nullptr || received_bytes_size == 0)
323                          ? grpc_empty_slice()
324                          : grpc_slice_from_copied_buffer(
325                                reinterpret_cast<const char*>(received_bytes),
326                                received_bytes_size);
327   if (!handshaker->has_sent_start_message) {
328     ok = handshaker->is_client
329              ? alts_handshaker_client_start_client(handshaker->client)
330              : alts_handshaker_client_start_server(handshaker->client, &slice);
331     handshaker->has_sent_start_message = true;
332   } else {
333     ok = alts_handshaker_client_next(handshaker->client, &slice);
334   }
335   grpc_slice_unref_internal(slice);
336   if (ok != TSI_OK) {
337     gpr_log(GPR_ERROR, "Failed to schedule ALTS handshaker requests");
338     return ok;
339   }
340   return TSI_ASYNC;
341 }
342
343 /*
344  * This API will be invoked by a non-gRPC application, and an ExecCtx needs
345  * to be explicitly created in order to invoke ALTS handshaker client API's
346  * that assumes the caller is inside gRPC core.
347  */
348 static tsi_result handshaker_next_dedicated(
349     tsi_handshaker* self, const unsigned char* received_bytes,
350     size_t received_bytes_size, const unsigned char** bytes_to_send,
351     size_t* bytes_to_send_size, tsi_handshaker_result** result,
352     tsi_handshaker_on_next_done_cb cb, void* user_data) {
353   grpc_core::ExecCtx exec_ctx;
354   return handshaker_next(self, received_bytes, received_bytes_size,
355                          bytes_to_send, bytes_to_send_size, result, cb,
356                          user_data);
357 }
358
359 static void handshaker_shutdown(tsi_handshaker* self) {
360   GPR_ASSERT(self != nullptr);
361   if (self->handshake_shutdown) {
362     return;
363   }
364   alts_tsi_handshaker* handshaker =
365       reinterpret_cast<alts_tsi_handshaker*>(self);
366   alts_handshaker_client_shutdown(handshaker->client);
367 }
368
369 static void handshaker_destroy(tsi_handshaker* self) {
370   if (self == nullptr) {
371     return;
372   }
373   alts_tsi_handshaker* handshaker =
374       reinterpret_cast<alts_tsi_handshaker*>(self);
375   alts_handshaker_client_destroy(handshaker->client);
376   grpc_slice_unref_internal(handshaker->target_name);
377   grpc_alts_credentials_options_destroy(handshaker->options);
378   if (handshaker->channel != nullptr) {
379     grpc_channel_destroy(handshaker->channel);
380   }
381   gpr_free(handshaker->handshaker_service_url);
382   gpr_free(handshaker);
383 }
384
385 static const tsi_handshaker_vtable handshaker_vtable = {
386     nullptr,         nullptr,
387     nullptr,         nullptr,
388     nullptr,         handshaker_destroy,
389     handshaker_next, handshaker_shutdown};
390
391 static const tsi_handshaker_vtable handshaker_vtable_dedicated = {
392     nullptr,
393     nullptr,
394     nullptr,
395     nullptr,
396     nullptr,
397     handshaker_destroy,
398     handshaker_next_dedicated,
399     handshaker_shutdown};
400
401 bool alts_tsi_handshaker_has_shutdown(alts_tsi_handshaker* handshaker) {
402   GPR_ASSERT(handshaker != nullptr);
403   return handshaker->base.handshake_shutdown;
404 }
405
406 tsi_result alts_tsi_handshaker_create(
407     const grpc_alts_credentials_options* options, const char* target_name,
408     const char* handshaker_service_url, bool is_client,
409     grpc_pollset_set* interested_parties, tsi_handshaker** self) {
410   if (handshaker_service_url == nullptr || self == nullptr ||
411       options == nullptr || (is_client && target_name == nullptr)) {
412     gpr_log(GPR_ERROR, "Invalid arguments to alts_tsi_handshaker_create()");
413     return TSI_INVALID_ARGUMENT;
414   }
415   alts_tsi_handshaker* handshaker =
416       static_cast<alts_tsi_handshaker*>(gpr_zalloc(sizeof(*handshaker)));
417   bool use_dedicated_cq = interested_parties == nullptr;
418   handshaker->client = nullptr;
419   handshaker->is_client = is_client;
420   handshaker->has_sent_start_message = false;
421   handshaker->target_name = target_name == nullptr
422                                 ? grpc_empty_slice()
423                                 : grpc_slice_from_static_string(target_name);
424   handshaker->interested_parties = interested_parties;
425   handshaker->has_created_handshaker_client = false;
426   handshaker->handshaker_service_url = gpr_strdup(handshaker_service_url);
427   handshaker->options = grpc_alts_credentials_options_copy(options);
428   handshaker->base.vtable =
429       use_dedicated_cq ? &handshaker_vtable_dedicated : &handshaker_vtable;
430   handshaker->channel =
431       use_dedicated_cq
432           ? nullptr
433           : grpc_insecure_channel_create(handshaker->handshaker_service_url,
434                                          nullptr, nullptr);
435   *self = &handshaker->base;
436   return TSI_OK;
437 }
438
439 void alts_tsi_handshaker_result_set_unused_bytes(tsi_handshaker_result* self,
440                                                  grpc_slice* recv_bytes,
441                                                  size_t bytes_consumed) {
442   GPR_ASSERT(recv_bytes != nullptr && self != nullptr);
443   if (GRPC_SLICE_LENGTH(*recv_bytes) == bytes_consumed) {
444     return;
445   }
446   alts_tsi_handshaker_result* result =
447       reinterpret_cast<alts_tsi_handshaker_result*>(self);
448   result->unused_bytes_size = GRPC_SLICE_LENGTH(*recv_bytes) - bytes_consumed;
449   result->unused_bytes =
450       static_cast<unsigned char*>(gpr_zalloc(result->unused_bytes_size));
451   memcpy(result->unused_bytes,
452          GRPC_SLICE_START_PTR(*recv_bytes) + bytes_consumed,
453          result->unused_bytes_size);
454 }
455
456 namespace grpc_core {
457 namespace internal {
458
459 bool alts_tsi_handshaker_get_has_sent_start_message_for_testing(
460     alts_tsi_handshaker* handshaker) {
461   GPR_ASSERT(handshaker != nullptr);
462   return handshaker->has_sent_start_message;
463 }
464
465 void alts_tsi_handshaker_set_client_vtable_for_testing(
466     alts_tsi_handshaker* handshaker, alts_handshaker_client_vtable* vtable) {
467   GPR_ASSERT(handshaker != nullptr);
468   handshaker->client_vtable_for_testing = vtable;
469 }
470
471 bool alts_tsi_handshaker_get_is_client_for_testing(
472     alts_tsi_handshaker* handshaker) {
473   GPR_ASSERT(handshaker != nullptr);
474   return handshaker->is_client;
475 }
476
477 alts_handshaker_client* alts_tsi_handshaker_get_client_for_testing(
478     alts_tsi_handshaker* handshaker) {
479   return handshaker->client;
480 }
481
482 }  // namespace internal
483 }  // namespace grpc_core