GRPC Core  0.11.0.0
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
transport_security_interface.h
Go to the documentation of this file.
1 /*
2  *
3  * Copyright 2015, Google Inc.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are
8  * met:
9  *
10  * * Redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer.
12  * * Redistributions in binary form must reproduce the above
13  * copyright notice, this list of conditions and the following disclaimer
14  * in the documentation and/or other materials provided with the
15  * distribution.
16  * * Neither the name of Google Inc. nor the names of its
17  * contributors may be used to endorse or promote products derived from
18  * this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  *
32  */
33 
34 #ifndef GRPC_INTERNAL_CORE_TSI_TRANSPORT_SECURITY_INTERFACE_H
35 #define GRPC_INTERNAL_CORE_TSI_TRANSPORT_SECURITY_INTERFACE_H
36 
37 #include <stdint.h>
38 #include <stdlib.h>
39 
40 #ifdef __cplusplus
41 extern "C" {
42 #endif
43 
44 /* --- tsi result --- */
45 
46 typedef enum {
47  TSI_OK = 0,
60 } tsi_result;
61 
62 const char* tsi_result_to_string(tsi_result result);
63 
64 /* --- tsi tracing --- */
65 
66 /* Set this early to avoid races */
67 extern int tsi_tracing_enabled;
68 
69 /* --- tsi_frame_protector object ---
70 
71  This object protects and unprotects buffers once the handshake is done.
72  Implementations of this object must be thread compatible. */
73 
75 
76 /* Outputs protected frames.
77  - unprotected_bytes is an input only parameter and points to the data
78  to be protected.
79  - unprotected_bytes_size is an input/output parameter used by the caller to
80  specify how many bytes are available in unprotected_bytes. The output
81  value is the number of bytes consumed during the call.
82  - protected_output_frames points to a buffer allocated by the caller that
83  will be written.
84  - protected_output_frames_size is an input/output parameter used by the
85  caller to specify how many bytes are available in protected_output_frames.
86  As an output, this value indicates the number of bytes written.
87  - This method returns TSI_OK in case of success or a specific error code in
88  case of failure. Note that even if all the input unprotected bytes are
89  consumed, they may not have been processed into the returned protected
90  output frames. The caller should call the protect_flush method
91  to make sure that there are no more protected bytes buffered in the
92  protector.
93 
94  A typical way to call this method would be:
95 
96  ------------------------------------------------------------------------
97  unsigned char protected_buffer[4096];
98  size_t protected_buffer_size = sizeof(protected_buffer);
99  tsi_result result = TSI_OK;
100  while (message_size > 0) {
101  size_t protected_buffer_size_to_send = protected_buffer_size;
102  size_t processed_message_size = message_size;
103  result = tsi_frame_protector_protect(protector,
104  message_bytes,
105  &processed_message_size,
106  protected_buffer,
107  &protected_buffer_size_to_send);
108  if (result != TSI_OK) break;
109  send_bytes_to_peer(protected_buffer, protected_buffer_size_to_send);
110  message_bytes += processed_message_size;
111  message_size -= processed_message_size;
112 
113  // Don't forget to flush.
114  if (message_size == 0) {
115  size_t still_pending_size;
116  do {
117  protected_buffer_size_to_send = protected_buffer_size;
118  result = tsi_frame_protector_protect_flush(
119  protector, protected_buffer,
120  &protected_buffer_size_to_send, &still_pending_size);
121  if (result != TSI_OK) break;
122  send_bytes_to_peer(protected_buffer, protected_buffer_size_to_send);
123  } while (still_pending_size > 0);
124  }
125  }
126 
127  if (result != TSI_OK) HandleError(result);
128  ------------------------------------------------------------------------ */
130  const unsigned char* unprotected_bytes,
131  size_t* unprotected_bytes_size,
132  unsigned char* protected_output_frames,
133  size_t* protected_output_frames_size);
134 
135 /* Indicates that we need to flush the bytes buffered in the protector and get
136  the resulting frame.
137  - protected_output_frames points to a buffer allocated by the caller that
138  will be written.
139  - protected_output_frames_size is an input/output parameter used by the
140  caller to specify how many bytes are available in protected_output_frames.
141  - still_pending_bytes is an output parameter indicating the number of bytes
142  that still need to be flushed from the protector.*/
144  tsi_frame_protector* self, unsigned char* protected_output_frames,
145  size_t* protected_output_frames_size, size_t* still_pending_size);
146 
147 /* Outputs unprotected bytes.
148  - protected_frames_bytes is an input only parameter and points to the
149  protected frames to be unprotected.
150  - protected_frames_bytes_size is an input/output only parameter used by the
151  caller to specify how many bytes are available in protected_bytes. The
152  output value is the number of bytes consumed during the call.
153  Implementations will buffer up to a frame of protected data.
154  - unprotected_bytes points to a buffer allocated by the caller that will be
155  written.
156  - unprotected_bytes_size is an input/output parameter used by the caller to
157  specify how many bytes are available in unprotected_bytes. This
158  value is expected to be at most max_protected_frame_size minus overhead
159  which means that max_protected_frame_size is a safe bet. The output value
160  is the number of bytes actually written.
161  If *unprotected_bytes_size is unchanged, there may be more data remaining
162  to unprotect, and the caller should call this function again.
163 
164  - This method returns TSI_OK in case of success. Success includes cases where
165  there is not enough data to output a frame in which case
166  unprotected_bytes_size will be set to 0 and cases where the internal buffer
167  needs to be read before new protected data can be processed in which case
168  protected_frames_size will be set to 0. */
170  tsi_frame_protector* self, const unsigned char* protected_frames_bytes,
171  size_t* protected_frames_bytes_size, unsigned char* unprotected_bytes,
172  size_t* unprotected_bytes_size);
173 
174 /* Destroys the tsi_frame_protector object. */
176 
177 /* --- tsi_peer objects ---
178 
179  tsi_peer objects are a set of properties. The peer owns the properties. */
180 
181 /* This property is of type TSI_PEER_PROPERTY_STRING. */
182 #define TSI_CERTIFICATE_TYPE_PEER_PROPERTY "certificate_type"
183 
184 /* Property values may contain NULL characters just like C++ strings.
185  The length field gives the length of the string. */
186 typedef struct tsi_peer_property {
187  char* name;
188  struct {
189  char* data;
190  size_t length;
191  } value;
193 
194 typedef struct {
197 } tsi_peer;
198 
199 /* Destructs the tsi_peer object. */
200 void tsi_peer_destruct(tsi_peer* self);
201 
202 /* --- tsi_handshaker objects ----
203 
204  Implementations of this object must be thread compatible.
205 
206  A typical usage of this object would be:
207 
208  ------------------------------------------------------------------------
209  tsi_result result = TSI_OK;
210  unsigned char buf[4096];
211  size_t buf_offset;
212  size_t buf_size;
213  while (1) {
214  // See if we need to send some bytes to the peer.
215  do {
216  size_t buf_size_to_send = sizeof(buf);
217  result = tsi_handshaker_get_bytes_to_send_to_peer(handshaker, buf,
218  &buf_size_to_send);
219  if (buf_size_to_send > 0) send_bytes_to_peer(buf, buf_size_to_send);
220  } while (result == TSI_INCOMPLETE_DATA);
221  if (result != TSI_OK) return result;
222  if (!tsi_handshaker_is_in_progress(handshaker)) break;
223 
224  do {
225  // Read bytes from the peer.
226  buf_size = sizeof(buf);
227  buf_offset = 0;
228  read_bytes_from_peer(buf, &buf_size);
229  if (buf_size == 0) break;
230 
231  // Process the bytes from the peer. We have to be careful as these bytes
232  // may contain non-handshake data (protected data). If this is the case,
233  // we will exit from the loop with buf_size > 0.
234  size_t consumed_by_handshaker = buf_size;
235  result = tsi_handshaker_process_bytes_from_peer(
236  handshaker, buf, &consumed_by_handshaker);
237  buf_size -= consumed_by_handshaker;
238  buf_offset += consumed_by_handshaker;
239  } while (result == TSI_INCOMPLETE_DATA);
240 
241  if (result != TSI_OK) return result;
242  if (!tsi_handshaker_is_in_progress(handshaker)) break;
243  }
244 
245  // Check the Peer.
246  tsi_peer peer;
247  do {
248  result = tsi_handshaker_extract_peer(handshaker, &peer);
249  if (result != TSI_OK) break;
250  result = check_peer(&peer);
251  } while (0);
252  tsi_peer_destruct(&peer);
253  if (result != TSI_OK) return result;
254 
255  // Create the protector.
256  tsi_frame_protector* protector = NULL;
257  result = tsi_handshaker_create_frame_protector(handshaker, NULL,
258  &protector);
259  if (result != TSI_OK) return result;
260 
261  // Do not forget to unprotect outstanding data if any.
262  if (buf_size > 0) {
263  result = tsi_frame_protector_unprotect(protector, buf + buf_offset,
264  buf_size, ..., ...);
265  ....
266  }
267  ...
268  ------------------------------------------------------------------------ */
270 
271 /* Gets bytes that need to be sent to the peer.
272  - bytes is the buffer that will be written with the data to be sent to the
273  peer.
274  - bytes_size is an input/output parameter specifying the capacity of the
275  bytes parameter as input and the number of bytes written as output.
276  Returns TSI_OK if all the data to send to the peer has been written or if
277  nothing has to be sent to the peer (in which base bytes_size outputs to 0),
278  otherwise returns TSI_INCOMPLETE_DATA which indicates that this method
279  needs to be called again to get all the bytes to send to the peer (there
280  was more data to write than the specified bytes_size). In case of a fatal
281  error in the handshake, another specific error code is returned. */
283  unsigned char* bytes,
284  size_t* bytes_size);
285 
286 /* Processes bytes received from the peer.
287  - bytes is the buffer containing the data.
288  - bytes_size is an input/output parameter specifying the size of the data as
289  input and the number of bytes consumed as output.
290  Return TSI_OK if the handshake has all the data it needs to process,
291  otherwise return TSI_INCOMPLETE_DATA which indicates that this method
292  needs to be called again to complete the data needed for processing. In
293  case of a fatal error in the handshake, another specific error code is
294  returned. */
296  const unsigned char* bytes,
297  size_t* bytes_size);
298 
299 /* Gets the result of the handshaker.
300  Returns TSI_OK if the hanshake completed successfully and there has been no
301  errors. Returns TSI_HANDSHAKE_IN_PROGRESS if the handshaker is not done yet
302  but no error has been encountered so far. Otherwise the handshaker failed
303  with the returned error. */
305 
306 /* Returns 1 if the handshake is in progress, 0 otherwise. */
307 #define tsi_handshaker_is_in_progress(h) \
308  (tsi_handshaker_get_result((h)) == TSI_HANDSHAKE_IN_PROGRESS)
309 
310 /* This method may return TSI_FAILED_PRECONDITION if
311  tsi_handshaker_is_in_progress returns 1, it returns TSI_OK otherwise
312  assuming the handshaker is not in a fatal error state.
313  The caller is responsible for destructing the peer. */
315 
316 /* This method creates a tsi_frame_protector object after the handshake phase
317  is done. After this method has been called successfully, the only method
318  that can be called on this object is Destroy.
319  - max_output_protected_frame_size is an input/output parameter specifying the
320  desired max output protected frame size as input and outputing the actual
321  max output frame size as the output. Passing NULL is OK and will result in
322  the implementation choosing the default maximum protected frame size. Note
323  that this size only applies to outgoing frames (generated with
324  tsi_frame_protector_protect) and not incoming frames (input of
325  tsi_frame_protector_unprotect).
326  - protector is an output parameter pointing to the newly created
327  tsi_frame_protector object.
328  This method may return TSI_FAILED_PRECONDITION if
329  tsi_handshaker_is_in_progress returns 1, it returns TSI_OK otherwise assuming
330  the handshaker is not in a fatal error state.
331  The caller is responsible for destroying the protector. */
333  tsi_handshaker* self, size_t* max_output_protected_frame_size,
334  tsi_frame_protector** protector);
335 
336 /* This method releases the tsi_handshaker object. After this method is called,
337  no other method can be called on the object. */
339 
340 #ifdef __cplusplus
341 }
342 #endif
343 
344 #endif /* GRPC_INTERNAL_CORE_TSI_TRANSPORT_SECURITY_INTERFACE_H */
Definition: transport_security.h:65
tsi_result tsi_handshaker_process_bytes_from_peer(tsi_handshaker *self, const unsigned char *bytes, size_t *bytes_size)
Definition: transport_security.c:153
Definition: transport_security_interface.h:57
Definition: transport_security_interface.h:54
Definition: transport_security_interface.h:59
tsi_result tsi_handshaker_get_bytes_to_send_to_peer(tsi_handshaker *self, unsigned char *bytes, size_t *bytes_size)
Definition: transport_security.c:145
void tsi_peer_destruct(tsi_peer *self)
Definition: transport_security.c:226
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.c:95
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.c:122
char * data
Definition: transport_security_interface.h:189
Definition: transport_security_interface.h:55
Definition: transport_security_interface.h:194
Definition: transport_security_interface.h:51
Definition: transport_security_interface.h:50
Definition: transport_security_interface.h:52
struct tsi_peer_property::@14 value
tsi_peer_property * properties
Definition: transport_security_interface.h:195
size_t property_count
Definition: transport_security_interface.h:196
tsi_result
Definition: transport_security_interface.h:46
void tsi_handshaker_destroy(tsi_handshaker *self)
Definition: transport_security.c:194
Definition: transport_security_interface.h:53
tsi_result tsi_handshaker_create_frame_protector(tsi_handshaker *self, size_t *max_output_protected_frame_size, tsi_frame_protector **protector)
Definition: transport_security.c:177
int tsi_tracing_enabled
Definition: transport_security.c:41
Definition: transport_security_interface.h:56
tsi_result tsi_handshaker_get_result(tsi_handshaker *self)
Definition: transport_security.c:161
struct tsi_peer_property tsi_peer_property
Definition: transport_security_interface.h:49
char * name
Definition: transport_security_interface.h:187
tsi_result tsi_handshaker_extract_peer(tsi_handshaker *self, tsi_peer *peer)
Definition: transport_security.c:167
void tsi_frame_protector_destroy(tsi_frame_protector *self)
Definition: transport_security.c:136
Definition: transport_security_interface.h:58
Definition: transport_security.h:86
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.c:110
const char * tsi_result_to_string(tsi_result result)
Definition: transport_security.c:58
size_t length
Definition: transport_security_interface.h:190
Definition: transport_security_interface.h:48
Definition: transport_security_interface.h:47
Definition: transport_security_interface.h:186