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