GRPC Core  18.0.0
transport_security_interface.h
Go to the documentation of this file.
1 /*
2  *
3  * Copyright 2015 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 #ifndef GRPC_CORE_TSI_TRANSPORT_SECURITY_INTERFACE_H
20 #define GRPC_CORE_TSI_TRANSPORT_SECURITY_INTERFACE_H
21 
23 
24 #include <stdint.h>
25 #include <stdlib.h>
26 
28 
29 /* --- tsi result --- */
30 
31 typedef enum {
32  TSI_OK = 0,
45  TSI_ASYNC = 13,
47  TSI_CLOSE_NOTIFY = 15, // Indicates that the connection should be closed.
48 } tsi_result;
49 
50 typedef enum {
57 
58 typedef enum {
59  // Default option
66 
67 typedef enum {
71 
72 const char* tsi_result_to_string(tsi_result result);
73 const char* tsi_security_level_to_string(tsi_security_level security_level);
74 
75 /* --- tsi tracing --- */
76 
78 
79 /* -- tsi_zero_copy_grpc_protector object --
80 
81  This object protects and unprotects grpc slice buffers with zero or minimized
82  memory copy once the handshake is done. Implementations of this object must be
83  thread compatible. This object depends on grpc and the details of this object
84  is defined in transport_security_grpc.h. */
85 
87 
88 /* --- tsi_frame_protector object ---
89 
90  This object protects and unprotects buffers once the handshake is done.
91  Implementations of this object must be thread compatible. */
92 
94 
95 /* Outputs protected frames.
96  - unprotected_bytes is an input only parameter and points to the data
97  to be protected.
98  - unprotected_bytes_size is an input/output parameter used by the caller to
99  specify how many bytes are available in unprotected_bytes. The output
100  value is the number of bytes consumed during the call.
101  - protected_output_frames points to a buffer allocated by the caller that
102  will be written.
103  - protected_output_frames_size is an input/output parameter used by the
104  caller to specify how many bytes are available in protected_output_frames.
105  As an output, this value indicates the number of bytes written.
106  - This method returns TSI_OK in case of success or a specific error code in
107  case of failure. Note that even if all the input unprotected bytes are
108  consumed, they may not have been processed into the returned protected
109  output frames. The caller should call the protect_flush method
110  to make sure that there are no more protected bytes buffered in the
111  protector.
112 
113  A typical way to call this method would be:
114 
115  ------------------------------------------------------------------------
116  unsigned char protected_buffer[4096];
117  size_t protected_buffer_size = sizeof(protected_buffer);
118  tsi_result result = TSI_OK;
119  while (message_size > 0) {
120  size_t protected_buffer_size_to_send = protected_buffer_size;
121  size_t processed_message_size = message_size;
122  result = tsi_frame_protector_protect(protector,
123  message_bytes,
124  &processed_message_size,
125  protected_buffer,
126  &protected_buffer_size_to_send);
127  if (result != TSI_OK) break;
128  send_bytes_to_peer(protected_buffer, protected_buffer_size_to_send);
129  message_bytes += processed_message_size;
130  message_size -= processed_message_size;
131 
132  // Don't forget to flush.
133  if (message_size == 0) {
134  size_t still_pending_size;
135  do {
136  protected_buffer_size_to_send = protected_buffer_size;
137  result = tsi_frame_protector_protect_flush(
138  protector, protected_buffer,
139  &protected_buffer_size_to_send, &still_pending_size);
140  if (result != TSI_OK) break;
141  send_bytes_to_peer(protected_buffer, protected_buffer_size_to_send);
142  } while (still_pending_size > 0);
143  }
144  }
145 
146  if (result != TSI_OK) HandleError(result);
147  ------------------------------------------------------------------------ */
149  const unsigned char* unprotected_bytes,
150  size_t* unprotected_bytes_size,
151  unsigned char* protected_output_frames,
152  size_t* protected_output_frames_size);
153 
154 /* Indicates that we need to flush the bytes buffered in the protector and get
155  the resulting frame.
156  - protected_output_frames points to a buffer allocated by the caller that
157  will be written.
158  - protected_output_frames_size is an input/output parameter used by the
159  caller to specify how many bytes are available in protected_output_frames.
160  - still_pending_bytes is an output parameter indicating the number of bytes
161  that still need to be flushed from the protector.*/
163  tsi_frame_protector* self, unsigned char* protected_output_frames,
164  size_t* protected_output_frames_size, size_t* still_pending_size);
165 
166 /* Outputs unprotected bytes.
167  - protected_frames_bytes is an input only parameter and points to the
168  protected frames to be unprotected.
169  - protected_frames_bytes_size is an input/output only parameter used by the
170  caller to specify how many bytes are available in protected_bytes. The
171  output value is the number of bytes consumed during the call.
172  Implementations will buffer up to a frame of protected data.
173  - unprotected_bytes points to a buffer allocated by the caller that will be
174  written.
175  - unprotected_bytes_size is an input/output parameter used by the caller to
176  specify how many bytes are available in unprotected_bytes. This
177  value is expected to be at most max_protected_frame_size minus overhead
178  which means that max_protected_frame_size is a safe bet. The output value
179  is the number of bytes actually written.
180  If *unprotected_bytes_size is unchanged, there may be more data remaining
181  to unprotect, and the caller should call this function again.
182 
183  - This method returns TSI_OK in case of success. Success includes cases where
184  there is not enough data to output a frame in which case
185  unprotected_bytes_size will be set to 0 and cases where the internal buffer
186  needs to be read before new protected data can be processed in which case
187  protected_frames_size will be set to 0. */
189  tsi_frame_protector* self, const unsigned char* protected_frames_bytes,
190  size_t* protected_frames_bytes_size, unsigned char* unprotected_bytes,
191  size_t* unprotected_bytes_size);
192 
193 /* Destroys the tsi_frame_protector object. */
195 
196 /* --- tsi_peer objects ---
197 
198  tsi_peer objects are a set of properties. The peer owns the properties. */
199 
200 /* This property is of type TSI_PEER_PROPERTY_STRING. */
201 #define TSI_CERTIFICATE_TYPE_PEER_PROPERTY "certificate_type"
202 
203 /* This property represents security level of a channel. */
204 #define TSI_SECURITY_LEVEL_PEER_PROPERTY "security_level"
205 
206 /* Property values may contain NULL characters just like C++ strings.
207  The length field gives the length of the string. */
208 typedef struct tsi_peer_property {
209  char* name;
210  struct {
211  char* data;
212  size_t length;
213  } value;
215 
216 struct tsi_peer {
219 };
220 /* Destructs the tsi_peer object. */
222 
223 /* --- tsi_handshaker_result object ---
224 
225  This object contains all necessary handshake results and data such as peer
226  info, negotiated keys, unused handshake bytes, when the handshake completes.
227  Implementations of this object must be thread compatible. */
228 
230 
231 /* This method extracts tsi peer. It returns TSI_OK assuming there is no fatal
232  error.
233  The caller is responsible for destructing the peer. */
235  tsi_peer* peer);
236 
237 /* This method creates a tsi_frame_protector object. It returns TSI_OK assuming
238  there is no fatal error.
239  The caller is responsible for destroying the protector. */
241  const tsi_handshaker_result* self, size_t* max_output_protected_frame_size,
242  tsi_frame_protector** protector);
243 
244 /* This method returns the unused bytes from the handshake. It returns TSI_OK
245  assuming there is no fatal error.
246  Ownership of the bytes is retained by the handshaker result. As a
247  consequence, the caller must not free the bytes. */
249  const tsi_handshaker_result* self, const unsigned char** bytes,
250  size_t* bytes_size);
251 
252 /* This method releases the tsi_handshaker_handshaker object. After this method
253  is called, no other method can be called on the object. */
255 
256 /* --- tsi_handshaker objects ----
257 
258  Implementations of this object must be thread compatible.
259 
260  ------------------------------------------------------------------------
261 
262  A typical usage supporting both synchronous and asynchronous TSI handshaker
263  implementations would be:
264 
265  ------------------------------------------------------------------------
266 
267  typedef struct {
268  tsi_handshaker *handshaker;
269  tsi_handshaker_result *handshaker_result;
270  unsigned char *handshake_buffer;
271  size_t handshake_buffer_size;
272  ...
273  } security_handshaker;
274 
275  void do_handshake(security_handshaker *h, ...) {
276  // Start the handshake by the calling do_handshake_next.
277  do_handshake_next(h, NULL, 0);
278  ...
279  }
280 
281  // This method is the callback function when data is received from the
282  // peer. This method will read bytes into the handshake buffer and call
283  // do_handshake_next.
284  void on_handshake_data_received_from_peer(void *user_data) {
285  security_handshaker *h = (security_handshaker *)user_data;
286  size_t bytes_received_size = h->handshake_buffer_size;
287  read_bytes_from_peer(h->handshake_buffer, &bytes_received_size);
288  do_handshake_next(h, h->handshake_buffer, bytes_received_size);
289  }
290 
291  // This method processes a step of handshake, calling tsi_handshaker_next.
292  void do_handshake_next(security_handshaker *h,
293  const unsigned char* bytes_received,
294  size_t bytes_received_size) {
295  tsi_result status = TSI_OK;
296  unsigned char *bytes_to_send = NULL;
297  size_t bytes_to_send_size = 0;
298  tsi_handshaker_result *result = NULL;
299  status = tsi_handshaker_next(
300  handshaker, bytes_received, bytes_received_size, &bytes_to_send,
301  &bytes_to_send_size, &result, on_handshake_next_done, h);
302  // If TSI handshaker is asynchronous, on_handshake_next_done will be
303  // executed inside tsi_handshaker_next.
304  if (status == TSI_ASYNC) return;
305  // If TSI handshaker is synchronous, invoke callback directly in this
306  // thread.
307  on_handshake_next_done(status, (void *)h, bytes_to_send,
308  bytes_to_send_size, result);
309  }
310 
311  // This is the callback function to execute after tsi_handshaker_next.
312  // It is passed to tsi_handshaker_next as a function parameter.
313  void on_handshake_next_done(
314  tsi_result status, void *user_data, const unsigned char *bytes_to_send,
315  size_t bytes_to_send_size, tsi_handshaker_result *result) {
316  security_handshaker *h = (security_handshaker *)user_data;
317  if (status == TSI_INCOMPLETE_DATA) {
318  // Schedule an asynchronous read from the peer. If handshake data are
319  // received, on_handshake_data_received_from_peer will be called.
320  async_read_from_peer(..., ..., on_handshake_data_received_from_peer);
321  return;
322  }
323  if (status != TSI_OK) return;
324 
325  if (bytes_to_send_size > 0) {
326  send_bytes_to_peer(bytes_to_send, bytes_to_send_size);
327  }
328 
329  if (result != NULL) {
330  // Handshake completed.
331  h->result = result;
332  // Check the Peer.
333  tsi_peer peer;
334  status = tsi_handshaker_result_extract_peer(result, &peer);
335  if (status != TSI_OK) return;
336  status = check_peer(&peer);
337  tsi_peer_destruct(&peer);
338  if (status != TSI_OK) return;
339 
340  // Create the protector.
341  tsi_frame_protector* protector = NULL;
342  status = tsi_handshaker_result_create_frame_protector(result, NULL,
343  &protector);
344  if (status != TSI_OK) return;
345 
346  // Do not forget to unprotect outstanding data if any.
347  ....
348  }
349  }
350  ------------------------------------------------------------------------ */
351 typedef struct tsi_handshaker tsi_handshaker;
352 
353 /* TODO(jiangtaoli2016): Cleans up deprecated methods when we are ready. */
354 
355 /* TO BE DEPRECATED SOON. Use tsi_handshaker_next instead.
356  Gets bytes that need to be sent to the peer.
357  - bytes is the buffer that will be written with the data to be sent to the
358  peer.
359  - bytes_size is an input/output parameter specifying the capacity of the
360  bytes parameter as input and the number of bytes written as output.
361  Returns TSI_OK if all the data to send to the peer has been written or if
362  nothing has to be sent to the peer (in which base bytes_size outputs to 0),
363  otherwise returns TSI_INCOMPLETE_DATA which indicates that this method
364  needs to be called again to get all the bytes to send to the peer (there
365  was more data to write than the specified bytes_size). In case of a fatal
366  error in the handshake, another specific error code is returned. */
368  unsigned char* bytes,
369  size_t* bytes_size);
370 
371 /* TO BE DEPRECATED SOON. Use tsi_handshaker_next instead.
372  Processes bytes received from the peer.
373  - bytes is the buffer containing the data.
374  - bytes_size is an input/output parameter specifying the size of the data as
375  input and the number of bytes consumed as output.
376  Return TSI_OK if the handshake has all the data it needs to process,
377  otherwise return TSI_INCOMPLETE_DATA which indicates that this method
378  needs to be called again to complete the data needed for processing. In
379  case of a fatal error in the handshake, another specific error code is
380  returned. */
382  const unsigned char* bytes,
383  size_t* bytes_size);
384 
385 /* TO BE DEPRECATED SOON.
386  Gets the result of the handshaker.
387  Returns TSI_OK if the hanshake completed successfully and there has been no
388  errors. Returns TSI_HANDSHAKE_IN_PROGRESS if the handshaker is not done yet
389  but no error has been encountered so far. Otherwise the handshaker failed
390  with the returned error. */
392 
393 /* TO BE DEPRECATED SOON.
394  Returns 1 if the handshake is in progress, 0 otherwise. */
395 #define tsi_handshaker_is_in_progress(h) \
396  (tsi_handshaker_get_result((h)) == TSI_HANDSHAKE_IN_PROGRESS)
397 
398 /* TO BE DEPRECATED SOON. Use tsi_handshaker_result_extract_peer instead.
399  This method may return TSI_FAILED_PRECONDITION if
400  tsi_handshaker_is_in_progress returns 1, it returns TSI_OK otherwise
401  assuming the handshaker is not in a fatal error state.
402  The caller is responsible for destructing the peer. */
404 
405 /* TO BE DEPRECATED SOON. Use tsi_handshaker_result_create_frame_protector
406  instead.
407  This method creates a tsi_frame_protector object after the handshake phase
408  is done. After this method has been called successfully, the only method
409  that can be called on this object is Destroy.
410  - max_output_protected_frame_size is an input/output parameter specifying the
411  desired max output protected frame size as input and outputing the actual
412  max output frame size as the output. Passing NULL is OK and will result in
413  the implementation choosing the default maximum protected frame size. Note
414  that this size only applies to outgoing frames (generated with
415  tsi_frame_protector_protect) and not incoming frames (input of
416  tsi_frame_protector_unprotect).
417  - protector is an output parameter pointing to the newly created
418  tsi_frame_protector object.
419  This method may return TSI_FAILED_PRECONDITION if
420  tsi_handshaker_is_in_progress returns 1, it returns TSI_OK otherwise assuming
421  the handshaker is not in a fatal error state.
422  The caller is responsible for destroying the protector. */
424  tsi_handshaker* self, size_t* max_output_protected_frame_size,
425  tsi_frame_protector** protector);
426 
427 /* Callback function definition for tsi_handshaker_next.
428  - status indicates the status of the next operation.
429  - user_data is the argument to callback function passed from the caller.
430  - bytes_to_send is the data buffer to be sent to the peer.
431  - bytes_to_send_size is the size of data buffer to be sent to the peer.
432  - handshaker_result is the result of handshake when the handshake completes,
433  is NULL otherwise. */
435  tsi_result status, void* user_data, const unsigned char* bytes_to_send,
436  size_t bytes_to_send_size, tsi_handshaker_result* handshaker_result);
437 
438 /* Conduct a next step of the handshake.
439  - received_bytes is the buffer containing the data received from the peer.
440  - received_bytes_size is the size of the data received from the peer.
441  - bytes_to_send is the data buffer to be sent to the peer.
442  - bytes_to_send_size is the size of data buffer to be sent to the peer.
443  - handshaker_result is the result of handshake if the handshake completes.
444  - cb is the callback function defined above. It can be NULL for synchronous
445  TSI handshaker implementation.
446  - user_data is the argument to callback function passed from the caller.
447  This method returns TSI_ASYNC if the TSI handshaker implementation is
448  asynchronous, and in this case, the callback is guaranteed to run in another
449  thread owned by TSI. It returns TSI_OK if the handshake completes or if
450  there are data to send to the peer, otherwise returns TSI_INCOMPLETE_DATA
451  which indicates that this method needs to be called again with more data
452  from the peer. In case of a fatal error in the handshake, another specific
453  error code is returned.
454  The caller is responsible for destroying the handshaker_result. However,
455  the caller should not free bytes_to_send, as the buffer is owned by the
456  tsi_handshaker object. */
458  tsi_handshaker* self, const unsigned char* received_bytes,
459  size_t received_bytes_size, const unsigned char** bytes_to_send,
460  size_t* bytes_to_send_size, tsi_handshaker_result** handshaker_result,
461  tsi_handshaker_on_next_done_cb cb, void* user_data);
462 
463 /* This method shuts down a TSI handshake that is in progress.
464  *
465  * This method will be invoked when TSI handshake should be terminated before
466  * being finished in order to free any resources being used.
467  */
469 
470 /* This method releases the tsi_handshaker object. After this method is called,
471  no other method can be called on the object. */
473 
474 /* This method initializes the necessary shared objects used for tsi
475  implementation. */
476 void tsi_init();
477 
478 /* This method destroys the shared objects created by tsi_init. */
479 void tsi_destroy();
480 
481 #endif /* GRPC_CORE_TSI_TRANSPORT_SECURITY_INTERFACE_H */
Definition: trace.h:61
Definition: transport_security.h:50
Definition: transport_security.h:106
Definition: transport_security.h:77
Definition: transport_security_interface.h:208
struct tsi_peer_property::@40 value
char * name
Definition: transport_security_interface.h:209
size_t length
Definition: transport_security_interface.h:212
char * data
Definition: transport_security_interface.h:211
Definition: transport_security_interface.h:216
tsi_peer_property * properties
Definition: transport_security_interface.h:217
size_t property_count
Definition: transport_security_interface.h:218
Definition: transport_security_grpc.h:75
void tsi_handshaker_result_destroy(tsi_handshaker_result *self)
Definition: transport_security.cc:276
tsi_result tsi_handshaker_result_get_unused_bytes(const tsi_handshaker_result *self, const unsigned char **bytes, size_t *bytes_size)
Definition: transport_security.cc:265
void tsi_handshaker_shutdown(tsi_handshaker *self)
Definition: transport_security.cc:229
const char * tsi_security_level_to_string(tsi_security_level security_level)
Definition: transport_security.cc:70
tsi_result tsi_handshaker_get_bytes_to_send_to_peer(tsi_handshaker *self, unsigned char *bytes, size_t *bytes_size)
Definition: transport_security.cc:144
tsi_security_level
Definition: transport_security_interface.h:50
@ TSI_SECURITY_NONE
Definition: transport_security_interface.h:52
@ TSI_INTEGRITY_ONLY
Definition: transport_security_interface.h:53
@ TSI_SECURITY_MIN
Definition: transport_security_interface.h:51
@ TSI_SECURITY_MAX
Definition: transport_security_interface.h:55
@ TSI_PRIVACY_AND_INTEGRITY
Definition: transport_security_interface.h:54
void tsi_peer_destruct(tsi_peer *self)
Definition: transport_security.cc:308
tsi_result
Definition: transport_security_interface.h:31
@ TSI_HANDSHAKE_SHUTDOWN
Definition: transport_security_interface.h:46
@ TSI_INCOMPLETE_DATA
Definition: transport_security_interface.h:36
@ TSI_UNIMPLEMENTED
Definition: transport_security_interface.h:38
@ TSI_INVALID_ARGUMENT
Definition: transport_security_interface.h:34
@ TSI_UNKNOWN_ERROR
Definition: transport_security_interface.h:33
@ TSI_INTERNAL_ERROR
Definition: transport_security_interface.h:39
@ TSI_OK
Definition: transport_security_interface.h:32
@ TSI_OUT_OF_RESOURCES
Definition: transport_security_interface.h:44
@ TSI_PROTOCOL_FAILURE
Definition: transport_security_interface.h:42
@ TSI_ASYNC
Definition: transport_security_interface.h:45
@ TSI_NOT_FOUND
Definition: transport_security_interface.h:41
@ TSI_CLOSE_NOTIFY
Definition: transport_security_interface.h:47
@ TSI_HANDSHAKE_IN_PROGRESS
Definition: transport_security_interface.h:43
@ TSI_DATA_CORRUPTED
Definition: transport_security_interface.h:40
@ TSI_FAILED_PRECONDITION
Definition: transport_security_interface.h:37
@ TSI_PERMISSION_DENIED
Definition: transport_security_interface.h:35
tsi_result tsi_handshaker_result_create_frame_protector(const tsi_handshaker_result *self, size_t *max_output_protected_frame_size, tsi_frame_protector **protector)
Definition: transport_security.cc:254
tsi_tls_version
Definition: transport_security_interface.h:67
@ TSI_TLS1_2
Definition: transport_security_interface.h:68
@ TSI_TLS1_3
Definition: transport_security_interface.h:69
void tsi_init()
void tsi_destroy()
tsi_result tsi_handshaker_create_frame_protector(tsi_handshaker *self, size_t *max_output_protected_frame_size, tsi_frame_protector **protector)
Definition: transport_security.cc:196
tsi_result tsi_frame_protector_protect(tsi_frame_protector *self, const unsigned char *unprotected_bytes, size_t *unprotected_bytes_size, unsigned char *protected_output_frames, size_t *protected_output_frames_size)
Definition: transport_security.cc:87
tsi_result tsi_frame_protector_protect_flush(tsi_frame_protector *self, unsigned char *protected_output_frames, size_t *protected_output_frames_size, size_t *still_pending_size)
Definition: transport_security.cc:104
struct tsi_peer_property tsi_peer_property
void tsi_handshaker_destroy(tsi_handshaker *self)
Definition: transport_security.cc:237
const char * tsi_result_to_string(tsi_result result)
Definition: transport_security.cc:35
tsi_result tsi_handshaker_get_result(tsi_handshaker *self)
Definition: transport_security.cc:174
tsi_client_certificate_request_type
Definition: transport_security_interface.h:58
@ TSI_REQUEST_CLIENT_CERTIFICATE_BUT_DONT_VERIFY
Definition: transport_security_interface.h:61
@ TSI_DONT_REQUEST_CLIENT_CERTIFICATE
Definition: transport_security_interface.h:60
@ TSI_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY
Definition: transport_security_interface.h:64
@ TSI_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_BUT_DONT_VERIFY
Definition: transport_security_interface.h:63
@ TSI_REQUEST_CLIENT_CERTIFICATE_AND_VERIFY
Definition: transport_security_interface.h:62
tsi_result tsi_handshaker_extract_peer(tsi_handshaker *self, tsi_peer *peer)
Definition: transport_security.cc:182
void(* tsi_handshaker_on_next_done_cb)(tsi_result status, void *user_data, const unsigned char *bytes_to_send, size_t bytes_to_send_size, tsi_handshaker_result *handshaker_result)
Definition: transport_security_interface.h:434
tsi_result tsi_handshaker_process_bytes_from_peer(tsi_handshaker *self, const unsigned char *bytes, size_t *bytes_size)
Definition: transport_security.cc:159
void tsi_frame_protector_destroy(tsi_frame_protector *self)
Definition: transport_security.cc:135
grpc_core::TraceFlag tsi_tracing_enabled
tsi_result tsi_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 **handshaker_result, tsi_handshaker_on_next_done_cb cb, void *user_data)
Definition: transport_security.cc:215
tsi_result tsi_frame_protector_unprotect(tsi_frame_protector *self, const unsigned char *protected_frames_bytes, size_t *protected_frames_bytes_size, unsigned char *unprotected_bytes, size_t *unprotected_bytes_size)
Definition: transport_security.cc:119
tsi_result tsi_handshaker_result_extract_peer(const tsi_handshaker_result *self, tsi_peer *peer)
Definition: transport_security.cc:244