s2n_post_handshake.c 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. /*
  2. * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License").
  5. * You may not use this file except in compliance with the License.
  6. * A copy of the License is located at
  7. *
  8. * http://aws.amazon.com/apache2.0
  9. *
  10. * or in the "license" file accompanying this file. This file is distributed
  11. * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
  12. * express or implied. See the License for the specific language governing
  13. * permissions and limitations under the License.
  14. */
  15. #include <sys/param.h>
  16. #include "error/s2n_errno.h"
  17. #include "tls/s2n_connection.h"
  18. #include "tls/s2n_key_update.h"
  19. #include "tls/s2n_tls.h"
  20. #include "utils/s2n_safety.h"
  21. S2N_RESULT s2n_post_handshake_process(struct s2n_connection *conn, struct s2n_stuffer *in, uint8_t message_type)
  22. {
  23. RESULT_ENSURE_REF(conn);
  24. switch (message_type) {
  25. case TLS_KEY_UPDATE:
  26. RESULT_GUARD_POSIX(s2n_key_update_recv(conn, in));
  27. break;
  28. case TLS_SERVER_NEW_SESSION_TICKET:
  29. RESULT_GUARD(s2n_tls13_server_nst_recv(conn, in));
  30. break;
  31. case TLS_HELLO_REQUEST:
  32. RESULT_GUARD(s2n_client_hello_request_recv(conn));
  33. break;
  34. case TLS_CERT_REQ:
  35. /*
  36. * s2n-tls does not support post-handshake authentication.
  37. *
  38. *= https://tools.ietf.org/rfc/rfc8446#section-4.6.2
  39. *# A client that receives a CertificateRequest message without having
  40. *# sent the "post_handshake_auth" extension MUST send an
  41. *# "unexpected_message" fatal alert.
  42. */
  43. RESULT_BAIL(S2N_ERR_BAD_MESSAGE);
  44. default:
  45. /* All other messages are unexpected */
  46. RESULT_BAIL(S2N_ERR_BAD_MESSAGE);
  47. }
  48. return S2N_RESULT_OK;
  49. }
  50. /*
  51. * Read a handshake message from conn->in.
  52. *
  53. * Handshake messages can be fragmented, meaning that a single message
  54. * may be split between multiple records. conn->in only holds a single
  55. * record at a time, so we may need to call this method multiple
  56. * times to construct the complete message. We store the partial message
  57. * in conn->post_handshake.in between calls.
  58. */
  59. S2N_RESULT s2n_post_handshake_message_recv(struct s2n_connection *conn)
  60. {
  61. RESULT_ENSURE_REF(conn);
  62. struct s2n_stuffer *in = &conn->in;
  63. struct s2n_stuffer *message = &conn->post_handshake.in;
  64. uint8_t message_type = 0;
  65. uint32_t message_len = 0;
  66. /* We always start reading from the beginning of the message.
  67. * Reset the read progress, but keep the write progress since
  68. * there may already be a partial message stored in `message`.
  69. */
  70. RESULT_GUARD_POSIX(s2n_stuffer_reread(message));
  71. /* At minimum, the message stuffer needs to have enough space to read the header.
  72. * For small messages like KeyUpdate and HelloRequest, this is all the space we will need.
  73. */
  74. if (s2n_stuffer_is_freed(message)) {
  75. struct s2n_blob b = { 0 };
  76. RESULT_GUARD_POSIX(s2n_blob_init(&b, conn->post_handshake.header_in,
  77. sizeof(conn->post_handshake.header_in)));
  78. RESULT_GUARD_POSIX(s2n_stuffer_init(message, &b));
  79. }
  80. /* Try to copy the header into the message stuffer.
  81. * The message stuffer may already contain some or all of the header if
  82. * we have read fragments of this message from previous records.
  83. */
  84. if (s2n_stuffer_data_available(message) < TLS_HANDSHAKE_HEADER_LENGTH) {
  85. uint32_t remaining = TLS_HANDSHAKE_HEADER_LENGTH - s2n_stuffer_data_available(message);
  86. uint32_t to_read = MIN(remaining, s2n_stuffer_data_available(in));
  87. RESULT_GUARD_POSIX(s2n_stuffer_copy(in, message, to_read));
  88. }
  89. RESULT_ENSURE(s2n_stuffer_data_available(message) >= TLS_HANDSHAKE_HEADER_LENGTH, S2N_ERR_IO_BLOCKED);
  90. /* Parse the header */
  91. RESULT_GUARD(s2n_handshake_parse_header(message, &message_type, &message_len));
  92. RESULT_ENSURE(message_len == 0 || s2n_stuffer_data_available(in), S2N_ERR_IO_BLOCKED);
  93. RESULT_ENSURE(message_len <= S2N_MAXIMUM_HANDSHAKE_MESSAGE_LENGTH, S2N_ERR_BAD_MESSAGE);
  94. /* If the message body is not fragmented, just process it directly from conn->in.
  95. * This will be the most common case, and does not require us to allocate any new memory.
  96. */
  97. if (s2n_stuffer_data_available(message) == 0 && s2n_stuffer_data_available(in) >= message_len) {
  98. struct s2n_stuffer full_message = { 0 };
  99. struct s2n_blob full_message_blob = { 0 };
  100. RESULT_GUARD_POSIX(s2n_blob_init(&full_message_blob, s2n_stuffer_raw_read(in, message_len), message_len));
  101. RESULT_GUARD_POSIX(s2n_stuffer_init(&full_message, &full_message_blob));
  102. RESULT_GUARD_POSIX(s2n_stuffer_skip_write(&full_message, message_len));
  103. RESULT_GUARD(s2n_post_handshake_process(conn, &full_message, message_type));
  104. return S2N_RESULT_OK;
  105. }
  106. /* If the message body is fragmented, then the current fragment will be wiped from conn->in
  107. * in order to read the next record. So the message stuffer needs enough space to store
  108. * the full message as we reconstruct it from multiple records.
  109. * For large messages like NewSessionTicket, this will require allocating new memory.
  110. */
  111. if (s2n_stuffer_space_remaining(message) < message_len) {
  112. /* We want to avoid servers allocating memory in response to post-handshake messages
  113. * to avoid a potential DDOS / resource exhaustion attack.
  114. *
  115. * Currently, s2n-tls servers only support the KeyUpdate message,
  116. * which should never require additional memory to parse.
  117. */
  118. RESULT_ENSURE(conn->mode == S2N_CLIENT, S2N_ERR_BAD_MESSAGE);
  119. uint32_t total_size = message_len + TLS_HANDSHAKE_HEADER_LENGTH;
  120. if (message->alloced) {
  121. RESULT_GUARD_POSIX(s2n_stuffer_resize(message, total_size));
  122. } else {
  123. /* Manually convert our static stuffer to a growable stuffer */
  124. RESULT_GUARD_POSIX(s2n_stuffer_growable_alloc(message, total_size));
  125. RESULT_GUARD_POSIX(s2n_stuffer_write_bytes(message, conn->post_handshake.header_in, TLS_HANDSHAKE_HEADER_LENGTH));
  126. RESULT_GUARD_POSIX(s2n_stuffer_skip_read(message, TLS_HANDSHAKE_HEADER_LENGTH));
  127. }
  128. }
  129. /* Try to copy the message body into the message stuffer.
  130. * The message stuffer may already contain some of the message body if
  131. * we have already read fragments from previous records.
  132. */
  133. if (s2n_stuffer_data_available(message) < message_len) {
  134. uint32_t remaining = message_len - s2n_stuffer_data_available(message);
  135. uint32_t to_read = MIN(remaining, s2n_stuffer_data_available(in));
  136. RESULT_GUARD_POSIX(s2n_stuffer_copy(in, message, to_read));
  137. }
  138. RESULT_ENSURE(s2n_stuffer_data_available(message) == message_len, S2N_ERR_IO_BLOCKED);
  139. /* Now that the full message body is available, process it. */
  140. RESULT_GUARD(s2n_post_handshake_process(conn, message, message_type));
  141. return S2N_RESULT_OK;
  142. }
  143. S2N_RESULT s2n_post_handshake_recv(struct s2n_connection *conn)
  144. {
  145. RESULT_ENSURE_REF(conn);
  146. while (s2n_stuffer_data_available(&conn->in)) {
  147. RESULT_GUARD(s2n_post_handshake_message_recv(conn));
  148. RESULT_GUARD_POSIX(s2n_stuffer_wipe(&conn->post_handshake.in));
  149. }
  150. return S2N_RESULT_OK;
  151. }
  152. S2N_RESULT s2n_post_handshake_write_records(struct s2n_connection *conn, s2n_blocked_status *blocked)
  153. {
  154. struct s2n_stuffer *message = &conn->handshake.io;
  155. /* Flush any existing records before we write a new handshake record.
  156. * We do not support buffering multiple handshake records.
  157. */
  158. if (s2n_stuffer_data_available(message)) {
  159. RESULT_GUARD_POSIX(s2n_flush(conn, blocked));
  160. }
  161. RESULT_GUARD(s2n_handshake_message_send(conn, TLS_HANDSHAKE, blocked));
  162. RESULT_GUARD_POSIX(s2n_stuffer_wipe(message));
  163. return S2N_RESULT_OK;
  164. }
  165. int s2n_post_handshake_send(struct s2n_connection *conn, s2n_blocked_status *blocked)
  166. {
  167. POSIX_ENSURE_REF(conn);
  168. /* Currently, we only support TLS1.3 post-handshake messages. */
  169. if (conn->actual_protocol_version < S2N_TLS13) {
  170. return S2N_SUCCESS;
  171. }
  172. POSIX_GUARD_RESULT(s2n_post_handshake_write_records(conn, blocked));
  173. POSIX_GUARD(s2n_key_update_send(conn, blocked));
  174. POSIX_GUARD_RESULT(s2n_tls13_server_nst_send(conn, blocked));
  175. POSIX_GUARD(s2n_stuffer_resize(&conn->handshake.io, 0));
  176. return S2N_SUCCESS;
  177. }