@@ -23,13 +23,16 @@ struct s2n_cert_validation_data {
23
23
unsigned return_success : 1 ;
24
24
25
25
int invoked_count ;
26
+ struct s2n_cert_validation_info * info ;
26
27
};
27
28
28
29
static int s2n_test_cert_validation_callback (struct s2n_connection * conn , struct s2n_cert_validation_info * info , void * ctx )
29
30
{
30
31
struct s2n_cert_validation_data * data = (struct s2n_cert_validation_data * ) ctx ;
31
32
32
33
data -> invoked_count += 1 ;
34
+ /* Pass the `s2n_cert_validation_info` struct to application-defined `ctx` */
35
+ data -> info = info ;
33
36
34
37
int ret = S2N_FAILURE ;
35
38
if (data -> return_success ) {
@@ -187,16 +190,6 @@ int main(int argc, char *argv[])
187
190
.data = { .call_accept_or_reject = true, .accept = false, .return_success = false },
188
191
.expected_error = S2N_ERR_CANCELLED
189
192
},
190
- {
191
- .data = { .call_accept_or_reject = false, .return_success = false },
192
- .expected_error = S2N_ERR_CANCELLED
193
- },
194
-
195
- /* Error if accept or reject wasn't called from the callback */
196
- {
197
- .data = { .call_accept_or_reject = false, .return_success = true },
198
- .expected_error = S2N_ERR_INVALID_STATE
199
- },
200
193
};
201
194
/* clang-format on */
202
195
@@ -444,6 +437,139 @@ int main(int argc, char *argv[])
444
437
445
438
EXPECT_EQUAL (data .invoked_count , 1 );
446
439
}
440
+
441
+ /* For async cases, accept or reject API will be called outside of the validation callback.
442
+ * Iterate over both TLS 1.3 and 1.2 policies to ensure the stuffer reset logic works in all cases.
443
+ */
444
+ struct s2n_cert_validation_data async_test_cases [] = {
445
+ { .call_accept_or_reject = false, .accept = true, .return_success = true },
446
+ { .call_accept_or_reject = false, .accept = false, .return_success = true },
447
+ };
448
+ const char * versions [] = { "20240501" , "20170210" };
449
+
450
+ /* Async callback is invoked on the client after receiving the server's certificate */
451
+ for (int test_case_idx = 0 ; test_case_idx < s2n_array_len (async_test_cases ); test_case_idx ++ ) {
452
+ for (int version_idx = 0 ; version_idx < s2n_array_len (versions ); version_idx ++ ) {
453
+ DEFER_CLEANUP (struct s2n_config * config = s2n_config_new (), s2n_config_ptr_free );
454
+ EXPECT_NOT_NULL (config );
455
+ EXPECT_SUCCESS (s2n_config_add_cert_chain_and_key_to_store (config , chain_and_key ));
456
+ EXPECT_SUCCESS (s2n_config_set_verification_ca_location (config , S2N_DEFAULT_TEST_CERT_CHAIN , NULL ));
457
+ EXPECT_SUCCESS (s2n_config_set_cipher_preferences (config , versions [version_idx ]));
458
+
459
+ struct s2n_cert_validation_data data = async_test_cases [test_case_idx ];
460
+ EXPECT_SUCCESS (s2n_config_set_cert_validation_cb (config , s2n_test_cert_validation_callback_self_talk , & data ));
461
+
462
+ DEFER_CLEANUP (struct s2n_connection * server_conn = s2n_connection_new (S2N_SERVER ), s2n_connection_ptr_free );
463
+ EXPECT_NOT_NULL (server_conn );
464
+ EXPECT_SUCCESS (s2n_connection_set_config (server_conn , config ));
465
+
466
+ DEFER_CLEANUP (struct s2n_connection * client_conn = s2n_connection_new (S2N_CLIENT ), s2n_connection_ptr_free );
467
+ EXPECT_NOT_NULL (client_conn );
468
+ EXPECT_SUCCESS (s2n_connection_set_config (client_conn , config ));
469
+ EXPECT_SUCCESS (s2n_connection_set_blinding (client_conn , S2N_SELF_SERVICE_BLINDING ));
470
+ EXPECT_SUCCESS (s2n_set_server_name (client_conn , "localhost" ));
471
+
472
+ DEFER_CLEANUP (struct s2n_test_io_pair io_pair = { 0 }, s2n_io_pair_close );
473
+ EXPECT_SUCCESS (s2n_io_pair_init_non_blocking (& io_pair ));
474
+ EXPECT_SUCCESS (s2n_connection_set_io_pair (client_conn , & io_pair ));
475
+ EXPECT_SUCCESS (s2n_connection_set_io_pair (server_conn , & io_pair ));
476
+
477
+ for (int i = 0 ; i < 3 ; i ++ ) {
478
+ EXPECT_FAILURE_WITH_ERRNO (s2n_negotiate_test_server_and_client (server_conn , client_conn ),
479
+ S2N_ERR_ASYNC_BLOCKED );
480
+ EXPECT_EQUAL (data .invoked_count , 1 );
481
+ }
482
+
483
+ /* Ensure that the server's certificate chain can be retrieved after `S2N_ERR_ASYNC_BLOCKED` */
484
+ DEFER_CLEANUP (struct s2n_cert_chain_and_key * peer_cert_chain = s2n_cert_chain_and_key_new (),
485
+ s2n_cert_chain_and_key_ptr_free );
486
+ EXPECT_NOT_NULL (peer_cert_chain );
487
+ EXPECT_SUCCESS (s2n_connection_get_peer_cert_chain (client_conn , peer_cert_chain ));
488
+ /* Ensure the certificate chain is non-empty */
489
+ uint32_t peer_cert_chain_len = 0 ;
490
+ EXPECT_SUCCESS (s2n_cert_chain_get_length (peer_cert_chain , & peer_cert_chain_len ));
491
+ EXPECT_TRUE (peer_cert_chain_len > 0 );
492
+
493
+ struct s2n_cert_validation_info * info = data .info ;
494
+ EXPECT_NOT_NULL (info );
495
+
496
+ if (async_test_cases [test_case_idx ].accept ) {
497
+ EXPECT_SUCCESS (s2n_cert_validation_accept (info ));
498
+ EXPECT_SUCCESS (s2n_negotiate_test_server_and_client (server_conn , client_conn ));
499
+ } else {
500
+ EXPECT_SUCCESS (s2n_cert_validation_reject (info ));
501
+ EXPECT_FAILURE_WITH_ERRNO (s2n_negotiate_test_server_and_client (server_conn , client_conn ),
502
+ S2N_ERR_CERT_REJECTED );
503
+ }
504
+
505
+ EXPECT_EQUAL (data .invoked_count , 1 );
506
+ }
507
+ }
508
+
509
+ /* Async callback is invoked on the server after receiving the client's certificate */
510
+ for (int test_case_idx = 0 ; test_case_idx < s2n_array_len (async_test_cases ); test_case_idx ++ ) {
511
+ for (int version_idx = 0 ; version_idx < s2n_array_len (versions ); version_idx ++ ) {
512
+ DEFER_CLEANUP (struct s2n_config * server_config = s2n_config_new (), s2n_config_ptr_free );
513
+ EXPECT_NOT_NULL (server_config );
514
+ EXPECT_SUCCESS (s2n_config_add_cert_chain_and_key_to_store (server_config , chain_and_key ));
515
+ EXPECT_SUCCESS (s2n_config_set_verification_ca_location (server_config , S2N_DEFAULT_TEST_CERT_CHAIN , NULL ));
516
+ EXPECT_SUCCESS (s2n_config_set_cipher_preferences (server_config , versions [version_idx ]));
517
+ EXPECT_SUCCESS (s2n_config_set_client_auth_type (server_config , S2N_CERT_AUTH_REQUIRED ));
518
+
519
+ struct s2n_cert_validation_data data = async_test_cases [test_case_idx ];
520
+ EXPECT_SUCCESS (s2n_config_set_cert_validation_cb (server_config ,
521
+ s2n_test_cert_validation_callback_self_talk_server , & data ));
522
+
523
+ DEFER_CLEANUP (struct s2n_connection * server_conn = s2n_connection_new (S2N_SERVER ), s2n_connection_ptr_free );
524
+ EXPECT_NOT_NULL (server_conn );
525
+ EXPECT_SUCCESS (s2n_connection_set_config (server_conn , server_config ));
526
+ EXPECT_SUCCESS (s2n_connection_set_blinding (server_conn , S2N_SELF_SERVICE_BLINDING ));
527
+
528
+ DEFER_CLEANUP (struct s2n_config * client_config = s2n_config_new (), s2n_config_ptr_free );
529
+ EXPECT_NOT_NULL (client_config );
530
+ EXPECT_SUCCESS (s2n_config_add_cert_chain_and_key_to_store (client_config , chain_and_key ));
531
+ EXPECT_SUCCESS (s2n_config_set_verification_ca_location (client_config , S2N_DEFAULT_TEST_CERT_CHAIN , NULL ));
532
+ EXPECT_SUCCESS (s2n_config_set_cipher_preferences (client_config , versions [version_idx ]));
533
+ EXPECT_SUCCESS (s2n_config_set_client_auth_type (client_config , S2N_CERT_AUTH_OPTIONAL ));
534
+
535
+ DEFER_CLEANUP (struct s2n_connection * client_conn = s2n_connection_new (S2N_CLIENT ), s2n_connection_ptr_free );
536
+ EXPECT_NOT_NULL (client_conn );
537
+ EXPECT_SUCCESS (s2n_connection_set_config (client_conn , client_config ));
538
+ EXPECT_SUCCESS (s2n_set_server_name (client_conn , "localhost" ));
539
+
540
+ DEFER_CLEANUP (struct s2n_test_io_pair io_pair = { 0 }, s2n_io_pair_close );
541
+ EXPECT_SUCCESS (s2n_io_pair_init_non_blocking (& io_pair ));
542
+ EXPECT_SUCCESS (s2n_connection_set_io_pair (client_conn , & io_pair ));
543
+ EXPECT_SUCCESS (s2n_connection_set_io_pair (server_conn , & io_pair ));
544
+
545
+ for (int i = 0 ; i < 3 ; i ++ ) {
546
+ EXPECT_FAILURE_WITH_ERRNO (s2n_negotiate_test_server_and_client (server_conn , client_conn ),
547
+ S2N_ERR_ASYNC_BLOCKED );
548
+ EXPECT_EQUAL (data .invoked_count , 1 );
549
+ }
550
+
551
+ /* Ensure that the client's certificate chain can be retrieved after `S2N_ERR_ASYNC_BLOCKED` */
552
+ uint8_t * der_cert_chain = 0 ;
553
+ uint32_t cert_chain_len = 0 ;
554
+ EXPECT_SUCCESS (s2n_connection_get_client_cert_chain (server_conn , & der_cert_chain , & cert_chain_len ));
555
+ /* Ensure the certificate chain is non-empty */
556
+ EXPECT_TRUE (cert_chain_len > 0 );
557
+
558
+ struct s2n_cert_validation_info * info = data .info ;
559
+ EXPECT_NOT_NULL (info );
560
+
561
+ if (async_test_cases [test_case_idx ].accept ) {
562
+ EXPECT_SUCCESS (s2n_cert_validation_accept (info ));
563
+ EXPECT_SUCCESS (s2n_negotiate_test_server_and_client (server_conn , client_conn ));
564
+ } else {
565
+ EXPECT_SUCCESS (s2n_cert_validation_reject (info ));
566
+ EXPECT_FAILURE_WITH_ERRNO (s2n_negotiate_test_server_and_client (server_conn , client_conn ),
567
+ S2N_ERR_CERT_REJECTED );
568
+ }
569
+
570
+ EXPECT_EQUAL (data .invoked_count , 1 );
571
+ }
572
+ }
447
573
}
448
574
449
575
END_TEST ();
0 commit comments