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
16 #include "tls/extensions/s2n_cookie.h"
17 #include "tls/s2n_tls.h"
18
19 #define S2N_SIZE_OF_EXTENSION_TYPE 2
20 #define S2N_SIZE_OF_EXTENSION_DATA_SIZE 2
21 #define S2N_SIZE_OF_COOKIE_DATA_SIZE 2
22
23 const s2n_extension_type s2n_client_cookie_extension = {
24 .iana_value = TLS_EXTENSION_COOKIE,
25 .minimum_version = S2N_TLS13,
26 .is_response = true,
27 .send = s2n_extension_send_noop,
28 .recv = s2n_extension_recv_noop,
29 .should_send = s2n_extension_never_send,
30 .if_missing = s2n_extension_noop_if_missing,
31 };
32
33 static bool s2n_cookie_should_send(struct s2n_connection *conn);
34 static int s2n_cookie_send(struct s2n_connection *conn, struct s2n_stuffer *out);
35 static int s2n_cookie_recv(struct s2n_connection *conn, struct s2n_stuffer *extension);
36
37 const s2n_extension_type s2n_server_cookie_extension = {
38 .iana_value = TLS_EXTENSION_COOKIE,
39 .minimum_version = S2N_TLS13,
40 .is_response = false,
41 .send = s2n_cookie_send,
42 .recv = s2n_cookie_recv,
43 .should_send = s2n_cookie_should_send,
44 .if_missing = s2n_extension_noop_if_missing,
45 };
46
s2n_cookie_should_send(struct s2n_connection * conn)47 static bool s2n_cookie_should_send(struct s2n_connection *conn)
48 {
49 return conn && s2n_stuffer_data_available(&conn->cookie_stuffer) > 0;
50 }
51
s2n_cookie_send(struct s2n_connection * conn,struct s2n_stuffer * out)52 static int s2n_cookie_send(struct s2n_connection *conn, struct s2n_stuffer *out)
53 {
54 POSIX_ENSURE_REF(conn);
55 uint16_t cookie_size = s2n_stuffer_data_available(&conn->cookie_stuffer);
56 POSIX_GUARD(s2n_stuffer_write_uint16(out, cookie_size));
57 POSIX_GUARD(s2n_stuffer_copy(&conn->cookie_stuffer, out, cookie_size));
58 return S2N_SUCCESS;
59 }
60
s2n_cookie_recv(struct s2n_connection * conn,struct s2n_stuffer * extension)61 static int s2n_cookie_recv(struct s2n_connection *conn, struct s2n_stuffer *extension)
62 {
63 POSIX_ENSURE_REF(conn);
64
65 uint16_t cookie_len;
66 POSIX_GUARD(s2n_stuffer_read_uint16(extension, &cookie_len));
67 POSIX_ENSURE(s2n_stuffer_data_available(extension) == cookie_len, S2N_ERR_BAD_MESSAGE);
68
69 POSIX_GUARD(s2n_stuffer_wipe(&conn->cookie_stuffer));
70 POSIX_GUARD(s2n_stuffer_resize(&conn->cookie_stuffer, cookie_len));
71 POSIX_GUARD(s2n_stuffer_copy(extension, &conn->cookie_stuffer, cookie_len));
72 return S2N_SUCCESS;
73 }
74
75 /* Old-style extension functions -- remove after extensions refactor is complete */
76
s2n_extensions_cookie_size(struct s2n_connection * conn)77 int s2n_extensions_cookie_size(struct s2n_connection *conn)
78 {
79 POSIX_GUARD(s2n_stuffer_reread(&conn->cookie_stuffer));
80
81 if (s2n_stuffer_data_available(&conn->cookie_stuffer) == 0) {
82 return 0;
83 }
84
85 const int cookie_extension_size = S2N_SIZE_OF_EXTENSION_TYPE
86 + S2N_SIZE_OF_EXTENSION_DATA_SIZE
87 + S2N_SIZE_OF_COOKIE_DATA_SIZE
88 + s2n_stuffer_data_available(&conn->cookie_stuffer);
89
90 return cookie_extension_size;
91 }
92
s2n_extensions_cookie_recv(struct s2n_connection * conn,struct s2n_stuffer * extension)93 int s2n_extensions_cookie_recv(struct s2n_connection *conn, struct s2n_stuffer *extension)
94 {
95 return s2n_extension_send(&s2n_server_cookie_extension, conn, extension);
96 }
97
s2n_extensions_cookie_send(struct s2n_connection * conn,struct s2n_stuffer * out)98 int s2n_extensions_cookie_send(struct s2n_connection *conn, struct s2n_stuffer *out)
99 {
100 return s2n_extension_send(&s2n_server_cookie_extension, conn, out);
101 }
102