secure_endpoint.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  1. /*
  2. *
  3. * Copyright 2015, 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. #include "src/core/security/secure_endpoint.h"
  34. #include "src/core/support/string.h"
  35. #include <grpc/support/alloc.h>
  36. #include <grpc/support/log.h>
  37. #include <grpc/support/slice_buffer.h>
  38. #include <grpc/support/slice.h>
  39. #include <grpc/support/sync.h>
  40. #include "src/core/tsi/transport_security_interface.h"
  41. #include "src/core/debug/trace.h"
  42. #define STAGING_BUFFER_SIZE 8192
  43. typedef struct {
  44. grpc_endpoint base;
  45. grpc_endpoint *wrapped_ep;
  46. struct tsi_frame_protector *protector;
  47. gpr_mu protector_mu;
  48. /* saved upper level callbacks and user_data. */
  49. grpc_closure *read_cb;
  50. grpc_closure *write_cb;
  51. grpc_closure on_read;
  52. gpr_slice_buffer *read_buffer;
  53. gpr_slice_buffer source_buffer;
  54. /* saved handshaker leftover data to unprotect. */
  55. gpr_slice_buffer leftover_bytes;
  56. /* buffers for read and write */
  57. gpr_slice read_staging_buffer;
  58. gpr_slice write_staging_buffer;
  59. gpr_slice_buffer output_buffer;
  60. gpr_refcount ref;
  61. } secure_endpoint;
  62. int grpc_trace_secure_endpoint = 0;
  63. static void destroy(secure_endpoint *secure_ep, grpc_call_list *call_list) {
  64. secure_endpoint *ep = secure_ep;
  65. grpc_endpoint_destroy(ep->wrapped_ep, call_list);
  66. tsi_frame_protector_destroy(ep->protector);
  67. gpr_slice_buffer_destroy(&ep->leftover_bytes);
  68. gpr_slice_unref(ep->read_staging_buffer);
  69. gpr_slice_unref(ep->write_staging_buffer);
  70. gpr_slice_buffer_destroy(&ep->output_buffer);
  71. gpr_slice_buffer_destroy(&ep->source_buffer);
  72. gpr_mu_destroy(&ep->protector_mu);
  73. gpr_free(ep);
  74. }
  75. /*#define GRPC_SECURE_ENDPOINT_REFCOUNT_DEBUG*/
  76. #ifdef GRPC_SECURE_ENDPOINT_REFCOUNT_DEBUG
  77. #define SECURE_ENDPOINT_UNREF(ep, reason, cl) \
  78. secure_endpoint_unref((ep), (cl), (reason), __FILE__, __LINE__)
  79. #define SECURE_ENDPOINT_REF(ep, reason) \
  80. secure_endpoint_ref((ep), (reason), __FILE__, __LINE__)
  81. static void secure_endpoint_unref(secure_endpoint *ep,
  82. grpc_call_list *call_list, const char *reason,
  83. const char *file, int line) {
  84. gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "SECENDP unref %p : %s %d -> %d",
  85. ep, reason, ep->ref.count, ep->ref.count - 1);
  86. if (gpr_unref(&ep->ref)) {
  87. destroy(ep, call_list);
  88. }
  89. }
  90. static void secure_endpoint_ref(secure_endpoint *ep, const char *reason,
  91. const char *file, int line) {
  92. gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "SECENDP ref %p : %s %d -> %d",
  93. ep, reason, ep->ref.count, ep->ref.count + 1);
  94. gpr_ref(&ep->ref);
  95. }
  96. #else
  97. #define SECURE_ENDPOINT_UNREF(ep, reason, cl) secure_endpoint_unref((ep), (cl))
  98. #define SECURE_ENDPOINT_REF(ep, reason) secure_endpoint_ref((ep))
  99. static void secure_endpoint_unref(secure_endpoint *ep,
  100. grpc_call_list *call_list) {
  101. if (gpr_unref(&ep->ref)) {
  102. destroy(ep, call_list);
  103. }
  104. }
  105. static void secure_endpoint_ref(secure_endpoint *ep) { gpr_ref(&ep->ref); }
  106. #endif
  107. static void flush_read_staging_buffer(secure_endpoint *ep, gpr_uint8 **cur,
  108. gpr_uint8 **end) {
  109. gpr_slice_buffer_add(ep->read_buffer, ep->read_staging_buffer);
  110. ep->read_staging_buffer = gpr_slice_malloc(STAGING_BUFFER_SIZE);
  111. *cur = GPR_SLICE_START_PTR(ep->read_staging_buffer);
  112. *end = GPR_SLICE_END_PTR(ep->read_staging_buffer);
  113. }
  114. static void call_read_cb(secure_endpoint *ep, int success,
  115. grpc_call_list *call_list) {
  116. if (grpc_trace_secure_endpoint) {
  117. size_t i;
  118. for (i = 0; i < ep->read_buffer->count; i++) {
  119. char *data = gpr_dump_slice(ep->read_buffer->slices[i],
  120. GPR_DUMP_HEX | GPR_DUMP_ASCII);
  121. gpr_log(GPR_DEBUG, "READ %p: %s", ep, data);
  122. gpr_free(data);
  123. }
  124. }
  125. ep->read_buffer = NULL;
  126. grpc_call_list_add(call_list, ep->read_cb, success);
  127. SECURE_ENDPOINT_UNREF(ep, "read", call_list);
  128. }
  129. static void on_read(void *user_data, int success, grpc_call_list *call_list) {
  130. unsigned i;
  131. gpr_uint8 keep_looping = 0;
  132. tsi_result result = TSI_OK;
  133. secure_endpoint *ep = (secure_endpoint *)user_data;
  134. gpr_uint8 *cur = GPR_SLICE_START_PTR(ep->read_staging_buffer);
  135. gpr_uint8 *end = GPR_SLICE_END_PTR(ep->read_staging_buffer);
  136. if (!success) {
  137. gpr_slice_buffer_reset_and_unref(ep->read_buffer);
  138. call_read_cb(ep, 0, call_list);
  139. return;
  140. }
  141. /* TODO(yangg) check error, maybe bail out early */
  142. for (i = 0; i < ep->source_buffer.count; i++) {
  143. gpr_slice encrypted = ep->source_buffer.slices[i];
  144. gpr_uint8 *message_bytes = GPR_SLICE_START_PTR(encrypted);
  145. size_t message_size = GPR_SLICE_LENGTH(encrypted);
  146. while (message_size > 0 || keep_looping) {
  147. size_t unprotected_buffer_size_written = (size_t)(end - cur);
  148. size_t processed_message_size = message_size;
  149. gpr_mu_lock(&ep->protector_mu);
  150. result = tsi_frame_protector_unprotect(ep->protector, message_bytes,
  151. &processed_message_size, cur,
  152. &unprotected_buffer_size_written);
  153. gpr_mu_unlock(&ep->protector_mu);
  154. if (result != TSI_OK) {
  155. gpr_log(GPR_ERROR, "Decryption error: %s",
  156. tsi_result_to_string(result));
  157. break;
  158. }
  159. message_bytes += processed_message_size;
  160. message_size -= processed_message_size;
  161. cur += unprotected_buffer_size_written;
  162. if (cur == end) {
  163. flush_read_staging_buffer(ep, &cur, &end);
  164. /* Force to enter the loop again to extract buffered bytes in protector.
  165. The bytes could be buffered because of running out of staging_buffer.
  166. If this happens at the end of all slices, doing another unprotect
  167. avoids leaving data in the protector. */
  168. keep_looping = 1;
  169. } else if (unprotected_buffer_size_written > 0) {
  170. keep_looping = 1;
  171. } else {
  172. keep_looping = 0;
  173. }
  174. }
  175. if (result != TSI_OK) break;
  176. }
  177. if (cur != GPR_SLICE_START_PTR(ep->read_staging_buffer)) {
  178. gpr_slice_buffer_add(
  179. ep->read_buffer,
  180. gpr_slice_split_head(
  181. &ep->read_staging_buffer,
  182. (size_t)(cur - GPR_SLICE_START_PTR(ep->read_staging_buffer))));
  183. }
  184. /* TODO(yangg) experiment with moving this block after read_cb to see if it
  185. helps latency */
  186. gpr_slice_buffer_reset_and_unref(&ep->source_buffer);
  187. if (result != TSI_OK) {
  188. gpr_slice_buffer_reset_and_unref(ep->read_buffer);
  189. call_read_cb(ep, 0, call_list);
  190. return;
  191. }
  192. call_read_cb(ep, 1, call_list);
  193. }
  194. static void endpoint_read(grpc_endpoint *secure_ep, gpr_slice_buffer *slices,
  195. grpc_closure *cb, grpc_call_list *call_list) {
  196. secure_endpoint *ep = (secure_endpoint *)secure_ep;
  197. ep->read_cb = cb;
  198. ep->read_buffer = slices;
  199. gpr_slice_buffer_reset_and_unref(ep->read_buffer);
  200. SECURE_ENDPOINT_REF(ep, "read");
  201. if (ep->leftover_bytes.count) {
  202. gpr_slice_buffer_swap(&ep->leftover_bytes, &ep->source_buffer);
  203. GPR_ASSERT(ep->leftover_bytes.count == 0);
  204. on_read(ep, 1, call_list);
  205. return;
  206. }
  207. grpc_endpoint_read(ep->wrapped_ep, &ep->source_buffer, &ep->on_read,
  208. call_list);
  209. }
  210. static void flush_write_staging_buffer(secure_endpoint *ep, gpr_uint8 **cur,
  211. gpr_uint8 **end) {
  212. gpr_slice_buffer_add(&ep->output_buffer, ep->write_staging_buffer);
  213. ep->write_staging_buffer = gpr_slice_malloc(STAGING_BUFFER_SIZE);
  214. *cur = GPR_SLICE_START_PTR(ep->write_staging_buffer);
  215. *end = GPR_SLICE_END_PTR(ep->write_staging_buffer);
  216. }
  217. static void endpoint_write(grpc_endpoint *secure_ep, gpr_slice_buffer *slices,
  218. grpc_closure *cb, grpc_call_list *call_list) {
  219. unsigned i;
  220. tsi_result result = TSI_OK;
  221. secure_endpoint *ep = (secure_endpoint *)secure_ep;
  222. gpr_uint8 *cur = GPR_SLICE_START_PTR(ep->write_staging_buffer);
  223. gpr_uint8 *end = GPR_SLICE_END_PTR(ep->write_staging_buffer);
  224. gpr_slice_buffer_reset_and_unref(&ep->output_buffer);
  225. if (grpc_trace_secure_endpoint) {
  226. for (i = 0; i < slices->count; i++) {
  227. char *data =
  228. gpr_dump_slice(slices->slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII);
  229. gpr_log(GPR_DEBUG, "WRITE %p: %s", ep, data);
  230. gpr_free(data);
  231. }
  232. }
  233. for (i = 0; i < slices->count; i++) {
  234. gpr_slice plain = slices->slices[i];
  235. gpr_uint8 *message_bytes = GPR_SLICE_START_PTR(plain);
  236. size_t message_size = GPR_SLICE_LENGTH(plain);
  237. while (message_size > 0) {
  238. size_t protected_buffer_size_to_send = (size_t)(end - cur);
  239. size_t processed_message_size = message_size;
  240. gpr_mu_lock(&ep->protector_mu);
  241. result = tsi_frame_protector_protect(ep->protector, message_bytes,
  242. &processed_message_size, cur,
  243. &protected_buffer_size_to_send);
  244. gpr_mu_unlock(&ep->protector_mu);
  245. if (result != TSI_OK) {
  246. gpr_log(GPR_ERROR, "Encryption error: %s",
  247. tsi_result_to_string(result));
  248. break;
  249. }
  250. message_bytes += processed_message_size;
  251. message_size -= processed_message_size;
  252. cur += protected_buffer_size_to_send;
  253. if (cur == end) {
  254. flush_write_staging_buffer(ep, &cur, &end);
  255. }
  256. }
  257. if (result != TSI_OK) break;
  258. }
  259. if (result == TSI_OK) {
  260. size_t still_pending_size;
  261. do {
  262. size_t protected_buffer_size_to_send = (size_t)(end - cur);
  263. gpr_mu_lock(&ep->protector_mu);
  264. result = tsi_frame_protector_protect_flush(ep->protector, cur,
  265. &protected_buffer_size_to_send,
  266. &still_pending_size);
  267. gpr_mu_unlock(&ep->protector_mu);
  268. if (result != TSI_OK) break;
  269. cur += protected_buffer_size_to_send;
  270. if (cur == end) {
  271. flush_write_staging_buffer(ep, &cur, &end);
  272. }
  273. } while (still_pending_size > 0);
  274. if (cur != GPR_SLICE_START_PTR(ep->write_staging_buffer)) {
  275. gpr_slice_buffer_add(
  276. &ep->output_buffer,
  277. gpr_slice_split_head(
  278. &ep->write_staging_buffer,
  279. (size_t)(cur - GPR_SLICE_START_PTR(ep->write_staging_buffer))));
  280. }
  281. }
  282. if (result != TSI_OK) {
  283. /* TODO(yangg) do different things according to the error type? */
  284. gpr_slice_buffer_reset_and_unref(&ep->output_buffer);
  285. grpc_call_list_add(call_list, cb, 0);
  286. return;
  287. }
  288. grpc_endpoint_write(ep->wrapped_ep, &ep->output_buffer, cb, call_list);
  289. }
  290. static void endpoint_shutdown(grpc_endpoint *secure_ep,
  291. grpc_call_list *call_list) {
  292. secure_endpoint *ep = (secure_endpoint *)secure_ep;
  293. grpc_endpoint_shutdown(ep->wrapped_ep, call_list);
  294. }
  295. static void endpoint_destroy(grpc_endpoint *secure_ep,
  296. grpc_call_list *call_list) {
  297. secure_endpoint *ep = (secure_endpoint *)secure_ep;
  298. SECURE_ENDPOINT_UNREF(ep, "destroy", call_list);
  299. }
  300. static void endpoint_add_to_pollset(grpc_endpoint *secure_ep,
  301. grpc_pollset *pollset,
  302. grpc_call_list *call_list) {
  303. secure_endpoint *ep = (secure_endpoint *)secure_ep;
  304. grpc_endpoint_add_to_pollset(ep->wrapped_ep, pollset, call_list);
  305. }
  306. static void endpoint_add_to_pollset_set(grpc_endpoint *secure_ep,
  307. grpc_pollset_set *pollset_set,
  308. grpc_call_list *call_list) {
  309. secure_endpoint *ep = (secure_endpoint *)secure_ep;
  310. grpc_endpoint_add_to_pollset_set(ep->wrapped_ep, pollset_set, call_list);
  311. }
  312. static char *endpoint_get_peer(grpc_endpoint *secure_ep) {
  313. secure_endpoint *ep = (secure_endpoint *)secure_ep;
  314. return grpc_endpoint_get_peer(ep->wrapped_ep);
  315. }
  316. static const grpc_endpoint_vtable vtable = {
  317. endpoint_read, endpoint_write,
  318. endpoint_add_to_pollset, endpoint_add_to_pollset_set,
  319. endpoint_shutdown, endpoint_destroy,
  320. endpoint_get_peer};
  321. grpc_endpoint *grpc_secure_endpoint_create(
  322. struct tsi_frame_protector *protector, grpc_endpoint *transport,
  323. gpr_slice *leftover_slices, size_t leftover_nslices) {
  324. size_t i;
  325. secure_endpoint *ep = (secure_endpoint *)gpr_malloc(sizeof(secure_endpoint));
  326. ep->base.vtable = &vtable;
  327. ep->wrapped_ep = transport;
  328. ep->protector = protector;
  329. gpr_slice_buffer_init(&ep->leftover_bytes);
  330. for (i = 0; i < leftover_nslices; i++) {
  331. gpr_slice_buffer_add(&ep->leftover_bytes,
  332. gpr_slice_ref(leftover_slices[i]));
  333. }
  334. ep->write_staging_buffer = gpr_slice_malloc(STAGING_BUFFER_SIZE);
  335. ep->read_staging_buffer = gpr_slice_malloc(STAGING_BUFFER_SIZE);
  336. gpr_slice_buffer_init(&ep->output_buffer);
  337. gpr_slice_buffer_init(&ep->source_buffer);
  338. ep->read_buffer = NULL;
  339. grpc_closure_init(&ep->on_read, on_read, ep);
  340. gpr_mu_init(&ep->protector_mu);
  341. gpr_ref_init(&ep->ref, 1);
  342. return &ep->base;
  343. }