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