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