const N: usize = 701;
const LOGQ: usize = 13;
const Q: u32 = 1 << LOGQ;
const Q_MASK: u16 = (Q as u16).wrapping_sub(1);
const PRFKEYBYTES: usize = 32;
const SHAREDKEYBYTES: usize = 32;
const SAMPLE_IID_BYTES: usize = N - 1; const SAMPLE_FG_BYTES: usize = 2 * SAMPLE_IID_BYTES; const SAMPLE_RM_BYTES: usize = 2 * SAMPLE_IID_BYTES;
const PACK_DEG: usize = N - 1; const PACK_TRINARY_BYTES: usize = (PACK_DEG + 4) / 5;
const OWCPA_MSGBYTES: usize = 2 * PACK_TRINARY_BYTES; const OWCPA_PUBLICKEYBYTES: usize = (LOGQ * PACK_DEG + 7) / 8; const OWCPA_SECRETKEYBYTES: usize = 2 * PACK_TRINARY_BYTES + OWCPA_PUBLICKEYBYTES; const OWCPA_BYTES: usize = (LOGQ * PACK_DEG + 7) / 8;
pub const PUBLIC_KEY_BYTES: usize = OWCPA_PUBLICKEYBYTES; pub const PRIVATE_KEY_BYTES: usize = OWCPA_SECRETKEYBYTES + PRFKEYBYTES; pub const CIPHERTEXT_BYTES: usize = OWCPA_BYTES; pub const SHARED_SECRET_BYTES: usize = SHAREDKEYBYTES;
fn poly_lift_hrss(r: &mut [u16; N], a: &[u16; N]) {
let t: u16 = (3 - (N % 3)) as u16;
let mut b = [0u16; N];
b[0] = a[0]
.wrapping_mul(2u16.wrapping_sub(t))
.wrapping_add(a[2].wrapping_mul(t));
b[1] = a[1].wrapping_mul(2u16.wrapping_sub(t));
b[2] = a[2].wrapping_mul(2u16.wrapping_sub(t));
let mut zj: u16 = 0; for i in 3..N {
b[0] = b[0].wrapping_add(a[i].wrapping_mul(zj.wrapping_add(2 * t)));
b[1] = b[1].wrapping_add(a[i].wrapping_mul(zj.wrapping_add(t)));
b[2] = b[2].wrapping_add(a[i].wrapping_mul(zj));
zj = (zj.wrapping_add(t)) % 3;
}
b[1] = b[1].wrapping_add(a[0].wrapping_mul(zj.wrapping_add(t)));
b[2] = b[2].wrapping_add(a[0].wrapping_mul(zj));
b[2] = b[2].wrapping_add(a[1].wrapping_mul(zj.wrapping_add(t)));
for i in 3..N {
b[i] = b[i - 3].wrapping_add(
2u16.wrapping_mul(a[i].wrapping_add(a[i - 1]).wrapping_add(a[i - 2])),
);
}
crate::public_key::ntru_pqc_shared::poly_mod_3_phi_n::<N>(&mut b);
crate::public_key::ntru_pqc_shared::poly_z3_to_zq::<N>(&mut b, Q_MASK);
r[0] = 0u16.wrapping_sub(b[0]);
for i in 0..N - 1 {
r[i + 1] = b[i].wrapping_sub(b[i + 1]);
}
}
fn sample_iid_plus(r: &mut [u16; N], uniform_bytes: &[u8]) {
debug_assert_eq!(uniform_bytes.len(), SAMPLE_IID_BYTES);
crate::public_key::ntru_pqc_shared::sample_iid::<N>(r, uniform_bytes);
for i in 0..N - 1 {
let c = r[i];
r[i] = c | (0u16.wrapping_sub(c >> 1));
}
let mut s: u16 = 0;
for i in 0..N - 1 {
s = s.wrapping_add(r[i + 1].wrapping_mul(r[i]));
}
let s_sign: u16 = 1 | 0u16.wrapping_sub(s >> 15);
let mut i = 0;
while i < N {
r[i] = s_sign.wrapping_mul(r[i]);
i += 2;
}
for i in 0..N {
r[i] = 3 & (r[i] ^ (r[i] >> 15));
}
}
struct Hrss701Variant;
impl crate::public_key::ntru_pqc_shared::NtruVariant<N, LOGQ> for Hrss701Variant {
const Q_MASK: u16 = Q_MASK;
const WEIGHT: usize = 0;
const SAMPLE_FG_BYTES: usize = SAMPLE_FG_BYTES;
const SAMPLE_RM_BYTES: usize = SAMPLE_RM_BYTES;
const PACK_TRINARY_BYTES: usize = PACK_TRINARY_BYTES;
const OWCPA_PUBLICKEYBYTES: usize = OWCPA_PUBLICKEYBYTES;
const OWCPA_SECRETKEYBYTES: usize = OWCPA_SECRETKEYBYTES;
const OWCPA_BYTES: usize = OWCPA_BYTES;
const OWCPA_MSGBYTES: usize = OWCPA_MSGBYTES;
fn sample_fg(f: &mut [u16; N], g: &mut [u16; N], seed: &[u8]) {
debug_assert_eq!(seed.len(), SAMPLE_FG_BYTES);
sample_iid_plus(f, &seed[..SAMPLE_IID_BYTES]);
sample_iid_plus(g, &seed[SAMPLE_IID_BYTES..]);
}
fn sample_rm(r: &mut [u16; N], m: &mut [u16; N], seed: &[u8]) {
debug_assert_eq!(seed.len(), SAMPLE_RM_BYTES);
crate::public_key::ntru_pqc_shared::sample_iid::<N>(r, &seed[..SAMPLE_IID_BYTES]);
crate::public_key::ntru_pqc_shared::sample_iid::<N>(m, &seed[SAMPLE_IID_BYTES..]);
}
fn update_g_after_z3_to_zq(g: &mut [u16; N]) {
for i in (1..N).rev() {
g[i] = (3u16).wrapping_mul(g[i - 1].wrapping_sub(g[i]));
}
g[0] = 0u16.wrapping_sub((3u16).wrapping_mul(g[0]));
}
fn poly_lift(r: &mut [u16; N], a: &[u16; N]) {
poly_lift_hrss(r, a);
}
fn check_m(_m: &[u16; N]) -> i32 {
0
}
fn poly_sq_tobytes(r: &mut [u8], a: &[u16; N]) {
crate::public_key::ntru_pqc_shared::poly_sq_tobytes_logq13::<N>(r, a);
}
fn poly_sq_frombytes(r: &mut [u16; N], a: &[u8]) {
crate::public_key::ntru_pqc_shared::poly_sq_frombytes_logq13::<N>(r, a);
}
}
crate::public_key::ntru_pqc_shared::define_pqc_kem! {
namespace = NtruHrss701,
public_key = NtruHrss701PublicKey,
private_key = NtruHrss701PrivateKey,
ciphertext = NtruHrss701Ciphertext,
shared_secret = NtruHrss701SharedSecret,
variant = Hrss701Variant,
kat_path = "../../kat/ntruhrss701.rsp",
}