aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrobot-contrib <robot-contrib@yandex-team.com>2022-07-09 10:40:08 +0300
committerrobot-contrib <robot-contrib@yandex-team.com>2022-07-09 10:40:08 +0300
commit22acf19be42357b6bb0e7d601b0dc28695191463 (patch)
treea35a222fffb28fcf8a82dd7efe67f2276bfd1858
parent7a7d303e197aa7e4f43c61cc289d8652df38ab43 (diff)
downloadydb-22acf19be42357b6bb0e7d601b0dc28695191463.tar.gz
Update contrib/restricted/aws/s2n to 1.3.16
-rw-r--r--contrib/restricted/aws/s2n/CMakeLists.darwin.txt2
-rw-r--r--contrib/restricted/aws/s2n/CMakeLists.linux.txt2
-rw-r--r--contrib/restricted/aws/s2n/README.md13
-rw-r--r--contrib/restricted/aws/s2n/api/s2n.h45
-rw-r--r--contrib/restricted/aws/s2n/crypto/s2n_composite_cipher_aes_sha.c23
-rw-r--r--contrib/restricted/aws/s2n/pq-crypto/sike_r1/ec_isogeny_r1.c50
-rw-r--r--contrib/restricted/aws/s2n/pq-crypto/sike_r1/fpx_r1.c11
-rw-r--r--contrib/restricted/aws/s2n/pq-crypto/sike_r1/sidh_r1.c48
-rw-r--r--contrib/restricted/aws/s2n/pq-crypto/sike_r1/sike_r1_kem.c8
-rw-r--r--contrib/restricted/aws/s2n/pq-crypto/sike_r1/sike_r1_namespace.h3
-rw-r--r--contrib/restricted/aws/s2n/pq-crypto/sike_r3/sikep434r3_ec_isogeny.c52
-rw-r--r--contrib/restricted/aws/s2n/pq-crypto/sike_r3/sikep434r3_ec_isogeny.h6
-rw-r--r--contrib/restricted/aws/s2n/pq-crypto/sike_r3/sikep434r3_fpx.c34
-rw-r--r--contrib/restricted/aws/s2n/pq-crypto/sike_r3/sikep434r3_fpx.h6
-rw-r--r--contrib/restricted/aws/s2n/pq-crypto/sike_r3/sikep434r3_kem.c9
-rw-r--r--contrib/restricted/aws/s2n/pq-crypto/sike_r3/sikep434r3_sidh.c53
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_client_supported_versions.c9
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_extension_type.c10
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_server_key_share.c2
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_server_psk.c4
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_server_supported_versions.c12
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_cipher_preferences.c27
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_cipher_preferences.h1
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_cipher_suites.c26
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_client_hello.c19
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_connection.h3
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_ecc_preferences.c18
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_ecc_preferences.h1
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_handshake_io.c5
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_security_policies.c27
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_security_policies.h1
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_server_extensions.c11
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_server_hello.c70
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_signature_scheme.c22
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_signature_scheme.h1
-rw-r--r--contrib/restricted/aws/s2n/utils/s2n_random.c180
36 files changed, 663 insertions, 151 deletions
diff --git a/contrib/restricted/aws/s2n/CMakeLists.darwin.txt b/contrib/restricted/aws/s2n/CMakeLists.darwin.txt
index 979301a5d6..4c0756bee7 100644
--- a/contrib/restricted/aws/s2n/CMakeLists.darwin.txt
+++ b/contrib/restricted/aws/s2n/CMakeLists.darwin.txt
@@ -52,11 +52,11 @@ target_sources(restricted-aws-s2n PRIVATE
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/pq-crypto/bike_r3/gf2x_mul_avx512.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/pq-crypto/bike_r3/sampling_avx512.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/pq-crypto/bike_r3/gf2x_mul_base_vpclmul.c
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_basemul_avx2.S
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_fq_avx2.S
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_invntt_avx2.S
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_ntt_avx2.S
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_shuffle_avx2.S
- ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_basemul_avx2.S
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/crypto/s2n_aead_cipher_aes_gcm.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/crypto/s2n_aead_cipher_chacha20_poly1305.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/crypto/s2n_cbc_cipher_3des.c
diff --git a/contrib/restricted/aws/s2n/CMakeLists.linux.txt b/contrib/restricted/aws/s2n/CMakeLists.linux.txt
index a431e0ec07..40323364f9 100644
--- a/contrib/restricted/aws/s2n/CMakeLists.linux.txt
+++ b/contrib/restricted/aws/s2n/CMakeLists.linux.txt
@@ -55,11 +55,11 @@ target_sources(restricted-aws-s2n PRIVATE
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/pq-crypto/bike_r3/sampling_avx512.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/pq-crypto/bike_r3/gf2x_mul_base_vpclmul.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/pq-crypto/sike_r3/sikep434r3_fp_x64_asm.S
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_basemul_avx2.S
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_fq_avx2.S
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_invntt_avx2.S
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_ntt_avx2.S
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_shuffle_avx2.S
- ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_basemul_avx2.S
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/crypto/s2n_aead_cipher_aes_gcm.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/crypto/s2n_aead_cipher_chacha20_poly1305.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/crypto/s2n_cbc_cipher_3des.c
diff --git a/contrib/restricted/aws/s2n/README.md b/contrib/restricted/aws/s2n/README.md
index 6456d973d5..c7be8baa46 100644
--- a/contrib/restricted/aws/s2n/README.md
+++ b/contrib/restricted/aws/s2n/README.md
@@ -52,7 +52,7 @@ CTEST_PARALLEL_LEVEL=$(nproc) ninja -C build test
### Amazonlinux2
-Install dependancies with `./codebuild/bin/install_al2_dependencies.sh` after cloning.
+Install dependencies with `./codebuild/bin/install_al2_dependencies.sh` after cloning.
```sh
git clone https://github.com/${YOUR_GITHUB_ACCOUNT_NAME}/s2n-tls.git
@@ -62,12 +62,19 @@ cmake --build ./build -j $(nproc)
CTEST_PARALLEL_LEVEL=$(nproc) make -C build test
```
-
## Have a Question?
If you have any questions about Submitting PR's, Opening Issues, s2n-tls API usage, or something similar, we have a public chatroom available here to answer your questions: https://gitter.im/awslabs/s2n
Otherwise, if you think you might have found a security impacting issue, please instead follow [our Security Notification Process.](#security-issue-notifications)
+## Documentation
+
+s2n-tls uses [Doxygen](https://doxygen.nl/index.html) to document its public API. The latest s2n-tls documentation can be found on [GitHub pages](https://aws.github.io/s2n-tls/doxygen/).
+
+Documentation for older versions or branches of s2n-tls can be generated locally. To generate the documentation, install doxygen and run `doxygen docs/doxygen/Doxyfile`. The doxygen documentation can now be found at `docs/doxygen/output/html/index.html`.
+
+Doxygen installation instructions are available at the [Doxygen](https://doxygen.nl/download.html) webpage.
+
## Using s2n-tls
The s2n-tls I/O APIs are designed to be intuitive to developers familiar with the widely-used POSIX I/O APIs, and s2n-tls supports blocking, non-blocking, and full-duplex I/O. Additionally there are no locks or mutexes within s2n-tls.
@@ -95,7 +102,7 @@ int bytes_written;
bytes_written = s2n_send(conn, "Hello World", sizeof("Hello World"), &blocked);
```
-For details on building the s2n-tls library and how to use s2n-tls in an application you are developing, see the [API Reference](https://github.com/aws/s2n-tls/blob/main/docs/USAGE-GUIDE.md).
+For details on building the s2n-tls library and how to use s2n-tls in an application you are developing, see the [usage guide](https://github.com/aws/s2n-tls/blob/main/docs/USAGE-GUIDE.md).
## s2n-tls features
diff --git a/contrib/restricted/aws/s2n/api/s2n.h b/contrib/restricted/aws/s2n/api/s2n.h
index adc970386c..f1395151db 100644
--- a/contrib/restricted/aws/s2n/api/s2n.h
+++ b/contrib/restricted/aws/s2n/api/s2n.h
@@ -136,16 +136,32 @@ extern int *s2n_errno_location(void);
*
* This enum is optimized for use in C switch statements. Each value in the enum represents
* an error "category".
+ *
+ * s2n-tls organizes errors into different "types" to allow applications to handle error
+ * values without catching all possibilities. Applications using non-blocking I/O should check
+ * the error type to determine if the I/O operation failed because it would block or for some other
+ * error. To retrieve the type for a given error use `s2n_error_get_type()`. Applications should
+ * perform any error handling logic using these high level types.
+ *
+ * See the [Error Handling](https://github.com/aws/s2n-tls/blob/main/docs/USAGE-GUIDE.md#error-handling) section for how the errors should be interpreted.
*/
typedef enum {
- S2N_ERR_T_OK=0,
- S2N_ERR_T_IO,
- S2N_ERR_T_CLOSED,
- S2N_ERR_T_BLOCKED,
- S2N_ERR_T_ALERT,
- S2N_ERR_T_PROTO,
- S2N_ERR_T_INTERNAL,
- S2N_ERR_T_USAGE
+ /** No error */
+ S2N_ERR_T_OK=0,
+ /** Underlying I/O operation failed, check system errno */
+ S2N_ERR_T_IO,
+ /** EOF */
+ S2N_ERR_T_CLOSED,
+ /** Underlying I/O operation would block */
+ S2N_ERR_T_BLOCKED,
+ /** Incoming Alert */
+ S2N_ERR_T_ALERT,
+ /** Failure in some part of the TLS protocol. Ex: CBC verification failure */
+ S2N_ERR_T_PROTO,
+ /** Error internal to s2n-tls. A precondition could have failed. */
+ S2N_ERR_T_INTERNAL,
+ /** User input error. Ex: Providing an invalid cipher preference version */
+ S2N_ERR_T_USAGE
} s2n_error_type;
/**
@@ -176,6 +192,13 @@ struct s2n_connection;
* prior to 1.1.x. This allows applications or languages that also init OpenSSL to interoperate
* with S2N.
*
+ * @warning This function must be called BEFORE s2n_init() to have any effect. It will return an error
+ * if s2n is already initialized.
+ *
+ * @note If you disable this and are using a version of OpenSSL/libcrypto < 1.1.x, you will
+ * be responsible for library init and cleanup (specifically `OPENSSL_add_all_algorithms()`
+ * or `OPENSSL_crypto_init()`, and EVP_* APIs will not be usable unless the library is initialized.
+ *
* @returns S2N_SUCCESS on success. S2N_FAILURE on failure
*/
S2N_API
@@ -185,6 +208,12 @@ extern int s2n_crypto_disable_init(void);
* Prevents S2N from installing an atexit handler, which allows safe shutdown of S2N from within a
* re-entrant shared library
*
+ * @warning This function must be called BEFORE s2n_init() to have any effect. It will return an error
+ * if s2n is already initialized.
+ *
+ * @note This will cause `s2n_cleanup` to do complete cleanup of s2n-tls when called from the main
+ * thread (the thread `s2n_init` was called from).
+ *
* @returns S2N_SUCCESS on success. S2N_FAILURE on failure
*/
S2N_API
diff --git a/contrib/restricted/aws/s2n/crypto/s2n_composite_cipher_aes_sha.c b/contrib/restricted/aws/s2n/crypto/s2n_composite_cipher_aes_sha.c
index 3be8de854f..353c841f87 100644
--- a/contrib/restricted/aws/s2n/crypto/s2n_composite_cipher_aes_sha.c
+++ b/contrib/restricted/aws/s2n/crypto/s2n_composite_cipher_aes_sha.c
@@ -26,16 +26,19 @@
#include "utils/s2n_safety.h"
#include "utils/s2n_blob.h"
-/* LibreSSL, BoringSSL and AWS-LC support the cipher, but the interface is different from Openssl's. We
- * should define a separate s2n_cipher struct for LibreSSL, BoringSSL and AWS-LC.
+/* LibreSSL and BoringSSL support the cipher, but the interface is different from Openssl's. We
+ * should define a separate s2n_cipher struct for LibreSSL and BoringSSL.
*/
-#if !defined(LIBRESSL_VERSION_NUMBER) && !defined(OPENSSL_IS_BORINGSSL) && !defined(OPENSSL_IS_AWSLC)
+#if !defined(LIBRESSL_VERSION_NUMBER) && !defined(OPENSSL_IS_BORINGSSL)
/* Symbols for AES-SHA1-CBC composite ciphers were added in Openssl 1.0.1
* These composite ciphers exhibit erratic behavior in LibreSSL releases.
*/
-#if S2N_OPENSSL_VERSION_AT_LEAST(1,0,1)
+#if S2N_OPENSSL_VERSION_AT_LEAST(1,0,1)
#define S2N_AES_SHA1_COMPOSITE_AVAILABLE
#endif
+#if defined(AWSLC_API_VERSION) && (AWSLC_API_VERSION <= 17)
+#undef S2N_AES_SHA1_COMPOSITE_AVAILABLE
+#endif
/* Symbols for AES-SHA256-CBC composite ciphers were added in Openssl 1.0.2
* See https://www.openssl.org/news/cl102.txt
* These composite ciphers exhibit erratic behavior in LibreSSL releases.
@@ -43,7 +46,9 @@
#if S2N_OPENSSL_VERSION_AT_LEAST(1,0,2)
#define S2N_AES_SHA256_COMPOSITE_AVAILABLE
#endif
-
+#if defined(AWSLC_API_VERSION) && (AWSLC_API_VERSION <= 17)
+#undef S2N_AES_SHA256_COMPOSITE_AVAILABLE
+#endif
#endif
/* Silly accessors, but we avoid using version macro guards in multiple places */
@@ -125,11 +130,11 @@ static uint8_t s2n_composite_cipher_aes256_sha256_available(void)
static int s2n_composite_cipher_aes_sha_initial_hmac(struct s2n_session_key *key, uint8_t *sequence_number, uint8_t content_type,
uint16_t protocol_version, uint16_t payload_and_eiv_len, int *extra)
{
- /* BoringSSL and AWS-LC do not support these composite ciphers with the existing EVP API, and they took out the
- * constants used below. This method should never be called with BoringSSL or AWS-LC because the isAvaliable checked
- * will fail. Instead of defining a possibly dangerous default or hard coding this to 0x16 error out with BoringSSL and AWS-LC.
+ /* BoringSSL and AWS-LC(AWSLC_API_VERSION <= 17) do not support these composite ciphers with the existing EVP API, and they took out the
+ * constants used below. This method should never be called with BoringSSL or AWS-LC(AWSLC_API_VERSION <= 17) because the isAvaliable checked
+ * will fail. Instead of defining a possibly dangerous default or hard coding this to 0x16 error out with BoringSSL and AWS-LC(AWSLC_API_VERSION <= 17).
*/
-#if defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC)
+#if defined(OPENSSL_IS_BORINGSSL) || (defined(AWSLC_API_VERSION) && (AWSLC_API_VERSION <= 17))
POSIX_BAIL(S2N_ERR_NO_SUPPORTED_LIBCRYPTO_API);
#else
uint8_t ctrl_buf[S2N_TLS12_AAD_LEN];
diff --git a/contrib/restricted/aws/s2n/pq-crypto/sike_r1/ec_isogeny_r1.c b/contrib/restricted/aws/s2n/pq-crypto/sike_r1/ec_isogeny_r1.c
index b83e7a3ae3..50dfd68373 100644
--- a/contrib/restricted/aws/s2n/pq-crypto/sike_r1/ec_isogeny_r1.c
+++ b/contrib/restricted/aws/s2n/pq-crypto/sike_r1/ec_isogeny_r1.c
@@ -31,11 +31,10 @@ void xDBLe(const point_proj_t P, point_proj_t Q, const f2elm_t *A24plus, const f
{ // Computes [2^e](X:Z) on Montgomery curve with projective constant via e repeated doublings.
// Input: projective Montgomery x-coordinates P = (XP:ZP), such that xP=XP/ZP and Montgomery curve constants A+2C and 4C.
// Output: projective Montgomery x-coordinates Q <- (2^e)*P.
- int i;
copy_words((const digit_t*)P, (digit_t*)Q, 2*2*NWORDS_FIELD);
- for (i = 0; i < e; i++) {
+ for (int i = 0; i < e; i++) {
xDBL(Q, Q, A24plus, C24);
}
}
@@ -121,11 +120,10 @@ void xTPLe(const point_proj_t P, point_proj_t Q, const f2elm_t *A24minus, const
{ // Computes [3^e](X:Z) on Montgomery curve with projective constant via e repeated triplings.
// Input: projective Montgomery x-coordinates P = (XP:ZP), such that xP=XP/ZP and Montgomery curve constants A24plus = A+2C and A24minus = A-2C.
// Output: projective Montgomery x-coordinates Q <- (3^e)*P.
- int i;
copy_words((const digit_t*)P, (digit_t*)Q, 2*2*NWORDS_FIELD);
- for (i = 0; i < e; i++) {
+ for (int i = 0; i < e; i++) {
xTPL(Q, Q, A24minus, A24plus);
}
}
@@ -344,3 +342,47 @@ static void LADDER3PT(const f2elm_t *xP, const f2elm_t *xQ, const f2elm_t *xPQ,
fp2mul_mont(&R2->X, &R->Z, &R2->X);
}
}
+
+void xTPL_fast(const point_proj_t P, point_proj_t Q, const f2elm_t *A2)
+{ // Montgomery curve (E: y^2 = x^3 + A*x^2 + x) x-only tripling at a cost of 5M + 6S + 11A.
+ // Input : projective Montgomery x-coordinates P = (X:Z), where x=X/Z and Montgomery curve constant A/2.
+ // Output: projective Montgomery x-coordinates Q = 3*P = (X3:Z3).
+ f2elm_t _t1, _t2, _t3, _t4;
+ f2elm_t *t1=&_t1, *t2=&_t2, *t3=&_t3, *t4=&_t4;
+
+ fp2sqr_mont(&P->X, t1); // t1 = x^2
+ fp2sqr_mont(&P->Z, t2); // t2 = z^2
+ fp2add(t1, t2, t3); // t3 = t1 + t2
+ fp2add(&P->X, &P->Z, t4); // t4 = x + z
+ fp2sqr_mont(t4, t4); // t4 = t4^2
+ fp2sub(t4, t3, t4); // t4 = t4 - t3
+ fp2mul_mont(A2, t4, t4); // t4 = t4*A2
+ fp2add(t3, t4, t4); // t4 = t4 + t3
+ fp2sub(t1, t2, t3); // t3 = t1 - t2
+ fp2sqr_mont(t3, t3); // t3 = t3^2
+ fp2mul_mont(t1, t4, t1); // t1 = t1*t4
+ fp2add(t1, t1, t1); // t1 = 2*t1
+ fp2add(t1, t1, t1); // t1 = 4*t1
+ fp2sub(t1, t3, t1); // t1 = t1 - t3
+ fp2sqr_mont(t1, t1); // t1 = t1^2
+ fp2mul_mont(t2, t4, t2); // t2 = t2*t4
+ fp2add(t2, t2, t2); // t2 = 2*t2
+ fp2add(t2, t2, t2); // t2 = 4*t2
+ fp2sub(t2, t3, t2); // t2 = t2 - t3
+ fp2sqr_mont(t2, t2); // t2 = t2^2
+ fp2mul_mont(&P->X, t2, &Q->X); // x = x*t2
+ fp2mul_mont(&P->Z, t1, &Q->Z); // z = z*t1
+}
+
+
+void xTPLe_fast(point_proj_t P, point_proj_t Q, const f2elm_t *A2, int e)
+{ // Computes [3^e](X:Z) on Montgomery curve with projective constant via e repeated triplings. e triplings in E costs e*(5M + 6S + 11A)
+ // Input: projective Montgomery x-coordinates P = (X:Z), where x=X/Z, Montgomery curve constant A2 = A/2 and the number of triplings e.
+ // Output: projective Montgomery x-coordinates Q <- [3^e]P.
+
+ copy_words((digit_t*)P, (digit_t*)Q, 2 * 2 * NWORDS_FIELD);
+
+ for (int i = 0; i < e; i++) {
+ xTPL_fast(Q, Q, A2);
+ }
+}
diff --git a/contrib/restricted/aws/s2n/pq-crypto/sike_r1/fpx_r1.c b/contrib/restricted/aws/s2n/pq-crypto/sike_r1/fpx_r1.c
index 9661567985..82ae6cfceb 100644
--- a/contrib/restricted/aws/s2n/pq-crypto/sike_r1/fpx_r1.c
+++ b/contrib/restricted/aws/s2n/pq-crypto/sike_r1/fpx_r1.c
@@ -333,6 +333,17 @@ void from_fp2mont(const f2elm_t *ma, f2elm_t *c)
from_mont(ma->e[1], c->e[1]);
}
+unsigned int is_felm_zero(const felm_t x)
+{ // Is x = 0? return 1 (TRUE) if condition is true, 0 (FALSE) otherwise.
+ // SECURITY NOTE: This function does not run in constant-time.
+
+ for (unsigned int i = 0; i < NWORDS_FIELD; i++) {
+ if (x[i] != 0) {
+ return 0;
+ }
+ }
+ return 1;
+}
unsigned int mp_add(const digit_t* a, const digit_t* b, digit_t* c, const unsigned int nwords)
{ // Multiprecision addition, c = a+b, where lng(a) = lng(b) = nwords. Returns the carry bit.
diff --git a/contrib/restricted/aws/s2n/pq-crypto/sike_r1/sidh_r1.c b/contrib/restricted/aws/s2n/pq-crypto/sike_r1/sidh_r1.c
index bdf2834121..3f49fa1461 100644
--- a/contrib/restricted/aws/s2n/pq-crypto/sike_r1/sidh_r1.c
+++ b/contrib/restricted/aws/s2n/pq-crypto/sike_r1/sidh_r1.c
@@ -268,6 +268,49 @@ int EphemeralSecretAgreement_A(const digit_t* PrivateKeyA, const unsigned char*
return S2N_SUCCESS;
}
+int sike_p503_r1_publickey_validation(const f2elm_t *PKB, const f2elm_t *A)
+{ // Public key validation
+ point_proj_t P = { 0 }, Q = { 0 };
+ f2elm_t _A2={0}, _tmp1={0}, _tmp2={0};
+ f2elm_t *A2=&_A2, *tmp1=&_tmp1, *tmp2=&_tmp2;
+
+ // Verify that P and Q generate E_A[3^e_3] by checking that [3^(e_3-1)]P != [+-3^(e_3-1)]Q
+ fp2div2(A, A2);
+ fp2copy(&PKB[0], &P->X);
+ fpcopy((const digit_t*)&Montgomery_one, (digit_t*)&P->Z);
+ fp2copy(&PKB[1], &Q->X);
+ fpcopy((const digit_t*)&Montgomery_one, (digit_t*)&Q->Z);
+
+ xTPLe_fast(P, P, A2, MAX_Bob - 1);
+ xTPLe_fast(Q, Q, A2, MAX_Bob - 1);
+ fp2correction(&P->Z);
+ fp2correction(&Q->Z);
+
+ if ((is_felm_zero((P->Z.e)[0]) && is_felm_zero((P->Z.e)[1])) || (is_felm_zero((Q->Z.e)[0]) && is_felm_zero((Q->Z.e)[1]))) {
+ return 1;
+ }
+
+ fp2mul_mont(&P->X, &Q->Z, tmp1);
+ fp2mul_mont(&P->Z, &Q->X, tmp2);
+ fp2correction(tmp1);
+ fp2correction(tmp2);
+
+ if (memcmp((uint8_t*)tmp1, (uint8_t*)tmp2, FP2_ENCODED_BYTES) == 0) {
+ return 1;
+ }
+
+ // Check that Ord(P) = Ord(Q) = 3^(e_3)
+ xTPL_fast(P, P, A2);
+ xTPL_fast(Q, Q, A2);
+ fp2correction(&P->Z);
+ fp2correction(&Q->Z);
+
+ if (!is_felm_zero((P->Z.e)[0]) || !is_felm_zero((P->Z.e)[1]) || !is_felm_zero((Q->Z.e)[0]) || !is_felm_zero((Q->Z.e)[1])) {
+ return 1;
+ }
+
+ return 0;
+}
int EphemeralSecretAgreement_B(const digit_t* PrivateKeyB, const unsigned char* PublicKeyA, unsigned char* SharedSecretB)
{ // Bob's ephemeral shared secret computation
@@ -292,6 +335,11 @@ int EphemeralSecretAgreement_B(const digit_t* PrivateKeyB, const unsigned char*
fp2add(A, A24minus, A24plus);
fp2sub(A, A24minus, A24minus);
+ // Always perform public key validation before using peer's public key
+ if (sike_p503_r1_publickey_validation(PKB, A) == 1) {
+ return 1;
+ }
+
// Retrieve kernel point
LADDER3PT(&PKB[0], &PKB[1], &PKB[2], PrivateKeyB, BOB, R, A);
diff --git a/contrib/restricted/aws/s2n/pq-crypto/sike_r1/sike_r1_kem.c b/contrib/restricted/aws/s2n/pq-crypto/sike_r1/sike_r1_kem.c
index ee905ca74a..973640e156 100644
--- a/contrib/restricted/aws/s2n/pq-crypto/sike_r1/sike_r1_kem.c
+++ b/contrib/restricted/aws/s2n/pq-crypto/sike_r1/sike_r1_kem.c
@@ -96,13 +96,16 @@ int SIKE_P503_r1_crypto_kem_dec(unsigned char *ss, const unsigned char *ct, cons
unsigned char c0_[SIKE_P503_R1_PUBLIC_KEY_BYTES];
unsigned char temp[SIKE_P503_R1_CIPHERTEXT_BYTES+MSG_BYTES];
unsigned int i;
+ bool dont_copy = 1;
digit_t _sk[SECRETKEY_B_BYTES/sizeof(digit_t)];
memcpy(_sk, sk + MSG_BYTES, SECRETKEY_B_BYTES);
// Decrypt
- EphemeralSecretAgreement_B(_sk, ct, jinvariant_);
+ if (!(EphemeralSecretAgreement_B(_sk, ct, jinvariant_) == 0)) {
+ goto S2N_SIKE_P503_R1_HASHING;
+ }
cshake256_simple(h_, MSG_BYTES, P, jinvariant_, FP2_ENCODED_BYTES);
for (i = 0; i < MSG_BYTES; i++) temp[i] = ct[i + SIKE_P503_R1_PUBLIC_KEY_BYTES] ^ h_[i];
@@ -120,7 +123,8 @@ int SIKE_P503_r1_crypto_kem_dec(unsigned char *ss, const unsigned char *ct, cons
// Note: This step deviates from the NIST supplied code by using constant time operations.
// We only want to copy the data if c0_ and ct are different
- bool dont_copy = s2n_constant_time_equals(c0_, ct, SIKE_P503_R1_PUBLIC_KEY_BYTES);
+ dont_copy = s2n_constant_time_equals(c0_, ct, SIKE_P503_R1_PUBLIC_KEY_BYTES);
+S2N_SIKE_P503_R1_HASHING:
// The last argument to s2n_constant_time_copy_or_dont is dont and thus prevents the copy when non-zero/true
s2n_constant_time_copy_or_dont(temp, sk, MSG_BYTES, dont_copy);
diff --git a/contrib/restricted/aws/s2n/pq-crypto/sike_r1/sike_r1_namespace.h b/contrib/restricted/aws/s2n/pq-crypto/sike_r1/sike_r1_namespace.h
index 68d9b40c4b..b3e37982fa 100644
--- a/contrib/restricted/aws/s2n/pq-crypto/sike_r1/sike_r1_namespace.h
+++ b/contrib/restricted/aws/s2n/pq-crypto/sike_r1/sike_r1_namespace.h
@@ -20,6 +20,8 @@
#define xDBLADD xDBLADD_r1
#define swap_points swap_points_r1
#define LADDER3PT LADDER3PT_r1
+#define xTPL_fast xTPL_fast_r1
+#define xTPLe_fast xTPLe_fast_r1
#define load64 load64_r1
#define store64 store64_r1
#define KeccakF1600_StatePermute KeccakF1600_StatePermute_r1
@@ -39,6 +41,7 @@
#define mp_subfast mp_subfast_r1
#define to_fp2mont to_fp2mont_r1
#define from_fp2mont from_fp2mont_r1
+#define is_felm_zero is_felm_zero_r1
#define mp_add mp_add_r1
#define mp_shiftr1 mp_shiftr1_r1
#define Alice_order Alice_order_r1
diff --git a/contrib/restricted/aws/s2n/pq-crypto/sike_r3/sikep434r3_ec_isogeny.c b/contrib/restricted/aws/s2n/pq-crypto/sike_r3/sikep434r3_ec_isogeny.c
index e5ae4e7c7e..a2e3dd969b 100644
--- a/contrib/restricted/aws/s2n/pq-crypto/sike_r3/sikep434r3_ec_isogeny.c
+++ b/contrib/restricted/aws/s2n/pq-crypto/sike_r3/sikep434r3_ec_isogeny.c
@@ -33,11 +33,9 @@ void xDBL(const point_proj_t P, point_proj_t Q, const f2elm_t *A24plus, const f2
* Output: projective Montgomery x-coordinates Q <- (2^e)*P. */
void xDBLe(const point_proj_t P, point_proj_t Q, const f2elm_t *A24plus, const f2elm_t *C24, const int e)
{
- int i;
-
copy_words((const digit_t*)P, (digit_t*)Q, 2*2*S2N_SIKE_P434_R3_NWORDS_FIELD);
- for (i = 0; i < e; i++) {
+ for (int i = 0; i < e; i++) {
xDBL(Q, Q, A24plus, C24);
}
}
@@ -121,11 +119,9 @@ void xTPL(const point_proj_t P, point_proj_t Q, const f2elm_t *A24minus, const f
* Output: projective Montgomery x-coordinates Q <- (3^e)*P. */
void xTPLe(const point_proj_t P, point_proj_t Q, const f2elm_t *A24minus, const f2elm_t *A24plus, const int e)
{
- int i;
-
copy_words((const digit_t*)P, (digit_t*)Q, 2*2*S2N_SIKE_P434_R3_NWORDS_FIELD);
- for (i = 0; i < e; i++) {
+ for (int i = 0; i < e; i++) {
xTPL(Q, Q, A24minus, A24plus);
}
}
@@ -346,3 +342,47 @@ void LADDER3PT(const f2elm_t *xP, const f2elm_t *xQ, const f2elm_t *xPQ, const d
mask = 0 - (digit_t)swap;
swap_points(R, R2, mask);
}
+
+void xTPL_fast(const point_proj_t P, point_proj_t Q, const f2elm_t *A2)
+{ // Montgomery curve (E: y^2 = x^3 + A*x^2 + x) x-only tripling at a cost of 5M + 6S + 11A.
+ // Input : projective Montgomery x-coordinates P = (X:Z), where x=X/Z and Montgomery curve constant A/2.
+ // Output: projective Montgomery x-coordinates Q = 3*P = (X3:Z3).
+ f2elm_t _t1, _t2, _t3, _t4;
+ f2elm_t *t1=&_t1, *t2=&_t2, *t3=&_t3, *t4=&_t4;
+
+ fp2sqr_mont(&P->X, t1); // t1 = x^2
+ fp2sqr_mont(&P->Z, t2); // t2 = z^2
+ fp2add(t1, t2, t3); // t3 = t1 + t2
+ fp2add(&P->X, &P->Z, t4); // t4 = x + z
+ fp2sqr_mont(t4, t4); // t4 = t4^2
+ fp2sub(t4, t3, t4); // t4 = t4 - t3
+ fp2mul_mont(A2, t4, t4); // t4 = t4*A2
+ fp2add(t3, t4, t4); // t4 = t4 + t3
+ fp2sub(t1, t2, t3); // t3 = t1 - t2
+ fp2sqr_mont(t3, t3); // t3 = t3^2
+ fp2mul_mont(t1, t4, t1); // t1 = t1*t4
+ fp2add(t1, t1, t1); // t1 = 2*t1
+ fp2add(t1, t1, t1); // t1 = 4*t1
+ fp2sub(t1, t3, t1); // t1 = t1 - t3
+ fp2sqr_mont(t1, t1); // t1 = t1^2
+ fp2mul_mont(t2, t4, t2); // t2 = t2*t4
+ fp2add(t2, t2, t2); // t2 = 2*t2
+ fp2add(t2, t2, t2); // t2 = 4*t2
+ fp2sub(t2, t3, t2); // t2 = t2 - t3
+ fp2sqr_mont(t2, t2); // t2 = t2^2
+ fp2mul_mont(&P->X, t2, &Q->X); // x = x*t2
+ fp2mul_mont(&P->Z, t1, &Q->Z); // z = z*t1
+}
+
+
+void xTPLe_fast(point_proj_t P, point_proj_t Q, const f2elm_t *A2, int e)
+{ // Computes [3^e](X:Z) on Montgomery curve with projective constant via e repeated triplings. e triplings in E costs e*(5M + 6S + 11A)
+ // Input: projective Montgomery x-coordinates P = (X:Z), where x=X/Z, Montgomery curve constant A2 = A/2 and the number of triplings e.
+ // Output: projective Montgomery x-coordinates Q <- [3^e]P.
+
+ copy_words((digit_t*)P, (digit_t*)Q, 2 * 2 * S2N_SIKE_P434_R3_NWORDS_FIELD);
+
+ for (int i = 0; i < e; i++) {
+ xTPL_fast(Q, Q, A2);
+ }
+}
diff --git a/contrib/restricted/aws/s2n/pq-crypto/sike_r3/sikep434r3_ec_isogeny.h b/contrib/restricted/aws/s2n/pq-crypto/sike_r3/sikep434r3_ec_isogeny.h
index 44245ec726..c09111e9d0 100644
--- a/contrib/restricted/aws/s2n/pq-crypto/sike_r3/sikep434r3_ec_isogeny.h
+++ b/contrib/restricted/aws/s2n/pq-crypto/sike_r3/sikep434r3_ec_isogeny.h
@@ -44,3 +44,9 @@ void j_inv(const f2elm_t *A, const f2elm_t *C, f2elm_t *jinv);
#define LADDER3PT S2N_SIKE_P434_R3_NAMESPACE(LADDER3PT)
void LADDER3PT(const f2elm_t *xP, const f2elm_t *xQ, const f2elm_t *xPQ, const digit_t *m,
const unsigned int AliceOrBob, point_proj_t R, const f2elm_t *A);
+
+#define xTPL_fast S2N_SIKE_P434_R3_NAMESPACE(xTPL_fast)
+void xTPL_fast(const point_proj_t P, point_proj_t Q, const f2elm_t *A2);
+
+#define xTPLe_fast S2N_SIKE_P434_R3_NAMESPACE(xTPLe_fast)
+void xTPLe_fast(point_proj_t P, point_proj_t Q, const f2elm_t *A2, int e);
diff --git a/contrib/restricted/aws/s2n/pq-crypto/sike_r3/sikep434r3_fpx.c b/contrib/restricted/aws/s2n/pq-crypto/sike_r3/sikep434r3_fpx.c
index 40c61144e4..d9cb686edf 100644
--- a/contrib/restricted/aws/s2n/pq-crypto/sike_r3/sikep434r3_fpx.c
+++ b/contrib/restricted/aws/s2n/pq-crypto/sike_r3/sikep434r3_fpx.c
@@ -122,6 +122,28 @@ void fp2div2(const f2elm_t *a, f2elm_t *c)
fpdiv2_434(a->e[1], c->e[1]);
}
+void fpcorrection(digit_t* a)
+{ // Modular correction to reduce field element a in [0, 2*p434-1] to [0, p434-1].
+ unsigned int i, borrow = 0;
+ digit_t mask;
+
+ for (i = 0; i < S2N_SIKE_P434_R3_NWORDS_FIELD; i++) {
+ S2N_SIKE_P434_R3_SUBC(borrow, a[i], ((const digit_t*)p434)[i], borrow, a[i]);
+ }
+ mask = 0 - (digit_t)borrow;
+
+ borrow = 0;
+ for (i = 0; i < S2N_SIKE_P434_R3_NWORDS_FIELD; i++) {
+ S2N_SIKE_P434_R3_ADDC(borrow, a[i], ((const digit_t*)p434)[i] & mask, borrow, a[i]);
+ }
+}
+
+void fp2correction(f2elm_t *a)
+{ // Modular correction, a = a in GF(p^2).
+ fpcorrection(a->e[0]);
+ fpcorrection(a->e[1]);
+}
+
/* Multiprecision addition, c = a+b, where lng(a) = lng(b) = nwords. Returns the carry bit. */
unsigned int mp_add(const digit_t* a, const digit_t* b, digit_t* c, const unsigned int nwords)
{
@@ -411,6 +433,18 @@ void mp_shiftr1(digit_t* x, const unsigned int nwords)
x[nwords-1] >>= 1;
}
+unsigned int is_felm_zero(const felm_t x)
+{ // Is x = 0? return 1 (TRUE) if condition is true, 0 (FALSE) otherwise.
+ // SECURITY NOTE: This function does not run in constant-time.
+
+ for (unsigned int i = 0; i < S2N_SIKE_P434_R3_NWORDS_FIELD; i++) {
+ if (x[i] != 0) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
void decode_to_digits(const unsigned char* x, digit_t* dec, int nbytes, int ndigits)
{
dec[ndigits - 1] = 0;
diff --git a/contrib/restricted/aws/s2n/pq-crypto/sike_r3/sikep434r3_fpx.h b/contrib/restricted/aws/s2n/pq-crypto/sike_r3/sikep434r3_fpx.h
index bce1849ce1..c6d8e8dc94 100644
--- a/contrib/restricted/aws/s2n/pq-crypto/sike_r3/sikep434r3_fpx.h
+++ b/contrib/restricted/aws/s2n/pq-crypto/sike_r3/sikep434r3_fpx.h
@@ -25,6 +25,9 @@ void fp2copy(const f2elm_t *a, f2elm_t *c);
#define fp2div2 S2N_SIKE_P434_R3_NAMESPACE(fp2div2)
void fp2div2(const f2elm_t *a, f2elm_t *c);
+#define fp2correction S2N_SIKE_P434_R3_NAMESPACE(fp2correction)
+void fp2correction(f2elm_t *a);
+
#define mp_add S2N_SIKE_P434_R3_NAMESPACE(mp_add)
unsigned int mp_add(const digit_t* a, const digit_t* b, digit_t* c, const unsigned int nwords);
@@ -40,6 +43,9 @@ void fp2inv_mont(f2elm_t *a);
#define mp_shiftr1 S2N_SIKE_P434_R3_NAMESPACE(mp_shiftr1)
void mp_shiftr1(digit_t* x, const unsigned int nwords);
+#define is_felm_zero S2N_SIKE_P434_R3_NAMESPACE(is_felm_zero)
+unsigned int is_felm_zero(const felm_t x);
+
#define decode_to_digits S2N_SIKE_P434_R3_NAMESPACE(decode_to_digits)
void decode_to_digits(const unsigned char* x, digit_t* dec, int nbytes, int ndigits);
diff --git a/contrib/restricted/aws/s2n/pq-crypto/sike_r3/sikep434r3_kem.c b/contrib/restricted/aws/s2n/pq-crypto/sike_r3/sikep434r3_kem.c
index b32add7723..9ce254fbf1 100644
--- a/contrib/restricted/aws/s2n/pq-crypto/sike_r3/sikep434r3_kem.c
+++ b/contrib/restricted/aws/s2n/pq-crypto/sike_r3/sikep434r3_kem.c
@@ -81,9 +81,13 @@ int s2n_sike_p434_r3_crypto_kem_dec(unsigned char *ss, const unsigned char *ct,
unsigned char h_[S2N_SIKE_P434_R3_MSG_BYTES];
unsigned char c0_[S2N_SIKE_P434_R3_PUBLIC_KEY_BYTES];
unsigned char temp[S2N_SIKE_P434_R3_CIPHERTEXT_BYTES+S2N_SIKE_P434_R3_MSG_BYTES];
+ bool dont_copy = 1;
/* Decrypt */
- EphemeralSecretAgreement_B(sk + S2N_SIKE_P434_R3_MSG_BYTES, ct, jinvariant_);
+ if (!(EphemeralSecretAgreement_B(sk + S2N_SIKE_P434_R3_MSG_BYTES, ct, jinvariant_) == 0)) {
+ goto S2N_SIKE_P434_R3_HASHING;
+ }
+
shake256(h_, S2N_SIKE_P434_R3_MSG_BYTES, jinvariant_, S2N_SIKE_P434_R3_FP2_ENCODED_BYTES);
for (int i = 0; i < S2N_SIKE_P434_R3_MSG_BYTES; i++) {
temp[i] = ct[i + S2N_SIKE_P434_R3_PUBLIC_KEY_BYTES] ^ h_[i];
@@ -103,7 +107,8 @@ int s2n_sike_p434_r3_crypto_kem_dec(unsigned char *ss, const unsigned char *ct,
*
* If c0_ and ct are equal, then decaps succeeded and we skip the overwrite and output
* the actual shared secret: ss = H(m||ct) (dont_copy = true). */
- bool dont_copy = s2n_constant_time_equals(c0_, ct, S2N_SIKE_P434_R3_PUBLIC_KEY_BYTES);
+ dont_copy = s2n_constant_time_equals(c0_, ct, S2N_SIKE_P434_R3_PUBLIC_KEY_BYTES);
+S2N_SIKE_P434_R3_HASHING:
POSIX_GUARD(s2n_constant_time_copy_or_dont(temp, sk, S2N_SIKE_P434_R3_MSG_BYTES, dont_copy));
memcpy(&temp[S2N_SIKE_P434_R3_MSG_BYTES], ct, S2N_SIKE_P434_R3_CIPHERTEXT_BYTES);
shake256(ss, S2N_SIKE_P434_R3_SHARED_SECRET_BYTES, temp, S2N_SIKE_P434_R3_CIPHERTEXT_BYTES+S2N_SIKE_P434_R3_MSG_BYTES);
diff --git a/contrib/restricted/aws/s2n/pq-crypto/sike_r3/sikep434r3_sidh.c b/contrib/restricted/aws/s2n/pq-crypto/sike_r3/sikep434r3_sidh.c
index f570e27e32..8bd5124b41 100644
--- a/contrib/restricted/aws/s2n/pq-crypto/sike_r3/sikep434r3_sidh.c
+++ b/contrib/restricted/aws/s2n/pq-crypto/sike_r3/sikep434r3_sidh.c
@@ -245,15 +245,57 @@ int EphemeralSecretAgreement_A(const unsigned char* PrivateKeyA, const unsigned
return 0;
}
+int sike_p434_r3_publickey_validation(const f2elm_t *PKB, const f2elm_t *A)
+{ // Public key validation
+ point_proj_t P = { 0 }, Q = { 0 };
+ f2elm_t _A2={0}, _tmp1={0}, _tmp2={0};
+ f2elm_t *A2=&_A2, *tmp1=&_tmp1, *tmp2=&_tmp2;
+
+ // Verify that P and Q generate E_A[3^e_3] by checking that [3^(e_3-1)]P != [+-3^(e_3-1)]Q
+ fp2div2(A, A2);
+ fp2copy(&PKB[0], &P->X);
+ fpcopy((const digit_t*)&Montgomery_one, (digit_t*)&P->Z);
+ fp2copy(&PKB[1], &Q->X);
+ fpcopy((const digit_t*)&Montgomery_one, (digit_t*)&Q->Z);
+
+ xTPLe_fast(P, P, A2, S2N_SIKE_P434_R3_MAX_BOB - 1);
+ xTPLe_fast(Q, Q, A2, S2N_SIKE_P434_R3_MAX_BOB - 1);
+ fp2correction(&P->Z);
+ fp2correction(&Q->Z);
+
+ if ((is_felm_zero((P->Z.e)[0]) && is_felm_zero((P->Z.e)[1])) || (is_felm_zero((Q->Z.e)[0]) && is_felm_zero((Q->Z.e)[1]))) {
+ return 1;
+ }
+
+ fp2mul_mont(&P->X, &Q->Z, tmp1);
+ fp2mul_mont(&P->Z, &Q->X, tmp2);
+ fp2correction(tmp1);
+ fp2correction(tmp2);
+
+ if (memcmp((uint8_t*)tmp1, (uint8_t*)tmp2, S2N_SIKE_P434_R3_FP2_ENCODED_BYTES) == 0) {
+ return 1;
+ }
+
+ // Check that Ord(P) = Ord(Q) = 3^(e_3)
+ xTPL_fast(P, P, A2);
+ xTPL_fast(Q, Q, A2);
+ fp2correction(&P->Z);
+ fp2correction(&Q->Z);
+
+ if (!is_felm_zero((P->Z.e)[0]) || !is_felm_zero((P->Z.e)[1]) || !is_felm_zero((Q->Z.e)[0]) || !is_felm_zero((Q->Z.e)[1])) {
+ return 1;
+ }
+
+ return 0;
+}
+
/* Bob's ephemeral shared secret computation
* It produces a shared secret key SharedSecretB using his secret key PrivateKeyB and Alice's public key PublicKeyA
* Inputs: Bob's PrivateKeyB is an integer in the range [0, 2^Floor(Log(2,oB)) - 1].
* Alice's PublicKeyA consists of 3 elements in GF(p^2) encoded by removing leading 0 bytes.
* Output: a shared secret SharedSecretB that consists of one element in GF(p^2) encoded
* by removing leading 0 bytes. */
-int EphemeralSecretAgreement_B(const unsigned char* PrivateKeyB, const unsigned char* PublicKeyA,
- unsigned char* SharedSecretB)
-{
+int EphemeralSecretAgreement_B(const unsigned char* PrivateKeyB, const unsigned char* PublicKeyA, unsigned char* SharedSecretB) {
point_proj_t R, pts[S2N_SIKE_P434_R3_MAX_INT_POINTS_BOB];
f2elm_t coeff[3], PKB[3], _jinv;
f2elm_t _A24plus = {0}, _A24minus = {0}, _A = {0};
@@ -272,6 +314,11 @@ int EphemeralSecretAgreement_B(const unsigned char* PrivateKeyB, const unsigned
mp2_add(A, A24minus, A24plus);
mp2_sub_p2(A, A24minus, A24minus);
+ // Always perform public key validation before using peer's public key
+ if (sike_p434_r3_publickey_validation(PKB, A) == 1) {
+ return 1;
+ }
+
/* Retrieve kernel point */
decode_to_digits(PrivateKeyB, SecretKeyB, S2N_SIKE_P434_R3_SECRETKEY_B_BYTES, S2N_SIKE_P434_R3_NWORDS_ORDER);
LADDER3PT(&PKB[0], &PKB[1], &PKB[2], SecretKeyB, S2N_SIKE_P434_R3_BOB, R, A);
diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_supported_versions.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_supported_versions.c
index bbc37e475a..067a9d3eaf 100644
--- a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_supported_versions.c
+++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_supported_versions.c
@@ -115,7 +115,8 @@ static int s2n_extensions_client_supported_versions_process(struct s2n_connectio
conn->actual_protocol_version = MAX(client_version, conn->actual_protocol_version);
}
- S2N_ERROR_IF(conn->actual_protocol_version == s2n_unknown_protocol_version, S2N_ERR_UNKNOWN_PROTOCOL_VERSION);
+ POSIX_ENSURE(conn->client_protocol_version != s2n_unknown_protocol_version, S2N_ERR_UNKNOWN_PROTOCOL_VERSION);
+ POSIX_ENSURE(conn->actual_protocol_version != s2n_unknown_protocol_version, S2N_ERR_PROTOCOL_VERSION_UNSUPPORTED);
return S2N_SUCCESS;
}
@@ -126,10 +127,12 @@ static int s2n_client_supported_versions_recv(struct s2n_connection *conn, struc
return S2N_SUCCESS;
}
- if (s2n_extensions_client_supported_versions_process(conn, in) < 0) {
+ int result = s2n_extensions_client_supported_versions_process(conn, in);
+ if (result != S2N_SUCCESS) {
s2n_queue_reader_unsupported_protocol_version_alert(conn);
- POSIX_BAIL(S2N_ERR_BAD_MESSAGE);
+ POSIX_ENSURE(s2n_errno != S2N_ERR_SAFETY, S2N_ERR_BAD_MESSAGE);
}
+ POSIX_GUARD(result);
return S2N_SUCCESS;
}
diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_type.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_type.c
index 1c808f1d8c..4e4aa5d3bc 100644
--- a/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_type.c
+++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_type.c
@@ -147,6 +147,12 @@ int s2n_extension_recv(const s2n_extension_type *extension_type, struct s2n_conn
*# If the original session did not use the "extended_master_secret"
*# extension but the new ServerHello contains the extension, the
*# client MUST abort the handshake.
+ *
+ *= https://tools.ietf.org/rfc/rfc8446#4.1.4
+ *# As with the ServerHello, a HelloRetryRequest MUST NOT contain any
+ *# extensions that were not first offered by the client in its
+ *# ClientHello, with the exception of optionally the "cookie" (see
+ *# Section 4.2.2) extension.
**/
if (extension_type->is_response &&
!S2N_CBIT_TEST(conn->extension_requests_sent, extension_id)) {
@@ -161,7 +167,9 @@ int s2n_extension_recv(const s2n_extension_type *extension_type, struct s2n_conn
POSIX_GUARD(extension_type->recv(conn, in));
/* Set request bit flag */
- if (!extension_type->is_response) {
+ if (extension_type->is_response) {
+ S2N_CBIT_SET(conn->extension_responses_received, extension_id);
+ } else {
S2N_CBIT_SET(conn->extension_requests_received, extension_id);
}
diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_key_share.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_key_share.c
index 46f5deb1d5..02fa59ac3e 100644
--- a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_key_share.c
+++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_key_share.c
@@ -28,7 +28,7 @@ static int s2n_server_key_share_recv(struct s2n_connection *conn, struct s2n_stu
const s2n_extension_type s2n_server_key_share_extension = {
.iana_value = TLS_EXTENSION_KEY_SHARE,
.minimum_version = S2N_TLS13,
- .is_response = false,
+ .is_response = true,
.send = s2n_server_key_share_send,
.recv = s2n_server_key_share_recv,
.should_send = s2n_extension_always_send,
diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_psk.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_psk.c
index 9a36caff9f..09e525fa93 100644
--- a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_psk.c
+++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_psk.c
@@ -60,9 +60,9 @@ static int s2n_server_psk_recv(struct s2n_connection *conn, struct s2n_stuffer *
* Any other mode selected by the server is invalid because it was not offered by the client.
* A key_share extension MUST have been received in order to use a pre-shared key in (EC)DHE key exchange mode.
*/
- s2n_extension_type_id key_share_ext_id;
+ s2n_extension_type_id key_share_ext_id = s2n_unsupported_extension;
POSIX_GUARD(s2n_extension_supported_iana_value_to_id(TLS_EXTENSION_KEY_SHARE, &key_share_ext_id));
- POSIX_ENSURE(S2N_CBIT_TEST(conn->extension_requests_received, key_share_ext_id), S2N_ERR_MISSING_EXTENSION);
+ POSIX_ENSURE(S2N_CBIT_TEST(conn->extension_responses_received, key_share_ext_id), S2N_ERR_MISSING_EXTENSION);
/* From RFC section: https://tools.ietf.org/html/rfc8446#section-4.2.8.1
* Any future values that are allocated must ensure that the transmitted protocol messages
diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_supported_versions.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_supported_versions.c
index 53e387d8cc..55a3e4ebd2 100644
--- a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_supported_versions.c
+++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_supported_versions.c
@@ -70,6 +70,18 @@ static int s2n_extensions_server_supported_versions_process(struct s2n_connectio
uint16_t server_version = (server_version_parts[0] * 10) + server_version_parts[1];
+ /**
+ *= https://tools.ietf.org/rfc/rfc8446#4.1.4
+ *# The value of selected_version in the HelloRetryRequest
+ *# "supported_versions" extension MUST be retained in the ServerHello,
+ *# and a client MUST abort the handshake with an "illegal_parameter"
+ *# alert if the value changes.
+ **/
+ if (s2n_is_hello_retry_handshake(conn) && !s2n_is_hello_retry_message(conn)) {
+ POSIX_ENSURE(conn->server_protocol_version == server_version,
+ S2N_ERR_BAD_MESSAGE);
+ }
+
POSIX_ENSURE_GTE(server_version, S2N_TLS13);
POSIX_ENSURE_LTE(server_version, highest_supported_version);
POSIX_ENSURE_GTE(server_version, minimum_supported_version);
diff --git a/contrib/restricted/aws/s2n/tls/s2n_cipher_preferences.c b/contrib/restricted/aws/s2n/tls/s2n_cipher_preferences.c
index 10407f487a..b7268e55f5 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_cipher_preferences.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_cipher_preferences.c
@@ -82,6 +82,33 @@ const struct s2n_cipher_preferences cipher_preferences_20210831 = {
.suites = cipher_suites_20210831,
};
+/*
+ * These cipher suites were chosen based on the following specification:
+ * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-52r2.pdf
+ */
+struct s2n_cipher_suite *cipher_suites_default_fips[] = {
+ /* tls1.2 with ECDSA */
+ &s2n_ecdhe_ecdsa_with_aes_128_gcm_sha256,
+ &s2n_ecdhe_ecdsa_with_aes_256_gcm_sha384,
+ &s2n_ecdhe_ecdsa_with_aes_128_cbc_sha256,
+ &s2n_ecdhe_ecdsa_with_aes_256_cbc_sha384,
+
+ /* tls1.2 with RSA */
+ &s2n_ecdhe_rsa_with_aes_128_gcm_sha256,
+ &s2n_ecdhe_rsa_with_aes_256_gcm_sha384,
+ &s2n_ecdhe_rsa_with_aes_128_cbc_sha256,
+ &s2n_ecdhe_rsa_with_aes_256_cbc_sha384,
+ &s2n_dhe_rsa_with_aes_128_cbc_sha256,
+ &s2n_dhe_rsa_with_aes_256_cbc_sha256,
+ &s2n_dhe_rsa_with_aes_128_gcm_sha256,
+ &s2n_dhe_rsa_with_aes_256_gcm_sha384,
+};
+
+const struct s2n_cipher_preferences cipher_preferences_default_fips = {
+ .count = s2n_array_len(cipher_suites_default_fips),
+ .suites = cipher_suites_default_fips,
+};
+
/* s2n's list of cipher suites, in order of preference, as of 2014-06-01 */
struct s2n_cipher_suite *cipher_suites_20140601[] = {
&s2n_dhe_rsa_with_aes_128_cbc_sha256,
diff --git a/contrib/restricted/aws/s2n/tls/s2n_cipher_preferences.h b/contrib/restricted/aws/s2n/tls/s2n_cipher_preferences.h
index 7156c68185..c7305a3908 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_cipher_preferences.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_cipher_preferences.h
@@ -51,6 +51,7 @@ extern const struct s2n_cipher_preferences cipher_preferences_20210816_gcm;
extern const struct s2n_cipher_preferences cipher_preferences_20210825;
extern const struct s2n_cipher_preferences cipher_preferences_20210825_gcm;
extern const struct s2n_cipher_preferences cipher_preferences_20210831;
+extern const struct s2n_cipher_preferences cipher_preferences_default_fips;
extern const struct s2n_cipher_preferences cipher_preferences_test_all;
diff --git a/contrib/restricted/aws/s2n/tls/s2n_cipher_suites.c b/contrib/restricted/aws/s2n/tls/s2n_cipher_suites.c
index cf82b7c6f4..e18efb0c87 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_cipher_suites.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_cipher_suites.c
@@ -1124,6 +1124,23 @@ int s2n_set_cipher_as_client(struct s2n_connection *conn, uint8_t wire[S2N_TLS_C
POSIX_GUARD(s2n_connection_get_security_policy(conn, &security_policy));
POSIX_ENSURE_REF(security_policy);
+ /**
+ * Ensure that the wire cipher suite is contained in the security
+ * policy, and thus was offered by the client.
+ *
+ *= https://tools.ietf.org/rfc/rfc8446#4.1.3
+ *# A client which receives a
+ *# cipher suite that was not offered MUST abort the handshake with an
+ *# "illegal_parameter" alert.
+ *
+ *= https://tools.ietf.org/rfc/rfc8446#4.1.4
+ *# A client which receives a cipher suite that was not offered MUST
+ *# abort the handshake.
+ *
+ *= https://tools.ietf.org/rfc/rfc8446#4.1.4
+ *# Upon receipt of a HelloRetryRequest, the client MUST check the
+ *# legacy_version, legacy_session_id_echo, cipher_suite
+ **/
struct s2n_cipher_suite *cipher_suite = NULL;
for (size_t i = 0; i < security_policy->cipher_preferences->count; i++) {
const uint8_t *ours = security_policy->cipher_preferences->suites[i]->iana_value;
@@ -1133,6 +1150,7 @@ int s2n_set_cipher_as_client(struct s2n_connection *conn, uint8_t wire[S2N_TLS_C
}
}
POSIX_ENSURE(cipher_suite != NULL, S2N_ERR_CIPHER_NOT_SUPPORTED);
+
POSIX_ENSURE(cipher_suite->available, S2N_ERR_CIPHER_NOT_SUPPORTED);
/** Clients MUST verify
@@ -1145,7 +1163,13 @@ int s2n_set_cipher_as_client(struct s2n_connection *conn, uint8_t wire[S2N_TLS_C
S2N_ERR_CIPHER_NOT_SUPPORTED);
}
- /* Verify cipher suite sent in server hello is the same as sent in hello retry */
+ /**
+ *= https://tools.ietf.org/rfc/rfc8446#4.1.4
+ *# Upon receiving
+ *# the ServerHello, clients MUST check that the cipher suite supplied in
+ *# the ServerHello is the same as that in the HelloRetryRequest and
+ *# otherwise abort the handshake with an "illegal_parameter" alert.
+ **/
if (s2n_is_hello_retry_handshake(conn) && !s2n_is_hello_retry_message(conn)) {
POSIX_ENSURE(conn->secure.cipher_suite->iana_value == cipher_suite->iana_value, S2N_ERR_CIPHER_NOT_SUPPORTED);
return S2N_SUCCESS;
diff --git a/contrib/restricted/aws/s2n/tls/s2n_client_hello.c b/contrib/restricted/aws/s2n/tls/s2n_client_hello.c
index 149f4d4b53..0553d1fe14 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_client_hello.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_client_hello.c
@@ -433,9 +433,28 @@ int s2n_process_client_hello(struct s2n_connection *conn)
/* Find potential certificate matches before we choose the cipher. */
POSIX_GUARD(s2n_conn_find_name_matching_certs(conn));
+ /* Save the previous cipher suite */
+ uint8_t previous_cipher_suite_iana[S2N_TLS_CIPHER_SUITE_LEN] = { 0 };
+ POSIX_CHECKED_MEMCPY(previous_cipher_suite_iana, conn->secure.cipher_suite->iana_value, S2N_TLS_CIPHER_SUITE_LEN);
+
/* Now choose the ciphers we have certs for. */
POSIX_GUARD(s2n_set_cipher_as_tls_server(conn, client_hello->cipher_suites.data, client_hello->cipher_suites.size / 2));
+ /* Check if this is the second client hello in a hello retry handshake */
+ if (s2n_is_hello_retry_handshake(conn) &&
+ conn->handshake.message_number > 0) {
+
+ /**
+ *= https://tools.ietf.org/rfc/rfc8446#4.1.4
+ *# Servers MUST ensure that they negotiate the
+ *# same cipher suite when receiving a conformant updated ClientHello (if
+ *# the server selects the cipher suite as the first step in the
+ *# negotiation, then this will happen automatically).
+ **/
+ POSIX_ENSURE(s2n_constant_time_equals(previous_cipher_suite_iana, conn->secure.cipher_suite->iana_value,
+ S2N_TLS_CIPHER_SUITE_LEN),S2N_ERR_BAD_MESSAGE);
+ }
+
/* If we're using a PSK, we don't need to choose a signature algorithm or certificate,
* because no additional auth is required. */
if (conn->psk_params.chosen_psk != NULL) {
diff --git a/contrib/restricted/aws/s2n/tls/s2n_connection.h b/contrib/restricted/aws/s2n/tls/s2n_connection.h
index 09e1f19724..be375551b1 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_connection.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_connection.h
@@ -144,7 +144,7 @@ struct s2n_connection {
void *send_io_context;
void *recv_io_context;
- /* Track request extensions to ensure correct response extension behavior.
+ /* Track request/response extensions to ensure correct response extension behavior.
*
* We need to track client and server extensions separately because some
* extensions (like request_status and other Certificate extensions) can
@@ -152,6 +152,7 @@ struct s2n_connection {
*/
s2n_extension_bitfield extension_requests_sent;
s2n_extension_bitfield extension_requests_received;
+ s2n_extension_bitfield extension_responses_received;
/* Is this connection a client or a server connection */
s2n_mode mode;
diff --git a/contrib/restricted/aws/s2n/tls/s2n_ecc_preferences.c b/contrib/restricted/aws/s2n/tls/s2n_ecc_preferences.c
index f1632a0a53..53b9e95a13 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_ecc_preferences.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_ecc_preferences.c
@@ -33,6 +33,15 @@ const struct s2n_ecc_named_curve *const s2n_ecc_pref_list_20200310[] = {
&s2n_ecc_curve_secp384r1,
};
+/*
+ * These curves were chosen based on the following specification:
+ * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-52r2.pdf
+ */
+const struct s2n_ecc_named_curve *const s2n_ecc_pref_list_default_fips[] = {
+ &s2n_ecc_curve_secp256r1,
+ &s2n_ecc_curve_secp384r1,
+};
+
const struct s2n_ecc_named_curve *const s2n_ecc_pref_list_20201021[] = {
&s2n_ecc_curve_secp256r1,
&s2n_ecc_curve_secp384r1,
@@ -62,6 +71,11 @@ const struct s2n_ecc_preferences s2n_ecc_preferences_20200310 = {
.ecc_curves = s2n_ecc_pref_list_20200310,
};
+const struct s2n_ecc_preferences s2n_ecc_preferences_default_fips = {
+ .count = s2n_array_len(s2n_ecc_pref_list_default_fips),
+ .ecc_curves = s2n_ecc_pref_list_default_fips,
+};
+
const struct s2n_ecc_preferences s2n_ecc_preferences_20201021 = {
.count = s2n_array_len(s2n_ecc_pref_list_20201021),
.ecc_curves = s2n_ecc_pref_list_20201021,
@@ -92,10 +106,10 @@ int s2n_check_ecc_preferences_curves_list(const struct s2n_ecc_preferences *ecc_
for (size_t j = 0; j < s2n_all_supported_curves_list_len; j++) {
if (named_curve->iana_id == s2n_all_supported_curves_list[j]->iana_id) {
curve_found = 1;
- break;
+ break;
}
}
- check *= curve_found;
+ check *= curve_found;
if (check == 0) {
POSIX_BAIL(S2N_ERR_ECDHE_UNSUPPORTED_CURVE);
}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_ecc_preferences.h b/contrib/restricted/aws/s2n/tls/s2n_ecc_preferences.h
index 564d722726..3d4a168264 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_ecc_preferences.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_ecc_preferences.h
@@ -27,6 +27,7 @@ struct s2n_ecc_preferences {
};
extern const struct s2n_ecc_preferences s2n_ecc_preferences_20140601;
extern const struct s2n_ecc_preferences s2n_ecc_preferences_20200310;
+extern const struct s2n_ecc_preferences s2n_ecc_preferences_default_fips;
extern const struct s2n_ecc_preferences s2n_ecc_preferences_20201021;
extern const struct s2n_ecc_preferences s2n_ecc_preferences_20210816;
extern const struct s2n_ecc_preferences s2n_ecc_preferences_test_all;
diff --git a/contrib/restricted/aws/s2n/tls/s2n_handshake_io.c b/contrib/restricted/aws/s2n/tls/s2n_handshake_io.c
index 3c490212a7..a1f5c1215f 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_handshake_io.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_handshake_io.c
@@ -1365,6 +1365,11 @@ int s2n_negotiate_impl(struct s2n_connection *conn, s2n_blocked_status *blocked)
/* Flush any pending I/O or alert messages */
POSIX_GUARD(s2n_flush(conn, blocked));
+ /* If the connection is closed, the handshake will never complete. */
+ if (conn->closed) {
+ POSIX_BAIL(S2N_ERR_CLOSED);
+ }
+
/* If the handshake was paused, retry the current message */
if (conn->handshake.paused) {
*blocked = S2N_BLOCKED_ON_APPLICATION_INPUT;
diff --git a/contrib/restricted/aws/s2n/tls/s2n_security_policies.c b/contrib/restricted/aws/s2n/tls/s2n_security_policies.c
index 90c0cb16a3..d8a041aca5 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_security_policies.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_security_policies.c
@@ -36,6 +36,21 @@ const struct s2n_security_policy security_policy_default_tls13 = {
.ecc_preferences = &s2n_ecc_preferences_20200310,
};
+/*
+ * This security policy is derived from the following specification:
+ * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-52r2.pdf
+ *
+ * Supports TLS1.2
+ */
+const struct s2n_security_policy security_policy_default_fips = {
+ .minimum_protocol_version = S2N_TLS12,
+ .cipher_preferences = &cipher_preferences_default_fips,
+ .kem_preferences = &kem_preferences_null,
+ .signature_preferences = &s2n_signature_preferences_default_fips,
+ .certificate_signature_preferences = &s2n_signature_preferences_default_fips,
+ .ecc_preferences = &s2n_ecc_preferences_default_fips,
+};
+
const struct s2n_security_policy security_policy_20190801 = {
.minimum_protocol_version = S2N_TLS10,
.cipher_preferences = &cipher_preferences_20190801,
@@ -362,7 +377,7 @@ const struct s2n_security_policy security_policy_kms_pq_tls_1_0_2020_02 = {
};
const struct s2n_security_policy security_policy_pq_sike_test_tls_1_0_2019_11 = {
- .minimum_protocol_version = S2N_TLS10,
+ .minimum_protocol_version = S2N_TLS10,
.cipher_preferences = &cipher_preferences_pq_sike_test_tls_1_0_2019_11,
.kem_preferences = &kem_preferences_pq_sike_test_tls_1_0_2019_11,
.signature_preferences = &s2n_signature_preferences_20140601,
@@ -370,7 +385,7 @@ const struct s2n_security_policy security_policy_pq_sike_test_tls_1_0_2019_11 =
};
const struct s2n_security_policy security_policy_pq_sike_test_tls_1_0_2020_02 = {
- .minimum_protocol_version = S2N_TLS10,
+ .minimum_protocol_version = S2N_TLS10,
.cipher_preferences = &cipher_preferences_pq_sike_test_tls_1_0_2020_02,
.kem_preferences = &kem_preferences_pq_sike_test_tls_1_0_2020_02,
.signature_preferences = &s2n_signature_preferences_20140601,
@@ -734,7 +749,7 @@ const struct s2n_security_policy security_policy_null = {
struct s2n_security_policy_selection security_policy_selection[] = {
{ .version="default", .security_policy=&security_policy_20170210, .ecc_extension_required=0, .pq_kem_extension_required=0 },
{ .version="default_tls13", .security_policy=&security_policy_default_tls13, .ecc_extension_required=0, .pq_kem_extension_required=0 },
- { .version="default_fips", .security_policy=&security_policy_20170405, .ecc_extension_required=0, .pq_kem_extension_required=0 },
+ { .version="default_fips", .security_policy=&security_policy_default_fips, .ecc_extension_required=0, .pq_kem_extension_required=0 },
{ .version="ELBSecurityPolicy-TLS-1-0-2015-04", .security_policy=&security_policy_elb_2015_04, .ecc_extension_required=0, .pq_kem_extension_required=0 },
/* Not a mistake. TLS-1-0-2015-05 and 2016-08 are equivalent */
{ .version="ELBSecurityPolicy-TLS-1-0-2015-05", .security_policy=&security_policy_elb_2016_08, .ecc_extension_required=0, .pq_kem_extension_required=0 },
@@ -743,9 +758,9 @@ struct s2n_security_policy_selection security_policy_selection[] = {
{ .version="ELBSecurityPolicy-TLS-1-2-2017-01", .security_policy=&security_policy_elb_tls_1_2_2017_01, .ecc_extension_required=0, .pq_kem_extension_required=0 },
{ .version="ELBSecurityPolicy-TLS-1-2-Ext-2018-06", .security_policy=&security_policy_elb_tls_1_2_ext_2018_06, .ecc_extension_required=0, .pq_kem_extension_required=0 },
{ .version="ELBSecurityPolicy-FS-2018-06", .security_policy=&security_policy_elb_fs_2018_06, .ecc_extension_required=0, .pq_kem_extension_required=0 },
- { .version="ELBSecurityPolicy-FS-1-2-2019-08", .security_policy=&security_policy_elb_fs_1_2_2019_08, .ecc_extension_required=0, .pq_kem_extension_required=0 },
- { .version="ELBSecurityPolicy-FS-1-1-2019-08", .security_policy=&security_policy_elb_fs_1_1_2019_08, .ecc_extension_required=0, .pq_kem_extension_required=0 },
- { .version="ELBSecurityPolicy-FS-1-2-Res-2019-08", .security_policy=&security_policy_elb_fs_1_2_Res_2019_08, .ecc_extension_required=0, .pq_kem_extension_required=0 },
+ { .version="ELBSecurityPolicy-FS-1-2-2019-08", .security_policy=&security_policy_elb_fs_1_2_2019_08, .ecc_extension_required=0, .pq_kem_extension_required=0 },
+ { .version="ELBSecurityPolicy-FS-1-1-2019-08", .security_policy=&security_policy_elb_fs_1_1_2019_08, .ecc_extension_required=0, .pq_kem_extension_required=0 },
+ { .version="ELBSecurityPolicy-FS-1-2-Res-2019-08", .security_policy=&security_policy_elb_fs_1_2_Res_2019_08, .ecc_extension_required=0, .pq_kem_extension_required=0 },
{ .version="CloudFront-Upstream", .security_policy=&security_policy_cloudfront_upstream, .ecc_extension_required=0, .pq_kem_extension_required=0 },
{ .version="CloudFront-Upstream-TLS-1-0", .security_policy=&security_policy_cloudfront_upstream_tls10, .ecc_extension_required=0, .pq_kem_extension_required=0 },
{ .version="CloudFront-Upstream-TLS-1-1", .security_policy=&security_policy_cloudfront_upstream_tls11, .ecc_extension_required=0, .pq_kem_extension_required=0 },
diff --git a/contrib/restricted/aws/s2n/tls/s2n_security_policies.h b/contrib/restricted/aws/s2n/tls/s2n_security_policies.h
index be28fb584a..e4fec2c492 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_security_policies.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_security_policies.h
@@ -63,6 +63,7 @@ extern const struct s2n_security_policy security_policy_20190214_gcm;
extern const struct s2n_security_policy security_policy_20190801;
extern const struct s2n_security_policy security_policy_20190802;
extern const struct s2n_security_policy security_policy_default_tls13;
+extern const struct s2n_security_policy security_policy_default_fips;
extern const struct s2n_security_policy security_policy_test_all;
extern const struct s2n_security_policy security_policy_test_all_tls12;
diff --git a/contrib/restricted/aws/s2n/tls/s2n_server_extensions.c b/contrib/restricted/aws/s2n/tls/s2n_server_extensions.c
index b604556009..f0cb6d6d39 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_server_extensions.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_server_extensions.c
@@ -58,13 +58,20 @@ int s2n_server_extensions_recv(struct s2n_connection *conn, struct s2n_stuffer *
s2n_parsed_extensions_list parsed_extension_list = { 0 };
POSIX_GUARD(s2n_extension_list_parse(in, &parsed_extension_list));
- /* Process supported_versions first so that we know which extensions list to use.
+ /**
+ * Process supported_versions first so that we know which extensions list to use.
* - If the supported_versions extension exists, then it will set server_protocol_version.
* - If the supported_versions extension does not exist, then the server_protocol_version will remain
- * unknown and we will use the default list of allowed extension types. */
+ * unknown and we will use the default list of allowed extension types.
+ **/
POSIX_GUARD(s2n_extension_process(&s2n_server_supported_versions_extension, conn, &parsed_extension_list));
if (s2n_is_hello_retry_message(conn)) {
+ /**
+ *= https://tools.ietf.org/rfc/rfc8446#4.1.4
+ *# Otherwise, the client MUST process all extensions in the
+ *# HelloRetryRequest
+ */
POSIX_GUARD(s2n_extension_list_process(S2N_EXTENSION_LIST_HELLO_RETRY_REQUEST, conn, &parsed_extension_list));
} else if (conn->server_protocol_version >= S2N_TLS13) {
POSIX_GUARD(s2n_extension_list_process(S2N_EXTENSION_LIST_SERVER_HELLO_TLS13, conn, &parsed_extension_list));
diff --git a/contrib/restricted/aws/s2n/tls/s2n_server_hello.c b/contrib/restricted/aws/s2n/tls/s2n_server_hello.c
index 632f745478..efe4c08114 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_server_hello.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_server_hello.c
@@ -37,6 +37,7 @@
#include "utils/s2n_safety.h"
#include "utils/s2n_random.h"
+#include "utils/s2n_bitmap.h"
/* From RFC5246 7.4.1.2. */
#define S2N_TLS_COMPRESSION_METHOD_NULL 0
@@ -51,7 +52,7 @@ const uint8_t tls11_downgrade_protection_bytes[] = {
0x44, 0x4F, 0x57, 0x4E, 0x47, 0x52, 0x44, 0x00
};
-static int s2n_hello_retry_validate(struct s2n_connection *conn) {
+static int s2n_random_value_is_hello_retry(struct s2n_connection *conn) {
POSIX_ENSURE_REF(conn);
POSIX_ENSURE(memcmp(hello_retry_req_random, conn->handshake_params.server_random, S2N_TLS_RANDOM_DATA_LEN) == 0,
@@ -107,9 +108,32 @@ static int s2n_server_hello_parse(struct s2n_connection *conn)
POSIX_GUARD(s2n_stuffer_read_bytes(in, protocol_version, S2N_TLS_PROTOCOL_VERSION_LEN));
POSIX_GUARD(s2n_stuffer_read_bytes(in, conn->handshake_params.server_random, S2N_TLS_RANDOM_DATA_LEN));
- /* If the client receives a second HelloRetryRequest in the same connection, it MUST send an error. */
- if (s2n_hello_retry_validate(conn) == S2N_SUCCESS) {
+ uint8_t legacy_version = (uint8_t)(protocol_version[0] * 10) + protocol_version[1];
+
+ /**
+ *= https://tools.ietf.org/rfc/rfc8446#4.1.3
+ *# Upon receiving a message with type server_hello, implementations MUST
+ *# first examine the Random value and, if it matches this value, process
+ *# it as described in Section 4.1.4).
+ **/
+ if (s2n_random_value_is_hello_retry(conn) == S2N_SUCCESS) {
+
+ /**
+ *= https://tools.ietf.org/rfc/rfc8446#4.1.4
+ *# If a client receives a second
+ *# HelloRetryRequest in the same connection (i.e., where the ClientHello
+ *# was itself in response to a HelloRetryRequest), it MUST abort the
+ *# handshake with an "unexpected_message" alert.
+ **/
POSIX_ENSURE(!s2n_is_hello_retry_handshake(conn), S2N_ERR_INVALID_HELLO_RETRY);
+
+ /**
+ *= https://tools.ietf.org/rfc/rfc8446#4.1.4
+ *# Upon receipt of a HelloRetryRequest, the client MUST check the
+ *# legacy_version
+ **/
+ POSIX_ENSURE(legacy_version == S2N_TLS12, S2N_ERR_INVALID_HELLO_RETRY);
+
POSIX_GUARD(s2n_set_hello_retry_required(conn));
}
@@ -121,6 +145,17 @@ static int s2n_server_hello_parse(struct s2n_connection *conn)
POSIX_ENSURE_REF(cipher_suite_wire);
POSIX_GUARD(s2n_stuffer_read_uint8(in, &compression_method));
+
+ /**
+ *= https://tools.ietf.org/rfc/rfc8446#4.1.3
+ *# legacy_compression_method: A single byte which MUST have the
+ *# value 0.
+ *
+ *= https://tools.ietf.org/rfc/rfc8446#4.1.4
+ *# Upon receipt of a HelloRetryRequest, the client MUST check the
+ *# legacy_version, legacy_session_id_echo, cipher_suite, and
+ *# legacy_compression_method
+ **/
S2N_ERROR_IF(compression_method != S2N_TLS_COMPRESSION_METHOD_NULL, S2N_ERR_BAD_MESSAGE);
bool session_ids_match = session_id_len != 0 && session_id_len == conn->session_id_len
@@ -131,16 +166,43 @@ static int s2n_server_hello_parse(struct s2n_connection *conn)
POSIX_GUARD(s2n_server_extensions_recv(conn, in));
+ /**
+ *= https://tools.ietf.org/rfc/rfc8446#4.1.4
+ *# The server's extensions MUST contain "supported_versions".
+ **/
+ if (s2n_is_hello_retry_message(conn)) {
+ s2n_extension_type_id supported_versions_id = s2n_unsupported_extension;
+ POSIX_GUARD(s2n_extension_supported_iana_value_to_id(TLS_EXTENSION_SUPPORTED_VERSIONS, &supported_versions_id));
+ POSIX_ENSURE(S2N_CBIT_TEST(conn->extension_responses_received, supported_versions_id),
+ S2N_ERR_MISSING_EXTENSION);
+ }
+
if (conn->server_protocol_version >= S2N_TLS13) {
+
+ /**
+ *= https://www.rfc-editor.org/rfc/rfc8446#section-4.1.3
+ *# A client which
+ *# receives a legacy_session_id_echo field that does not match what
+ *# it sent in the ClientHello MUST abort the handshake with an
+ *# "illegal_parameter" alert.
+ *
+ *= https://tools.ietf.org/rfc/rfc8446#4.1.4
+ *# Upon receipt of a HelloRetryRequest, the client MUST check the
+ *# legacy_version, legacy_session_id_echo
+ **/
POSIX_ENSURE(session_ids_match || (session_id_len == 0 && conn->session_id_len == 0), S2N_ERR_BAD_MESSAGE);
+
conn->actual_protocol_version = conn->server_protocol_version;
POSIX_GUARD(s2n_set_cipher_as_client(conn, cipher_suite_wire));
} else {
- conn->server_protocol_version = (uint8_t)(protocol_version[0] * 10) + protocol_version[1];
+ conn->server_protocol_version = legacy_version;
POSIX_ENSURE(!s2n_client_detect_downgrade_mechanism(conn), S2N_ERR_PROTOCOL_DOWNGRADE_DETECTED);
POSIX_ENSURE(!s2n_connection_is_quic_enabled(conn), S2N_ERR_PROTOCOL_VERSION_UNSUPPORTED);
+ /* Hello retries are only supported in >=TLS1.3. */
+ POSIX_ENSURE(!s2n_is_hello_retry_handshake(conn), S2N_ERR_BAD_MESSAGE);
+
/*
*= https://tools.ietf.org/rfc/rfc8446#appendix-D.3
*# A client that attempts to send 0-RTT data MUST fail a connection if
diff --git a/contrib/restricted/aws/s2n/tls/s2n_signature_scheme.c b/contrib/restricted/aws/s2n/tls/s2n_signature_scheme.c
index 6ccddacab6..2ccc0fd651 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_signature_scheme.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_signature_scheme.c
@@ -260,6 +260,28 @@ const struct s2n_signature_scheme* const s2n_sig_scheme_pref_list_20200207[] = {
&s2n_ecdsa_sha1,
};
+/*
+ * These signature schemes were chosen based on the following specification:
+ * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-52r2.pdf
+ */
+const struct s2n_signature_scheme* const s2n_sig_scheme_pref_list_default_fips[] = {
+ /* RSA PKCS1 - TLS1.2 */
+ &s2n_rsa_pkcs1_sha256,
+ &s2n_rsa_pkcs1_sha384,
+ &s2n_rsa_pkcs1_sha512,
+
+ /* ECDSA - TLS 1.2 */
+ &s2n_ecdsa_sha256, /* same iana value as TLS 1.3 s2n_ecdsa_secp256r1_sha256 */
+ &s2n_ecdsa_sha384, /* same iana value as TLS 1.3 s2n_ecdsa_secp384r1_sha384 */
+ &s2n_ecdsa_sha512,
+ &s2n_ecdsa_sha224,
+};
+
+const struct s2n_signature_preferences s2n_signature_preferences_default_fips = {
+ .count = s2n_array_len(s2n_sig_scheme_pref_list_default_fips),
+ .signature_schemes = s2n_sig_scheme_pref_list_default_fips,
+};
+
/* Add s2n_ecdsa_secp521r1_sha512 */
const struct s2n_signature_scheme* const s2n_sig_scheme_pref_list_20201021[] = {
/* RSA PSS */
diff --git a/contrib/restricted/aws/s2n/tls/s2n_signature_scheme.h b/contrib/restricted/aws/s2n/tls/s2n_signature_scheme.h
index 3f78d8a500..d8eee975ab 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_signature_scheme.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_signature_scheme.h
@@ -77,6 +77,7 @@ extern const struct s2n_signature_preferences s2n_signature_preferences_20140601
extern const struct s2n_signature_preferences s2n_signature_preferences_20200207;
extern const struct s2n_signature_preferences s2n_signature_preferences_20201021;
extern const struct s2n_signature_preferences s2n_signature_preferences_20210816;
+extern const struct s2n_signature_preferences s2n_signature_preferences_default_fips;
extern const struct s2n_signature_preferences s2n_signature_preferences_null;
extern const struct s2n_signature_preferences s2n_certificate_signature_preferences_20201110;
diff --git a/contrib/restricted/aws/s2n/utils/s2n_random.c b/contrib/restricted/aws/s2n/utils/s2n_random.c
index 295c87006f..9c0efc0f9f 100644
--- a/contrib/restricted/aws/s2n/utils/s2n_random.c
+++ b/contrib/restricted/aws/s2n/utils/s2n_random.c
@@ -14,6 +14,7 @@
*/
#include <openssl/engine.h>
+#include <openssl/rand.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -28,25 +29,20 @@
#include <errno.h>
#include <time.h>
-#include "api/s2n.h"
-
#if defined(S2N_CPUID_AVAILABLE)
#include <cpuid.h>
#endif
-#include "stuffer/s2n_stuffer.h"
-
+#include "api/s2n.h"
#include "crypto/s2n_drbg.h"
-
#include "error/s2n_errno.h"
-
+#include "stuffer/s2n_stuffer.h"
+#include "utils/s2n_fork_detection.h"
#include "utils/s2n_result.h"
#include "utils/s2n_safety.h"
#include "utils/s2n_random.h"
#include "utils/s2n_mem.h"
-#include <openssl/rand.h>
-
#define ENTROPY_SOURCE "/dev/urandom"
/* See https://en.wikipedia.org/wiki/CPUID */
@@ -60,14 +56,19 @@
static int entropy_fd = UNINITIALIZED_ENTROPY_FD;
-static __thread struct s2n_drbg per_thread_private_drbg = {0};
-static __thread struct s2n_drbg per_thread_public_drbg = {0};
-
-static void *zeroed_when_forked_page = NULL;
-static int zero = 0;
+struct s2n_rand_state {
+ uint64_t cached_fork_generation_number;
+ struct s2n_drbg public_drbg;
+ struct s2n_drbg private_drbg;
+ bool drbgs_initialized;
+};
-static __thread void *zero_if_forked_ptr = &zero;
-#define zero_if_forked (* (int *) zero_if_forked_ptr)
+static __thread struct s2n_rand_state s2n_per_thread_rand_state = {
+ .cached_fork_generation_number = 0,
+ .public_drbg = {0},
+ .private_drbg = {0},
+ .drbgs_initialized = false
+};
static int s2n_rand_init_impl(void);
static int s2n_rand_cleanup_impl(void);
@@ -79,6 +80,7 @@ static s2n_rand_cleanup_callback s2n_rand_cleanup_cb = s2n_rand_cleanup_impl;
static s2n_rand_seed_callback s2n_rand_seed_cb = s2n_rand_urandom_impl;
static s2n_rand_mix_callback s2n_rand_mix_cb = s2n_rand_urandom_impl;
+/* non-static for SAW proof */
bool s2n_cpu_supports_rdrand() {
#if defined(S2N_CPUID_AVAILABLE)
uint32_t eax, ebx, ecx, edx;
@@ -128,65 +130,74 @@ S2N_RESULT s2n_get_mix_entropy(struct s2n_blob *blob)
return S2N_RESULT_OK;
}
-void s2n_on_fork(void)
-{
- zero_if_forked = 0;
-}
-
-static inline S2N_RESULT s2n_defend_if_forked(void)
+static S2N_RESULT s2n_init_drbgs(void)
{
uint8_t s2n_public_drbg[] = "s2n public drbg";
uint8_t s2n_private_drbg[] = "s2n private drbg";
- struct s2n_blob public = {.data = s2n_public_drbg,.size = sizeof(s2n_public_drbg) };
- struct s2n_blob private = {.data = s2n_private_drbg,.size = sizeof(s2n_private_drbg) };
+ struct s2n_blob public = { .data = s2n_public_drbg, .size = sizeof(s2n_public_drbg) };
+ struct s2n_blob private = { .data = s2n_private_drbg, .size = sizeof(s2n_private_drbg) };
- if (zero_if_forked == 0) {
- /* Clean up the old drbg first */
- RESULT_GUARD(s2n_rand_cleanup_thread());
- /* Instantiate the new ones */
- RESULT_GUARD(s2n_drbg_instantiate(&per_thread_public_drbg, &public, S2N_AES_128_CTR_NO_DF_PR));
- RESULT_GUARD(s2n_drbg_instantiate(&per_thread_private_drbg, &private, S2N_AES_128_CTR_NO_DF_PR));
- zero_if_forked_ptr = zeroed_when_forked_page;
- zero_if_forked = 1;
- }
+ RESULT_GUARD(s2n_drbg_instantiate(&s2n_per_thread_rand_state.public_drbg, &public, S2N_AES_128_CTR_NO_DF_PR));
+ RESULT_GUARD(s2n_drbg_instantiate(&s2n_per_thread_rand_state.private_drbg, &private, S2N_AES_256_CTR_NO_DF_PR));
+
+ s2n_per_thread_rand_state.drbgs_initialized = true;
return S2N_RESULT_OK;
}
-S2N_RESULT s2n_get_public_random_data(struct s2n_blob *blob)
+static S2N_RESULT s2n_ensure_initialized_drbgs(void)
{
- RESULT_GUARD(s2n_defend_if_forked());
+ if (s2n_per_thread_rand_state.drbgs_initialized == false) {
+ RESULT_GUARD(s2n_init_drbgs());
- uint32_t offset = 0;
- uint32_t remaining = blob->size;
+ /* Then cache the fork generation number. We just initialized the drbg
+ * states with new entropy and forking is not an external event.
+ */
+ uint64_t returned_fork_generation_number = 0;
+ RESULT_GUARD(s2n_get_fork_generation_number(&returned_fork_generation_number));
+ s2n_per_thread_rand_state.cached_fork_generation_number = returned_fork_generation_number;
+ }
- while(remaining) {
- struct s2n_blob slice = { 0 };
+ return S2N_RESULT_OK;
+}
- RESULT_GUARD_POSIX(s2n_blob_slice(blob, &slice, offset, MIN(remaining, S2N_DRBG_GENERATE_LIMIT)));;
+/* s2n_ensure_uniqueness() implements defenses against uniqueness
+ * breaking events that might cause duplicated drbg states. Currently, only
+ * implements fork detection.
+ */
+static S2N_RESULT s2n_ensure_uniqueness(void)
+{
+ uint64_t returned_fork_generation_number = 0;
+ RESULT_GUARD(s2n_get_fork_generation_number(&returned_fork_generation_number));
- RESULT_GUARD(s2n_drbg_generate(&per_thread_public_drbg, &slice));
+ if (returned_fork_generation_number != s2n_per_thread_rand_state.cached_fork_generation_number) {
- remaining -= slice.size;
- offset += slice.size;
+ /* This assumes that s2n_rand_cleanup_thread() doesn't mutate any other
+ * state than the drbg states and it resets the drbg initialization
+ * boolean to false. s2n_ensure_initialized_drbgs() will cache the new
+ * fork generation number in the per thread state.
+ */
+ RESULT_GUARD(s2n_rand_cleanup_thread());
+ RESULT_GUARD(s2n_ensure_initialized_drbgs());
}
return S2N_RESULT_OK;
}
-S2N_RESULT s2n_get_private_random_data(struct s2n_blob *blob)
+static S2N_RESULT s2n_get_random_data(struct s2n_blob *out_blob,
+ struct s2n_drbg *drbg_state)
{
- RESULT_GUARD(s2n_defend_if_forked());
+ RESULT_GUARD(s2n_ensure_initialized_drbgs());
+ RESULT_GUARD(s2n_ensure_uniqueness());
uint32_t offset = 0;
- uint32_t remaining = blob->size;
+ uint32_t remaining = out_blob->size;
while(remaining) {
struct s2n_blob slice = { 0 };
- RESULT_GUARD_POSIX(s2n_blob_slice(blob, &slice, offset, MIN(remaining, S2N_DRBG_GENERATE_LIMIT)));;
-
- RESULT_GUARD(s2n_drbg_generate(&per_thread_private_drbg, &slice));
+ RESULT_GUARD_POSIX(s2n_blob_slice(out_blob, &slice, offset, MIN(remaining, S2N_DRBG_GENERATE_LIMIT)));
+ RESULT_GUARD(s2n_drbg_generate(drbg_state, &slice));
remaining -= slice.size;
offset += slice.size;
@@ -195,15 +206,29 @@ S2N_RESULT s2n_get_private_random_data(struct s2n_blob *blob)
return S2N_RESULT_OK;
}
+S2N_RESULT s2n_get_public_random_data(struct s2n_blob *blob)
+{
+ RESULT_GUARD(s2n_get_random_data(blob, &s2n_per_thread_rand_state.public_drbg));
+
+ return S2N_RESULT_OK;
+}
+
+S2N_RESULT s2n_get_private_random_data(struct s2n_blob *blob)
+{
+ RESULT_GUARD(s2n_get_random_data(blob, &s2n_per_thread_rand_state.private_drbg));
+
+ return S2N_RESULT_OK;
+}
+
S2N_RESULT s2n_get_public_random_bytes_used(uint64_t *bytes_used)
{
- RESULT_GUARD(s2n_drbg_bytes_used(&per_thread_public_drbg, bytes_used));
+ RESULT_GUARD(s2n_drbg_bytes_used(&s2n_per_thread_rand_state.public_drbg, bytes_used));
return S2N_RESULT_OK;
}
S2N_RESULT s2n_get_private_random_bytes_used(uint64_t *bytes_used)
{
- RESULT_GUARD(s2n_drbg_bytes_used(&per_thread_private_drbg, bytes_used));
+ RESULT_GUARD(s2n_drbg_bytes_used(&s2n_per_thread_rand_state.private_drbg, bytes_used));
return S2N_RESULT_OK;
}
@@ -328,7 +353,7 @@ static int s2n_rand_init_impl(void)
{
OPEN:
entropy_fd = open(ENTROPY_SOURCE, O_RDONLY);
- if (entropy_fd == S2N_FAILURE) {
+ if (entropy_fd == -1) {
if (errno == EINTR) {
goto OPEN;
}
@@ -344,33 +369,9 @@ static int s2n_rand_init_impl(void)
S2N_RESULT s2n_rand_init(void)
{
- uint32_t pagesize;
-
RESULT_GUARD_POSIX(s2n_rand_init_cb());
- pagesize = s2n_mem_get_page_size();
-
- /* We need a single-aligned page for our protected memory region */
- RESULT_ENSURE(posix_memalign(&zeroed_when_forked_page, pagesize, pagesize) == S2N_SUCCESS, S2N_ERR_OPEN_RANDOM);
- RESULT_ENSURE(zeroed_when_forked_page != NULL, S2N_ERR_OPEN_RANDOM);
-
- /* Initialized to zero to ensure that we seed our DRBGs */
- zero_if_forked = 0;
-
- /* INHERIT_ZERO and WIPEONFORK reset a page to all-zeroes when a fork occurs */
-#if defined(MAP_INHERIT_ZERO)
- RESULT_ENSURE(minherit(zeroed_when_forked_page, pagesize, MAP_INHERIT_ZERO) != S2N_FAILURE, S2N_ERR_OPEN_RANDOM);
-#endif
-
-#if defined(MADV_WIPEONFORK)
- RESULT_ENSURE(madvise(zeroed_when_forked_page, pagesize, MADV_WIPEONFORK) == S2N_SUCCESS, S2N_ERR_OPEN_RANDOM);
-#endif
-
- /* For defence in depth */
- RESULT_ENSURE(pthread_atfork(NULL, NULL, s2n_on_fork) == S2N_SUCCESS, S2N_ERR_OPEN_RANDOM);
-
- /* Seed everything */
- RESULT_GUARD(s2n_defend_if_forked());
+ RESULT_GUARD(s2n_ensure_initialized_drbgs());
#if S2N_LIBCRYPTO_SUPPORTS_CUSTOM_RAND
/* Create an engine */
@@ -423,12 +424,6 @@ S2N_RESULT s2n_rand_cleanup(void)
}
#endif
- if (zeroed_when_forked_page != NULL) {
- free(zeroed_when_forked_page);
- zeroed_when_forked_page = NULL;
- zero_if_forked_ptr = &zero;
- }
-
s2n_rand_init_cb = s2n_rand_init_impl;
s2n_rand_cleanup_cb = s2n_rand_cleanup_impl;
s2n_rand_seed_cb = s2n_rand_urandom_impl;
@@ -439,22 +434,29 @@ S2N_RESULT s2n_rand_cleanup(void)
S2N_RESULT s2n_rand_cleanup_thread(void)
{
- RESULT_GUARD(s2n_drbg_wipe(&per_thread_private_drbg));
- RESULT_GUARD(s2n_drbg_wipe(&per_thread_public_drbg));
+ /* Currently, it is only safe for this function to mutate the drbg states
+ * in the per thread rand state. See s2n_ensure_uniqueness().
+ */
+ RESULT_GUARD(s2n_drbg_wipe(&s2n_per_thread_rand_state.private_drbg));
+ RESULT_GUARD(s2n_drbg_wipe(&s2n_per_thread_rand_state.public_drbg));
+
+ s2n_per_thread_rand_state.drbgs_initialized = false;
return S2N_RESULT_OK;
}
-/*
- * This must only be used for unit tests. Any real use is dangerous and will be overwritten in s2n_defend_if_forked if
- * it is forked. This was added to support known answer tests that use OpenSSL and s2n_get_private_random_data directly.
+/* This must only be used for unit tests. Any real use is dangerous and will be
+ * overwritten in s2n_ensure_uniqueness() if it is forked. This was added to
+ * support known answer tests that use OpenSSL and s2n_get_private_random_data
+ * directly.
*/
S2N_RESULT s2n_set_private_drbg_for_test(struct s2n_drbg drbg)
{
RESULT_ENSURE(s2n_in_unit_test(), S2N_ERR_NOT_IN_UNIT_TEST);
- RESULT_GUARD(s2n_drbg_wipe(&per_thread_private_drbg));
+ RESULT_GUARD(s2n_drbg_wipe(&s2n_per_thread_rand_state.private_drbg));
+
+ s2n_per_thread_rand_state.private_drbg = drbg;
- per_thread_private_drbg = drbg;
return S2N_RESULT_OK;
}