diff options
author | robot-contrib <robot-contrib@yandex-team.com> | 2022-07-09 10:40:08 +0300 |
---|---|---|
committer | robot-contrib <robot-contrib@yandex-team.com> | 2022-07-09 10:40:08 +0300 |
commit | 22acf19be42357b6bb0e7d601b0dc28695191463 (patch) | |
tree | a35a222fffb28fcf8a82dd7efe67f2276bfd1858 /contrib/restricted/aws/s2n/pq-crypto | |
parent | 7a7d303e197aa7e4f43c61cc289d8652df38ab43 (diff) | |
download | ydb-22acf19be42357b6bb0e7d601b0dc28695191463.tar.gz |
Update contrib/restricted/aws/s2n to 1.3.16
Diffstat (limited to 'contrib/restricted/aws/s2n/pq-crypto')
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); |