From 600212c29b7a35c622dfb142e037eeaa33200210 Mon Sep 17 00:00:00 2001 From: Tiago Oliveira Date: Wed, 17 Apr 2024 00:39:11 +0100 Subject: [PATCH] xwing: review + sct. --- .../mlkem/mlkem768/amd64/ref/params.jinc | 7 + src/crypto_kem/xwing/META.yml | 6 +- src/crypto_kem/xwing/amd64/avx2/kem.jazz | 54 +++- src/crypto_kem/xwing/amd64/avx2/kem.jinc | 171 ----------- src/crypto_kem/xwing/amd64/avx2/params.jinc | 21 -- .../xwing/amd64/avx2/scalarmult_mulx.jinc | 33 -- src/crypto_kem/xwing/amd64/ref/kem.jazz | 54 +++- src/crypto_kem/xwing/amd64/ref/kem.jinc | 283 ++++++++---------- src/crypto_kem/xwing/amd64/ref/params.jinc | 26 +- .../xwing/amd64/ref/scalarmult.jinc | 51 ++-- src/crypto_kem/xwing/amd64/ref/sha3.jinc | 44 +++ .../curve25519/amd64/ref4/curve25519.jinc | 10 +- 12 files changed, 299 insertions(+), 461 deletions(-) delete mode 100644 src/crypto_kem/xwing/amd64/avx2/kem.jinc delete mode 100644 src/crypto_kem/xwing/amd64/avx2/params.jinc delete mode 100644 src/crypto_kem/xwing/amd64/avx2/scalarmult_mulx.jinc create mode 100644 src/crypto_kem/xwing/amd64/ref/sha3.jinc diff --git a/src/crypto_kem/mlkem/mlkem768/amd64/ref/params.jinc b/src/crypto_kem/mlkem/mlkem768/amd64/ref/params.jinc index 085e975c..9e38ad46 100644 --- a/src/crypto_kem/mlkem/mlkem768/amd64/ref/params.jinc +++ b/src/crypto_kem/mlkem/mlkem768/amd64/ref/params.jinc @@ -14,3 +14,10 @@ param int MLKEM_CT_LEN = MLKEM_POLYVECCOMPRESSEDBYTES + MLKEM_POLYCOMPRESSEDBYTE param int MLKEM_INDCPA_PUBLICKEYBYTES = MLKEM_POLYVECBYTES + MLKEM_SYMBYTES; param int MLKEM_PUBLICKEYBYTES = MLKEM_INDCPA_PUBLICKEYBYTES; param int MLKEM_SSBYTES = 32; + +// the following is a patch to handle inconsistencies between ref/params.jinc and avx2/params.jinc (motivated by xwing); +// this needs to be fixed upstream, in formosa-mlkem +param int MLKEM_INDCPA_CIPHERTEXTBYTES = MLKEM_POLYVECCOMPRESSEDBYTES + MLKEM_POLYCOMPRESSEDBYTES; +param int MLKEM_INDCPA_SECRETKEYBYTES = MLKEM_POLYVECBYTES; +param int MLKEM_SECRETKEYBYTES = MLKEM_INDCPA_SECRETKEYBYTES + MLKEM_INDCPA_PUBLICKEYBYTES + 2*MLKEM_SYMBYTES; +param int MLKEM_CIPHERTEXTBYTES = MLKEM_INDCPA_CIPHERTEXTBYTES; diff --git a/src/crypto_kem/xwing/META.yml b/src/crypto_kem/xwing/META.yml index 9198864c..21c2b0e6 100644 --- a/src/crypto_kem/xwing/META.yml +++ b/src/crypto_kem/xwing/META.yml @@ -1,7 +1,7 @@ name: X-Wing type: kem -checksumsmall: 844bca7a113f642135f10d7ab047f8fbc137a6d0c7bbe64dbde0b48c46681872 -checksumbig: 05451934bd516a3b885896e7e448d9739ed1ccc67339f438db230bd479f026bb +checksumsmall: d80f0bfdf6d38a189cfffe48c048973521c02456bde1934475c38e0819c4afae +checksumbig: 607234d1da70d4441c64c8bb3deff3f22728a38942500457c92dbcdaf393d0c0 claimed-nist-level: 3 claimed-security: IND-CCA2 length-public-key: 1216 @@ -23,4 +23,4 @@ implementations: required_flags: # FIXME - avx2 - bmi2 - - popcnt \ No newline at end of file + - popcnt diff --git a/src/crypto_kem/xwing/amd64/avx2/kem.jazz b/src/crypto_kem/xwing/amd64/avx2/kem.jazz index aa7d4eea..21b5056c 100644 --- a/src/crypto_kem/xwing/amd64/avx2/kem.jazz +++ b/src/crypto_kem/xwing/amd64/avx2/kem.jazz @@ -1,33 +1,39 @@ -require "params.jinc" -require "kem.jinc" from Jade require "common/tofromstack.jinc" +from Jade require "crypto_kem/mlkem/mlkem768/amd64/avx2/kem.jinc" +from Jade require "crypto_kem/xwing/amd64/ref/kem.jinc" +from Jade require "crypto_kem/xwing/amd64/ref/params.jinc" + export fn jade_kem_xwing_amd64_avx2_keypair_derand(reg u64 public_key secret_key coins) -> reg u64 { - reg u64 r; - stack u8[96] stack_coins; + reg u64 r; + stack u8[XWING_KEYPAIRCOINBYTES] stack_coins; - public_key = public_key; - secret_key = secret_key; + _ = #init_msf(); - stack_coins = __tostack96u8(stack_coins, coins); + public_key = public_key; + secret_key = secret_key; + stack_coins = __tostack96u8(stack_coins, coins); - _crypto_xkem_keypair_derand_jazz(public_key, secret_key, stack_coins); + _crypto_xkem_keypair_derand_jazz(public_key, secret_key, stack_coins); - ?{}, r = #set0(); - return r; + ?{}, r = #set0(); + return r; } - export fn jade_kem_xwing_amd64_avx2_keypair(reg u64 public_key secret_key) -> reg u64 { reg u64 r; - stack u8[96] stack_coins; + stack u8[XWING_KEYPAIRCOINBYTES] stack_coins; + + _ = #init_msf(); public_key = public_key; secret_key = secret_key; stack_coins = #randombytes(stack_coins); + _crypto_xkem_keypair_derand_jazz(public_key, secret_key, stack_coins); + ?{}, r = #set0(); return r; } @@ -35,13 +41,17 @@ export fn jade_kem_xwing_amd64_avx2_keypair(reg u64 public_key secret_key) -> re export fn jade_kem_xwing_amd64_avx2_enc_derand(reg u64 ciphertext shared_secret public_key coins) -> reg u64 { reg u64 r; - stack u8[64] stack_coins; - + stack u8[XWING_ENCCOINBYTES] stack_coins; + + _ = #init_msf(); + ciphertext = ciphertext; shared_secret = shared_secret; public_key = public_key; stack_coins = __tostack64u8(stack_coins, coins); + _crypto_xkem_enc_derand_jazz(ciphertext, shared_secret, public_key, stack_coins); + ?{}, r = #set0(); return r; } @@ -49,13 +59,17 @@ export fn jade_kem_xwing_amd64_avx2_enc_derand(reg u64 ciphertext shared_secret export fn jade_kem_xwing_amd64_avx2_enc(reg u64 ciphertext shared_secret public_key) -> reg u64 { reg u64 r; - stack u8[64] stack_coins; + stack u8[XWING_ENCCOINBYTES] stack_coins; + + _ = #init_msf(); ciphertext = ciphertext; shared_secret = shared_secret; public_key = public_key; stack_coins = #randombytes(stack_coins); + _crypto_xkem_enc_derand_jazz(ciphertext, shared_secret, public_key, stack_coins); + ?{}, r = #set0(); return r; } @@ -63,7 +77,15 @@ export fn jade_kem_xwing_amd64_avx2_enc(reg u64 ciphertext shared_secret public_ export fn jade_kem_xwing_amd64_avx2_dec(reg u64 shared_secret ciphertext secret_key) -> reg u64 { reg u64 r; - __crypto_xkem_dec_jazz(shared_secret, ciphertext, secret_key); + + _ = #init_msf(); + + shared_secret = shared_secret; + ciphertext = ciphertext; + secret_key = secret_key; + + _crypto_xkem_dec_jazz(shared_secret, ciphertext, secret_key); + ?{}, r = #set0(); return r; } diff --git a/src/crypto_kem/xwing/amd64/avx2/kem.jinc b/src/crypto_kem/xwing/amd64/avx2/kem.jinc deleted file mode 100644 index 9b4bc9d8..00000000 --- a/src/crypto_kem/xwing/amd64/avx2/kem.jinc +++ /dev/null @@ -1,171 +0,0 @@ -from Jade require "common/tofromstack.jinc" -from Jade require "crypto_kem/kyber/kyber768/common/params.jinc" -from Jade require "crypto_kem/kyber/kyber768/amd64/avx2/indcpa.jinc" -from Jade require "crypto_kem/kyber/common/amd64/avx2/verify.jinc" -from Jade require "crypto_kem/kyber/common/amd64/kem.jinc" -require "params.jinc" -require "scalarmult_mulx.jinc" - -#[returnaddress="stack"] -fn _crypto_xkem_keypair_derand_jazz(reg u64 pkp, reg u64 skp, reg ptr u8[3*XWING_SYMBYTES] randomnessp) -{ - () = #spill(pkp, skp, randomnessp); - - __crypto_kem_keypair_derand_jazz(pkp, skp, randomnessp[0:2*MLKEM_SYMBYTES]); - - () = #unspill(pkp, skp); - - skp += MLKEM_SECRETKEYBYTES; - pkp += MLKEM_PUBLICKEYBYTES; - - () = #unspill(randomnessp); - - __fromstack32u8(skp, randomnessp[2*XWING_SYMBYTES:XWING_SYMBYTES]); - - () = #spill(pkp, skp); - scalarmult_base(pkp, skp); - - () = #unspill(pkp, skp); - - skp += X25519_PUBLICKEYBYTES; - - inline int i; - for i=0 to X25519_PUBLICKEYBYTES { - (u8)[skp + i] = (u8)[pkp + i]; - } -} - -#[returnaddress="stack"] -fn _crypto_xkem_enc_derand_jazz(reg u64 ctp, reg u64 shkp, reg u64 pkp, reg ptr u8[2*XWING_SYMBYTES] randomnessp) -{ - stack u8[32] m_shkp d_shkp dh_ctp; - stack u64 s_shkp; - - s_shkp = shkp; - - () = #spill(pkp, ctp, shkp, randomnessp); - __crypto_kem_enc_derand_jazz(ctp, shkp, pkp, randomnessp[0:32]); - - () = #unspill(pkp, ctp, shkp); - - m_shkp = __tostack32u8(m_shkp, shkp); - - pkp += MLKEM_PUBLICKEYBYTES; - ctp += MLKEM_CIPHERTEXTBYTES; - - () = #spill(pkp); - () = #unspill(randomnessp); - - __fromstack32u8(shkp, randomnessp[XWING_SYMBYTES:XWING_SYMBYTES]); - - () = #spill(ctp, shkp); - scalarmult_base(ctp, shkp); - () = #unspill(ctp, shkp); - - - reg u64 dh_ekp; - dh_ekp = shkp; - - dh_ctp = __tostack32u8(dh_ctp, ctp); - d_shkp = __tostack32u8(d_shkp, shkp); - - () = #unspill(pkp); - shkp = s_shkp; - - () = #spill(shkp, pkp); - scalarmult(shkp, dh_ekp, pkp); - () = #unspill(shkp, pkp); - - d_shkp = __tostack32u8(d_shkp, shkp); - - stack u8[XWING_PRFINPUT] buf; - stack u8[XWING_SYMBYTES] s_dh_pkp; - - s_dh_pkp = __tostack32u8(s_dh_pkp, pkp); - - inline int i j k l p; - - for i=0 to 6{ - buf[i] = label[i]; - } - - for i=0 to XWING_SYMBYTES{ - l = i + 6; - j = l + MLKEM_SSBYTES; - k = j + X25519_CIPHERTEXTBYTES; - p = k + X25519_PUBLICKEYBYTES; - buf[l] = m_shkp[i]; - buf[j] = d_shkp[i]; - buf[k] = dh_ctp[i]; - buf[p] = s_dh_pkp[i]; - } - - reg ptr u8[32] outp; - stack u8[32] out; - outp = out; - - outp = _sha3_256_134(outp, buf); - __fromstack32u8(shkp, outp); -} - -inline -fn __crypto_xkem_dec_jazz(reg u64 shkp, reg u64 ctp, reg u64 skp) -{ - stack u64 s_shkp; - s_shkp = shkp; - - () = #spill(shkp, ctp, skp); - __crypto_kem_dec_jazz(shkp, ctp, skp); - () = #unspill(shkp, ctp, skp); - - ctp += MLKEM_CIPHERTEXTBYTES; - skp += MLKEM_SECRETKEYBYTES; - - stack u8[MLKEM_SSBYTES] mlkem_shkp; - mlkem_shkp = __tostack32u8(mlkem_shkp, shkp); - - () = #spill(shkp, skp, ctp); - scalarmult(shkp, skp, ctp); - () = #unspill(shkp, skp, ctp); - - shkp = s_shkp; - - stack u8[X25519_SECRETKEYBYTES + X25519_PUBLICKEYBYTES] s_dh_kp; - stack u8[X25519_SSBYTES] s_dh_shkp dh_skp dh_ctp dh_pkp; - - - s_dh_shkp = __tostack32u8(s_dh_shkp, shkp); - dh_ctp = __tostack32u8(dh_ctp, ctp); - s_dh_kp = __tostack64u8(s_dh_kp, skp); - - dh_skp = s_dh_kp[0:X25519_SECRETKEYBYTES]; - dh_pkp = s_dh_kp[X25519_SECRETKEYBYTES:X25519_PUBLICKEYBYTES]; - - stack u8[XWING_PRFINPUT] buf; - - inline int i j k l p; - - for i=0 to 6{ - buf[i] = label[i]; - } - - for i=0 to XWING_SYMBYTES{ - l = i + 6; - j = l + MLKEM_SSBYTES; - k = j + X25519_CIPHERTEXTBYTES; - p = k + X25519_PUBLICKEYBYTES; - buf[l] = mlkem_shkp[i]; - buf[j] = s_dh_shkp[i]; - buf[k] = dh_ctp[i]; - buf[p] = dh_pkp[i]; - } - - shkp = s_shkp; - reg ptr u8[32] outp; - stack u8[32] out; - outp = out; - - outp = _sha3_256_134(outp, buf); - __fromstack32u8(shkp, outp); - -} \ No newline at end of file diff --git a/src/crypto_kem/xwing/amd64/avx2/params.jinc b/src/crypto_kem/xwing/amd64/avx2/params.jinc deleted file mode 100644 index d7b7d46f..00000000 --- a/src/crypto_kem/xwing/amd64/avx2/params.jinc +++ /dev/null @@ -1,21 +0,0 @@ -param int MLKEM_PUBLICKEYBYTES = 1184; -param int MLKEM_SECRETKEYBYTES = 2400; -param int MLKEM_CIPHERTEXTBYTES = 1088; -param int MLKEM_SSBYTES = 32; -param int MLKEM_SYMBYTES = 32; - -param int X25519_PUBLICKEYBYTES = 32; -param int X25519_SECRETKEYBYTES = 32; -param int X25519_CIPHERTEXTBYTES = 32; -param int X25519_SSBYTES = 32; -param int X25519_EPHBYTES = 32; - -param int XWING_LABELBYTES = 6; -param int XWING_PUBLICKEYBYTES = MLKEM_PUBLICKEYBYTES + X25519_PUBLICKEYBYTES; -param int XWING_SECRETKEYBYTES = MLKEM_SECRETKEYBYTES + X25519_SECRETKEYBYTES + X25519_PUBLICKEYBYTES; -param int XWING_CIPHERTEXTBYTES = MLKEM_CIPHERTEXTBYTES + X25519_CIPHERTEXTBYTES; -param int XWING_SSBYTES = 32; -param int XWING_SYMBYTES = 32; -param int XWING_PRFINPUT = 134; - -u8[6] label = {0x5c,0x2e,0x2f,0x2f,0x5e,0x5c}; \ No newline at end of file diff --git a/src/crypto_kem/xwing/amd64/avx2/scalarmult_mulx.jinc b/src/crypto_kem/xwing/amd64/avx2/scalarmult_mulx.jinc deleted file mode 100644 index 19b42644..00000000 --- a/src/crypto_kem/xwing/amd64/avx2/scalarmult_mulx.jinc +++ /dev/null @@ -1,33 +0,0 @@ -from Jade require "crypto_scalarmult/curve25519/amd64/common/load_store4.jinc" -from Jade require "crypto_scalarmult/curve25519/amd64/mulx/curve25519.jinc" - -#[returnaddress="stack"] -fn scalarmult_base(reg u64 qp np) -{ - stack u64 qps; - reg u64[4] q n; - - qps = qp; - n = __load4(np); - - q = __curve25519_mulx_base(n); - - qp = qps; - __store4(qp, q); -} - -#[returnaddress="stack"] -fn scalarmult(reg u64 qp np pp) -{ - stack u64 qps; - reg u64[4] q n p; - - qps = qp; - n = __load4(np); - p = __load4(pp); - - q = __curve25519_mulx(n, p); - - qp = qps; - __store4(qp, q); -} diff --git a/src/crypto_kem/xwing/amd64/ref/kem.jazz b/src/crypto_kem/xwing/amd64/ref/kem.jazz index e7557260..34d81363 100644 --- a/src/crypto_kem/xwing/amd64/ref/kem.jazz +++ b/src/crypto_kem/xwing/amd64/ref/kem.jazz @@ -1,33 +1,39 @@ -require "params.jinc" -require "kem.jinc" from Jade require "common/tofromstack.jinc" +from Jade require "crypto_kem/mlkem/mlkem768/amd64/ref/kem.jinc" +require "kem.jinc" +require "params.jinc" + export fn jade_kem_xwing_amd64_ref_keypair_derand(reg u64 public_key secret_key coins) -> reg u64 { - reg u64 r; - stack u8[96] stack_coins; + reg u64 r; + stack u8[XWING_KEYPAIRCOINBYTES] stack_coins; - public_key = public_key; - secret_key = secret_key; + _ = #init_msf(); - stack_coins = __tostack96u8(stack_coins, coins); + public_key = public_key; + secret_key = secret_key; + stack_coins = __tostack96u8(stack_coins, coins); - _crypto_xkem_keypair_derand_jazz(public_key, secret_key, stack_coins); + _crypto_xkem_keypair_derand_jazz(public_key, secret_key, stack_coins); - ?{}, r = #set0(); - return r; + ?{}, r = #set0(); + return r; } - export fn jade_kem_xwing_amd64_ref_keypair(reg u64 public_key secret_key) -> reg u64 { reg u64 r; - stack u8[96] stack_coins; + stack u8[XWING_KEYPAIRCOINBYTES] stack_coins; + + _ = #init_msf(); public_key = public_key; secret_key = secret_key; stack_coins = #randombytes(stack_coins); + _crypto_xkem_keypair_derand_jazz(public_key, secret_key, stack_coins); + ?{}, r = #set0(); return r; } @@ -35,13 +41,17 @@ export fn jade_kem_xwing_amd64_ref_keypair(reg u64 public_key secret_key) -> reg export fn jade_kem_xwing_amd64_ref_enc_derand(reg u64 ciphertext shared_secret public_key coins) -> reg u64 { reg u64 r; - stack u8[64] stack_coins; - + stack u8[XWING_ENCCOINBYTES] stack_coins; + + _ = #init_msf(); + ciphertext = ciphertext; shared_secret = shared_secret; public_key = public_key; stack_coins = __tostack64u8(stack_coins, coins); + _crypto_xkem_enc_derand_jazz(ciphertext, shared_secret, public_key, stack_coins); + ?{}, r = #set0(); return r; } @@ -49,13 +59,17 @@ export fn jade_kem_xwing_amd64_ref_enc_derand(reg u64 ciphertext shared_secret p export fn jade_kem_xwing_amd64_ref_enc(reg u64 ciphertext shared_secret public_key) -> reg u64 { reg u64 r; - stack u8[64] stack_coins; + stack u8[XWING_ENCCOINBYTES] stack_coins; + + _ = #init_msf(); ciphertext = ciphertext; shared_secret = shared_secret; public_key = public_key; stack_coins = #randombytes(stack_coins); + _crypto_xkem_enc_derand_jazz(ciphertext, shared_secret, public_key, stack_coins); + ?{}, r = #set0(); return r; } @@ -63,7 +77,15 @@ export fn jade_kem_xwing_amd64_ref_enc(reg u64 ciphertext shared_secret public_k export fn jade_kem_xwing_amd64_ref_dec(reg u64 shared_secret ciphertext secret_key) -> reg u64 { reg u64 r; - __crypto_xkem_dec_jazz(shared_secret, ciphertext, secret_key); + + _ = #init_msf(); + + shared_secret = shared_secret; + ciphertext = ciphertext; + secret_key = secret_key; + + _crypto_xkem_dec_jazz(shared_secret, ciphertext, secret_key); + ?{}, r = #set0(); return r; } diff --git a/src/crypto_kem/xwing/amd64/ref/kem.jinc b/src/crypto_kem/xwing/amd64/ref/kem.jinc index 5019d64b..409e35da 100644 --- a/src/crypto_kem/xwing/amd64/ref/kem.jinc +++ b/src/crypto_kem/xwing/amd64/ref/kem.jinc @@ -1,170 +1,133 @@ -from Jade require "crypto_kem/kyber/kyber768/amd64/ref/kem.jinc" -from Jade require "common/keccak/common/fips202_ref_DIRTY.jinc" -from Jade require "common/tofromstack.jinc" +// paper: https://eprint.iacr.org/2024/039.pdf +// note: the require from mlkem768 is missing on purpose + require "params.jinc" require "scalarmult.jinc" - -#[returnaddress="stack"] -fn _crypto_xkem_keypair_derand_jazz(reg u64 pkp, reg u64 skp, reg ptr u8[3*XWING_SYMBYTES] randomnessp) +require "sha3.jinc" + +// sct: at this level there are no more #mmx register to spend +// as such, after unspill, an init_msf (lfence) is needed +// to "promote" transient variables to public; in this +// particular case, there is no advantage in patching the +// implementations to preserve the misspeculation register. +// Some performance data next. +// +// - cpu cycles of the following code without lfences, 11700K: +// keypair , 345740 +// keypair_derand, 343532 +// enc , 518594 +// enc_derand , 516238 +// dec , 462404 +// +// - and with the lfences, 11700K: +// keypair , 345744 +// keypair_derand, 343496 +// enc , 518260 +// enc_derand , 515878 +// dec , 462904 +// +// So, minus the usual noise, its pretty much the same + + +// note: +// - (MLKEM_SYMBYTES*2) was copy pasted from params.jinc file from mlkem768 implementation +// - for simplicity and efficiency of the last for loop, 32 is hardcoded: if the caller of +// of this function provides something different from (MLKEM_SYMBYTES*2) + 32 then +// then the compilation should fail. + +fn _crypto_xkem_keypair_derand_jazz(reg u64 pkp skp, reg ptr u8[(MLKEM_SYMBYTES*2) + 32] randomness) { - () = #spill(pkp, skp, randomnessp); - - _crypto_kem_keypair_derand_jazz(pkp, skp, randomnessp[0:2*MLKEM_SYMBYTES]); - - () = #unspill(pkp, skp); - - skp += MLKEM_SECRETKEYBYTES; - pkp += MLKEM_PUBLICKEYBYTES; - - () = #unspill(randomnessp); - - __fromstack32u8(skp, randomnessp[2*XWING_SYMBYTES:XWING_SYMBYTES]); - - () = #spill(pkp, skp); - scalarmult_base(pkp, skp); - - () = #unspill(pkp, skp); - - skp += X25519_PUBLICKEYBYTES; - - inline int i; - for i=0 to X25519_PUBLICKEYBYTES { - (u8)[skp + i] = (u8)[pkp + i]; - } + inline int i; + reg u64 pk2; + reg ptr u8[32] sk2; + + // spill all + () = #spill(pkp, skp, randomness); + + // (sk1, pk1) <- KEM.KeyGen() // skp, pkp <- KEM.KeyGen(randomness[0:64]) + __crypto_kem_keypair_jazz(pkp, skp, randomness[0:(MLKEM_SYMBYTES*2)]); + + // sk2 <-$ // randomness[64:32] + // pk2 <- exp(G, sk2) + () = #unspill(pkp, randomness); _ = #init_msf(); + pk2 = #LEA(pkp + MLKEM_PUBLICKEYBYTES); + xwing_x25519_base_p_rp(pk2, randomness[(MLKEM_SYMBYTES*2):32]); + + // pk <- (pk1, pk2) + // done. + + // sk <- (sk1, sk2, pk2) + () = #unspill(pkp, skp, randomness); _ = #init_msf(); + sk2 = randomness[(MLKEM_SYMBYTES*2):32]; + pk2 = #LEA(pkp + MLKEM_PUBLICKEYBYTES); + + for i=0 to 4 // assumes: sk2 with 32 bytes; pk2 with 32 bytes + { (u64)[skp + MLKEM_SECRETKEYBYTES + i*8] = sk2[u64 i]; + (u64)[skp + MLKEM_SECRETKEYBYTES + 32 + i*8] = (u64)[pk2 + i*8]; + } } -#[returnaddress="stack"] -fn _crypto_xkem_enc_derand_jazz(reg u64 ctp, reg u64 shkp, reg u64 pkp, reg ptr u8[2*XWING_SYMBYTES] randomnessp) -{ - stack u8[32] m_shkp d_shkp dh_ctp; - stack u64 s_shkp; - - s_shkp = shkp; - - () = #spill(pkp, ctp, shkp, randomnessp); - _crypto_kem_enc_derand_jazz(ctp, shkp, pkp, randomnessp[0:32]); - - () = #unspill(pkp, ctp, shkp); - - m_shkp = __tostack32u8(m_shkp, shkp); - - pkp += MLKEM_PUBLICKEYBYTES; - ctp += MLKEM_CIPHERTEXTBYTES; - - () = #spill(pkp); - () = #unspill(randomnessp); - - __fromstack32u8(shkp, randomnessp[XWING_SYMBYTES:XWING_SYMBYTES]); - - () = #spill(ctp, shkp); - scalarmult_base(ctp, shkp); - () = #unspill(ctp, shkp); - - - reg u64 dh_ekp; - dh_ekp = shkp; - - dh_ctp = __tostack32u8(dh_ctp, ctp); - d_shkp = __tostack32u8(d_shkp, shkp); - - () = #unspill(pkp); - shkp = s_shkp; - - () = #spill(shkp, pkp); - scalarmult(shkp, dh_ekp, pkp); - () = #unspill(shkp, pkp); - d_shkp = __tostack32u8(d_shkp, shkp); - - stack u8[XWING_PRFINPUT] buf; - stack u8[XWING_SYMBYTES] s_dh_pkp; - - s_dh_pkp = __tostack32u8(s_dh_pkp, pkp); - - inline int i j k l p; - - for i=0 to 6{ - buf[i] = label[i]; - } - - for i=0 to XWING_SYMBYTES{ - l = i + 6; - j = l + MLKEM_SSBYTES; - k = j + X25519_CIPHERTEXTBYTES; - p = k + X25519_PUBLICKEYBYTES; - buf[l] = m_shkp[i]; - buf[j] = d_shkp[i]; - buf[k] = dh_ctp[i]; - buf[p] = s_dh_pkp[i]; - } - - reg ptr u8[32] outp; - stack u8[32] out; - outp = out; - - outp = _sha3_256_134(outp, buf); - __fromstack32u8(shkp, outp); -} - -inline -fn __crypto_xkem_dec_jazz(reg u64 shkp, reg u64 ctp, reg u64 skp) +fn _crypto_xkem_enc_derand_jazz(reg u64 ctp shkp pkp, reg ptr u8[MLKEM_SYMBYTES + 32] randomness) { - stack u64 s_shkp; - s_shkp = shkp; - - () = #spill(shkp, ctp, skp); - __crypto_kem_dec_jazz(shkp, ctp, skp); - () = #unspill(shkp, ctp, skp); - - ctp += MLKEM_CIPHERTEXTBYTES; - skp += MLKEM_SECRETKEYBYTES; - - stack u8[MLKEM_SSBYTES] mlkem_shkp; - mlkem_shkp = __tostack32u8(mlkem_shkp, shkp); - - () = #spill(shkp, skp, ctp); - scalarmult(shkp, skp, ctp); - () = #unspill(shkp, skp, ctp); - - shkp = s_shkp; - - stack u8[X25519_SECRETKEYBYTES + X25519_PUBLICKEYBYTES] s_dh_kp; - stack u8[X25519_SSBYTES] s_dh_shkp dh_skp dh_ctp dh_pkp; - - - s_dh_shkp = __tostack32u8(s_dh_shkp, shkp); - dh_ctp = __tostack32u8(dh_ctp, ctp); - s_dh_kp = __tostack64u8(s_dh_kp, skp); - - dh_skp = s_dh_kp[0:X25519_SECRETKEYBYTES]; - dh_pkp = s_dh_kp[X25519_SECRETKEYBYTES:X25519_PUBLICKEYBYTES]; - - stack u8[XWING_PRFINPUT] buf; - - inline int i j k l p; - - for i=0 to 6{ - buf[i] = label[i]; - } - - for i=0 to XWING_SYMBYTES{ - l = i + 6; - j = l + MLKEM_SSBYTES; - k = j + X25519_CIPHERTEXTBYTES; - p = k + X25519_PUBLICKEYBYTES; - buf[l] = mlkem_shkp[i]; - buf[j] = s_dh_shkp[i]; - buf[k] = dh_ctp[i]; - buf[p] = dh_pkp[i]; - } + reg u64 k k1 c2 pk2; + reg ptr u8[32] ske; + stack u8[32] k2; + + // spill all + () = #spill(pkp, ctp, shkp, randomness); + + // k1, c1 <- KEM.Enc(pk1) // shkp+0 (as aux), ctp+0 <- KEM.Enc(pkp+0, randomness[0:32]) + __crypto_kem_enc_jazz(ctp, shkp, pkp, randomness[0:32]); + + // ske <-$ // randomness[32:32] + // c2 <- exp(G, ske) // ctp+MLKEM_CIPHERTEXTBYTES <- exp(G, randomness[32:32]) + () = #unspill(ctp, randomness); _ = #init_msf(); + c2 = #LEA(ctp + MLKEM_CIPHERTEXTBYTES); + ske = randomness[MLKEM_SYMBYTES:32]; + xwing_x25519_base_p_rp(c2, ske); + + // k2 <- exp(pk2, ske) // k2 <- exp(pkp + MLKEM_PUBLICKEYBYTES, randomness[32:32]) + () = #unspill(randomness, pkp); _ = #init_msf(); + ske = randomness[MLKEM_SYMBYTES:32]; + pk2 = #LEA(pkp + MLKEM_PUBLICKEYBYTES); + k2 = xwing_x25519_rp_rp_p(k2, ske, pk2); + + // k <- H(label || k1 || k2 || c2 || pk2) + () = #unspill(shkp, ctp, pkp); _ = #init_msf(); + k = shkp; + k1 = shkp; + c2 = #LEA(ctp + MLKEM_CIPHERTEXTBYTES); + pk2 = #LEA(pkp + MLKEM_PUBLICKEYBYTES); + _xwing_sha3(k, k1, k2, c2, pk2); +} - shkp = s_shkp; - - reg ptr u8[32] outp; - stack u8[32] out; - outp = out; - outp = _sha3_256_134(outp, buf); - __fromstack32u8(shkp, outp); +fn _crypto_xkem_dec_jazz(reg u64 shkp ctp skp) +{ + reg u64 k k1 c2 sk2 pk2; + stack u8[32] k2; + + // spill all + () = #spill(shkp, ctp, skp); + + // (sk1, sk2, pk2) <- sk + // (c1, c2) <- c + // k1 <- KEM.Dec(c1, sk1) // shkp+0 (as aux) <- KEM.Dec(ctp, skp) + __crypto_kem_dec_jazz(shkp, ctp, skp); + + // k2 <- exp(c2, sk2) // k2 <- exp(ctp + MLKEM_CIPHERTEXTBYTES, skp + MLKEM_SECRETKEYBYTES); + () = #unspill(skp, ctp); _ = #init_msf(); + sk2 = #LEA(skp + MLKEM_SECRETKEYBYTES); + c2 = #LEA(ctp + MLKEM_CIPHERTEXTBYTES); + k2 = xwing_x25519_rp_p_p(k2, sk2, c2); + + // k <- H(label || k1 || k2 || c2 || pk2) + () = #unspill(shkp, ctp, skp); _ = #init_msf(); + k = shkp; + k1 = shkp; + c2 = #LEA(ctp + MLKEM_CIPHERTEXTBYTES); + pk2 = #LEA(skp + MLKEM_SECRETKEYBYTES + 32); + _xwing_sha3(k, k1, k2, c2, pk2); +} -} \ No newline at end of file diff --git a/src/crypto_kem/xwing/amd64/ref/params.jinc b/src/crypto_kem/xwing/amd64/ref/params.jinc index d7b7d46f..d45117a3 100644 --- a/src/crypto_kem/xwing/amd64/ref/params.jinc +++ b/src/crypto_kem/xwing/amd64/ref/params.jinc @@ -1,21 +1,9 @@ -param int MLKEM_PUBLICKEYBYTES = 1184; -param int MLKEM_SECRETKEYBYTES = 2400; -param int MLKEM_CIPHERTEXTBYTES = 1088; -param int MLKEM_SSBYTES = 32; -param int MLKEM_SYMBYTES = 32; +u8[6] XWING_LABEL = {0x5c,0x2e,0x2f,0x2f,0x5e,0x5c}; -param int X25519_PUBLICKEYBYTES = 32; -param int X25519_SECRETKEYBYTES = 32; -param int X25519_CIPHERTEXTBYTES = 32; -param int X25519_SSBYTES = 32; -param int X25519_EPHBYTES = 32; +param int XWING_PUBLICKEYBYTES = MLKEM_PUBLICKEYBYTES + 32; +param int XWING_SECRETKEYBYTES = MLKEM_SECRETKEYBYTES + 64; +param int XWING_CIPHERTEXTBYTES = MLKEM_CIPHERTEXTBYTES + 32; +param int XWING_KEYPAIRCOINBYTES = MLKEM_SYMBYTES*2 + 32; +param int XWING_ENCCOINBYTES = MLKEM_SYMBYTES + 32; +param int XWING_BYTES = 32; -param int XWING_LABELBYTES = 6; -param int XWING_PUBLICKEYBYTES = MLKEM_PUBLICKEYBYTES + X25519_PUBLICKEYBYTES; -param int XWING_SECRETKEYBYTES = MLKEM_SECRETKEYBYTES + X25519_SECRETKEYBYTES + X25519_PUBLICKEYBYTES; -param int XWING_CIPHERTEXTBYTES = MLKEM_CIPHERTEXTBYTES + X25519_CIPHERTEXTBYTES; -param int XWING_SSBYTES = 32; -param int XWING_SYMBYTES = 32; -param int XWING_PRFINPUT = 134; - -u8[6] label = {0x5c,0x2e,0x2f,0x2f,0x5e,0x5c}; \ No newline at end of file diff --git a/src/crypto_kem/xwing/amd64/ref/scalarmult.jinc b/src/crypto_kem/xwing/amd64/ref/scalarmult.jinc index d196091c..98a12c78 100644 --- a/src/crypto_kem/xwing/amd64/ref/scalarmult.jinc +++ b/src/crypto_kem/xwing/amd64/ref/scalarmult.jinc @@ -1,33 +1,50 @@ -from Jade require "crypto_scalarmult/curve25519/amd64/common/load_store4.jinc" from Jade require "crypto_scalarmult/curve25519/amd64/ref4/curve25519.jinc" -#[returnaddress="stack"] -fn scalarmult_base(reg u64 qp np) +fn xwing_x25519_base_p_rp(#spill_to_mmx reg u64 qp, reg ptr u8[32] _n) { - stack u64 qps; reg u64[4] q n; + inline int i; - qps = qp; - n = __load4(np); + () = #spill(qp); + for i=0 to 4 { n[i] = _n[u64 i]; } - q = __curve25519_ref4_base(n); + q = _curve25519_ref4_base(n); // q = nG - qp = qps; + () = #unspill(qp); __store4(qp, q); } -#[returnaddress="stack"] -fn scalarmult(reg u64 qp np pp) +fn xwing_x25519_rp_rp_p(#spill_to_mmx reg ptr u8[32] _q, reg ptr u8[32] _n, reg u64 pp) -> reg ptr u8[32] { - stack u64 qps; reg u64[4] q n p; + inline int i; - qps = qp; - n = __load4(np); - p = __load4(pp); + () = #spill(_q); + for i=0 to 4 { n[i] = _n[u64 i]; } + for i=0 to 4 { p[i] = (u64)[pp + 8*i]; } - q = __curve25519_ref4(n, p); + q = _curve25519_ref4(n, p); // q = nP - qp = qps; - __store4(qp, q); + () = #unspill(_q); + for i=0 to 4 { _q[u64 i] = q[i]; } + + return _q; } + +fn xwing_x25519_rp_p_p(#spill_to_mmx reg ptr u8[32] _q, reg u64 np, reg u64 pp) -> reg ptr u8[32] +{ + reg u64[4] q n p; + inline int i; + + () = #spill(_q); + for i=0 to 4 { n[i] = (u64)[np + 8*i]; } + for i=0 to 4 { p[i] = (u64)[pp + 8*i]; } + + q = _curve25519_ref4(n, p); // q = nP + + () = #unspill(_q); + for i=0 to 4 { _q[u64 i] = q[i]; } + + return _q; +} + diff --git a/src/crypto_kem/xwing/amd64/ref/sha3.jinc b/src/crypto_kem/xwing/amd64/ref/sha3.jinc new file mode 100644 index 00000000..5e3ea21e --- /dev/null +++ b/src/crypto_kem/xwing/amd64/ref/sha3.jinc @@ -0,0 +1,44 @@ + +fn _xwing_sha3( + #spill_to_mmx + reg u64 k, // writes: 32 bytes + reg u64 k1, // reads: 32 bytes + reg ptr u8[32] k2, // reads: 32 bytes + reg u64 c2, // reads: 32 bytes + reg u64 pk2) // reads: 32 bytes +{ + stack u64[25] state; + inline int i; + + () = #spill(k); + + // copy label + for i=0 to 6 + { state[u8 i] = XWING_LABEL[i]; } + + // copy k1, k2, c2, pk2 + for i=0 to 4 + { state.[6 + 0 + i*8] = (u64)[k1 + i*8]; + state.[6 + 32 + i*8] = k2[u64 i]; + state.[6 + 64 + i*8] = (u64)[c2 + i*8]; + state.[6 + 96 + i*8] = (u64)[pk2 + i*8]; + } + // 6 + 96 + 3*8 = 126 (and +8 byte write, 134) + + // zero the remaining state + state.[u16 134] = 0; + for i=17 to 25 + { state[i] = 0; } + + state[u8 134] ^= 0x06; + state[u8 SHA3_256_RATE - 1] = 0x80; + + // it uses the same keccakf1600 as mlkem768 + state = _keccakf1600_(state); + + () = #unspill(k); + + for i=0 to 4 + { (u64)[k + 8*i] = state[i]; } +} + diff --git a/src/crypto_scalarmult/curve25519/amd64/ref4/curve25519.jinc b/src/crypto_scalarmult/curve25519/amd64/ref4/curve25519.jinc index 3f29fd3c..abc13cd7 100644 --- a/src/crypto_scalarmult/curve25519/amd64/ref4/curve25519.jinc +++ b/src/crypto_scalarmult/curve25519/amd64/ref4/curve25519.jinc @@ -1,5 +1,6 @@ from Jade require "crypto_scalarmult/curve25519/amd64/common/bit.jinc" from Jade require "crypto_scalarmult/curve25519/amd64/common/decode_scalar.jinc" +from Jade require "crypto_scalarmult/curve25519/amd64/common/load_store4.jinc" from Jade require "crypto_scalarmult/curve25519/amd64/common/64/decode_u4.jinc" from Jade require "crypto_scalarmult/curve25519/amd64/common/64/init_points4.jinc" @@ -143,7 +144,7 @@ inline fn __curve25519_internal_ref4(stack u8[32] k, reg u64[4] u) -> reg u64[4] return r; } -inline fn __curve25519_ref4(reg u64[4] _k _u) -> reg u64[4] +fn _curve25519_ref4(reg u64[4] _k _u) -> reg u64[4] { stack u8[32] k; reg u64[4] u r; @@ -163,7 +164,7 @@ inline fn __curve25519_ref4_ptr(#spill_to_mmx reg u64 rp, reg u64 kp up) k = __load4(kp); u = __load4(up); - r = __curve25519_ref4(k, u); + r = _curve25519_ref4(k, u); () = #unspill(rp); @@ -171,7 +172,7 @@ inline fn __curve25519_ref4_ptr(#spill_to_mmx reg u64 rp, reg u64 kp up) } -inline fn __curve25519_ref4_base(reg u64[4] _k) -> reg u64[4] +fn _curve25519_ref4_base(reg u64[4] _k) -> reg u64[4] { stack u8[32] k; reg u64[4] u r; @@ -190,11 +191,10 @@ inline fn __curve25519_ref4_base_ptr(#spill_to_mmx reg u64 rp, reg u64 kp) () = #spill(rp); k = __load4(kp); - r = __curve25519_ref4_base(k); + r = _curve25519_ref4_base(k); () = #unspill(rp); __store4(rp, r); } -