Home | History | Annotate | Download | only in tsi
      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/iomgr/exec_ctx.h"
     32 #include "src/core/tsi/transport_security_grpc.h"
     33 
     34 /* Main struct for local TSI zero-copy frame protector. */
     35 typedef struct local_zero_copy_grpc_protector {
     36   tsi_zero_copy_grpc_protector base;
     37 } local_zero_copy_grpc_protector;
     38 
     39 /* Main struct for local TSI handshaker result. */
     40 typedef struct local_tsi_handshaker_result {
     41   tsi_handshaker_result base;
     42   bool is_client;
     43 } local_tsi_handshaker_result;
     44 
     45 /* Main struct for local TSI handshaker. */
     46 typedef struct local_tsi_handshaker {
     47   tsi_handshaker base;
     48   bool is_client;
     49 } local_tsi_handshaker;
     50 
     51 /* --- tsi_zero_copy_grpc_protector methods implementation. --- */
     52 
     53 static tsi_result local_zero_copy_grpc_protector_protect(
     54     tsi_zero_copy_grpc_protector* self, grpc_slice_buffer* unprotected_slices,
     55     grpc_slice_buffer* protected_slices) {
     56   if (self == nullptr || unprotected_slices == nullptr ||
     57       protected_slices == nullptr) {
     58     gpr_log(GPR_ERROR, "Invalid nullptr arguments to zero-copy grpc protect.");
     59     return TSI_INVALID_ARGUMENT;
     60   }
     61   grpc_slice_buffer_move_into(unprotected_slices, protected_slices);
     62   return TSI_OK;
     63 }
     64 
     65 static tsi_result local_zero_copy_grpc_protector_unprotect(
     66     tsi_zero_copy_grpc_protector* self, grpc_slice_buffer* protected_slices,
     67     grpc_slice_buffer* unprotected_slices) {
     68   if (self == nullptr || unprotected_slices == nullptr ||
     69       protected_slices == nullptr) {
     70     gpr_log(GPR_ERROR,
     71             "Invalid nullptr arguments to zero-copy grpc unprotect.");
     72     return TSI_INVALID_ARGUMENT;
     73   }
     74   grpc_slice_buffer_move_into(protected_slices, unprotected_slices);
     75   return TSI_OK;
     76 }
     77 
     78 static void local_zero_copy_grpc_protector_destroy(
     79     tsi_zero_copy_grpc_protector* self) {
     80   gpr_free(self);
     81 }
     82 
     83 static const tsi_zero_copy_grpc_protector_vtable
     84     local_zero_copy_grpc_protector_vtable = {
     85         local_zero_copy_grpc_protector_protect,
     86         local_zero_copy_grpc_protector_unprotect,
     87         local_zero_copy_grpc_protector_destroy};
     88 
     89 tsi_result local_zero_copy_grpc_protector_create(
     90     tsi_zero_copy_grpc_protector** protector) {
     91   if (grpc_core::ExecCtx::Get() == nullptr || protector == nullptr) {
     92     gpr_log(
     93         GPR_ERROR,
     94         "Invalid nullptr arguments to local_zero_copy_grpc_protector create.");
     95     return TSI_INVALID_ARGUMENT;
     96   }
     97   local_zero_copy_grpc_protector* impl =
     98       static_cast<local_zero_copy_grpc_protector*>(gpr_zalloc(sizeof(*impl)));
     99   impl->base.vtable = &local_zero_copy_grpc_protector_vtable;
    100   *protector = &impl->base;
    101   return TSI_OK;
    102 }
    103 
    104 /* --- tsi_handshaker_result methods implementation. --- */
    105 
    106 static tsi_result handshaker_result_extract_peer(
    107     const tsi_handshaker_result* self, tsi_peer* peer) {
    108   return TSI_OK;
    109 }
    110 
    111 static tsi_result handshaker_result_create_zero_copy_grpc_protector(
    112     const tsi_handshaker_result* self, size_t* max_output_protected_frame_size,
    113     tsi_zero_copy_grpc_protector** protector) {
    114   if (self == nullptr || protector == nullptr) {
    115     gpr_log(GPR_ERROR,
    116             "Invalid arguments to create_zero_copy_grpc_protector()");
    117     return TSI_INVALID_ARGUMENT;
    118   }
    119   tsi_result ok = local_zero_copy_grpc_protector_create(protector);
    120   if (ok != TSI_OK) {
    121     gpr_log(GPR_ERROR, "Failed to create zero-copy grpc protector");
    122   }
    123   return ok;
    124 }
    125 
    126 static void handshaker_result_destroy(tsi_handshaker_result* self) {
    127   if (self == nullptr) {
    128     return;
    129   }
    130   local_tsi_handshaker_result* result =
    131       reinterpret_cast<local_tsi_handshaker_result*>(
    132           const_cast<tsi_handshaker_result*>(self));
    133   gpr_free(result);
    134 }
    135 
    136 static const tsi_handshaker_result_vtable result_vtable = {
    137     handshaker_result_extract_peer,
    138     handshaker_result_create_zero_copy_grpc_protector,
    139     nullptr, /* handshaker_result_create_frame_protector */
    140     nullptr, /* handshaker_result_get_unused_bytes */
    141     handshaker_result_destroy};
    142 
    143 static tsi_result create_handshaker_result(bool is_client,
    144                                            tsi_handshaker_result** self) {
    145   if (self == nullptr) {
    146     gpr_log(GPR_ERROR, "Invalid arguments to create_handshaker_result()");
    147     return TSI_INVALID_ARGUMENT;
    148   }
    149   local_tsi_handshaker_result* result =
    150       static_cast<local_tsi_handshaker_result*>(gpr_zalloc(sizeof(*result)));
    151   result->is_client = is_client;
    152   result->base.vtable = &result_vtable;
    153   *self = &result->base;
    154   return TSI_OK;
    155 }
    156 
    157 /* --- tsi_handshaker methods implementation. --- */
    158 
    159 static tsi_result handshaker_next(
    160     tsi_handshaker* self, const unsigned char* received_bytes,
    161     size_t received_bytes_size, const unsigned char** bytes_to_send,
    162     size_t* bytes_to_send_size, tsi_handshaker_result** result,
    163     tsi_handshaker_on_next_done_cb cb, void* user_data) {
    164   if (self == nullptr) {
    165     gpr_log(GPR_ERROR, "Invalid arguments to handshaker_next()");
    166     return TSI_INVALID_ARGUMENT;
    167   }
    168   /* Note that there is no interaction between TSI peers, and all operations are
    169    * local.
    170    */
    171   local_tsi_handshaker* handshaker =
    172       reinterpret_cast<local_tsi_handshaker*>(self);
    173   *bytes_to_send_size = 0;
    174   create_handshaker_result(handshaker->is_client, result);
    175   return TSI_OK;
    176 }
    177 
    178 static void handshaker_destroy(tsi_handshaker* self) {
    179   if (self == nullptr) {
    180     return;
    181   }
    182   local_tsi_handshaker* handshaker =
    183       reinterpret_cast<local_tsi_handshaker*>(self);
    184   gpr_free(handshaker);
    185 }
    186 
    187 static const tsi_handshaker_vtable handshaker_vtable = {
    188     nullptr, /* get_bytes_to_send_to_peer -- deprecated */
    189     nullptr, /* process_bytes_from_peer   -- deprecated */
    190     nullptr, /* get_result                -- deprecated */
    191     nullptr, /* extract_peer              -- deprecated */
    192     nullptr, /* create_frame_protector    -- deprecated */
    193     handshaker_destroy,
    194     handshaker_next,
    195     nullptr, /* shutdown */
    196 };
    197 
    198 tsi_result local_tsi_handshaker_create(bool is_client, tsi_handshaker** self) {
    199   if (self == nullptr) {
    200     gpr_log(GPR_ERROR, "Invalid arguments to local_tsi_handshaker_create()");
    201     return TSI_INVALID_ARGUMENT;
    202   }
    203   local_tsi_handshaker* handshaker =
    204       static_cast<local_tsi_handshaker*>(gpr_zalloc(sizeof(*handshaker)));
    205   handshaker->is_client = is_client;
    206   handshaker->base.vtable = &handshaker_vtable;
    207   *self = &handshaker->base;
    208   return TSI_OK;
    209 }
    210