#ifndef MLD_PACKING_H
#define MLD_PACKING_H
#include "polyvec.h"
#include "polyvec_lazy.h"
#if !defined(MLD_CONFIG_NO_KEYPAIR_API)
#define mld_pack_sk_s1 MLD_NAMESPACE_KL(pack_sk_s1)
MLD_INTERNAL_API
void mld_pack_sk_s1(uint8_t sk[MLDSA_CRYPTO_SECRETKEYBYTES],
const mld_polyvecl *s1)
__contract__(
requires(memory_no_alias(sk, MLDSA_CRYPTO_SECRETKEYBYTES))
requires(memory_no_alias(s1, sizeof(mld_polyvecl)))
requires(forall(k1, 0, MLDSA_L,
array_abs_bound(s1->vec[k1].coeffs, 0, MLDSA_N, MLDSA_ETA + 1)))
assigns(memory_slice(sk, MLDSA_CRYPTO_SECRETKEYBYTES))
);
#define mld_pack_sk_rho_key_tr_s2 MLD_NAMESPACE_KL(pack_sk_rho_key_tr_s2)
MLD_INTERNAL_API
void mld_pack_sk_rho_key_tr_s2(uint8_t sk[MLDSA_CRYPTO_SECRETKEYBYTES],
const uint8_t rho[MLDSA_SEEDBYTES],
const uint8_t tr[MLDSA_TRBYTES],
const uint8_t key[MLDSA_SEEDBYTES],
const mld_polyveck *s2)
__contract__(
requires(memory_no_alias(sk, MLDSA_CRYPTO_SECRETKEYBYTES))
requires(memory_no_alias(rho, MLDSA_SEEDBYTES))
requires(memory_no_alias(tr, MLDSA_TRBYTES))
requires(memory_no_alias(key, MLDSA_SEEDBYTES))
requires(memory_no_alias(s2, sizeof(mld_polyveck)))
requires(forall(k2, 0, MLDSA_K,
array_abs_bound(s2->vec[k2].coeffs, 0, MLDSA_N, MLDSA_ETA + 1)))
assigns(memory_slice(sk, MLDSA_CRYPTO_SECRETKEYBYTES))
);
#endif
#if !defined(MLD_CONFIG_NO_SIGN_API)
#define mld_pack_sig_c MLD_NAMESPACE_KL(pack_sig_c)
MLD_INTERNAL_API
void mld_pack_sig_c(uint8_t sig[MLDSA_CRYPTO_BYTES],
const uint8_t c[MLDSA_CTILDEBYTES])
__contract__(
requires(memory_no_alias(sig, MLDSA_CRYPTO_BYTES))
requires(memory_no_alias(c, MLDSA_CTILDEBYTES))
assigns(memory_slice(sig, MLDSA_CRYPTO_BYTES))
);
#define mld_pack_sig_h MLD_NAMESPACE_KL(pack_sig_h)
MLD_INTERNAL_API
MLD_MUST_CHECK_RETURN_VALUE
int mld_pack_sig_h(uint8_t sig[MLDSA_CRYPTO_BYTES], const mld_polyveck *w0,
const mld_polyveck *w1)
__contract__(
requires(memory_no_alias(sig, MLDSA_CRYPTO_BYTES))
requires(memory_no_alias(w0, sizeof(mld_polyveck)))
requires(memory_no_alias(w1, sizeof(mld_polyveck)))
assigns(memory_slice(sig + MLDSA_SIG_H_OFFSET, MLDSA_POLYVECH_PACKEDBYTES))
ensures(return_value == 0 || return_value == MLD_ERR_FAIL)
);
#define mld_pack_sig_z MLD_NAMESPACE_KL(pack_sig_z)
MLD_INTERNAL_API
void mld_pack_sig_z(uint8_t sig[MLDSA_CRYPTO_BYTES], const mld_poly *zi,
unsigned i)
__contract__(
requires(memory_no_alias(sig, MLDSA_CRYPTO_BYTES))
requires(memory_no_alias(zi, sizeof(mld_poly)))
requires(i < MLDSA_L)
requires(array_bound(zi->coeffs, 0, MLDSA_N, -(MLDSA_GAMMA1 - 1), MLDSA_GAMMA1 + 1))
assigns(memory_slice(sig, MLDSA_CRYPTO_BYTES))
);
#endif
#if !defined(MLD_CONFIG_NO_VERIFY_API)
#define mld_unpack_pk_t1 MLD_NAMESPACE_KL(unpack_pk_t1)
MLD_INTERNAL_API
void mld_unpack_pk_t1(mld_poly *t1,
const uint8_t pk[MLDSA_CRYPTO_PUBLICKEYBYTES],
unsigned int i)
__contract__(
requires(memory_no_alias(pk, MLDSA_CRYPTO_PUBLICKEYBYTES))
requires(memory_no_alias(t1, sizeof(mld_poly)))
requires(i < MLDSA_K)
assigns(memory_slice(t1, sizeof(mld_poly)))
ensures(array_bound(t1->coeffs, 0, MLDSA_N, 0, 1 << 10))
);
#endif
#if !defined(MLD_CONFIG_NO_SIGN_API)
#define mld_unpack_sk MLD_NAMESPACE_KL(unpack_sk)
MLD_INTERNAL_API
void mld_unpack_sk(uint8_t rho[MLDSA_SEEDBYTES], uint8_t tr[MLDSA_TRBYTES],
uint8_t key[MLDSA_SEEDBYTES], mld_sk_t0hat *t0,
mld_sk_s1hat *s1, mld_sk_s2hat *s2,
const uint8_t sk[MLDSA_CRYPTO_SECRETKEYBYTES])
__contract__(
requires(memory_no_alias(rho, MLDSA_SEEDBYTES))
requires(memory_no_alias(tr, MLDSA_TRBYTES))
requires(memory_no_alias(key, MLDSA_SEEDBYTES))
requires(memory_no_alias(t0, sizeof(mld_sk_t0hat)))
requires(memory_no_alias(s1, sizeof(mld_sk_s1hat)))
requires(memory_no_alias(s2, sizeof(mld_sk_s2hat)))
requires(memory_no_alias(sk, MLDSA_CRYPTO_SECRETKEYBYTES))
assigns(memory_slice(rho, MLDSA_SEEDBYTES))
assigns(memory_slice(tr, MLDSA_TRBYTES))
assigns(memory_slice(key, MLDSA_SEEDBYTES))
assigns(memory_slice(t0, sizeof(mld_sk_t0hat)))
assigns(memory_slice(s1, sizeof(mld_sk_s1hat)))
assigns(memory_slice(s2, sizeof(mld_sk_s2hat)))
MLD_IF_NOT_REDUCE_RAM(
ensures(forall(k0, 0, MLDSA_K,
array_abs_bound(t0->vec.vec[k0].coeffs, 0, MLDSA_N, MLD_NTT_BOUND)))
ensures(forall(k1, 0, MLDSA_L,
array_abs_bound(s1->vec.vec[k1].coeffs, 0, MLDSA_N, MLD_NTT_BOUND)))
ensures(forall(k2, 0, MLDSA_K,
array_abs_bound(s2->vec.vec[k2].coeffs, 0, MLDSA_N, MLD_NTT_BOUND)))
)
MLD_IF_REDUCE_RAM(
ensures(s1->packed == old(sk) + MLDSA_SK_S1_OFFSET)
ensures(s2->packed == old(sk) + MLDSA_SK_S2_OFFSET)
ensures(t0->packed == old(sk) + MLDSA_SK_T0_OFFSET)
)
);
#endif
#if !defined(MLD_CONFIG_NO_VERIFY_API)
#define mld_sig_unpack_hints MLD_NAMESPACE_KL(sig_unpack_hints)
MLD_INTERNAL_API
MLD_MUST_CHECK_RETURN_VALUE
int mld_sig_unpack_hints(mld_poly *h, const uint8_t sig[MLDSA_CRYPTO_BYTES],
unsigned int i)
__contract__(
requires(memory_no_alias(sig, MLDSA_CRYPTO_BYTES))
requires(memory_no_alias(h, sizeof(mld_poly)))
requires(i < MLDSA_K)
assigns(memory_slice(h, sizeof(mld_poly)))
ensures(return_value == 0 || return_value == MLD_ERR_FAIL)
ensures(return_value == 0 ==> array_bound(h->coeffs, 0, MLDSA_N, 0, 2))
);
#endif
#endif