aws-crt 0.1.4 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +5 -0
  3. data/VERSION +1 -1
  4. data/aws-crt-ffi/crt/aws-c-cal/CMakeLists.txt +2 -0
  5. data/aws-crt-ffi/crt/aws-c-cal/bin/produce_x_platform_fuzz_corpus/CMakeLists.txt +30 -0
  6. data/aws-crt-ffi/crt/aws-c-cal/bin/produce_x_platform_fuzz_corpus/main.c +208 -0
  7. data/aws-crt-ffi/crt/aws-c-cal/bin/run_x_platform_fuzz_corpus/CMakeLists.txt +30 -0
  8. data/aws-crt-ffi/crt/aws-c-cal/bin/run_x_platform_fuzz_corpus/main.c +244 -0
  9. data/aws-crt-ffi/crt/aws-c-cal/ecdsa-fuzz-corpus/darwin/p256_sig_corpus.txt +10000 -0
  10. data/aws-crt-ffi/crt/aws-c-cal/ecdsa-fuzz-corpus/windows/p256_sig_corpus.txt +10000 -0
  11. data/aws-crt-ffi/crt/aws-c-cal/source/windows/bcrypt_ecc.c +8 -0
  12. data/aws-crt-ffi/crt/aws-c-http/tests/CMakeLists.txt +11 -10
  13. data/aws-crt-ffi/crt/aws-c-io/include/aws/io/tls_channel_handler.h +2 -0
  14. data/aws-crt-ffi/crt/aws-c-io/source/darwin/darwin_pki_utils.c +8 -0
  15. data/aws-crt-ffi/crt/aws-c-io/source/tls_channel_handler.c +2 -0
  16. data/aws-crt-ffi/crt/aws-c-io/source/windows/windows_pki_utils.c +65 -35
  17. data/aws-crt-ffi/crt/s2n/CMakeLists.txt +67 -21
  18. data/aws-crt-ffi/crt/s2n/Makefile +10 -0
  19. data/aws-crt-ffi/crt/s2n/bin/Makefile +9 -0
  20. data/aws-crt-ffi/crt/s2n/bindings/rust/Makefile +14 -0
  21. data/aws-crt-ffi/crt/s2n/bindings/rust/integration/Cargo.toml +2 -2
  22. data/aws-crt-ffi/crt/s2n/bindings/rust/s2n-tls/Cargo.toml +3 -2
  23. data/aws-crt-ffi/crt/s2n/bindings/rust/s2n-tls/src/raw/config.rs +265 -39
  24. data/aws-crt-ffi/crt/s2n/bindings/rust/s2n-tls/src/raw/connection.rs +170 -20
  25. data/aws-crt-ffi/crt/s2n/bindings/rust/s2n-tls/src/testing/s2n_tls.rs +120 -0
  26. data/aws-crt-ffi/crt/s2n/bindings/rust/s2n-tls/src/testing.rs +58 -23
  27. data/aws-crt-ffi/crt/s2n/bindings/rust/s2n-tls-sys/Cargo.toml +1 -1
  28. data/aws-crt-ffi/crt/s2n/bindings/rust/s2n-tls-sys/src/internal.rs +3 -0
  29. data/aws-crt-ffi/crt/s2n/crypto/s2n_composite_cipher_aes_sha.c +1 -1
  30. data/aws-crt-ffi/crt/s2n/crypto/s2n_drbg.c +8 -3
  31. data/aws-crt-ffi/crt/s2n/error/s2n_errno.c +3 -0
  32. data/aws-crt-ffi/crt/s2n/error/s2n_errno.h +2 -0
  33. data/aws-crt-ffi/crt/s2n/lib/Makefile +11 -0
  34. data/aws-crt-ffi/crt/s2n/pq-crypto/kyber_90s_r2/ntt.h +2 -2
  35. data/aws-crt-ffi/crt/s2n/pq-crypto/kyber_r2/ntt.h +2 -2
  36. data/aws-crt-ffi/crt/s2n/pq-crypto/kyber_r3/kyber512r3_poly_avx2.h +2 -2
  37. data/aws-crt-ffi/crt/s2n/pq-crypto/kyber_r3/kyber512r3_polyvec_avx2.h +2 -2
  38. data/aws-crt-ffi/crt/s2n/pq-crypto/sike_r1/P503_internal_r1.h +1 -1
  39. data/aws-crt-ffi/crt/s2n/pq-crypto/sike_r1/fips202_r1.h +1 -1
  40. data/aws-crt-ffi/crt/s2n/pq-crypto/sike_r3/sikep434r3_fp_x64_asm.S +4 -0
  41. data/aws-crt-ffi/crt/s2n/s2n.mk +25 -0
  42. data/aws-crt-ffi/crt/s2n/scripts/s2n_safety_macros.py +14 -0
  43. data/aws-crt-ffi/crt/s2n/tests/benchmark/Readme.md +23 -9
  44. data/aws-crt-ffi/crt/s2n/tests/features/clone.c +24 -0
  45. data/aws-crt-ffi/crt/s2n/tests/features/madvise.c +27 -0
  46. data/aws-crt-ffi/crt/s2n/tests/features/minherit.c +22 -0
  47. data/aws-crt-ffi/crt/s2n/tests/integrationv2/conftest.py +2 -2
  48. data/aws-crt-ffi/crt/s2n/tests/unit/s2n_connection_test.c +1 -1
  49. data/aws-crt-ffi/crt/s2n/tests/unit/s2n_fork_generation_number_test.c +335 -0
  50. data/aws-crt-ffi/crt/s2n/tests/unit/s2n_mem_usage_test.c +1 -1
  51. data/aws-crt-ffi/crt/s2n/tests/unit/s2n_self_talk_client_hello_cb_test.c +93 -11
  52. data/aws-crt-ffi/crt/s2n/tests/unit/s2n_server_hello_retry_test.c +123 -1
  53. data/aws-crt-ffi/crt/s2n/tests/unit/s2n_tls13_key_schedule_rfc8448_test.c +18 -3
  54. data/aws-crt-ffi/crt/s2n/tests/unit/s2n_tls13_key_schedule_test.c +0 -38
  55. data/aws-crt-ffi/crt/s2n/tests/unit/s2n_tls13_secrets_test.c +134 -15
  56. data/aws-crt-ffi/crt/s2n/tls/s2n_cipher_suites.c +1 -1
  57. data/aws-crt-ffi/crt/s2n/tls/s2n_client_hello.c +20 -9
  58. data/aws-crt-ffi/crt/s2n/tls/s2n_client_hello.h +8 -0
  59. data/aws-crt-ffi/crt/s2n/tls/s2n_config.c +13 -0
  60. data/aws-crt-ffi/crt/s2n/tls/s2n_config.h +6 -0
  61. data/aws-crt-ffi/crt/s2n/tls/s2n_handshake_io.c +2 -1
  62. data/aws-crt-ffi/crt/s2n/tls/s2n_internal.h +9 -0
  63. data/aws-crt-ffi/crt/s2n/tls/s2n_tls13_key_schedule.c +7 -7
  64. data/aws-crt-ffi/crt/s2n/tls/s2n_tls13_secrets.c +61 -8
  65. data/aws-crt-ffi/crt/s2n/tls/s2n_tls13_secrets.h +11 -5
  66. data/aws-crt-ffi/crt/s2n/utils/s2n_fork_detection.c +367 -0
  67. data/aws-crt-ffi/crt/s2n/utils/s2n_fork_detection.h +28 -0
  68. data/aws-crt-ffi/crt/s2n/utils/s2n_safety_macros.h +13 -22
  69. metadata +18 -3
@@ -0,0 +1,335 @@
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
+ /* For clone() */
17
+ #define _GNU_SOURCE
18
+
19
+ #include "s2n_test.h"
20
+ #include "utils/s2n_fork_detection.h"
21
+
22
+ #include <pthread.h>
23
+ #include <sched.h>
24
+ #include <stdio.h>
25
+ #include <sys/wait.h>
26
+
27
+ #define NUMBER_OF_FGN_TEST_CASES 4
28
+ #define MAX_NUMBER_OF_TEST_THREADS 2
29
+ #define FORK_LEVEL_FOR_TESTS 2
30
+ /* Before calling s2n_get_fork_generation_number() set the argument to this
31
+ * value to avoid any unlucky collisions
32
+ */
33
+ #define UNEXPECTED_RETURNED_FGN 0xFF
34
+
35
+ #define CLONE_TEST_NO 0
36
+ #define CLONE_TEST_YES 1
37
+ #define CLONE_TEST_DETERMINE_AT_RUNTIME 2
38
+
39
+ struct fgn_test_case {
40
+ const char *test_case_label;
41
+ int (*test_case_cb)(struct fgn_test_case *test_case);
42
+ int test_case_must_pass_clone_test;
43
+ };
44
+
45
+ static void s2n_verify_child_exit_status(pid_t proc_pid)
46
+ {
47
+ int status = 0;
48
+ EXPECT_EQUAL(waitpid(proc_pid, &status, __WALL), proc_pid);
49
+
50
+ /* Check that child exited with EXIT_SUCCESS. If not, this indicates
51
+ * that an error was encountered in the unit tests executed in that
52
+ * child process.
53
+ */
54
+ EXPECT_NOT_EQUAL(WIFEXITED(status), 0);
55
+ EXPECT_EQUAL(WEXITSTATUS(status), EXIT_SUCCESS);
56
+ }
57
+
58
+ static void * s2n_unit_test_thread_get_fgn(void *expected_fork_generation_number)
59
+ {
60
+ uint64_t return_fork_generation_number = UNEXPECTED_RETURNED_FGN;
61
+ EXPECT_OK(s2n_get_fork_generation_number(&return_fork_generation_number));
62
+ EXPECT_EQUAL(return_fork_generation_number, *(uint64_t *) expected_fork_generation_number);
63
+
64
+ return NULL;
65
+ }
66
+
67
+ static int s2n_unit_test_thread(uint64_t expected_fork_generation_number)
68
+ {
69
+ pthread_t threads[MAX_NUMBER_OF_TEST_THREADS];
70
+
71
+ for (size_t thread_index = 0; thread_index < MAX_NUMBER_OF_TEST_THREADS; thread_index++) {
72
+ EXPECT_EQUAL(pthread_create(&threads[thread_index], NULL, &s2n_unit_test_thread_get_fgn, (void *) &expected_fork_generation_number), 0);
73
+ }
74
+
75
+ /* Wait for all threads to finish */
76
+ for (size_t thread_index = 0; thread_index < MAX_NUMBER_OF_TEST_THREADS; thread_index++) {
77
+ pthread_join(threads[thread_index], NULL);
78
+ }
79
+
80
+ return S2N_SUCCESS;
81
+ }
82
+
83
+ static int s2n_unit_test_fork(uint64_t parent_process_fgn, int fork_level)
84
+ {
85
+ pid_t proc_pid = fork();
86
+ EXPECT_TRUE(proc_pid >= 0);
87
+
88
+ fork_level = fork_level - 1;
89
+
90
+ if (proc_pid == 0) {
91
+ /* In child */
92
+ uint64_t return_fork_generation_number = UNEXPECTED_RETURNED_FGN;
93
+ EXPECT_OK(s2n_get_fork_generation_number(&return_fork_generation_number));
94
+ EXPECT_EQUAL(return_fork_generation_number, parent_process_fgn + 1);
95
+
96
+ /* Verify stability */
97
+ return_fork_generation_number = UNEXPECTED_RETURNED_FGN;
98
+ EXPECT_OK(s2n_get_fork_generation_number(&return_fork_generation_number));
99
+ EXPECT_EQUAL(return_fork_generation_number, parent_process_fgn + 1);
100
+
101
+ /* Verify in threads */
102
+ EXPECT_EQUAL(s2n_unit_test_thread(return_fork_generation_number), S2N_SUCCESS);
103
+
104
+ if (fork_level > 0) {
105
+ /* Fork again and verify fork generation number */
106
+ EXPECT_EQUAL(s2n_unit_test_fork(parent_process_fgn + 1, fork_level), S2N_SUCCESS);
107
+ }
108
+
109
+ /* Exit code EXIT_SUCCESS means that tests in this process finished
110
+ * successfully. Any errors would have exited the process with an
111
+ * exit code != EXIT_SUCCESS. We verify this in the parent process.
112
+ */
113
+ exit(EXIT_SUCCESS);
114
+ }
115
+ else {
116
+ s2n_verify_child_exit_status(proc_pid);
117
+
118
+ /* Verify stability */
119
+ uint64_t return_fork_generation_number = UNEXPECTED_RETURNED_FGN;
120
+ EXPECT_OK(s2n_get_fork_generation_number(&return_fork_generation_number));
121
+ EXPECT_EQUAL(return_fork_generation_number, parent_process_fgn);
122
+ }
123
+
124
+ return S2N_SUCCESS;
125
+ }
126
+
127
+ /* Similar test to unit_test_fork() but verify in threads first */
128
+ static int s2n_unit_test_fork_check_threads_first(uint64_t parent_process_fgn)
129
+ {
130
+ pid_t proc_pid = fork();
131
+ EXPECT_TRUE(proc_pid >= 0);
132
+
133
+ if (proc_pid == 0) {
134
+ /* In child. Verify threads first. */
135
+ EXPECT_EQUAL(s2n_unit_test_thread(parent_process_fgn + 1), S2N_SUCCESS);
136
+
137
+ /* Then in the thread spawned when forking */
138
+ uint64_t return_fork_generation_number = UNEXPECTED_RETURNED_FGN;
139
+ EXPECT_OK(s2n_get_fork_generation_number(&return_fork_generation_number));
140
+ EXPECT_EQUAL(return_fork_generation_number, parent_process_fgn + 1);
141
+
142
+ /* Verify stability */
143
+ return_fork_generation_number = UNEXPECTED_RETURNED_FGN;
144
+ EXPECT_OK(s2n_get_fork_generation_number(&return_fork_generation_number));
145
+ EXPECT_EQUAL(return_fork_generation_number, parent_process_fgn + 1);
146
+
147
+ /* Exit code EXIT_SUCCESS means that tests in this process finished
148
+ * successfully. Any errors would have exited the process with an
149
+ * exit code != EXIT_SUCCESS. We verify this in the parent process.
150
+ */
151
+ exit(EXIT_SUCCESS);
152
+ }
153
+ else {
154
+ s2n_verify_child_exit_status(proc_pid);
155
+
156
+ /* Verify stability */
157
+ uint64_t return_fork_generation_number = UNEXPECTED_RETURNED_FGN;
158
+ EXPECT_OK(s2n_get_fork_generation_number(&return_fork_generation_number));
159
+ EXPECT_EQUAL(return_fork_generation_number, parent_process_fgn);
160
+ }
161
+
162
+ return S2N_SUCCESS;
163
+ }
164
+
165
+ static int s2n_unit_test_clone_child_process(void *parent_process_fgn)
166
+ {
167
+ /* In child */
168
+ uint64_t local_parent_process_fgn = *(uint64_t *) parent_process_fgn;
169
+ uint64_t return_fork_generation_number = UNEXPECTED_RETURNED_FGN;
170
+ EXPECT_OK(s2n_get_fork_generation_number(&return_fork_generation_number));
171
+ EXPECT_EQUAL(return_fork_generation_number, local_parent_process_fgn + 1);
172
+
173
+ /* Verify stability */
174
+ return_fork_generation_number = UNEXPECTED_RETURNED_FGN;
175
+ EXPECT_OK(s2n_get_fork_generation_number(&return_fork_generation_number));
176
+ EXPECT_EQUAL(return_fork_generation_number, local_parent_process_fgn + 1);
177
+
178
+ /* Verify in threads */
179
+ EXPECT_EQUAL(s2n_unit_test_thread(return_fork_generation_number), S2N_SUCCESS);
180
+
181
+ /* This translates to the exit code for this child process */
182
+ return EXIT_SUCCESS;
183
+ }
184
+
185
+ #define PROCESS_CHILD_STACK_SIZE (1024 * 1024) /* Suggested by clone() man page... */
186
+ static int s2n_unit_test_clone(uint64_t parent_process_fgn)
187
+ {
188
+ #if defined(S2N_CLONE_SUPPORTED)
189
+ /* Verify stability */
190
+ uint64_t return_fork_generation_number = UNEXPECTED_RETURNED_FGN;
191
+ EXPECT_OK(s2n_get_fork_generation_number(&return_fork_generation_number));
192
+ EXPECT_EQUAL(return_fork_generation_number, parent_process_fgn);
193
+
194
+ /* Use stack memory for this... We don't exit unit_test_clone() before this
195
+ * memory has served its purpose.
196
+ * Why? Using dynamically allocated memory causes Valgrind to squat on the
197
+ * allocated memory when the child process exists.
198
+ */
199
+ char process_child_stack[PROCESS_CHILD_STACK_SIZE];
200
+ EXPECT_NOT_NULL(process_child_stack);
201
+
202
+ int proc_pid = clone(s2n_unit_test_clone_child_process, (void *) (process_child_stack + PROCESS_CHILD_STACK_SIZE), 0, (void *) &return_fork_generation_number);
203
+ EXPECT_NOT_EQUAL(proc_pid, -1);
204
+
205
+ s2n_verify_child_exit_status(proc_pid);
206
+
207
+ /* Verify stability */
208
+ return_fork_generation_number = UNEXPECTED_RETURNED_FGN;
209
+ EXPECT_OK(s2n_get_fork_generation_number(&return_fork_generation_number));
210
+ EXPECT_EQUAL(return_fork_generation_number, parent_process_fgn);
211
+ #endif
212
+
213
+ return S2N_SUCCESS;
214
+ }
215
+
216
+ static int s2n_unit_tests_common(struct fgn_test_case *test_case)
217
+ {
218
+ uint64_t return_fork_generation_number = 0;
219
+
220
+ EXPECT_OK(s2n_get_fork_generation_number(&return_fork_generation_number));
221
+ EXPECT_EQUAL(return_fork_generation_number, 0);
222
+
223
+ /* Should be idempotent if no fork event occurred */
224
+ return_fork_generation_number = UNEXPECTED_RETURNED_FGN;
225
+ EXPECT_OK(s2n_get_fork_generation_number(&return_fork_generation_number));
226
+ EXPECT_EQUAL(return_fork_generation_number, 0);
227
+
228
+ /* Should be idempotent in threaded environment as well */
229
+ EXPECT_EQUAL(s2n_unit_test_thread(return_fork_generation_number), S2N_SUCCESS);
230
+
231
+ /* Cached FGN should increment if a fork event occurs */
232
+ EXPECT_EQUAL(s2n_unit_test_fork(return_fork_generation_number, FORK_LEVEL_FOR_TESTS), S2N_SUCCESS);
233
+ EXPECT_EQUAL(s2n_unit_test_fork_check_threads_first(return_fork_generation_number), S2N_SUCCESS);
234
+
235
+ /* Some fork detection mechanisms can also detect forks through clone() */
236
+ if (test_case->test_case_must_pass_clone_test == CLONE_TEST_YES) {
237
+ EXPECT_EQUAL((s2n_is_madv_wipeonfork_supported() == true) || (s2n_is_map_inherit_zero_supported() == true), true);
238
+ EXPECT_EQUAL(s2n_unit_test_clone(return_fork_generation_number), S2N_SUCCESS);
239
+ }
240
+ else if (test_case->test_case_must_pass_clone_test == CLONE_TEST_DETERMINE_AT_RUNTIME) {
241
+ if ((s2n_is_madv_wipeonfork_supported() == true) ||
242
+ (s2n_is_map_inherit_zero_supported() == true)) {
243
+ EXPECT_EQUAL(s2n_unit_test_clone(return_fork_generation_number), S2N_SUCCESS);
244
+ }
245
+ }
246
+
247
+ return S2N_SUCCESS;
248
+ }
249
+
250
+ static int s2n_test_case_default_cb(struct fgn_test_case *test_case)
251
+ {
252
+ EXPECT_EQUAL(s2n_unit_tests_common(test_case), S2N_SUCCESS);
253
+
254
+ return S2N_SUCCESS;
255
+ }
256
+
257
+ static int s2n_test_case_pthread_atfork_cb(struct fgn_test_case *test_case)
258
+ {
259
+ POSIX_GUARD_RESULT(s2n_ignore_wipeonfork_and_inherit_zero_for_testing());
260
+ EXPECT_EQUAL(s2n_unit_tests_common(test_case), S2N_SUCCESS);
261
+
262
+ return S2N_SUCCESS;
263
+ }
264
+
265
+ static int s2n_test_case_madv_wipeonfork_cb(struct fgn_test_case *test_case)
266
+ {
267
+ if (s2n_is_madv_wipeonfork_supported() == false) {
268
+ TEST_DEBUG_PRINT("s2n_fork_generation_number_test.c test case not supported. Skipping.\nTest case: %s\n", test_case->test_case_label);
269
+ return S2N_SUCCESS;
270
+ }
271
+
272
+ POSIX_GUARD_RESULT(s2n_ignore_pthread_atfork_for_testing());
273
+ EXPECT_EQUAL(s2n_unit_tests_common(test_case), S2N_SUCCESS);
274
+
275
+ return S2N_SUCCESS;
276
+ }
277
+
278
+ static int s2n_test_case_map_inherit_zero_cb(struct fgn_test_case *test_case)
279
+ {
280
+ if (s2n_is_map_inherit_zero_supported() == false) {
281
+ TEST_DEBUG_PRINT("s2n_fork_generation_number_test.c test case not supported. Skipping.\nTest case: %s\n", test_case->test_case_label);
282
+ return S2N_SUCCESS;
283
+ }
284
+
285
+ POSIX_GUARD_RESULT(s2n_ignore_pthread_atfork_for_testing());
286
+ EXPECT_EQUAL(s2n_unit_tests_common(test_case), S2N_SUCCESS);
287
+
288
+ return S2N_SUCCESS;
289
+ }
290
+
291
+ struct fgn_test_case fgn_test_cases[NUMBER_OF_FGN_TEST_CASES] = {
292
+ {"Default fork detect mechanisms.", s2n_test_case_default_cb, CLONE_TEST_DETERMINE_AT_RUNTIME},
293
+ {"Only pthread_atfork fork detection mechanism.", s2n_test_case_pthread_atfork_cb, CLONE_TEST_NO},
294
+ {"Only madv_wipeonfork fork detection mechanism.", s2n_test_case_madv_wipeonfork_cb, CLONE_TEST_YES},
295
+ {"Only map_inheret_zero fork detection mechanism.", s2n_test_case_map_inherit_zero_cb, CLONE_TEST_YES}
296
+ };
297
+
298
+ int main(int argc, char **argv)
299
+ {
300
+ BEGIN_TEST();
301
+
302
+ EXPECT_TRUE(s2n_array_len(fgn_test_cases) == NUMBER_OF_FGN_TEST_CASES);
303
+
304
+ /* Create NUMBER_OF_FGN_TEST_CASES number of child processes that run each
305
+ * test case.
306
+ *
307
+ * Fork detection is lazily initialised on first invocation of
308
+ * s2n_get_fork_generation_number(). Hence, it is important that childs are
309
+ * created before calling into the fork detection code.
310
+ */
311
+ pid_t proc_pids[NUMBER_OF_FGN_TEST_CASES] = {0};
312
+
313
+ for (size_t i = 0; i < NUMBER_OF_FGN_TEST_CASES; i++) {
314
+
315
+ proc_pids[i] = fork();
316
+ EXPECT_TRUE(proc_pids[i] >= 0);
317
+
318
+ if (proc_pids[i] == 0) {
319
+ /* In child */
320
+ EXPECT_EQUAL(fgn_test_cases[i].test_case_cb(&fgn_test_cases[i]), S2N_SUCCESS);
321
+
322
+ /* Exit code EXIT_SUCCESS means that tests in this process finished
323
+ * successfully. Any errors would have exited the process with an
324
+ * exit code != EXIT_SUCCESS. We verify this in the parent process.
325
+ * Also prevents child from creating more childs.
326
+ */
327
+ exit(EXIT_SUCCESS);
328
+ }
329
+ else {
330
+ s2n_verify_child_exit_status(proc_pids[i]);
331
+ }
332
+ }
333
+
334
+ END_TEST();
335
+ }
@@ -47,7 +47,7 @@
47
47
  #ifdef __FreeBSD__
48
48
  #define MEM_PER_CONNECTION 57
49
49
  #else
50
- #define MEM_PER_CONNECTION 48
50
+ #define MEM_PER_CONNECTION 49
51
51
  #endif
52
52
 
53
53
  /* This is the maximum memory per connection including 4KB of slack */
@@ -24,6 +24,7 @@
24
24
 
25
25
  #include "api/s2n.h"
26
26
  #include "tls/s2n_connection.h"
27
+ #include "tls/s2n_internal.h"
27
28
 
28
29
  struct client_hello_context {
29
30
  int invoked;
@@ -38,6 +39,7 @@ struct client_hello_context {
38
39
  * this flag tests the previous behavior from blocking callbacks
39
40
  */
40
41
  int legacy_rc_for_server_name_used;
42
+ bool mark_done;
41
43
  };
42
44
 
43
45
  int mock_client(struct s2n_test_io_pair *io_pair, int expect_failure, int expect_server_name_used)
@@ -181,9 +183,27 @@ int client_hello_fail_handshake(struct s2n_connection *conn, void *ctx)
181
183
  /* Return negative value to terminate the handshake */
182
184
  return -1;
183
185
 
184
- }
186
+ }
187
+
188
+ int s2n_client_hello_poll_cb(struct s2n_connection *conn, void *ctx)
189
+ {
190
+ struct client_hello_context *client_hello_ctx;
191
+ if (ctx == NULL) {
192
+ return -1;
193
+ }
194
+ client_hello_ctx = ctx;
195
+ /* Increment counter to ensure that callback was invoked */
196
+ client_hello_ctx->invoked++;
197
+
198
+ if (client_hello_ctx->mark_done) {
199
+ EXPECT_SUCCESS(s2n_client_hello_cb_done(conn));
200
+ return S2N_SUCCESS;
201
+ }
202
+
203
+ return S2N_SUCCESS;
204
+ }
185
205
 
186
- int s2n_negotiate_nonblocking_ch_cb(struct s2n_connection *conn,
206
+ int s2n_negotiate_nonblocking_ch_cb(struct s2n_connection *conn,
187
207
  struct client_hello_context *ch_ctx, bool server_name_used)
188
208
  {
189
209
  s2n_blocked_status blocked;
@@ -191,7 +211,7 @@ int s2n_negotiate_nonblocking_ch_cb(struct s2n_connection *conn,
191
211
  /* negotiate handshake, we should pause after the nonblocking callback is invoked */
192
212
  EXPECT_FAILURE_WITH_ERRNO(s2n_negotiate(conn, &blocked), S2N_ERR_ASYNC_BLOCKED);
193
213
  EXPECT_EQUAL(blocked, S2N_BLOCKED_ON_APPLICATION_INPUT);
194
-
214
+
195
215
  /* verify client hello cb has been invoked */
196
216
  EXPECT_EQUAL(ch_ctx->invoked, 1);
197
217
 
@@ -201,7 +221,7 @@ int s2n_negotiate_nonblocking_ch_cb(struct s2n_connection *conn,
201
221
  }
202
222
  /* unless explicitly unblocked we should stay paused */
203
223
  EXPECT_FAILURE_WITH_ERRNO(s2n_negotiate(conn, &blocked), S2N_ERR_ASYNC_BLOCKED);
204
- EXPECT_EQUAL(blocked, S2N_BLOCKED_ON_APPLICATION_INPUT);
224
+ EXPECT_EQUAL(blocked, S2N_BLOCKED_ON_APPLICATION_INPUT);
205
225
 
206
226
  /* mark the client hello cb complete */
207
227
  EXPECT_SUCCESS(s2n_client_hello_cb_done(conn));
@@ -211,11 +231,39 @@ int s2n_negotiate_nonblocking_ch_cb(struct s2n_connection *conn,
211
231
  return s2n_negotiate(conn, &blocked);
212
232
  }
213
233
 
234
+ int s2n_negotiate_nonblocking_poll(struct s2n_connection *conn,
235
+ struct client_hello_context *ch_ctx)
236
+ {
237
+ EXPECT_NOT_NULL(conn);
238
+ EXPECT_NOT_NULL(ch_ctx);
239
+ int invoked = 0;
240
+ s2n_blocked_status blocked = S2N_NOT_BLOCKED;
241
+
242
+ EXPECT_EQUAL(ch_ctx->invoked, 0);
243
+
244
+ do {
245
+ /* negotiate handshake, we should pause after the nonblocking callback is invoked */
246
+ EXPECT_FAILURE_WITH_ERRNO(s2n_negotiate(conn, &blocked), S2N_ERR_ASYNC_BLOCKED);
247
+ EXPECT_EQUAL(blocked, S2N_BLOCKED_ON_APPLICATION_INPUT);
248
+ invoked++;
249
+ EXPECT_EQUAL(ch_ctx->invoked, invoked);
250
+ } while(invoked < 10);
251
+ EXPECT_EQUAL(ch_ctx->invoked, invoked);
252
+
253
+ ch_ctx->mark_done = true;
254
+
255
+ /* Expect the callback to complete after 2nd iteration */
256
+ EXPECT_SUCCESS(s2n_negotiate(conn, &blocked));
257
+ EXPECT_EQUAL(ch_ctx->invoked, invoked + 1);
258
+
259
+ return S2N_SUCCESS;
260
+ }
261
+
214
262
  int s2n_negotiate_blocking_ch_cb(struct s2n_connection *conn, struct client_hello_context *ch_ctx)
215
263
  {
216
264
  s2n_blocked_status blocked;
217
265
  EXPECT_NOT_NULL(conn);
218
-
266
+
219
267
  int rc = s2n_negotiate(conn, &blocked);
220
268
  /* verify client hello cb has been invoked */
221
269
  EXPECT_EQUAL(ch_ctx->invoked, 1);
@@ -329,7 +377,7 @@ int run_test_config_swap_ch_cb(s2n_client_hello_cb_mode cb_mode,
329
377
 
330
378
  EXPECT_SUCCESS(start_client_conn(&io_pair, &pid, 0 , 1));
331
379
  EXPECT_SUCCESS(init_server_conn(&conn, &io_pair, config));
332
-
380
+
333
381
  /* do the handshake */
334
382
  if ( cb_mode == S2N_CLIENT_HELLO_CB_NONBLOCKING && !ch_ctx->mark_done_during_callback) {
335
383
  /* swap the config and mark server_name_used in the async context */
@@ -340,7 +388,7 @@ int run_test_config_swap_ch_cb(s2n_client_hello_cb_mode cb_mode,
340
388
  */
341
389
  EXPECT_SUCCESS(s2n_negotiate_blocking_ch_cb(conn, ch_ctx));
342
390
  }
343
-
391
+
344
392
  /* Server name and error are as expected with null connection */
345
393
  EXPECT_NULL(s2n_get_server_name(NULL));
346
394
  EXPECT_EQUAL(s2n_errno, S2N_ERR_NULL);
@@ -349,7 +397,7 @@ int run_test_config_swap_ch_cb(s2n_client_hello_cb_mode cb_mode,
349
397
  EXPECT_STRING_EQUAL(s2n_get_application_protocol(conn), protocols[0]);
350
398
 
351
399
  EXPECT_SUCCESS(server_recv(conn));
352
-
400
+
353
401
  EXPECT_SUCCESS(test_case_clean(conn, pid, config, &io_pair, ch_ctx));
354
402
  EXPECT_SUCCESS(s2n_config_free(swap_config));
355
403
  return S2N_SUCCESS;
@@ -372,7 +420,7 @@ int run_test_no_config_swap_ch_cb(s2n_client_hello_cb_mode cb_mode,
372
420
  EXPECT_SUCCESS(s2n_config_set_client_hello_cb_mode(config, cb_mode));
373
421
  EXPECT_SUCCESS(start_client_conn(&io_pair, &pid, 0 , 0));
374
422
  EXPECT_SUCCESS(init_server_conn(&conn, &io_pair, config));
375
-
423
+
376
424
  /* do the handshake */
377
425
  if ( cb_mode == S2N_CLIENT_HELLO_CB_NONBLOCKING ) {
378
426
  /* swap the config and mark server_name_used in the async context */
@@ -387,7 +435,7 @@ int run_test_no_config_swap_ch_cb(s2n_client_hello_cb_mode cb_mode,
387
435
  EXPECT_EQUAL(s2n_errno, S2N_ERR_NULL);
388
436
 
389
437
  EXPECT_SUCCESS(server_recv(conn));
390
-
438
+
391
439
  EXPECT_SUCCESS(test_case_clean(conn, pid, config, &io_pair, ch_ctx));
392
440
  return S2N_SUCCESS;
393
441
  }
@@ -425,7 +473,7 @@ int run_test_reject_handshake_ch_cb(s2n_client_hello_cb_mode cb_mode,
425
473
 
426
474
  /* Ensure that callback was invoked */
427
475
  EXPECT_EQUAL(ch_ctx->invoked, 1);
428
-
476
+
429
477
  /* shutdown to flush alert, expext failure as client doesn't send close notify */
430
478
  EXPECT_FAILURE(s2n_shutdown(conn, &blocked));
431
479
  EXPECT_SUCCESS(s2n_connection_free(conn));
@@ -434,6 +482,37 @@ int run_test_reject_handshake_ch_cb(s2n_client_hello_cb_mode cb_mode,
434
482
  return S2N_SUCCESS;
435
483
  }
436
484
 
485
+ int run_test_poll_ch_cb(s2n_client_hello_cb_mode cb_mode,
486
+ struct s2n_cert_chain_and_key *chain_and_key,
487
+ struct client_hello_context *ch_ctx)
488
+ {
489
+ struct s2n_test_io_pair io_pair = { 0 };
490
+ struct s2n_config *config = s2n_config_new();
491
+ EXPECT_NOT_NULL(config);
492
+ struct s2n_connection *conn;
493
+ pid_t pid = 0;
494
+
495
+ EXPECT_SUCCESS(s2n_config_add_cert_chain_and_key_to_store(config, chain_and_key));
496
+
497
+ /* Setup ClientHello callback */
498
+ EXPECT_SUCCESS(s2n_config_set_client_hello_cb(config, s2n_client_hello_poll_cb, ch_ctx));
499
+ EXPECT_SUCCESS(s2n_config_set_client_hello_cb_mode(config, cb_mode));
500
+
501
+ /* Enable callback polling mode */
502
+ EXPECT_SUCCESS(s2n_config_client_hello_cb_enable_poll(config));
503
+
504
+ EXPECT_SUCCESS(start_client_conn(&io_pair, &pid, 0 , 0));
505
+ EXPECT_SUCCESS(init_server_conn(&conn, &io_pair, config));
506
+
507
+ /* negotiate and make assertions */
508
+ EXPECT_SUCCESS(s2n_negotiate_nonblocking_poll(conn, ch_ctx));
509
+
510
+ EXPECT_SUCCESS(server_recv(conn));
511
+
512
+ EXPECT_SUCCESS(test_case_clean(conn, pid, config, &io_pair, ch_ctx));
513
+ return S2N_SUCCESS;
514
+ }
515
+
437
516
  int main(int argc, char **argv)
438
517
  {
439
518
  struct client_hello_context client_hello_ctx = {0};
@@ -487,6 +566,9 @@ int main(int argc, char **argv)
487
566
  EXPECT_SUCCESS(run_test_reject_handshake_ch_cb(S2N_CLIENT_HELLO_CB_NONBLOCKING,
488
567
  chain_and_key, &client_hello_ctx));
489
568
 
569
+ EXPECT_SUCCESS(run_test_poll_ch_cb(S2N_CLIENT_HELLO_CB_NONBLOCKING,
570
+ chain_and_key, &client_hello_ctx));
571
+
490
572
  EXPECT_SUCCESS(s2n_cert_chain_and_key_free(chain_and_key));
491
573
  free(cert_chain_pem);
492
574
  free(private_key_pem);