@@ -84,11 +84,11 @@ struct s2n_connection *s2n_connection_new(s2n_mode mode)
8484 conn -> mode = mode ;
8585
8686 /* Allocate the fixed-size stuffers */
87- blob = (struct s2n_blob ){ 0 };
87+ blob = (struct s2n_blob ) { 0 };
8888 PTR_GUARD_POSIX (s2n_blob_init (& blob , conn -> alert_in_data , S2N_ALERT_LENGTH ));
8989 PTR_GUARD_POSIX (s2n_stuffer_init (& conn -> alert_in , & blob ));
9090
91- blob = (struct s2n_blob ){ 0 };
91+ blob = (struct s2n_blob ) { 0 };
9292 PTR_GUARD_POSIX (s2n_blob_init (& blob , conn -> ticket_ext_data , S2N_TLS12_TICKET_SIZE_IN_BYTES ));
9393 PTR_GUARD_POSIX (s2n_stuffer_init (& conn -> client_ticket_to_decrypt , & blob ));
9494
@@ -99,7 +99,7 @@ struct s2n_connection *s2n_connection_new(s2n_mode mode)
9999 /* Initialize the growable stuffers. Zero length at first, but the resize
100100 * in _wipe will fix that
101101 */
102- blob = (struct s2n_blob ){ 0 };
102+ blob = (struct s2n_blob ) { 0 };
103103 PTR_GUARD_POSIX (s2n_blob_init (& blob , conn -> header_in_data , S2N_TLS_RECORD_HEADER_LENGTH ));
104104 PTR_GUARD_POSIX (s2n_stuffer_init (& conn -> header_in , & blob ));
105105 PTR_GUARD_POSIX (s2n_stuffer_growable_alloc (& conn -> out , 0 ));
@@ -309,12 +309,24 @@ int s2n_connection_set_config(struct s2n_connection *conn, struct s2n_config *co
309309 POSIX_BAIL (S2N_ERR_TOO_MANY_CERTIFICATES );
310310 }
311311
312- s2n_x509_validator_wipe (& conn -> x509_validator );
312+ /* Build the new validator into a local so that the connection's existing
313+ * validator is not destroyed until the new one is fully initialized.
314+ * Without this staging, a failure mid-init (e.g. X509_STORE_CTX_new
315+ * returning NULL under OOM) would leave conn->x509_validator wiped
316+ * while conn->config still references the old config.
317+ */
318+ struct s2n_x509_validator new_validator = { 0 };
313319
314320 if (config -> disable_x509_validation ) {
315- POSIX_GUARD (s2n_x509_validator_init_no_x509_validation (& conn -> x509_validator ));
321+ POSIX_GUARD (s2n_x509_validator_init_no_x509_validation (& new_validator ));
316322 } else {
317- POSIX_GUARD (s2n_x509_validator_init (& conn -> x509_validator , & config -> trust_store , config -> check_ocsp ));
323+ int ret = s2n_x509_validator_init (& new_validator , & config -> trust_store , config -> check_ocsp );
324+ if (ret != S2N_SUCCESS ) {
325+ /* init may have partially populated new_validator before failing */
326+ s2n_x509_validator_wipe (& new_validator );
327+ POSIX_GUARD (ret );
328+ }
329+
318330 if (!conn -> verify_host_fn_overridden ) {
319331 if (config -> verify_host_fn != NULL ) {
320332 conn -> verify_host_fn = config -> verify_host_fn ;
@@ -326,9 +338,18 @@ int s2n_connection_set_config(struct s2n_connection *conn, struct s2n_config *co
326338 }
327339
328340 if (config -> max_verify_cert_chain_depth_set ) {
329- POSIX_GUARD (s2n_x509_validator_set_max_chain_depth (& conn -> x509_validator , config -> max_verify_cert_chain_depth ));
341+ ret = s2n_x509_validator_set_max_chain_depth (& new_validator , config -> max_verify_cert_chain_depth );
342+ if (ret != S2N_SUCCESS ) {
343+ s2n_x509_validator_wipe (& new_validator );
344+ POSIX_GUARD (ret );
345+ }
330346 }
331347 }
348+
349+ /* New validator is fully initialized. Swap it in. */
350+ s2n_x509_validator_wipe (& conn -> x509_validator );
351+ conn -> x509_validator = new_validator ;
352+
332353 conn -> tickets_to_send = config -> initial_tickets_to_send ;
333354
334355 if (conn -> psk_params .psk_list .len == 0 && !conn -> psk_mode_overridden ) {
@@ -369,7 +390,7 @@ int s2n_connection_set_config(struct s2n_connection *conn, struct s2n_config *co
369390 * However, the s2n_config_set_verification_ca_location behavior predates client authentication
370391 * support for OCSP stapling, so could only affect whether clients requested OCSP stapling. We
371392 * therefore only have to maintain the legacy behavior for clients, not servers.
372- *
393+ *
373394 * Note: The Rust bindings do not maintain the legacy behavior.
374395 */
375396 conn -> request_ocsp_status = config -> ocsp_status_requested_by_user ;
@@ -1020,7 +1041,7 @@ int s2n_connection_get_key_exchange_group(struct s2n_connection *conn, const cha
10201041 POSIX_ENSURE_REF (conn );
10211042 POSIX_ENSURE_REF (group_name );
10221043
1023- /* s2n_connection_get_curve returns only the ECDH curve portion of a named group, even if
1044+ /* s2n_connection_get_curve returns only the ECDH curve portion of a named group, even if
10241045 the negotiated group was a hybrid PQ key exchange also containing a KEM. Therefore,
10251046 we use the result of s2n_connection_get_kem_group_name if the connection supports PQ. */
10261047 if (s2n_tls13_pq_hybrid_supported (conn )) {
@@ -1256,11 +1277,11 @@ uint64_t s2n_connection_get_delay(struct s2n_connection *conn)
12561277
12571278/* s2n-tls has a random delay that will trigger for sensitive errors. This is a mitigation
12581279 * for possible timing sidechannels.
1259- *
1280+ *
12601281 * The historical sidechannel that inspired s2n-tls blinding was the Lucky 13 attack, which takes
12611282 * advantage of potential timing differences when removing padding from a record encrypted in CBC mode.
1262- * The attack is only theoretical in TLS; the attack criteria is unlikely to ever occur
1263- * (See: Fardan, N. J. A., & Paterson, K. G. (2013, May 1). Lucky Thirteen: Breaking the TLS and
1283+ * The attack is only theoretical in TLS; the attack criteria is unlikely to ever occur
1284+ * (See: Fardan, N. J. A., & Paterson, K. G. (2013, May 1). Lucky Thirteen: Breaking the TLS and
12641285 * DTLS Record Protocols.) However, we still include blinding to provide a defense in depth mitigation.
12651286 */
12661287S2N_RESULT s2n_connection_calculate_blinding (struct s2n_connection * conn , int64_t * min , int64_t * max )
0 commit comments