Index: third_party/grpc/src/core/tsi/transport_security_interface.h |
diff --git a/third_party/grpc/src/core/tsi/transport_security_interface.h b/third_party/grpc/src/core/tsi/transport_security_interface.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..69ee17ae917924c88448815a60c86fb8f5bf37d4 |
--- /dev/null |
+++ b/third_party/grpc/src/core/tsi/transport_security_interface.h |
@@ -0,0 +1,344 @@ |
+/* |
+ * |
+ * Copyright 2015, Google Inc. |
+ * All rights reserved. |
+ * |
+ * Redistribution and use in source and binary forms, with or without |
+ * modification, are permitted provided that the following conditions are |
+ * met: |
+ * |
+ * * Redistributions of source code must retain the above copyright |
+ * notice, this list of conditions and the following disclaimer. |
+ * * Redistributions in binary form must reproduce the above |
+ * copyright notice, this list of conditions and the following disclaimer |
+ * in the documentation and/or other materials provided with the |
+ * distribution. |
+ * * Neither the name of Google Inc. nor the names of its |
+ * contributors may be used to endorse or promote products derived from |
+ * this software without specific prior written permission. |
+ * |
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
+ * |
+ */ |
+ |
+#ifndef GRPC_INTERNAL_CORE_TSI_TRANSPORT_SECURITY_INTERFACE_H |
+#define GRPC_INTERNAL_CORE_TSI_TRANSPORT_SECURITY_INTERFACE_H |
+ |
+#include <stdint.h> |
+#include <stdlib.h> |
+ |
+#ifdef __cplusplus |
+extern "C" { |
+#endif |
+ |
+/* --- tsi result --- */ |
+ |
+typedef enum { |
+ TSI_OK = 0, |
+ TSI_UNKNOWN_ERROR = 1, |
+ TSI_INVALID_ARGUMENT = 2, |
+ TSI_PERMISSION_DENIED = 3, |
+ TSI_INCOMPLETE_DATA = 4, |
+ TSI_FAILED_PRECONDITION = 5, |
+ TSI_UNIMPLEMENTED = 6, |
+ TSI_INTERNAL_ERROR = 7, |
+ TSI_DATA_CORRUPTED = 8, |
+ TSI_NOT_FOUND = 9, |
+ TSI_PROTOCOL_FAILURE = 10, |
+ TSI_HANDSHAKE_IN_PROGRESS = 11, |
+ TSI_OUT_OF_RESOURCES = 12 |
+} tsi_result; |
+ |
+const char *tsi_result_to_string(tsi_result result); |
+ |
+/* --- tsi tracing --- */ |
+ |
+/* Set this early to avoid races */ |
+extern int tsi_tracing_enabled; |
+ |
+/* --- tsi_frame_protector object --- |
+ |
+ This object protects and unprotects buffers once the handshake is done. |
+ Implementations of this object must be thread compatible. */ |
+ |
+typedef struct tsi_frame_protector tsi_frame_protector; |
+ |
+/* Outputs protected frames. |
+ - unprotected_bytes is an input only parameter and points to the data |
+ to be protected. |
+ - unprotected_bytes_size is an input/output parameter used by the caller to |
+ specify how many bytes are available in unprotected_bytes. The output |
+ value is the number of bytes consumed during the call. |
+ - protected_output_frames points to a buffer allocated by the caller that |
+ will be written. |
+ - protected_output_frames_size is an input/output parameter used by the |
+ caller to specify how many bytes are available in protected_output_frames. |
+ As an output, this value indicates the number of bytes written. |
+ - This method returns TSI_OK in case of success or a specific error code in |
+ case of failure. Note that even if all the input unprotected bytes are |
+ consumed, they may not have been processed into the returned protected |
+ output frames. The caller should call the protect_flush method |
+ to make sure that there are no more protected bytes buffered in the |
+ protector. |
+ |
+ A typical way to call this method would be: |
+ |
+ ------------------------------------------------------------------------ |
+ unsigned char protected_buffer[4096]; |
+ size_t protected_buffer_size = sizeof(protected_buffer); |
+ tsi_result result = TSI_OK; |
+ while (message_size > 0) { |
+ size_t protected_buffer_size_to_send = protected_buffer_size; |
+ size_t processed_message_size = message_size; |
+ result = tsi_frame_protector_protect(protector, |
+ message_bytes, |
+ &processed_message_size, |
+ protected_buffer, |
+ &protected_buffer_size_to_send); |
+ if (result != TSI_OK) break; |
+ send_bytes_to_peer(protected_buffer, protected_buffer_size_to_send); |
+ message_bytes += processed_message_size; |
+ message_size -= processed_message_size; |
+ |
+ // Don't forget to flush. |
+ if (message_size == 0) { |
+ size_t still_pending_size; |
+ do { |
+ protected_buffer_size_to_send = protected_buffer_size; |
+ result = tsi_frame_protector_protect_flush( |
+ protector, protected_buffer, |
+ &protected_buffer_size_to_send, &still_pending_size); |
+ if (result != TSI_OK) break; |
+ send_bytes_to_peer(protected_buffer, protected_buffer_size_to_send); |
+ } while (still_pending_size > 0); |
+ } |
+ } |
+ |
+ if (result != TSI_OK) HandleError(result); |
+ ------------------------------------------------------------------------ */ |
+tsi_result tsi_frame_protector_protect(tsi_frame_protector *self, |
+ const unsigned char *unprotected_bytes, |
+ size_t *unprotected_bytes_size, |
+ unsigned char *protected_output_frames, |
+ size_t *protected_output_frames_size); |
+ |
+/* Indicates that we need to flush the bytes buffered in the protector and get |
+ the resulting frame. |
+ - protected_output_frames points to a buffer allocated by the caller that |
+ will be written. |
+ - protected_output_frames_size is an input/output parameter used by the |
+ caller to specify how many bytes are available in protected_output_frames. |
+ - still_pending_bytes is an output parameter indicating the number of bytes |
+ that still need to be flushed from the protector.*/ |
+tsi_result tsi_frame_protector_protect_flush( |
+ tsi_frame_protector *self, unsigned char *protected_output_frames, |
+ size_t *protected_output_frames_size, size_t *still_pending_size); |
+ |
+/* Outputs unprotected bytes. |
+ - protected_frames_bytes is an input only parameter and points to the |
+ protected frames to be unprotected. |
+ - protected_frames_bytes_size is an input/output only parameter used by the |
+ caller to specify how many bytes are available in protected_bytes. The |
+ output value is the number of bytes consumed during the call. |
+ Implementations will buffer up to a frame of protected data. |
+ - unprotected_bytes points to a buffer allocated by the caller that will be |
+ written. |
+ - unprotected_bytes_size is an input/output parameter used by the caller to |
+ specify how many bytes are available in unprotected_bytes. This |
+ value is expected to be at most max_protected_frame_size minus overhead |
+ which means that max_protected_frame_size is a safe bet. The output value |
+ is the number of bytes actually written. |
+ If *unprotected_bytes_size is unchanged, there may be more data remaining |
+ to unprotect, and the caller should call this function again. |
+ |
+ - This method returns TSI_OK in case of success. Success includes cases where |
+ there is not enough data to output a frame in which case |
+ unprotected_bytes_size will be set to 0 and cases where the internal buffer |
+ needs to be read before new protected data can be processed in which case |
+ protected_frames_size will be set to 0. */ |
+tsi_result tsi_frame_protector_unprotect( |
+ tsi_frame_protector *self, const unsigned char *protected_frames_bytes, |
+ size_t *protected_frames_bytes_size, unsigned char *unprotected_bytes, |
+ size_t *unprotected_bytes_size); |
+ |
+/* Destroys the tsi_frame_protector object. */ |
+void tsi_frame_protector_destroy(tsi_frame_protector *self); |
+ |
+/* --- tsi_peer objects --- |
+ |
+ tsi_peer objects are a set of properties. The peer owns the properties. */ |
+ |
+/* This property is of type TSI_PEER_PROPERTY_STRING. */ |
+#define TSI_CERTIFICATE_TYPE_PEER_PROPERTY "certificate_type" |
+ |
+/* Property values may contain NULL characters just like C++ strings. |
+ The length field gives the length of the string. */ |
+typedef struct tsi_peer_property { |
+ char *name; |
+ struct { |
+ char *data; |
+ size_t length; |
+ } value; |
+} tsi_peer_property; |
+ |
+typedef struct { |
+ tsi_peer_property *properties; |
+ size_t property_count; |
+} tsi_peer; |
+ |
+/* Destructs the tsi_peer object. */ |
+void tsi_peer_destruct(tsi_peer *self); |
+ |
+/* --- tsi_handshaker objects ---- |
+ |
+ Implementations of this object must be thread compatible. |
+ |
+ A typical usage of this object would be: |
+ |
+ ------------------------------------------------------------------------ |
+ tsi_result result = TSI_OK; |
+ unsigned char buf[4096]; |
+ size_t buf_offset; |
+ size_t buf_size; |
+ while (1) { |
+ // See if we need to send some bytes to the peer. |
+ do { |
+ size_t buf_size_to_send = sizeof(buf); |
+ result = tsi_handshaker_get_bytes_to_send_to_peer(handshaker, buf, |
+ &buf_size_to_send); |
+ if (buf_size_to_send > 0) send_bytes_to_peer(buf, buf_size_to_send); |
+ } while (result == TSI_INCOMPLETE_DATA); |
+ if (result != TSI_OK) return result; |
+ if (!tsi_handshaker_is_in_progress(handshaker)) break; |
+ |
+ do { |
+ // Read bytes from the peer. |
+ buf_size = sizeof(buf); |
+ buf_offset = 0; |
+ read_bytes_from_peer(buf, &buf_size); |
+ if (buf_size == 0) break; |
+ |
+ // Process the bytes from the peer. We have to be careful as these bytes |
+ // may contain non-handshake data (protected data). If this is the case, |
+ // we will exit from the loop with buf_size > 0. |
+ size_t consumed_by_handshaker = buf_size; |
+ result = tsi_handshaker_process_bytes_from_peer( |
+ handshaker, buf, &consumed_by_handshaker); |
+ buf_size -= consumed_by_handshaker; |
+ buf_offset += consumed_by_handshaker; |
+ } while (result == TSI_INCOMPLETE_DATA); |
+ |
+ if (result != TSI_OK) return result; |
+ if (!tsi_handshaker_is_in_progress(handshaker)) break; |
+ } |
+ |
+ // Check the Peer. |
+ tsi_peer peer; |
+ do { |
+ result = tsi_handshaker_extract_peer(handshaker, &peer); |
+ if (result != TSI_OK) break; |
+ result = check_peer(&peer); |
+ } while (0); |
+ tsi_peer_destruct(&peer); |
+ if (result != TSI_OK) return result; |
+ |
+ // Create the protector. |
+ tsi_frame_protector* protector = NULL; |
+ result = tsi_handshaker_create_frame_protector(handshaker, NULL, |
+ &protector); |
+ if (result != TSI_OK) return result; |
+ |
+ // Do not forget to unprotect outstanding data if any. |
+ if (buf_size > 0) { |
+ result = tsi_frame_protector_unprotect(protector, buf + buf_offset, |
+ buf_size, ..., ...); |
+ .... |
+ } |
+ ... |
+ ------------------------------------------------------------------------ */ |
+typedef struct tsi_handshaker tsi_handshaker; |
+ |
+/* Gets bytes that need to be sent to the peer. |
+ - bytes is the buffer that will be written with the data to be sent to the |
+ peer. |
+ - bytes_size is an input/output parameter specifying the capacity of the |
+ bytes parameter as input and the number of bytes written as output. |
+ Returns TSI_OK if all the data to send to the peer has been written or if |
+ nothing has to be sent to the peer (in which base bytes_size outputs to 0), |
+ otherwise returns TSI_INCOMPLETE_DATA which indicates that this method |
+ needs to be called again to get all the bytes to send to the peer (there |
+ was more data to write than the specified bytes_size). In case of a fatal |
+ error in the handshake, another specific error code is returned. */ |
+tsi_result tsi_handshaker_get_bytes_to_send_to_peer(tsi_handshaker *self, |
+ unsigned char *bytes, |
+ size_t *bytes_size); |
+ |
+/* Processes bytes received from the peer. |
+ - bytes is the buffer containing the data. |
+ - bytes_size is an input/output parameter specifying the size of the data as |
+ input and the number of bytes consumed as output. |
+ Return TSI_OK if the handshake has all the data it needs to process, |
+ otherwise return TSI_INCOMPLETE_DATA which indicates that this method |
+ needs to be called again to complete the data needed for processing. In |
+ case of a fatal error in the handshake, another specific error code is |
+ returned. */ |
+tsi_result tsi_handshaker_process_bytes_from_peer(tsi_handshaker *self, |
+ const unsigned char *bytes, |
+ size_t *bytes_size); |
+ |
+/* Gets the result of the handshaker. |
+ Returns TSI_OK if the hanshake completed successfully and there has been no |
+ errors. Returns TSI_HANDSHAKE_IN_PROGRESS if the handshaker is not done yet |
+ but no error has been encountered so far. Otherwise the handshaker failed |
+ with the returned error. */ |
+tsi_result tsi_handshaker_get_result(tsi_handshaker *self); |
+ |
+/* Returns 1 if the handshake is in progress, 0 otherwise. */ |
+#define tsi_handshaker_is_in_progress(h) \ |
+ (tsi_handshaker_get_result((h)) == TSI_HANDSHAKE_IN_PROGRESS) |
+ |
+/* This method may return TSI_FAILED_PRECONDITION if |
+ tsi_handshaker_is_in_progress returns 1, it returns TSI_OK otherwise |
+ assuming the handshaker is not in a fatal error state. |
+ The caller is responsible for destructing the peer. */ |
+tsi_result tsi_handshaker_extract_peer(tsi_handshaker *self, tsi_peer *peer); |
+ |
+/* This method creates a tsi_frame_protector object after the handshake phase |
+ is done. After this method has been called successfully, the only method |
+ that can be called on this object is Destroy. |
+ - max_output_protected_frame_size is an input/output parameter specifying the |
+ desired max output protected frame size as input and outputing the actual |
+ max output frame size as the output. Passing NULL is OK and will result in |
+ the implementation choosing the default maximum protected frame size. Note |
+ that this size only applies to outgoing frames (generated with |
+ tsi_frame_protector_protect) and not incoming frames (input of |
+ tsi_frame_protector_unprotect). |
+ - protector is an output parameter pointing to the newly created |
+ tsi_frame_protector object. |
+ This method may return TSI_FAILED_PRECONDITION if |
+ tsi_handshaker_is_in_progress returns 1, it returns TSI_OK otherwise assuming |
+ the handshaker is not in a fatal error state. |
+ The caller is responsible for destroying the protector. */ |
+tsi_result tsi_handshaker_create_frame_protector( |
+ tsi_handshaker *self, size_t *max_output_protected_frame_size, |
+ tsi_frame_protector **protector); |
+ |
+/* This method releases the tsi_handshaker object. After this method is called, |
+ no other method can be called on the object. */ |
+void tsi_handshaker_destroy(tsi_handshaker *self); |
+ |
+#ifdef __cplusplus |
+} |
+#endif |
+ |
+#endif /* GRPC_INTERNAL_CORE_TSI_TRANSPORT_SECURITY_INTERFACE_H */ |