blob: 2cbf381c88d6bd5fa92d40c5b1158e453e345787 [file] [log] [blame]
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001/*
2 *
Craig Tiller6169d5f2016-03-31 07:46:18 -07003 * Copyright 2015, Google Inc.
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08004 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following disclaimer
14 * in the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Google Inc. nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 */
33
Craig Tiller9533d042016-03-25 17:11:06 -070034#include "src/core/lib/tsi/transport_security.h"
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080035
Nicolas "Pixel" Nobleb29d8cf2016-04-08 01:38:29 +020036#include <grpc/support/alloc.h>
37#include <grpc/support/string_util.h>
38
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080039#include <stdlib.h>
40#include <string.h>
41
Julien Boeuf980f6002015-02-26 16:41:41 -080042/* --- Tracing. --- */
43
44int tsi_tracing_enabled = 0;
45
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080046/* --- tsi_result common implementation. --- */
47
Craig Tillera82950e2015-09-22 12:33:20 -070048const char *tsi_result_to_string(tsi_result result) {
49 switch (result) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080050 case TSI_OK:
51 return "TSI_OK";
52 case TSI_UNKNOWN_ERROR:
53 return "TSI_UNKNOWN_ERROR";
54 case TSI_INVALID_ARGUMENT:
55 return "TSI_INVALID_ARGUMENT";
56 case TSI_PERMISSION_DENIED:
57 return "TSI_PERMISSION_DENIED";
58 case TSI_INCOMPLETE_DATA:
59 return "TSI_INCOMPLETE_DATA";
60 case TSI_FAILED_PRECONDITION:
61 return "TSI_FAILED_PRECONDITION";
62 case TSI_UNIMPLEMENTED:
63 return "TSI_UNIMPLEMENTED";
64 case TSI_INTERNAL_ERROR:
65 return "TSI_INTERNAL_ERROR";
66 case TSI_DATA_CORRUPTED:
67 return "TSI_DATA_CORRUPTED";
68 case TSI_NOT_FOUND:
69 return "TSI_NOT_FOUND";
70 case TSI_PROTOCOL_FAILURE:
71 return "TSI_PROTOCOL_FAILURE";
72 case TSI_HANDSHAKE_IN_PROGRESS:
73 return "TSI_HANDSHAKE_IN_PROGRESS";
74 case TSI_OUT_OF_RESOURCES:
75 return "TSI_OUT_OF_RESOURCES";
76 default:
77 return "UNKNOWN";
Craig Tillera82950e2015-09-22 12:33:20 -070078 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080079}
80
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080081/* --- tsi_frame_protector common implementation. ---
82
83 Calls specific implementation after state/input validation. */
84
Craig Tillera82950e2015-09-22 12:33:20 -070085tsi_result tsi_frame_protector_protect(tsi_frame_protector *self,
86 const unsigned char *unprotected_bytes,
87 size_t *unprotected_bytes_size,
88 unsigned char *protected_output_frames,
89 size_t *protected_output_frames_size) {
90 if (self == NULL || unprotected_bytes == NULL ||
91 unprotected_bytes_size == NULL || protected_output_frames == NULL ||
92 protected_output_frames_size == NULL) {
93 return TSI_INVALID_ARGUMENT;
94 }
95 return self->vtable->protect(self, unprotected_bytes, unprotected_bytes_size,
96 protected_output_frames,
97 protected_output_frames_size);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080098}
99
Craig Tillera82950e2015-09-22 12:33:20 -0700100tsi_result tsi_frame_protector_protect_flush(
101 tsi_frame_protector *self, unsigned char *protected_output_frames,
102 size_t *protected_output_frames_size, size_t *still_pending_size) {
103 if (self == NULL || protected_output_frames == NULL ||
104 protected_output_frames == NULL || still_pending_size == NULL) {
105 return TSI_INVALID_ARGUMENT;
106 }
107 return self->vtable->protect_flush(self, protected_output_frames,
108 protected_output_frames_size,
109 still_pending_size);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800110}
111
Craig Tillera82950e2015-09-22 12:33:20 -0700112tsi_result tsi_frame_protector_unprotect(
113 tsi_frame_protector *self, const unsigned char *protected_frames_bytes,
114 size_t *protected_frames_bytes_size, unsigned char *unprotected_bytes,
115 size_t *unprotected_bytes_size) {
116 if (self == NULL || protected_frames_bytes == NULL ||
117 protected_frames_bytes_size == NULL || unprotected_bytes == NULL ||
118 unprotected_bytes_size == NULL) {
119 return TSI_INVALID_ARGUMENT;
120 }
121 return self->vtable->unprotect(self, protected_frames_bytes,
122 protected_frames_bytes_size, unprotected_bytes,
123 unprotected_bytes_size);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800124}
125
Craig Tillera82950e2015-09-22 12:33:20 -0700126void tsi_frame_protector_destroy(tsi_frame_protector *self) {
127 if (self == NULL) return;
128 self->vtable->destroy(self);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800129}
130
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800131/* --- tsi_handshaker common implementation. ---
132
133 Calls specific implementation after state/input validation. */
134
Craig Tillera82950e2015-09-22 12:33:20 -0700135tsi_result tsi_handshaker_get_bytes_to_send_to_peer(tsi_handshaker *self,
136 unsigned char *bytes,
137 size_t *bytes_size) {
Julien Boeuf4c8e8182015-12-07 11:34:12 -0800138 if (self == NULL || bytes == NULL || bytes_size == NULL) {
139 return TSI_INVALID_ARGUMENT;
140 }
Craig Tillera82950e2015-09-22 12:33:20 -0700141 if (self->frame_protector_created) return TSI_FAILED_PRECONDITION;
142 return self->vtable->get_bytes_to_send_to_peer(self, bytes, bytes_size);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800143}
144
Craig Tillera82950e2015-09-22 12:33:20 -0700145tsi_result tsi_handshaker_process_bytes_from_peer(tsi_handshaker *self,
146 const unsigned char *bytes,
147 size_t *bytes_size) {
Julien Boeuf4c8e8182015-12-07 11:34:12 -0800148 if (self == NULL || bytes == NULL || bytes_size == NULL) {
149 return TSI_INVALID_ARGUMENT;
150 }
Craig Tillera82950e2015-09-22 12:33:20 -0700151 if (self->frame_protector_created) return TSI_FAILED_PRECONDITION;
152 return self->vtable->process_bytes_from_peer(self, bytes, bytes_size);
Craig Tiller45724b32015-09-22 10:42:19 -0700153}
154
Craig Tillera82950e2015-09-22 12:33:20 -0700155tsi_result tsi_handshaker_get_result(tsi_handshaker *self) {
156 if (self == NULL) return TSI_INVALID_ARGUMENT;
157 if (self->frame_protector_created) return TSI_FAILED_PRECONDITION;
158 return self->vtable->get_result(self);
Craig Tiller45724b32015-09-22 10:42:19 -0700159}
160
Craig Tillera82950e2015-09-22 12:33:20 -0700161tsi_result tsi_handshaker_extract_peer(tsi_handshaker *self, tsi_peer *peer) {
162 if (self == NULL || peer == NULL) return TSI_INVALID_ARGUMENT;
163 memset(peer, 0, sizeof(tsi_peer));
164 if (self->frame_protector_created) return TSI_FAILED_PRECONDITION;
165 if (tsi_handshaker_get_result(self) != TSI_OK) {
Craig Tiller45724b32015-09-22 10:42:19 -0700166 return TSI_FAILED_PRECONDITION;
Craig Tillera82950e2015-09-22 12:33:20 -0700167 }
168 return self->vtable->extract_peer(self, peer);
Craig Tiller45724b32015-09-22 10:42:19 -0700169}
170
Craig Tillera82950e2015-09-22 12:33:20 -0700171tsi_result tsi_handshaker_create_frame_protector(
172 tsi_handshaker *self, size_t *max_protected_frame_size,
173 tsi_frame_protector **protector) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800174 tsi_result result;
Craig Tillera82950e2015-09-22 12:33:20 -0700175 if (self == NULL || protector == NULL) return TSI_INVALID_ARGUMENT;
176 if (self->frame_protector_created) return TSI_FAILED_PRECONDITION;
177 if (tsi_handshaker_get_result(self) != TSI_OK) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800178 return TSI_FAILED_PRECONDITION;
Craig Tillera82950e2015-09-22 12:33:20 -0700179 }
180 result = self->vtable->create_frame_protector(self, max_protected_frame_size,
181 protector);
182 if (result == TSI_OK) {
183 self->frame_protector_created = 1;
184 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800185 return result;
186}
187
Craig Tillera82950e2015-09-22 12:33:20 -0700188void tsi_handshaker_destroy(tsi_handshaker *self) {
189 if (self == NULL) return;
190 self->vtable->destroy(self);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800191}
192
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800193/* --- tsi_peer implementation. --- */
194
Craig Tillera82950e2015-09-22 12:33:20 -0700195tsi_peer_property tsi_init_peer_property(void) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800196 tsi_peer_property property;
Craig Tillera82950e2015-09-22 12:33:20 -0700197 memset(&property, 0, sizeof(tsi_peer_property));
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800198 return property;
199}
200
Craig Tillera82950e2015-09-22 12:33:20 -0700201static void tsi_peer_destroy_list_property(tsi_peer_property *children,
202 size_t child_count) {
Julien Boeufb222b4d2015-01-15 17:01:39 -0800203 size_t i;
Craig Tillera82950e2015-09-22 12:33:20 -0700204 for (i = 0; i < child_count; i++) {
205 tsi_peer_property_destruct(&children[i]);
206 }
Nicolas "Pixel" Nobleb29d8cf2016-04-08 01:38:29 +0200207 gpr_free(children);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800208}
209
Craig Tillera82950e2015-09-22 12:33:20 -0700210void tsi_peer_property_destruct(tsi_peer_property *property) {
211 if (property->name != NULL) {
Nicolas "Pixel" Nobleb29d8cf2016-04-08 01:38:29 +0200212 gpr_free(property->name);
Craig Tillera82950e2015-09-22 12:33:20 -0700213 }
214 if (property->value.data != NULL) {
Nicolas "Pixel" Nobleb29d8cf2016-04-08 01:38:29 +0200215 gpr_free(property->value.data);
Craig Tillera82950e2015-09-22 12:33:20 -0700216 }
217 *property = tsi_init_peer_property(); /* Reset everything to 0. */
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800218}
219
Craig Tillera82950e2015-09-22 12:33:20 -0700220void tsi_peer_destruct(tsi_peer *self) {
221 if (self == NULL) return;
222 if (self->properties != NULL) {
223 tsi_peer_destroy_list_property(self->properties, self->property_count);
224 self->properties = NULL;
225 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800226 self->property_count = 0;
227}
228
Craig Tillera82950e2015-09-22 12:33:20 -0700229tsi_result tsi_construct_allocated_string_peer_property(
230 const char *name, size_t value_length, tsi_peer_property *property) {
231 *property = tsi_init_peer_property();
Nicolas "Pixel" Noble7c9a1542016-03-26 01:33:34 +0100232 if (name != NULL) property->name = gpr_strdup(name);
Craig Tillera82950e2015-09-22 12:33:20 -0700233 if (value_length > 0) {
Craig Tiller6f417882017-02-16 14:09:39 -0800234 property->value.data = gpr_zalloc(value_length);
Craig Tillera82950e2015-09-22 12:33:20 -0700235 property->value.length = value_length;
236 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800237 return TSI_OK;
238}
239
Craig Tillera82950e2015-09-22 12:33:20 -0700240tsi_result tsi_construct_string_peer_property_from_cstring(
241 const char *name, const char *value, tsi_peer_property *property) {
242 return tsi_construct_string_peer_property(name, value, strlen(value),
243 property);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800244}
245
Craig Tillera82950e2015-09-22 12:33:20 -0700246tsi_result tsi_construct_string_peer_property(const char *name,
247 const char *value,
248 size_t value_length,
249 tsi_peer_property *property) {
250 tsi_result result = tsi_construct_allocated_string_peer_property(
251 name, value_length, property);
252 if (result != TSI_OK) return result;
253 if (value_length > 0) {
254 memcpy(property->value.data, value, value_length);
255 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800256 return TSI_OK;
257}
258
Craig Tillera82950e2015-09-22 12:33:20 -0700259tsi_result tsi_construct_peer(size_t property_count, tsi_peer *peer) {
260 memset(peer, 0, sizeof(tsi_peer));
261 if (property_count > 0) {
Craig Tiller6f417882017-02-16 14:09:39 -0800262 peer->properties = gpr_zalloc(property_count * sizeof(tsi_peer_property));
Craig Tillera82950e2015-09-22 12:33:20 -0700263 peer->property_count = property_count;
264 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800265 return TSI_OK;
Craig Tiller190d3602015-02-18 09:23:38 -0800266}