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