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