blob: 9f2147b53017376b6148d269166f04436558bf5a [file] [log] [blame]
jiangtaoli201620b9f942017-04-07 12:50:33 -07001/*
2 *
3 * Copyright 2017, Google Inc.
4 * 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
34#include "src/core/tsi/transport_security_adapter.h"
35
36#include <string.h>
37
38#include <grpc/support/alloc.h>
39#include <grpc/support/log.h>
40#include "src/core/tsi/transport_security.h"
41
42#define TSI_ADAPTER_INITIAL_BUFFER_SIZE 256
43
44/* --- tsi_adapter_handshaker_result implementation ---*/
45
46typedef struct {
47 tsi_handshaker_result base;
jiangtaoli2016c1955022017-04-11 09:36:19 -070048 tsi_handshaker *wrapped;
jiangtaoli201620b9f942017-04-07 12:50:33 -070049 unsigned char *unused_bytes;
50 size_t unused_bytes_size;
51} tsi_adapter_handshaker_result;
52
jiangtaoli2016c1955022017-04-11 09:36:19 -070053static tsi_result adapter_result_extract_peer(const tsi_handshaker_result *self,
54 tsi_peer *peer) {
jiangtaoli201620b9f942017-04-07 12:50:33 -070055 tsi_adapter_handshaker_result *impl = (tsi_adapter_handshaker_result *)self;
jiangtaoli2016c1955022017-04-11 09:36:19 -070056 return tsi_handshaker_extract_peer(impl->wrapped, peer);
jiangtaoli201620b9f942017-04-07 12:50:33 -070057}
58
jiangtaoli2016c1955022017-04-11 09:36:19 -070059static tsi_result adapter_result_create_frame_protector(
jiangtaoli2016e69881d2017-04-10 14:29:43 -070060 const tsi_handshaker_result *self, size_t *max_output_protected_frame_size,
jiangtaoli201620b9f942017-04-07 12:50:33 -070061 tsi_frame_protector **protector) {
62 tsi_adapter_handshaker_result *impl = (tsi_adapter_handshaker_result *)self;
63 return tsi_handshaker_create_frame_protector(
jiangtaoli2016c1955022017-04-11 09:36:19 -070064 impl->wrapped, max_output_protected_frame_size, protector);
jiangtaoli201620b9f942017-04-07 12:50:33 -070065}
66
jiangtaoli2016c1955022017-04-11 09:36:19 -070067static tsi_result adapter_result_get_unused_bytes(
jiangtaoli2016e69881d2017-04-10 14:29:43 -070068 const tsi_handshaker_result *self, unsigned char **bytes,
69 size_t *byte_size) {
jiangtaoli201620b9f942017-04-07 12:50:33 -070070 tsi_adapter_handshaker_result *impl = (tsi_adapter_handshaker_result *)self;
71 *bytes = impl->unused_bytes;
72 *byte_size = impl->unused_bytes_size;
73 return TSI_OK;
74}
75
jiangtaoli2016c1955022017-04-11 09:36:19 -070076static void adapter_result_destroy(tsi_handshaker_result *self) {
jiangtaoli201620b9f942017-04-07 12:50:33 -070077 tsi_adapter_handshaker_result *impl = (tsi_adapter_handshaker_result *)self;
jiangtaoli2016c953b622017-04-11 10:16:19 -070078 tsi_handshaker_destroy(impl->wrapped);
jiangtaoli2016e69881d2017-04-10 14:29:43 -070079 gpr_free(impl->unused_bytes);
jiangtaoli201620b9f942017-04-07 12:50:33 -070080 gpr_free(self);
81}
82
83static const tsi_handshaker_result_vtable result_vtable = {
jiangtaoli2016c1955022017-04-11 09:36:19 -070084 adapter_result_extract_peer, adapter_result_create_frame_protector,
85 adapter_result_get_unused_bytes, adapter_result_destroy,
jiangtaoli201620b9f942017-04-07 12:50:33 -070086};
87
jiangtaoli2016c953b622017-04-11 10:16:19 -070088/* Ownership of wrapped tsi_handshaker is transferred to the result object. */
89static tsi_result tsi_adapter_create_handshaker_result(
jiangtaoli2016c1955022017-04-11 09:36:19 -070090 tsi_handshaker *wrapped, const unsigned char *unused_bytes,
jiangtaoli201620b9f942017-04-07 12:50:33 -070091 size_t unused_bytes_size, tsi_handshaker_result **handshaker_result) {
jiangtaoli2016c1955022017-04-11 09:36:19 -070092 if (wrapped == NULL || (unused_bytes_size > 0 && unused_bytes == NULL)) {
jiangtaoli201620b9f942017-04-07 12:50:33 -070093 return TSI_INVALID_ARGUMENT;
94 }
95 tsi_adapter_handshaker_result *impl = gpr_zalloc(sizeof(*impl));
96 impl->base.vtable = &result_vtable;
jiangtaoli2016c1955022017-04-11 09:36:19 -070097 impl->wrapped = wrapped;
jiangtaoli201620b9f942017-04-07 12:50:33 -070098 impl->unused_bytes_size = unused_bytes_size;
99 if (unused_bytes_size > 0) {
100 impl->unused_bytes = gpr_malloc(unused_bytes_size);
101 memcpy(impl->unused_bytes, unused_bytes, unused_bytes_size);
102 } else {
103 impl->unused_bytes = NULL;
104 }
105 *handshaker_result = &impl->base;
106 return TSI_OK;
107}
108
109/* --- tsi_adapter_handshaker implementation ---*/
110
111typedef struct {
112 tsi_handshaker base;
113 tsi_handshaker *wrapped;
114 unsigned char *adapter_buffer;
115 size_t adapter_buffer_size;
116} tsi_adapter_handshaker;
117
jiangtaoli2016c1955022017-04-11 09:36:19 -0700118static tsi_result adapter_get_bytes_to_send_to_peer(tsi_handshaker *self,
119 unsigned char *bytes,
120 size_t *bytes_size) {
jiangtaoli201620b9f942017-04-07 12:50:33 -0700121 return tsi_handshaker_get_bytes_to_send_to_peer(
122 tsi_adapter_handshaker_get_wrapped(self), bytes, bytes_size);
123}
124
jiangtaoli2016c1955022017-04-11 09:36:19 -0700125static tsi_result adapter_process_bytes_from_peer(tsi_handshaker *self,
126 const unsigned char *bytes,
127 size_t *bytes_size) {
jiangtaoli201620b9f942017-04-07 12:50:33 -0700128 return tsi_handshaker_process_bytes_from_peer(
129 tsi_adapter_handshaker_get_wrapped(self), bytes, bytes_size);
130}
131
jiangtaoli2016c1955022017-04-11 09:36:19 -0700132static tsi_result adapter_get_result(tsi_handshaker *self) {
jiangtaoli201620b9f942017-04-07 12:50:33 -0700133 return tsi_handshaker_get_result(tsi_adapter_handshaker_get_wrapped(self));
134}
135
jiangtaoli2016c1955022017-04-11 09:36:19 -0700136static tsi_result adapter_extract_peer(tsi_handshaker *self, tsi_peer *peer) {
jiangtaoli201620b9f942017-04-07 12:50:33 -0700137 return tsi_handshaker_extract_peer(tsi_adapter_handshaker_get_wrapped(self),
138 peer);
139}
140
jiangtaoli2016c1955022017-04-11 09:36:19 -0700141static tsi_result adapter_create_frame_protector(
jiangtaoli2016e69881d2017-04-10 14:29:43 -0700142 tsi_handshaker *self, size_t *max_protected_frame_size,
143 tsi_frame_protector **protector) {
jiangtaoli201620b9f942017-04-07 12:50:33 -0700144 return tsi_handshaker_create_frame_protector(
145 tsi_adapter_handshaker_get_wrapped(self), max_protected_frame_size,
146 protector);
147}
148
jiangtaoli2016c1955022017-04-11 09:36:19 -0700149static void adapter_destroy(tsi_handshaker *self) {
jiangtaoli201620b9f942017-04-07 12:50:33 -0700150 tsi_adapter_handshaker *impl = (tsi_adapter_handshaker *)self;
151 tsi_handshaker_destroy(impl->wrapped);
152 gpr_free(impl->adapter_buffer);
153 gpr_free(self);
154}
155
jiangtaoli2016c1955022017-04-11 09:36:19 -0700156static tsi_result adapter_next(
jiangtaoli201620b9f942017-04-07 12:50:33 -0700157 tsi_handshaker *self, const unsigned char *received_bytes,
158 size_t received_bytes_size, unsigned char **bytes_to_send,
159 size_t *bytes_to_send_size, tsi_handshaker_result **handshaker_result,
160 tsi_handshaker_on_next_done_cb cb, void *user_data) {
161 /* Input sanity check. */
162 if ((received_bytes_size > 0 && received_bytes == NULL) ||
163 bytes_to_send == NULL || bytes_to_send_size == NULL ||
164 handshaker_result == NULL) {
165 return TSI_INVALID_ARGUMENT;
166 }
167
168 /* If there are received bytes, process them first. */
169 tsi_adapter_handshaker *impl = (tsi_adapter_handshaker *)self;
170 tsi_result status = TSI_OK;
171 size_t bytes_consumed = received_bytes_size;
172 if (received_bytes_size > 0) {
173 status = tsi_handshaker_process_bytes_from_peer(
174 impl->wrapped, received_bytes, &bytes_consumed);
175 if (status != TSI_OK) return status;
176 }
177
178 /* Get bytes to send to the peer, if available. */
179 size_t offset = 0;
180 do {
181 size_t to_send_size = impl->adapter_buffer_size - offset;
182 status = tsi_handshaker_get_bytes_to_send_to_peer(
183 impl->wrapped, impl->adapter_buffer + offset, &to_send_size);
184 offset += to_send_size;
185 if (status == TSI_INCOMPLETE_DATA) {
186 impl->adapter_buffer_size *= 2;
187 impl->adapter_buffer =
188 gpr_realloc(impl->adapter_buffer, impl->adapter_buffer_size);
189 }
190 } while (status == TSI_INCOMPLETE_DATA);
191 if (status != TSI_OK) return status;
192 *bytes_to_send = impl->adapter_buffer;
193 *bytes_to_send_size = offset;
194
195 /* If handshake completes, create tsi_handshaker_result. */
jiangtaoli2016a2a20242017-04-10 15:03:21 -0700196 if (tsi_handshaker_is_in_progress(impl->wrapped)) {
197 *handshaker_result = NULL;
198 } else {
jiangtaoli201620b9f942017-04-07 12:50:33 -0700199 size_t unused_bytes_size = received_bytes_size - bytes_consumed;
200 const unsigned char *unused_bytes =
201 unused_bytes_size == 0 ? NULL : received_bytes + bytes_consumed;
jiangtaoli2016e69881d2017-04-10 14:29:43 -0700202 status = tsi_adapter_create_handshaker_result(
jiangtaoli201620b9f942017-04-07 12:50:33 -0700203 impl->wrapped, unused_bytes, unused_bytes_size, handshaker_result);
jiangtaoli2016e69881d2017-04-10 14:29:43 -0700204 if (status == TSI_OK) {
205 impl->base.handshaker_result_created = true;
jiangtaoli2016c953b622017-04-11 10:16:19 -0700206 impl->wrapped = NULL;
jiangtaoli2016e69881d2017-04-10 14:29:43 -0700207 }
jiangtaoli201620b9f942017-04-07 12:50:33 -0700208 }
jiangtaoli2016e69881d2017-04-10 14:29:43 -0700209 return status;
jiangtaoli201620b9f942017-04-07 12:50:33 -0700210}
211
212static const tsi_handshaker_vtable handshaker_vtable = {
jiangtaoli2016c1955022017-04-11 09:36:19 -0700213 adapter_get_bytes_to_send_to_peer,
214 adapter_process_bytes_from_peer,
215 adapter_get_result,
216 adapter_extract_peer,
217 adapter_create_frame_protector,
218 adapter_destroy,
219 adapter_next,
jiangtaoli201620b9f942017-04-07 12:50:33 -0700220};
221
222tsi_handshaker *tsi_create_adapter_handshaker(tsi_handshaker *wrapped) {
223 GPR_ASSERT(wrapped != NULL);
224 tsi_adapter_handshaker *impl = gpr_zalloc(sizeof(*impl));
225 impl->base.vtable = &handshaker_vtable;
226 impl->wrapped = wrapped;
227 impl->adapter_buffer_size = TSI_ADAPTER_INITIAL_BUFFER_SIZE;
228 impl->adapter_buffer = gpr_malloc(impl->adapter_buffer_size);
229 return &impl->base;
230}
231
232tsi_handshaker *tsi_adapter_handshaker_get_wrapped(tsi_handshaker *adapter) {
233 if (adapter == NULL) return NULL;
234 tsi_adapter_handshaker *impl = (tsi_adapter_handshaker *)adapter;
235 return impl->wrapped;
236}