use crate::params::*;
use crate::poly::Poly;
use crate::polyvec::{PolyVecK, PolyVecL};
pub fn pack_pk(mode: DilithiumMode, pk: &mut [u8], rho: &[u8; SEEDBYTES], t1: &PolyVecK) {
pk[..SEEDBYTES].copy_from_slice(rho);
let mut offset = SEEDBYTES;
for i in 0..mode.k() {
Poly::polyt1_pack(&mut pk[offset..offset + POLYT1_PACKEDBYTES], &t1.vec[i]);
offset += POLYT1_PACKEDBYTES;
}
}
pub fn unpack_pk(mode: DilithiumMode, rho: &mut [u8; SEEDBYTES], t1: &mut PolyVecK, pk: &[u8]) {
rho.copy_from_slice(&pk[..SEEDBYTES]);
let mut offset = SEEDBYTES;
for i in 0..mode.k() {
Poly::polyt1_unpack(&mut t1.vec[i], &pk[offset..offset + POLYT1_PACKEDBYTES]);
offset += POLYT1_PACKEDBYTES;
}
}
pub fn pack_sk(
mode: DilithiumMode,
sk: &mut [u8],
rho: &[u8; SEEDBYTES],
tr: &[u8],
key: &[u8; SEEDBYTES],
t0: &PolyVecK,
s1: &PolyVecL,
s2: &PolyVecK,
) {
let eta_packed = mode.polyeta_packedbytes();
let mut offset = 0;
sk[offset..offset + SEEDBYTES].copy_from_slice(rho);
offset += SEEDBYTES;
sk[offset..offset + SEEDBYTES].copy_from_slice(key);
offset += SEEDBYTES;
sk[offset..offset + TRBYTES].copy_from_slice(&tr[..TRBYTES]);
offset += TRBYTES;
for i in 0..mode.l() {
Poly::polyeta_pack(mode, &mut sk[offset..offset + eta_packed], &s1.vec[i]);
offset += eta_packed;
}
for i in 0..mode.k() {
Poly::polyeta_pack(mode, &mut sk[offset..offset + eta_packed], &s2.vec[i]);
offset += eta_packed;
}
for i in 0..mode.k() {
Poly::polyt0_pack(&mut sk[offset..offset + POLYT0_PACKEDBYTES], &t0.vec[i]);
offset += POLYT0_PACKEDBYTES;
}
}
pub fn unpack_sk(
mode: DilithiumMode,
rho: &mut [u8; SEEDBYTES],
tr: &mut [u8],
key: &mut [u8; SEEDBYTES],
t0: &mut PolyVecK,
s1: &mut PolyVecL,
s2: &mut PolyVecK,
sk: &[u8],
) {
let eta_packed = mode.polyeta_packedbytes();
let mut offset = 0;
rho.copy_from_slice(&sk[offset..offset + SEEDBYTES]);
offset += SEEDBYTES;
key.copy_from_slice(&sk[offset..offset + SEEDBYTES]);
offset += SEEDBYTES;
tr[..TRBYTES].copy_from_slice(&sk[offset..offset + TRBYTES]);
offset += TRBYTES;
for i in 0..mode.l() {
Poly::polyeta_unpack(mode, &mut s1.vec[i], &sk[offset..offset + eta_packed]);
offset += eta_packed;
}
for i in 0..mode.k() {
Poly::polyeta_unpack(mode, &mut s2.vec[i], &sk[offset..offset + eta_packed]);
offset += eta_packed;
}
for i in 0..mode.k() {
Poly::polyt0_unpack(&mut t0.vec[i], &sk[offset..offset + POLYT0_PACKEDBYTES]);
offset += POLYT0_PACKEDBYTES;
}
}
pub fn pack_sig(mode: DilithiumMode, sig: &mut [u8], c: &[u8], z: &PolyVecL, h: &PolyVecK) {
let ctilde = mode.ctildebytes();
let polyz_packed = mode.polyz_packedbytes();
let omega = mode.omega();
let k = mode.k();
sig[..ctilde].copy_from_slice(&c[..ctilde]);
let mut offset = ctilde;
for i in 0..mode.l() {
Poly::polyz_pack(mode, &mut sig[offset..offset + polyz_packed], &z.vec[i]);
offset += polyz_packed;
}
let h_start = offset;
for i in 0..(omega + k) {
sig[h_start + i] = 0;
}
let mut idx = 0;
for i in 0..k {
for j in 0..N {
if h.vec[i].coeffs[j] != 0 {
sig[h_start + idx] = j as u8;
idx += 1;
}
}
sig[h_start + omega + i] = idx as u8;
}
}
pub fn unpack_sig(
mode: DilithiumMode,
c: &mut [u8],
z: &mut PolyVecL,
h: &mut PolyVecK,
sig: &[u8],
) -> bool {
if sig.len() != mode.signature_bytes() || c.len() < mode.ctildebytes() {
return true;
}
let ctilde = mode.ctildebytes();
let polyz_packed = mode.polyz_packedbytes();
let omega = mode.omega();
let k = mode.k();
c[..ctilde].copy_from_slice(&sig[..ctilde]);
let mut offset = ctilde;
for i in 0..mode.l() {
Poly::polyz_unpack(mode, &mut z.vec[i], &sig[offset..offset + polyz_packed]);
offset += polyz_packed;
}
let h_start = offset;
let mut idx: usize = 0;
for i in 0..k {
for j in 0..N {
h.vec[i].coeffs[j] = 0;
}
let end = sig[h_start + omega + i] as usize;
if end < idx || end > omega {
return true;
}
for j in idx..end {
if j > idx && sig[h_start + j] <= sig[h_start + j - 1] {
return true;
}
h.vec[i].coeffs[sig[h_start + j] as usize] = 1;
}
idx = end;
}
for j in idx..omega {
if sig[h_start + j] != 0 {
return true;
}
}
false
}