@@ -57,6 +57,16 @@ static int s2n_signature_scheme_valid_to_accept(struct s2n_connection *conn, con
5757 return 0 ;
5858}
5959
60+ static int s2n_is_signature_scheme_usable (struct s2n_connection * conn , const struct s2n_signature_scheme * candidate ) {
61+ notnull_check (conn );
62+ notnull_check (candidate );
63+
64+ GUARD (s2n_signature_scheme_valid_to_accept (conn , candidate ));
65+ GUARD (s2n_is_sig_scheme_valid_for_auth (conn , candidate ));
66+
67+ return S2N_SUCCESS ;
68+ }
69+
6070static int s2n_choose_sig_scheme (struct s2n_connection * conn , struct s2n_sig_scheme_list * peer_wire_prefs ,
6171 struct s2n_signature_scheme * chosen_scheme_out )
6272{
@@ -68,18 +78,14 @@ static int s2n_choose_sig_scheme(struct s2n_connection *conn, struct s2n_sig_sch
6878 struct s2n_cipher_suite * cipher_suite = conn -> secure .cipher_suite ;
6979 notnull_check (cipher_suite );
7080
71- for (int i = 0 ; i < signature_preferences -> count ; i ++ ) {
81+ for (size_t i = 0 ; i < signature_preferences -> count ; i ++ ) {
7282 const struct s2n_signature_scheme * candidate = signature_preferences -> signature_schemes [i ];
7383
74- if (s2n_signature_scheme_valid_to_accept (conn , candidate ) != S2N_SUCCESS ) {
75- continue ;
76- }
77-
78- if (s2n_is_sig_scheme_valid_for_auth (conn , candidate ) != S2N_SUCCESS ) {
84+ if (s2n_is_signature_scheme_usable (conn , candidate ) != S2N_SUCCESS ) {
7985 continue ;
8086 }
8187
82- for (int j = 0 ; j < peer_wire_prefs -> len ; j ++ ) {
88+ for (size_t j = 0 ; j < peer_wire_prefs -> len ; j ++ ) {
8389 uint16_t their_iana_val = peer_wire_prefs -> iana_list [j ];
8490
8591 if (candidate -> iana_value == their_iana_val ) {
@@ -89,6 +95,32 @@ static int s2n_choose_sig_scheme(struct s2n_connection *conn, struct s2n_sig_sch
8995 }
9096 }
9197
98+ /* do not error even if there's no match */
99+ return S2N_SUCCESS ;
100+ }
101+
102+ /* similar to s2n_choose_sig_scheme() without matching client's preference */
103+ static int s2n_tls13_default_sig_scheme (struct s2n_connection * conn , struct s2n_signature_scheme * chosen_scheme_out )
104+ {
105+ notnull_check (conn );
106+ const struct s2n_signature_preferences * signature_preferences = NULL ;
107+ GUARD (s2n_connection_get_signature_preferences (conn , & signature_preferences ));
108+ notnull_check (signature_preferences );
109+
110+ struct s2n_cipher_suite * cipher_suite = conn -> secure .cipher_suite ;
111+ notnull_check (cipher_suite );
112+
113+ for (size_t i = 0 ; i < signature_preferences -> count ; i ++ ) {
114+ const struct s2n_signature_scheme * candidate = signature_preferences -> signature_schemes [i ];
115+
116+ if (s2n_is_signature_scheme_usable (conn , candidate ) != S2N_SUCCESS ) {
117+ continue ;
118+ }
119+
120+ * chosen_scheme_out = * candidate ;
121+ return S2N_SUCCESS ;
122+ }
123+
92124 S2N_ERROR (S2N_ERR_INVALID_SIGNATURE_SCHEME );
93125}
94126
@@ -102,7 +134,7 @@ int s2n_get_and_validate_negotiated_signature_scheme(struct s2n_connection *conn
102134 GUARD (s2n_connection_get_signature_preferences (conn , & signature_preferences ));
103135 notnull_check (signature_preferences );
104136
105- for (int i = 0 ; i < signature_preferences -> count ; i ++ ) {
137+ for (size_t i = 0 ; i < signature_preferences -> count ; i ++ ) {
106138 const struct s2n_signature_scheme * candidate = signature_preferences -> signature_schemes [i ];
107139
108140 if (0 != s2n_signature_scheme_valid_to_accept (conn , candidate )) {
@@ -167,18 +199,17 @@ int s2n_choose_sig_scheme_from_peer_preference_list(struct s2n_connection *conn,
167199
168200 struct s2n_signature_scheme chosen_scheme ;
169201
170- GUARD (s2n_choose_default_sig_scheme (conn , & chosen_scheme ));
202+ if (conn -> actual_protocol_version < S2N_TLS13 ) {
203+ GUARD (s2n_choose_default_sig_scheme (conn , & chosen_scheme ));
204+ } else {
205+ /* Pick a default signature algorithm in TLS 1.3 https://tools.ietf.org/html/rfc8446#section-4.4.2.2 */
206+ GUARD (s2n_tls13_default_sig_scheme (conn , & chosen_scheme ));
207+ }
171208
172209 /* SignatureScheme preference list was first added in TLS 1.2. It will be empty in older TLS versions. */
173210 if (peer_wire_prefs != NULL && peer_wire_prefs -> len > 0 ) {
174- int result = s2n_choose_sig_scheme (conn , peer_wire_prefs , & chosen_scheme );
175-
176- /* We require an exact match in TLS 1.3, but all previous versions can fall back to the default.
177- * The pre-TLS1.3 behavior is an intentional choice to maximize support. */
178- S2N_ERROR_IF (result != S2N_SUCCESS && conn -> actual_protocol_version == S2N_TLS13 ,
179- S2N_ERR_INVALID_SIGNATURE_SCHEME );
180- } else {
181- S2N_ERROR_IF (conn -> actual_protocol_version == S2N_TLS13 , S2N_ERR_EMPTY_SIGNATURE_SCHEME );
211+ /* Use a best effort approach to selecting a signature scheme matching client's preferences */
212+ GUARD (s2n_choose_sig_scheme (conn , peer_wire_prefs , & chosen_scheme ));
182213 }
183214
184215 * sig_scheme_out = chosen_scheme ;
@@ -194,7 +225,7 @@ int s2n_send_supported_sig_scheme_list(struct s2n_connection *conn, struct s2n_s
194225
195226 GUARD (s2n_stuffer_write_uint16 (out , s2n_supported_sig_scheme_list_size (conn )));
196227
197- for (int i = 0 ; i < signature_preferences -> count ; i ++ ) {
228+ for (size_t i = 0 ; i < signature_preferences -> count ; i ++ ) {
198229 const struct s2n_signature_scheme * const scheme = signature_preferences -> signature_schemes [i ];
199230 if (0 == s2n_signature_scheme_valid_to_offer (conn , scheme )) {
200231 GUARD (s2n_stuffer_write_uint16 (out , scheme -> iana_value ));
@@ -216,7 +247,7 @@ int s2n_supported_sig_schemes_count(struct s2n_connection *conn)
216247 notnull_check (signature_preferences );
217248
218249 uint8_t count = 0 ;
219- for (int i = 0 ; i < signature_preferences -> count ; i ++ ) {
250+ for (size_t i = 0 ; i < signature_preferences -> count ; i ++ ) {
220251 if (0 == s2n_signature_scheme_valid_to_offer (conn , signature_preferences -> signature_schemes [i ])) {
221252 count ++ ;
222253 }
@@ -247,7 +278,7 @@ int s2n_recv_supported_sig_scheme_list(struct s2n_stuffer *in, struct s2n_sig_sc
247278
248279 sig_hash_algs -> len = 0 ;
249280
250- for (int i = 0 ; i < pairs_available ; i ++ ) {
281+ for (size_t i = 0 ; i < pairs_available ; i ++ ) {
251282 uint16_t sig_scheme = 0 ;
252283 GUARD (s2n_stuffer_read_uint16 (in , & sig_scheme ));
253284
0 commit comments