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 <sys/param.h>
17 #include <stdint.h>
18 
19 #include "tls/extensions/s2n_client_supported_groups.h"
20 #include "tls/extensions/s2n_ec_point_format.h"
21 #include "tls/s2n_tls.h"
22 
23 #include "utils/s2n_safety.h"
24 
25 static int s2n_ec_point_format_send(struct s2n_connection *conn, struct s2n_stuffer *out);
26 static int s2n_ec_point_format_recv(struct s2n_connection *conn, struct s2n_stuffer *extension);
27 
28 const s2n_extension_type s2n_client_ec_point_format_extension = {
29     .iana_value = TLS_EXTENSION_EC_POINT_FORMATS,
30     .is_response = false,
31     .send = s2n_ec_point_format_send,
32     .recv = s2n_ec_point_format_recv,
33     .should_send = s2n_extension_should_send_if_ecc_enabled,
34     .if_missing = s2n_extension_noop_if_missing,
35 };
36 
37 static bool s2n_server_ec_point_format_should_send(struct s2n_connection *conn);
38 
39 const s2n_extension_type s2n_server_ec_point_format_extension = {
40     .iana_value = TLS_EXTENSION_EC_POINT_FORMATS,
41     .is_response = true,
42     .send = s2n_ec_point_format_send,
43     .recv = s2n_extension_recv_noop,
44     .should_send = s2n_server_ec_point_format_should_send,
45     .if_missing = s2n_extension_noop_if_missing,
46 };
47 
s2n_server_ec_point_format_should_send(struct s2n_connection * conn)48 static bool s2n_server_ec_point_format_should_send(struct s2n_connection *conn)
49 {
50     return conn && conn->secure.cipher_suite
51             && s2n_kex_includes(conn->secure.cipher_suite->key_exchange_alg, &s2n_ecdhe);
52 }
53 
s2n_ec_point_format_send(struct s2n_connection * conn,struct s2n_stuffer * out)54 static int s2n_ec_point_format_send(struct s2n_connection *conn, struct s2n_stuffer *out)
55 {
56     /* Point format list len. We only support one. */
57     POSIX_GUARD(s2n_stuffer_write_uint8(out, 1));
58 
59     /* Only allow uncompressed format */
60     POSIX_GUARD(s2n_stuffer_write_uint8(out, TLS_EC_POINT_FORMAT_UNCOMPRESSED));
61 
62     return S2N_SUCCESS;
63 }
64 
s2n_ec_point_format_recv(struct s2n_connection * conn,struct s2n_stuffer * extension)65 static int s2n_ec_point_format_recv(struct s2n_connection *conn, struct s2n_stuffer *extension)
66 {
67     /**
68      * Only uncompressed points are supported by the server and the client must include it in
69      * the extension. Just skip the extension.
70      */
71     conn->ec_point_formats = 1;
72     return S2N_SUCCESS;
73 }
74 
75 /* Old-style extension functions -- remove after extensions refactor is complete */
76 
s2n_server_ecc_point_format_extension_size(struct s2n_connection * conn)77 int s2n_server_ecc_point_format_extension_size(struct s2n_connection *conn)
78 {
79     if (s2n_server_ec_point_format_extension.should_send(conn) && s2n_server_can_send_ec_point_formats(conn)) {
80         return sizeof(uint16_t)     /* extension type */
81                 + sizeof(uint16_t)  /* extension size */
82                 + sizeof(uint8_t)   /* point list size */
83                 + sizeof(uint8_t);  /* point */
84     }
85     return 0;
86 }
87 
s2n_recv_client_ec_point_formats(struct s2n_connection * conn,struct s2n_stuffer * extension)88 int s2n_recv_client_ec_point_formats(struct s2n_connection *conn, struct s2n_stuffer *extension)
89 {
90     return s2n_extension_recv(&s2n_client_ec_point_format_extension, conn, extension);
91 }
92