1
1
mirror of https://github.com/henrydcase/pqc.git synced 2024-11-23 16:08:59 +00:00
pqcrypto/crypto_sign/dilithium-iii/clean/packing.c

288 lines
8.1 KiB
C
Raw Normal View History

2019-01-16 09:15:18 +00:00
#include "packing.h"
#include "params.h"
#include "poly.h"
#include "polyvec.h"
/*************************************************
* Name: pack_pk
*
* Description: Bit-pack public key pk = (rho, t1).
*
* Arguments: - unsigned char pk[]: output byte array
* - const unsigned char rho[]: byte array containing rho
* - const polyveck *t1: pointer to vector t1
**************************************************/
void pack_pk(unsigned char pk[CRYPTO_PUBLICKEYBYTES],
const unsigned char rho[SEEDBYTES], const polyveck *t1) {
2019-01-16 10:02:32 +00:00
unsigned int i;
2019-01-16 09:15:18 +00:00
2019-01-16 12:02:35 +00:00
for (i = 0; i < SEEDBYTES; ++i) {
2019-01-16 10:02:32 +00:00
pk[i] = rho[i];
2019-01-16 12:02:35 +00:00
}
2019-01-16 10:02:32 +00:00
pk += SEEDBYTES;
2019-01-16 09:15:18 +00:00
2019-01-16 12:02:35 +00:00
for (i = 0; i < K; ++i) {
2019-01-16 10:02:32 +00:00
polyt1_pack(pk + i * POLT1_SIZE_PACKED, t1->vec + i);
2019-01-16 12:02:35 +00:00
}
2019-01-16 09:15:18 +00:00
}
/*************************************************
* Name: unpack_pk
*
* Description: Unpack public key pk = (rho, t1).
*
* Arguments: - const unsigned char rho[]: output byte array for rho
* - const polyveck *t1: pointer to output vector t1
* - unsigned char pk[]: byte array containing bit-packed pk
**************************************************/
void unpack_pk(unsigned char rho[SEEDBYTES], polyveck *t1,
const unsigned char pk[CRYPTO_PUBLICKEYBYTES]) {
2019-01-16 10:02:32 +00:00
unsigned int i;
2019-01-16 09:15:18 +00:00
2019-01-16 12:02:35 +00:00
for (i = 0; i < SEEDBYTES; ++i) {
2019-01-16 10:02:32 +00:00
rho[i] = pk[i];
2019-01-16 12:02:35 +00:00
}
2019-01-16 10:02:32 +00:00
pk += SEEDBYTES;
2019-01-16 09:15:18 +00:00
2019-01-16 12:02:35 +00:00
for (i = 0; i < K; ++i) {
2019-01-16 10:02:32 +00:00
polyt1_unpack(t1->vec + i, pk + i * POLT1_SIZE_PACKED);
2019-01-16 12:02:35 +00:00
}
2019-01-16 09:15:18 +00:00
}
/*************************************************
* Name: pack_sk
*
* Description: Bit-pack secret key sk = (rho, key, tr, s1, s2, t0).
*
* Arguments: - unsigned char sk[]: output byte array
* - const unsigned char rho[]: byte array containing rho
* - const unsigned char key[]: byte array containing key
* - const unsigned char tr[]: byte array containing tr
* - const polyvecl *s1: pointer to vector s1
* - const polyveck *s2: pointer to vector s2
* - const polyveck *t0: pointer to vector t0
**************************************************/
void pack_sk(unsigned char sk[CRYPTO_SECRETKEYBYTES],
const unsigned char rho[SEEDBYTES],
const unsigned char key[SEEDBYTES],
const unsigned char tr[CRHBYTES], const polyvecl *s1,
const polyveck *s2, const polyveck *t0) {
2019-01-16 10:02:32 +00:00
unsigned int i;
2019-01-16 09:15:18 +00:00
2019-01-16 12:02:35 +00:00
for (i = 0; i < SEEDBYTES; ++i) {
2019-01-16 10:02:32 +00:00
sk[i] = rho[i];
2019-01-16 12:02:35 +00:00
}
2019-01-16 10:02:32 +00:00
sk += SEEDBYTES;
2019-01-16 09:15:18 +00:00
2019-01-16 12:02:35 +00:00
for (i = 0; i < SEEDBYTES; ++i) {
2019-01-16 10:02:32 +00:00
sk[i] = key[i];
2019-01-16 12:02:35 +00:00
}
2019-01-16 10:02:32 +00:00
sk += SEEDBYTES;
2019-01-16 09:15:18 +00:00
2019-01-16 12:02:35 +00:00
for (i = 0; i < CRHBYTES; ++i) {
2019-01-16 10:02:32 +00:00
sk[i] = tr[i];
2019-01-16 12:02:35 +00:00
}
2019-01-16 10:02:32 +00:00
sk += CRHBYTES;
2019-01-16 09:15:18 +00:00
2019-01-16 12:02:35 +00:00
for (i = 0; i < L; ++i) {
2019-01-16 10:02:32 +00:00
polyeta_pack(sk + i * POLETA_SIZE_PACKED, s1->vec + i);
2019-01-16 12:02:35 +00:00
}
2019-01-16 10:02:32 +00:00
sk += L * POLETA_SIZE_PACKED;
2019-01-16 09:15:18 +00:00
2019-01-16 12:02:35 +00:00
for (i = 0; i < K; ++i) {
2019-01-16 10:02:32 +00:00
polyeta_pack(sk + i * POLETA_SIZE_PACKED, s2->vec + i);
2019-01-16 12:02:35 +00:00
}
2019-01-16 10:02:32 +00:00
sk += K * POLETA_SIZE_PACKED;
2019-01-16 09:15:18 +00:00
2019-01-16 12:02:35 +00:00
for (i = 0; i < K; ++i) {
2019-01-16 10:02:32 +00:00
polyt0_pack(sk + i * POLT0_SIZE_PACKED, t0->vec + i);
2019-01-16 12:02:35 +00:00
}
2019-01-16 09:15:18 +00:00
}
/*************************************************
* Name: unpack_sk
*
* Description: Unpack secret key sk = (rho, key, tr, s1, s2, t0).
*
* Arguments: - const unsigned char rho[]: output byte array for rho
* - const unsigned char key[]: output byte array for key
* - const unsigned char tr[]: output byte array for tr
* - const polyvecl *s1: pointer to output vector s1
* - const polyveck *s2: pointer to output vector s2
* - const polyveck *r0: pointer to output vector t0
* - unsigned char sk[]: byte array containing bit-packed sk
**************************************************/
void unpack_sk(unsigned char rho[SEEDBYTES], unsigned char key[SEEDBYTES],
unsigned char tr[CRHBYTES], polyvecl *s1, polyveck *s2,
polyveck *t0, const unsigned char sk[CRYPTO_SECRETKEYBYTES]) {
2019-01-16 10:02:32 +00:00
unsigned int i;
2019-01-16 09:15:18 +00:00
2019-01-16 12:02:35 +00:00
for (i = 0; i < SEEDBYTES; ++i) {
2019-01-16 10:02:32 +00:00
rho[i] = sk[i];
2019-01-16 12:02:35 +00:00
}
2019-01-16 10:02:32 +00:00
sk += SEEDBYTES;
2019-01-16 09:15:18 +00:00
2019-01-16 12:02:35 +00:00
for (i = 0; i < SEEDBYTES; ++i) {
2019-01-16 10:02:32 +00:00
key[i] = sk[i];
2019-01-16 12:02:35 +00:00
}
2019-01-16 10:02:32 +00:00
sk += SEEDBYTES;
2019-01-16 09:15:18 +00:00
2019-01-16 12:02:35 +00:00
for (i = 0; i < CRHBYTES; ++i) {
2019-01-16 10:02:32 +00:00
tr[i] = sk[i];
2019-01-16 12:02:35 +00:00
}
2019-01-16 10:02:32 +00:00
sk += CRHBYTES;
2019-01-16 09:15:18 +00:00
2019-01-16 12:02:35 +00:00
for (i = 0; i < L; ++i) {
2019-01-16 10:02:32 +00:00
polyeta_unpack(s1->vec + i, sk + i * POLETA_SIZE_PACKED);
2019-01-16 12:02:35 +00:00
}
2019-01-16 10:02:32 +00:00
sk += L * POLETA_SIZE_PACKED;
2019-01-16 09:15:18 +00:00
2019-01-16 12:02:35 +00:00
for (i = 0; i < K; ++i) {
2019-01-16 10:02:32 +00:00
polyeta_unpack(s2->vec + i, sk + i * POLETA_SIZE_PACKED);
2019-01-16 12:02:35 +00:00
}
2019-01-16 10:02:32 +00:00
sk += K * POLETA_SIZE_PACKED;
2019-01-16 09:15:18 +00:00
2019-01-16 12:02:35 +00:00
for (i = 0; i < K; ++i) {
2019-01-16 10:02:32 +00:00
polyt0_unpack(t0->vec + i, sk + i * POLT0_SIZE_PACKED);
2019-01-16 12:02:35 +00:00
}
2019-01-16 09:15:18 +00:00
}
/*************************************************
* Name: pack_sig
*
* Description: Bit-pack signature sig = (z, h, c).
*
* Arguments: - unsigned char sig[]: output byte array
* - const polyvecl *z: pointer to vector z
* - const polyveck *h: pointer to hint vector h
* - const poly *c: pointer to challenge polynomial
**************************************************/
void pack_sig(unsigned char sig[CRYPTO_BYTES], const polyvecl *z,
const polyveck *h, const poly *c) {
2019-01-16 10:02:32 +00:00
unsigned int i, j, k;
uint64_t signs, mask;
2019-01-16 12:02:35 +00:00
for (i = 0; i < L; ++i) {
2019-01-16 10:02:32 +00:00
polyz_pack(sig + i * POLZ_SIZE_PACKED, z->vec + i);
2019-01-16 12:02:35 +00:00
}
2019-01-16 10:02:32 +00:00
sig += L * POLZ_SIZE_PACKED;
/* Encode h */
k = 0;
for (i = 0; i < K; ++i) {
2019-01-16 12:02:35 +00:00
for (j = 0; j < N; ++j) {
if (h->vec[i].coeffs[j] != 0) {
2019-01-16 10:02:32 +00:00
sig[k++] = j;
2019-01-16 12:02:35 +00:00
}
}
2019-01-16 10:02:32 +00:00
sig[OMEGA + i] = k;
2019-01-16 09:15:18 +00:00
}
2019-01-16 12:02:35 +00:00
while (k < OMEGA) {
2019-01-16 10:02:32 +00:00
sig[k++] = 0;
2019-01-16 12:02:35 +00:00
}
2019-01-16 10:02:32 +00:00
sig += OMEGA + K;
/* Encode c */
signs = 0;
mask = 1;
for (i = 0; i < N / 8; ++i) {
sig[i] = 0;
for (j = 0; j < 8; ++j) {
if (c->coeffs[8 * i + j] != 0) {
sig[i] |= (1U << j);
2019-01-16 12:02:35 +00:00
if (c->coeffs[8 * i + j] == (Q - 1)) {
2019-01-16 10:02:32 +00:00
signs |= mask;
2019-01-16 12:02:35 +00:00
}
2019-01-16 10:02:32 +00:00
mask <<= 1;
}
}
}
sig += N / 8;
2019-01-16 12:02:35 +00:00
for (i = 0; i < 8; ++i) {
2019-01-16 10:02:32 +00:00
sig[i] = signs >> 8 * i;
2019-01-16 12:02:35 +00:00
}
2019-01-16 09:15:18 +00:00
}
/*************************************************
* Name: unpack_sig
*
* Description: Unpack signature sig = (z, h, c).
*
* Arguments: - polyvecl *z: pointer to output vector z
* - polyveck *h: pointer to output hint vector h
* - poly *c: pointer to output challenge polynomial
* - const unsigned char sig[]: byte array containing
* bit-packed signature
*
* Returns 1 in case of malformed signature; otherwise 0.
**************************************************/
int unpack_sig(polyvecl *z, polyveck *h, poly *c,
const unsigned char sig[CRYPTO_BYTES]) {
2019-01-16 10:02:32 +00:00
unsigned int i, j, k;
uint64_t signs, mask;
2019-01-16 12:02:35 +00:00
for (i = 0; i < L; ++i) {
2019-01-16 10:02:32 +00:00
polyz_unpack(z->vec + i, sig + i * POLZ_SIZE_PACKED);
2019-01-16 12:02:35 +00:00
}
2019-01-16 10:02:32 +00:00
sig += L * POLZ_SIZE_PACKED;
/* Decode h */
k = 0;
for (i = 0; i < K; ++i) {
2019-01-16 12:02:35 +00:00
for (j = 0; j < N; ++j) {
2019-01-16 10:02:32 +00:00
h->vec[i].coeffs[j] = 0;
2019-01-16 12:02:35 +00:00
}
2019-01-16 10:02:32 +00:00
2019-01-16 12:02:35 +00:00
if (sig[OMEGA + i] < k || sig[OMEGA + i] > OMEGA) {
2019-01-16 10:02:32 +00:00
return 1;
2019-01-16 12:02:35 +00:00
}
2019-01-16 10:02:32 +00:00
for (j = k; j < sig[OMEGA + i]; ++j) {
/* Coefficients are ordered for strong unforgeability */
2019-01-16 12:02:35 +00:00
if (j > k && sig[j] <= sig[j - 1]) {
2019-01-16 10:02:32 +00:00
return 1;
2019-01-16 12:02:35 +00:00
}
2019-01-16 10:02:32 +00:00
h->vec[i].coeffs[sig[j]] = 1;
}
k = sig[OMEGA + i];
2019-01-16 09:15:18 +00:00
}
2019-01-16 10:02:32 +00:00
/* Extra indices are zero for strong unforgeability */
2019-01-16 12:02:35 +00:00
for (j = k; j < OMEGA; ++j) {
if (sig[j]) {
2019-01-16 10:02:32 +00:00
return 1;
2019-01-16 12:02:35 +00:00
}
}
2019-01-16 09:15:18 +00:00
2019-01-16 10:02:32 +00:00
sig += OMEGA + K;
2019-01-16 09:15:18 +00:00
2019-01-16 10:02:32 +00:00
/* Decode c */
2019-01-16 12:02:35 +00:00
for (i = 0; i < N; ++i) {
2019-01-16 10:02:32 +00:00
c->coeffs[i] = 0;
2019-01-16 12:02:35 +00:00
}
2019-01-16 09:15:18 +00:00
2019-01-16 10:02:32 +00:00
signs = 0;
2019-01-16 12:02:35 +00:00
for (i = 0; i < 8; ++i) {
2019-01-16 10:02:32 +00:00
signs |= (uint64_t)sig[N / 8 + i] << 8 * i;
2019-01-16 12:02:35 +00:00
}
2019-01-16 09:15:18 +00:00
2019-01-16 10:02:32 +00:00
/* Extra sign bits are zero for strong unforgeability */
2019-01-16 12:02:35 +00:00
if (signs >> 60) {
2019-01-16 10:02:32 +00:00
return 1;
2019-01-16 12:02:35 +00:00
}
2019-01-16 09:15:18 +00:00
2019-01-16 10:02:32 +00:00
mask = 1;
for (i = 0; i < N / 8; ++i) {
for (j = 0; j < 8; ++j) {
if ((sig[i] >> j) & 0x01) {
c->coeffs[8 * i + j] = (signs & mask) ? Q - 1 : 1;
mask <<= 1;
}
}
2019-01-16 09:15:18 +00:00
}
2019-01-16 10:02:32 +00:00
return 0;
2019-01-16 09:15:18 +00:00
}