aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/restricted/aws/s2n/pq-crypto
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 /contrib/restricted/aws/s2n/pq-crypto
parent7a7d303e197aa7e4f43c61cc289d8652df38ab43 (diff)
downloadydb-22acf19be42357b6bb0e7d601b0dc28695191463.tar.gz
Update contrib/restricted/aws/s2n to 1.3.16
Diffstat (limited to 'contrib/restricted/aws/s2n/pq-crypto')
-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
11 files changed, 263 insertions, 17 deletions
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);