diff --git a/Makefile b/Makefile index 833ea1a..5192d01 100755 --- a/Makefile +++ b/Makefile @@ -77,7 +77,7 @@ else CFLAGS= $(EXTRA_CFLAGS) endif CFLAGS+= $(VALGRIND_CFLAGS) -CFLAGS+= -std=gnu11 -Wall $(ADDITIONAL_SETTINGS) -D $(ARCHITECTURE) -D __NIX__ -D $(USE_OPT_LEVEL) $(MULX) $(ADX) -Wno-missing-braces +CFLAGS+= -std=gnu11 -Wall $(ADDITIONAL_SETTINGS) -D $(ARCHITECTURE) -D __NIX__ -D $(USE_OPT_LEVEL) $(MULX) $(ADX) -Wno-missing-braces -Wno-logical-not-parentheses LDFLAGS=-lm ifeq "$(USE_OPT_LEVEL)" "_GENERIC_" EXTRA_OBJECTS_434=objs434/fp_generic.o diff --git a/src/compression/sidh_compressed.c b/src/compression/sidh_compressed.c index c894b92..858381a 100644 --- a/src/compression/sidh_compressed.c +++ b/src/compression/sidh_compressed.c @@ -51,7 +51,7 @@ int random_mod_order_A(unsigned char* random_digits) int random_mod_order_B(unsigned char* random_digits) { // Generation of Bob's secret key // Outputs random value in [0, 2^Floor(Log(2, oB)) - 1]. Returns 1 on error - + if (randombytes(random_digits, SECRETKEY_B_BYTES) != 0) return 1; FormatPrivKey_B(random_digits); @@ -422,11 +422,11 @@ static void Dlogs2_dual(const f2elm_t *f, int *D, digit_t *d0, digit_t *c0, digi } -static void PKBDecompression_extended(const unsigned char* SecretKeyA, const unsigned char* CompressedPKB, point_proj_t R, f2elm_t A, unsigned char* tphiBKA_t) +static int PKBDecompression_extended(const unsigned char* SecretKeyA, const unsigned char* CompressedPKB, point_proj_t R, f2elm_t A, unsigned char* tphiBKA_t) { // Bob's PK decompression -- SIKE protocol uint64_t mask = (digit_t)(-1); unsigned char qnr, ind; - f2elm_t A24, Adiv2 = {0}; + f2elm_t A24, Atmp = {0}; digit_t tmp1[2*NWORDS_ORDER] = {0}, tmp2[2*NWORDS_ORDER] = {0}, inv[NWORDS_ORDER] = {0}, scal[2*NWORDS_ORDER] = {0}; digit_t SKin[NWORDS_ORDER] = {0}, a0[NWORDS_ORDER] = {0}, a1[NWORDS_ORDER] = {0}, b0[NWORDS_ORDER] = {0}, b1[NWORDS_ORDER] = {0}; point_proj_t Rs[3] = {0}; @@ -434,6 +434,18 @@ static void PKBDecompression_extended(const unsigned char* SecretKeyA, const uns mask >>= (MAXBITS_ORDER - OALICE_BITS); fp2_decode(&CompressedPKB[4*ORDER_A_ENCODED_BYTES], A); + + // Check that A^2 - 4 is a square in GF(p^2) + fp2sqr_mont(A, A24); + fpcopy((digit_t*)Montgomery_one, Atmp[0]); + fp2add(Atmp, Atmp, Atmp); + fp2add(Atmp, Atmp, Atmp); + fp2sub(A24, Atmp, A24); + fp2correction(A24); + + if (!is_sqr_fp2(A24, Atmp[0])) + return 1; + qnr = CompressedPKB[4*ORDER_A_ENCODED_BYTES + FP2_ENCODED_BYTES] & 0x01; ind = CompressedPKB[4*ORDER_A_ENCODED_BYTES + FP2_ENCODED_BYTES + 1]; @@ -478,12 +490,13 @@ static void PKBDecompression_extended(const unsigned char* SecretKeyA, const uns Ladder3pt_dual(Rs, scal, ALICE, R, A24); } - fp2div2(A,Adiv2); - xTPLe_fast(R, R, Adiv2, OBOB_EXPON); + fp2div2(A, Atmp); // A/2 + xTPLe_fast(R, R, Atmp, OBOB_EXPON); fp2_encode(R->X, tphiBKA_t); fp2_encode(R->Z, &tphiBKA_t[FP2_ENCODED_BYTES]); encode_to_bytes(inv, &tphiBKA_t[2*FP2_ENCODED_BYTES], ORDER_A_ENCODED_BYTES); + return 0; } @@ -684,10 +697,12 @@ static int EphemeralSecretAgreement_A_extended(const unsigned char* PrivateKeyA, f2elm_t jinv, coeff[5], A; f2elm_t param_A = {0}; - if (sike == 1) - PKBDecompression_extended(PrivateKeyA, PKB, R, param_A, SharedSecretA+FP2_ENCODED_BYTES); - else + if (sike == 1) { + if (!PKBDecompression_extended(PrivateKeyA, PKB, R, param_A, SharedSecretA + FP2_ENCODED_BYTES) == 0) + return 1; + } else { PKBDecompression(PrivateKeyA, PKB, R, param_A); + } fp2copy(param_A, A); fpadd((digit_t*)&Montgomery_one, (digit_t*)&Montgomery_one, C24[0]); diff --git a/src/compression/sike_compressed.c b/src/compression/sike_compressed.c index 7376f69..f8bf165 100644 --- a/src/compression/sike_compressed.c +++ b/src/compression/sike_compressed.c @@ -73,9 +73,12 @@ int crypto_kem_dec(unsigned char *ss, const unsigned char *ct, const unsigned ch unsigned char jinvariant_[FP2_ENCODED_BYTES + 2*FP2_ENCODED_BYTES + SECRETKEY_A_BYTES] = {0}, h_[MSG_BYTES]; unsigned char temp[CRYPTO_CIPHERTEXTBYTES + MSG_BYTES] = {0}; unsigned char* tphiBKA_t = &jinvariant_[FP2_ENCODED_BYTES]; + int8_t selector = -1; // Decrypt - EphemeralSecretAgreement_A_extended(sk + MSG_BYTES, ct, jinvariant_, 1); + if (!EphemeralSecretAgreement_A_extended(sk + MSG_BYTES, ct, jinvariant_, 1) == 0) { + goto Hashing; + } shake256(h_, MSG_BYTES, jinvariant_, FP2_ENCODED_BYTES); for (int i = 0; i < MSG_BYTES; i++) { @@ -89,7 +92,8 @@ int crypto_kem_dec(unsigned char *ss, const unsigned char *ct, const unsigned ch // Generate shared secret ss <- H(m||ct), or output ss <- H(s||ct) in case of ct verification failure // No need to recompress, just check if x(phi(P) + t*phi(Q)) == x((a0 + t*a1)*R1 + (b0 + t*b1)*R2) - int8_t selector = validate_ciphertext(ephemeralsk_, ct, &sk[MSG_BYTES + SECRETKEY_A_BYTES + CRYPTO_PUBLICKEYBYTES], tphiBKA_t); + selector = validate_ciphertext(ephemeralsk_, ct, &sk[MSG_BYTES + SECRETKEY_A_BYTES + CRYPTO_PUBLICKEYBYTES], tphiBKA_t); +Hashing: // If ct validation passes (selector = 0) then do ss = H(m||ct), otherwise (selector = -1) load s to do ss = H(s||ct) ct_cmov(temp, sk, MSG_BYTES, selector); memcpy(&temp[MSG_BYTES], ct, CRYPTO_CIPHERTEXTBYTES); diff --git a/src/config.h b/src/config.h index d2fcc77..646d766 100644 --- a/src/config.h +++ b/src/config.h @@ -92,6 +92,10 @@ #define RADIX64 64 +// Switch for enabling SIKE's public key validation during decapsulation +#define PK_VALIDATION + + // Selection of generic, portable implementation #if defined(_GENERIC_) diff --git a/src/ec_isogeny.c b/src/ec_isogeny.c index 7c693c3..8e64391 100644 --- a/src/ec_isogeny.c +++ b/src/ec_isogeny.c @@ -32,11 +32,10 @@ void xDBLe(const point_proj_t P, point_proj_t Q, const f2elm_t A24plus, const f2 { // 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((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); } } @@ -151,11 +150,10 @@ void xTPLe(const point_proj_t P, point_proj_t Q, const f2elm_t A24minus, const f { // 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((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); } } @@ -366,8 +364,51 @@ static void LADDER3PT(const f2elm_t xP, const f2elm_t xQ, const f2elm_t xPQ, con swap_points(R, R2, mask); } -#ifdef COMPRESS +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; + + 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); + } +} + +#ifdef COMPRESS static void RecoverY(const f2elm_t A, const point_proj_t *xs, point_full_proj_t *Rs) { @@ -481,49 +522,6 @@ void Double(point_proj_t P, point_proj_t Q, f2elm_t A24, const int k) } -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 5M + 6S + 9A = 27p + 61a. - // 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; - - 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 - fp2shl(t1, 2, 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 - fp2shl(t2, 2, 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 k*(5M + 6S + 9A) - // 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. - point_proj_t T; - - copy_words((digit_t*)P, (digit_t*)T, 2*2*NWORDS_FIELD); - for (int j = 0; j < e; j++) { - xTPL_fast(T, T, A2); - } - copy_words((digit_t*)T, (digit_t*)Q, 2*2*NWORDS_FIELD); -} - - void xDBL_e(const point_proj_t P, point_proj_t Q, const f2elm_t A24, const int e) { // Doubling of a Montgomery point in projective coordinates (X:Z) over affine curve coefficient A. // Input: projective Montgomery x-coordinates P = (X1:Z1), where x1=X1/Z1 and Montgomery curve constants (A+2)/4. diff --git a/src/fpx.c b/src/fpx.c index c65988a..a668fea 100644 --- a/src/fpx.c +++ b/src/fpx.c @@ -336,10 +336,10 @@ void fp2mul_mont(const f2elm_t a, const f2elm_t b, f2elm_t c) // Inputs: a = a0+a1*i and b = b0+b1*i, where a0, a1, b0, b1 are in [0, 2*p-1] // Output: c = c0+c1*i, where c0, c1 are in [0, 2*p-1] #if defined(_MULX_) && defined(_ADX_) && (OS_TARGET == OS_NIX) && (NBITS_FIELD != 751) - felm_t t1; - - fp2mul_c0_mont(a[0], b[0], t1); // c0 = a0*b0 - a1*b1 - fp2mul_c1_mont(a[0], b[0], c[1]); // c1 = a0*b1 + a1*b0 + felm_t t1; + + fp2mul_c0_mont(a[0], b[0], t1); // c0 = a0*b0 - a1*b1 + fp2mul_c1_mont(a[0], b[0], c[1]); // c1 = a0*b1 + a1*b0 fpcopy(t1, c[0]); #else felm_t t1, t2; @@ -849,19 +849,47 @@ void mp_shiftl1(digit_t* x, const unsigned int nwords) x[0] <<= 1; } -#ifdef COMPRESS static inline 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. - unsigned int i; - for (i = 0; i < NWORDS_FIELD; i++) { + for (unsigned int i = 0; i < NWORDS_FIELD; i++) { if (x[i] != 0) return 0; } return 1; } + +unsigned char is_sqr_fp2(const f2elm_t a, felm_t s) +{ // Test if a is a square in GF(p^2) and return 1 if true, 0 otherwise + // If a is a quadratic residue, s will be assigned with a partially computed square root of a + int i; + felm_t a0, a1, z, temp; + + fpsqr_mont(a[0], a0); + fpsqr_mont(a[1], a1); + fpadd(a0, a1, z); + + fpcopy(z, s); + for (i = 0; i < OALICE_BITS - 2; i++) { + fpsqr_mont(s, s); + } + for (i = 0; i < OBOB_EXPON; i++) { + fpsqr_mont(s, temp); + fpmul_mont(s, temp, s); + } + fpsqr_mont(s, temp); // s = z^((p+1)/4) + fpcorrection(temp); + fpcorrection(z); + if (memcmp(temp, z, NBITS_TO_NBYTES(NBITS_FIELD)) != 0) // s^2 != z? + return 0; + + return 1; +} + +#ifdef COMPRESS + static inline unsigned int is_felm_one(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. @@ -873,6 +901,7 @@ static inline unsigned int is_felm_one(const felm_t x) return 1; } + void mul3(unsigned char *a) { // Computes a = 3*a // The input is assumed to be OBOB_BITS-2 bits long and stored in SECRETKEY_B_BYTES @@ -950,10 +979,6 @@ void cube_Fp2_cycl(f2elm_t a, const felm_t one) } - - - - static bool is_zero(digit_t* a, unsigned int nwords) { // Check if multiprecision element is zero. // SECURITY NOTE: This function does not run in constant time. @@ -968,34 +993,6 @@ static bool is_zero(digit_t* a, unsigned int nwords) } -unsigned char is_sqr_fp2(const f2elm_t a, felm_t s) -{ // Test if a is a square in GF(p^2) and return 1 if true, 0 otherwise - // If a is a quadratic residue, s will be assigned with a partially computed square root of a - int i; - felm_t a0,a1,z,temp; - - fpsqr_mont(a[0],a0); - fpsqr_mont(a[1],a1); - fpadd(a0,a1,z); - - fpcopy(z,s); - for (i = 0; i < OALICE_BITS - 2; i++) { - fpsqr_mont(s, s); - } - for (i = 0; i < OBOB_EXPON; i++) { - fpsqr_mont(s, temp); - fpmul_mont(s, temp, s); - } - fpsqr_mont(s,temp); // s = z^((p+1)/4) - fpcorrection(temp); - fpcorrection(z); - if (memcmp(temp, z, NBITS_TO_NBYTES(NBITS_FIELD)) != 0) // s^2 !=? z - return 0; - - return 1; -} - - void sqrt_Fp2(const f2elm_t u, f2elm_t y) { // Computes square roots of elements in (Fp2)^2 using Hamburg's trick. felm_t t0, t1, t2, t3; diff --git a/src/sidh.c b/src/sidh.c index 47386b3..b8bfd99 100644 --- a/src/sidh.c +++ b/src/sidh.c @@ -271,8 +271,52 @@ int EphemeralSecretAgreement_A(const unsigned char* PrivateKeyA, const unsigned } -int EphemeralSecretAgreement_B(const unsigned char* PrivateKeyB, const unsigned char* PublicKeyA, unsigned char* SharedSecretB) -{ // Bob's ephemeral shared secret computation +static int publickey_validation(const f2elm_t* PKB, const f2elm_t A, const f2elm_t A24plus, const f2elm_t A24minus) +{ // Public key validation + point_proj_t P = { 0 }, Q = { 0 }; + f2elm_t A2, tmp1, 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((digit_t*)&Montgomery_one, (digit_t*)P->Z); + fp2copy(PKB[1], Q->X); + fpcopy((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[0]) && is_felm_zero(P->Z[1])) || (is_felm_zero(Q->Z[0]) && is_felm_zero(Q->Z[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, 2*NBITS_TO_NBYTES(NBITS_FIELD)) == 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[0]) || !is_felm_zero(P->Z[1]) || !is_felm_zero(Q->Z[0]) || !is_felm_zero(Q->Z[1])) + return 1; + +#if NBITS_FIELD == 610 // Additionally check that 8 | #E + if (!is_sqr_fp2(A24plus, tmp1[0]) || !is_sqr_fp2(A24minus, tmp1[0])) + return 1; +#else + (void)A24plus, (void)A24minus; +#endif + return 0; +} + + +int EphemeralSecretAgreement_B_extended(const unsigned char* PrivateKeyB, const unsigned char* PublicKeyA, unsigned char* SharedSecretB, unsigned int sike) +{ // Bob's ephemeral shared secret computation, including public key's validation (enabled through input "sike") // 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. @@ -294,6 +338,13 @@ int EphemeralSecretAgreement_B(const unsigned char* PrivateKeyB, const unsigned mp2_add(A, A24minus, A24plus); mp2_sub_p2(A, A24minus, A24minus); + if (sike == 1) { +#if defined(PK_VALIDATION) // Validation of public key + if (publickey_validation(PKB, A, A24plus, A24minus) == 1) + return 1; +#endif + } + // Retrieve kernel point decode_to_digits(PrivateKeyB, SecretKeyB, SECRETKEY_B_BYTES, NWORDS_ORDER); LADDER3PT(PKB[0], PKB[1], PKB[2], SecretKeyB, BOB, R, A); @@ -329,4 +380,15 @@ int EphemeralSecretAgreement_B(const unsigned char* PrivateKeyB, const unsigned fp2_encode(jinv, SharedSecretB); // Format shared secret return 0; +} + + +int EphemeralSecretAgreement_B(const unsigned char* PrivateKeyB, const unsigned char* PublicKeyA, unsigned char* SharedSecretB) +{ // 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. + + return EphemeralSecretAgreement_B_extended(PrivateKeyB, PublicKeyA, SharedSecretB, 0); } \ No newline at end of file diff --git a/src/sike.c b/src/sike.c index 0f15422..2822c68 100644 --- a/src/sike.c +++ b/src/sike.c @@ -90,12 +90,15 @@ int crypto_kem_dec(unsigned char *ss, const unsigned char *ct, const unsigned ch unsigned char h_[MSG_BYTES]; unsigned char c0_[CRYPTO_PUBLICKEYBYTES]; unsigned char temp[CRYPTO_CIPHERTEXTBYTES+MSG_BYTES]; + int8_t selector = -1; #ifdef DO_VALGRIND_CHECK VALGRIND_MAKE_MEM_UNDEFINED(sk, CRYPTO_SECRETKEYBYTES); #endif // Decrypt - EphemeralSecretAgreement_B(sk + MSG_BYTES, ct, jinvariant_); + if (!EphemeralSecretAgreement_B_extended(sk + MSG_BYTES, ct, jinvariant_, 1) == 0) { + goto Hashing; + } shake256(h_, MSG_BYTES, jinvariant_, FP2_ENCODED_BYTES); for (int i = 0; i < MSG_BYTES; i++) { temp[i] = ct[i + CRYPTO_PUBLICKEYBYTES] ^ h_[i]; @@ -109,7 +112,8 @@ int crypto_kem_dec(unsigned char *ss, const unsigned char *ct, const unsigned ch // Generate shared secret ss <- H(m||ct), or output ss <- H(s||ct) in case of ct verification failure EphemeralKeyGeneration_A(ephemeralsk_, c0_); // If selector = 0 then do ss = H(m||ct), else if selector = -1 load s to do ss = H(s||ct) - int8_t selector = ct_compare(c0_, ct, CRYPTO_PUBLICKEYBYTES); + selector = ct_compare(c0_, ct, CRYPTO_PUBLICKEYBYTES); +Hashing: ct_cmov(temp, sk, MSG_BYTES, selector); memcpy(&temp[MSG_BYTES], ct, CRYPTO_CIPHERTEXTBYTES); shake256(ss, CRYPTO_BYTES, temp, CRYPTO_CIPHERTEXTBYTES+MSG_BYTES);