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
@@ -77,7 +77,7 @@ static S2N_RESULT s2n_set_key(struct s2n_connection *conn, s2n_extract_secret_ty
77
77
  struct s2n_blob secret = { 0 };
78
78
  uint8_t secret_bytes[S2N_TLS13_SECRET_MAX_LEN] = { 0 };
79
79
  RESULT_GUARD_POSIX(s2n_blob_init(&secret, secret_bytes, S2N_TLS13_SECRET_MAX_LEN));
80
- RESULT_GUARD(s2n_tls13_derive_secret(conn, secret_type, mode, &secret));
80
+ RESULT_GUARD(s2n_tls13_secrets_get(conn, secret_type, mode, &secret));
81
81
 
82
82
  /**
83
83
  *= https://tools.ietf.org/rfc/rfc8446#section-7.3
@@ -246,22 +246,21 @@ static S2N_RESULT s2n_server_key_schedule(struct s2n_connection *conn)
246
246
  *# Can send | [Send Certificate + CertificateVerify]
247
247
  *# app data | Send Finished
248
248
  *# after --> | K_send = application
249
+ */
250
+ if (message_type == SERVER_FINISHED) {
251
+ K_send(conn, S2N_APPLICATION_SECRET);
252
+ /**
253
+ *= https://tools.ietf.org/rfc/rfc8446#appendix-A.2
249
254
  *# here +--------+--------+
250
255
  *# No 0-RTT | | 0-RTT
251
256
  *# | |
252
257
  *# K_recv = handshake | | K_recv = early data
253
258
  */
254
- if (message_type == SERVER_FINISHED) {
255
- /* Warning: s2n-quic currently requires that we emit secrets in pairs.
256
- * Therefore, we must handle the handshake secret before we handle
257
- * the application secret here.
258
- */
259
259
  if (WITH_EARLY_DATA(conn)) {
260
260
  K_recv(conn, S2N_EARLY_SECRET);
261
261
  } else {
262
262
  K_recv(conn, S2N_HANDSHAKE_SECRET);
263
263
  }
264
- K_send(conn, S2N_APPLICATION_SECRET);
265
264
  }
266
265
  /**
267
266
  *= https://tools.ietf.org/rfc/rfc8446#appendix-A.2
@@ -314,6 +313,7 @@ S2N_RESULT s2n_tls13_key_schedule_update(struct s2n_connection *conn)
314
313
  if (s2n_connection_get_protocol_version(conn) < S2N_TLS13) {
315
314
  return S2N_RESULT_OK;
316
315
  }
316
+ RESULT_GUARD(s2n_tls13_secrets_update(conn));
317
317
  RESULT_ENSURE_REF(key_schedules[conn->mode]);
318
318
  RESULT_GUARD(key_schedules[conn->mode](conn));
319
319
  return S2N_RESULT_OK;
@@ -504,20 +504,13 @@ S2N_RESULT s2n_tls13_derive_secret(struct s2n_connection *conn, s2n_extract_secr
504
504
  return S2N_RESULT_OK;
505
505
  }
506
506
 
507
- S2N_RESULT s2n_tls13_secrets_finish(struct s2n_connection *conn)
507
+ S2N_RESULT s2n_tls13_secrets_clean(struct s2n_connection *conn)
508
508
  {
509
509
  RESULT_ENSURE_REF(conn);
510
510
  if (conn->actual_protocol_version < S2N_TLS13) {
511
511
  return S2N_RESULT_OK;
512
512
  }
513
513
 
514
- /*
515
- * Prepare TLS1.3 resumption secret.
516
- * A ticket can be requested any time after the handshake ends,
517
- * so we need to calculate this before the handshake ends.
518
- */
519
- RESULT_GUARD(s2n_derive_resumption_master_secret(conn));
520
-
521
514
  /*
522
515
  * Wipe base secrets.
523
516
  * Not strictly necessary, but probably safer than leaving them.
@@ -529,5 +522,65 @@ S2N_RESULT s2n_tls13_secrets_finish(struct s2n_connection *conn)
529
522
  RESULT_GUARD_POSIX(s2n_blob_zero(&CONN_SECRET(conn, master_secret)));
530
523
  conn->secrets.tls13.secrets_state = S2N_NONE_SECRET;
531
524
 
525
+ /* Wipe other secrets no longer needed */
526
+ RESULT_GUARD_POSIX(s2n_blob_zero(&CONN_SECRET(conn, client_handshake_secret)));
527
+ RESULT_GUARD_POSIX(s2n_blob_zero(&CONN_SECRET(conn, server_handshake_secret)));
528
+
529
+ return S2N_RESULT_OK;
530
+ }
531
+
532
+ S2N_RESULT s2n_tls13_secrets_update(struct s2n_connection *conn)
533
+ {
534
+ RESULT_ENSURE_REF(conn);
535
+ RESULT_ENSURE_REF(conn->secure.cipher_suite);
536
+
537
+ message_type_t message_type = s2n_conn_get_current_message_type(conn);
538
+ switch(message_type) {
539
+ case SERVER_HELLO:
540
+ RESULT_GUARD(s2n_tls13_derive_secret(conn, S2N_HANDSHAKE_SECRET,
541
+ S2N_CLIENT, &CONN_SECRET(conn, client_handshake_secret)));
542
+ RESULT_GUARD(s2n_tls13_derive_secret(conn, S2N_HANDSHAKE_SECRET,
543
+ S2N_SERVER, &CONN_SECRET(conn, server_handshake_secret)));
544
+ RESULT_ENSURE_EQ(CONN_SECRETS(conn).secrets_state, S2N_HANDSHAKE_SECRET);
545
+ break;
546
+ case SERVER_FINISHED:
547
+ RESULT_GUARD(s2n_tls13_derive_secret(conn, S2N_MASTER_SECRET,
548
+ S2N_CLIENT, &CONN_SECRET(conn, client_app_secret)));
549
+ RESULT_GUARD(s2n_tls13_derive_secret(conn, S2N_MASTER_SECRET,
550
+ S2N_SERVER, &CONN_SECRET(conn, server_app_secret)));
551
+ RESULT_ENSURE_EQ(CONN_SECRETS(conn).secrets_state, S2N_MASTER_SECRET);
552
+ break;
553
+ case CLIENT_FINISHED:
554
+ RESULT_GUARD(s2n_derive_resumption_master_secret(conn));
555
+ break;
556
+ default:
557
+ break;
558
+ }
559
+ return S2N_RESULT_OK;
560
+ }
561
+
562
+ S2N_RESULT s2n_tls13_secrets_get(struct s2n_connection *conn, s2n_extract_secret_type_t secret_type,
563
+ s2n_mode mode, struct s2n_blob *secret)
564
+ {
565
+ RESULT_ENSURE_REF(conn);
566
+ RESULT_ENSURE_REF(secret);
567
+
568
+ uint8_t *secrets[][2] = {
569
+ [S2N_HANDSHAKE_SECRET] = { CONN_SECRETS(conn).server_handshake_secret, CONN_SECRETS(conn).client_handshake_secret },
570
+ [S2N_MASTER_SECRET] = { CONN_SECRETS(conn).server_app_secret, CONN_SECRETS(conn).client_app_secret },
571
+ };
572
+ RESULT_ENSURE_GT(secret_type, S2N_NONE_SECRET);
573
+ RESULT_ENSURE_LT(secret_type, s2n_array_len(secrets));
574
+
575
+ if (secrets[secret_type][mode] == NULL) {
576
+ RESULT_GUARD(s2n_tls13_derive_secret(conn, secret_type, mode, secret));
577
+ return S2N_RESULT_OK;
578
+ }
579
+
580
+ RESULT_ENSURE_GTE(CONN_SECRETS(conn).secrets_state, secret_type);
581
+
582
+ secret->size = s2n_get_hash_len(CONN_HMAC_ALG(conn));
583
+ RESULT_CHECKED_MEMCPY(secret->data, secrets[secret_type][mode], secret->size);
584
+ RESULT_ENSURE_GT(secret->size, 0);
532
585
  return S2N_RESULT_OK;
533
586
  }
@@ -31,25 +31,31 @@ typedef enum {
31
31
  } s2n_extract_secret_type_t;
32
32
 
33
33
  struct s2n_tls13_secrets {
34
- /* Secrets only used during the handshake */
35
34
  uint8_t early_secret[S2N_TLS13_SECRET_MAX_LEN];
35
+
36
36
  uint8_t handshake_secret[S2N_TLS13_SECRET_MAX_LEN];
37
- uint8_t master_secret[S2N_TLS13_SECRET_MAX_LEN];
38
- s2n_extract_secret_type_t secrets_state;
37
+ uint8_t client_handshake_secret[S2N_TLS13_SECRET_MAX_LEN];
38
+ uint8_t server_handshake_secret[S2N_TLS13_SECRET_MAX_LEN];
39
39
 
40
- /* Secrets used after the handshake */
40
+ uint8_t master_secret[S2N_TLS13_SECRET_MAX_LEN];
41
41
  uint8_t client_app_secret[S2N_TLS13_SECRET_MAX_LEN];
42
42
  uint8_t server_app_secret[S2N_TLS13_SECRET_MAX_LEN];
43
43
  uint8_t resumption_master_secret[S2N_TLS13_SECRET_MAX_LEN];
44
+
45
+ s2n_extract_secret_type_t secrets_state;
44
46
  };
45
47
 
46
48
  S2N_RESULT s2n_tls13_empty_transcripts_init();
47
- S2N_RESULT s2n_tls13_secrets_finish(struct s2n_connection *conn);
48
49
 
49
50
  S2N_RESULT s2n_tls13_extract_secret(struct s2n_connection *conn, s2n_extract_secret_type_t secret_type);
50
51
  S2N_RESULT s2n_tls13_derive_secret(struct s2n_connection *conn, s2n_extract_secret_type_t secret_type,
51
52
  s2n_mode mode, struct s2n_blob *secret);
52
53
 
54
+ S2N_RESULT s2n_tls13_secrets_update(struct s2n_connection *conn);
55
+ S2N_RESULT s2n_tls13_secrets_get(struct s2n_connection *conn, s2n_extract_secret_type_t secret_type,
56
+ s2n_mode mode, struct s2n_blob *secret);
57
+ S2N_RESULT s2n_tls13_secrets_clean(struct s2n_connection *conn);
58
+
53
59
  S2N_RESULT s2n_derive_binder_key(struct s2n_psk *psk, struct s2n_blob *output);
54
60
  S2N_RESULT s2n_derive_resumption_master_secret(struct s2n_connection *conn);
55
61
 
@@ -0,0 +1,367 @@
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
+ /* This captures Darwin specialities. This is the only APPLE flavor we care about.
17
+ * Here we also capture varius required feature test macros.
18
+ */
19
+ #if defined(__APPLE__)
20
+ typedef struct _opaque_pthread_once_t __darwin_pthread_once_t;
21
+ typedef __darwin_pthread_once_t pthread_once_t;
22
+ #define _DARWIN_C_SOURCE
23
+ #elif !defined(_GNU_SOURCE)
24
+ /* Keep in sync with feature probe tests/features/madvise.c */
25
+ #define _GNU_SOURCE
26
+ #endif
27
+
28
+ #include <sys/mman.h>
29
+
30
+ /* Not always defined for Darwin */
31
+ #if !defined(MAP_ANONYMOUS)
32
+ #define MAP_ANONYMOUS MAP_ANON
33
+ #endif
34
+
35
+ #include "error/s2n_errno.h"
36
+ #include "utils/s2n_fork_detection.h"
37
+ #include "utils/s2n_safety.h"
38
+
39
+ #include <pthread.h>
40
+ #include <stdlib.h>
41
+ #include <sys/types.h>
42
+ #include <unistd.h>
43
+
44
+
45
+ #if defined(S2N_MINHERIT_SUPPORTED) && defined(S2N_MADVISE_SUPPORTED)
46
+ #error "Both S2N_MINHERIT_SUPPORTED and S2N_MADVISE_SUPPORTED are defined. This should not be possible."
47
+ #endif
48
+
49
+ #if defined(S2N_MADVISE_SUPPORTED) && defined(MADV_WIPEONFORK)
50
+ #if (MADV_WIPEONFORK != 18)
51
+ #error "MADV_WIPEONFORK is not 18"
52
+ #endif
53
+ #else /* defined(S2N_MADVISE_SUPPORTED) && defined(MADV_WIPEONFORK) */
54
+ #define MADV_WIPEONFORK 18
55
+ #endif
56
+
57
+ /* These variables are used to disable all fork detection mechanisms or at the
58
+ * individual level during testing.
59
+ */
60
+ static bool ignore_wipeonfork_or_inherit_zero_method_for_testing = false;
61
+ static bool ignore_pthread_atfork_method_for_testing = false;
62
+ static bool ignore_fork_detection_for_testing = false;
63
+
64
+ #define S2N_FORK_EVENT 0
65
+ #define S2N_NO_FORK_EVENT 1
66
+
67
+ struct FGN_STATE {
68
+ /* The current cached fork generation number for this process */
69
+ uint64_t current_fork_generation_number;
70
+
71
+ /* Semaphore controlling access to the shared sentinel and signaling whether
72
+ * fork detection is enabled or not. We could use zero_on_fork_addr, but
73
+ * avoid overloading by using an explicit variable.
74
+ */
75
+ bool is_fork_detection_enabled;
76
+
77
+ /* Sentinel that signals a fork event has occurred */
78
+ volatile char *zero_on_fork_addr;
79
+
80
+ pthread_once_t fork_detection_once;
81
+ pthread_rwlock_t fork_detection_rw_lock;
82
+ };
83
+
84
+ /* We only need a single statically initialised state. Note, the state is
85
+ * inherited by child processes.
86
+ */
87
+ static struct FGN_STATE fgn_state = {
88
+ .current_fork_generation_number = 0,
89
+ .is_fork_detection_enabled = false,
90
+ .zero_on_fork_addr = NULL,
91
+ .fork_detection_once = PTHREAD_ONCE_INIT,
92
+ .fork_detection_rw_lock = PTHREAD_RWLOCK_INITIALIZER,
93
+ };
94
+
95
+
96
+ /* Can currently never fail. See initialise_fork_detection_methods() for
97
+ * motivation.
98
+ */
99
+ static inline S2N_RESULT s2n_initialise_wipeonfork_best_effort(void *addr, long page_size)
100
+ {
101
+ #if defined(S2N_MADVISE_SUPPORTED)
102
+ /* Return value ignored on purpose */
103
+ madvise(addr, (size_t) page_size, MADV_WIPEONFORK);
104
+ #endif
105
+
106
+ return S2N_RESULT_OK;
107
+ }
108
+
109
+ static inline S2N_RESULT s2n_initialise_inherit_zero(void *addr, long page_size)
110
+ {
111
+ #if defined(S2N_MINHERIT_SUPPORTED) && defined(MAP_INHERIT_ZERO)
112
+ RESULT_ENSURE(minherit(addr, pagesize, MAP_INHERIT_ZERO) == 0, S2N_ERR_FORK_DETECTION_INIT);
113
+ #endif
114
+
115
+ return S2N_RESULT_OK;
116
+ }
117
+
118
+ static void s2n_pthread_atfork_on_fork(void)
119
+ {
120
+ /* This zeroises the first byte of the memory page pointed to by
121
+ * *zero_on_fork_addr. This is the same byte used as fork event detection
122
+ * sentinel in s2n_get_fork_generation_number(). The same memory page, and in
123
+ * turn, the byte, is also the memory zeroised by the MADV_WIPEONFORK fork
124
+ * detection mechanism.
125
+ *
126
+ * Aquire locks to be on the safe side. We want to avoid the checks in
127
+ * s2n_get_fork_generation_number() getting executed before setting the sentinel
128
+ * flag. The write lock prevents any other thread from owning any other type
129
+ * of lock.
130
+ *
131
+ * pthread_atfork_on_fork() cannot return errors. Hence, there is no way to
132
+ * gracefully recover if [un]locking fails.
133
+ */
134
+ if (pthread_rwlock_wrlock(&fgn_state.fork_detection_rw_lock) != 0) {
135
+ printf("pthread_rwlock_wrlock() failed. Aborting.\n");
136
+ abort();
137
+ }
138
+
139
+ if (fgn_state.zero_on_fork_addr == NULL) {
140
+ printf("fgn_state.zero_on_fork_addr is NULL. Aborting.\n");
141
+ abort();
142
+ }
143
+ *fgn_state.zero_on_fork_addr = 0;
144
+
145
+ if (pthread_rwlock_unlock(&fgn_state.fork_detection_rw_lock) != 0) {
146
+ printf("pthread_rwlock_unlock() failed. Aborting.\n");
147
+ abort();
148
+ }
149
+ }
150
+
151
+ static S2N_RESULT s2n_inititalise_pthread_atfork(void)
152
+ {
153
+ /* Register the fork handler pthread_atfork_on_fork that is excuted in the
154
+ * child process after a fork.
155
+ */
156
+ RESULT_ENSURE(pthread_atfork(NULL, NULL, s2n_pthread_atfork_on_fork) == 0, S2N_ERR_FORK_DETECTION_INIT);
157
+
158
+ return S2N_RESULT_OK;
159
+ }
160
+
161
+ static S2N_RESULT s2n_initialise_fork_detection_methods_try(void *addr, long page_size)
162
+ {
163
+ RESULT_GUARD_PTR(addr);
164
+
165
+ /* Some systems don't define MADV_WIPEONFORK in sys/mman.h but the kernel
166
+ * still supports the mechanism (AL2 being a prime example). Likely because
167
+ * glibc on the system is old. We might be able to include kernel header
168
+ * files directly, that define MADV_WIPEONFORK, conditioning on specific
169
+ * OS's. But it is a mess. A more reliable method is to probe the system, at
170
+ * run-time, whether madvise supports the MADV_WIPEONFORK advice. However,
171
+ * the method to probe for this feature is equivalent to actually attempting
172
+ * to initialise the MADV_WIPEONFORK fork detection. Compare with
173
+ * probe_madv_wipeonfork_support() (used for testing).
174
+ *
175
+ * Instead, we apply best-effort to initialise the MADV_WIPEONFORK fork
176
+ * detection and otherwise always require pthread_atfork to be initialised.
177
+ * We also currently always apply prediction resistance. So, this should be
178
+ * a safe default.
179
+ */
180
+ if (ignore_wipeonfork_or_inherit_zero_method_for_testing == false) {
181
+ RESULT_GUARD(s2n_initialise_wipeonfork_best_effort(addr, page_size));
182
+ }
183
+
184
+ if (ignore_wipeonfork_or_inherit_zero_method_for_testing == false) {
185
+ RESULT_GUARD(s2n_initialise_inherit_zero(addr, page_size));
186
+ }
187
+
188
+ if (ignore_pthread_atfork_method_for_testing == false) {
189
+ RESULT_GUARD(s2n_inititalise_pthread_atfork());
190
+ }
191
+
192
+ fgn_state.zero_on_fork_addr = addr;
193
+ *fgn_state.zero_on_fork_addr = S2N_NO_FORK_EVENT;
194
+ fgn_state.is_fork_detection_enabled = true;
195
+
196
+ return S2N_RESULT_OK;
197
+ }
198
+
199
+ static S2N_RESULT s2n_setup_mapping(void **addr, long *page_size) {
200
+
201
+ *page_size = sysconf(_SC_PAGESIZE);
202
+ RESULT_ENSURE_GT(*page_size, 0);
203
+
204
+ *addr = mmap(NULL, (size_t) *page_size, PROT_READ | PROT_WRITE,
205
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
206
+ RESULT_ENSURE_NE(*addr, MAP_FAILED);
207
+
208
+ return S2N_RESULT_OK;
209
+ }
210
+
211
+ static void s2n_initialise_fork_detection_methods(void)
212
+ {
213
+ void *addr = MAP_FAILED;
214
+ long page_size = 0;
215
+
216
+ /* Only used to disable fork detection mechanisms during testing. */
217
+ if (ignore_wipeonfork_or_inherit_zero_method_for_testing == true &&
218
+ ignore_pthread_atfork_method_for_testing == true) {
219
+
220
+ ignore_fork_detection_for_testing = true;
221
+ return;
222
+ }
223
+
224
+ if (s2n_result_is_error(s2n_setup_mapping(&addr, &page_size)) == true) {
225
+ return;
226
+ }
227
+
228
+ /* Now we know that we have some memory mapped. Try to initialise fork
229
+ * detection methods. Unmap the memory if we fail for some reason.
230
+ */
231
+ if (s2n_result_is_error(s2n_initialise_fork_detection_methods_try(addr, page_size)) == true) {
232
+ /* No reason to verify return value of munmap() since we can't use that
233
+ * information for anything anyway. */
234
+ munmap(addr, (size_t) page_size);
235
+ addr = NULL;
236
+ fgn_state.zero_on_fork_addr = NULL;
237
+ fgn_state.is_fork_detection_enabled = false;
238
+ }
239
+ }
240
+
241
+ /* s2n_get_fork_generation_number returns S2N_RESULT_OK on success and
242
+ * S2N_RESULT_ERROR otherwise.
243
+ *
244
+ * On success, returns the current fork generation number in
245
+ * return_fork_generation_number. Caller must synchronise access to
246
+ * return_fork_generation_number.
247
+ */
248
+ S2N_RESULT s2n_get_fork_generation_number(uint64_t *return_fork_generation_number)
249
+ {
250
+ RESULT_ENSURE(pthread_once(&fgn_state.fork_detection_once, s2n_initialise_fork_detection_methods) == 0, S2N_ERR_FORK_DETECTION_INIT);
251
+
252
+ if (ignore_fork_detection_for_testing == true) {
253
+ /* Fork detection is meant to be disabled. Hence, return success.
254
+ * This should only happen during testing.
255
+ */
256
+ RESULT_ENSURE(s2n_in_unit_test(), S2N_ERR_NOT_IN_UNIT_TEST);
257
+ return S2N_RESULT_OK;
258
+ }
259
+
260
+ RESULT_ENSURE(fgn_state.is_fork_detection_enabled == true, S2N_ERR_FORK_DETECTION_INIT);
261
+
262
+ /* In most cases, we would not need to increment the fork generation number.
263
+ * So, it is cheaper, in the expected case, to take an optimistic read lock
264
+ * and later aquire a write lock if needed.
265
+ * Note that we set the returned fgn before checking for a fork event. We
266
+ * need to do this because thread execution might change between releasing
267
+ * the read lock and taking the write lock. In that time span, another
268
+ * thread can reset the fork event detection sentinel and we return from
269
+ * s2n_get_fork_generation_number() without setting the returned fgn
270
+ * appropriately.
271
+ */
272
+ RESULT_ENSURE(pthread_rwlock_rdlock(&fgn_state.fork_detection_rw_lock) == 0, S2N_ERR_RETRIEVE_FORK_GENERATION_NUMBER);
273
+ *return_fork_generation_number = fgn_state.current_fork_generation_number;
274
+ if (*fgn_state.zero_on_fork_addr != S2N_FORK_EVENT) {
275
+ /* No fork event detected. */
276
+ RESULT_ENSURE(pthread_rwlock_unlock(&fgn_state.fork_detection_rw_lock) == 0, S2N_ERR_RETRIEVE_FORK_GENERATION_NUMBER);
277
+ return S2N_RESULT_OK;
278
+ }
279
+ RESULT_ENSURE(pthread_rwlock_unlock(&fgn_state.fork_detection_rw_lock) == 0, S2N_ERR_RETRIEVE_FORK_GENERATION_NUMBER);
280
+
281
+ /* We are mutating the process-global, cached fork generation number. Need
282
+ * to acquire the write lock for that. Set returned fgn before checking the
283
+ * if condition with the same reasons as above.
284
+ */
285
+ RESULT_ENSURE(pthread_rwlock_wrlock(&fgn_state.fork_detection_rw_lock) == 0, S2N_ERR_RETRIEVE_FORK_GENERATION_NUMBER);
286
+ *return_fork_generation_number = fgn_state.current_fork_generation_number;
287
+ if (*fgn_state.zero_on_fork_addr == S2N_FORK_EVENT) {
288
+ /* Fork event has been detected; reset sentinel, increment cached fork
289
+ * generation number (which is now "current" in this child process), and
290
+ * write incremented fork generation number to the output parameter.
291
+ */
292
+ *fgn_state.zero_on_fork_addr = S2N_NO_FORK_EVENT;
293
+ fgn_state.current_fork_generation_number = fgn_state.current_fork_generation_number + 1;
294
+ *return_fork_generation_number = fgn_state.current_fork_generation_number;
295
+ }
296
+ RESULT_ENSURE(pthread_rwlock_unlock(&fgn_state.fork_detection_rw_lock) == 0, S2N_ERR_RETRIEVE_FORK_GENERATION_NUMBER);
297
+
298
+ return S2N_RESULT_OK;
299
+ }
300
+
301
+ static void s2n_cleanup_cb_munmap(void *probe_addr)
302
+ {
303
+ munmap(probe_addr, (size_t) sysconf(_SC_PAGESIZE));
304
+ }
305
+
306
+ /* Run-time probe checking whether the system supports the MADV_WIPEONFORK fork
307
+ * detection mechanism.
308
+ */
309
+ static S2N_RESULT s2n_probe_madv_wipeonfork_support(void) {
310
+
311
+ bool result = false;
312
+
313
+ /* It is not an error to call munmap on a range that does not contain any
314
+ * mapped pages.
315
+ */
316
+ DEFER_CLEANUP(void *probe_addr = MAP_FAILED, s2n_cleanup_cb_munmap);
317
+ long page_size = 0;
318
+
319
+ RESULT_GUARD(s2n_setup_mapping(&probe_addr, &page_size));
320
+
321
+ #if defined(S2N_MADVISE_SUPPORTED)
322
+ /* Some versions of qemu (up to at least 5.0.0-rc4, see
323
+ * linux-user/syscall.c) ignore invalid advice arguments. Hence, we first
324
+ * verify that madvise() rejects advice arguments it doesn't know about.
325
+ */
326
+ RESULT_ENSURE_NE(madvise(probe_addr, (size_t) page_size, -1), 0);
327
+ RESULT_ENSURE_EQ(madvise(probe_addr, (size_t) page_size, MADV_WIPEONFORK), 0);
328
+
329
+ result = true;
330
+ #endif
331
+
332
+ RESULT_ENSURE_EQ(result, true);
333
+
334
+ return S2N_RESULT_OK;
335
+ }
336
+
337
+ bool s2n_is_madv_wipeonfork_supported(void)
338
+ {
339
+ return s2n_result_is_ok(s2n_probe_madv_wipeonfork_support());
340
+ }
341
+
342
+ bool s2n_is_map_inherit_zero_supported(void)
343
+ {
344
+ #if defined(S2N_MINHERIT_SUPPORTED) && defined(MAP_INHERIT_ZERO)
345
+ return true
346
+ #else
347
+ return false;
348
+ #endif
349
+ }
350
+
351
+ /* Use for testing only */
352
+ S2N_RESULT s2n_ignore_wipeonfork_and_inherit_zero_for_testing(void) {
353
+ RESULT_ENSURE(s2n_in_unit_test(), S2N_ERR_NOT_IN_UNIT_TEST);
354
+
355
+ ignore_wipeonfork_or_inherit_zero_method_for_testing = true;
356
+
357
+ return S2N_RESULT_OK;
358
+ }
359
+
360
+ S2N_RESULT s2n_ignore_pthread_atfork_for_testing(void) {
361
+ RESULT_ENSURE(s2n_in_unit_test(), S2N_ERR_NOT_IN_UNIT_TEST);
362
+
363
+ ignore_pthread_atfork_method_for_testing = true;
364
+
365
+ return S2N_RESULT_OK;
366
+ }
367
+
@@ -0,0 +1,28 @@
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
+ #pragma once
17
+
18
+ #include <stdint.h>
19
+
20
+ #include "utils/s2n_result.h"
21
+
22
+ S2N_RESULT s2n_get_fork_generation_number(uint64_t *return_fork_generation_number);
23
+ bool s2n_is_madv_wipeonfork_supported(void);
24
+ bool s2n_is_map_inherit_zero_supported(void);
25
+
26
+ /* Use for testing only */
27
+ S2N_RESULT s2n_ignore_wipeonfork_and_inherit_zero_for_testing(void);
28
+ S2N_RESULT s2n_ignore_pthread_atfork_for_testing(void);
@@ -128,10 +128,10 @@
128
128
  * Ensures the `result` is `S2N_RESULT_OK`, otherwise the function will return an error signal
129
129
  *
130
130
  * `RESULT_PRECONDITION` should be used at the beginning of a function to make assertions about
131
- * the provided arguments. By default, it is functionally equivalent to `RESULT_GUARD_RESULT(result)`
131
+ * the provided arguments. By default, it is functionally equivalent to `RESULT_GUARD(result)`
132
132
  * but can be altered by a testing environment to provide additional guarantees.
133
133
  */
134
- #define RESULT_PRECONDITION(result) RESULT_GUARD_RESULT(__S2N_ENSURE_PRECONDITION((result)))
134
+ #define RESULT_PRECONDITION(result) RESULT_GUARD(__S2N_ENSURE_PRECONDITION((result)))
135
135
 
136
136
  /**
137
137
  * Ensures the `result` is `S2N_RESULT_OK`, otherwise the function will return an error signal
@@ -140,11 +140,11 @@
140
140
  * In release mode, the check is removed.
141
141
  *
142
142
  * `RESULT_POSTCONDITION` should be used at the end of a function to make assertions about
143
- * the resulting state. In debug mode, it is functionally equivalent to `RESULT_GUARD_RESULT(result)`.
143
+ * the resulting state. In debug mode, it is functionally equivalent to `RESULT_GUARD(result)`.
144
144
  * In production builds, it becomes a no-op. This can also be altered by a testing environment
145
145
  * to provide additional guarantees.
146
146
  */
147
- #define RESULT_POSTCONDITION(result) RESULT_GUARD_RESULT(__S2N_ENSURE_POSTCONDITION((result)))
147
+ #define RESULT_POSTCONDITION(result) RESULT_GUARD(__S2N_ENSURE_POSTCONDITION((result)))
148
148
 
149
149
  /**
150
150
  * Performs a safer memcpy.
@@ -185,11 +185,6 @@
185
185
  */
186
186
  #define RESULT_GUARD_OSSL(result, error) __S2N_ENSURE((result) == _OSSL_SUCCESS, RESULT_BAIL(error))
187
187
 
188
- /**
189
- * Ensures `s2n_result_is_ok(result)`, otherwise the function will return `S2N_RESULT_ERROR`
190
- */
191
- #define RESULT_GUARD_RESULT(result) __S2N_ENSURE(s2n_result_is_ok(result), return S2N_RESULT_ERROR)
192
-
193
188
  /**
194
189
  * Ensures `(result) >= S2N_SUCCESS`, otherwise the function will return `S2N_RESULT_ERROR`
195
190
  */
@@ -393,16 +388,15 @@
393
388
  #define POSIX_GUARD_OSSL(result, error) __S2N_ENSURE((result) == _OSSL_SUCCESS, POSIX_BAIL(error))
394
389
 
395
390
  /**
391
+ * DEPRECATED: all methods (except those in s2n.h) should return s2n_result.
392
+ *
396
393
  * Ensures `s2n_result_is_ok(result)`, otherwise the function will return `S2N_FAILURE`
397
394
  */
398
395
  #define POSIX_GUARD_RESULT(result) __S2N_ENSURE(s2n_result_is_ok(result), return S2N_FAILURE)
399
396
 
400
397
  /**
401
- * Ensures `(result) >= S2N_SUCCESS`, otherwise the function will return `S2N_FAILURE`
402
- */
403
- #define POSIX_GUARD_POSIX(result) __S2N_ENSURE((result) >= S2N_SUCCESS, return S2N_FAILURE)
404
-
405
- /**
398
+ * DEPRECATED: all methods (except those in s2n.h) should return s2n_result.
399
+ *
406
400
  * Ensures `(result) != NULL`, otherwise the function will return `S2N_FAILURE`
407
401
  *
408
402
  * Does not set s2n_errno to S2N_ERR_NULL, so is NOT a direct replacement for POSIX_ENSURE_REF.
@@ -567,7 +561,7 @@
567
561
  * * The size of the data pointed to by both the `destination` and `source` parameters,
568
562
  * shall be at least `len` bytes.
569
563
  */
570
- #define PTR_CHECKED_MEMCPY(destination, source, len) __S2N_ENSURE_SAFE_MEMCPY((destination), (source), (len), PTR_GUARD_PTR)
564
+ #define PTR_CHECKED_MEMCPY(destination, source, len) __S2N_ENSURE_SAFE_MEMCPY((destination), (source), (len), PTR_GUARD)
571
565
 
572
566
  /**
573
567
  * DEPRECATED: all methods (except those in s2n.h) should return s2n_result.
@@ -600,19 +594,16 @@
600
594
  #define PTR_GUARD_OSSL(result, error) __S2N_ENSURE((result) == _OSSL_SUCCESS, PTR_BAIL(error))
601
595
 
602
596
  /**
597
+ * DEPRECATED: all methods (except those in s2n.h) should return s2n_result.
598
+ *
603
599
  * Ensures `s2n_result_is_ok(result)`, otherwise the function will return `NULL`
604
600
  */
605
601
  #define PTR_GUARD_RESULT(result) __S2N_ENSURE(s2n_result_is_ok(result), return NULL)
606
602
 
607
603
  /**
604
+ * DEPRECATED: all methods (except those in s2n.h) should return s2n_result.
605
+ *
608
606
  * Ensures `(result) >= S2N_SUCCESS`, otherwise the function will return `NULL`
609
607
  */
610
608
  #define PTR_GUARD_POSIX(result) __S2N_ENSURE((result) >= S2N_SUCCESS, return NULL)
611
609
 
612
- /**
613
- * Ensures `(result) != NULL`, otherwise the function will return `NULL`
614
- *
615
- * Does not set s2n_errno to S2N_ERR_NULL, so is NOT a direct replacement for PTR_ENSURE_REF.
616
- */
617
- #define PTR_GUARD_PTR(result) __S2N_ENSURE((result) != NULL, return NULL)
618
-