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