blob: 4efcf8f43d8668db95ef74419094f14d9280e659 [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 Tillerb29f1fe2017-03-28 15:49:23 -070034#include "src/core/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
Craig Tiller3b654362017-05-04 08:11:17 -070044grpc_tracer_flag tsi_tracing_enabled = GRPC_TRACER_INITIALIZER(false);
Julien Boeuf980f6002015-02-26 16:41:41 -080045
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";
jiangtaoli201620b9f942017-04-07 12:50:33 -070076 case TSI_ASYNC:
77 return "TSI_ASYNC";
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080078 default:
79 return "UNKNOWN";
Craig Tillera82950e2015-09-22 12:33:20 -070080 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080081}
82
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080083/* --- tsi_frame_protector common implementation. ---
84
85 Calls specific implementation after state/input validation. */
86
Craig Tillera82950e2015-09-22 12:33:20 -070087tsi_result tsi_frame_protector_protect(tsi_frame_protector *self,
88 const unsigned char *unprotected_bytes,
89 size_t *unprotected_bytes_size,
90 unsigned char *protected_output_frames,
91 size_t *protected_output_frames_size) {
92 if (self == NULL || unprotected_bytes == NULL ||
93 unprotected_bytes_size == NULL || protected_output_frames == NULL ||
94 protected_output_frames_size == NULL) {
95 return TSI_INVALID_ARGUMENT;
96 }
jiangtaoli2016c1955022017-04-11 09:36:19 -070097 if (self->vtable == NULL || self->vtable->protect == NULL) {
98 return TSI_UNIMPLEMENTED;
99 }
Craig Tillera82950e2015-09-22 12:33:20 -0700100 return self->vtable->protect(self, unprotected_bytes, unprotected_bytes_size,
101 protected_output_frames,
102 protected_output_frames_size);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800103}
104
Craig Tillera82950e2015-09-22 12:33:20 -0700105tsi_result tsi_frame_protector_protect_flush(
106 tsi_frame_protector *self, unsigned char *protected_output_frames,
107 size_t *protected_output_frames_size, size_t *still_pending_size) {
108 if (self == NULL || protected_output_frames == NULL ||
Igor Pylypivb7de7172017-03-30 23:06:16 -0700109 protected_output_frames_size == NULL || still_pending_size == NULL) {
Craig Tillera82950e2015-09-22 12:33:20 -0700110 return TSI_INVALID_ARGUMENT;
111 }
jiangtaoli2016c1955022017-04-11 09:36:19 -0700112 if (self->vtable == NULL || self->vtable->protect_flush == NULL) {
113 return TSI_UNIMPLEMENTED;
114 }
Craig Tillera82950e2015-09-22 12:33:20 -0700115 return self->vtable->protect_flush(self, protected_output_frames,
116 protected_output_frames_size,
117 still_pending_size);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800118}
119
Craig Tillera82950e2015-09-22 12:33:20 -0700120tsi_result tsi_frame_protector_unprotect(
121 tsi_frame_protector *self, const unsigned char *protected_frames_bytes,
122 size_t *protected_frames_bytes_size, unsigned char *unprotected_bytes,
123 size_t *unprotected_bytes_size) {
124 if (self == NULL || protected_frames_bytes == NULL ||
125 protected_frames_bytes_size == NULL || unprotected_bytes == NULL ||
126 unprotected_bytes_size == NULL) {
127 return TSI_INVALID_ARGUMENT;
128 }
jiangtaoli2016c1955022017-04-11 09:36:19 -0700129 if (self->vtable == NULL || self->vtable->unprotect == NULL) {
130 return TSI_UNIMPLEMENTED;
131 }
Craig Tillera82950e2015-09-22 12:33:20 -0700132 return self->vtable->unprotect(self, protected_frames_bytes,
133 protected_frames_bytes_size, unprotected_bytes,
134 unprotected_bytes_size);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800135}
136
Craig Tillera82950e2015-09-22 12:33:20 -0700137void tsi_frame_protector_destroy(tsi_frame_protector *self) {
138 if (self == NULL) return;
139 self->vtable->destroy(self);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800140}
141
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800142/* --- tsi_handshaker common implementation. ---
143
144 Calls specific implementation after state/input validation. */
145
Craig Tillera82950e2015-09-22 12:33:20 -0700146tsi_result tsi_handshaker_get_bytes_to_send_to_peer(tsi_handshaker *self,
147 unsigned char *bytes,
148 size_t *bytes_size) {
Julien Boeuf4c8e8182015-12-07 11:34:12 -0800149 if (self == NULL || bytes == NULL || bytes_size == NULL) {
150 return TSI_INVALID_ARGUMENT;
151 }
Craig Tillera82950e2015-09-22 12:33:20 -0700152 if (self->frame_protector_created) return TSI_FAILED_PRECONDITION;
jiangtaoli2016c1955022017-04-11 09:36:19 -0700153 if (self->vtable == NULL || self->vtable->get_bytes_to_send_to_peer == NULL) {
154 return TSI_UNIMPLEMENTED;
155 }
Craig Tillera82950e2015-09-22 12:33:20 -0700156 return self->vtable->get_bytes_to_send_to_peer(self, bytes, bytes_size);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800157}
158
Craig Tillera82950e2015-09-22 12:33:20 -0700159tsi_result tsi_handshaker_process_bytes_from_peer(tsi_handshaker *self,
160 const unsigned char *bytes,
161 size_t *bytes_size) {
Julien Boeuf4c8e8182015-12-07 11:34:12 -0800162 if (self == NULL || bytes == NULL || bytes_size == NULL) {
163 return TSI_INVALID_ARGUMENT;
164 }
Craig Tillera82950e2015-09-22 12:33:20 -0700165 if (self->frame_protector_created) return TSI_FAILED_PRECONDITION;
jiangtaoli2016c1955022017-04-11 09:36:19 -0700166 if (self->vtable == NULL || self->vtable->process_bytes_from_peer == NULL) {
167 return TSI_UNIMPLEMENTED;
168 }
Craig Tillera82950e2015-09-22 12:33:20 -0700169 return self->vtable->process_bytes_from_peer(self, bytes, bytes_size);
Craig Tiller45724b32015-09-22 10:42:19 -0700170}
171
Craig Tillera82950e2015-09-22 12:33:20 -0700172tsi_result tsi_handshaker_get_result(tsi_handshaker *self) {
173 if (self == NULL) return TSI_INVALID_ARGUMENT;
174 if (self->frame_protector_created) return TSI_FAILED_PRECONDITION;
jiangtaoli2016c1955022017-04-11 09:36:19 -0700175 if (self->vtable == NULL || self->vtable->get_result == NULL) {
176 return TSI_UNIMPLEMENTED;
177 }
Craig Tillera82950e2015-09-22 12:33:20 -0700178 return self->vtable->get_result(self);
Craig Tiller45724b32015-09-22 10:42:19 -0700179}
180
Craig Tillera82950e2015-09-22 12:33:20 -0700181tsi_result tsi_handshaker_extract_peer(tsi_handshaker *self, tsi_peer *peer) {
182 if (self == NULL || peer == NULL) return TSI_INVALID_ARGUMENT;
183 memset(peer, 0, sizeof(tsi_peer));
184 if (self->frame_protector_created) return TSI_FAILED_PRECONDITION;
185 if (tsi_handshaker_get_result(self) != TSI_OK) {
Craig Tiller45724b32015-09-22 10:42:19 -0700186 return TSI_FAILED_PRECONDITION;
Craig Tillera82950e2015-09-22 12:33:20 -0700187 }
jiangtaoli2016c1955022017-04-11 09:36:19 -0700188 if (self->vtable == NULL || self->vtable->extract_peer == NULL) {
189 return TSI_UNIMPLEMENTED;
190 }
Craig Tillera82950e2015-09-22 12:33:20 -0700191 return self->vtable->extract_peer(self, peer);
Craig Tiller45724b32015-09-22 10:42:19 -0700192}
193
Craig Tillera82950e2015-09-22 12:33:20 -0700194tsi_result tsi_handshaker_create_frame_protector(
195 tsi_handshaker *self, size_t *max_protected_frame_size,
196 tsi_frame_protector **protector) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800197 tsi_result result;
Craig Tillera82950e2015-09-22 12:33:20 -0700198 if (self == NULL || protector == NULL) return TSI_INVALID_ARGUMENT;
199 if (self->frame_protector_created) return TSI_FAILED_PRECONDITION;
200 if (tsi_handshaker_get_result(self) != TSI_OK) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800201 return TSI_FAILED_PRECONDITION;
Craig Tillera82950e2015-09-22 12:33:20 -0700202 }
jiangtaoli2016c1955022017-04-11 09:36:19 -0700203 if (self->vtable == NULL || self->vtable->create_frame_protector == NULL) {
204 return TSI_UNIMPLEMENTED;
205 }
Craig Tillera82950e2015-09-22 12:33:20 -0700206 result = self->vtable->create_frame_protector(self, max_protected_frame_size,
207 protector);
208 if (result == TSI_OK) {
jiangtaoli2016e69881d2017-04-10 14:29:43 -0700209 self->frame_protector_created = true;
Craig Tillera82950e2015-09-22 12:33:20 -0700210 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800211 return result;
212}
213
jiangtaoli201620b9f942017-04-07 12:50:33 -0700214tsi_result tsi_handshaker_next(
215 tsi_handshaker *self, const unsigned char *received_bytes,
216 size_t received_bytes_size, unsigned char **bytes_to_send,
217 size_t *bytes_to_send_size, tsi_handshaker_result **handshaker_result,
218 tsi_handshaker_on_next_done_cb cb, void *user_data) {
219 if (self == NULL) return TSI_INVALID_ARGUMENT;
220 if (self->handshaker_result_created) return TSI_FAILED_PRECONDITION;
jiangtaoli2016c1955022017-04-11 09:36:19 -0700221 if (self->vtable == NULL || self->vtable->next == NULL) {
222 return TSI_UNIMPLEMENTED;
223 }
jiangtaoli201620b9f942017-04-07 12:50:33 -0700224 return self->vtable->next(self, received_bytes, received_bytes_size,
225 bytes_to_send, bytes_to_send_size,
226 handshaker_result, cb, user_data);
227}
228
Craig Tillera82950e2015-09-22 12:33:20 -0700229void tsi_handshaker_destroy(tsi_handshaker *self) {
230 if (self == NULL) return;
231 self->vtable->destroy(self);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800232}
233
jiangtaoli201620b9f942017-04-07 12:50:33 -0700234/* --- tsi_handshaker_result implementation. --- */
235
jiangtaoli2016e69881d2017-04-10 14:29:43 -0700236tsi_result tsi_handshaker_result_extract_peer(const tsi_handshaker_result *self,
jiangtaoli201620b9f942017-04-07 12:50:33 -0700237 tsi_peer *peer) {
238 if (self == NULL || peer == NULL) return TSI_INVALID_ARGUMENT;
239 memset(peer, 0, sizeof(tsi_peer));
jiangtaoli2016c1955022017-04-11 09:36:19 -0700240 if (self->vtable == NULL || self->vtable->extract_peer == NULL) {
241 return TSI_UNIMPLEMENTED;
242 }
jiangtaoli201620b9f942017-04-07 12:50:33 -0700243 return self->vtable->extract_peer(self, peer);
244}
245
246tsi_result tsi_handshaker_result_create_frame_protector(
jiangtaoli2016e69881d2017-04-10 14:29:43 -0700247 const tsi_handshaker_result *self, size_t *max_protected_frame_size,
jiangtaoli201620b9f942017-04-07 12:50:33 -0700248 tsi_frame_protector **protector) {
249 if (self == NULL || protector == NULL) return TSI_INVALID_ARGUMENT;
jiangtaoli2016c1955022017-04-11 09:36:19 -0700250 if (self->vtable == NULL || self->vtable->create_frame_protector == NULL) {
251 return TSI_UNIMPLEMENTED;
252 }
jiangtaoli201620b9f942017-04-07 12:50:33 -0700253 return self->vtable->create_frame_protector(self, max_protected_frame_size,
254 protector);
255}
256
257tsi_result tsi_handshaker_result_get_unused_bytes(
jiangtaoli2016e69881d2017-04-10 14:29:43 -0700258 const tsi_handshaker_result *self, unsigned char **bytes,
259 size_t *bytes_size) {
jiangtaoli201620b9f942017-04-07 12:50:33 -0700260 if (self == NULL || bytes == NULL || bytes_size == NULL) {
261 return TSI_INVALID_ARGUMENT;
262 }
jiangtaoli2016c1955022017-04-11 09:36:19 -0700263 if (self->vtable == NULL || self->vtable->get_unused_bytes == NULL) {
264 return TSI_UNIMPLEMENTED;
265 }
jiangtaoli201620b9f942017-04-07 12:50:33 -0700266 return self->vtable->get_unused_bytes(self, bytes, bytes_size);
267}
268
269void tsi_handshaker_result_destroy(tsi_handshaker_result *self) {
270 if (self == NULL) return;
271 self->vtable->destroy(self);
272}
273
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800274/* --- tsi_peer implementation. --- */
275
Craig Tillera82950e2015-09-22 12:33:20 -0700276tsi_peer_property tsi_init_peer_property(void) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800277 tsi_peer_property property;
Craig Tillera82950e2015-09-22 12:33:20 -0700278 memset(&property, 0, sizeof(tsi_peer_property));
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800279 return property;
280}
281
Craig Tillera82950e2015-09-22 12:33:20 -0700282static void tsi_peer_destroy_list_property(tsi_peer_property *children,
283 size_t child_count) {
Julien Boeufb222b4d2015-01-15 17:01:39 -0800284 size_t i;
Craig Tillera82950e2015-09-22 12:33:20 -0700285 for (i = 0; i < child_count; i++) {
286 tsi_peer_property_destruct(&children[i]);
287 }
Nicolas "Pixel" Nobleb29d8cf2016-04-08 01:38:29 +0200288 gpr_free(children);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800289}
290
Craig Tillera82950e2015-09-22 12:33:20 -0700291void tsi_peer_property_destruct(tsi_peer_property *property) {
292 if (property->name != NULL) {
Nicolas "Pixel" Nobleb29d8cf2016-04-08 01:38:29 +0200293 gpr_free(property->name);
Craig Tillera82950e2015-09-22 12:33:20 -0700294 }
295 if (property->value.data != NULL) {
Nicolas "Pixel" Nobleb29d8cf2016-04-08 01:38:29 +0200296 gpr_free(property->value.data);
Craig Tillera82950e2015-09-22 12:33:20 -0700297 }
298 *property = tsi_init_peer_property(); /* Reset everything to 0. */
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800299}
300
Craig Tillera82950e2015-09-22 12:33:20 -0700301void tsi_peer_destruct(tsi_peer *self) {
302 if (self == NULL) return;
303 if (self->properties != NULL) {
304 tsi_peer_destroy_list_property(self->properties, self->property_count);
305 self->properties = NULL;
306 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800307 self->property_count = 0;
308}
309
Craig Tillera82950e2015-09-22 12:33:20 -0700310tsi_result tsi_construct_allocated_string_peer_property(
311 const char *name, size_t value_length, tsi_peer_property *property) {
312 *property = tsi_init_peer_property();
Nicolas "Pixel" Noble7c9a1542016-03-26 01:33:34 +0100313 if (name != NULL) property->name = gpr_strdup(name);
Craig Tillera82950e2015-09-22 12:33:20 -0700314 if (value_length > 0) {
Craig Tiller6f417882017-02-16 14:09:39 -0800315 property->value.data = gpr_zalloc(value_length);
Craig Tillera82950e2015-09-22 12:33:20 -0700316 property->value.length = value_length;
317 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800318 return TSI_OK;
319}
320
Craig Tillera82950e2015-09-22 12:33:20 -0700321tsi_result tsi_construct_string_peer_property_from_cstring(
322 const char *name, const char *value, tsi_peer_property *property) {
323 return tsi_construct_string_peer_property(name, value, strlen(value),
324 property);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800325}
326
Craig Tillera82950e2015-09-22 12:33:20 -0700327tsi_result tsi_construct_string_peer_property(const char *name,
328 const char *value,
329 size_t value_length,
330 tsi_peer_property *property) {
331 tsi_result result = tsi_construct_allocated_string_peer_property(
332 name, value_length, property);
333 if (result != TSI_OK) return result;
334 if (value_length > 0) {
335 memcpy(property->value.data, value, value_length);
336 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800337 return TSI_OK;
338}
339
Craig Tillera82950e2015-09-22 12:33:20 -0700340tsi_result tsi_construct_peer(size_t property_count, tsi_peer *peer) {
341 memset(peer, 0, sizeof(tsi_peer));
342 if (property_count > 0) {
Craig Tiller6f417882017-02-16 14:09:39 -0800343 peer->properties = gpr_zalloc(property_count * sizeof(tsi_peer_property));
Craig Tillera82950e2015-09-22 12:33:20 -0700344 peer->property_count = property_count;
345 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800346 return TSI_OK;
Craig Tiller190d3602015-02-18 09:23:38 -0800347}