KpqC-0.1.0: cbits/third_party/HAETAE/src/packing.c
// SPDX-License-Identifier: MIT
#include "packing.h"
#include "encoding.h"
#include "params.h"
#include "poly.h"
#include "polymat.h"
#include "polyvec.h"
#include <string.h>
/*************************************************
* Name: pack_vk
*
* Description: Bit-pack public key vk = (seed, b).
*
* Arguments: - uint8_t vk[]: output byte array
* - const polyveck *b: polynomial vector of length HAETAE_K
* containg b
* - const uint8_t seed[]: seed for A'
*
* Specification: Implements @[Algorithm 23, PackVK]
**************************************************/
void pack_vk(uint8_t vk[HAETAE_CRYPTO_PUBLICKEYBYTES], polyveck *b,
const uint8_t seed[HAETAE_SEEDBYTES]) {
unsigned int i;
memcpy(vk, seed, HAETAE_SEEDBYTES);
vk += HAETAE_SEEDBYTES;
for (i = 0; i < HAETAE_K; ++i) {
pack_poly_q(vk + i * HAETAE_POLYQ_PACKEDBYTES, &b->vec[i]);
}
}
/*************************************************
* Name: unpack_vk
*
* Description: Unpack public key vk = (seed, b).
*
* Arguments: - uint8_t seed[]: seed for A'
* - polyveck *b: polynomial vector of length HAETAE_K containg b
* - const uint8_t vk[]: output byte array
*
* Specification: Implements @[Algorithm 24, UnpackVK]
**************************************************/
void unpack_vk(polyvecl A[HAETAE_K],
const uint8_t vk[HAETAE_CRYPTO_PUBLICKEYBYTES]) {
unsigned int i;
polyveck b;
uint8_t seed[HAETAE_SEEDBYTES];
memcpy(seed, vk, HAETAE_SEEDBYTES);
vk += HAETAE_SEEDBYTES;
for (i = 0; i < HAETAE_K; ++i) {
unpack_poly_q(&b.vec[i], vk + i * HAETAE_POLYQ_PACKEDBYTES);
}
// A' = PRG(rhoprime)
polymatkl_expand_matA(A, seed);
polymatkl_double(A);
#if (HAETAE_MODE == HAETAE_MODE2) || (HAETAE_MODE == HAETAE_MODE3)
polyveck a;
polyveck_expand_vecA(&a, seed);
// first column of A = 2(a-b1*2^d)
polyveck_double(&b);
polyveck_sub(&b, &a, &b);
polyveck_double(&b);
polyveck_ntt(&b);
#endif
// append b into A
for (i = 0; i < HAETAE_K; ++i) {
A[i].vec[0] = b.vec[i];
}
}
/*************************************************
* Name: pack_sk
*
* Description: Bit-pack secret key sk = (vk, s).
*
* Arguments: - uint8_t sk[]: output byte array
* - const uint8_t vk[PUBLICKEYBYTES]: packed vk
* - const polyvecl *s0: polyvecl pointer containing s0 (encoding
* starting at offset 1)
* - const polyveck *s1: polyveck pointer containing s1
*
* Specification: Implements @[Algorithm 25, PackSK]
**************************************************/
void pack_sk(uint8_t sk[HAETAE_CRYPTO_SECRETKEYBYTES],
const uint8_t vk[HAETAE_CRYPTO_PUBLICKEYBYTES], const polyvecm *s0,
const polyveck *s1, const uint8_t key[HAETAE_SEEDBYTES]) {
unsigned int i;
memcpy(sk, vk, HAETAE_CRYPTO_PUBLICKEYBYTES);
sk += HAETAE_CRYPTO_PUBLICKEYBYTES;
for (i = 0; i < HAETAE_M; ++i)
pack_poly_eta(sk + i * HAETAE_POLYETA_PACKEDBYTES, &s0->vec[i]);
sk += (HAETAE_L - 1) * HAETAE_POLYETA_PACKEDBYTES;
#if (HAETAE_MODE == HAETAE_MODE2) || (HAETAE_MODE == HAETAE_MODE3)
for (i = 0; i < HAETAE_K; ++i)
pack_poly2_eta(sk + i * HAETAE_POLY2ETA_PACKEDBYTES, &s1->vec[i]);
sk += HAETAE_K * HAETAE_POLY2ETA_PACKEDBYTES;
#elif HAETAE_MODE == HAETAE_MODE5
for (i = 0; i < HAETAE_K; ++i)
pack_poly_eta(sk + i * HAETAE_POLYETA_PACKEDBYTES, &s1->vec[i]);
sk += HAETAE_K * HAETAE_POLYETA_PACKEDBYTES;
#else
#error "Not yet implemented."
#endif
memcpy(sk, key, HAETAE_SEEDBYTES);
}
/*************************************************
* Name: unpack_sk
*
* Description: Unpack secret key sk = (A, s).
*
* Arguments: - polyvecl A[HAETAE_K]: output polyvecl array for A
* - polyvecl s0: output polyvecl pointer for s0
* - polyveck s1: output polyveck pointer for s1
* - const uint8_t sk[]: byte array containing bit-packed sk
*
* Specification: Implements @[Algorithm 26, UnPackSK]
**************************************************/
void unpack_sk(polyvecl A[HAETAE_K], polyvecm *s0, polyveck *s1, uint8_t *key,
const uint8_t sk[HAETAE_CRYPTO_SECRETKEYBYTES]) {
unsigned int i;
unpack_vk(A, sk);
sk += HAETAE_CRYPTO_PUBLICKEYBYTES;
for (i = 0; i < HAETAE_M; ++i)
unpack_poly_eta(&s0->vec[i], sk + i * HAETAE_POLYETA_PACKEDBYTES);
sk += HAETAE_M * HAETAE_POLYETA_PACKEDBYTES;
#if (HAETAE_MODE == HAETAE_MODE2) || (HAETAE_MODE == HAETAE_MODE3)
for (i = 0; i < HAETAE_K; ++i)
unpack_poly2_eta(&s1->vec[i], sk + i * HAETAE_POLY2ETA_PACKEDBYTES);
sk += HAETAE_K * HAETAE_POLY2ETA_PACKEDBYTES;
#elif HAETAE_MODE == HAETAE_MODE5
for (i = 0; i < HAETAE_K; ++i)
unpack_poly_eta(&s1->vec[i], sk + i * HAETAE_POLYETA_PACKEDBYTES);
sk += HAETAE_K * HAETAE_POLYETA_PACKEDBYTES;
#endif
memcpy(key, sk, HAETAE_SEEDBYTES);
}
/*************************************************
* Name: pack_sig
*
* Description: Bit-pack signature sig = (c, LB(z1), len(x), len(y), x =
* Enc(HB(z1)), y = Enc(h)), Zeropadding.
*
* Arguments: - uint8_t sig[]: output byte array
* - const poly *c: pointer to challenge polynomial
* - const polyvecl *lowbits_z1: pointer to vector LowBits(z1) of
* length L
* - const polyvecl *highbits_z1: pointer to vector HighBits(z1) of
* length L
* - const polyveck *h: pointer t vector h of length HAETAE_K
* Returns 1 in case the signature packing failed; otherwise 0.
*
* Specification: Implements @[Algorithm 27, PackSIG]
**************************************************/
int pack_sig(uint8_t sig[HAETAE_CRYPTO_BYTES], const poly *c,
const polyvecl *lowbits_z1, const polyvecl *highbits_z1,
const polyveck *h) {
uint8_t encoded_h[HAETAE_N * HAETAE_K];
uint8_t encoded_hb_z1[HAETAE_N * HAETAE_L];
uint16_t size_enc_h, size_enc_hb_z1;
uint8_t offset_enc_h, offset_enc_hb_z1;
// init/padding with zeros:
memset(sig, 0, HAETAE_CRYPTO_BYTES);
// encode challenge
for (size_t i = 0; i < HAETAE_N; i++) {
sig[i / 8] |= c->coeffs[i] << (i % 8);
}
sig += HAETAE_N / 8;
for (int i = 0; i < HAETAE_L; ++i)
poly_decomposed_pack(sig + HAETAE_N * i, &lowbits_z1->vec[i]);
sig += HAETAE_L * HAETAE_N;
size_enc_hb_z1 = encode_hb_z1(encoded_hb_z1, &highbits_z1->vec[0].coeffs[0]);
size_enc_h = encode_h(encoded_h, &h->vec[0].coeffs[0]);
if (size_enc_h == 0 || size_enc_hb_z1 == 0) {
return 1; // encoding failed
}
// The size of the encoded h and HB(z1) does not always fit in one byte,
// thus we output a one byte offset to a fixed baseline
if (size_enc_h < HAETAE_BASE_ENC_H ||
size_enc_hb_z1 < HAETAE_BASE_ENC_HB_Z1 ||
size_enc_h > HAETAE_BASE_ENC_H + 255 ||
size_enc_hb_z1 > HAETAE_BASE_ENC_HB_Z1 + 255) {
return 1; // encoding size offset out of range
}
offset_enc_hb_z1 = size_enc_hb_z1 - HAETAE_BASE_ENC_HB_Z1;
offset_enc_h = size_enc_h - HAETAE_BASE_ENC_H;
if (HAETAE_SEEDBYTES + HAETAE_L * HAETAE_N + 2 + size_enc_hb_z1 + size_enc_h >
HAETAE_CRYPTO_BYTES) {
return 1; // signature too big
}
sig[0] = offset_enc_hb_z1;
sig[1] = offset_enc_h;
sig += 2;
memcpy(sig, encoded_hb_z1, size_enc_hb_z1);
sig += size_enc_hb_z1;
memcpy(sig, encoded_h, size_enc_h);
return 0;
}
/*************************************************
* Name: unpack_sig
*
* Description: Unpack signature sig = (c, LB(z1), len(x), len(y), x =
* Enc(HB(z1)), y = Enc(h)), Zeropadding.
*
* Arguments: - poly *c: pointer to challenge polynomial
* - polyvecl *lowbits_z1: pointer to output vector LowBits(z1)
* - polyvecl *highbits_z1: pointer to output vector HighBits(z1)
* - polyveck *h: pointer to output vector h
* - const uint8_t sig[]: byte array containing
* bit-packed signature
*
* Returns 1 in case of malformed signature; otherwise 0.
*
* Specification: Implements @[Algorithm 28, UnpackSIG]
**************************************************/
int unpack_sig(poly *c, polyvecl *lowbits_z1, polyvecl *highbits_z1,
polyveck *h, const uint8_t sig[HAETAE_CRYPTO_BYTES]) {
unsigned int i;
uint16_t size_enc_hb_z1, size_enc_h;
for (i = 0; i < HAETAE_N; i++) {
c->coeffs[i] = (sig[i / 8] >> (i % 8)) & 1;
}
sig += HAETAE_N / 8;
for (i = 0; i < HAETAE_L; ++i)
poly_decomposed_unpack(&lowbits_z1->vec[i], sig + HAETAE_N * i);
sig += HAETAE_L * HAETAE_N;
size_enc_hb_z1 = (uint16_t)sig[0] + HAETAE_BASE_ENC_HB_Z1;
size_enc_h = (uint16_t)sig[1] + HAETAE_BASE_ENC_H;
sig += 2;
if (HAETAE_CRYPTO_BYTES < (2 + HAETAE_L * HAETAE_N + HAETAE_SEEDBYTES +
size_enc_h + size_enc_hb_z1))
return 1; // invalid size_enc_h and/or size_enc_hb_z1
if (decode_hb_z1(&highbits_z1->vec[0].coeffs[0], sig, size_enc_hb_z1)) {
return 1; // decoding failed
}
sig += size_enc_hb_z1;
if (decode_h(&h->vec[0].coeffs[0], sig, size_enc_h)) {
return 1; // decoding failed
}
sig += size_enc_h;
for (int i = 0;
i < HAETAE_CRYPTO_BYTES - (HAETAE_SEEDBYTES + HAETAE_L * HAETAE_N + 2 +
size_enc_hb_z1 + size_enc_h);
i++)
if (sig[i] != 0)
return 1; // verify zero padding
return 0;
}
/*************************************************
* Name: pack_poly_q
*
* Description: Bit-pack polynomial with coefficients in [0, HAETAE_Q - 1].
*
* Arguments: - uint8_t *r: pointer to output byte array with at least
* HAETAE_POLYQ_PACKEDBYTES bytes
* - const poly *a: pointer to input polynomial
*
* Specification: Implements @[Algorithm 29, PackPolyQ]
**************************************************/
void pack_poly_q(uint8_t *r, const poly *a) {
unsigned int i;
#if (HAETAE_MODE == HAETAE_MODE2) || (HAETAE_MODE == HAETAE_MODE3)
int b_idx = 0, d_idx = 0;
for (i = 0; i < (HAETAE_N >> 3); ++i) {
b_idx = 15 * i;
d_idx = 8 * i;
r[b_idx] = (a->coeffs[d_idx] & 0xff);
r[b_idx + 1] =
((a->coeffs[d_idx] >> 8) & 0x7f) | ((a->coeffs[d_idx + 1] & 0x1) << 7);
r[b_idx + 2] = ((a->coeffs[d_idx + 1] >> 1) & 0xff);
r[b_idx + 3] = ((a->coeffs[d_idx + 1] >> 9) & 0x3f) |
((a->coeffs[d_idx + 2] & 0x3) << 6);
r[b_idx + 4] = ((a->coeffs[d_idx + 2] >> 2) & 0xff);
r[b_idx + 5] = ((a->coeffs[d_idx + 2] >> 10) & 0x1f) |
((a->coeffs[d_idx + 3] & 0x7) << 5);
r[b_idx + 6] = ((a->coeffs[d_idx + 3] >> 3) & 0xff);
r[b_idx + 7] = ((a->coeffs[d_idx + 3] >> 11) & 0xf) |
((a->coeffs[d_idx + 4] & 0xf) << 4);
r[b_idx + 8] = ((a->coeffs[d_idx + 4] >> 4) & 0xff);
r[b_idx + 9] = ((a->coeffs[d_idx + 4] >> 12) & 0x7) |
((a->coeffs[d_idx + 5] & 0x1f) << 3);
r[b_idx + 10] = ((a->coeffs[d_idx + 5] >> 5) & 0xff);
r[b_idx + 11] = ((a->coeffs[d_idx + 5] >> 13) & 0x3) |
((a->coeffs[d_idx + 6] & 0x3f) << 2);
r[b_idx + 12] = ((a->coeffs[d_idx + 6] >> 6) & 0xff);
r[b_idx + 13] = ((a->coeffs[d_idx + 6] >> 14) & 0x1) |
(a->coeffs[d_idx + 7] & 0x7f) << 1;
r[b_idx + 14] = ((a->coeffs[d_idx + 7] >> 7) & 0xff);
}
#elif HAETAE_MODE == HAETAE_MODE5
for (i = 0; i < HAETAE_N / 1; ++i) {
r[2 * i + 0] = a->coeffs[1 * i + 0] >> 0;
r[2 * i + 1] = a->coeffs[1 * i + 0] >> 8;
}
#endif
}
/*************************************************
* Name: unpack_poly_q
*
* Description: Unpack polynomial with coefficients in [0, HAETAE_Q - 1].
*
* Arguments: - poly *r: pointer to output polynomial
* - const uint8_t *a: byte array with bit-packed polynomial
*
* Specification: Implements @[Algorithm 30, UnpackPolyQ]
**************************************************/
void unpack_poly_q(poly *r, const uint8_t *a) {
unsigned int i;
#if (HAETAE_MODE == HAETAE_MODE2) || (HAETAE_MODE == HAETAE_MODE3)
int b_idx = 0, d_idx = 0;
for (i = 0; i < (HAETAE_N >> 3); ++i) {
b_idx = 15 * i;
d_idx = 8 * i;
r->coeffs[d_idx] = (a[b_idx] & 0xff) | ((a[b_idx + 1] & 0x7f) << 8);
r->coeffs[d_idx + 1] = ((a[b_idx + 1] >> 7) & 0x1) |
((a[b_idx + 2] & 0xff) << 1) |
((a[b_idx + 3] & 0x3f) << 9);
r->coeffs[d_idx + 2] = ((a[b_idx + 3] >> 6) & 0x3) |
((a[b_idx + 4] & 0xff) << 2) |
((a[b_idx + 5] & 0x1f) << 10);
r->coeffs[d_idx + 3] = ((a[b_idx + 5] >> 5) & 0x7) |
((a[b_idx + 6] & 0xff) << 3) |
((a[b_idx + 7] & 0xf) << 11);
r->coeffs[d_idx + 4] = ((a[b_idx + 7] >> 4) & 0xf) |
((a[b_idx + 8] & 0xff) << 4) |
((a[b_idx + 9] & 0x7) << 12);
r->coeffs[d_idx + 5] = ((a[b_idx + 9] >> 3) & 0x1f) |
((a[b_idx + 10] & 0xff) << 5) |
((a[b_idx + 11] & 0x3) << 13);
r->coeffs[d_idx + 6] = ((a[b_idx + 11] >> 2) & 0x3f) |
((a[b_idx + 12] & 0xff) << 6) |
((a[b_idx + 13] & 0x1) << 14);
r->coeffs[d_idx + 7] =
((a[b_idx + 13] >> 1) & 0x7f) | ((a[b_idx + 14] & 0xff) << 7);
}
#elif HAETAE_MODE == HAETAE_MODE5
for (i = 0; i < HAETAE_N / 1; ++i) {
r->coeffs[1 * i + 0] = a[2 * i + 0] >> 0;
r->coeffs[1 * i + 0] |= (uint16_t)a[2 * i + 1] << 8;
r->coeffs[1 * i + 0] &= 0xffff;
}
#endif
}
/*************************************************
* Name: pack_polyeta
*
* Description: Bit-pack polynomial with coefficients in [-ETA,ETA].
*
* Arguments: - uint8_t *r: pointer to output byte array with at least
* HAETAE_POLYETA_PACKEDBYTES bytes
* - const poly *a: pointer to input polynomial
*
* Specification: Implements @[Algorithm 31, PackPolyEta]
**************************************************/
void pack_poly_eta(uint8_t *r, const poly *a) {
unsigned int i;
uint8_t t[8];
for (i = 0; i < HAETAE_N / 4; ++i) {
t[0] = HAETAE_ETA - a->coeffs[4 * i + 0];
t[1] = HAETAE_ETA - a->coeffs[4 * i + 1];
t[2] = HAETAE_ETA - a->coeffs[4 * i + 2];
t[3] = HAETAE_ETA - a->coeffs[4 * i + 3];
r[i] = t[0] >> 0;
r[i] |= t[1] << 2;
r[i] |= t[2] << 4;
r[i] |= t[3] << 6;
}
}
/*************************************************
* Name: unpack_poly_eta
*
* Description: Unpack polynomial with coefficients in [-ETA,ETA].
*
* Arguments: - poly *r: pointer to output polynomial
* - const uint8_t *a: byte array with bit-packed polynomial
*
* Specification: Implements @[Algorithm 32, UnpackPolyEta]
**************************************************/
void unpack_poly_eta(poly *r, const uint8_t *a) {
unsigned int i;
for (i = 0; i < HAETAE_N / 4; ++i) {
r->coeffs[4 * i + 0] = a[i] >> 0;
r->coeffs[4 * i + 0] &= 0x3;
r->coeffs[4 * i + 1] = a[i] >> 2;
r->coeffs[4 * i + 1] &= 0x3;
r->coeffs[4 * i + 2] = a[i] >> 4;
r->coeffs[4 * i + 2] &= 0x3;
r->coeffs[4 * i + 3] = a[i] >> 6;
r->coeffs[4 * i + 3] &= 0x3;
r->coeffs[4 * i + 0] = HAETAE_ETA - r->coeffs[4 * i + 0];
r->coeffs[4 * i + 1] = HAETAE_ETA - r->coeffs[4 * i + 1];
r->coeffs[4 * i + 2] = HAETAE_ETA - r->coeffs[4 * i + 2];
r->coeffs[4 * i + 3] = HAETAE_ETA - r->coeffs[4 * i + 3];
}
}
/*************************************************
* Name: pack_poly2eta
*
* Description: Bit-pack polynomial with coefficients in [-ETA-1,ETA+1].
*
* Arguments: - uint8_t *r: pointer to output byte array with at least
* HAETAE_POLYETA_PACKEDBYTES bytes
* - const poly *a: pointer to input polynomial
*
* Specification: Implements @[Algorithm 33, PackPoly2Eta]
**************************************************/
void pack_poly2_eta(uint8_t *r, const poly *a) {
unsigned int i;
uint8_t t[8];
for (i = 0; i < HAETAE_N / 8; ++i) {
t[0] = 2 * HAETAE_ETA - a->coeffs[8 * i + 0];
t[1] = 2 * HAETAE_ETA - a->coeffs[8 * i + 1];
t[2] = 2 * HAETAE_ETA - a->coeffs[8 * i + 2];
t[3] = 2 * HAETAE_ETA - a->coeffs[8 * i + 3];
t[4] = 2 * HAETAE_ETA - a->coeffs[8 * i + 4];
t[5] = 2 * HAETAE_ETA - a->coeffs[8 * i + 5];
t[6] = 2 * HAETAE_ETA - a->coeffs[8 * i + 6];
t[7] = 2 * HAETAE_ETA - a->coeffs[8 * i + 7];
r[3 * i + 0] = (t[0] >> 0) | (t[1] << 3) | (t[2] << 6);
r[3 * i + 1] = (t[2] >> 2) | (t[3] << 1) | (t[4] << 4) | (t[5] << 7);
r[3 * i + 2] = (t[5] >> 1) | (t[6] << 2) | (t[7] << 5);
}
}
/*************************************************
* Name: unpack_poly2eta
*
* Description: Unpack polynomial with coefficients in [-ETA-1,ETA+1].
*
* Arguments: - poly *r: pointer to output polynomial
* - const uint8_t *a: byte array with bit-packed polynomial
*
* Specification: Implements @[Algorithm 34, UnpackPoly2Eta]
**************************************************/
void unpack_poly2_eta(poly *r, const uint8_t *a) {
unsigned int i;
for (i = 0; i < HAETAE_N / 8; ++i) {
r->coeffs[8 * i + 0] = (a[3 * i + 0] >> 0) & 7;
r->coeffs[8 * i + 1] = (a[3 * i + 0] >> 3) & 7;
r->coeffs[8 * i + 2] = ((a[3 * i + 0] >> 6) | (a[3 * i + 1] << 2)) & 7;
r->coeffs[8 * i + 3] = (a[3 * i + 1] >> 1) & 7;
r->coeffs[8 * i + 4] = (a[3 * i + 1] >> 4) & 7;
r->coeffs[8 * i + 5] = ((a[3 * i + 1] >> 7) | (a[3 * i + 2] << 1)) & 7;
r->coeffs[8 * i + 6] = (a[3 * i + 2] >> 2) & 7;
r->coeffs[8 * i + 7] = (a[3 * i + 2] >> 5) & 7;
r->coeffs[8 * i + 0] = 2 * HAETAE_ETA - r->coeffs[8 * i + 0];
r->coeffs[8 * i + 1] = 2 * HAETAE_ETA - r->coeffs[8 * i + 1];
r->coeffs[8 * i + 2] = 2 * HAETAE_ETA - r->coeffs[8 * i + 2];
r->coeffs[8 * i + 3] = 2 * HAETAE_ETA - r->coeffs[8 * i + 3];
r->coeffs[8 * i + 4] = 2 * HAETAE_ETA - r->coeffs[8 * i + 4];
r->coeffs[8 * i + 5] = 2 * HAETAE_ETA - r->coeffs[8 * i + 5];
r->coeffs[8 * i + 6] = 2 * HAETAE_ETA - r->coeffs[8 * i + 6];
r->coeffs[8 * i + 7] = 2 * HAETAE_ETA - r->coeffs[8 * i + 7];
}
}
/*************************************************
* Name: pack_vec_highbits
*
* Description: pack highbits of a vector of polynomials
*
* Arguments: - uint8_t *buf: pointer to output bytes array
* - const polyveck *v: a vector of polynomials
*
* Specification: Implements @[Algorithm 35, PackVecHighBits]
**************************************************/
void pack_vec_highbits(uint8_t *buf, const polyveck *v) {
unsigned int i;
for (i = 0; i < HAETAE_K; i++) {
pack_poly_highbits(buf + i * HAETAE_POLY_HIGHBITS_PACKEDBYTES, &v->vec[i]);
}
}
/*************************************************
* Name: pack_poly_highbits
*
* Description: pack highbits of a polynomial
*
* Arguments: - uint8_t *buf: pointer to output bytes array
* - const poly *v: a polynomial
*
* Specification: Implements @[Algorithm 36, PackPolyHighBits]
**************************************************/
void pack_poly_highbits(uint8_t *buf, const poly *a) {
unsigned int i;
#if (HAETAE_MODE == HAETAE_MODE2) || (HAETAE_MODE == HAETAE_MODE3)
for (i = 0; i < HAETAE_N; i++) {
// if ((uint32_t)a->coeffs[i] > 0xFF) {
// printf("1byte overflow: i=%d coeff=%08X\n", i, a->coeffs[i]);
// }
buf[i] = (uint8_t)a->coeffs[i];
}
#elif HAETAE_MODE == HAETAE_MODE5
for (i = 0; i < HAETAE_N / 8; i++) {
buf[9 * i + 0] = a->coeffs[8 * i + 0] & 0xff;
buf[9 * i + 1] = (a->coeffs[8 * i + 0] >> 8) & 0x01;
buf[9 * i + 1] |= (a->coeffs[8 * i + 1] << 1) & 0xff;
buf[9 * i + 2] = (a->coeffs[8 * i + 1] >> 7) & 0x03;
buf[9 * i + 2] |= (a->coeffs[8 * i + 2] << 2) & 0xff;
buf[9 * i + 3] = (a->coeffs[8 * i + 2] >> 6) & 0x07;
buf[9 * i + 3] |= (a->coeffs[8 * i + 3] << 3) & 0xff;
buf[9 * i + 4] = (a->coeffs[8 * i + 3] >> 5) & 0x0f;
buf[9 * i + 4] |= (a->coeffs[8 * i + 4] << 4) & 0xff;
buf[9 * i + 5] = (a->coeffs[8 * i + 4] >> 4) & 0x1f;
buf[9 * i + 5] |= (a->coeffs[8 * i + 5] << 5) & 0xff;
buf[9 * i + 6] = (a->coeffs[8 * i + 5] >> 3) & 0x3f;
buf[9 * i + 6] |= (a->coeffs[8 * i + 6] << 6) & 0xff;
buf[9 * i + 7] = (a->coeffs[8 * i + 6] >> 2) & 0x7f;
buf[9 * i + 7] |= (a->coeffs[8 * i + 7] << 7) & 0xff;
buf[9 * i + 8] = (a->coeffs[8 * i + 7] >> 1) & 0xff;
}
#endif
}
/*************************************************
* Name: pack_poly_lsb
*
* Description: pack lsb of a polynomial
*
* Arguments: - uint8_t *buf: pointer to output bytes array
* - const poly *a: a polynomial
*
* Specification: Implements @[Algorithm 37, PackPolyLsb]
**************************************************/
void pack_poly_lsb(uint8_t *buf, const poly *a) {
unsigned int i;
for (i = 0; i < HAETAE_N; i++) {
if ((i % 8) == 0) {
buf[i / 8] = 0;
}
buf[i / 8] |= (a->coeffs[i] & 1) << (i % 8);
}
}