Browse Source

Add Dilithium (#172)

* fixes dynamic memory allocation test. previously a function called freeze() would trigger it

* this adds DilithiumII. Preprocessor conditionals still need to be removed

* fix ms Makefile

* fix MS compiler warnings

* clean-up

* remove preprocessor conditionals

* add dilithium3

* add dilithium4

* add duplicate consistency checks

* SHA2 state constants in common

* clean up symmetric.h

* Port SPHINCS+-SHA256 to sha256ctx struct

* Implement ctx struct for fips202

* Port Kyber{512,768,1024} to fips202 ctx struct

* Port NewHope to fips202 structs

* Port SPHINCS+-SHAKE256 to fips202 ctx structs

* Use opaque fips202 structs in MQDSS

* port dilithium to use fips202 ctx structs

* include -Wredundant-decls

* remove comment; format NTT constants

* reduce casts in power2round
master
Matthias J. Kannwischer 5 years ago
committed by GitHub
parent
commit
e56b2e5556
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
70 changed files with 7672 additions and 1 deletions
  1. +19
    -0
      crypto_sign/dilithium2/META.yml
  2. +2
    -0
      crypto_sign/dilithium2/clean/LICENSE
  3. +22
    -0
      crypto_sign/dilithium2/clean/Makefile
  4. +18
    -0
      crypto_sign/dilithium2/clean/Makefile.Microsoft_nmake
  5. +32
    -0
      crypto_sign/dilithium2/clean/api.h
  6. +137
    -0
      crypto_sign/dilithium2/clean/ntt.c
  7. +10
    -0
      crypto_sign/dilithium2/clean/ntt.h
  8. +297
    -0
      crypto_sign/dilithium2/clean/packing.c
  9. +31
    -0
      crypto_sign/dilithium2/clean/packing.h
  10. +35
    -0
      crypto_sign/dilithium2/clean/params.h
  11. +737
    -0
      crypto_sign/dilithium2/clean/poly.c
  12. +53
    -0
      crypto_sign/dilithium2/clean/poly.h
  13. +357
    -0
      crypto_sign/dilithium2/clean/polyvec.c
  14. +51
    -0
      crypto_sign/dilithium2/clean/polyvec.h
  15. +74
    -0
      crypto_sign/dilithium2/clean/reduce.c
  16. +21
    -0
      crypto_sign/dilithium2/clean/reduce.h
  17. +105
    -0
      crypto_sign/dilithium2/clean/rounding.c
  18. +11
    -0
      crypto_sign/dilithium2/clean/rounding.h
  19. +414
    -0
      crypto_sign/dilithium2/clean/sign.c
  20. +30
    -0
      crypto_sign/dilithium2/clean/sign.h
  21. +32
    -0
      crypto_sign/dilithium2/clean/symmetric.c
  22. +23
    -0
      crypto_sign/dilithium2/clean/symmetric.h
  23. +19
    -0
      crypto_sign/dilithium3/META.yml
  24. +2
    -0
      crypto_sign/dilithium3/clean/LICENSE
  25. +22
    -0
      crypto_sign/dilithium3/clean/Makefile
  26. +18
    -0
      crypto_sign/dilithium3/clean/Makefile.Microsoft_nmake
  27. +32
    -0
      crypto_sign/dilithium3/clean/api.h
  28. +137
    -0
      crypto_sign/dilithium3/clean/ntt.c
  29. +10
    -0
      crypto_sign/dilithium3/clean/ntt.h
  30. +297
    -0
      crypto_sign/dilithium3/clean/packing.c
  31. +31
    -0
      crypto_sign/dilithium3/clean/packing.h
  32. +33
    -0
      crypto_sign/dilithium3/clean/params.h
  33. +737
    -0
      crypto_sign/dilithium3/clean/poly.c
  34. +53
    -0
      crypto_sign/dilithium3/clean/poly.h
  35. +357
    -0
      crypto_sign/dilithium3/clean/polyvec.c
  36. +51
    -0
      crypto_sign/dilithium3/clean/polyvec.h
  37. +74
    -0
      crypto_sign/dilithium3/clean/reduce.c
  38. +21
    -0
      crypto_sign/dilithium3/clean/reduce.h
  39. +105
    -0
      crypto_sign/dilithium3/clean/rounding.c
  40. +11
    -0
      crypto_sign/dilithium3/clean/rounding.h
  41. +414
    -0
      crypto_sign/dilithium3/clean/sign.c
  42. +30
    -0
      crypto_sign/dilithium3/clean/sign.h
  43. +32
    -0
      crypto_sign/dilithium3/clean/symmetric.c
  44. +23
    -0
      crypto_sign/dilithium3/clean/symmetric.h
  45. +19
    -0
      crypto_sign/dilithium4/META.yml
  46. +2
    -0
      crypto_sign/dilithium4/clean/LICENSE
  47. +22
    -0
      crypto_sign/dilithium4/clean/Makefile
  48. +18
    -0
      crypto_sign/dilithium4/clean/Makefile.Microsoft_nmake
  49. +31
    -0
      crypto_sign/dilithium4/clean/api.h
  50. +137
    -0
      crypto_sign/dilithium4/clean/ntt.c
  51. +10
    -0
      crypto_sign/dilithium4/clean/ntt.h
  52. +297
    -0
      crypto_sign/dilithium4/clean/packing.c
  53. +31
    -0
      crypto_sign/dilithium4/clean/packing.h
  54. +34
    -0
      crypto_sign/dilithium4/clean/params.h
  55. +760
    -0
      crypto_sign/dilithium4/clean/poly.c
  56. +53
    -0
      crypto_sign/dilithium4/clean/poly.h
  57. +357
    -0
      crypto_sign/dilithium4/clean/polyvec.c
  58. +51
    -0
      crypto_sign/dilithium4/clean/polyvec.h
  59. +74
    -0
      crypto_sign/dilithium4/clean/reduce.c
  60. +21
    -0
      crypto_sign/dilithium4/clean/reduce.h
  61. +105
    -0
      crypto_sign/dilithium4/clean/rounding.c
  62. +11
    -0
      crypto_sign/dilithium4/clean/rounding.h
  63. +414
    -0
      crypto_sign/dilithium4/clean/sign.c
  64. +30
    -0
      crypto_sign/dilithium4/clean/sign.h
  65. +32
    -0
      crypto_sign/dilithium4/clean/symmetric.c
  66. +23
    -0
      crypto_sign/dilithium4/clean/symmetric.h
  67. +40
    -0
      test/duplicate_consistency/dilithium2_clean.yml
  68. +40
    -0
      test/duplicate_consistency/dilithium3_clean.yml
  69. +39
    -0
      test/duplicate_consistency/dilithium4_clean.yml
  70. +1
    -1
      test/test_dynamic_memory.py

+ 19
- 0
crypto_sign/dilithium2/META.yml View File

@@ -0,0 +1,19 @@
name: DilithiumII
type: signature
claimed-nist-level: 1
length-public-key: 1184
length-secret-key: 2800
length-signature: 2044
nistkat-sha256: 23b7d52a268bbd8633d139b64a1b0e3263777cb2b074f7af0a7fd315afe94d18
testvectors-sha256: d647039ae7e1785414c64934d5ae37518f259acab95d6a6e873e9b6d3ad63dfd
principal-submitter: Vadim Lyubashevsky
auxiliary-submitters:
- Léo Ducas
- Eike Kiltz
- Tancrède Lepoint
- Peter Schwabe
- Gregor Seiler
- Damien Stehlé
implementations:
- name: clean
version: https://github.com/pq-crystals/dilithium/commit/40f79645879b5c69835cd91d06945d7c24f39922

+ 2
- 0
crypto_sign/dilithium2/clean/LICENSE View File

@@ -0,0 +1,2 @@
Public Domain
Authors: Léo Ducas, Eike Kiltz, Tancrède Lepoint, Vadim Lyubashevsky, Gregor Seiler, Peter Schwabe, Damien Stehlé

+ 22
- 0
crypto_sign/dilithium2/clean/Makefile View File

@@ -0,0 +1,22 @@
# This Makefile can be used with GNU Make or BSD Make

LIB=libdilithium2_clean.a

SOURCES = sign.c polyvec.c poly.c packing.c ntt.c reduce.c rounding.c symmetric.c
OBJECTS = sign.o polyvec.o poly.o packing.o ntt.o reduce.o rounding.o symmetric.o
HEADERS = api.h params.h sign.h polyvec.h poly.h packing.h ntt.h \
reduce.h rounding.h symmetric.h

CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -Wredundant-decls -std=c99 -I../../../common $(EXTRAFLAGS)

all: $(LIB)

%.o: %.c $(HEADERS)
$(CC) $(CFLAGS) -c -o $@ $<

$(LIB): $(OBJECTS)
$(AR) -r $@ $(OBJECTS)

clean:
$(RM) $(OBJECTS)
$(RM) $(LIB)

+ 18
- 0
crypto_sign/dilithium2/clean/Makefile.Microsoft_nmake View File

@@ -0,0 +1,18 @@
# This Makefile can be used with Microsoft Visual Studio's nmake using the command:
# nmake /f Makefile.Microsoft_nmake

LIBRARY=libdilithium2_clean.lib
OBJECTS=sign.obj polyvec.obj poly.obj packing.obj ntt.obj reduce.obj rounding.obj symmetric.obj
CFLAGS=/nologo /I ..\..\..\common /W4 /WX

all: $(LIBRARY)

# Make sure objects are recompiled if headers change.
$(OBJECTS): *.h

$(LIBRARY): $(OBJECTS)
LIB.EXE /NOLOGO /WX /OUT:$@ $**

clean:
-DEL $(OBJECTS)
-DEL $(LIBRARY)

+ 32
- 0
crypto_sign/dilithium2/clean/api.h View File

@@ -0,0 +1,32 @@
#ifndef PQCLEAN_DILITHIUM2_CLEAN_API_H
#define PQCLEAN_DILITHIUM2_CLEAN_API_H

#include <stdint.h>

#define MODE 2

#define PQCLEAN_DILITHIUM2_CLEAN_CRYPTO_PUBLICKEYBYTES 1184U
#define PQCLEAN_DILITHIUM2_CLEAN_CRYPTO_SECRETKEYBYTES 2800U
#define PQCLEAN_DILITHIUM2_CLEAN_CRYPTO_BYTES 2044U
#define PQCLEAN_DILITHIUM2_CLEAN_CRYPTO_ALGNAME "Dilithium2"

int PQCLEAN_DILITHIUM2_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk);

int PQCLEAN_DILITHIUM2_CLEAN_crypto_sign_signature(
uint8_t *sig, size_t *siglen,
const uint8_t *m, size_t mlen, const uint8_t *sk);

int PQCLEAN_DILITHIUM2_CLEAN_crypto_sign_verify(
const uint8_t *sig, size_t siglen,
const uint8_t *m, size_t mlen, const uint8_t *pk);

int PQCLEAN_DILITHIUM2_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen,
const uint8_t *msg, size_t len,
const uint8_t *sk);

int PQCLEAN_DILITHIUM2_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen,
const uint8_t *sm, size_t smlen,
const uint8_t *pk);


#endif

+ 137
- 0
crypto_sign/dilithium2/clean/ntt.c View File

@@ -0,0 +1,137 @@
#include "ntt.h"
#include "params.h"
#include "poly.h"
#include "reduce.h"
#include <stdint.h>

/* Roots of unity in order needed by forward ntt */
static const uint32_t zetas[N] = {
0, 25847, 5771523, 7861508, 237124, 7602457, 7504169, 466468, 1826347,
2353451, 8021166, 6288512, 3119733, 5495562, 3111497, 2680103, 2725464,
1024112, 7300517, 3585928, 7830929, 7260833, 2619752, 6271868, 6262231,
4520680, 6980856, 5102745, 1757237, 8360995, 4010497, 280005, 2706023,
95776, 3077325, 3530437, 6718724, 4788269, 5842901, 3915439, 4519302,
5336701, 3574422, 5512770, 3539968, 8079950, 2348700, 7841118, 6681150,
6736599, 3505694, 4558682, 3507263, 6239768, 6779997, 3699596, 811944,
531354, 954230, 3881043, 3900724, 5823537, 2071892, 5582638, 4450022,
6851714, 4702672, 5339162, 6927966, 3475950, 2176455, 6795196, 7122806,
1939314, 4296819, 7380215, 5190273, 5223087, 4747489, 126922, 3412210,
7396998, 2147896, 2715295, 5412772, 4686924, 7969390, 5903370, 7709315,
7151892, 8357436, 7072248, 7998430, 1349076, 1852771, 6949987, 5037034,
264944, 508951, 3097992, 44288, 7280319, 904516, 3958618, 4656075, 8371839,
1653064, 5130689, 2389356, 8169440, 759969, 7063561, 189548, 4827145,
3159746, 6529015, 5971092, 8202977, 1315589, 1341330, 1285669, 6795489,
7567685, 6940675, 5361315, 4499357, 4751448, 3839961, 2091667, 3407706,
2316500, 3817976, 5037939, 2244091, 5933984, 4817955, 266997, 2434439,
7144689, 3513181, 4860065, 4621053, 7183191, 5187039, 900702, 1859098,
909542, 819034, 495491, 6767243, 8337157, 7857917, 7725090, 5257975,
2031748, 3207046, 4823422, 7855319, 7611795, 4784579, 342297, 286988,
5942594, 4108315, 3437287, 5038140, 1735879, 203044, 2842341, 2691481,
5790267, 1265009, 4055324, 1247620, 2486353, 1595974, 4613401, 1250494,
2635921, 4832145, 5386378, 1869119, 1903435, 7329447, 7047359, 1237275,
5062207, 6950192, 7929317, 1312455, 3306115, 6417775, 7100756, 1917081,
5834105, 7005614, 1500165, 777191, 2235880, 3406031, 7838005, 5548557,
6709241, 6533464, 5796124, 4656147, 594136, 4603424, 6366809, 2432395,
2454455, 8215696, 1957272, 3369112, 185531, 7173032, 5196991, 162844,
1616392, 3014001, 810149, 1652634, 4686184, 6581310, 5341501, 3523897,
3866901, 269760, 2213111, 7404533, 1717735, 472078, 7953734, 1723600,
6577327, 1910376, 6712985, 7276084, 8119771, 4546524, 5441381, 6144432,
7959518, 6094090, 183443, 7403526, 1612842, 4834730, 7826001, 3919660,
8332111, 7018208, 3937738, 1400424, 7534263, 1976782
};

/* Roots of unity in order needed by inverse ntt */
static const uint32_t zetas_inv[N] = {
6403635, 846154, 6979993, 4442679, 1362209, 48306, 4460757, 554416,
3545687, 6767575, 976891, 8196974, 2286327, 420899, 2235985, 2939036,
3833893, 260646, 1104333, 1667432, 6470041, 1803090, 6656817, 426683,
7908339, 6662682, 975884, 6167306, 8110657, 4513516, 4856520, 3038916,
1799107, 3694233, 6727783, 7570268, 5366416, 6764025, 8217573, 3183426,
1207385, 8194886, 5011305, 6423145, 164721, 5925962, 5948022, 2013608,
3776993, 7786281, 3724270, 2584293, 1846953, 1671176, 2831860, 542412,
4974386, 6144537, 7603226, 6880252, 1374803, 2546312, 6463336, 1279661,
1962642, 5074302, 7067962, 451100, 1430225, 3318210, 7143142, 1333058,
1050970, 6476982, 6511298, 2994039, 3548272, 5744496, 7129923, 3767016,
6784443, 5894064, 7132797, 4325093, 7115408, 2590150, 5688936, 5538076,
8177373, 6644538, 3342277, 4943130, 4272102, 2437823, 8093429, 8038120,
3595838, 768622, 525098, 3556995, 5173371, 6348669, 3122442, 655327,
522500, 43260, 1613174, 7884926, 7561383, 7470875, 6521319, 7479715,
3193378, 1197226, 3759364, 3520352, 4867236, 1235728, 5945978, 8113420,
3562462, 2446433, 6136326, 3342478, 4562441, 6063917, 4972711, 6288750,
4540456, 3628969, 3881060, 3019102, 1439742, 812732, 1584928, 7094748,
7039087, 7064828, 177440, 2409325, 1851402, 5220671, 3553272, 8190869,
1316856, 7620448, 210977, 5991061, 3249728, 6727353, 8578, 3724342,
4421799, 7475901, 1100098, 8336129, 5282425, 7871466, 8115473, 3343383,
1430430, 6527646, 7031341, 381987, 1308169, 22981, 1228525, 671102,
2477047, 411027, 3693493, 2967645, 5665122, 6232521, 983419, 4968207,
8253495, 3632928, 3157330, 3190144, 1000202, 4083598, 6441103, 1257611,
1585221, 6203962, 4904467, 1452451, 3041255, 3677745, 1528703, 3930395,
2797779, 6308525, 2556880, 4479693, 4499374, 7426187, 7849063, 7568473,
4680821, 1600420, 2140649, 4873154, 3821735, 4874723, 1643818, 1699267,
539299, 6031717, 300467, 4840449, 2867647, 4805995, 3043716, 3861115,
4464978, 2537516, 3592148, 1661693, 4849980, 5303092, 8284641, 5674394,
8100412, 4369920, 19422, 6623180, 3277672, 1399561, 3859737, 2118186,
2108549, 5760665, 1119584, 549488, 4794489, 1079900, 7356305, 5654953,
5700314, 5268920, 2884855, 5260684, 2091905, 359251, 6026966, 6554070,
7913949, 876248, 777960, 8143293, 518909, 2608894, 8354570
};

/*************************************************
* Name: ntt
*
* Description: Forward NTT, in-place. No modular reduction is performed after
* additions or subtractions. Hence output coefficients can be up
* to 16*Q larger than the coefficients of the input polynomial.
* Output vector is in bitreversed order.
*
* Arguments: - uint32_t p[N]: input/output coefficient array
**************************************************/
void PQCLEAN_DILITHIUM2_CLEAN_ntt(uint32_t p[N]) {
unsigned int len, start, j, k;
uint32_t zeta, t;

k = 1;
for (len = 128; len > 0; len >>= 1) {
for (start = 0; start < N; start = j + len) {
zeta = zetas[k++];
for (j = start; j < start + len; ++j) {
t = PQCLEAN_DILITHIUM2_CLEAN_montgomery_reduce((uint64_t)zeta * p[j + len]);
p[j + len] = p[j] + 2 * Q - t;
p[j] = p[j] + t;
}
}
}
}

/*************************************************
* Name: invntt_frominvmont
*
* Description: Inverse NTT and multiplication by Montgomery factor 2^32.
* In-place. No modular reductions after additions or
* subtractions. Input coefficient need to be smaller than 2*Q.
* Output coefficient are smaller than 2*Q.
*
* Arguments: - uint32_t p[N]: input/output coefficient array
**************************************************/
void PQCLEAN_DILITHIUM2_CLEAN_invntt_frominvmont(uint32_t p[N]) {
unsigned int start, len, j, k;
uint32_t t, zeta;
const uint32_t f = (((uint64_t)MONT * MONT % Q) * (Q - 1) % Q) * ((Q - 1) >> 8) % Q;

k = 0;
for (len = 1; len < N; len <<= 1) {
for (start = 0; start < N; start = j + len) {
zeta = zetas_inv[k++];
for (j = start; j < start + len; ++j) {
t = p[j];
p[j] = t + p[j + len];
p[j + len] = t + 256 * Q - p[j + len];
p[j + len] = PQCLEAN_DILITHIUM2_CLEAN_montgomery_reduce((uint64_t)zeta * p[j + len]);
}
}
}

for (j = 0; j < N; ++j) {
p[j] = PQCLEAN_DILITHIUM2_CLEAN_montgomery_reduce((uint64_t)f * p[j]);
}
}

+ 10
- 0
crypto_sign/dilithium2/clean/ntt.h View File

@@ -0,0 +1,10 @@
#ifndef NTT_H
#define NTT_H

#include "params.h"
#include <stdint.h>

void PQCLEAN_DILITHIUM2_CLEAN_ntt(uint32_t p[N]);
void PQCLEAN_DILITHIUM2_CLEAN_invntt_frominvmont(uint32_t p[N]);

#endif

+ 297
- 0
crypto_sign/dilithium2/clean/packing.c View File

@@ -0,0 +1,297 @@
#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 PQCLEAN_DILITHIUM2_CLEAN_pack_pk(unsigned char pk[CRYPTO_PUBLICKEYBYTES],
const unsigned char rho[SEEDBYTES],
const polyveck *t1) {
unsigned int i;

for (i = 0; i < SEEDBYTES; ++i) {
pk[i] = rho[i];
}
pk += SEEDBYTES;

for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM2_CLEAN_polyt1_pack(pk + i * POLT1_SIZE_PACKED, &t1->vec[i]);
}
}

/*************************************************
* 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 PQCLEAN_DILITHIUM2_CLEAN_unpack_pk(unsigned char rho[SEEDBYTES],
polyveck *t1,
const unsigned char pk[CRYPTO_PUBLICKEYBYTES]) {
unsigned int i;

for (i = 0; i < SEEDBYTES; ++i) {
rho[i] = pk[i];
}
pk += SEEDBYTES;

for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM2_CLEAN_polyt1_unpack(&t1->vec[i], pk + i * POLT1_SIZE_PACKED);
}
}

/*************************************************
* 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 PQCLEAN_DILITHIUM2_CLEAN_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) {
unsigned int i;

for (i = 0; i < SEEDBYTES; ++i) {
sk[i] = rho[i];
}
sk += SEEDBYTES;

for (i = 0; i < SEEDBYTES; ++i) {
sk[i] = key[i];
}
sk += SEEDBYTES;

for (i = 0; i < CRHBYTES; ++i) {
sk[i] = tr[i];
}
sk += CRHBYTES;

for (i = 0; i < L; ++i) {
PQCLEAN_DILITHIUM2_CLEAN_polyeta_pack(sk + i * POLETA_SIZE_PACKED, &s1->vec[i]);
}
sk += L * POLETA_SIZE_PACKED;

for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM2_CLEAN_polyeta_pack(sk + i * POLETA_SIZE_PACKED, &s2->vec[i]);
}
sk += K * POLETA_SIZE_PACKED;

for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM2_CLEAN_polyt0_pack(sk + i * POLT0_SIZE_PACKED, &t0->vec[i]);
}
}

/*************************************************
* 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 PQCLEAN_DILITHIUM2_CLEAN_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]) {
unsigned int i;

for (i = 0; i < SEEDBYTES; ++i) {
rho[i] = sk[i];
}
sk += SEEDBYTES;

for (i = 0; i < SEEDBYTES; ++i) {
key[i] = sk[i];
}
sk += SEEDBYTES;

for (i = 0; i < CRHBYTES; ++i) {
tr[i] = sk[i];
}
sk += CRHBYTES;

for (i = 0; i < L; ++i) {
PQCLEAN_DILITHIUM2_CLEAN_polyeta_unpack(&s1->vec[i], sk + i * POLETA_SIZE_PACKED);
}
sk += L * POLETA_SIZE_PACKED;

for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM2_CLEAN_polyeta_unpack(&s2->vec[i], sk + i * POLETA_SIZE_PACKED);
}
sk += K * POLETA_SIZE_PACKED;

for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM2_CLEAN_polyt0_unpack(&t0->vec[i], sk + i * POLT0_SIZE_PACKED);
}
}

/*************************************************
* 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 PQCLEAN_DILITHIUM2_CLEAN_pack_sig(unsigned char sig[CRYPTO_BYTES],
const polyvecl *z,
const polyveck *h,
const poly *c) {
unsigned int i, j, k;
uint64_t signs, mask;

for (i = 0; i < L; ++i) {
PQCLEAN_DILITHIUM2_CLEAN_polyz_pack(sig + i * POLZ_SIZE_PACKED, &z->vec[i]);
}
sig += L * POLZ_SIZE_PACKED;

/* Encode h */
k = 0;
for (i = 0; i < K; ++i) {
for (j = 0; j < N; ++j) {
if (h->vec[i].coeffs[j] != 0) {
sig[k++] = (unsigned char) j;
}
}
sig[OMEGA + i] = (unsigned char) k;
}
while (k < OMEGA) {
sig[k++] = 0;
}
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] |= (unsigned char) (1U << j);
if (c->coeffs[8 * i + j] == (Q - 1)) {
signs |= mask;
}
mask <<= 1;
}
}
}
sig += N / 8;
for (i = 0; i < 8; ++i) {
sig[i] = (unsigned char) (signs >> 8 * i);
}
}

/*************************************************
* 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 PQCLEAN_DILITHIUM2_CLEAN_unpack_sig(polyvecl *z,
polyveck *h,
poly *c,
const unsigned char sig[CRYPTO_BYTES]) {
unsigned int i, j, k;
uint64_t signs;

for (i = 0; i < L; ++i) {
PQCLEAN_DILITHIUM2_CLEAN_polyz_unpack(&z->vec[i], sig + i * POLZ_SIZE_PACKED);
}
sig += L * POLZ_SIZE_PACKED;

/* Decode h */
k = 0;
for (i = 0; i < K; ++i) {
for (j = 0; j < N; ++j) {
h->vec[i].coeffs[j] = 0;
}

if (sig[OMEGA + i] < k || sig[OMEGA + i] > OMEGA) {
return 1;
}

for (j = k; j < sig[OMEGA + i]; ++j) {
/* Coefficients are ordered for strong unforgeability */
if (j > k && sig[j] <= sig[j - 1]) {
return 1;
}
h->vec[i].coeffs[sig[j]] = 1;
}

k = sig[OMEGA + i];
}

/* Extra indices are zero for strong unforgeability */
for (j = k; j < OMEGA; ++j) {
if (sig[j]) {
return 1;
}
}
sig += OMEGA + K;

/* Decode c */
for (i = 0; i < N; ++i) {
c->coeffs[i] = 0;
}

signs = 0;
for (i = 0; i < 8; ++i) {
signs |= (uint64_t)sig[N / 8 + i] << 8 * i;
}

/* Extra sign bits are zero for strong unforgeability */
if (signs >> 60) {
return 1;
}

for (i = 0; i < N / 8; ++i) {
for (j = 0; j < 8; ++j) {
if ((sig[i] >> j) & 0x01) {
c->coeffs[8 * i + j] = 1;
c->coeffs[8 * i + j] ^= -((int32_t) signs & 1) & (1 ^ (Q - 1));
signs >>= 1;
}
}
}

return 0;
}

+ 31
- 0
crypto_sign/dilithium2/clean/packing.h View File

@@ -0,0 +1,31 @@
#ifndef PACKING_H
#define PACKING_H

#include "params.h"
#include "polyvec.h"

void PQCLEAN_DILITHIUM2_CLEAN_pack_pk(unsigned char pk[CRYPTO_PUBLICKEYBYTES],
const unsigned char rho[SEEDBYTES], const polyveck *t1);
void PQCLEAN_DILITHIUM2_CLEAN_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);
void PQCLEAN_DILITHIUM2_CLEAN_pack_sig(unsigned char sig[CRYPTO_BYTES],
const polyvecl *z, const polyveck *h, const poly *c);

void PQCLEAN_DILITHIUM2_CLEAN_unpack_pk(unsigned char rho[SEEDBYTES], polyveck *t1,
const unsigned char pk[CRYPTO_PUBLICKEYBYTES]);
void PQCLEAN_DILITHIUM2_CLEAN_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]);
int PQCLEAN_DILITHIUM2_CLEAN_unpack_sig(polyvecl *z, polyveck *h, poly *c,
const unsigned char sig[CRYPTO_BYTES]);

#endif

+ 35
- 0
crypto_sign/dilithium2/clean/params.h View File

@@ -0,0 +1,35 @@
#ifndef PARAMS_H
#define PARAMS_H

#define SEEDBYTES 32
#define CRHBYTES 48
#define N 256
#define Q 8380417
#define QBITS 23
#define ROOT_OF_UNITY 1753
#define D 14
#define GAMMA1 ((Q - 1)/16)
#define GAMMA2 (GAMMA1/2)
#define ALPHA (2*GAMMA2)


// DilithiumII parameters
#define K 4
#define L 3
#define ETA 6
#define SETABITS 4
#define BETA 325
#define OMEGA 80


#define POLT1_SIZE_PACKED ((N*(QBITS - D))/8)
#define POLT0_SIZE_PACKED ((N*D)/8)
#define POLETA_SIZE_PACKED ((N*SETABITS)/8)
#define POLZ_SIZE_PACKED ((N*(QBITS - 3))/8)
#define POLW1_SIZE_PACKED ((N*4)/8)

#define CRYPTO_PUBLICKEYBYTES (SEEDBYTES + K*POLT1_SIZE_PACKED)
#define CRYPTO_SECRETKEYBYTES (2*SEEDBYTES + (L + K)*POLETA_SIZE_PACKED + CRHBYTES + K*POLT0_SIZE_PACKED)
#define CRYPTO_BYTES (L*POLZ_SIZE_PACKED + (OMEGA + K) + (N/8 + 8))

#endif

+ 737
- 0
crypto_sign/dilithium2/clean/poly.c View File

@@ -0,0 +1,737 @@
#include "ntt.h"
#include "params.h"
#include "poly.h"
#include "reduce.h"
#include "rounding.h"
#include "symmetric.h"
#include <stdint.h>


/*************************************************
* Name: PQCLEAN_DILITHIUM2_CLEAN_poly_reduce
*
* Description: Reduce all coefficients of input polynomial to representative
* in [0,2*Q[.
*
* Arguments: - poly *a: pointer to input/output polynomial
**************************************************/
void PQCLEAN_DILITHIUM2_CLEAN_poly_reduce(poly *a) {
unsigned int i;
for (i = 0; i < N; ++i) {
a->coeffs[i] = PQCLEAN_DILITHIUM2_CLEAN_reduce32(a->coeffs[i]);
}
}

/*************************************************
* Name: PQCLEAN_DILITHIUM2_CLEAN_poly_csubq
*
* Description: For all coefficients of input polynomial subtract Q if
* coefficient is bigger than Q.
*
* Arguments: - poly *a: pointer to input/output polynomial
**************************************************/
void PQCLEAN_DILITHIUM2_CLEAN_poly_csubq(poly *a) {
unsigned int i;
for (i = 0; i < N; ++i) {
a->coeffs[i] = PQCLEAN_DILITHIUM2_CLEAN_csubq(a->coeffs[i]);
}
}

/*************************************************
* Name: PQCLEAN_DILITHIUM2_CLEAN_poly_freeze
*
* Description: Reduce all coefficients of the polynomial to standard
* representatives.
*
* Arguments: - poly *a: pointer to input/output polynomial
**************************************************/
void PQCLEAN_DILITHIUM2_CLEAN_poly_freeze(poly *a) {
unsigned int i;
for (i = 0; i < N; ++i) {
a->coeffs[i] = PQCLEAN_DILITHIUM2_CLEAN_freeze(a->coeffs[i]);
}
}

/*************************************************
* Name: PQCLEAN_DILITHIUM2_CLEAN_poly_add
*
* Description: Add polynomials. No modular reduction is performed.
*
* Arguments: - poly *c: pointer to output polynomial
* - const poly *a: pointer to first summand
* - const poly *b: pointer to second summand
**************************************************/
void PQCLEAN_DILITHIUM2_CLEAN_poly_add(poly *c, const poly *a, const poly *b) {
unsigned int i;
for (i = 0; i < N; ++i) {
c->coeffs[i] = a->coeffs[i] + b->coeffs[i];
}
}

/*************************************************
* Name: PQCLEAN_DILITHIUM2_CLEAN_poly_sub
*
* Description: Subtract polynomials. Assumes coefficients of second input
* polynomial to be less than 2*Q. No modular reduction is
* performed.
*
* Arguments: - poly *c: pointer to output polynomial
* - const poly *a: pointer to first input polynomial
* - const poly *b: pointer to second input polynomial to be
* subtraced from first input polynomial
**************************************************/
void PQCLEAN_DILITHIUM2_CLEAN_poly_sub(poly *c, const poly *a, const poly *b) {
unsigned int i;
for (i = 0; i < N; ++i) {
c->coeffs[i] = a->coeffs[i] + 2 * Q - b->coeffs[i];
}
}

/*************************************************
* Name: PQCLEAN_DILITHIUM2_CLEAN_poly_shiftl
*
* Description: Multiply polynomial by 2^D without modular reduction. Assumes
* input coefficients to be less than 2^{32-D}.
*
* Arguments: - poly *a: pointer to input/output polynomial
**************************************************/
void PQCLEAN_DILITHIUM2_CLEAN_poly_shiftl(poly *a) {
unsigned int i;
for (i = 0; i < N; ++i) {
a->coeffs[i] <<= D;
}
}

/*************************************************
* Name: PQCLEAN_DILITHIUM2_CLEAN_poly_ntt
*
* Description: Forward NTT. Output coefficients can be up to 16*Q larger than
* input coefficients.
*
* Arguments: - poly *a: pointer to input/output polynomial
**************************************************/
void PQCLEAN_DILITHIUM2_CLEAN_poly_ntt(poly *a) {
PQCLEAN_DILITHIUM2_CLEAN_ntt(a->coeffs);
}

/*************************************************
* Name: PQCLEAN_DILITHIUM2_CLEAN_poly_invntt_montgomery
*
* Description: Inverse NTT and multiplication with 2^{32}. Input coefficients
* need to be less than 2*Q. Output coefficients are less than 2*Q.
*
* Arguments: - poly *a: pointer to input/output polynomial
**************************************************/
void PQCLEAN_DILITHIUM2_CLEAN_poly_invntt_montgomery(poly *a) {
PQCLEAN_DILITHIUM2_CLEAN_invntt_frominvmont(a->coeffs);
}

/*************************************************
* Name: PQCLEAN_DILITHIUM2_CLEAN_poly_pointwise_invmontgomery
*
* Description: Pointwise multiplication of polynomials in NTT domain
* representation and multiplication of resulting polynomial
* with 2^{-32}. Output coefficients are less than 2*Q if input
* coefficient are less than 22*Q.
*
* Arguments: - poly *c: pointer to output polynomial
* - const poly *a: pointer to first input polynomial
* - const poly *b: pointer to second input polynomial
**************************************************/
void PQCLEAN_DILITHIUM2_CLEAN_poly_pointwise_invmontgomery(poly *c, const poly *a, const poly *b) {
unsigned int i;

for (i = 0; i < N; ++i) {
c->coeffs[i] = PQCLEAN_DILITHIUM2_CLEAN_montgomery_reduce((uint64_t)a->coeffs[i] * b->coeffs[i]);
}

}

/*************************************************
* Name: PQCLEAN_DILITHIUM2_CLEAN_poly_power2round
*
* Description: For all coefficients c of the input polynomial,
* compute c0, c1 such that c mod Q = c1*2^D + c0
* with -2^{D-1} < c0 <= 2^{D-1}. Assumes coefficients to be
* standard representatives.
*
* Arguments: - poly *a1: pointer to output polynomial with coefficients c1
* - poly *a0: pointer to output polynomial with coefficients Q + a0
* - const poly *v: pointer to input polynomial
**************************************************/
void PQCLEAN_DILITHIUM2_CLEAN_poly_power2round(poly *a1, poly *a0, const poly *a) {
unsigned int i;

for (i = 0; i < N; ++i) {
a1->coeffs[i] = PQCLEAN_DILITHIUM2_CLEAN_power2round(a->coeffs[i], &a0->coeffs[i]);
}

}

/*************************************************
* Name: PQCLEAN_DILITHIUM2_CLEAN_poly_decompose
*
* Description: For all coefficients c of the input polynomial,
* compute high and low bits c0, c1 such c mod Q = c1*ALPHA + c0
* with -ALPHA/2 < c0 <= ALPHA/2 except c1 = (Q-1)/ALPHA where we
* set c1 = 0 and -ALPHA/2 <= c0 = c mod Q - Q < 0.
* Assumes coefficients to be standard representatives.
*
* Arguments: - poly *a1: pointer to output polynomial with coefficients c1
* - poly *a0: pointer to output polynomial with coefficients Q + a0
* - const poly *c: pointer to input polynomial
**************************************************/
void PQCLEAN_DILITHIUM2_CLEAN_poly_decompose(poly *a1, poly *a0, const poly *a) {
unsigned int i;

for (i = 0; i < N; ++i) {
a1->coeffs[i] = PQCLEAN_DILITHIUM2_CLEAN_decompose(a->coeffs[i], &a0->coeffs[i]);
}

}

/*************************************************
* Name: PQCLEAN_DILITHIUM2_CLEAN_poly_make_hint
*
* Description: Compute hint polynomial. The coefficients of which indicate
* whether the low bits of the corresponding coefficient of
* the input polynomial overflow into the high bits.
*
* Arguments: - poly *h: pointer to output hint polynomial
* - const poly *a0: pointer to low part of input polynomial
* - const poly *a1: pointer to high part of input polynomial
*
* Returns number of 1 bits.
**************************************************/
unsigned int PQCLEAN_DILITHIUM2_CLEAN_poly_make_hint(poly *h, const poly *a0, const poly *a1) {
unsigned int i, s = 0;

for (i = 0; i < N; ++i) {
h->coeffs[i] = PQCLEAN_DILITHIUM2_CLEAN_make_hint(a0->coeffs[i], a1->coeffs[i]);
s += h->coeffs[i];
}

return s;
}

/*************************************************
* Name: PQCLEAN_DILITHIUM2_CLEAN_poly_use_hint
*
* Description: Use hint polynomial to correct the high bits of a polynomial.
*
* Arguments: - poly *a: pointer to output polynomial with corrected high bits
* - const poly *b: pointer to input polynomial
* - const poly *h: pointer to input hint polynomial
**************************************************/
void PQCLEAN_DILITHIUM2_CLEAN_poly_use_hint(poly *a, const poly *b, const poly *h) {
unsigned int i;

for (i = 0; i < N; ++i) {
a->coeffs[i] = PQCLEAN_DILITHIUM2_CLEAN_use_hint(b->coeffs[i], h->coeffs[i]);
}

}

/*************************************************
* Name: PQCLEAN_DILITHIUM2_CLEAN_poly_chknorm
*
* Description: Check infinity norm of polynomial against given bound.
* Assumes input coefficients to be standard representatives.
*
* Arguments: - const poly *a: pointer to polynomial
* - uint32_t B: norm bound
*
* Returns 0 if norm is strictly smaller than B and 1 otherwise.
**************************************************/
int PQCLEAN_DILITHIUM2_CLEAN_poly_chknorm(const poly *a, uint32_t B) {
unsigned int i;
int32_t t;

/* It is ok to leak which coefficient violates the bound since
the probability for each coefficient is independent of secret
data but we must not leak the sign of the centralized representative. */
for (i = 0; i < N; ++i) {
/* Absolute value of centralized representative */
t = (int32_t) ((Q - 1) / 2 - a->coeffs[i]);
t ^= (t >> 31);
t = (Q - 1) / 2 - t;

if ((uint32_t)t >= B) {
return 1;
}
}

return 0;
}

/*************************************************
* Name: rej_uniform
*
* Description: Sample uniformly random coefficients in [0, Q-1] by
* performing rejection sampling using array of random bytes.
*
* Arguments: - uint32_t *a: pointer to output array (allocated)
* - unsigned int len: number of coefficients to be sampled
* - const unsigned char *buf: array of random bytes
* - unsigned int buflen: length of array of random bytes
*
* Returns number of sampled coefficients. Can be smaller than len if not enough
* random bytes were given.
**************************************************/
static unsigned int rej_uniform(uint32_t *a,
unsigned int len,
const unsigned char *buf,
unsigned int buflen) {
unsigned int ctr, pos;
uint32_t t;

ctr = pos = 0;
while (ctr < len && pos + 3 <= buflen) {
t = buf[pos++];
t |= (uint32_t)buf[pos++] << 8;
t |= (uint32_t)buf[pos++] << 16;
t &= 0x7FFFFF;

if (t < Q) {
a[ctr++] = t;
}
}

return ctr;
}

/*************************************************
* Name: PQCLEAN_DILITHIUM2_CLEAN_poly_uniform
*
* Description: Sample polynomial with uniformly random coefficients
* in [0,Q-1] by performing rejection sampling using the
* output stream from SHAKE256(seed|nonce).
*
* Arguments: - poly *a: pointer to output polynomial
* - const unsigned char seed[]: byte array with seed of length
* SEEDBYTES
* - uint16_t nonce: 2-byte nonce
**************************************************/
#define POLY_UNIFORM_NBLOCKS ((769 + STREAM128_BLOCKBYTES)/STREAM128_BLOCKBYTES)
#define POLY_UNIFORM_BUFLEN (POLY_UNIFORM_NBLOCKS * STREAM128_BLOCKBYTES)
void PQCLEAN_DILITHIUM2_CLEAN_poly_uniform(poly *a,
const unsigned char seed[SEEDBYTES],
uint16_t nonce) {
unsigned int i, ctr, off;
unsigned int buflen = POLY_UNIFORM_BUFLEN;
unsigned char buf[POLY_UNIFORM_BUFLEN + 2];
shake128ctx state;

stream128_init(&state, seed, nonce);
stream128_squeezeblocks(buf, POLY_UNIFORM_NBLOCKS, &state);

ctr = rej_uniform(a->coeffs, N, buf, buflen);

while (ctr < N) {
off = buflen % 3;
for (i = 0; i < off; ++i) {
buf[i] = buf[buflen - off + i];
}

buflen = STREAM128_BLOCKBYTES + off;
stream128_squeezeblocks(buf + off, 1, &state);
ctr += rej_uniform(a->coeffs + ctr, N - ctr, buf, buflen);
}
}

/*************************************************
* Name: rej_eta
*
* Description: Sample uniformly random coefficients in [-ETA, ETA] by
* performing rejection sampling using array of random bytes.
*
* Arguments: - uint32_t *a: pointer to output array (allocated)
* - unsigned int len: number of coefficients to be sampled
* - const unsigned char *buf: array of random bytes
* - unsigned int buflen: length of array of random bytes
*
* Returns number of sampled coefficients. Can be smaller than len if not enough
* random bytes were given.
**************************************************/
static unsigned int rej_eta(uint32_t *a,
unsigned int len,
const unsigned char *buf,
unsigned int buflen) {
unsigned int ctr, pos;
uint32_t t0, t1;

ctr = pos = 0;
while (ctr < len && pos < buflen) {
t0 = buf[pos] & 0x0F;
t1 = buf[pos++] >> 4;

if (t0 <= 2 * ETA) {
a[ctr++] = Q + ETA - t0;
}
if (t1 <= 2 * ETA && ctr < len) {
a[ctr++] = Q + ETA - t1;
}
}

return ctr;
}

/*************************************************
* Name: PQCLEAN_DILITHIUM2_CLEAN_poly_uniform_eta
*
* Description: Sample polynomial with uniformly random coefficients
* in [-ETA,ETA] by performing rejection sampling using the
* output stream from SHAKE256(seed|nonce).
*
* Arguments: - poly *a: pointer to output polynomial
* - const unsigned char seed[]: byte array with seed of length
* SEEDBYTES
* - uint16_t nonce: 2-byte nonce
**************************************************/
#define POLY_UNIFORM_ETA_NBLOCKS (((N/2 * (1U << SETABITS)) / (2*ETA + 1)\
+ STREAM128_BLOCKBYTES) / STREAM128_BLOCKBYTES)
#define POLY_UNIFORM_ETA_BUFLEN (POLY_UNIFORM_ETA_NBLOCKS*STREAM128_BLOCKBYTES)
void PQCLEAN_DILITHIUM2_CLEAN_poly_uniform_eta(poly *a,
const unsigned char seed[SEEDBYTES],
uint16_t nonce) {
unsigned int ctr;
unsigned char buf[POLY_UNIFORM_ETA_BUFLEN];
shake128ctx state;

stream128_init(&state, seed, nonce);
stream128_squeezeblocks(buf, POLY_UNIFORM_ETA_NBLOCKS, &state);

ctr = rej_eta(a->coeffs, N, buf, POLY_UNIFORM_ETA_BUFLEN);

while (ctr < N) {
stream128_squeezeblocks(buf, 1, &state);
ctr += rej_eta(a->coeffs + ctr, N - ctr, buf, STREAM128_BLOCKBYTES);
}
}

/*************************************************
* Name: rej_gamma1m1
*
* Description: Sample uniformly random coefficients
* in [-(GAMMA1 - 1), GAMMA1 - 1] by performing rejection sampling
* using array of random bytes.
*
* Arguments: - uint32_t *a: pointer to output array (allocated)
* - unsigned int len: number of coefficients to be sampled
* - const unsigned char *buf: array of random bytes
* - unsigned int buflen: length of array of random bytes
*
* Returns number of sampled coefficients. Can be smaller than len if not enough
* random bytes were given.
**************************************************/
static unsigned int rej_gamma1m1(uint32_t *a,
unsigned int len,
const unsigned char *buf,
unsigned int buflen) {
unsigned int ctr, pos;
uint32_t t0, t1;

ctr = pos = 0;
while (ctr < len && pos + 5 <= buflen) {
t0 = buf[pos];
t0 |= (uint32_t)buf[pos + 1] << 8;
t0 |= (uint32_t)buf[pos + 2] << 16;
t0 &= 0xFFFFF;

t1 = buf[pos + 2] >> 4;
t1 |= (uint32_t)buf[pos + 3] << 4;
t1 |= (uint32_t)buf[pos + 4] << 12;

pos += 5;

if (t0 <= 2 * GAMMA1 - 2) {
a[ctr++] = Q + GAMMA1 - 1 - t0;
}
if (t1 <= 2 * GAMMA1 - 2 && ctr < len) {
a[ctr++] = Q + GAMMA1 - 1 - t1;
}
}

return ctr;
}

/*************************************************
* Name: PQCLEAN_DILITHIUM2_CLEAN_poly_uniform_gamma1m1
*
* Description: Sample polynomial with uniformly random coefficients
* in [-(GAMMA1 - 1), GAMMA1 - 1] by performing rejection
* sampling on output stream of SHAKE256(seed|nonce).
*
* Arguments: - poly *a: pointer to output polynomial
* - const unsigned char seed[]: byte array with seed of length
* CRHBYTES
* - uint16_t nonce: 16-bit nonce
**************************************************/
#define POLY_UNIFORM_GAMMA1M1_NBLOCKS ((641 + STREAM256_BLOCKBYTES) / STREAM256_BLOCKBYTES)
#define POLY_UNIFORM_GAMMA1M1_BUFLEN (POLY_UNIFORM_GAMMA1M1_NBLOCKS * STREAM256_BLOCKBYTES)
void PQCLEAN_DILITHIUM2_CLEAN_poly_uniform_gamma1m1(poly *a,
const unsigned char seed[CRHBYTES],
uint16_t nonce) {
unsigned int i, ctr, off;
unsigned int buflen = POLY_UNIFORM_GAMMA1M1_BUFLEN;
unsigned char buf[POLY_UNIFORM_GAMMA1M1_BUFLEN + 4];
shake256ctx state;

stream256_init(&state, seed, nonce);
stream256_squeezeblocks(buf, POLY_UNIFORM_GAMMA1M1_NBLOCKS, &state);

ctr = rej_gamma1m1(a->coeffs, N, buf, buflen);

while (ctr < N) {
off = buflen % 5;
for (i = 0; i < off; ++i) {
buf[i] = buf[buflen - off + i];
}

buflen = STREAM256_BLOCKBYTES + off;
stream256_squeezeblocks(buf + off, 1, &state);
ctr += rej_gamma1m1(a->coeffs + ctr, N - ctr, buf, buflen);
}
}

/*************************************************
* Name: PQCLEAN_DILITHIUM2_CLEAN_polyeta_pack
*
* Description: Bit-pack polynomial with coefficients in [-ETA,ETA].
* Input coefficients are assumed to lie in [Q-ETA,Q+ETA].
*
* Arguments: - unsigned char *r: pointer to output byte array with at least
* POLETA_SIZE_PACKED bytes
* - const poly *a: pointer to input polynomial
**************************************************/
void PQCLEAN_DILITHIUM2_CLEAN_polyeta_pack(unsigned char *r, const poly *a) {
unsigned int i;
unsigned char t[8];

for (i = 0; i < N / 2; ++i) {
t[0] = (uint8_t) (Q + ETA - a->coeffs[2 * i + 0]);
t[1] = (uint8_t) (Q + ETA - a->coeffs[2 * i + 1]);
r[i] = (uint8_t) (t[0] | (t[1] << 4));
}
}

/*************************************************
* Name: PQCLEAN_DILITHIUM2_CLEAN_polyeta_unpack
*
* Description: Unpack polynomial with coefficients in [-ETA,ETA].
* Output coefficients lie in [Q-ETA,Q+ETA].
*
* Arguments: - poly *r: pointer to output polynomial
* - const unsigned char *a: byte array with bit-packed polynomial
**************************************************/
void PQCLEAN_DILITHIUM2_CLEAN_polyeta_unpack(poly *r, const unsigned char *a) {
unsigned int i;
for (i = 0; i < N / 2; ++i) {
r->coeffs[2 * i + 0] = a[i] & 0x0F;
r->coeffs[2 * i + 1] = a[i] >> 4;
r->coeffs[2 * i + 0] = Q + ETA - r->coeffs[2 * i + 0];
r->coeffs[2 * i + 1] = Q + ETA - r->coeffs[2 * i + 1];
}
}

/*************************************************
* Name: polyt1_pack
*
* Description: Bit-pack polynomial t1 with coefficients fitting in 9 bits.
* Input coefficients are assumed to be standard representatives.
*
* Arguments: - unsigned char *r: pointer to output byte array with at least
* POLT1_SIZE_PACKED bytes
* - const poly *a: pointer to input polynomial
**************************************************/
void PQCLEAN_DILITHIUM2_CLEAN_polyt1_pack(unsigned char *r, const poly *a) {
unsigned int i;

for (i = 0; i < N / 8; ++i) {
r[9 * i + 0] = (uint8_t) ((a->coeffs[8 * i + 0] >> 0));
r[9 * i + 1] = (uint8_t) ((a->coeffs[8 * i + 0] >> 8) | (a->coeffs[8 * i + 1] << 1));
r[9 * i + 2] = (uint8_t) ((a->coeffs[8 * i + 1] >> 7) | (a->coeffs[8 * i + 2] << 2));
r[9 * i + 3] = (uint8_t) ((a->coeffs[8 * i + 2] >> 6) | (a->coeffs[8 * i + 3] << 3));
r[9 * i + 4] = (uint8_t) ((a->coeffs[8 * i + 3] >> 5) | (a->coeffs[8 * i + 4] << 4));
r[9 * i + 5] = (uint8_t) ((a->coeffs[8 * i + 4] >> 4) | (a->coeffs[8 * i + 5] << 5));
r[9 * i + 6] = (uint8_t) ((a->coeffs[8 * i + 5] >> 3) | (a->coeffs[8 * i + 6] << 6));
r[9 * i + 7] = (uint8_t) ((a->coeffs[8 * i + 6] >> 2) | (a->coeffs[8 * i + 7] << 7));
r[9 * i + 8] = (uint8_t) ((a->coeffs[8 * i + 7] >> 1));
}

}

/*************************************************
* Name: polyt1_unpack
*
* Description: Unpack polynomial t1 with 9-bit coefficients.
* Output coefficients are standard representatives.
*
* Arguments: - poly *r: pointer to output polynomial
* - const unsigned char *a: byte array with bit-packed polynomial
**************************************************/
void PQCLEAN_DILITHIUM2_CLEAN_polyt1_unpack(poly *r, const unsigned char *a) {
unsigned int i;

for (i = 0; i < N / 8; ++i) {
r->coeffs[8 * i + 0] = ((a[9 * i + 0] ) | ((uint32_t)a[9 * i + 1] << 8)) & 0x1FF;
r->coeffs[8 * i + 1] = ((a[9 * i + 1] >> 1) | ((uint32_t)a[9 * i + 2] << 7)) & 0x1FF;
r->coeffs[8 * i + 2] = ((a[9 * i + 2] >> 2) | ((uint32_t)a[9 * i + 3] << 6)) & 0x1FF;
r->coeffs[8 * i + 3] = ((a[9 * i + 3] >> 3) | ((uint32_t)a[9 * i + 4] << 5)) & 0x1FF;
r->coeffs[8 * i + 4] = ((a[9 * i + 4] >> 4) | ((uint32_t)a[9 * i + 5] << 4)) & 0x1FF;
r->coeffs[8 * i + 5] = ((a[9 * i + 5] >> 5) | ((uint32_t)a[9 * i + 6] << 3)) & 0x1FF;
r->coeffs[8 * i + 6] = ((a[9 * i + 6] >> 6) | ((uint32_t)a[9 * i + 7] << 2)) & 0x1FF;
r->coeffs[8 * i + 7] = ((a[9 * i + 7] >> 7) | ((uint32_t)a[9 * i + 8] << 1)) & 0x1FF;
}

}

/*************************************************
* Name: PQCLEAN_DILITHIUM2_CLEAN_polyt0_pack
*
* Description: Bit-pack polynomial t0 with coefficients in ]-2^{D-1}, 2^{D-1}].
* Input coefficients are assumed to lie in ]Q-2^{D-1}, Q+2^{D-1}].
*
* Arguments: - unsigned char *r: pointer to output byte array with at least
* POLT0_SIZE_PACKED bytes
* - const poly *a: pointer to input polynomial
**************************************************/
void PQCLEAN_DILITHIUM2_CLEAN_polyt0_pack(unsigned char *r, const poly *a) {
unsigned int i;
uint32_t t[4];

for (i = 0; i < N / 4; ++i) {
t[0] = Q + (1U << (D - 1)) - a->coeffs[4 * i + 0];
t[1] = Q + (1U << (D - 1)) - a->coeffs[4 * i + 1];
t[2] = Q + (1U << (D - 1)) - a->coeffs[4 * i + 2];
t[3] = Q + (1U << (D - 1)) - a->coeffs[4 * i + 3];

r[7 * i + 0] = (uint8_t) (t[0]);
r[7 * i + 1] = (uint8_t) (t[0] >> 8);
r[7 * i + 1] |= (uint8_t) (t[1] << 6);
r[7 * i + 2] = (uint8_t) (t[1] >> 2);
r[7 * i + 3] = (uint8_t) (t[1] >> 10);
r[7 * i + 3] |= (uint8_t) (t[2] << 4);
r[7 * i + 4] = (uint8_t) (t[2] >> 4);
r[7 * i + 5] = (uint8_t) (t[2] >> 12);
r[7 * i + 5] |= (uint8_t) (t[3] << 2);
r[7 * i + 6] = (uint8_t) (t[3] >> 6);
}

}

/*************************************************
* Name: PQCLEAN_DILITHIUM2_CLEAN_polyt0_unpack
*
* Description: Unpack polynomial t0 with coefficients in ]-2^{D-1}, 2^{D-1}].
* Output coefficients lie in ]Q-2^{D-1},Q+2^{D-1}].
*
* Arguments: - poly *r: pointer to output polynomial
* - const unsigned char *a: byte array with bit-packed polynomial
**************************************************/
void PQCLEAN_DILITHIUM2_CLEAN_polyt0_unpack(poly *r, const unsigned char *a) {
unsigned int i;

for (i = 0; i < N / 4; ++i) {
r->coeffs[4 * i + 0] = a[7 * i + 0];
r->coeffs[4 * i + 0] |= (uint32_t)(a[7 * i + 1] & 0x3F) << 8;

r->coeffs[4 * i + 1] = a[7 * i + 1] >> 6;
r->coeffs[4 * i + 1] |= (uint32_t)a[7 * i + 2] << 2;
r->coeffs[4 * i + 1] |= (uint32_t)(a[7 * i + 3] & 0x0F) << 10;

r->coeffs[4 * i + 2] = a[7 * i + 3] >> 4;
r->coeffs[4 * i + 2] |= (uint32_t)a[7 * i + 4] << 4;
r->coeffs[4 * i + 2] |= (uint32_t)(a[7 * i + 5] & 0x03) << 12;

r->coeffs[4 * i + 3] = a[7 * i + 5] >> 2;
r->coeffs[4 * i + 3] |= (uint32_t)a[7 * i + 6] << 6;

r->coeffs[4 * i + 0] = Q + (1U << (D - 1)) - r->coeffs[4 * i + 0];
r->coeffs[4 * i + 1] = Q + (1U << (D - 1)) - r->coeffs[4 * i + 1];
r->coeffs[4 * i + 2] = Q + (1U << (D - 1)) - r->coeffs[4 * i + 2];
r->coeffs[4 * i + 3] = Q + (1U << (D - 1)) - r->coeffs[4 * i + 3];
}

}

/*************************************************
* Name: PQCLEAN_DILITHIUM2_CLEAN_polyz_pack
*
* Description: Bit-pack polynomial z with coefficients
* in [-(GAMMA1 - 1), GAMMA1 - 1].
* Input coefficients are assumed to be standard representatives.
*
* Arguments: - unsigned char *r: pointer to output byte array with at least
* POLZ_SIZE_PACKED bytes
* - const poly *a: pointer to input polynomial
**************************************************/
void PQCLEAN_DILITHIUM2_CLEAN_polyz_pack(unsigned char *r, const poly *a) {
unsigned int i;
uint32_t t[2];

for (i = 0; i < N / 2; ++i) {
/* Map to {0,...,2*GAMMA1 - 2} */
t[0] = GAMMA1 - 1 - a->coeffs[2 * i + 0];
t[0] += ((int32_t)t[0] >> 31) & Q;
t[1] = GAMMA1 - 1 - a->coeffs[2 * i + 1];
t[1] += ((int32_t)t[1] >> 31) & Q;

r[5 * i + 0] = (uint8_t) (t[0]);
r[5 * i + 1] = (uint8_t) (t[0] >> 8);
r[5 * i + 2] = (uint8_t) (t[0] >> 16);
r[5 * i + 2] |= (uint8_t) (t[1] << 4);
r[5 * i + 3] = (uint8_t) (t[1] >> 4);
r[5 * i + 4] = (uint8_t) (t[1] >> 12);
}

}

/*************************************************
* Name: PQCLEAN_DILITHIUM2_CLEAN_polyz_unpack
*
* Description: Unpack polynomial z with coefficients
* in [-(GAMMA1 - 1), GAMMA1 - 1].
* Output coefficients are standard representatives.
*
* Arguments: - poly *r: pointer to output polynomial
* - const unsigned char *a: byte array with bit-packed polynomial
**************************************************/
void PQCLEAN_DILITHIUM2_CLEAN_polyz_unpack(poly *r, const unsigned char *a) {
unsigned int i;

for (i = 0; i < N / 2; ++i) {
r->coeffs[2 * i + 0] = a[5 * i + 0];
r->coeffs[2 * i + 0] |= (uint32_t)a[5 * i + 1] << 8;
r->coeffs[2 * i + 0] |= (uint32_t)(a[5 * i + 2] & 0x0F) << 16;

r->coeffs[2 * i + 1] = a[5 * i + 2] >> 4;
r->coeffs[2 * i + 1] |= (uint32_t)a[5 * i + 3] << 4;
r->coeffs[2 * i + 1] |= (uint32_t)a[5 * i + 4] << 12;

r->coeffs[2 * i + 0] = GAMMA1 - 1 - r->coeffs[2 * i + 0];
r->coeffs[2 * i + 0] += ((int32_t)r->coeffs[2 * i + 0] >> 31) & Q;
r->coeffs[2 * i + 1] = GAMMA1 - 1 - r->coeffs[2 * i + 1];
r->coeffs[2 * i + 1] += ((int32_t)r->coeffs[2 * i + 1] >> 31) & Q;
}

}

/*************************************************
* Name: PQCLEAN_DILITHIUM2_CLEAN_polyw1_pack
*
* Description: Bit-pack polynomial w1 with coefficients in [0, 15].
* Input coefficients are assumed to be standard representatives.
*
* Arguments: - unsigned char *r: pointer to output byte array with at least
* POLW1_SIZE_PACKED bytes
* - const poly *a: pointer to input polynomial
**************************************************/
void PQCLEAN_DILITHIUM2_CLEAN_polyw1_pack(unsigned char *r, const poly *a) {
unsigned int i;

for (i = 0; i < N / 2; ++i) {
r[i] = (uint8_t) (a->coeffs[2 * i + 0] | (a->coeffs[2 * i + 1] << 4));
}

}

+ 53
- 0
crypto_sign/dilithium2/clean/poly.h View File

@@ -0,0 +1,53 @@
#ifndef POLY_H
#define POLY_H

#include "params.h"
#include <stdint.h>

typedef struct {
uint32_t coeffs[N];
} poly;

void PQCLEAN_DILITHIUM2_CLEAN_poly_reduce(poly *a);
void PQCLEAN_DILITHIUM2_CLEAN_poly_csubq(poly *a);
void PQCLEAN_DILITHIUM2_CLEAN_poly_freeze(poly *a);

void PQCLEAN_DILITHIUM2_CLEAN_poly_add(poly *c, const poly *a, const poly *b);
void PQCLEAN_DILITHIUM2_CLEAN_poly_sub(poly *c, const poly *a, const poly *b);
void PQCLEAN_DILITHIUM2_CLEAN_poly_shiftl(poly *a);

void PQCLEAN_DILITHIUM2_CLEAN_poly_ntt(poly *a);
void PQCLEAN_DILITHIUM2_CLEAN_poly_invntt_montgomery(poly *a);
void PQCLEAN_DILITHIUM2_CLEAN_poly_pointwise_invmontgomery(poly *c, const poly *a, const poly *b);

void PQCLEAN_DILITHIUM2_CLEAN_poly_power2round(poly *a1, poly *a0, const poly *a);
void PQCLEAN_DILITHIUM2_CLEAN_poly_decompose(poly *a1, poly *a0, const poly *a);
unsigned int PQCLEAN_DILITHIUM2_CLEAN_poly_make_hint(poly *h, const poly *a0, const poly *a1);
void PQCLEAN_DILITHIUM2_CLEAN_poly_use_hint(poly *a, const poly *b, const poly *h);

int PQCLEAN_DILITHIUM2_CLEAN_poly_chknorm(const poly *a, uint32_t B);
void PQCLEAN_DILITHIUM2_CLEAN_poly_uniform(poly *a,
const unsigned char seed[SEEDBYTES],
uint16_t nonce);
void PQCLEAN_DILITHIUM2_CLEAN_poly_uniform_eta(poly *a,
const unsigned char seed[SEEDBYTES],
uint16_t nonce);
void PQCLEAN_DILITHIUM2_CLEAN_poly_uniform_gamma1m1(poly *a,
const unsigned char seed[CRHBYTES],
uint16_t nonce);

void PQCLEAN_DILITHIUM2_CLEAN_polyeta_pack(unsigned char *r, const poly *a);
void PQCLEAN_DILITHIUM2_CLEAN_polyeta_unpack(poly *r, const unsigned char *a);

void PQCLEAN_DILITHIUM2_CLEAN_polyt1_pack(unsigned char *r, const poly *a);
void PQCLEAN_DILITHIUM2_CLEAN_polyt1_unpack(poly *r, const unsigned char *a);

void PQCLEAN_DILITHIUM2_CLEAN_polyt0_pack(unsigned char *r, const poly *a);
void PQCLEAN_DILITHIUM2_CLEAN_polyt0_unpack(poly *r, const unsigned char *a);

void PQCLEAN_DILITHIUM2_CLEAN_polyz_pack(unsigned char *r, const poly *a);
void PQCLEAN_DILITHIUM2_CLEAN_polyz_unpack(poly *r, const unsigned char *a);

void PQCLEAN_DILITHIUM2_CLEAN_polyw1_pack(unsigned char *r, const poly *a);

#endif

+ 357
- 0
crypto_sign/dilithium2/clean/polyvec.c View File

@@ -0,0 +1,357 @@
#include "params.h"
#include "poly.h"
#include "polyvec.h"
#include <stdint.h>

/**************************************************************/
/************ Vectors of polynomials of length L **************/
/**************************************************************/

/*************************************************
* Name: polyvecl_freeze
*
* Description: Reduce coefficients of polynomials in vector of length L
* to standard representatives.
*
* Arguments: - polyvecl *v: pointer to input/output vector
**************************************************/
void PQCLEAN_DILITHIUM2_CLEAN_polyvecl_freeze(polyvecl *v) {
unsigned int i;

for (i = 0; i < L; ++i) {
PQCLEAN_DILITHIUM2_CLEAN_poly_freeze(&v->vec[i]);
}
}

/*************************************************
* Name: polyvecl_add
*
* Description: Add vectors of polynomials of length L.
* No modular reduction is performed.
*
* Arguments: - polyvecl *w: pointer to output vector
* - const polyvecl *u: pointer to first summand
* - const polyvecl *v: pointer to second summand
**************************************************/
void PQCLEAN_DILITHIUM2_CLEAN_polyvecl_add(polyvecl *w, const polyvecl *u, const polyvecl *v) {
unsigned int i;

for (i = 0; i < L; ++i) {
PQCLEAN_DILITHIUM2_CLEAN_poly_add(&w->vec[i], &u->vec[i], &v->vec[i]);
}
}

/*************************************************
* Name: polyvecl_ntt
*
* Description: Forward NTT of all polynomials in vector of length L. Output
* coefficients can be up to 16*Q larger than input coefficients.
*
* Arguments: - polyvecl *v: pointer to input/output vector
**************************************************/
void PQCLEAN_DILITHIUM2_CLEAN_polyvecl_ntt(polyvecl *v) {
unsigned int i;

for (i = 0; i < L; ++i) {
PQCLEAN_DILITHIUM2_CLEAN_poly_ntt(&v->vec[i]);
}
}

/*************************************************
* Name: polyvecl_pointwise_acc_invmontgomery
*
* Description: Pointwise multiply vectors of polynomials of length L, multiply
* resulting vector by 2^{-32} and add (accumulate) polynomials
* in it. Input/output vectors are in NTT domain representation.
* Input coefficients are assumed to be less than 22*Q. Output
* coeffcient are less than 2*L*Q.
*
* Arguments: - poly *w: output polynomial
* - const polyvecl *u: pointer to first input vector
* - const polyvecl *v: pointer to second input vector
**************************************************/
void PQCLEAN_DILITHIUM2_CLEAN_polyvecl_pointwise_acc_invmontgomery(poly *w,
const polyvecl *u,
const polyvecl *v) {
unsigned int i;
poly t;

PQCLEAN_DILITHIUM2_CLEAN_poly_pointwise_invmontgomery(w, &u->vec[0], &v->vec[0]);

for (i = 1; i < L; ++i) {
PQCLEAN_DILITHIUM2_CLEAN_poly_pointwise_invmontgomery(&t, &u->vec[i], &v->vec[i]);
PQCLEAN_DILITHIUM2_CLEAN_poly_add(w, w, &t);
}
}

/*************************************************
* Name: polyvecl_chknorm
*
* Description: Check infinity norm of polynomials in vector of length L.
* Assumes input coefficients to be standard representatives.
*
* Arguments: - const polyvecl *v: pointer to vector
* - uint32_t B: norm bound
*
* Returns 0 if norm of all polynomials is strictly smaller than B and 1
* otherwise.
**************************************************/
int PQCLEAN_DILITHIUM2_CLEAN_polyvecl_chknorm(const polyvecl *v, uint32_t bound) {
unsigned int i;

for (i = 0; i < L; ++i) {
if (PQCLEAN_DILITHIUM2_CLEAN_poly_chknorm(&v->vec[i], bound)) {
return 1;
}
}
return 0;
}

/**************************************************************/
/************ Vectors of polynomials of length K **************/
/**************************************************************/


/*************************************************
* Name: polyveck_reduce
*
* Description: Reduce coefficients of polynomials in vector of length K
* to representatives in [0,2*Q[.
*
* Arguments: - polyveck *v: pointer to input/output vector
**************************************************/
void PQCLEAN_DILITHIUM2_CLEAN_polyveck_reduce(polyveck *v) {
unsigned int i;

for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM2_CLEAN_poly_reduce(&v->vec[i]);
}
}

/*************************************************
* Name: polyveck_csubq
*
* Description: For all coefficients of polynomials in vector of length K
* subtract Q if coefficient is bigger than Q.
*
* Arguments: - polyveck *v: pointer to input/output vector
**************************************************/
void PQCLEAN_DILITHIUM2_CLEAN_polyveck_csubq(polyveck *v) {
unsigned int i;

for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM2_CLEAN_poly_csubq(&v->vec[i]);
}
}

/*************************************************
* Name: polyveck_freeze
*
* Description: Reduce coefficients of polynomials in vector of length K
* to standard representatives.
*
* Arguments: - polyveck *v: pointer to input/output vector
**************************************************/
void PQCLEAN_DILITHIUM2_CLEAN_polyveck_freeze(polyveck *v) {
unsigned int i;

for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM2_CLEAN_poly_freeze(&v->vec[i]);
}
}

/*************************************************
* Name: polyveck_add
*
* Description: Add vectors of polynomials of length K.
* No modular reduction is performed.
*
* Arguments: - polyveck *w: pointer to output vector
* - const polyveck *u: pointer to first summand
* - const polyveck *v: pointer to second summand
**************************************************/
void PQCLEAN_DILITHIUM2_CLEAN_polyveck_add(polyveck *w, const polyveck *u, const polyveck *v) {
unsigned int i;

for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM2_CLEAN_poly_add(&w->vec[i], &u->vec[i], &v->vec[i]);
}
}

/*************************************************
* Name: polyveck_sub
*
* Description: Subtract vectors of polynomials of length K.
* Assumes coefficients of polynomials in second input vector
* to be less than 2*Q. No modular reduction is performed.
*
* Arguments: - polyveck *w: pointer to output vector
* - const polyveck *u: pointer to first input vector
* - const polyveck *v: pointer to second input vector to be
* subtracted from first input vector
**************************************************/
void PQCLEAN_DILITHIUM2_CLEAN_polyveck_sub(polyveck *w, const polyveck *u, const polyveck *v) {
unsigned int i;

for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM2_CLEAN_poly_sub(&w->vec[i], &u->vec[i], &v->vec[i]);
}
}

/*************************************************
* Name: polyveck_shiftl
*
* Description: Multiply vector of polynomials of Length K by 2^D without modular
* reduction. Assumes input coefficients to be less than 2^{32-D}.
*
* Arguments: - polyveck *v: pointer to input/output vector
**************************************************/
void PQCLEAN_DILITHIUM2_CLEAN_polyveck_shiftl(polyveck *v) {
unsigned int i;

for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM2_CLEAN_poly_shiftl(&v->vec[i]);
}
}

/*************************************************
* Name: polyveck_ntt
*
* Description: Forward NTT of all polynomials in vector of length K. Output
* coefficients can be up to 16*Q larger than input coefficients.
*
* Arguments: - polyveck *v: pointer to input/output vector
**************************************************/
void PQCLEAN_DILITHIUM2_CLEAN_polyveck_ntt(polyveck *v) {
unsigned int i;

for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM2_CLEAN_poly_ntt(&v->vec[i]);
}
}

/*************************************************
* Name: polyveck_invntt_montgomery
*
* Description: Inverse NTT and multiplication by 2^{32} of polynomials
* in vector of length K. Input coefficients need to be less
* than 2*Q.
*
* Arguments: - polyveck *v: pointer to input/output vector
**************************************************/
void PQCLEAN_DILITHIUM2_CLEAN_polyveck_invntt_montgomery(polyveck *v) {
unsigned int i;

for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM2_CLEAN_poly_invntt_montgomery(&v->vec[i]);
}
}

/*************************************************
* Name: polyveck_chknorm
*
* Description: Check infinity norm of polynomials in vector of length K.
* Assumes input coefficients to be standard representatives.
*
* Arguments: - const polyveck *v: pointer to vector
* - uint32_t B: norm bound
*
* Returns 0 if norm of all polynomials are strictly smaller than B and 1
* otherwise.
**************************************************/
int PQCLEAN_DILITHIUM2_CLEAN_polyveck_chknorm(const polyveck *v, uint32_t bound) {
unsigned int i;

for (i = 0; i < K; ++i) {
if (PQCLEAN_DILITHIUM2_CLEAN_poly_chknorm(&v->vec[i], bound)) {
return 1;
}
}
return 0;
}

/*************************************************
* Name: polyveck_power2round
*
* Description: For all coefficients a of polynomials in vector of length K,
* compute a0, a1 such that a mod Q = a1*2^D + a0
* with -2^{D-1} < a0 <= 2^{D-1}. Assumes coefficients to be
* standard representatives.
*
* Arguments: - polyveck *v1: pointer to output vector of polynomials with
* coefficients a1
* - polyveck *v0: pointer to output vector of polynomials with
* coefficients Q + a0
* - const polyveck *v: pointer to input vector
**************************************************/
void PQCLEAN_DILITHIUM2_CLEAN_polyveck_power2round(polyveck *v1, polyveck *v0, const polyveck *v) {
unsigned int i;

for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM2_CLEAN_poly_power2round(&v1->vec[i], &v0->vec[i], &v->vec[i]);
}
}

/*************************************************
* Name: polyveck_decompose
*
* Description: For all coefficients a of polynomials in vector of length K,
* compute high and low bits a0, a1 such a mod Q = a1*ALPHA + a0
* with -ALPHA/2 < a0 <= ALPHA/2 except a1 = (Q-1)/ALPHA where we
* set a1 = 0 and -ALPHA/2 <= a0 = a mod Q - Q < 0.
* Assumes coefficients to be standard representatives.
*
* Arguments: - polyveck *v1: pointer to output vector of polynomials with
* coefficients a1
* - polyveck *v0: pointer to output vector of polynomials with
* coefficients Q + a0
* - const polyveck *v: pointer to input vector
**************************************************/
void PQCLEAN_DILITHIUM2_CLEAN_polyveck_decompose(polyveck *v1, polyveck *v0, const polyveck *v) {
unsigned int i;

for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM2_CLEAN_poly_decompose(&v1->vec[i], &v0->vec[i], &v->vec[i]);
}
}

/*************************************************
* Name: polyveck_make_hint
*
* Description: Compute hint vector.
*
* Arguments: - polyveck *h: pointer to output vector
* - const polyveck *v0: pointer to low part of input vector
* - const polyveck *v1: pointer to high part of input vector
*
* Returns number of 1 bits.
**************************************************/
unsigned int PQCLEAN_DILITHIUM2_CLEAN_polyveck_make_hint(polyveck *h,
const polyveck *v0,
const polyveck *v1) {
unsigned int i, s = 0;

for (i = 0; i < K; ++i) {
s += PQCLEAN_DILITHIUM2_CLEAN_poly_make_hint(&h->vec[i], &v0->vec[i], &v1->vec[i]);
}

return s;
}

/*************************************************
* Name: polyveck_use_hint
*
* Description: Use hint vector to correct the high bits of input vector.
*
* Arguments: - polyveck *w: pointer to output vector of polynomials with
* corrected high bits
* - const polyveck *u: pointer to input vector
* - const polyveck *h: pointer to input hint vector
**************************************************/
void PQCLEAN_DILITHIUM2_CLEAN_polyveck_use_hint(polyveck *w, const polyveck *u, const polyveck *h) {
unsigned int i;

for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM2_CLEAN_poly_use_hint(&w->vec[i], &u->vec[i], &h->vec[i]);
}
}

+ 51
- 0
crypto_sign/dilithium2/clean/polyvec.h View File

@@ -0,0 +1,51 @@
#ifndef POLYVEC_H
#define POLYVEC_H

#include "params.h"
#include "poly.h"
#include <stdint.h>

/* Vectors of polynomials of length L */
typedef struct {
poly vec[L];
} polyvecl;

void PQCLEAN_DILITHIUM2_CLEAN_polyvecl_freeze(polyvecl *v);

void PQCLEAN_DILITHIUM2_CLEAN_polyvecl_add(polyvecl *w, const polyvecl *u, const polyvecl *v);

void PQCLEAN_DILITHIUM2_CLEAN_polyvecl_ntt(polyvecl *v);
void PQCLEAN_DILITHIUM2_CLEAN_polyvecl_pointwise_acc_invmontgomery(poly *w,
const polyvecl *u,
const polyvecl *v);

int PQCLEAN_DILITHIUM2_CLEAN_polyvecl_chknorm(const polyvecl *v, uint32_t B);



/* Vectors of polynomials of length K */
typedef struct {
poly vec[K];
} polyveck;

void PQCLEAN_DILITHIUM2_CLEAN_polyveck_reduce(polyveck *v);
void PQCLEAN_DILITHIUM2_CLEAN_polyveck_csubq(polyveck *v);
void PQCLEAN_DILITHIUM2_CLEAN_polyveck_freeze(polyveck *v);

void PQCLEAN_DILITHIUM2_CLEAN_polyveck_add(polyveck *w, const polyveck *u, const polyveck *v);
void PQCLEAN_DILITHIUM2_CLEAN_polyveck_sub(polyveck *w, const polyveck *u, const polyveck *v);
void PQCLEAN_DILITHIUM2_CLEAN_polyveck_shiftl(polyveck *v);

void PQCLEAN_DILITHIUM2_CLEAN_polyveck_ntt(polyveck *v);
void PQCLEAN_DILITHIUM2_CLEAN_polyveck_invntt_montgomery(polyveck *v);

int PQCLEAN_DILITHIUM2_CLEAN_polyveck_chknorm(const polyveck *v, uint32_t B);

void PQCLEAN_DILITHIUM2_CLEAN_polyveck_power2round(polyveck *v1, polyveck *v0, const polyveck *v);
void PQCLEAN_DILITHIUM2_CLEAN_polyveck_decompose(polyveck *v1, polyveck *v0, const polyveck *v);
unsigned int PQCLEAN_DILITHIUM2_CLEAN_polyveck_make_hint(polyveck *h,
const polyveck *v0,
const polyveck *v1);
void PQCLEAN_DILITHIUM2_CLEAN_polyveck_use_hint(polyveck *w, const polyveck *u, const polyveck *h);

#endif

+ 74
- 0
crypto_sign/dilithium2/clean/reduce.c View File

@@ -0,0 +1,74 @@
#include "params.h"
#include "reduce.h"
#include <stdint.h>

/*************************************************
* Name: montgomery_reduce
*
* Description: For finite field element a with 0 <= a <= Q*2^32,
* compute r \equiv a*2^{-32} (mod Q) such that 0 <= r < 2*Q.
*
* Arguments: - uint64_t: finite field element a
*
* Returns r.
**************************************************/
uint32_t PQCLEAN_DILITHIUM2_CLEAN_montgomery_reduce(uint64_t a) {
uint64_t t;

t = a * QINV;
t &= (1ULL << 32) - 1;
t *= Q;
t = a + t;
t >>= 32;
return (uint32_t) t;
}

/*************************************************
* Name: reduce32
*
* Description: For finite field element a, compute r \equiv a (mod Q)
* such that 0 <= r < 2*Q.
*
* Arguments: - uint32_t: finite field element a
*
* Returns r.
**************************************************/
uint32_t PQCLEAN_DILITHIUM2_CLEAN_reduce32(uint32_t a) {
uint32_t t;

t = a & 0x7FFFFF;
a >>= 23;
t += (a << 13) - a;
return t;
}

/*************************************************
* Name: csubq
*
* Description: Subtract Q if input coefficient is bigger than Q.
*
* Arguments: - uint32_t: finite field element a
*
* Returns r.
**************************************************/
uint32_t PQCLEAN_DILITHIUM2_CLEAN_csubq(uint32_t a) {
a -= Q;
a += ((int32_t)a >> 31) & Q;
return a;
}

/*************************************************
* Name: freeze
*
* Description: For finite field element a, compute standard
* representative r = a mod Q.
*
* Arguments: - uint32_t: finite field element a
*
* Returns r.
**************************************************/
uint32_t PQCLEAN_DILITHIUM2_CLEAN_freeze(uint32_t a) {
a = PQCLEAN_DILITHIUM2_CLEAN_reduce32(a);
a = PQCLEAN_DILITHIUM2_CLEAN_csubq(a);
return a;
}

+ 21
- 0
crypto_sign/dilithium2/clean/reduce.h View File

@@ -0,0 +1,21 @@
#ifndef REDUCE_H
#define REDUCE_H

#include <stdint.h>

#define MONT 4193792U // 2^32 % Q
#define QINV 4236238847U // -q^(-1) mod 2^32

/* a <= Q*2^32 => r < 2*Q */
uint32_t PQCLEAN_DILITHIUM2_CLEAN_montgomery_reduce(uint64_t a);

/* r < 2*Q */
uint32_t PQCLEAN_DILITHIUM2_CLEAN_reduce32(uint32_t a);

/* a < 2*Q => r < Q */
uint32_t PQCLEAN_DILITHIUM2_CLEAN_csubq(uint32_t a);

/* r < Q */
uint32_t PQCLEAN_DILITHIUM2_CLEAN_freeze(uint32_t a);

#endif

+ 105
- 0
crypto_sign/dilithium2/clean/rounding.c View File

@@ -0,0 +1,105 @@
#include "params.h"
#include "rounding.h"
/*************************************************
* Name: power2round
*
* Description: For finite field element a, compute a0, a1 such that
* a mod Q = a1*2^D + a0 with -2^{D-1} < a0 <= 2^{D-1}.
* Assumes a to be standard representative.
*
* Arguments: - uint32_t a: input element
* - uint32_t *a0: pointer to output element Q + a0
*
* Returns a1.
**************************************************/
uint32_t PQCLEAN_DILITHIUM2_CLEAN_power2round(uint32_t a, uint32_t *a0) {
uint32_t t;

/* Centralized remainder mod 2^D */
t = a & ((1U << D) - 1);
t -= ((1U << (D - 1)) + 1);
t += ((uint32_t)((int32_t)t >> 31) & (1U << D));
t -= ((1U << (D - 1)) - 1);
*a0 = (Q + t);
a = (a - t) >> D;
return a;
}

/*************************************************
* Name: decompose
*
* Description: For finite field element a, compute high and low bits a0, a1 such
* that a mod Q = a1*ALPHA + a0 with -ALPHA/2 < a0 <= ALPHA/2 except
* if a1 = (Q-1)/ALPHA where we set a1 = 0 and
* -ALPHA/2 <= a0 = a mod Q - Q < 0. Assumes a to be standard
* representative.
*
* Arguments: - uint32_t a: input element
* - uint32_t *a0: pointer to output element Q + a0
*
* Returns a1.
**************************************************/
uint32_t PQCLEAN_DILITHIUM2_CLEAN_decompose(uint32_t a, uint32_t *a0) {
int32_t t, u;
/* Centralized remainder mod ALPHA */
t = a & 0x7FFFF;
t += (int32_t) ((a >> 19) << 9);
t -= ALPHA / 2 + 1;
t += (t >> 31) & ALPHA;
t -= ALPHA / 2 - 1;
a -= (uint32_t) t;

/* Divide by ALPHA (possible to avoid) */
u = (int32_t) a - 1;
u >>= 31;
a = (a >> 19) + 1;
a -= u & 1;

/* Border case */
*a0 = Q + (uint32_t)t - (a >> 4);
a &= 0xF;
return a;
}

/*************************************************
* Name: make_hint
*
* Description: Compute hint bit indicating whether the low bits of the
* input element overflow into the high bits. Inputs assumed to be
* standard representatives.
*
* Arguments: - uint32_t a0: low bits of input element
* - uint32_t a1: high bits of input element
*
* Returns 1 if high bits of a and b differ and 0 otherwise.
**************************************************/
unsigned int PQCLEAN_DILITHIUM2_CLEAN_make_hint(uint32_t a0, uint32_t a1) {
if (a0 <= GAMMA2 || a0 > Q - GAMMA2 || (a0 == Q - GAMMA2 && a1 == 0)) {
return 0;
}

return 1;
}

/*************************************************
* Name: use_hint
*
* Description: Correct high bits according to hint.
*
* Arguments: - uint32_t a: input element
* - unsigned int hint: hint bit
*
* Returns corrected high bits.
**************************************************/
uint32_t PQCLEAN_DILITHIUM2_CLEAN_use_hint(uint32_t a, unsigned int hint) {
uint32_t a0, a1;

a1 = PQCLEAN_DILITHIUM2_CLEAN_decompose(a, &a0);
if (hint == 0) {
return a1;
}
if (a0 > Q) {
return (a1 + 1) & 0xF;
}
return (a1 - 1) & 0xF;
}

+ 11
- 0
crypto_sign/dilithium2/clean/rounding.h View File

@@ -0,0 +1,11 @@
#ifndef ROUNDING_H
#define ROUNDING_H

#include <stdint.h>

uint32_t PQCLEAN_DILITHIUM2_CLEAN_power2round(uint32_t a, uint32_t *a0);
uint32_t PQCLEAN_DILITHIUM2_CLEAN_decompose(uint32_t a, uint32_t *a0);
unsigned int PQCLEAN_DILITHIUM2_CLEAN_make_hint(uint32_t a0, uint32_t a1);
uint32_t PQCLEAN_DILITHIUM2_CLEAN_use_hint(uint32_t a, unsigned int hint);

#endif

+ 414
- 0
crypto_sign/dilithium2/clean/sign.c View File

@@ -0,0 +1,414 @@
#include "fips202.h"
#include "packing.h"
#include "params.h"
#include "poly.h"
#include "polyvec.h"
#include "randombytes.h"
#include "sign.h"
#include "symmetric.h"

#include <stdint.h>

/*************************************************
* Name: expand_mat
*
* Description: Implementation of ExpandA. Generates matrix A with uniformly
* random coefficients a_{i,j} by performing rejection
* sampling on the output stream of SHAKE128(rho|i|j).
*
* Arguments: - polyvecl mat[K]: output matrix
* - const unsigned char rho[]: byte array containing seed rho
**************************************************/
void PQCLEAN_DILITHIUM2_CLEAN_expand_mat(polyvecl mat[K], const unsigned char rho[SEEDBYTES]) {
unsigned int i, j;

for (i = 0; i < K; ++i) {
for (j = 0; j < L; ++j) {
PQCLEAN_DILITHIUM2_CLEAN_poly_uniform(&mat[i].vec[j], rho, (uint16_t)((i << 8) + j));
}
}
}

/*************************************************
* Name: challenge
*
* Description: Implementation of H. Samples polynomial with 60 nonzero
* coefficients in {-1,1} using the output stream of
* SHAKE256(mu|w1).
*
* Arguments: - poly *c: pointer to output polynomial
* - const unsigned char mu[]: byte array containing mu
* - const polyveck *w1: pointer to vector w1
**************************************************/
void PQCLEAN_DILITHIUM2_CLEAN_challenge(poly *c,
const unsigned char mu[CRHBYTES],
const polyveck *w1) {
unsigned int i, b, pos;
uint64_t signs;
unsigned char inbuf[CRHBYTES + K * POLW1_SIZE_PACKED];
unsigned char outbuf[SHAKE256_RATE];
shake256ctx state;

for (i = 0; i < CRHBYTES; ++i) {
inbuf[i] = mu[i];
}
for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM2_CLEAN_polyw1_pack(inbuf + CRHBYTES + i * POLW1_SIZE_PACKED, &w1->vec[i]);
}

shake256_absorb(&state, inbuf, sizeof(inbuf));
shake256_squeezeblocks(outbuf, 1, &state);

signs = 0;
for (i = 0; i < 8; ++i) {
signs |= (uint64_t)outbuf[i] << 8 * i;
}

pos = 8;

for (i = 0; i < N; ++i) {
c->coeffs[i] = 0;
}

for (i = 196; i < 256; ++i) {
do {
if (pos >= SHAKE256_RATE) {
shake256_squeezeblocks(outbuf, 1, &state);
pos = 0;
}

b = outbuf[pos++];
} while (b > i);

c->coeffs[i] = c->coeffs[b];
c->coeffs[b] = 1;
c->coeffs[b] ^= -((int32_t)signs & 1) & (1 ^ (Q - 1));
signs >>= 1;
}
}

/*************************************************
* Name: crypto_sign_keypair
*
* Description: Generates public and private key.
*
* Arguments: - unsigned char *pk: pointer to output public key (allocated
* array of CRYPTO_PUBLICKEYBYTES bytes)
* - unsigned char *sk: pointer to output private key (allocated
* array of CRYPTO_SECRETKEYBYTES bytes)
*
* Returns 0 (success)
**************************************************/
int PQCLEAN_DILITHIUM2_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk) {
unsigned int i;
unsigned char seedbuf[3 * SEEDBYTES];
unsigned char tr[CRHBYTES];
const unsigned char *rho, *rhoprime, *key;
uint16_t nonce = 0;
polyvecl mat[K];
polyvecl s1, s1hat;
polyveck s2, t, t1, t0;

/* Expand 32 bytes of randomness into rho, rhoprime and key */
randombytes(seedbuf, 3 * SEEDBYTES);
rho = seedbuf;
rhoprime = seedbuf + SEEDBYTES;
key = seedbuf + 2 * SEEDBYTES;

/* Expand matrix */
PQCLEAN_DILITHIUM2_CLEAN_expand_mat(mat, rho);

/* Sample short vectors s1 and s2 */
for (i = 0; i < L; ++i) {
PQCLEAN_DILITHIUM2_CLEAN_poly_uniform_eta(&s1.vec[i], rhoprime, nonce++);
}
for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM2_CLEAN_poly_uniform_eta(&s2.vec[i], rhoprime, nonce++);
}

/* Matrix-vector multiplication */
s1hat = s1;
PQCLEAN_DILITHIUM2_CLEAN_polyvecl_ntt(&s1hat);
for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM2_CLEAN_polyvecl_pointwise_acc_invmontgomery(&t.vec[i], &mat[i], &s1hat);
PQCLEAN_DILITHIUM2_CLEAN_poly_reduce(&t.vec[i]);
PQCLEAN_DILITHIUM2_CLEAN_poly_invntt_montgomery(&t.vec[i]);
}

/* Add error vector s2 */
PQCLEAN_DILITHIUM2_CLEAN_polyveck_add(&t, &t, &s2);

/* Extract t1 and write public key */
PQCLEAN_DILITHIUM2_CLEAN_polyveck_freeze(&t);
PQCLEAN_DILITHIUM2_CLEAN_polyveck_power2round(&t1, &t0, &t);
PQCLEAN_DILITHIUM2_CLEAN_pack_pk(pk, rho, &t1);

/* Compute CRH(rho, t1) and write secret key */
crh(tr, pk, CRYPTO_PUBLICKEYBYTES);
PQCLEAN_DILITHIUM2_CLEAN_pack_sk(sk, rho, key, tr, &s1, &s2, &t0);

return 0;
}

int PQCLEAN_DILITHIUM2_CLEAN_crypto_sign_signature(
uint8_t *sig, size_t *siglen,
const uint8_t *m, size_t mlen, const uint8_t *sk) {
unsigned long long i;
unsigned int n;
unsigned char seedbuf[2 * SEEDBYTES + 3 * CRHBYTES];
unsigned char *rho, *tr, *key, *mu, *rhoprime;
uint16_t nonce = 0;
poly c, chat;
polyvecl mat[K], s1, y, yhat, z;
polyveck t0, s2, w, w1, w0;
polyveck h, cs2, ct0;

rho = seedbuf;
tr = rho + SEEDBYTES;
key = tr + CRHBYTES;
mu = key + SEEDBYTES;
rhoprime = mu + CRHBYTES;
PQCLEAN_DILITHIUM2_CLEAN_unpack_sk(rho, key, tr, &s1, &s2, &t0, sk);


// use incremental hash API instead of copying around buffers
/* Compute CRH(tr, msg) */
shake256incctx state;
shake256_inc_init(&state);
shake256_inc_absorb(&state, tr, CRHBYTES);
shake256_inc_absorb(&state, m, mlen);
shake256_inc_finalize(&state);
shake256_inc_squeeze(mu, CRHBYTES, &state);


for (i = 0; i < CRHBYTES; ++i) {
sig[CRYPTO_BYTES - CRHBYTES + i] = tr[i];
}

crh(rhoprime, key, SEEDBYTES + CRHBYTES);

/* Expand matrix and transform vectors */
PQCLEAN_DILITHIUM2_CLEAN_expand_mat(mat, rho);
PQCLEAN_DILITHIUM2_CLEAN_polyvecl_ntt(&s1);
PQCLEAN_DILITHIUM2_CLEAN_polyveck_ntt(&s2);
PQCLEAN_DILITHIUM2_CLEAN_polyveck_ntt(&t0);

rej:
/* Sample intermediate vector y */
for (i = 0; i < L; ++i) {
PQCLEAN_DILITHIUM2_CLEAN_poly_uniform_gamma1m1(&y.vec[i], rhoprime, nonce++);
}

/* Matrix-vector multiplication */
yhat = y;
PQCLEAN_DILITHIUM2_CLEAN_polyvecl_ntt(&yhat);
for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM2_CLEAN_polyvecl_pointwise_acc_invmontgomery(&w.vec[i], &mat[i], &yhat);
PQCLEAN_DILITHIUM2_CLEAN_poly_reduce(&w.vec[i]);
PQCLEAN_DILITHIUM2_CLEAN_poly_invntt_montgomery(&w.vec[i]);
}

/* Decompose w and call the random oracle */
PQCLEAN_DILITHIUM2_CLEAN_polyveck_csubq(&w);
PQCLEAN_DILITHIUM2_CLEAN_polyveck_decompose(&w1, &w0, &w);
PQCLEAN_DILITHIUM2_CLEAN_challenge(&c, mu, &w1);
chat = c;
PQCLEAN_DILITHIUM2_CLEAN_poly_ntt(&chat);

/* Check that subtracting cs2 does not change high bits of w and low bits
* do not reveal secret information */
for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM2_CLEAN_poly_pointwise_invmontgomery(&cs2.vec[i], &chat, &s2.vec[i]);
PQCLEAN_DILITHIUM2_CLEAN_poly_invntt_montgomery(&cs2.vec[i]);
}
PQCLEAN_DILITHIUM2_CLEAN_polyveck_sub(&w0, &w0, &cs2);
PQCLEAN_DILITHIUM2_CLEAN_polyveck_freeze(&w0);
if (PQCLEAN_DILITHIUM2_CLEAN_polyveck_chknorm(&w0, GAMMA2 - BETA)) {
goto rej;
}

/* Compute z, reject if it reveals secret */
for (i = 0; i < L; ++i) {
PQCLEAN_DILITHIUM2_CLEAN_poly_pointwise_invmontgomery(&z.vec[i], &chat, &s1.vec[i]);
PQCLEAN_DILITHIUM2_CLEAN_poly_invntt_montgomery(&z.vec[i]);
}
PQCLEAN_DILITHIUM2_CLEAN_polyvecl_add(&z, &z, &y);
PQCLEAN_DILITHIUM2_CLEAN_polyvecl_freeze(&z);
if (PQCLEAN_DILITHIUM2_CLEAN_polyvecl_chknorm(&z, GAMMA1 - BETA)) {
goto rej;
}

/* Compute hints for w1 */
for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM2_CLEAN_poly_pointwise_invmontgomery(&ct0.vec[i], &chat, &t0.vec[i]);
PQCLEAN_DILITHIUM2_CLEAN_poly_invntt_montgomery(&ct0.vec[i]);
}

PQCLEAN_DILITHIUM2_CLEAN_polyveck_csubq(&ct0);
if (PQCLEAN_DILITHIUM2_CLEAN_polyveck_chknorm(&ct0, GAMMA2)) {
goto rej;
}

PQCLEAN_DILITHIUM2_CLEAN_polyveck_add(&w0, &w0, &ct0);
PQCLEAN_DILITHIUM2_CLEAN_polyveck_csubq(&w0);
n = PQCLEAN_DILITHIUM2_CLEAN_polyveck_make_hint(&h, &w0, &w1);
if (n > OMEGA) {
goto rej;
}

/* Write signature */
PQCLEAN_DILITHIUM2_CLEAN_pack_sig(sig, &z, &h, &c);

*siglen = CRYPTO_BYTES;
return 0;
}

int PQCLEAN_DILITHIUM2_CLEAN_crypto_sign_verify(
const uint8_t *sig, size_t siglen,
const uint8_t *m, size_t mlen, const uint8_t *pk) {
unsigned long long i;
unsigned char rho[SEEDBYTES];
unsigned char mu[CRHBYTES];
poly c, chat, cp;
polyvecl mat[K], z;
polyveck t1, w1, h, tmp1, tmp2;

if (siglen < CRYPTO_BYTES) {
return -1;
}

PQCLEAN_DILITHIUM2_CLEAN_unpack_pk(rho, &t1, pk);
if (PQCLEAN_DILITHIUM2_CLEAN_unpack_sig(&z, &h, &c, sig)) {
return -1;
}
if (PQCLEAN_DILITHIUM2_CLEAN_polyvecl_chknorm(&z, GAMMA1 - BETA)) {
return -1;
}

/* Compute CRH(CRH(rho, t1), msg) */
shake256incctx state;
shake256_inc_init(&state);
shake256_inc_absorb(&state, pk, CRYPTO_PUBLICKEYBYTES);
shake256_inc_finalize(&state);
shake256_inc_squeeze(mu, CRHBYTES, &state);

shake256_inc_init(&state);
shake256_inc_absorb(&state, mu, CRHBYTES);
shake256_inc_absorb(&state, m, mlen);
shake256_inc_finalize(&state);
shake256_inc_squeeze(mu, CRHBYTES, &state);


/* Matrix-vector multiplication; compute Az - c2^dt1 */
PQCLEAN_DILITHIUM2_CLEAN_expand_mat(mat, rho);

PQCLEAN_DILITHIUM2_CLEAN_polyvecl_ntt(&z);
for (i = 0; i < K ; ++i) {
PQCLEAN_DILITHIUM2_CLEAN_polyvecl_pointwise_acc_invmontgomery(&tmp1.vec[i], &mat[i], &z);
}

chat = c;
PQCLEAN_DILITHIUM2_CLEAN_poly_ntt(&chat);
PQCLEAN_DILITHIUM2_CLEAN_polyveck_shiftl(&t1);
PQCLEAN_DILITHIUM2_CLEAN_polyveck_ntt(&t1);
for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM2_CLEAN_poly_pointwise_invmontgomery(&tmp2.vec[i], &chat, &t1.vec[i]);
}

PQCLEAN_DILITHIUM2_CLEAN_polyveck_sub(&tmp1, &tmp1, &tmp2);
PQCLEAN_DILITHIUM2_CLEAN_polyveck_reduce(&tmp1);
PQCLEAN_DILITHIUM2_CLEAN_polyveck_invntt_montgomery(&tmp1);

/* Reconstruct w1 */
PQCLEAN_DILITHIUM2_CLEAN_polyveck_csubq(&tmp1);
PQCLEAN_DILITHIUM2_CLEAN_polyveck_use_hint(&w1, &tmp1, &h);

/* Call random oracle and verify challenge */
PQCLEAN_DILITHIUM2_CLEAN_challenge(&cp, mu, &w1);
for (i = 0; i < N; ++i) {
if (c.coeffs[i] != cp.coeffs[i]) {
return -1;
}
}

// All good
return 0;
}
/*************************************************
* Name: crypto_sign
*
* Description: Compute signed message.
*
* Arguments: - unsigned char *sm: pointer to output signed message (allocated
* array with CRYPTO_BYTES + mlen bytes),
* can be equal to m
* - unsigned long long *smlen: pointer to output length of signed
* message
* - const unsigned char *m: pointer to message to be signed
* - unsigned long long mlen: length of message
* - const unsigned char *sk: pointer to bit-packed secret key
*
* Returns 0 (success)
**************************************************/
int PQCLEAN_DILITHIUM2_CLEAN_crypto_sign(uint8_t *sm,
size_t *smlen,
const uint8_t *m,
size_t mlen,
const uint8_t *sk) {
size_t i;
int rc;
for (i = 0; i < mlen; i++) {
sm[CRYPTO_BYTES + i] = m[i];
}
rc = PQCLEAN_DILITHIUM2_CLEAN_crypto_sign_signature(sm, smlen, m, mlen, sk);
*smlen += mlen;
return rc;

}

/*************************************************
* Name: crypto_sign_open
*
* Description: Verify signed message.
*
* Arguments: - unsigned char *m: pointer to output message (allocated
* array with smlen bytes), can be equal to sm
* - unsigned long long *mlen: pointer to output length of message
* - const unsigned char *sm: pointer to signed message
* - unsigned long long smlen: length of signed message
* - const unsigned char *sk: pointer to bit-packed public key
*
* Returns 0 if signed message could be verified correctly and -1 otherwise
**************************************************/
int PQCLEAN_DILITHIUM2_CLEAN_crypto_sign_open(uint8_t *m,
size_t *mlen,
const uint8_t *sm,
size_t smlen,
const uint8_t *pk) {
size_t i;
if (smlen < CRYPTO_BYTES) {
goto badsig;
}
*mlen = smlen - CRYPTO_BYTES;

if (PQCLEAN_DILITHIUM2_CLEAN_crypto_sign_verify(sm, CRYPTO_BYTES,
sm + CRYPTO_BYTES, *mlen, pk)) {
goto badsig;
} else {
/* All good, copy msg, return 0 */
for (i = 0; i < *mlen; ++i) {
m[i] = sm[CRYPTO_BYTES + i];
}
return 0;
}

/* Signature verification failed */
badsig:
*mlen = (size_t) -1;
for (i = 0; i < smlen; ++i) {
m[i] = 0;
}

return -1;
}


+ 30
- 0
crypto_sign/dilithium2/clean/sign.h View File

@@ -0,0 +1,30 @@
#ifndef SIGN_H
#define SIGN_H

#include "params.h"
#include "poly.h"
#include "polyvec.h"

void PQCLEAN_DILITHIUM2_CLEAN_expand_mat(polyvecl mat[K], const unsigned char rho[SEEDBYTES]);
void PQCLEAN_DILITHIUM2_CLEAN_challenge(poly *c, const unsigned char mu[CRHBYTES],
const polyveck *w1);

int PQCLEAN_DILITHIUM2_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk);

int PQCLEAN_DILITHIUM2_CLEAN_crypto_sign_signature(
uint8_t *sig, size_t *siglen,
const uint8_t *m, size_t mlen, const uint8_t *sk);

int PQCLEAN_DILITHIUM2_CLEAN_crypto_sign_verify(
const uint8_t *sig, size_t siglen,
const uint8_t *m, size_t mlen, const uint8_t *pk);

int PQCLEAN_DILITHIUM2_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen,
const uint8_t *msg, size_t len,
const uint8_t *sk);

int PQCLEAN_DILITHIUM2_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen,
const uint8_t *sm, size_t smlen,
const uint8_t *pk);

#endif

+ 32
- 0
crypto_sign/dilithium2/clean/symmetric.c View File

@@ -0,0 +1,32 @@
#include "symmetric.h"
#include "fips202.h"

void PQCLEAN_DILITHIUM2_CLEAN_shake128_stream_init(shake128ctx *state,
const unsigned char seed[SEEDBYTES],
uint16_t nonce) {
unsigned int i;
unsigned char buf[SEEDBYTES + 2];

for (i = 0; i < SEEDBYTES; ++i) {
buf[i] = seed[i];
}
buf[SEEDBYTES] = (uint8_t) nonce;
buf[SEEDBYTES + 1] = (uint8_t) (nonce >> 8);

shake128_absorb(state, buf, sizeof(buf));
}

void PQCLEAN_DILITHIUM2_CLEAN_shake256_stream_init(shake256ctx *state,
const unsigned char seed[CRHBYTES],
uint16_t nonce) {
unsigned int i;
unsigned char buf[CRHBYTES + 2];

for (i = 0; i < CRHBYTES; ++i) {
buf[i] = seed[i];
}
buf[CRHBYTES] = (uint8_t) nonce;
buf[CRHBYTES + 1] = (uint8_t) (nonce >> 8);

shake256_absorb(state, buf, sizeof(buf));
}

+ 23
- 0
crypto_sign/dilithium2/clean/symmetric.h View File

@@ -0,0 +1,23 @@
#ifndef SYMMETRIC_H
#define SYMMETRIC_H

#include "fips202.h"
#include "params.h"

#define crh(OUT, IN, INBYTES) shake256(OUT, CRHBYTES, IN, INBYTES)
#define stream128_init(STATE, SEED, NONCE) PQCLEAN_DILITHIUM2_CLEAN_shake128_stream_init(STATE, SEED, NONCE)
#define stream128_squeezeblocks(OUT, OUTBLOCKS, STATE) shake128_squeezeblocks(OUT, OUTBLOCKS, STATE)
#define stream256_init(STATE, SEED, NONCE) PQCLEAN_DILITHIUM2_CLEAN_shake256_stream_init(STATE, SEED, NONCE)
#define stream256_squeezeblocks(OUT, OUTBLOCKS, STATE) shake256_squeezeblocks(OUT, OUTBLOCKS, STATE)

#define STREAM128_BLOCKBYTES SHAKE128_RATE
#define STREAM256_BLOCKBYTES SHAKE256_RATE

void PQCLEAN_DILITHIUM2_CLEAN_shake128_stream_init(shake128ctx *state,
const unsigned char *seed,
uint16_t nonce);
void PQCLEAN_DILITHIUM2_CLEAN_shake256_stream_init(shake256ctx *state,
const unsigned char *seed,
uint16_t nonce);

#endif

+ 19
- 0
crypto_sign/dilithium3/META.yml View File

@@ -0,0 +1,19 @@
name: DilithiumIII
type: signature
claimed-nist-level: 2
length-public-key: 1472
length-secret-key: 3504
length-signature: 2701
nistkat-sha256: 900268789819cc81b03e6384d97336b7bc700a5a9ffd5d3c993deacb6fe7f5b6
testvectors-sha256: 35d7e51b9e4e456c68bfc5ae393d311c96005d8563eb3240a051c97f3710c45d
principal-submitter: Vadim Lyubashevsky
auxiliary-submitters:
- Léo Ducas
- Eike Kiltz
- Tancrède Lepoint
- Peter Schwabe
- Gregor Seiler
- Damien Stehlé
implementations:
- name: clean
version: https://github.com/pq-crystals/dilithium/commit/40f79645879b5c69835cd91d06945d7c24f39922

+ 2
- 0
crypto_sign/dilithium3/clean/LICENSE View File

@@ -0,0 +1,2 @@
Public Domain
Authors: Léo Ducas, Eike Kiltz, Tancrède Lepoint, Vadim Lyubashevsky, Gregor Seiler, Peter Schwabe, Damien Stehlé

+ 22
- 0
crypto_sign/dilithium3/clean/Makefile View File

@@ -0,0 +1,22 @@
# This Makefile can be used with GNU Make or BSD Make

LIB=libdilithium3_clean.a

SOURCES = sign.c polyvec.c poly.c packing.c ntt.c reduce.c rounding.c symmetric.c
OBJECTS = sign.o polyvec.o poly.o packing.o ntt.o reduce.o rounding.o symmetric.o
HEADERS = api.h params.h sign.h polyvec.h poly.h packing.h ntt.h \
reduce.h rounding.h symmetric.h

CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -Wredundant-decls -std=c99 -I../../../common $(EXTRAFLAGS)

all: $(LIB)

%.o: %.c $(HEADERS)
$(CC) $(CFLAGS) -c -o $@ $<

$(LIB): $(OBJECTS)
$(AR) -r $@ $(OBJECTS)

clean:
$(RM) $(OBJECTS)
$(RM) $(LIB)

+ 18
- 0
crypto_sign/dilithium3/clean/Makefile.Microsoft_nmake View File

@@ -0,0 +1,18 @@
# This Makefile can be used with Microsoft Visual Studio's nmake using the command:
# nmake /f Makefile.Microsoft_nmake

LIBRARY=libdilithium3_clean.lib
OBJECTS=sign.obj polyvec.obj poly.obj packing.obj ntt.obj reduce.obj rounding.obj symmetric.obj
CFLAGS=/nologo /I ..\..\..\common /W4 /WX

all: $(LIBRARY)

# Make sure objects are recompiled if headers change.
$(OBJECTS): *.h

$(LIBRARY): $(OBJECTS)
LIB.EXE /NOLOGO /WX /OUT:$@ $**

clean:
-DEL $(OBJECTS)
-DEL $(LIBRARY)

+ 32
- 0
crypto_sign/dilithium3/clean/api.h View File

@@ -0,0 +1,32 @@
#ifndef PQCLEAN_DILITHIUM3_CLEAN_API_H
#define PQCLEAN_DILITHIUM3_CLEAN_API_H

#include <stdint.h>


#define PQCLEAN_DILITHIUM3_CLEAN_CRYPTO_PUBLICKEYBYTES 1472U
#define PQCLEAN_DILITHIUM3_CLEAN_CRYPTO_SECRETKEYBYTES 3504U
#define PQCLEAN_DILITHIUM3_CLEAN_CRYPTO_BYTES 2701U

#define PQCLEAN_DILITHIUM3_CLEAN_CRYPTO_ALGNAME "Dilithium3"

int PQCLEAN_DILITHIUM3_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk);

int PQCLEAN_DILITHIUM3_CLEAN_crypto_sign_signature(
uint8_t *sig, size_t *siglen,
const uint8_t *m, size_t mlen, const uint8_t *sk);

int PQCLEAN_DILITHIUM3_CLEAN_crypto_sign_verify(
const uint8_t *sig, size_t siglen,
const uint8_t *m, size_t mlen, const uint8_t *pk);

int PQCLEAN_DILITHIUM3_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen,
const uint8_t *msg, size_t len,
const uint8_t *sk);

int PQCLEAN_DILITHIUM3_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen,
const uint8_t *sm, size_t smlen,
const uint8_t *pk);


#endif

+ 137
- 0
crypto_sign/dilithium3/clean/ntt.c View File

@@ -0,0 +1,137 @@
#include "ntt.h"
#include "params.h"
#include "poly.h"
#include "reduce.h"
#include <stdint.h>

/* Roots of unity in order needed by forward ntt */
static const uint32_t zetas[N] = {
0, 25847, 5771523, 7861508, 237124, 7602457, 7504169, 466468, 1826347,
2353451, 8021166, 6288512, 3119733, 5495562, 3111497, 2680103, 2725464,
1024112, 7300517, 3585928, 7830929, 7260833, 2619752, 6271868, 6262231,
4520680, 6980856, 5102745, 1757237, 8360995, 4010497, 280005, 2706023,
95776, 3077325, 3530437, 6718724, 4788269, 5842901, 3915439, 4519302,
5336701, 3574422, 5512770, 3539968, 8079950, 2348700, 7841118, 6681150,
6736599, 3505694, 4558682, 3507263, 6239768, 6779997, 3699596, 811944,
531354, 954230, 3881043, 3900724, 5823537, 2071892, 5582638, 4450022,
6851714, 4702672, 5339162, 6927966, 3475950, 2176455, 6795196, 7122806,
1939314, 4296819, 7380215, 5190273, 5223087, 4747489, 126922, 3412210,
7396998, 2147896, 2715295, 5412772, 4686924, 7969390, 5903370, 7709315,
7151892, 8357436, 7072248, 7998430, 1349076, 1852771, 6949987, 5037034,
264944, 508951, 3097992, 44288, 7280319, 904516, 3958618, 4656075, 8371839,
1653064, 5130689, 2389356, 8169440, 759969, 7063561, 189548, 4827145,
3159746, 6529015, 5971092, 8202977, 1315589, 1341330, 1285669, 6795489,
7567685, 6940675, 5361315, 4499357, 4751448, 3839961, 2091667, 3407706,
2316500, 3817976, 5037939, 2244091, 5933984, 4817955, 266997, 2434439,
7144689, 3513181, 4860065, 4621053, 7183191, 5187039, 900702, 1859098,
909542, 819034, 495491, 6767243, 8337157, 7857917, 7725090, 5257975,
2031748, 3207046, 4823422, 7855319, 7611795, 4784579, 342297, 286988,
5942594, 4108315, 3437287, 5038140, 1735879, 203044, 2842341, 2691481,
5790267, 1265009, 4055324, 1247620, 2486353, 1595974, 4613401, 1250494,
2635921, 4832145, 5386378, 1869119, 1903435, 7329447, 7047359, 1237275,
5062207, 6950192, 7929317, 1312455, 3306115, 6417775, 7100756, 1917081,
5834105, 7005614, 1500165, 777191, 2235880, 3406031, 7838005, 5548557,
6709241, 6533464, 5796124, 4656147, 594136, 4603424, 6366809, 2432395,
2454455, 8215696, 1957272, 3369112, 185531, 7173032, 5196991, 162844,
1616392, 3014001, 810149, 1652634, 4686184, 6581310, 5341501, 3523897,
3866901, 269760, 2213111, 7404533, 1717735, 472078, 7953734, 1723600,
6577327, 1910376, 6712985, 7276084, 8119771, 4546524, 5441381, 6144432,
7959518, 6094090, 183443, 7403526, 1612842, 4834730, 7826001, 3919660,
8332111, 7018208, 3937738, 1400424, 7534263, 1976782
};

/* Roots of unity in order needed by inverse ntt */
static const uint32_t zetas_inv[N] = {
6403635, 846154, 6979993, 4442679, 1362209, 48306, 4460757, 554416,
3545687, 6767575, 976891, 8196974, 2286327, 420899, 2235985, 2939036,
3833893, 260646, 1104333, 1667432, 6470041, 1803090, 6656817, 426683,
7908339, 6662682, 975884, 6167306, 8110657, 4513516, 4856520, 3038916,
1799107, 3694233, 6727783, 7570268, 5366416, 6764025, 8217573, 3183426,
1207385, 8194886, 5011305, 6423145, 164721, 5925962, 5948022, 2013608,
3776993, 7786281, 3724270, 2584293, 1846953, 1671176, 2831860, 542412,
4974386, 6144537, 7603226, 6880252, 1374803, 2546312, 6463336, 1279661,
1962642, 5074302, 7067962, 451100, 1430225, 3318210, 7143142, 1333058,
1050970, 6476982, 6511298, 2994039, 3548272, 5744496, 7129923, 3767016,
6784443, 5894064, 7132797, 4325093, 7115408, 2590150, 5688936, 5538076,
8177373, 6644538, 3342277, 4943130, 4272102, 2437823, 8093429, 8038120,
3595838, 768622, 525098, 3556995, 5173371, 6348669, 3122442, 655327,
522500, 43260, 1613174, 7884926, 7561383, 7470875, 6521319, 7479715,
3193378, 1197226, 3759364, 3520352, 4867236, 1235728, 5945978, 8113420,
3562462, 2446433, 6136326, 3342478, 4562441, 6063917, 4972711, 6288750,
4540456, 3628969, 3881060, 3019102, 1439742, 812732, 1584928, 7094748,
7039087, 7064828, 177440, 2409325, 1851402, 5220671, 3553272, 8190869,
1316856, 7620448, 210977, 5991061, 3249728, 6727353, 8578, 3724342,
4421799, 7475901, 1100098, 8336129, 5282425, 7871466, 8115473, 3343383,
1430430, 6527646, 7031341, 381987, 1308169, 22981, 1228525, 671102,
2477047, 411027, 3693493, 2967645, 5665122, 6232521, 983419, 4968207,
8253495, 3632928, 3157330, 3190144, 1000202, 4083598, 6441103, 1257611,
1585221, 6203962, 4904467, 1452451, 3041255, 3677745, 1528703, 3930395,
2797779, 6308525, 2556880, 4479693, 4499374, 7426187, 7849063, 7568473,
4680821, 1600420, 2140649, 4873154, 3821735, 4874723, 1643818, 1699267,
539299, 6031717, 300467, 4840449, 2867647, 4805995, 3043716, 3861115,
4464978, 2537516, 3592148, 1661693, 4849980, 5303092, 8284641, 5674394,
8100412, 4369920, 19422, 6623180, 3277672, 1399561, 3859737, 2118186,
2108549, 5760665, 1119584, 549488, 4794489, 1079900, 7356305, 5654953,
5700314, 5268920, 2884855, 5260684, 2091905, 359251, 6026966, 6554070,
7913949, 876248, 777960, 8143293, 518909, 2608894, 8354570
};

/*************************************************
* Name: ntt
*
* Description: Forward NTT, in-place. No modular reduction is performed after
* additions or subtractions. Hence output coefficients can be up
* to 16*Q larger than the coefficients of the input polynomial.
* Output vector is in bitreversed order.
*
* Arguments: - uint32_t p[N]: input/output coefficient array
**************************************************/
void PQCLEAN_DILITHIUM3_CLEAN_ntt(uint32_t p[N]) {
unsigned int len, start, j, k;
uint32_t zeta, t;

k = 1;
for (len = 128; len > 0; len >>= 1) {
for (start = 0; start < N; start = j + len) {
zeta = zetas[k++];
for (j = start; j < start + len; ++j) {
t = PQCLEAN_DILITHIUM3_CLEAN_montgomery_reduce((uint64_t)zeta * p[j + len]);
p[j + len] = p[j] + 2 * Q - t;
p[j] = p[j] + t;
}
}
}
}

/*************************************************
* Name: invntt_frominvmont
*
* Description: Inverse NTT and multiplication by Montgomery factor 2^32.
* In-place. No modular reductions after additions or
* subtractions. Input coefficient need to be smaller than 2*Q.
* Output coefficient are smaller than 2*Q.
*
* Arguments: - uint32_t p[N]: input/output coefficient array
**************************************************/
void PQCLEAN_DILITHIUM3_CLEAN_invntt_frominvmont(uint32_t p[N]) {
unsigned int start, len, j, k;
uint32_t t, zeta;
const uint32_t f = (((uint64_t)MONT * MONT % Q) * (Q - 1) % Q) * ((Q - 1) >> 8) % Q;

k = 0;
for (len = 1; len < N; len <<= 1) {
for (start = 0; start < N; start = j + len) {
zeta = zetas_inv[k++];
for (j = start; j < start + len; ++j) {
t = p[j];
p[j] = t + p[j + len];
p[j + len] = t + 256 * Q - p[j + len];
p[j + len] = PQCLEAN_DILITHIUM3_CLEAN_montgomery_reduce((uint64_t)zeta * p[j + len]);
}
}
}

for (j = 0; j < N; ++j) {
p[j] = PQCLEAN_DILITHIUM3_CLEAN_montgomery_reduce((uint64_t)f * p[j]);
}
}

+ 10
- 0
crypto_sign/dilithium3/clean/ntt.h View File

@@ -0,0 +1,10 @@
#ifndef NTT_H
#define NTT_H

#include "params.h"
#include <stdint.h>

void PQCLEAN_DILITHIUM3_CLEAN_ntt(uint32_t p[N]);
void PQCLEAN_DILITHIUM3_CLEAN_invntt_frominvmont(uint32_t p[N]);

#endif

+ 297
- 0
crypto_sign/dilithium3/clean/packing.c View File

@@ -0,0 +1,297 @@
#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 PQCLEAN_DILITHIUM3_CLEAN_pack_pk(unsigned char pk[CRYPTO_PUBLICKEYBYTES],
const unsigned char rho[SEEDBYTES],
const polyveck *t1) {
unsigned int i;

for (i = 0; i < SEEDBYTES; ++i) {
pk[i] = rho[i];
}
pk += SEEDBYTES;

for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM3_CLEAN_polyt1_pack(pk + i * POLT1_SIZE_PACKED, &t1->vec[i]);
}
}

/*************************************************
* 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 PQCLEAN_DILITHIUM3_CLEAN_unpack_pk(unsigned char rho[SEEDBYTES],
polyveck *t1,
const unsigned char pk[CRYPTO_PUBLICKEYBYTES]) {
unsigned int i;

for (i = 0; i < SEEDBYTES; ++i) {
rho[i] = pk[i];
}
pk += SEEDBYTES;

for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM3_CLEAN_polyt1_unpack(&t1->vec[i], pk + i * POLT1_SIZE_PACKED);
}
}

/*************************************************
* 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 PQCLEAN_DILITHIUM3_CLEAN_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) {
unsigned int i;

for (i = 0; i < SEEDBYTES; ++i) {
sk[i] = rho[i];
}
sk += SEEDBYTES;

for (i = 0; i < SEEDBYTES; ++i) {
sk[i] = key[i];
}
sk += SEEDBYTES;

for (i = 0; i < CRHBYTES; ++i) {
sk[i] = tr[i];
}
sk += CRHBYTES;

for (i = 0; i < L; ++i) {
PQCLEAN_DILITHIUM3_CLEAN_polyeta_pack(sk + i * POLETA_SIZE_PACKED, &s1->vec[i]);
}
sk += L * POLETA_SIZE_PACKED;

for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM3_CLEAN_polyeta_pack(sk + i * POLETA_SIZE_PACKED, &s2->vec[i]);
}
sk += K * POLETA_SIZE_PACKED;

for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM3_CLEAN_polyt0_pack(sk + i * POLT0_SIZE_PACKED, &t0->vec[i]);
}
}

/*************************************************
* 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 PQCLEAN_DILITHIUM3_CLEAN_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]) {
unsigned int i;

for (i = 0; i < SEEDBYTES; ++i) {
rho[i] = sk[i];
}
sk += SEEDBYTES;

for (i = 0; i < SEEDBYTES; ++i) {
key[i] = sk[i];
}
sk += SEEDBYTES;

for (i = 0; i < CRHBYTES; ++i) {
tr[i] = sk[i];
}
sk += CRHBYTES;

for (i = 0; i < L; ++i) {
PQCLEAN_DILITHIUM3_CLEAN_polyeta_unpack(&s1->vec[i], sk + i * POLETA_SIZE_PACKED);
}
sk += L * POLETA_SIZE_PACKED;

for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM3_CLEAN_polyeta_unpack(&s2->vec[i], sk + i * POLETA_SIZE_PACKED);
}
sk += K * POLETA_SIZE_PACKED;

for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM3_CLEAN_polyt0_unpack(&t0->vec[i], sk + i * POLT0_SIZE_PACKED);
}
}

/*************************************************
* 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 PQCLEAN_DILITHIUM3_CLEAN_pack_sig(unsigned char sig[CRYPTO_BYTES],
const polyvecl *z,
const polyveck *h,
const poly *c) {
unsigned int i, j, k;
uint64_t signs, mask;

for (i = 0; i < L; ++i) {
PQCLEAN_DILITHIUM3_CLEAN_polyz_pack(sig + i * POLZ_SIZE_PACKED, &z->vec[i]);
}
sig += L * POLZ_SIZE_PACKED;

/* Encode h */
k = 0;
for (i = 0; i < K; ++i) {
for (j = 0; j < N; ++j) {
if (h->vec[i].coeffs[j] != 0) {
sig[k++] = (unsigned char) j;
}
}
sig[OMEGA + i] = (unsigned char) k;
}
while (k < OMEGA) {
sig[k++] = 0;
}
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] |= (unsigned char) (1U << j);
if (c->coeffs[8 * i + j] == (Q - 1)) {
signs |= mask;
}
mask <<= 1;
}
}
}
sig += N / 8;
for (i = 0; i < 8; ++i) {
sig[i] = (unsigned char) (signs >> 8 * i);
}
}

/*************************************************
* 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 PQCLEAN_DILITHIUM3_CLEAN_unpack_sig(polyvecl *z,
polyveck *h,
poly *c,
const unsigned char sig[CRYPTO_BYTES]) {
unsigned int i, j, k;
uint64_t signs;

for (i = 0; i < L; ++i) {
PQCLEAN_DILITHIUM3_CLEAN_polyz_unpack(&z->vec[i], sig + i * POLZ_SIZE_PACKED);
}
sig += L * POLZ_SIZE_PACKED;

/* Decode h */
k = 0;
for (i = 0; i < K; ++i) {
for (j = 0; j < N; ++j) {
h->vec[i].coeffs[j] = 0;
}

if (sig[OMEGA + i] < k || sig[OMEGA + i] > OMEGA) {
return 1;
}

for (j = k; j < sig[OMEGA + i]; ++j) {
/* Coefficients are ordered for strong unforgeability */
if (j > k && sig[j] <= sig[j - 1]) {
return 1;
}
h->vec[i].coeffs[sig[j]] = 1;
}

k = sig[OMEGA + i];
}

/* Extra indices are zero for strong unforgeability */
for (j = k; j < OMEGA; ++j) {
if (sig[j]) {
return 1;
}
}
sig += OMEGA + K;

/* Decode c */
for (i = 0; i < N; ++i) {
c->coeffs[i] = 0;
}

signs = 0;
for (i = 0; i < 8; ++i) {
signs |= (uint64_t)sig[N / 8 + i] << 8 * i;
}

/* Extra sign bits are zero for strong unforgeability */
if (signs >> 60) {
return 1;
}

for (i = 0; i < N / 8; ++i) {
for (j = 0; j < 8; ++j) {
if ((sig[i] >> j) & 0x01) {
c->coeffs[8 * i + j] = 1;
c->coeffs[8 * i + j] ^= -((int32_t) signs & 1) & (1 ^ (Q - 1));
signs >>= 1;
}
}
}

return 0;
}

+ 31
- 0
crypto_sign/dilithium3/clean/packing.h View File

@@ -0,0 +1,31 @@
#ifndef PACKING_H
#define PACKING_H

#include "params.h"
#include "polyvec.h"

void PQCLEAN_DILITHIUM3_CLEAN_pack_pk(unsigned char pk[CRYPTO_PUBLICKEYBYTES],
const unsigned char rho[SEEDBYTES], const polyveck *t1);
void PQCLEAN_DILITHIUM3_CLEAN_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);
void PQCLEAN_DILITHIUM3_CLEAN_pack_sig(unsigned char sig[CRYPTO_BYTES],
const polyvecl *z, const polyveck *h, const poly *c);

void PQCLEAN_DILITHIUM3_CLEAN_unpack_pk(unsigned char rho[SEEDBYTES], polyveck *t1,
const unsigned char pk[CRYPTO_PUBLICKEYBYTES]);
void PQCLEAN_DILITHIUM3_CLEAN_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]);
int PQCLEAN_DILITHIUM3_CLEAN_unpack_sig(polyvecl *z, polyveck *h, poly *c,
const unsigned char sig[CRYPTO_BYTES]);

#endif

+ 33
- 0
crypto_sign/dilithium3/clean/params.h View File

@@ -0,0 +1,33 @@
#ifndef PARAMS_H
#define PARAMS_H

#define SEEDBYTES 32
#define CRHBYTES 48
#define N 256
#define Q 8380417
#define QBITS 23
#define ROOT_OF_UNITY 1753
#define D 14
#define GAMMA1 ((Q - 1)/16)
#define GAMMA2 (GAMMA1/2)
#define ALPHA (2*GAMMA2)

// DilithiumIII parameters
#define K 5
#define L 4
#define ETA 5
#define SETABITS 4
#define BETA 275
#define OMEGA 96

#define POLT1_SIZE_PACKED ((N*(QBITS - D))/8)
#define POLT0_SIZE_PACKED ((N*D)/8)
#define POLETA_SIZE_PACKED ((N*SETABITS)/8)
#define POLZ_SIZE_PACKED ((N*(QBITS - 3))/8)
#define POLW1_SIZE_PACKED ((N*4)/8)

#define CRYPTO_PUBLICKEYBYTES (SEEDBYTES + K*POLT1_SIZE_PACKED)
#define CRYPTO_SECRETKEYBYTES (2*SEEDBYTES + (L + K)*POLETA_SIZE_PACKED + CRHBYTES + K*POLT0_SIZE_PACKED)
#define CRYPTO_BYTES (L*POLZ_SIZE_PACKED + (OMEGA + K) + (N/8 + 8))

#endif

+ 737
- 0
crypto_sign/dilithium3/clean/poly.c View File

@@ -0,0 +1,737 @@
#include "ntt.h"
#include "params.h"
#include "poly.h"
#include "reduce.h"
#include "rounding.h"
#include "symmetric.h"
#include <stdint.h>


/*************************************************
* Name: PQCLEAN_DILITHIUM3_CLEAN_poly_reduce
*
* Description: Reduce all coefficients of input polynomial to representative
* in [0,2*Q[.
*
* Arguments: - poly *a: pointer to input/output polynomial
**************************************************/
void PQCLEAN_DILITHIUM3_CLEAN_poly_reduce(poly *a) {
unsigned int i;
for (i = 0; i < N; ++i) {
a->coeffs[i] = PQCLEAN_DILITHIUM3_CLEAN_reduce32(a->coeffs[i]);
}
}

/*************************************************
* Name: PQCLEAN_DILITHIUM3_CLEAN_poly_csubq
*
* Description: For all coefficients of input polynomial subtract Q if
* coefficient is bigger than Q.
*
* Arguments: - poly *a: pointer to input/output polynomial
**************************************************/
void PQCLEAN_DILITHIUM3_CLEAN_poly_csubq(poly *a) {
unsigned int i;
for (i = 0; i < N; ++i) {
a->coeffs[i] = PQCLEAN_DILITHIUM3_CLEAN_csubq(a->coeffs[i]);
}
}

/*************************************************
* Name: PQCLEAN_DILITHIUM3_CLEAN_poly_freeze
*
* Description: Reduce all coefficients of the polynomial to standard
* representatives.
*
* Arguments: - poly *a: pointer to input/output polynomial
**************************************************/
void PQCLEAN_DILITHIUM3_CLEAN_poly_freeze(poly *a) {
unsigned int i;
for (i = 0; i < N; ++i) {
a->coeffs[i] = PQCLEAN_DILITHIUM3_CLEAN_freeze(a->coeffs[i]);
}
}

/*************************************************
* Name: PQCLEAN_DILITHIUM3_CLEAN_poly_add
*
* Description: Add polynomials. No modular reduction is performed.
*
* Arguments: - poly *c: pointer to output polynomial
* - const poly *a: pointer to first summand
* - const poly *b: pointer to second summand
**************************************************/
void PQCLEAN_DILITHIUM3_CLEAN_poly_add(poly *c, const poly *a, const poly *b) {
unsigned int i;
for (i = 0; i < N; ++i) {
c->coeffs[i] = a->coeffs[i] + b->coeffs[i];
}
}

/*************************************************
* Name: PQCLEAN_DILITHIUM3_CLEAN_poly_sub
*
* Description: Subtract polynomials. Assumes coefficients of second input
* polynomial to be less than 2*Q. No modular reduction is
* performed.
*
* Arguments: - poly *c: pointer to output polynomial
* - const poly *a: pointer to first input polynomial
* - const poly *b: pointer to second input polynomial to be
* subtraced from first input polynomial
**************************************************/
void PQCLEAN_DILITHIUM3_CLEAN_poly_sub(poly *c, const poly *a, const poly *b) {
unsigned int i;
for (i = 0; i < N; ++i) {
c->coeffs[i] = a->coeffs[i] + 2 * Q - b->coeffs[i];
}
}

/*************************************************
* Name: PQCLEAN_DILITHIUM3_CLEAN_poly_shiftl
*
* Description: Multiply polynomial by 2^D without modular reduction. Assumes
* input coefficients to be less than 2^{32-D}.
*
* Arguments: - poly *a: pointer to input/output polynomial
**************************************************/
void PQCLEAN_DILITHIUM3_CLEAN_poly_shiftl(poly *a) {
unsigned int i;
for (i = 0; i < N; ++i) {
a->coeffs[i] <<= D;
}
}

/*************************************************
* Name: PQCLEAN_DILITHIUM3_CLEAN_poly_ntt
*
* Description: Forward NTT. Output coefficients can be up to 16*Q larger than
* input coefficients.
*
* Arguments: - poly *a: pointer to input/output polynomial
**************************************************/
void PQCLEAN_DILITHIUM3_CLEAN_poly_ntt(poly *a) {
PQCLEAN_DILITHIUM3_CLEAN_ntt(a->coeffs);
}

/*************************************************
* Name: PQCLEAN_DILITHIUM3_CLEAN_poly_invntt_montgomery
*
* Description: Inverse NTT and multiplication with 2^{32}. Input coefficients
* need to be less than 2*Q. Output coefficients are less than 2*Q.
*
* Arguments: - poly *a: pointer to input/output polynomial
**************************************************/
void PQCLEAN_DILITHIUM3_CLEAN_poly_invntt_montgomery(poly *a) {
PQCLEAN_DILITHIUM3_CLEAN_invntt_frominvmont(a->coeffs);
}

/*************************************************
* Name: PQCLEAN_DILITHIUM3_CLEAN_poly_pointwise_invmontgomery
*
* Description: Pointwise multiplication of polynomials in NTT domain
* representation and multiplication of resulting polynomial
* with 2^{-32}. Output coefficients are less than 2*Q if input
* coefficient are less than 22*Q.
*
* Arguments: - poly *c: pointer to output polynomial
* - const poly *a: pointer to first input polynomial
* - const poly *b: pointer to second input polynomial
**************************************************/
void PQCLEAN_DILITHIUM3_CLEAN_poly_pointwise_invmontgomery(poly *c, const poly *a, const poly *b) {
unsigned int i;

for (i = 0; i < N; ++i) {
c->coeffs[i] = PQCLEAN_DILITHIUM3_CLEAN_montgomery_reduce((uint64_t)a->coeffs[i] * b->coeffs[i]);
}

}

/*************************************************
* Name: PQCLEAN_DILITHIUM3_CLEAN_poly_power2round
*
* Description: For all coefficients c of the input polynomial,
* compute c0, c1 such that c mod Q = c1*2^D + c0
* with -2^{D-1} < c0 <= 2^{D-1}. Assumes coefficients to be
* standard representatives.
*
* Arguments: - poly *a1: pointer to output polynomial with coefficients c1
* - poly *a0: pointer to output polynomial with coefficients Q + a0
* - const poly *v: pointer to input polynomial
**************************************************/
void PQCLEAN_DILITHIUM3_CLEAN_poly_power2round(poly *a1, poly *a0, const poly *a) {
unsigned int i;

for (i = 0; i < N; ++i) {
a1->coeffs[i] = PQCLEAN_DILITHIUM3_CLEAN_power2round(a->coeffs[i], &a0->coeffs[i]);
}

}

/*************************************************
* Name: PQCLEAN_DILITHIUM3_CLEAN_poly_decompose
*
* Description: For all coefficients c of the input polynomial,
* compute high and low bits c0, c1 such c mod Q = c1*ALPHA + c0
* with -ALPHA/2 < c0 <= ALPHA/2 except c1 = (Q-1)/ALPHA where we
* set c1 = 0 and -ALPHA/2 <= c0 = c mod Q - Q < 0.
* Assumes coefficients to be standard representatives.
*
* Arguments: - poly *a1: pointer to output polynomial with coefficients c1
* - poly *a0: pointer to output polynomial with coefficients Q + a0
* - const poly *c: pointer to input polynomial
**************************************************/
void PQCLEAN_DILITHIUM3_CLEAN_poly_decompose(poly *a1, poly *a0, const poly *a) {
unsigned int i;

for (i = 0; i < N; ++i) {
a1->coeffs[i] = PQCLEAN_DILITHIUM3_CLEAN_decompose(a->coeffs[i], &a0->coeffs[i]);
}

}

/*************************************************
* Name: PQCLEAN_DILITHIUM3_CLEAN_poly_make_hint
*
* Description: Compute hint polynomial. The coefficients of which indicate
* whether the low bits of the corresponding coefficient of
* the input polynomial overflow into the high bits.
*
* Arguments: - poly *h: pointer to output hint polynomial
* - const poly *a0: pointer to low part of input polynomial
* - const poly *a1: pointer to high part of input polynomial
*
* Returns number of 1 bits.
**************************************************/
unsigned int PQCLEAN_DILITHIUM3_CLEAN_poly_make_hint(poly *h, const poly *a0, const poly *a1) {
unsigned int i, s = 0;

for (i = 0; i < N; ++i) {
h->coeffs[i] = PQCLEAN_DILITHIUM3_CLEAN_make_hint(a0->coeffs[i], a1->coeffs[i]);
s += h->coeffs[i];
}

return s;
}

/*************************************************
* Name: PQCLEAN_DILITHIUM3_CLEAN_poly_use_hint
*
* Description: Use hint polynomial to correct the high bits of a polynomial.
*
* Arguments: - poly *a: pointer to output polynomial with corrected high bits
* - const poly *b: pointer to input polynomial
* - const poly *h: pointer to input hint polynomial
**************************************************/
void PQCLEAN_DILITHIUM3_CLEAN_poly_use_hint(poly *a, const poly *b, const poly *h) {
unsigned int i;

for (i = 0; i < N; ++i) {
a->coeffs[i] = PQCLEAN_DILITHIUM3_CLEAN_use_hint(b->coeffs[i], h->coeffs[i]);
}

}

/*************************************************
* Name: PQCLEAN_DILITHIUM3_CLEAN_poly_chknorm
*
* Description: Check infinity norm of polynomial against given bound.
* Assumes input coefficients to be standard representatives.
*
* Arguments: - const poly *a: pointer to polynomial
* - uint32_t B: norm bound
*
* Returns 0 if norm is strictly smaller than B and 1 otherwise.
**************************************************/
int PQCLEAN_DILITHIUM3_CLEAN_poly_chknorm(const poly *a, uint32_t B) {
unsigned int i;
int32_t t;

/* It is ok to leak which coefficient violates the bound since
the probability for each coefficient is independent of secret
data but we must not leak the sign of the centralized representative. */
for (i = 0; i < N; ++i) {
/* Absolute value of centralized representative */
t = (int32_t) ((Q - 1) / 2 - a->coeffs[i]);
t ^= (t >> 31);
t = (Q - 1) / 2 - t;

if ((uint32_t)t >= B) {
return 1;
}
}

return 0;
}

/*************************************************
* Name: rej_uniform
*
* Description: Sample uniformly random coefficients in [0, Q-1] by
* performing rejection sampling using array of random bytes.
*
* Arguments: - uint32_t *a: pointer to output array (allocated)
* - unsigned int len: number of coefficients to be sampled
* - const unsigned char *buf: array of random bytes
* - unsigned int buflen: length of array of random bytes
*
* Returns number of sampled coefficients. Can be smaller than len if not enough
* random bytes were given.
**************************************************/
static unsigned int rej_uniform(uint32_t *a,
unsigned int len,
const unsigned char *buf,
unsigned int buflen) {
unsigned int ctr, pos;
uint32_t t;

ctr = pos = 0;
while (ctr < len && pos + 3 <= buflen) {
t = buf[pos++];
t |= (uint32_t)buf[pos++] << 8;
t |= (uint32_t)buf[pos++] << 16;
t &= 0x7FFFFF;

if (t < Q) {
a[ctr++] = t;
}
}

return ctr;
}

/*************************************************
* Name: PQCLEAN_DILITHIUM3_CLEAN_poly_uniform
*
* Description: Sample polynomial with uniformly random coefficients
* in [0,Q-1] by performing rejection sampling using the
* output stream from SHAKE256(seed|nonce).
*
* Arguments: - poly *a: pointer to output polynomial
* - const unsigned char seed[]: byte array with seed of length
* SEEDBYTES
* - uint16_t nonce: 2-byte nonce
**************************************************/
#define POLY_UNIFORM_NBLOCKS ((769 + STREAM128_BLOCKBYTES)/STREAM128_BLOCKBYTES)
#define POLY_UNIFORM_BUFLEN (POLY_UNIFORM_NBLOCKS * STREAM128_BLOCKBYTES)
void PQCLEAN_DILITHIUM3_CLEAN_poly_uniform(poly *a,
const unsigned char seed[SEEDBYTES],
uint16_t nonce) {
unsigned int i, ctr, off;
unsigned int buflen = POLY_UNIFORM_BUFLEN;
unsigned char buf[POLY_UNIFORM_BUFLEN + 2];
shake128ctx state;

stream128_init(&state, seed, nonce);
stream128_squeezeblocks(buf, POLY_UNIFORM_NBLOCKS, &state);

ctr = rej_uniform(a->coeffs, N, buf, buflen);

while (ctr < N) {
off = buflen % 3;
for (i = 0; i < off; ++i) {
buf[i] = buf[buflen - off + i];
}

buflen = STREAM128_BLOCKBYTES + off;
stream128_squeezeblocks(buf + off, 1, &state);
ctr += rej_uniform(a->coeffs + ctr, N - ctr, buf, buflen);
}
}

/*************************************************
* Name: rej_eta
*
* Description: Sample uniformly random coefficients in [-ETA, ETA] by
* performing rejection sampling using array of random bytes.
*
* Arguments: - uint32_t *a: pointer to output array (allocated)
* - unsigned int len: number of coefficients to be sampled
* - const unsigned char *buf: array of random bytes
* - unsigned int buflen: length of array of random bytes
*
* Returns number of sampled coefficients. Can be smaller than len if not enough
* random bytes were given.
**************************************************/
static unsigned int rej_eta(uint32_t *a,
unsigned int len,
const unsigned char *buf,
unsigned int buflen) {
unsigned int ctr, pos;
uint32_t t0, t1;

ctr = pos = 0;
while (ctr < len && pos < buflen) {
t0 = buf[pos] & 0x0F;
t1 = buf[pos++] >> 4;

if (t0 <= 2 * ETA) {
a[ctr++] = Q + ETA - t0;
}
if (t1 <= 2 * ETA && ctr < len) {
a[ctr++] = Q + ETA - t1;
}
}

return ctr;
}

/*************************************************
* Name: PQCLEAN_DILITHIUM3_CLEAN_poly_uniform_eta
*
* Description: Sample polynomial with uniformly random coefficients
* in [-ETA,ETA] by performing rejection sampling using the
* output stream from SHAKE256(seed|nonce).
*
* Arguments: - poly *a: pointer to output polynomial
* - const unsigned char seed[]: byte array with seed of length
* SEEDBYTES
* - uint16_t nonce: 2-byte nonce
**************************************************/
#define POLY_UNIFORM_ETA_NBLOCKS (((N/2 * (1U << SETABITS)) / (2*ETA + 1)\
+ STREAM128_BLOCKBYTES) / STREAM128_BLOCKBYTES)
#define POLY_UNIFORM_ETA_BUFLEN (POLY_UNIFORM_ETA_NBLOCKS*STREAM128_BLOCKBYTES)
void PQCLEAN_DILITHIUM3_CLEAN_poly_uniform_eta(poly *a,
const unsigned char seed[SEEDBYTES],
uint16_t nonce) {
unsigned int ctr;
unsigned char buf[POLY_UNIFORM_ETA_BUFLEN];
shake128ctx state;

stream128_init(&state, seed, nonce);
stream128_squeezeblocks(buf, POLY_UNIFORM_ETA_NBLOCKS, &state);

ctr = rej_eta(a->coeffs, N, buf, POLY_UNIFORM_ETA_BUFLEN);

while (ctr < N) {
stream128_squeezeblocks(buf, 1, &state);
ctr += rej_eta(a->coeffs + ctr, N - ctr, buf, STREAM128_BLOCKBYTES);
}
}

/*************************************************
* Name: rej_gamma1m1
*
* Description: Sample uniformly random coefficients
* in [-(GAMMA1 - 1), GAMMA1 - 1] by performing rejection sampling
* using array of random bytes.
*
* Arguments: - uint32_t *a: pointer to output array (allocated)
* - unsigned int len: number of coefficients to be sampled
* - const unsigned char *buf: array of random bytes
* - unsigned int buflen: length of array of random bytes
*
* Returns number of sampled coefficients. Can be smaller than len if not enough
* random bytes were given.
**************************************************/
static unsigned int rej_gamma1m1(uint32_t *a,
unsigned int len,
const unsigned char *buf,
unsigned int buflen) {
unsigned int ctr, pos;
uint32_t t0, t1;

ctr = pos = 0;
while (ctr < len && pos + 5 <= buflen) {
t0 = buf[pos];
t0 |= (uint32_t)buf[pos + 1] << 8;
t0 |= (uint32_t)buf[pos + 2] << 16;
t0 &= 0xFFFFF;

t1 = buf[pos + 2] >> 4;
t1 |= (uint32_t)buf[pos + 3] << 4;
t1 |= (uint32_t)buf[pos + 4] << 12;

pos += 5;

if (t0 <= 2 * GAMMA1 - 2) {
a[ctr++] = Q + GAMMA1 - 1 - t0;
}
if (t1 <= 2 * GAMMA1 - 2 && ctr < len) {
a[ctr++] = Q + GAMMA1 - 1 - t1;
}
}

return ctr;
}

/*************************************************
* Name: PQCLEAN_DILITHIUM3_CLEAN_poly_uniform_gamma1m1
*
* Description: Sample polynomial with uniformly random coefficients
* in [-(GAMMA1 - 1), GAMMA1 - 1] by performing rejection
* sampling on output stream of SHAKE256(seed|nonce).
*
* Arguments: - poly *a: pointer to output polynomial
* - const unsigned char seed[]: byte array with seed of length
* CRHBYTES
* - uint16_t nonce: 16-bit nonce
**************************************************/
#define POLY_UNIFORM_GAMMA1M1_NBLOCKS ((641 + STREAM256_BLOCKBYTES) / STREAM256_BLOCKBYTES)
#define POLY_UNIFORM_GAMMA1M1_BUFLEN (POLY_UNIFORM_GAMMA1M1_NBLOCKS * STREAM256_BLOCKBYTES)
void PQCLEAN_DILITHIUM3_CLEAN_poly_uniform_gamma1m1(poly *a,
const unsigned char seed[CRHBYTES],
uint16_t nonce) {
unsigned int i, ctr, off;
unsigned int buflen = POLY_UNIFORM_GAMMA1M1_BUFLEN;
unsigned char buf[POLY_UNIFORM_GAMMA1M1_BUFLEN + 4];
shake256ctx state;

stream256_init(&state, seed, nonce);
stream256_squeezeblocks(buf, POLY_UNIFORM_GAMMA1M1_NBLOCKS, &state);

ctr = rej_gamma1m1(a->coeffs, N, buf, buflen);

while (ctr < N) {
off = buflen % 5;
for (i = 0; i < off; ++i) {
buf[i] = buf[buflen - off + i];
}

buflen = STREAM256_BLOCKBYTES + off;
stream256_squeezeblocks(buf + off, 1, &state);
ctr += rej_gamma1m1(a->coeffs + ctr, N - ctr, buf, buflen);
}
}

/*************************************************
* Name: PQCLEAN_DILITHIUM3_CLEAN_polyeta_pack
*
* Description: Bit-pack polynomial with coefficients in [-ETA,ETA].
* Input coefficients are assumed to lie in [Q-ETA,Q+ETA].
*
* Arguments: - unsigned char *r: pointer to output byte array with at least
* POLETA_SIZE_PACKED bytes
* - const poly *a: pointer to input polynomial
**************************************************/
void PQCLEAN_DILITHIUM3_CLEAN_polyeta_pack(unsigned char *r, const poly *a) {
unsigned int i;
unsigned char t[8];

for (i = 0; i < N / 2; ++i) {
t[0] = (uint8_t) (Q + ETA - a->coeffs[2 * i + 0]);
t[1] = (uint8_t) (Q + ETA - a->coeffs[2 * i + 1]);
r[i] = (uint8_t) (t[0] | (t[1] << 4));
}
}

/*************************************************
* Name: PQCLEAN_DILITHIUM3_CLEAN_polyeta_unpack
*
* Description: Unpack polynomial with coefficients in [-ETA,ETA].
* Output coefficients lie in [Q-ETA,Q+ETA].
*
* Arguments: - poly *r: pointer to output polynomial
* - const unsigned char *a: byte array with bit-packed polynomial
**************************************************/
void PQCLEAN_DILITHIUM3_CLEAN_polyeta_unpack(poly *r, const unsigned char *a) {
unsigned int i;
for (i = 0; i < N / 2; ++i) {
r->coeffs[2 * i + 0] = a[i] & 0x0F;
r->coeffs[2 * i + 1] = a[i] >> 4;
r->coeffs[2 * i + 0] = Q + ETA - r->coeffs[2 * i + 0];
r->coeffs[2 * i + 1] = Q + ETA - r->coeffs[2 * i + 1];
}
}

/*************************************************
* Name: polyt1_pack
*
* Description: Bit-pack polynomial t1 with coefficients fitting in 9 bits.
* Input coefficients are assumed to be standard representatives.
*
* Arguments: - unsigned char *r: pointer to output byte array with at least
* POLT1_SIZE_PACKED bytes
* - const poly *a: pointer to input polynomial
**************************************************/
void PQCLEAN_DILITHIUM3_CLEAN_polyt1_pack(unsigned char *r, const poly *a) {
unsigned int i;

for (i = 0; i < N / 8; ++i) {
r[9 * i + 0] = (uint8_t) ((a->coeffs[8 * i + 0] >> 0));
r[9 * i + 1] = (uint8_t) ((a->coeffs[8 * i + 0] >> 8) | (a->coeffs[8 * i + 1] << 1));
r[9 * i + 2] = (uint8_t) ((a->coeffs[8 * i + 1] >> 7) | (a->coeffs[8 * i + 2] << 2));
r[9 * i + 3] = (uint8_t) ((a->coeffs[8 * i + 2] >> 6) | (a->coeffs[8 * i + 3] << 3));
r[9 * i + 4] = (uint8_t) ((a->coeffs[8 * i + 3] >> 5) | (a->coeffs[8 * i + 4] << 4));
r[9 * i + 5] = (uint8_t) ((a->coeffs[8 * i + 4] >> 4) | (a->coeffs[8 * i + 5] << 5));
r[9 * i + 6] = (uint8_t) ((a->coeffs[8 * i + 5] >> 3) | (a->coeffs[8 * i + 6] << 6));
r[9 * i + 7] = (uint8_t) ((a->coeffs[8 * i + 6] >> 2) | (a->coeffs[8 * i + 7] << 7));
r[9 * i + 8] = (uint8_t) ((a->coeffs[8 * i + 7] >> 1));
}

}

/*************************************************
* Name: polyt1_unpack
*
* Description: Unpack polynomial t1 with 9-bit coefficients.
* Output coefficients are standard representatives.
*
* Arguments: - poly *r: pointer to output polynomial
* - const unsigned char *a: byte array with bit-packed polynomial
**************************************************/
void PQCLEAN_DILITHIUM3_CLEAN_polyt1_unpack(poly *r, const unsigned char *a) {
unsigned int i;

for (i = 0; i < N / 8; ++i) {
r->coeffs[8 * i + 0] = ((a[9 * i + 0] ) | ((uint32_t)a[9 * i + 1] << 8)) & 0x1FF;
r->coeffs[8 * i + 1] = ((a[9 * i + 1] >> 1) | ((uint32_t)a[9 * i + 2] << 7)) & 0x1FF;
r->coeffs[8 * i + 2] = ((a[9 * i + 2] >> 2) | ((uint32_t)a[9 * i + 3] << 6)) & 0x1FF;
r->coeffs[8 * i + 3] = ((a[9 * i + 3] >> 3) | ((uint32_t)a[9 * i + 4] << 5)) & 0x1FF;
r->coeffs[8 * i + 4] = ((a[9 * i + 4] >> 4) | ((uint32_t)a[9 * i + 5] << 4)) & 0x1FF;
r->coeffs[8 * i + 5] = ((a[9 * i + 5] >> 5) | ((uint32_t)a[9 * i + 6] << 3)) & 0x1FF;
r->coeffs[8 * i + 6] = ((a[9 * i + 6] >> 6) | ((uint32_t)a[9 * i + 7] << 2)) & 0x1FF;
r->coeffs[8 * i + 7] = ((a[9 * i + 7] >> 7) | ((uint32_t)a[9 * i + 8] << 1)) & 0x1FF;
}

}

/*************************************************
* Name: PQCLEAN_DILITHIUM3_CLEAN_polyt0_pack
*
* Description: Bit-pack polynomial t0 with coefficients in ]-2^{D-1}, 2^{D-1}].
* Input coefficients are assumed to lie in ]Q-2^{D-1}, Q+2^{D-1}].
*
* Arguments: - unsigned char *r: pointer to output byte array with at least
* POLT0_SIZE_PACKED bytes
* - const poly *a: pointer to input polynomial
**************************************************/
void PQCLEAN_DILITHIUM3_CLEAN_polyt0_pack(unsigned char *r, const poly *a) {
unsigned int i;
uint32_t t[4];

for (i = 0; i < N / 4; ++i) {
t[0] = Q + (1U << (D - 1)) - a->coeffs[4 * i + 0];
t[1] = Q + (1U << (D - 1)) - a->coeffs[4 * i + 1];
t[2] = Q + (1U << (D - 1)) - a->coeffs[4 * i + 2];
t[3] = Q + (1U << (D - 1)) - a->coeffs[4 * i + 3];

r[7 * i + 0] = (uint8_t) (t[0]);
r[7 * i + 1] = (uint8_t) (t[0] >> 8);
r[7 * i + 1] |= (uint8_t) (t[1] << 6);
r[7 * i + 2] = (uint8_t) (t[1] >> 2);
r[7 * i + 3] = (uint8_t) (t[1] >> 10);
r[7 * i + 3] |= (uint8_t) (t[2] << 4);
r[7 * i + 4] = (uint8_t) (t[2] >> 4);
r[7 * i + 5] = (uint8_t) (t[2] >> 12);
r[7 * i + 5] |= (uint8_t) (t[3] << 2);
r[7 * i + 6] = (uint8_t) (t[3] >> 6);
}

}

/*************************************************
* Name: PQCLEAN_DILITHIUM3_CLEAN_polyt0_unpack
*
* Description: Unpack polynomial t0 with coefficients in ]-2^{D-1}, 2^{D-1}].
* Output coefficients lie in ]Q-2^{D-1},Q+2^{D-1}].
*
* Arguments: - poly *r: pointer to output polynomial
* - const unsigned char *a: byte array with bit-packed polynomial
**************************************************/
void PQCLEAN_DILITHIUM3_CLEAN_polyt0_unpack(poly *r, const unsigned char *a) {
unsigned int i;

for (i = 0; i < N / 4; ++i) {
r->coeffs[4 * i + 0] = a[7 * i + 0];
r->coeffs[4 * i + 0] |= (uint32_t)(a[7 * i + 1] & 0x3F) << 8;

r->coeffs[4 * i + 1] = a[7 * i + 1] >> 6;
r->coeffs[4 * i + 1] |= (uint32_t)a[7 * i + 2] << 2;
r->coeffs[4 * i + 1] |= (uint32_t)(a[7 * i + 3] & 0x0F) << 10;

r->coeffs[4 * i + 2] = a[7 * i + 3] >> 4;
r->coeffs[4 * i + 2] |= (uint32_t)a[7 * i + 4] << 4;
r->coeffs[4 * i + 2] |= (uint32_t)(a[7 * i + 5] & 0x03) << 12;

r->coeffs[4 * i + 3] = a[7 * i + 5] >> 2;
r->coeffs[4 * i + 3] |= (uint32_t)a[7 * i + 6] << 6;

r->coeffs[4 * i + 0] = Q + (1U << (D - 1)) - r->coeffs[4 * i + 0];
r->coeffs[4 * i + 1] = Q + (1U << (D - 1)) - r->coeffs[4 * i + 1];
r->coeffs[4 * i + 2] = Q + (1U << (D - 1)) - r->coeffs[4 * i + 2];
r->coeffs[4 * i + 3] = Q + (1U << (D - 1)) - r->coeffs[4 * i + 3];
}

}

/*************************************************
* Name: PQCLEAN_DILITHIUM3_CLEAN_polyz_pack
*
* Description: Bit-pack polynomial z with coefficients
* in [-(GAMMA1 - 1), GAMMA1 - 1].
* Input coefficients are assumed to be standard representatives.
*
* Arguments: - unsigned char *r: pointer to output byte array with at least
* POLZ_SIZE_PACKED bytes
* - const poly *a: pointer to input polynomial
**************************************************/
void PQCLEAN_DILITHIUM3_CLEAN_polyz_pack(unsigned char *r, const poly *a) {
unsigned int i;
uint32_t t[2];

for (i = 0; i < N / 2; ++i) {
/* Map to {0,...,2*GAMMA1 - 2} */
t[0] = GAMMA1 - 1 - a->coeffs[2 * i + 0];
t[0] += ((int32_t)t[0] >> 31) & Q;
t[1] = GAMMA1 - 1 - a->coeffs[2 * i + 1];
t[1] += ((int32_t)t[1] >> 31) & Q;

r[5 * i + 0] = (uint8_t) (t[0]);
r[5 * i + 1] = (uint8_t) (t[0] >> 8);
r[5 * i + 2] = (uint8_t) (t[0] >> 16);
r[5 * i + 2] |= (uint8_t) (t[1] << 4);
r[5 * i + 3] = (uint8_t) (t[1] >> 4);
r[5 * i + 4] = (uint8_t) (t[1] >> 12);
}

}

/*************************************************
* Name: PQCLEAN_DILITHIUM3_CLEAN_polyz_unpack
*
* Description: Unpack polynomial z with coefficients
* in [-(GAMMA1 - 1), GAMMA1 - 1].
* Output coefficients are standard representatives.
*
* Arguments: - poly *r: pointer to output polynomial
* - const unsigned char *a: byte array with bit-packed polynomial
**************************************************/
void PQCLEAN_DILITHIUM3_CLEAN_polyz_unpack(poly *r, const unsigned char *a) {
unsigned int i;

for (i = 0; i < N / 2; ++i) {
r->coeffs[2 * i + 0] = a[5 * i + 0];
r->coeffs[2 * i + 0] |= (uint32_t)a[5 * i + 1] << 8;
r->coeffs[2 * i + 0] |= (uint32_t)(a[5 * i + 2] & 0x0F) << 16;

r->coeffs[2 * i + 1] = a[5 * i + 2] >> 4;
r->coeffs[2 * i + 1] |= (uint32_t)a[5 * i + 3] << 4;
r->coeffs[2 * i + 1] |= (uint32_t)a[5 * i + 4] << 12;

r->coeffs[2 * i + 0] = GAMMA1 - 1 - r->coeffs[2 * i + 0];
r->coeffs[2 * i + 0] += ((int32_t)r->coeffs[2 * i + 0] >> 31) & Q;
r->coeffs[2 * i + 1] = GAMMA1 - 1 - r->coeffs[2 * i + 1];
r->coeffs[2 * i + 1] += ((int32_t)r->coeffs[2 * i + 1] >> 31) & Q;
}

}

/*************************************************
* Name: PQCLEAN_DILITHIUM3_CLEAN_polyw1_pack
*
* Description: Bit-pack polynomial w1 with coefficients in [0, 15].
* Input coefficients are assumed to be standard representatives.
*
* Arguments: - unsigned char *r: pointer to output byte array with at least
* POLW1_SIZE_PACKED bytes
* - const poly *a: pointer to input polynomial
**************************************************/
void PQCLEAN_DILITHIUM3_CLEAN_polyw1_pack(unsigned char *r, const poly *a) {
unsigned int i;

for (i = 0; i < N / 2; ++i) {
r[i] = (uint8_t) (a->coeffs[2 * i + 0] | (a->coeffs[2 * i + 1] << 4));
}

}

+ 53
- 0
crypto_sign/dilithium3/clean/poly.h View File

@@ -0,0 +1,53 @@
#ifndef POLY_H
#define POLY_H

#include "params.h"
#include <stdint.h>

typedef struct {
uint32_t coeffs[N];
} poly;

void PQCLEAN_DILITHIUM3_CLEAN_poly_reduce(poly *a);
void PQCLEAN_DILITHIUM3_CLEAN_poly_csubq(poly *a);
void PQCLEAN_DILITHIUM3_CLEAN_poly_freeze(poly *a);

void PQCLEAN_DILITHIUM3_CLEAN_poly_add(poly *c, const poly *a, const poly *b);
void PQCLEAN_DILITHIUM3_CLEAN_poly_sub(poly *c, const poly *a, const poly *b);
void PQCLEAN_DILITHIUM3_CLEAN_poly_shiftl(poly *a);

void PQCLEAN_DILITHIUM3_CLEAN_poly_ntt(poly *a);
void PQCLEAN_DILITHIUM3_CLEAN_poly_invntt_montgomery(poly *a);
void PQCLEAN_DILITHIUM3_CLEAN_poly_pointwise_invmontgomery(poly *c, const poly *a, const poly *b);

void PQCLEAN_DILITHIUM3_CLEAN_poly_power2round(poly *a1, poly *a0, const poly *a);
void PQCLEAN_DILITHIUM3_CLEAN_poly_decompose(poly *a1, poly *a0, const poly *a);
unsigned int PQCLEAN_DILITHIUM3_CLEAN_poly_make_hint(poly *h, const poly *a0, const poly *a1);
void PQCLEAN_DILITHIUM3_CLEAN_poly_use_hint(poly *a, const poly *b, const poly *h);

int PQCLEAN_DILITHIUM3_CLEAN_poly_chknorm(const poly *a, uint32_t B);
void PQCLEAN_DILITHIUM3_CLEAN_poly_uniform(poly *a,
const unsigned char seed[SEEDBYTES],
uint16_t nonce);
void PQCLEAN_DILITHIUM3_CLEAN_poly_uniform_eta(poly *a,
const unsigned char seed[SEEDBYTES],
uint16_t nonce);
void PQCLEAN_DILITHIUM3_CLEAN_poly_uniform_gamma1m1(poly *a,
const unsigned char seed[CRHBYTES],
uint16_t nonce);

void PQCLEAN_DILITHIUM3_CLEAN_polyeta_pack(unsigned char *r, const poly *a);
void PQCLEAN_DILITHIUM3_CLEAN_polyeta_unpack(poly *r, const unsigned char *a);

void PQCLEAN_DILITHIUM3_CLEAN_polyt1_pack(unsigned char *r, const poly *a);
void PQCLEAN_DILITHIUM3_CLEAN_polyt1_unpack(poly *r, const unsigned char *a);

void PQCLEAN_DILITHIUM3_CLEAN_polyt0_pack(unsigned char *r, const poly *a);
void PQCLEAN_DILITHIUM3_CLEAN_polyt0_unpack(poly *r, const unsigned char *a);

void PQCLEAN_DILITHIUM3_CLEAN_polyz_pack(unsigned char *r, const poly *a);
void PQCLEAN_DILITHIUM3_CLEAN_polyz_unpack(poly *r, const unsigned char *a);

void PQCLEAN_DILITHIUM3_CLEAN_polyw1_pack(unsigned char *r, const poly *a);

#endif

+ 357
- 0
crypto_sign/dilithium3/clean/polyvec.c View File

@@ -0,0 +1,357 @@
#include "params.h"
#include "poly.h"
#include "polyvec.h"
#include <stdint.h>

/**************************************************************/
/************ Vectors of polynomials of length L **************/
/**************************************************************/

/*************************************************
* Name: polyvecl_freeze
*
* Description: Reduce coefficients of polynomials in vector of length L
* to standard representatives.
*
* Arguments: - polyvecl *v: pointer to input/output vector
**************************************************/
void PQCLEAN_DILITHIUM3_CLEAN_polyvecl_freeze(polyvecl *v) {
unsigned int i;

for (i = 0; i < L; ++i) {
PQCLEAN_DILITHIUM3_CLEAN_poly_freeze(&v->vec[i]);
}
}

/*************************************************
* Name: polyvecl_add
*
* Description: Add vectors of polynomials of length L.
* No modular reduction is performed.
*
* Arguments: - polyvecl *w: pointer to output vector
* - const polyvecl *u: pointer to first summand
* - const polyvecl *v: pointer to second summand
**************************************************/
void PQCLEAN_DILITHIUM3_CLEAN_polyvecl_add(polyvecl *w, const polyvecl *u, const polyvecl *v) {
unsigned int i;

for (i = 0; i < L; ++i) {
PQCLEAN_DILITHIUM3_CLEAN_poly_add(&w->vec[i], &u->vec[i], &v->vec[i]);
}
}

/*************************************************
* Name: polyvecl_ntt
*
* Description: Forward NTT of all polynomials in vector of length L. Output
* coefficients can be up to 16*Q larger than input coefficients.
*
* Arguments: - polyvecl *v: pointer to input/output vector
**************************************************/
void PQCLEAN_DILITHIUM3_CLEAN_polyvecl_ntt(polyvecl *v) {
unsigned int i;

for (i = 0; i < L; ++i) {
PQCLEAN_DILITHIUM3_CLEAN_poly_ntt(&v->vec[i]);
}
}

/*************************************************
* Name: polyvecl_pointwise_acc_invmontgomery
*
* Description: Pointwise multiply vectors of polynomials of length L, multiply
* resulting vector by 2^{-32} and add (accumulate) polynomials
* in it. Input/output vectors are in NTT domain representation.
* Input coefficients are assumed to be less than 22*Q. Output
* coeffcient are less than 2*L*Q.
*
* Arguments: - poly *w: output polynomial
* - const polyvecl *u: pointer to first input vector
* - const polyvecl *v: pointer to second input vector
**************************************************/
void PQCLEAN_DILITHIUM3_CLEAN_polyvecl_pointwise_acc_invmontgomery(poly *w,
const polyvecl *u,
const polyvecl *v) {
unsigned int i;
poly t;

PQCLEAN_DILITHIUM3_CLEAN_poly_pointwise_invmontgomery(w, &u->vec[0], &v->vec[0]);

for (i = 1; i < L; ++i) {
PQCLEAN_DILITHIUM3_CLEAN_poly_pointwise_invmontgomery(&t, &u->vec[i], &v->vec[i]);
PQCLEAN_DILITHIUM3_CLEAN_poly_add(w, w, &t);
}
}

/*************************************************
* Name: polyvecl_chknorm
*
* Description: Check infinity norm of polynomials in vector of length L.
* Assumes input coefficients to be standard representatives.
*
* Arguments: - const polyvecl *v: pointer to vector
* - uint32_t B: norm bound
*
* Returns 0 if norm of all polynomials is strictly smaller than B and 1
* otherwise.
**************************************************/
int PQCLEAN_DILITHIUM3_CLEAN_polyvecl_chknorm(const polyvecl *v, uint32_t bound) {
unsigned int i;

for (i = 0; i < L; ++i) {
if (PQCLEAN_DILITHIUM3_CLEAN_poly_chknorm(&v->vec[i], bound)) {
return 1;
}
}
return 0;
}

/**************************************************************/
/************ Vectors of polynomials of length K **************/
/**************************************************************/


/*************************************************
* Name: polyveck_reduce
*
* Description: Reduce coefficients of polynomials in vector of length K
* to representatives in [0,2*Q[.
*
* Arguments: - polyveck *v: pointer to input/output vector
**************************************************/
void PQCLEAN_DILITHIUM3_CLEAN_polyveck_reduce(polyveck *v) {
unsigned int i;

for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM3_CLEAN_poly_reduce(&v->vec[i]);
}
}

/*************************************************
* Name: polyveck_csubq
*
* Description: For all coefficients of polynomials in vector of length K
* subtract Q if coefficient is bigger than Q.
*
* Arguments: - polyveck *v: pointer to input/output vector
**************************************************/
void PQCLEAN_DILITHIUM3_CLEAN_polyveck_csubq(polyveck *v) {
unsigned int i;

for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM3_CLEAN_poly_csubq(&v->vec[i]);
}
}

/*************************************************
* Name: polyveck_freeze
*
* Description: Reduce coefficients of polynomials in vector of length K
* to standard representatives.
*
* Arguments: - polyveck *v: pointer to input/output vector
**************************************************/
void PQCLEAN_DILITHIUM3_CLEAN_polyveck_freeze(polyveck *v) {
unsigned int i;

for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM3_CLEAN_poly_freeze(&v->vec[i]);
}
}

/*************************************************
* Name: polyveck_add
*
* Description: Add vectors of polynomials of length K.
* No modular reduction is performed.
*
* Arguments: - polyveck *w: pointer to output vector
* - const polyveck *u: pointer to first summand
* - const polyveck *v: pointer to second summand
**************************************************/
void PQCLEAN_DILITHIUM3_CLEAN_polyveck_add(polyveck *w, const polyveck *u, const polyveck *v) {
unsigned int i;

for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM3_CLEAN_poly_add(&w->vec[i], &u->vec[i], &v->vec[i]);
}
}

/*************************************************
* Name: polyveck_sub
*
* Description: Subtract vectors of polynomials of length K.
* Assumes coefficients of polynomials in second input vector
* to be less than 2*Q. No modular reduction is performed.
*
* Arguments: - polyveck *w: pointer to output vector
* - const polyveck *u: pointer to first input vector
* - const polyveck *v: pointer to second input vector to be
* subtracted from first input vector
**************************************************/
void PQCLEAN_DILITHIUM3_CLEAN_polyveck_sub(polyveck *w, const polyveck *u, const polyveck *v) {
unsigned int i;

for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM3_CLEAN_poly_sub(&w->vec[i], &u->vec[i], &v->vec[i]);
}
}

/*************************************************
* Name: polyveck_shiftl
*
* Description: Multiply vector of polynomials of Length K by 2^D without modular
* reduction. Assumes input coefficients to be less than 2^{32-D}.
*
* Arguments: - polyveck *v: pointer to input/output vector
**************************************************/
void PQCLEAN_DILITHIUM3_CLEAN_polyveck_shiftl(polyveck *v) {
unsigned int i;

for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM3_CLEAN_poly_shiftl(&v->vec[i]);
}
}

/*************************************************
* Name: polyveck_ntt
*
* Description: Forward NTT of all polynomials in vector of length K. Output
* coefficients can be up to 16*Q larger than input coefficients.
*
* Arguments: - polyveck *v: pointer to input/output vector
**************************************************/
void PQCLEAN_DILITHIUM3_CLEAN_polyveck_ntt(polyveck *v) {
unsigned int i;

for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM3_CLEAN_poly_ntt(&v->vec[i]);
}
}

/*************************************************
* Name: polyveck_invntt_montgomery
*
* Description: Inverse NTT and multiplication by 2^{32} of polynomials
* in vector of length K. Input coefficients need to be less
* than 2*Q.
*
* Arguments: - polyveck *v: pointer to input/output vector
**************************************************/
void PQCLEAN_DILITHIUM3_CLEAN_polyveck_invntt_montgomery(polyveck *v) {
unsigned int i;

for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM3_CLEAN_poly_invntt_montgomery(&v->vec[i]);
}
}

/*************************************************
* Name: polyveck_chknorm
*
* Description: Check infinity norm of polynomials in vector of length K.
* Assumes input coefficients to be standard representatives.
*
* Arguments: - const polyveck *v: pointer to vector
* - uint32_t B: norm bound
*
* Returns 0 if norm of all polynomials are strictly smaller than B and 1
* otherwise.
**************************************************/
int PQCLEAN_DILITHIUM3_CLEAN_polyveck_chknorm(const polyveck *v, uint32_t bound) {
unsigned int i;

for (i = 0; i < K; ++i) {
if (PQCLEAN_DILITHIUM3_CLEAN_poly_chknorm(&v->vec[i], bound)) {
return 1;
}
}
return 0;
}

/*************************************************
* Name: polyveck_power2round
*
* Description: For all coefficients a of polynomials in vector of length K,
* compute a0, a1 such that a mod Q = a1*2^D + a0
* with -2^{D-1} < a0 <= 2^{D-1}. Assumes coefficients to be
* standard representatives.
*
* Arguments: - polyveck *v1: pointer to output vector of polynomials with
* coefficients a1
* - polyveck *v0: pointer to output vector of polynomials with
* coefficients Q + a0
* - const polyveck *v: pointer to input vector
**************************************************/
void PQCLEAN_DILITHIUM3_CLEAN_polyveck_power2round(polyveck *v1, polyveck *v0, const polyveck *v) {
unsigned int i;

for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM3_CLEAN_poly_power2round(&v1->vec[i], &v0->vec[i], &v->vec[i]);
}
}

/*************************************************
* Name: polyveck_decompose
*
* Description: For all coefficients a of polynomials in vector of length K,
* compute high and low bits a0, a1 such a mod Q = a1*ALPHA + a0
* with -ALPHA/2 < a0 <= ALPHA/2 except a1 = (Q-1)/ALPHA where we
* set a1 = 0 and -ALPHA/2 <= a0 = a mod Q - Q < 0.
* Assumes coefficients to be standard representatives.
*
* Arguments: - polyveck *v1: pointer to output vector of polynomials with
* coefficients a1
* - polyveck *v0: pointer to output vector of polynomials with
* coefficients Q + a0
* - const polyveck *v: pointer to input vector
**************************************************/
void PQCLEAN_DILITHIUM3_CLEAN_polyveck_decompose(polyveck *v1, polyveck *v0, const polyveck *v) {
unsigned int i;

for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM3_CLEAN_poly_decompose(&v1->vec[i], &v0->vec[i], &v->vec[i]);
}
}

/*************************************************
* Name: polyveck_make_hint
*
* Description: Compute hint vector.
*
* Arguments: - polyveck *h: pointer to output vector
* - const polyveck *v0: pointer to low part of input vector
* - const polyveck *v1: pointer to high part of input vector
*
* Returns number of 1 bits.
**************************************************/
unsigned int PQCLEAN_DILITHIUM3_CLEAN_polyveck_make_hint(polyveck *h,
const polyveck *v0,
const polyveck *v1) {
unsigned int i, s = 0;

for (i = 0; i < K; ++i) {
s += PQCLEAN_DILITHIUM3_CLEAN_poly_make_hint(&h->vec[i], &v0->vec[i], &v1->vec[i]);
}

return s;
}

/*************************************************
* Name: polyveck_use_hint
*
* Description: Use hint vector to correct the high bits of input vector.
*
* Arguments: - polyveck *w: pointer to output vector of polynomials with
* corrected high bits
* - const polyveck *u: pointer to input vector
* - const polyveck *h: pointer to input hint vector
**************************************************/
void PQCLEAN_DILITHIUM3_CLEAN_polyveck_use_hint(polyveck *w, const polyveck *u, const polyveck *h) {
unsigned int i;

for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM3_CLEAN_poly_use_hint(&w->vec[i], &u->vec[i], &h->vec[i]);
}
}

+ 51
- 0
crypto_sign/dilithium3/clean/polyvec.h View File

@@ -0,0 +1,51 @@
#ifndef POLYVEC_H
#define POLYVEC_H

#include "params.h"
#include "poly.h"
#include <stdint.h>

/* Vectors of polynomials of length L */
typedef struct {
poly vec[L];
} polyvecl;

void PQCLEAN_DILITHIUM3_CLEAN_polyvecl_freeze(polyvecl *v);

void PQCLEAN_DILITHIUM3_CLEAN_polyvecl_add(polyvecl *w, const polyvecl *u, const polyvecl *v);

void PQCLEAN_DILITHIUM3_CLEAN_polyvecl_ntt(polyvecl *v);
void PQCLEAN_DILITHIUM3_CLEAN_polyvecl_pointwise_acc_invmontgomery(poly *w,
const polyvecl *u,
const polyvecl *v);

int PQCLEAN_DILITHIUM3_CLEAN_polyvecl_chknorm(const polyvecl *v, uint32_t B);



/* Vectors of polynomials of length K */
typedef struct {
poly vec[K];
} polyveck;

void PQCLEAN_DILITHIUM3_CLEAN_polyveck_reduce(polyveck *v);
void PQCLEAN_DILITHIUM3_CLEAN_polyveck_csubq(polyveck *v);
void PQCLEAN_DILITHIUM3_CLEAN_polyveck_freeze(polyveck *v);

void PQCLEAN_DILITHIUM3_CLEAN_polyveck_add(polyveck *w, const polyveck *u, const polyveck *v);
void PQCLEAN_DILITHIUM3_CLEAN_polyveck_sub(polyveck *w, const polyveck *u, const polyveck *v);
void PQCLEAN_DILITHIUM3_CLEAN_polyveck_shiftl(polyveck *v);

void PQCLEAN_DILITHIUM3_CLEAN_polyveck_ntt(polyveck *v);
void PQCLEAN_DILITHIUM3_CLEAN_polyveck_invntt_montgomery(polyveck *v);

int PQCLEAN_DILITHIUM3_CLEAN_polyveck_chknorm(const polyveck *v, uint32_t B);

void PQCLEAN_DILITHIUM3_CLEAN_polyveck_power2round(polyveck *v1, polyveck *v0, const polyveck *v);
void PQCLEAN_DILITHIUM3_CLEAN_polyveck_decompose(polyveck *v1, polyveck *v0, const polyveck *v);
unsigned int PQCLEAN_DILITHIUM3_CLEAN_polyveck_make_hint(polyveck *h,
const polyveck *v0,
const polyveck *v1);
void PQCLEAN_DILITHIUM3_CLEAN_polyveck_use_hint(polyveck *w, const polyveck *u, const polyveck *h);

#endif

+ 74
- 0
crypto_sign/dilithium3/clean/reduce.c View File

@@ -0,0 +1,74 @@
#include "params.h"
#include "reduce.h"
#include <stdint.h>

/*************************************************
* Name: montgomery_reduce
*
* Description: For finite field element a with 0 <= a <= Q*2^32,
* compute r \equiv a*2^{-32} (mod Q) such that 0 <= r < 2*Q.
*
* Arguments: - uint64_t: finite field element a
*
* Returns r.
**************************************************/
uint32_t PQCLEAN_DILITHIUM3_CLEAN_montgomery_reduce(uint64_t a) {
uint64_t t;

t = a * QINV;
t &= (1ULL << 32) - 1;
t *= Q;
t = a + t;
t >>= 32;
return (uint32_t) t;
}

/*************************************************
* Name: reduce32
*
* Description: For finite field element a, compute r \equiv a (mod Q)
* such that 0 <= r < 2*Q.
*
* Arguments: - uint32_t: finite field element a
*
* Returns r.
**************************************************/
uint32_t PQCLEAN_DILITHIUM3_CLEAN_reduce32(uint32_t a) {
uint32_t t;

t = a & 0x7FFFFF;
a >>= 23;
t += (a << 13) - a;
return t;
}

/*************************************************
* Name: csubq
*
* Description: Subtract Q if input coefficient is bigger than Q.
*
* Arguments: - uint32_t: finite field element a
*
* Returns r.
**************************************************/
uint32_t PQCLEAN_DILITHIUM3_CLEAN_csubq(uint32_t a) {
a -= Q;
a += ((int32_t)a >> 31) & Q;
return a;
}

/*************************************************
* Name: freeze
*
* Description: For finite field element a, compute standard
* representative r = a mod Q.
*
* Arguments: - uint32_t: finite field element a
*
* Returns r.
**************************************************/
uint32_t PQCLEAN_DILITHIUM3_CLEAN_freeze(uint32_t a) {
a = PQCLEAN_DILITHIUM3_CLEAN_reduce32(a);
a = PQCLEAN_DILITHIUM3_CLEAN_csubq(a);
return a;
}

+ 21
- 0
crypto_sign/dilithium3/clean/reduce.h View File

@@ -0,0 +1,21 @@
#ifndef REDUCE_H
#define REDUCE_H

#include <stdint.h>

#define MONT 4193792U // 2^32 % Q
#define QINV 4236238847U // -q^(-1) mod 2^32

/* a <= Q*2^32 => r < 2*Q */
uint32_t PQCLEAN_DILITHIUM3_CLEAN_montgomery_reduce(uint64_t a);

/* r < 2*Q */
uint32_t PQCLEAN_DILITHIUM3_CLEAN_reduce32(uint32_t a);

/* a < 2*Q => r < Q */
uint32_t PQCLEAN_DILITHIUM3_CLEAN_csubq(uint32_t a);

/* r < Q */
uint32_t PQCLEAN_DILITHIUM3_CLEAN_freeze(uint32_t a);

#endif

+ 105
- 0
crypto_sign/dilithium3/clean/rounding.c View File

@@ -0,0 +1,105 @@
#include "params.h"
#include "rounding.h"
/*************************************************
* Name: power2round
*
* Description: For finite field element a, compute a0, a1 such that
* a mod Q = a1*2^D + a0 with -2^{D-1} < a0 <= 2^{D-1}.
* Assumes a to be standard representative.
*
* Arguments: - uint32_t a: input element
* - uint32_t *a0: pointer to output element Q + a0
*
* Returns a1.
**************************************************/
uint32_t PQCLEAN_DILITHIUM3_CLEAN_power2round(uint32_t a, uint32_t *a0) {
uint32_t t;

/* Centralized remainder mod 2^D */
t = a & ((1U << D) - 1);
t -= ((1U << (D - 1)) + 1);
t += ((uint32_t)((int32_t)t >> 31) & (1U << D));
t -= ((1U << (D - 1)) - 1);
*a0 = (Q + t);
a = (a - t) >> D;
return a;
}

/*************************************************
* Name: decompose
*
* Description: For finite field element a, compute high and low bits a0, a1 such
* that a mod Q = a1*ALPHA + a0 with -ALPHA/2 < a0 <= ALPHA/2 except
* if a1 = (Q-1)/ALPHA where we set a1 = 0 and
* -ALPHA/2 <= a0 = a mod Q - Q < 0. Assumes a to be standard
* representative.
*
* Arguments: - uint32_t a: input element
* - uint32_t *a0: pointer to output element Q + a0
*
* Returns a1.
**************************************************/
uint32_t PQCLEAN_DILITHIUM3_CLEAN_decompose(uint32_t a, uint32_t *a0) {
int32_t t, u;
/* Centralized remainder mod ALPHA */
t = a & 0x7FFFF;
t += (int32_t) ((a >> 19) << 9);
t -= ALPHA / 2 + 1;
t += (t >> 31) & ALPHA;
t -= ALPHA / 2 - 1;
a -= (uint32_t) t;

/* Divide by ALPHA (possible to avoid) */
u = (int32_t) a - 1;
u >>= 31;
a = (a >> 19) + 1;
a -= u & 1;

/* Border case */
*a0 = Q + (uint32_t)t - (a >> 4);
a &= 0xF;
return a;
}

/*************************************************
* Name: make_hint
*
* Description: Compute hint bit indicating whether the low bits of the
* input element overflow into the high bits. Inputs assumed to be
* standard representatives.
*
* Arguments: - uint32_t a0: low bits of input element
* - uint32_t a1: high bits of input element
*
* Returns 1 if high bits of a and b differ and 0 otherwise.
**************************************************/
unsigned int PQCLEAN_DILITHIUM3_CLEAN_make_hint(uint32_t a0, uint32_t a1) {
if (a0 <= GAMMA2 || a0 > Q - GAMMA2 || (a0 == Q - GAMMA2 && a1 == 0)) {
return 0;
}

return 1;
}

/*************************************************
* Name: use_hint
*
* Description: Correct high bits according to hint.
*
* Arguments: - uint32_t a: input element
* - unsigned int hint: hint bit
*
* Returns corrected high bits.
**************************************************/
uint32_t PQCLEAN_DILITHIUM3_CLEAN_use_hint(uint32_t a, unsigned int hint) {
uint32_t a0, a1;

a1 = PQCLEAN_DILITHIUM3_CLEAN_decompose(a, &a0);
if (hint == 0) {
return a1;
}
if (a0 > Q) {
return (a1 + 1) & 0xF;
}
return (a1 - 1) & 0xF;
}

+ 11
- 0
crypto_sign/dilithium3/clean/rounding.h View File

@@ -0,0 +1,11 @@
#ifndef ROUNDING_H
#define ROUNDING_H

#include <stdint.h>

uint32_t PQCLEAN_DILITHIUM3_CLEAN_power2round(uint32_t a, uint32_t *a0);
uint32_t PQCLEAN_DILITHIUM3_CLEAN_decompose(uint32_t a, uint32_t *a0);
unsigned int PQCLEAN_DILITHIUM3_CLEAN_make_hint(uint32_t a0, uint32_t a1);
uint32_t PQCLEAN_DILITHIUM3_CLEAN_use_hint(uint32_t a, unsigned int hint);

#endif

+ 414
- 0
crypto_sign/dilithium3/clean/sign.c View File

@@ -0,0 +1,414 @@
#include "fips202.h"
#include "packing.h"
#include "params.h"
#include "poly.h"
#include "polyvec.h"
#include "randombytes.h"
#include "sign.h"
#include "symmetric.h"

#include <stdint.h>

/*************************************************
* Name: expand_mat
*
* Description: Implementation of ExpandA. Generates matrix A with uniformly
* random coefficients a_{i,j} by performing rejection
* sampling on the output stream of SHAKE128(rho|i|j).
*
* Arguments: - polyvecl mat[K]: output matrix
* - const unsigned char rho[]: byte array containing seed rho
**************************************************/
void PQCLEAN_DILITHIUM3_CLEAN_expand_mat(polyvecl mat[K], const unsigned char rho[SEEDBYTES]) {
unsigned int i, j;

for (i = 0; i < K; ++i) {
for (j = 0; j < L; ++j) {
PQCLEAN_DILITHIUM3_CLEAN_poly_uniform(&mat[i].vec[j], rho, (uint16_t)((i << 8) + j));
}
}
}

/*************************************************
* Name: challenge
*
* Description: Implementation of H. Samples polynomial with 60 nonzero
* coefficients in {-1,1} using the output stream of
* SHAKE256(mu|w1).
*
* Arguments: - poly *c: pointer to output polynomial
* - const unsigned char mu[]: byte array containing mu
* - const polyveck *w1: pointer to vector w1
**************************************************/
void PQCLEAN_DILITHIUM3_CLEAN_challenge(poly *c,
const unsigned char mu[CRHBYTES],
const polyveck *w1) {
unsigned int i, b, pos;
uint64_t signs;
unsigned char inbuf[CRHBYTES + K * POLW1_SIZE_PACKED];
unsigned char outbuf[SHAKE256_RATE];
shake256ctx state;

for (i = 0; i < CRHBYTES; ++i) {
inbuf[i] = mu[i];
}
for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM3_CLEAN_polyw1_pack(inbuf + CRHBYTES + i * POLW1_SIZE_PACKED, &w1->vec[i]);
}

shake256_absorb(&state, inbuf, sizeof(inbuf));
shake256_squeezeblocks(outbuf, 1, &state);

signs = 0;
for (i = 0; i < 8; ++i) {
signs |= (uint64_t)outbuf[i] << 8 * i;
}

pos = 8;

for (i = 0; i < N; ++i) {
c->coeffs[i] = 0;
}

for (i = 196; i < 256; ++i) {
do {
if (pos >= SHAKE256_RATE) {
shake256_squeezeblocks(outbuf, 1, &state);
pos = 0;
}

b = outbuf[pos++];
} while (b > i);

c->coeffs[i] = c->coeffs[b];
c->coeffs[b] = 1;
c->coeffs[b] ^= -((int32_t)signs & 1) & (1 ^ (Q - 1));
signs >>= 1;
}
}

/*************************************************
* Name: crypto_sign_keypair
*
* Description: Generates public and private key.
*
* Arguments: - unsigned char *pk: pointer to output public key (allocated
* array of CRYPTO_PUBLICKEYBYTES bytes)
* - unsigned char *sk: pointer to output private key (allocated
* array of CRYPTO_SECRETKEYBYTES bytes)
*
* Returns 0 (success)
**************************************************/
int PQCLEAN_DILITHIUM3_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk) {
unsigned int i;
unsigned char seedbuf[3 * SEEDBYTES];
unsigned char tr[CRHBYTES];
const unsigned char *rho, *rhoprime, *key;
uint16_t nonce = 0;
polyvecl mat[K];
polyvecl s1, s1hat;
polyveck s2, t, t1, t0;

/* Expand 32 bytes of randomness into rho, rhoprime and key */
randombytes(seedbuf, 3 * SEEDBYTES);
rho = seedbuf;
rhoprime = seedbuf + SEEDBYTES;
key = seedbuf + 2 * SEEDBYTES;

/* Expand matrix */
PQCLEAN_DILITHIUM3_CLEAN_expand_mat(mat, rho);

/* Sample short vectors s1 and s2 */
for (i = 0; i < L; ++i) {
PQCLEAN_DILITHIUM3_CLEAN_poly_uniform_eta(&s1.vec[i], rhoprime, nonce++);
}
for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM3_CLEAN_poly_uniform_eta(&s2.vec[i], rhoprime, nonce++);
}

/* Matrix-vector multiplication */
s1hat = s1;
PQCLEAN_DILITHIUM3_CLEAN_polyvecl_ntt(&s1hat);
for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM3_CLEAN_polyvecl_pointwise_acc_invmontgomery(&t.vec[i], &mat[i], &s1hat);
PQCLEAN_DILITHIUM3_CLEAN_poly_reduce(&t.vec[i]);
PQCLEAN_DILITHIUM3_CLEAN_poly_invntt_montgomery(&t.vec[i]);
}

/* Add error vector s2 */
PQCLEAN_DILITHIUM3_CLEAN_polyveck_add(&t, &t, &s2);

/* Extract t1 and write public key */
PQCLEAN_DILITHIUM3_CLEAN_polyveck_freeze(&t);
PQCLEAN_DILITHIUM3_CLEAN_polyveck_power2round(&t1, &t0, &t);
PQCLEAN_DILITHIUM3_CLEAN_pack_pk(pk, rho, &t1);

/* Compute CRH(rho, t1) and write secret key */
crh(tr, pk, CRYPTO_PUBLICKEYBYTES);
PQCLEAN_DILITHIUM3_CLEAN_pack_sk(sk, rho, key, tr, &s1, &s2, &t0);

return 0;
}

int PQCLEAN_DILITHIUM3_CLEAN_crypto_sign_signature(
uint8_t *sig, size_t *siglen,
const uint8_t *m, size_t mlen, const uint8_t *sk) {
unsigned long long i;
unsigned int n;
unsigned char seedbuf[2 * SEEDBYTES + 3 * CRHBYTES];
unsigned char *rho, *tr, *key, *mu, *rhoprime;
uint16_t nonce = 0;
poly c, chat;
polyvecl mat[K], s1, y, yhat, z;
polyveck t0, s2, w, w1, w0;
polyveck h, cs2, ct0;

rho = seedbuf;
tr = rho + SEEDBYTES;
key = tr + CRHBYTES;
mu = key + SEEDBYTES;
rhoprime = mu + CRHBYTES;
PQCLEAN_DILITHIUM3_CLEAN_unpack_sk(rho, key, tr, &s1, &s2, &t0, sk);


// use incremental hash API instead of copying around buffers
/* Compute CRH(tr, msg) */
shake256incctx state;
shake256_inc_init(&state);
shake256_inc_absorb(&state, tr, CRHBYTES);
shake256_inc_absorb(&state, m, mlen);
shake256_inc_finalize(&state);
shake256_inc_squeeze(mu, CRHBYTES, &state);


for (i = 0; i < CRHBYTES; ++i) {
sig[CRYPTO_BYTES - CRHBYTES + i] = tr[i];
}

crh(rhoprime, key, SEEDBYTES + CRHBYTES);

/* Expand matrix and transform vectors */
PQCLEAN_DILITHIUM3_CLEAN_expand_mat(mat, rho);
PQCLEAN_DILITHIUM3_CLEAN_polyvecl_ntt(&s1);
PQCLEAN_DILITHIUM3_CLEAN_polyveck_ntt(&s2);
PQCLEAN_DILITHIUM3_CLEAN_polyveck_ntt(&t0);

rej:
/* Sample intermediate vector y */
for (i = 0; i < L; ++i) {
PQCLEAN_DILITHIUM3_CLEAN_poly_uniform_gamma1m1(&y.vec[i], rhoprime, nonce++);
}

/* Matrix-vector multiplication */
yhat = y;
PQCLEAN_DILITHIUM3_CLEAN_polyvecl_ntt(&yhat);
for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM3_CLEAN_polyvecl_pointwise_acc_invmontgomery(&w.vec[i], &mat[i], &yhat);
PQCLEAN_DILITHIUM3_CLEAN_poly_reduce(&w.vec[i]);
PQCLEAN_DILITHIUM3_CLEAN_poly_invntt_montgomery(&w.vec[i]);
}

/* Decompose w and call the random oracle */
PQCLEAN_DILITHIUM3_CLEAN_polyveck_csubq(&w);
PQCLEAN_DILITHIUM3_CLEAN_polyveck_decompose(&w1, &w0, &w);
PQCLEAN_DILITHIUM3_CLEAN_challenge(&c, mu, &w1);
chat = c;
PQCLEAN_DILITHIUM3_CLEAN_poly_ntt(&chat);

/* Check that subtracting cs2 does not change high bits of w and low bits
* do not reveal secret information */
for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM3_CLEAN_poly_pointwise_invmontgomery(&cs2.vec[i], &chat, &s2.vec[i]);
PQCLEAN_DILITHIUM3_CLEAN_poly_invntt_montgomery(&cs2.vec[i]);
}
PQCLEAN_DILITHIUM3_CLEAN_polyveck_sub(&w0, &w0, &cs2);
PQCLEAN_DILITHIUM3_CLEAN_polyveck_freeze(&w0);
if (PQCLEAN_DILITHIUM3_CLEAN_polyveck_chknorm(&w0, GAMMA2 - BETA)) {
goto rej;
}

/* Compute z, reject if it reveals secret */
for (i = 0; i < L; ++i) {
PQCLEAN_DILITHIUM3_CLEAN_poly_pointwise_invmontgomery(&z.vec[i], &chat, &s1.vec[i]);
PQCLEAN_DILITHIUM3_CLEAN_poly_invntt_montgomery(&z.vec[i]);
}
PQCLEAN_DILITHIUM3_CLEAN_polyvecl_add(&z, &z, &y);
PQCLEAN_DILITHIUM3_CLEAN_polyvecl_freeze(&z);
if (PQCLEAN_DILITHIUM3_CLEAN_polyvecl_chknorm(&z, GAMMA1 - BETA)) {
goto rej;
}

/* Compute hints for w1 */
for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM3_CLEAN_poly_pointwise_invmontgomery(&ct0.vec[i], &chat, &t0.vec[i]);
PQCLEAN_DILITHIUM3_CLEAN_poly_invntt_montgomery(&ct0.vec[i]);
}

PQCLEAN_DILITHIUM3_CLEAN_polyveck_csubq(&ct0);
if (PQCLEAN_DILITHIUM3_CLEAN_polyveck_chknorm(&ct0, GAMMA2)) {
goto rej;
}

PQCLEAN_DILITHIUM3_CLEAN_polyveck_add(&w0, &w0, &ct0);
PQCLEAN_DILITHIUM3_CLEAN_polyveck_csubq(&w0);
n = PQCLEAN_DILITHIUM3_CLEAN_polyveck_make_hint(&h, &w0, &w1);
if (n > OMEGA) {
goto rej;
}

/* Write signature */
PQCLEAN_DILITHIUM3_CLEAN_pack_sig(sig, &z, &h, &c);

*siglen = CRYPTO_BYTES;
return 0;
}

int PQCLEAN_DILITHIUM3_CLEAN_crypto_sign_verify(
const uint8_t *sig, size_t siglen,
const uint8_t *m, size_t mlen, const uint8_t *pk) {
unsigned long long i;
unsigned char rho[SEEDBYTES];
unsigned char mu[CRHBYTES];
poly c, chat, cp;
polyvecl mat[K], z;
polyveck t1, w1, h, tmp1, tmp2;

if (siglen < CRYPTO_BYTES) {
return -1;
}

PQCLEAN_DILITHIUM3_CLEAN_unpack_pk(rho, &t1, pk);
if (PQCLEAN_DILITHIUM3_CLEAN_unpack_sig(&z, &h, &c, sig)) {
return -1;
}
if (PQCLEAN_DILITHIUM3_CLEAN_polyvecl_chknorm(&z, GAMMA1 - BETA)) {
return -1;
}

/* Compute CRH(CRH(rho, t1), msg) */
shake256incctx state;
shake256_inc_init(&state);
shake256_inc_absorb(&state, pk, CRYPTO_PUBLICKEYBYTES);
shake256_inc_finalize(&state);
shake256_inc_squeeze(mu, CRHBYTES, &state);

shake256_inc_init(&state);
shake256_inc_absorb(&state, mu, CRHBYTES);
shake256_inc_absorb(&state, m, mlen);
shake256_inc_finalize(&state);
shake256_inc_squeeze(mu, CRHBYTES, &state);


/* Matrix-vector multiplication; compute Az - c2^dt1 */
PQCLEAN_DILITHIUM3_CLEAN_expand_mat(mat, rho);

PQCLEAN_DILITHIUM3_CLEAN_polyvecl_ntt(&z);
for (i = 0; i < K ; ++i) {
PQCLEAN_DILITHIUM3_CLEAN_polyvecl_pointwise_acc_invmontgomery(&tmp1.vec[i], &mat[i], &z);
}

chat = c;
PQCLEAN_DILITHIUM3_CLEAN_poly_ntt(&chat);
PQCLEAN_DILITHIUM3_CLEAN_polyveck_shiftl(&t1);
PQCLEAN_DILITHIUM3_CLEAN_polyveck_ntt(&t1);
for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM3_CLEAN_poly_pointwise_invmontgomery(&tmp2.vec[i], &chat, &t1.vec[i]);
}

PQCLEAN_DILITHIUM3_CLEAN_polyveck_sub(&tmp1, &tmp1, &tmp2);
PQCLEAN_DILITHIUM3_CLEAN_polyveck_reduce(&tmp1);
PQCLEAN_DILITHIUM3_CLEAN_polyveck_invntt_montgomery(&tmp1);

/* Reconstruct w1 */
PQCLEAN_DILITHIUM3_CLEAN_polyveck_csubq(&tmp1);
PQCLEAN_DILITHIUM3_CLEAN_polyveck_use_hint(&w1, &tmp1, &h);

/* Call random oracle and verify challenge */
PQCLEAN_DILITHIUM3_CLEAN_challenge(&cp, mu, &w1);
for (i = 0; i < N; ++i) {
if (c.coeffs[i] != cp.coeffs[i]) {
return -1;
}
}

// All good
return 0;
}
/*************************************************
* Name: crypto_sign
*
* Description: Compute signed message.
*
* Arguments: - unsigned char *sm: pointer to output signed message (allocated
* array with CRYPTO_BYTES + mlen bytes),
* can be equal to m
* - unsigned long long *smlen: pointer to output length of signed
* message
* - const unsigned char *m: pointer to message to be signed
* - unsigned long long mlen: length of message
* - const unsigned char *sk: pointer to bit-packed secret key
*
* Returns 0 (success)
**************************************************/
int PQCLEAN_DILITHIUM3_CLEAN_crypto_sign(uint8_t *sm,
size_t *smlen,
const uint8_t *m,
size_t mlen,
const uint8_t *sk) {
size_t i;
int rc;
for (i = 0; i < mlen; i++) {
sm[CRYPTO_BYTES + i] = m[i];
}
rc = PQCLEAN_DILITHIUM3_CLEAN_crypto_sign_signature(sm, smlen, m, mlen, sk);
*smlen += mlen;
return rc;

}

/*************************************************
* Name: crypto_sign_open
*
* Description: Verify signed message.
*
* Arguments: - unsigned char *m: pointer to output message (allocated
* array with smlen bytes), can be equal to sm
* - unsigned long long *mlen: pointer to output length of message
* - const unsigned char *sm: pointer to signed message
* - unsigned long long smlen: length of signed message
* - const unsigned char *sk: pointer to bit-packed public key
*
* Returns 0 if signed message could be verified correctly and -1 otherwise
**************************************************/
int PQCLEAN_DILITHIUM3_CLEAN_crypto_sign_open(uint8_t *m,
size_t *mlen,
const uint8_t *sm,
size_t smlen,
const uint8_t *pk) {
size_t i;
if (smlen < CRYPTO_BYTES) {
goto badsig;
}
*mlen = smlen - CRYPTO_BYTES;

if (PQCLEAN_DILITHIUM3_CLEAN_crypto_sign_verify(sm, CRYPTO_BYTES,
sm + CRYPTO_BYTES, *mlen, pk)) {
goto badsig;
} else {
/* All good, copy msg, return 0 */
for (i = 0; i < *mlen; ++i) {
m[i] = sm[CRYPTO_BYTES + i];
}
return 0;
}

/* Signature verification failed */
badsig:
*mlen = (size_t) -1;
for (i = 0; i < smlen; ++i) {
m[i] = 0;
}

return -1;
}


+ 30
- 0
crypto_sign/dilithium3/clean/sign.h View File

@@ -0,0 +1,30 @@
#ifndef SIGN_H
#define SIGN_H

#include "params.h"
#include "poly.h"
#include "polyvec.h"

void PQCLEAN_DILITHIUM3_CLEAN_expand_mat(polyvecl mat[K], const unsigned char rho[SEEDBYTES]);
void PQCLEAN_DILITHIUM3_CLEAN_challenge(poly *c, const unsigned char mu[CRHBYTES],
const polyveck *w1);

int PQCLEAN_DILITHIUM3_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk);

int PQCLEAN_DILITHIUM3_CLEAN_crypto_sign_signature(
uint8_t *sig, size_t *siglen,
const uint8_t *m, size_t mlen, const uint8_t *sk);

int PQCLEAN_DILITHIUM3_CLEAN_crypto_sign_verify(
const uint8_t *sig, size_t siglen,
const uint8_t *m, size_t mlen, const uint8_t *pk);

int PQCLEAN_DILITHIUM3_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen,
const uint8_t *msg, size_t len,
const uint8_t *sk);

int PQCLEAN_DILITHIUM3_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen,
const uint8_t *sm, size_t smlen,
const uint8_t *pk);

#endif

+ 32
- 0
crypto_sign/dilithium3/clean/symmetric.c View File

@@ -0,0 +1,32 @@
#include "symmetric.h"
#include "fips202.h"

void PQCLEAN_DILITHIUM3_CLEAN_shake128_stream_init(shake128ctx *state,
const unsigned char seed[SEEDBYTES],
uint16_t nonce) {
unsigned int i;
unsigned char buf[SEEDBYTES + 2];

for (i = 0; i < SEEDBYTES; ++i) {
buf[i] = seed[i];
}
buf[SEEDBYTES] = (uint8_t) nonce;
buf[SEEDBYTES + 1] = (uint8_t) (nonce >> 8);

shake128_absorb(state, buf, sizeof(buf));
}

void PQCLEAN_DILITHIUM3_CLEAN_shake256_stream_init(shake256ctx *state,
const unsigned char seed[CRHBYTES],
uint16_t nonce) {
unsigned int i;
unsigned char buf[CRHBYTES + 2];

for (i = 0; i < CRHBYTES; ++i) {
buf[i] = seed[i];
}
buf[CRHBYTES] = (uint8_t) nonce;
buf[CRHBYTES + 1] = (uint8_t) (nonce >> 8);

shake256_absorb(state, buf, sizeof(buf));
}

+ 23
- 0
crypto_sign/dilithium3/clean/symmetric.h View File

@@ -0,0 +1,23 @@
#ifndef SYMMETRIC_H
#define SYMMETRIC_H

#include "fips202.h"
#include "params.h"

#define crh(OUT, IN, INBYTES) shake256(OUT, CRHBYTES, IN, INBYTES)
#define stream128_init(STATE, SEED, NONCE) PQCLEAN_DILITHIUM3_CLEAN_shake128_stream_init(STATE, SEED, NONCE)
#define stream128_squeezeblocks(OUT, OUTBLOCKS, STATE) shake128_squeezeblocks(OUT, OUTBLOCKS, STATE)
#define stream256_init(STATE, SEED, NONCE) PQCLEAN_DILITHIUM3_CLEAN_shake256_stream_init(STATE, SEED, NONCE)
#define stream256_squeezeblocks(OUT, OUTBLOCKS, STATE) shake256_squeezeblocks(OUT, OUTBLOCKS, STATE)

#define STREAM128_BLOCKBYTES SHAKE128_RATE
#define STREAM256_BLOCKBYTES SHAKE256_RATE

void PQCLEAN_DILITHIUM3_CLEAN_shake128_stream_init(shake128ctx *state,
const unsigned char *seed,
uint16_t nonce);
void PQCLEAN_DILITHIUM3_CLEAN_shake256_stream_init(shake256ctx *state,
const unsigned char *seed,
uint16_t nonce);

#endif

+ 19
- 0
crypto_sign/dilithium4/META.yml View File

@@ -0,0 +1,19 @@
name: DilithiumIV
type: signature
claimed-nist-level: 3
length-public-key: 1760
length-secret-key: 3856
length-signature: 3366
nistkat-sha256: 87844f967b4340d60dc4d83aac0f1d3a244fa8f9490017f72fd4969bba168f88
testvectors-sha256: 91087880c84678bf66008d843e7fa1ab5231114a8ca9e9e36c41065f14172af2
principal-submitter: Vadim Lyubashevsky
auxiliary-submitters:
- Léo Ducas
- Eike Kiltz
- Tancrède Lepoint
- Peter Schwabe
- Gregor Seiler
- Damien Stehlé
implementations:
- name: clean
version: https://github.com/pq-crystals/dilithium/commit/40f79645879b5c69835cd91d06945d7c24f39922

+ 2
- 0
crypto_sign/dilithium4/clean/LICENSE View File

@@ -0,0 +1,2 @@
Public Domain
Authors: Léo Ducas, Eike Kiltz, Tancrède Lepoint, Vadim Lyubashevsky, Gregor Seiler, Peter Schwabe, Damien Stehlé

+ 22
- 0
crypto_sign/dilithium4/clean/Makefile View File

@@ -0,0 +1,22 @@
# This Makefile can be used with GNU Make or BSD Make

LIB=libdilithium4_clean.a

SOURCES = sign.c polyvec.c poly.c packing.c ntt.c reduce.c rounding.c symmetric.c
OBJECTS = sign.o polyvec.o poly.o packing.o ntt.o reduce.o rounding.o symmetric.o
HEADERS = api.h params.h sign.h polyvec.h poly.h packing.h ntt.h \
reduce.h rounding.h symmetric.h

CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -Wredundant-decls -std=c99 -I../../../common $(EXTRAFLAGS)

all: $(LIB)

%.o: %.c $(HEADERS)
$(CC) $(CFLAGS) -c -o $@ $<

$(LIB): $(OBJECTS)
$(AR) -r $@ $(OBJECTS)

clean:
$(RM) $(OBJECTS)
$(RM) $(LIB)

+ 18
- 0
crypto_sign/dilithium4/clean/Makefile.Microsoft_nmake View File

@@ -0,0 +1,18 @@
# This Makefile can be used with Microsoft Visual Studio's nmake using the command:
# nmake /f Makefile.Microsoft_nmake

LIBRARY=libdilithium4_clean.lib
OBJECTS=sign.obj polyvec.obj poly.obj packing.obj ntt.obj reduce.obj rounding.obj symmetric.obj
CFLAGS=/nologo /I ..\..\..\common /W4 /WX

all: $(LIBRARY)

# Make sure objects are recompiled if headers change.
$(OBJECTS): *.h

$(LIBRARY): $(OBJECTS)
LIB.EXE /NOLOGO /WX /OUT:$@ $**

clean:
-DEL $(OBJECTS)
-DEL $(LIBRARY)

+ 31
- 0
crypto_sign/dilithium4/clean/api.h View File

@@ -0,0 +1,31 @@
#ifndef PQCLEAN_DILITHIUM4_CLEAN_API_H
#define PQCLEAN_DILITHIUM4_CLEAN_API_H

#include <stdint.h>

#define PQCLEAN_DILITHIUM4_CLEAN_CRYPTO_PUBLICKEYBYTES 1760U
#define PQCLEAN_DILITHIUM4_CLEAN_CRYPTO_SECRETKEYBYTES 3856U
#define PQCLEAN_DILITHIUM4_CLEAN_CRYPTO_BYTES 3366U
#define PQCLEAN_DILITHIUM4_CLEAN_CRYPTO_ALGNAME "Dilithium4"


int PQCLEAN_DILITHIUM4_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk);

int PQCLEAN_DILITHIUM4_CLEAN_crypto_sign_signature(
uint8_t *sig, size_t *siglen,
const uint8_t *m, size_t mlen, const uint8_t *sk);

int PQCLEAN_DILITHIUM4_CLEAN_crypto_sign_verify(
const uint8_t *sig, size_t siglen,
const uint8_t *m, size_t mlen, const uint8_t *pk);

int PQCLEAN_DILITHIUM4_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen,
const uint8_t *msg, size_t len,
const uint8_t *sk);

int PQCLEAN_DILITHIUM4_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen,
const uint8_t *sm, size_t smlen,
const uint8_t *pk);


#endif

+ 137
- 0
crypto_sign/dilithium4/clean/ntt.c View File

@@ -0,0 +1,137 @@
#include "ntt.h"
#include "params.h"
#include "poly.h"
#include "reduce.h"
#include <stdint.h>

/* Roots of unity in order needed by forward ntt */
static const uint32_t zetas[N] = {
0, 25847, 5771523, 7861508, 237124, 7602457, 7504169, 466468, 1826347,
2353451, 8021166, 6288512, 3119733, 5495562, 3111497, 2680103, 2725464,
1024112, 7300517, 3585928, 7830929, 7260833, 2619752, 6271868, 6262231,
4520680, 6980856, 5102745, 1757237, 8360995, 4010497, 280005, 2706023,
95776, 3077325, 3530437, 6718724, 4788269, 5842901, 3915439, 4519302,
5336701, 3574422, 5512770, 3539968, 8079950, 2348700, 7841118, 6681150,
6736599, 3505694, 4558682, 3507263, 6239768, 6779997, 3699596, 811944,
531354, 954230, 3881043, 3900724, 5823537, 2071892, 5582638, 4450022,
6851714, 4702672, 5339162, 6927966, 3475950, 2176455, 6795196, 7122806,
1939314, 4296819, 7380215, 5190273, 5223087, 4747489, 126922, 3412210,
7396998, 2147896, 2715295, 5412772, 4686924, 7969390, 5903370, 7709315,
7151892, 8357436, 7072248, 7998430, 1349076, 1852771, 6949987, 5037034,
264944, 508951, 3097992, 44288, 7280319, 904516, 3958618, 4656075, 8371839,
1653064, 5130689, 2389356, 8169440, 759969, 7063561, 189548, 4827145,
3159746, 6529015, 5971092, 8202977, 1315589, 1341330, 1285669, 6795489,
7567685, 6940675, 5361315, 4499357, 4751448, 3839961, 2091667, 3407706,
2316500, 3817976, 5037939, 2244091, 5933984, 4817955, 266997, 2434439,
7144689, 3513181, 4860065, 4621053, 7183191, 5187039, 900702, 1859098,
909542, 819034, 495491, 6767243, 8337157, 7857917, 7725090, 5257975,
2031748, 3207046, 4823422, 7855319, 7611795, 4784579, 342297, 286988,
5942594, 4108315, 3437287, 5038140, 1735879, 203044, 2842341, 2691481,
5790267, 1265009, 4055324, 1247620, 2486353, 1595974, 4613401, 1250494,
2635921, 4832145, 5386378, 1869119, 1903435, 7329447, 7047359, 1237275,
5062207, 6950192, 7929317, 1312455, 3306115, 6417775, 7100756, 1917081,
5834105, 7005614, 1500165, 777191, 2235880, 3406031, 7838005, 5548557,
6709241, 6533464, 5796124, 4656147, 594136, 4603424, 6366809, 2432395,
2454455, 8215696, 1957272, 3369112, 185531, 7173032, 5196991, 162844,
1616392, 3014001, 810149, 1652634, 4686184, 6581310, 5341501, 3523897,
3866901, 269760, 2213111, 7404533, 1717735, 472078, 7953734, 1723600,
6577327, 1910376, 6712985, 7276084, 8119771, 4546524, 5441381, 6144432,
7959518, 6094090, 183443, 7403526, 1612842, 4834730, 7826001, 3919660,
8332111, 7018208, 3937738, 1400424, 7534263, 1976782
};

/* Roots of unity in order needed by inverse ntt */
static const uint32_t zetas_inv[N] = {
6403635, 846154, 6979993, 4442679, 1362209, 48306, 4460757, 554416,
3545687, 6767575, 976891, 8196974, 2286327, 420899, 2235985, 2939036,
3833893, 260646, 1104333, 1667432, 6470041, 1803090, 6656817, 426683,
7908339, 6662682, 975884, 6167306, 8110657, 4513516, 4856520, 3038916,
1799107, 3694233, 6727783, 7570268, 5366416, 6764025, 8217573, 3183426,
1207385, 8194886, 5011305, 6423145, 164721, 5925962, 5948022, 2013608,
3776993, 7786281, 3724270, 2584293, 1846953, 1671176, 2831860, 542412,
4974386, 6144537, 7603226, 6880252, 1374803, 2546312, 6463336, 1279661,
1962642, 5074302, 7067962, 451100, 1430225, 3318210, 7143142, 1333058,
1050970, 6476982, 6511298, 2994039, 3548272, 5744496, 7129923, 3767016,
6784443, 5894064, 7132797, 4325093, 7115408, 2590150, 5688936, 5538076,
8177373, 6644538, 3342277, 4943130, 4272102, 2437823, 8093429, 8038120,
3595838, 768622, 525098, 3556995, 5173371, 6348669, 3122442, 655327,
522500, 43260, 1613174, 7884926, 7561383, 7470875, 6521319, 7479715,
3193378, 1197226, 3759364, 3520352, 4867236, 1235728, 5945978, 8113420,
3562462, 2446433, 6136326, 3342478, 4562441, 6063917, 4972711, 6288750,
4540456, 3628969, 3881060, 3019102, 1439742, 812732, 1584928, 7094748,
7039087, 7064828, 177440, 2409325, 1851402, 5220671, 3553272, 8190869,
1316856, 7620448, 210977, 5991061, 3249728, 6727353, 8578, 3724342,
4421799, 7475901, 1100098, 8336129, 5282425, 7871466, 8115473, 3343383,
1430430, 6527646, 7031341, 381987, 1308169, 22981, 1228525, 671102,
2477047, 411027, 3693493, 2967645, 5665122, 6232521, 983419, 4968207,
8253495, 3632928, 3157330, 3190144, 1000202, 4083598, 6441103, 1257611,
1585221, 6203962, 4904467, 1452451, 3041255, 3677745, 1528703, 3930395,
2797779, 6308525, 2556880, 4479693, 4499374, 7426187, 7849063, 7568473,
4680821, 1600420, 2140649, 4873154, 3821735, 4874723, 1643818, 1699267,
539299, 6031717, 300467, 4840449, 2867647, 4805995, 3043716, 3861115,
4464978, 2537516, 3592148, 1661693, 4849980, 5303092, 8284641, 5674394,
8100412, 4369920, 19422, 6623180, 3277672, 1399561, 3859737, 2118186,
2108549, 5760665, 1119584, 549488, 4794489, 1079900, 7356305, 5654953,
5700314, 5268920, 2884855, 5260684, 2091905, 359251, 6026966, 6554070,
7913949, 876248, 777960, 8143293, 518909, 2608894, 8354570
};

/*************************************************
* Name: ntt
*
* Description: Forward NTT, in-place. No modular reduction is performed after
* additions or subtractions. Hence output coefficients can be up
* to 16*Q larger than the coefficients of the input polynomial.
* Output vector is in bitreversed order.
*
* Arguments: - uint32_t p[N]: input/output coefficient array
**************************************************/
void PQCLEAN_DILITHIUM4_CLEAN_ntt(uint32_t p[N]) {
unsigned int len, start, j, k;
uint32_t zeta, t;

k = 1;
for (len = 128; len > 0; len >>= 1) {
for (start = 0; start < N; start = j + len) {
zeta = zetas[k++];
for (j = start; j < start + len; ++j) {
t = PQCLEAN_DILITHIUM4_CLEAN_montgomery_reduce((uint64_t)zeta * p[j + len]);
p[j + len] = p[j] + 2 * Q - t;
p[j] = p[j] + t;
}
}
}
}

/*************************************************
* Name: invntt_frominvmont
*
* Description: Inverse NTT and multiplication by Montgomery factor 2^32.
* In-place. No modular reductions after additions or
* subtractions. Input coefficient need to be smaller than 2*Q.
* Output coefficient are smaller than 2*Q.
*
* Arguments: - uint32_t p[N]: input/output coefficient array
**************************************************/
void PQCLEAN_DILITHIUM4_CLEAN_invntt_frominvmont(uint32_t p[N]) {
unsigned int start, len, j, k;
uint32_t t, zeta;
const uint32_t f = (((uint64_t)MONT * MONT % Q) * (Q - 1) % Q) * ((Q - 1) >> 8) % Q;

k = 0;
for (len = 1; len < N; len <<= 1) {
for (start = 0; start < N; start = j + len) {
zeta = zetas_inv[k++];
for (j = start; j < start + len; ++j) {
t = p[j];
p[j] = t + p[j + len];
p[j + len] = t + 256 * Q - p[j + len];
p[j + len] = PQCLEAN_DILITHIUM4_CLEAN_montgomery_reduce((uint64_t)zeta * p[j + len]);
}
}
}

for (j = 0; j < N; ++j) {
p[j] = PQCLEAN_DILITHIUM4_CLEAN_montgomery_reduce((uint64_t)f * p[j]);
}
}

+ 10
- 0
crypto_sign/dilithium4/clean/ntt.h View File

@@ -0,0 +1,10 @@
#ifndef NTT_H
#define NTT_H

#include "params.h"
#include <stdint.h>

void PQCLEAN_DILITHIUM4_CLEAN_ntt(uint32_t p[N]);
void PQCLEAN_DILITHIUM4_CLEAN_invntt_frominvmont(uint32_t p[N]);

#endif

+ 297
- 0
crypto_sign/dilithium4/clean/packing.c View File

@@ -0,0 +1,297 @@
#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 PQCLEAN_DILITHIUM4_CLEAN_pack_pk(unsigned char pk[CRYPTO_PUBLICKEYBYTES],
const unsigned char rho[SEEDBYTES],
const polyveck *t1) {
unsigned int i;

for (i = 0; i < SEEDBYTES; ++i) {
pk[i] = rho[i];
}
pk += SEEDBYTES;

for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM4_CLEAN_polyt1_pack(pk + i * POLT1_SIZE_PACKED, &t1->vec[i]);
}
}

/*************************************************
* 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 PQCLEAN_DILITHIUM4_CLEAN_unpack_pk(unsigned char rho[SEEDBYTES],
polyveck *t1,
const unsigned char pk[CRYPTO_PUBLICKEYBYTES]) {
unsigned int i;

for (i = 0; i < SEEDBYTES; ++i) {
rho[i] = pk[i];
}
pk += SEEDBYTES;

for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM4_CLEAN_polyt1_unpack(&t1->vec[i], pk + i * POLT1_SIZE_PACKED);
}
}

/*************************************************
* 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 PQCLEAN_DILITHIUM4_CLEAN_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) {
unsigned int i;

for (i = 0; i < SEEDBYTES; ++i) {
sk[i] = rho[i];
}
sk += SEEDBYTES;

for (i = 0; i < SEEDBYTES; ++i) {
sk[i] = key[i];
}
sk += SEEDBYTES;

for (i = 0; i < CRHBYTES; ++i) {
sk[i] = tr[i];
}
sk += CRHBYTES;

for (i = 0; i < L; ++i) {
PQCLEAN_DILITHIUM4_CLEAN_polyeta_pack(sk + i * POLETA_SIZE_PACKED, &s1->vec[i]);
}
sk += L * POLETA_SIZE_PACKED;

for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM4_CLEAN_polyeta_pack(sk + i * POLETA_SIZE_PACKED, &s2->vec[i]);
}
sk += K * POLETA_SIZE_PACKED;

for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM4_CLEAN_polyt0_pack(sk + i * POLT0_SIZE_PACKED, &t0->vec[i]);
}
}

/*************************************************
* 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 PQCLEAN_DILITHIUM4_CLEAN_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]) {
unsigned int i;

for (i = 0; i < SEEDBYTES; ++i) {
rho[i] = sk[i];
}
sk += SEEDBYTES;

for (i = 0; i < SEEDBYTES; ++i) {
key[i] = sk[i];
}
sk += SEEDBYTES;

for (i = 0; i < CRHBYTES; ++i) {
tr[i] = sk[i];
}
sk += CRHBYTES;

for (i = 0; i < L; ++i) {
PQCLEAN_DILITHIUM4_CLEAN_polyeta_unpack(&s1->vec[i], sk + i * POLETA_SIZE_PACKED);
}
sk += L * POLETA_SIZE_PACKED;

for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM4_CLEAN_polyeta_unpack(&s2->vec[i], sk + i * POLETA_SIZE_PACKED);
}
sk += K * POLETA_SIZE_PACKED;

for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM4_CLEAN_polyt0_unpack(&t0->vec[i], sk + i * POLT0_SIZE_PACKED);
}
}

/*************************************************
* 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 PQCLEAN_DILITHIUM4_CLEAN_pack_sig(unsigned char sig[CRYPTO_BYTES],
const polyvecl *z,
const polyveck *h,
const poly *c) {
unsigned int i, j, k;
uint64_t signs, mask;

for (i = 0; i < L; ++i) {
PQCLEAN_DILITHIUM4_CLEAN_polyz_pack(sig + i * POLZ_SIZE_PACKED, &z->vec[i]);
}
sig += L * POLZ_SIZE_PACKED;

/* Encode h */
k = 0;
for (i = 0; i < K; ++i) {
for (j = 0; j < N; ++j) {
if (h->vec[i].coeffs[j] != 0) {
sig[k++] = (unsigned char) j;
}
}
sig[OMEGA + i] = (unsigned char) k;
}
while (k < OMEGA) {
sig[k++] = 0;
}
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] |= (unsigned char) (1U << j);
if (c->coeffs[8 * i + j] == (Q - 1)) {
signs |= mask;
}
mask <<= 1;
}
}
}
sig += N / 8;
for (i = 0; i < 8; ++i) {
sig[i] = (unsigned char) (signs >> 8 * i);
}
}

/*************************************************
* 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 PQCLEAN_DILITHIUM4_CLEAN_unpack_sig(polyvecl *z,
polyveck *h,
poly *c,
const unsigned char sig[CRYPTO_BYTES]) {
unsigned int i, j, k;
uint64_t signs;

for (i = 0; i < L; ++i) {
PQCLEAN_DILITHIUM4_CLEAN_polyz_unpack(&z->vec[i], sig + i * POLZ_SIZE_PACKED);
}
sig += L * POLZ_SIZE_PACKED;

/* Decode h */
k = 0;
for (i = 0; i < K; ++i) {
for (j = 0; j < N; ++j) {
h->vec[i].coeffs[j] = 0;
}

if (sig[OMEGA + i] < k || sig[OMEGA + i] > OMEGA) {
return 1;
}

for (j = k; j < sig[OMEGA + i]; ++j) {
/* Coefficients are ordered for strong unforgeability */
if (j > k && sig[j] <= sig[j - 1]) {
return 1;
}
h->vec[i].coeffs[sig[j]] = 1;
}

k = sig[OMEGA + i];
}

/* Extra indices are zero for strong unforgeability */
for (j = k; j < OMEGA; ++j) {
if (sig[j]) {
return 1;
}
}
sig += OMEGA + K;

/* Decode c */
for (i = 0; i < N; ++i) {
c->coeffs[i] = 0;
}

signs = 0;
for (i = 0; i < 8; ++i) {
signs |= (uint64_t)sig[N / 8 + i] << 8 * i;
}

/* Extra sign bits are zero for strong unforgeability */
if (signs >> 60) {
return 1;
}

for (i = 0; i < N / 8; ++i) {
for (j = 0; j < 8; ++j) {
if ((sig[i] >> j) & 0x01) {
c->coeffs[8 * i + j] = 1;
c->coeffs[8 * i + j] ^= -((int32_t) signs & 1) & (1 ^ (Q - 1));
signs >>= 1;
}
}
}

return 0;
}

+ 31
- 0
crypto_sign/dilithium4/clean/packing.h View File

@@ -0,0 +1,31 @@
#ifndef PACKING_H
#define PACKING_H

#include "params.h"
#include "polyvec.h"

void PQCLEAN_DILITHIUM4_CLEAN_pack_pk(unsigned char pk[CRYPTO_PUBLICKEYBYTES],
const unsigned char rho[SEEDBYTES], const polyveck *t1);
void PQCLEAN_DILITHIUM4_CLEAN_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);
void PQCLEAN_DILITHIUM4_CLEAN_pack_sig(unsigned char sig[CRYPTO_BYTES],
const polyvecl *z, const polyveck *h, const poly *c);

void PQCLEAN_DILITHIUM4_CLEAN_unpack_pk(unsigned char rho[SEEDBYTES], polyveck *t1,
const unsigned char pk[CRYPTO_PUBLICKEYBYTES]);
void PQCLEAN_DILITHIUM4_CLEAN_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]);
int PQCLEAN_DILITHIUM4_CLEAN_unpack_sig(polyvecl *z, polyveck *h, poly *c,
const unsigned char sig[CRYPTO_BYTES]);

#endif

+ 34
- 0
crypto_sign/dilithium4/clean/params.h View File

@@ -0,0 +1,34 @@
#ifndef PARAMS_H
#define PARAMS_H


#define SEEDBYTES 32
#define CRHBYTES 48
#define N 256
#define Q 8380417
#define QBITS 23
#define ROOT_OF_UNITY 1753
#define D 14
#define GAMMA1 ((Q - 1)/16)
#define GAMMA2 (GAMMA1/2)
#define ALPHA (2*GAMMA2)

// DilithiumIV parameters
#define K 6
#define L 5
#define ETA 3
#define SETABITS 3
#define BETA 175
#define OMEGA 120

#define POLT1_SIZE_PACKED ((N*(QBITS - D))/8)
#define POLT0_SIZE_PACKED ((N*D)/8)
#define POLETA_SIZE_PACKED ((N*SETABITS)/8)
#define POLZ_SIZE_PACKED ((N*(QBITS - 3))/8)
#define POLW1_SIZE_PACKED ((N*4)/8)

#define CRYPTO_PUBLICKEYBYTES (SEEDBYTES + K*POLT1_SIZE_PACKED)
#define CRYPTO_SECRETKEYBYTES (2*SEEDBYTES + (L + K)*POLETA_SIZE_PACKED + CRHBYTES + K*POLT0_SIZE_PACKED)
#define CRYPTO_BYTES (L*POLZ_SIZE_PACKED + (OMEGA + K) + (N/8 + 8))

#endif

+ 760
- 0
crypto_sign/dilithium4/clean/poly.c View File

@@ -0,0 +1,760 @@
#include "ntt.h"
#include "params.h"
#include "poly.h"
#include "reduce.h"
#include "rounding.h"
#include "symmetric.h"
#include <stdint.h>


/*************************************************
* Name: PQCLEAN_DILITHIUM4_CLEAN_poly_reduce
*
* Description: Reduce all coefficients of input polynomial to representative
* in [0,2*Q[.
*
* Arguments: - poly *a: pointer to input/output polynomial
**************************************************/
void PQCLEAN_DILITHIUM4_CLEAN_poly_reduce(poly *a) {
unsigned int i;
for (i = 0; i < N; ++i) {
a->coeffs[i] = PQCLEAN_DILITHIUM4_CLEAN_reduce32(a->coeffs[i]);
}
}

/*************************************************
* Name: PQCLEAN_DILITHIUM4_CLEAN_poly_csubq
*
* Description: For all coefficients of input polynomial subtract Q if
* coefficient is bigger than Q.
*
* Arguments: - poly *a: pointer to input/output polynomial
**************************************************/
void PQCLEAN_DILITHIUM4_CLEAN_poly_csubq(poly *a) {
unsigned int i;
for (i = 0; i < N; ++i) {
a->coeffs[i] = PQCLEAN_DILITHIUM4_CLEAN_csubq(a->coeffs[i]);
}
}

/*************************************************
* Name: PQCLEAN_DILITHIUM4_CLEAN_poly_freeze
*
* Description: Reduce all coefficients of the polynomial to standard
* representatives.
*
* Arguments: - poly *a: pointer to input/output polynomial
**************************************************/
void PQCLEAN_DILITHIUM4_CLEAN_poly_freeze(poly *a) {
unsigned int i;
for (i = 0; i < N; ++i) {
a->coeffs[i] = PQCLEAN_DILITHIUM4_CLEAN_freeze(a->coeffs[i]);
}
}

/*************************************************
* Name: PQCLEAN_DILITHIUM4_CLEAN_poly_add
*
* Description: Add polynomials. No modular reduction is performed.
*
* Arguments: - poly *c: pointer to output polynomial
* - const poly *a: pointer to first summand
* - const poly *b: pointer to second summand
**************************************************/
void PQCLEAN_DILITHIUM4_CLEAN_poly_add(poly *c, const poly *a, const poly *b) {
unsigned int i;
for (i = 0; i < N; ++i) {
c->coeffs[i] = a->coeffs[i] + b->coeffs[i];
}
}

/*************************************************
* Name: PQCLEAN_DILITHIUM4_CLEAN_poly_sub
*
* Description: Subtract polynomials. Assumes coefficients of second input
* polynomial to be less than 2*Q. No modular reduction is
* performed.
*
* Arguments: - poly *c: pointer to output polynomial
* - const poly *a: pointer to first input polynomial
* - const poly *b: pointer to second input polynomial to be
* subtraced from first input polynomial
**************************************************/
void PQCLEAN_DILITHIUM4_CLEAN_poly_sub(poly *c, const poly *a, const poly *b) {
unsigned int i;
for (i = 0; i < N; ++i) {
c->coeffs[i] = a->coeffs[i] + 2 * Q - b->coeffs[i];
}
}

/*************************************************
* Name: PQCLEAN_DILITHIUM4_CLEAN_poly_shiftl
*
* Description: Multiply polynomial by 2^D without modular reduction. Assumes
* input coefficients to be less than 2^{32-D}.
*
* Arguments: - poly *a: pointer to input/output polynomial
**************************************************/
void PQCLEAN_DILITHIUM4_CLEAN_poly_shiftl(poly *a) {
unsigned int i;
for (i = 0; i < N; ++i) {
a->coeffs[i] <<= D;
}
}

/*************************************************
* Name: PQCLEAN_DILITHIUM4_CLEAN_poly_ntt
*
* Description: Forward NTT. Output coefficients can be up to 16*Q larger than
* input coefficients.
*
* Arguments: - poly *a: pointer to input/output polynomial
**************************************************/
void PQCLEAN_DILITHIUM4_CLEAN_poly_ntt(poly *a) {
PQCLEAN_DILITHIUM4_CLEAN_ntt(a->coeffs);
}

/*************************************************
* Name: PQCLEAN_DILITHIUM4_CLEAN_poly_invntt_montgomery
*
* Description: Inverse NTT and multiplication with 2^{32}. Input coefficients
* need to be less than 2*Q. Output coefficients are less than 2*Q.
*
* Arguments: - poly *a: pointer to input/output polynomial
**************************************************/
void PQCLEAN_DILITHIUM4_CLEAN_poly_invntt_montgomery(poly *a) {
PQCLEAN_DILITHIUM4_CLEAN_invntt_frominvmont(a->coeffs);
}

/*************************************************
* Name: PQCLEAN_DILITHIUM4_CLEAN_poly_pointwise_invmontgomery
*
* Description: Pointwise multiplication of polynomials in NTT domain
* representation and multiplication of resulting polynomial
* with 2^{-32}. Output coefficients are less than 2*Q if input
* coefficient are less than 22*Q.
*
* Arguments: - poly *c: pointer to output polynomial
* - const poly *a: pointer to first input polynomial
* - const poly *b: pointer to second input polynomial
**************************************************/
void PQCLEAN_DILITHIUM4_CLEAN_poly_pointwise_invmontgomery(poly *c, const poly *a, const poly *b) {
unsigned int i;

for (i = 0; i < N; ++i) {
c->coeffs[i] = PQCLEAN_DILITHIUM4_CLEAN_montgomery_reduce((uint64_t)a->coeffs[i] * b->coeffs[i]);
}

}

/*************************************************
* Name: PQCLEAN_DILITHIUM4_CLEAN_poly_power2round
*
* Description: For all coefficients c of the input polynomial,
* compute c0, c1 such that c mod Q = c1*2^D + c0
* with -2^{D-1} < c0 <= 2^{D-1}. Assumes coefficients to be
* standard representatives.
*
* Arguments: - poly *a1: pointer to output polynomial with coefficients c1
* - poly *a0: pointer to output polynomial with coefficients Q + a0
* - const poly *v: pointer to input polynomial
**************************************************/
void PQCLEAN_DILITHIUM4_CLEAN_poly_power2round(poly *a1, poly *a0, const poly *a) {
unsigned int i;

for (i = 0; i < N; ++i) {
a1->coeffs[i] = PQCLEAN_DILITHIUM4_CLEAN_power2round(a->coeffs[i], &a0->coeffs[i]);
}

}

/*************************************************
* Name: PQCLEAN_DILITHIUM4_CLEAN_poly_decompose
*
* Description: For all coefficients c of the input polynomial,
* compute high and low bits c0, c1 such c mod Q = c1*ALPHA + c0
* with -ALPHA/2 < c0 <= ALPHA/2 except c1 = (Q-1)/ALPHA where we
* set c1 = 0 and -ALPHA/2 <= c0 = c mod Q - Q < 0.
* Assumes coefficients to be standard representatives.
*
* Arguments: - poly *a1: pointer to output polynomial with coefficients c1
* - poly *a0: pointer to output polynomial with coefficients Q + a0
* - const poly *c: pointer to input polynomial
**************************************************/
void PQCLEAN_DILITHIUM4_CLEAN_poly_decompose(poly *a1, poly *a0, const poly *a) {
unsigned int i;

for (i = 0; i < N; ++i) {
a1->coeffs[i] = PQCLEAN_DILITHIUM4_CLEAN_decompose(a->coeffs[i], &a0->coeffs[i]);
}

}

/*************************************************
* Name: PQCLEAN_DILITHIUM4_CLEAN_poly_make_hint
*
* Description: Compute hint polynomial. The coefficients of which indicate
* whether the low bits of the corresponding coefficient of
* the input polynomial overflow into the high bits.
*
* Arguments: - poly *h: pointer to output hint polynomial
* - const poly *a0: pointer to low part of input polynomial
* - const poly *a1: pointer to high part of input polynomial
*
* Returns number of 1 bits.
**************************************************/
unsigned int PQCLEAN_DILITHIUM4_CLEAN_poly_make_hint(poly *h, const poly *a0, const poly *a1) {
unsigned int i, s = 0;

for (i = 0; i < N; ++i) {
h->coeffs[i] = PQCLEAN_DILITHIUM4_CLEAN_make_hint(a0->coeffs[i], a1->coeffs[i]);
s += h->coeffs[i];
}

return s;
}

/*************************************************
* Name: PQCLEAN_DILITHIUM4_CLEAN_poly_use_hint
*
* Description: Use hint polynomial to correct the high bits of a polynomial.
*
* Arguments: - poly *a: pointer to output polynomial with corrected high bits
* - const poly *b: pointer to input polynomial
* - const poly *h: pointer to input hint polynomial
**************************************************/
void PQCLEAN_DILITHIUM4_CLEAN_poly_use_hint(poly *a, const poly *b, const poly *h) {
unsigned int i;

for (i = 0; i < N; ++i) {
a->coeffs[i] = PQCLEAN_DILITHIUM4_CLEAN_use_hint(b->coeffs[i], h->coeffs[i]);
}

}

/*************************************************
* Name: PQCLEAN_DILITHIUM4_CLEAN_poly_chknorm
*
* Description: Check infinity norm of polynomial against given bound.
* Assumes input coefficients to be standard representatives.
*
* Arguments: - const poly *a: pointer to polynomial
* - uint32_t B: norm bound
*
* Returns 0 if norm is strictly smaller than B and 1 otherwise.
**************************************************/
int PQCLEAN_DILITHIUM4_CLEAN_poly_chknorm(const poly *a, uint32_t B) {
unsigned int i;
int32_t t;

/* It is ok to leak which coefficient violates the bound since
the probability for each coefficient is independent of secret
data but we must not leak the sign of the centralized representative. */
for (i = 0; i < N; ++i) {
/* Absolute value of centralized representative */
t = (int32_t) ((Q - 1) / 2 - a->coeffs[i]);
t ^= (t >> 31);
t = (Q - 1) / 2 - t;

if ((uint32_t)t >= B) {
return 1;
}
}

return 0;
}

/*************************************************
* Name: rej_uniform
*
* Description: Sample uniformly random coefficients in [0, Q-1] by
* performing rejection sampling using array of random bytes.
*
* Arguments: - uint32_t *a: pointer to output array (allocated)
* - unsigned int len: number of coefficients to be sampled
* - const unsigned char *buf: array of random bytes
* - unsigned int buflen: length of array of random bytes
*
* Returns number of sampled coefficients. Can be smaller than len if not enough
* random bytes were given.
**************************************************/
static unsigned int rej_uniform(uint32_t *a,
unsigned int len,
const unsigned char *buf,
unsigned int buflen) {
unsigned int ctr, pos;
uint32_t t;

ctr = pos = 0;
while (ctr < len && pos + 3 <= buflen) {
t = buf[pos++];
t |= (uint32_t)buf[pos++] << 8;
t |= (uint32_t)buf[pos++] << 16;
t &= 0x7FFFFF;

if (t < Q) {
a[ctr++] = t;
}
}

return ctr;
}

/*************************************************
* Name: PQCLEAN_DILITHIUM4_CLEAN_poly_uniform
*
* Description: Sample polynomial with uniformly random coefficients
* in [0,Q-1] by performing rejection sampling using the
* output stream from SHAKE256(seed|nonce).
*
* Arguments: - poly *a: pointer to output polynomial
* - const unsigned char seed[]: byte array with seed of length
* SEEDBYTES
* - uint16_t nonce: 2-byte nonce
**************************************************/
#define POLY_UNIFORM_NBLOCKS ((769 + STREAM128_BLOCKBYTES)/STREAM128_BLOCKBYTES)
#define POLY_UNIFORM_BUFLEN (POLY_UNIFORM_NBLOCKS * STREAM128_BLOCKBYTES)
void PQCLEAN_DILITHIUM4_CLEAN_poly_uniform(poly *a,
const unsigned char seed[SEEDBYTES],
uint16_t nonce) {
unsigned int i, ctr, off;
unsigned int buflen = POLY_UNIFORM_BUFLEN;
unsigned char buf[POLY_UNIFORM_BUFLEN + 2];
shake128ctx state;

stream128_init(&state, seed, nonce);
stream128_squeezeblocks(buf, POLY_UNIFORM_NBLOCKS, &state);

ctr = rej_uniform(a->coeffs, N, buf, buflen);

while (ctr < N) {
off = buflen % 3;
for (i = 0; i < off; ++i) {
buf[i] = buf[buflen - off + i];
}

buflen = STREAM128_BLOCKBYTES + off;
stream128_squeezeblocks(buf + off, 1, &state);
ctr += rej_uniform(a->coeffs + ctr, N - ctr, buf, buflen);
}
}

/*************************************************
* Name: rej_eta
*
* Description: Sample uniformly random coefficients in [-ETA, ETA] by
* performing rejection sampling using array of random bytes.
*
* Arguments: - uint32_t *a: pointer to output array (allocated)
* - unsigned int len: number of coefficients to be sampled
* - const unsigned char *buf: array of random bytes
* - unsigned int buflen: length of array of random bytes
*
* Returns number of sampled coefficients. Can be smaller than len if not enough
* random bytes were given.
**************************************************/
static unsigned int rej_eta(uint32_t *a,
unsigned int len,
const unsigned char *buf,
unsigned int buflen) {
unsigned int ctr, pos;
uint32_t t0, t1;

ctr = pos = 0;
while (ctr < len && pos < buflen) {
t0 = buf[pos] & 0x07;
t1 = buf[pos++] >> 5;

if (t0 <= 2 * ETA) {
a[ctr++] = Q + ETA - t0;
}
if (t1 <= 2 * ETA && ctr < len) {
a[ctr++] = Q + ETA - t1;
}
}

return ctr;
}

/*************************************************
* Name: PQCLEAN_DILITHIUM4_CLEAN_poly_uniform_eta
*
* Description: Sample polynomial with uniformly random coefficients
* in [-ETA,ETA] by performing rejection sampling using the
* output stream from SHAKE256(seed|nonce).
*
* Arguments: - poly *a: pointer to output polynomial
* - const unsigned char seed[]: byte array with seed of length
* SEEDBYTES
* - uint16_t nonce: 2-byte nonce
**************************************************/
#define POLY_UNIFORM_ETA_NBLOCKS (((N/2 * (1U << SETABITS)) / (2*ETA + 1)\
+ STREAM128_BLOCKBYTES) / STREAM128_BLOCKBYTES)
#define POLY_UNIFORM_ETA_BUFLEN (POLY_UNIFORM_ETA_NBLOCKS*STREAM128_BLOCKBYTES)
void PQCLEAN_DILITHIUM4_CLEAN_poly_uniform_eta(poly *a,
const unsigned char seed[SEEDBYTES],
uint16_t nonce) {
unsigned int ctr;
unsigned char buf[POLY_UNIFORM_ETA_BUFLEN];
shake128ctx state;

stream128_init(&state, seed, nonce);
stream128_squeezeblocks(buf, POLY_UNIFORM_ETA_NBLOCKS, &state);

ctr = rej_eta(a->coeffs, N, buf, POLY_UNIFORM_ETA_BUFLEN);

while (ctr < N) {
stream128_squeezeblocks(buf, 1, &state);
ctr += rej_eta(a->coeffs + ctr, N - ctr, buf, STREAM128_BLOCKBYTES);
}
}

/*************************************************
* Name: rej_gamma1m1
*
* Description: Sample uniformly random coefficients
* in [-(GAMMA1 - 1), GAMMA1 - 1] by performing rejection sampling
* using array of random bytes.
*
* Arguments: - uint32_t *a: pointer to output array (allocated)
* - unsigned int len: number of coefficients to be sampled
* - const unsigned char *buf: array of random bytes
* - unsigned int buflen: length of array of random bytes
*
* Returns number of sampled coefficients. Can be smaller than len if not enough
* random bytes were given.
**************************************************/
static unsigned int rej_gamma1m1(uint32_t *a,
unsigned int len,
const unsigned char *buf,
unsigned int buflen) {
unsigned int ctr, pos;
uint32_t t0, t1;

ctr = pos = 0;
while (ctr < len && pos + 5 <= buflen) {
t0 = buf[pos];
t0 |= (uint32_t)buf[pos + 1] << 8;
t0 |= (uint32_t)buf[pos + 2] << 16;
t0 &= 0xFFFFF;

t1 = buf[pos + 2] >> 4;
t1 |= (uint32_t)buf[pos + 3] << 4;
t1 |= (uint32_t)buf[pos + 4] << 12;

pos += 5;

if (t0 <= 2 * GAMMA1 - 2) {
a[ctr++] = Q + GAMMA1 - 1 - t0;
}
if (t1 <= 2 * GAMMA1 - 2 && ctr < len) {
a[ctr++] = Q + GAMMA1 - 1 - t1;
}
}

return ctr;
}

/*************************************************
* Name: PQCLEAN_DILITHIUM4_CLEAN_poly_uniform_gamma1m1
*
* Description: Sample polynomial with uniformly random coefficients
* in [-(GAMMA1 - 1), GAMMA1 - 1] by performing rejection
* sampling on output stream of SHAKE256(seed|nonce).
*
* Arguments: - poly *a: pointer to output polynomial
* - const unsigned char seed[]: byte array with seed of length
* CRHBYTES
* - uint16_t nonce: 16-bit nonce
**************************************************/
#define POLY_UNIFORM_GAMMA1M1_NBLOCKS ((641 + STREAM256_BLOCKBYTES) / STREAM256_BLOCKBYTES)
#define POLY_UNIFORM_GAMMA1M1_BUFLEN (POLY_UNIFORM_GAMMA1M1_NBLOCKS * STREAM256_BLOCKBYTES)
void PQCLEAN_DILITHIUM4_CLEAN_poly_uniform_gamma1m1(poly *a,
const unsigned char seed[CRHBYTES],
uint16_t nonce) {
unsigned int i, ctr, off;
unsigned int buflen = POLY_UNIFORM_GAMMA1M1_BUFLEN;
unsigned char buf[POLY_UNIFORM_GAMMA1M1_BUFLEN + 4];
shake256ctx state;

stream256_init(&state, seed, nonce);
stream256_squeezeblocks(buf, POLY_UNIFORM_GAMMA1M1_NBLOCKS, &state);

ctr = rej_gamma1m1(a->coeffs, N, buf, buflen);

while (ctr < N) {
off = buflen % 5;
for (i = 0; i < off; ++i) {
buf[i] = buf[buflen - off + i];
}

buflen = STREAM256_BLOCKBYTES + off;
stream256_squeezeblocks(buf + off, 1, &state);
ctr += rej_gamma1m1(a->coeffs + ctr, N - ctr, buf, buflen);
}
}

/*************************************************
* Name: PQCLEAN_DILITHIUM4_CLEAN_polyeta_pack
*
* Description: Bit-pack polynomial with coefficients in [-ETA,ETA].
* Input coefficients are assumed to lie in [Q-ETA,Q+ETA].
*
* Arguments: - unsigned char *r: pointer to output byte array with at least
* POLETA_SIZE_PACKED bytes
* - const poly *a: pointer to input polynomial
**************************************************/
void PQCLEAN_DILITHIUM4_CLEAN_polyeta_pack(unsigned char *r, const poly *a) {
unsigned int i;
unsigned char t[8];

for (i = 0; i < N / 8; ++i) {
t[0] = (uint8_t) (Q + ETA - a->coeffs[8 * i + 0]);
t[1] = (uint8_t) (Q + ETA - a->coeffs[8 * i + 1]);
t[2] = (uint8_t) (Q + ETA - a->coeffs[8 * i + 2]);
t[3] = (uint8_t) (Q + ETA - a->coeffs[8 * i + 3]);
t[4] = (uint8_t) (Q + ETA - a->coeffs[8 * i + 4]);
t[5] = (uint8_t) (Q + ETA - a->coeffs[8 * i + 5]);
t[6] = (uint8_t) (Q + ETA - a->coeffs[8 * i + 6]);
t[7] = (uint8_t) (Q + ETA - a->coeffs[8 * i + 7]);

r[3 * i + 0] = (uint8_t) ((t[0] >> 0) | (t[1] << 3) | (t[2] << 6));
r[3 * i + 1] = (uint8_t) ((t[2] >> 2) | (t[3] << 1) | (t[4] << 4) | (t[5] << 7));
r[3 * i + 2] = (uint8_t) ((t[5] >> 1) | (t[6] << 2) | (t[7] << 5));
}
}

/*************************************************
* Name: PQCLEAN_DILITHIUM4_CLEAN_polyeta_unpack
*
* Description: Unpack polynomial with coefficients in [-ETA,ETA].
* Output coefficients lie in [Q-ETA,Q+ETA].
*
* Arguments: - poly *r: pointer to output polynomial
* - const unsigned char *a: byte array with bit-packed polynomial
**************************************************/
void PQCLEAN_DILITHIUM4_CLEAN_polyeta_unpack(poly *r, const unsigned char *a) {
unsigned int i;

for (i = 0; i < N / 8; ++i) {
r->coeffs[8 * i + 0] = a[3 * i + 0] & 0x07;
r->coeffs[8 * i + 1] = (a[3 * i + 0] >> 3) & 0x07;
r->coeffs[8 * i + 2] = (uint32_t) ((a[3 * i + 0] >> 6) | (a[3 * i + 1] << 2)) & 0x07;
r->coeffs[8 * i + 3] = (a[3 * i + 1] >> 1) & 0x07;
r->coeffs[8 * i + 4] = (a[3 * i + 1] >> 4) & 0x07;
r->coeffs[8 * i + 5] = (uint32_t) ((a[3 * i + 1] >> 7) | (a[3 * i + 2] << 1)) & 0x07;
r->coeffs[8 * i + 6] = (a[3 * i + 2] >> 2) & 0x07;
r->coeffs[8 * i + 7] = (a[3 * i + 2] >> 5) & 0x07;

r->coeffs[8 * i + 0] = Q + ETA - r->coeffs[8 * i + 0];
r->coeffs[8 * i + 1] = Q + ETA - r->coeffs[8 * i + 1];
r->coeffs[8 * i + 2] = Q + ETA - r->coeffs[8 * i + 2];
r->coeffs[8 * i + 3] = Q + ETA - r->coeffs[8 * i + 3];
r->coeffs[8 * i + 4] = Q + ETA - r->coeffs[8 * i + 4];
r->coeffs[8 * i + 5] = Q + ETA - r->coeffs[8 * i + 5];
r->coeffs[8 * i + 6] = Q + ETA - r->coeffs[8 * i + 6];
r->coeffs[8 * i + 7] = Q + ETA - r->coeffs[8 * i + 7];
}
}

/*************************************************
* Name: polyt1_pack
*
* Description: Bit-pack polynomial t1 with coefficients fitting in 9 bits.
* Input coefficients are assumed to be standard representatives.
*
* Arguments: - unsigned char *r: pointer to output byte array with at least
* POLT1_SIZE_PACKED bytes
* - const poly *a: pointer to input polynomial
**************************************************/
void PQCLEAN_DILITHIUM4_CLEAN_polyt1_pack(unsigned char *r, const poly *a) {
unsigned int i;

for (i = 0; i < N / 8; ++i) {
r[9 * i + 0] = (uint8_t) ((a->coeffs[8 * i + 0] >> 0));
r[9 * i + 1] = (uint8_t) ((a->coeffs[8 * i + 0] >> 8) | (a->coeffs[8 * i + 1] << 1));
r[9 * i + 2] = (uint8_t) ((a->coeffs[8 * i + 1] >> 7) | (a->coeffs[8 * i + 2] << 2));
r[9 * i + 3] = (uint8_t) ((a->coeffs[8 * i + 2] >> 6) | (a->coeffs[8 * i + 3] << 3));
r[9 * i + 4] = (uint8_t) ((a->coeffs[8 * i + 3] >> 5) | (a->coeffs[8 * i + 4] << 4));
r[9 * i + 5] = (uint8_t) ((a->coeffs[8 * i + 4] >> 4) | (a->coeffs[8 * i + 5] << 5));
r[9 * i + 6] = (uint8_t) ((a->coeffs[8 * i + 5] >> 3) | (a->coeffs[8 * i + 6] << 6));
r[9 * i + 7] = (uint8_t) ((a->coeffs[8 * i + 6] >> 2) | (a->coeffs[8 * i + 7] << 7));
r[9 * i + 8] = (uint8_t) ((a->coeffs[8 * i + 7] >> 1));
}

}

/*************************************************
* Name: polyt1_unpack
*
* Description: Unpack polynomial t1 with 9-bit coefficients.
* Output coefficients are standard representatives.
*
* Arguments: - poly *r: pointer to output polynomial
* - const unsigned char *a: byte array with bit-packed polynomial
**************************************************/
void PQCLEAN_DILITHIUM4_CLEAN_polyt1_unpack(poly *r, const unsigned char *a) {
unsigned int i;

for (i = 0; i < N / 8; ++i) {
r->coeffs[8 * i + 0] = ((a[9 * i + 0] ) | ((uint32_t)a[9 * i + 1] << 8)) & 0x1FF;
r->coeffs[8 * i + 1] = ((a[9 * i + 1] >> 1) | ((uint32_t)a[9 * i + 2] << 7)) & 0x1FF;
r->coeffs[8 * i + 2] = ((a[9 * i + 2] >> 2) | ((uint32_t)a[9 * i + 3] << 6)) & 0x1FF;
r->coeffs[8 * i + 3] = ((a[9 * i + 3] >> 3) | ((uint32_t)a[9 * i + 4] << 5)) & 0x1FF;
r->coeffs[8 * i + 4] = ((a[9 * i + 4] >> 4) | ((uint32_t)a[9 * i + 5] << 4)) & 0x1FF;
r->coeffs[8 * i + 5] = ((a[9 * i + 5] >> 5) | ((uint32_t)a[9 * i + 6] << 3)) & 0x1FF;
r->coeffs[8 * i + 6] = ((a[9 * i + 6] >> 6) | ((uint32_t)a[9 * i + 7] << 2)) & 0x1FF;
r->coeffs[8 * i + 7] = ((a[9 * i + 7] >> 7) | ((uint32_t)a[9 * i + 8] << 1)) & 0x1FF;
}

}

/*************************************************
* Name: PQCLEAN_DILITHIUM4_CLEAN_polyt0_pack
*
* Description: Bit-pack polynomial t0 with coefficients in ]-2^{D-1}, 2^{D-1}].
* Input coefficients are assumed to lie in ]Q-2^{D-1}, Q+2^{D-1}].
*
* Arguments: - unsigned char *r: pointer to output byte array with at least
* POLT0_SIZE_PACKED bytes
* - const poly *a: pointer to input polynomial
**************************************************/
void PQCLEAN_DILITHIUM4_CLEAN_polyt0_pack(unsigned char *r, const poly *a) {
unsigned int i;
uint32_t t[4];

for (i = 0; i < N / 4; ++i) {
t[0] = Q + (1U << (D - 1)) - a->coeffs[4 * i + 0];
t[1] = Q + (1U << (D - 1)) - a->coeffs[4 * i + 1];
t[2] = Q + (1U << (D - 1)) - a->coeffs[4 * i + 2];
t[3] = Q + (1U << (D - 1)) - a->coeffs[4 * i + 3];

r[7 * i + 0] = (uint8_t) (t[0]);
r[7 * i + 1] = (uint8_t) (t[0] >> 8);
r[7 * i + 1] |= (uint8_t) (t[1] << 6);
r[7 * i + 2] = (uint8_t) (t[1] >> 2);
r[7 * i + 3] = (uint8_t) (t[1] >> 10);
r[7 * i + 3] |= (uint8_t) (t[2] << 4);
r[7 * i + 4] = (uint8_t) (t[2] >> 4);
r[7 * i + 5] = (uint8_t) (t[2] >> 12);
r[7 * i + 5] |= (uint8_t) (t[3] << 2);
r[7 * i + 6] = (uint8_t) (t[3] >> 6);
}

}

/*************************************************
* Name: PQCLEAN_DILITHIUM4_CLEAN_polyt0_unpack
*
* Description: Unpack polynomial t0 with coefficients in ]-2^{D-1}, 2^{D-1}].
* Output coefficients lie in ]Q-2^{D-1},Q+2^{D-1}].
*
* Arguments: - poly *r: pointer to output polynomial
* - const unsigned char *a: byte array with bit-packed polynomial
**************************************************/
void PQCLEAN_DILITHIUM4_CLEAN_polyt0_unpack(poly *r, const unsigned char *a) {
unsigned int i;

for (i = 0; i < N / 4; ++i) {
r->coeffs[4 * i + 0] = a[7 * i + 0];
r->coeffs[4 * i + 0] |= (uint32_t)(a[7 * i + 1] & 0x3F) << 8;

r->coeffs[4 * i + 1] = a[7 * i + 1] >> 6;
r->coeffs[4 * i + 1] |= (uint32_t)a[7 * i + 2] << 2;
r->coeffs[4 * i + 1] |= (uint32_t)(a[7 * i + 3] & 0x0F) << 10;

r->coeffs[4 * i + 2] = a[7 * i + 3] >> 4;
r->coeffs[4 * i + 2] |= (uint32_t)a[7 * i + 4] << 4;
r->coeffs[4 * i + 2] |= (uint32_t)(a[7 * i + 5] & 0x03) << 12;

r->coeffs[4 * i + 3] = a[7 * i + 5] >> 2;
r->coeffs[4 * i + 3] |= (uint32_t)a[7 * i + 6] << 6;

r->coeffs[4 * i + 0] = Q + (1U << (D - 1)) - r->coeffs[4 * i + 0];
r->coeffs[4 * i + 1] = Q + (1U << (D - 1)) - r->coeffs[4 * i + 1];
r->coeffs[4 * i + 2] = Q + (1U << (D - 1)) - r->coeffs[4 * i + 2];
r->coeffs[4 * i + 3] = Q + (1U << (D - 1)) - r->coeffs[4 * i + 3];
}

}

/*************************************************
* Name: PQCLEAN_DILITHIUM4_CLEAN_polyz_pack
*
* Description: Bit-pack polynomial z with coefficients
* in [-(GAMMA1 - 1), GAMMA1 - 1].
* Input coefficients are assumed to be standard representatives.
*
* Arguments: - unsigned char *r: pointer to output byte array with at least
* POLZ_SIZE_PACKED bytes
* - const poly *a: pointer to input polynomial
**************************************************/
void PQCLEAN_DILITHIUM4_CLEAN_polyz_pack(unsigned char *r, const poly *a) {
unsigned int i;
uint32_t t[2];

for (i = 0; i < N / 2; ++i) {
/* Map to {0,...,2*GAMMA1 - 2} */
t[0] = GAMMA1 - 1 - a->coeffs[2 * i + 0];
t[0] += ((int32_t)t[0] >> 31) & Q;
t[1] = GAMMA1 - 1 - a->coeffs[2 * i + 1];
t[1] += ((int32_t)t[1] >> 31) & Q;

r[5 * i + 0] = (uint8_t) (t[0]);
r[5 * i + 1] = (uint8_t) (t[0] >> 8);
r[5 * i + 2] = (uint8_t) (t[0] >> 16);
r[5 * i + 2] |= (uint8_t) (t[1] << 4);
r[5 * i + 3] = (uint8_t) (t[1] >> 4);
r[5 * i + 4] = (uint8_t) (t[1] >> 12);
}

}

/*************************************************
* Name: PQCLEAN_DILITHIUM4_CLEAN_polyz_unpack
*
* Description: Unpack polynomial z with coefficients
* in [-(GAMMA1 - 1), GAMMA1 - 1].
* Output coefficients are standard representatives.
*
* Arguments: - poly *r: pointer to output polynomial
* - const unsigned char *a: byte array with bit-packed polynomial
**************************************************/
void PQCLEAN_DILITHIUM4_CLEAN_polyz_unpack(poly *r, const unsigned char *a) {
unsigned int i;

for (i = 0; i < N / 2; ++i) {
r->coeffs[2 * i + 0] = a[5 * i + 0];
r->coeffs[2 * i + 0] |= (uint32_t)a[5 * i + 1] << 8;
r->coeffs[2 * i + 0] |= (uint32_t)(a[5 * i + 2] & 0x0F) << 16;

r->coeffs[2 * i + 1] = a[5 * i + 2] >> 4;
r->coeffs[2 * i + 1] |= (uint32_t)a[5 * i + 3] << 4;
r->coeffs[2 * i + 1] |= (uint32_t)a[5 * i + 4] << 12;

r->coeffs[2 * i + 0] = GAMMA1 - 1 - r->coeffs[2 * i + 0];
r->coeffs[2 * i + 0] += ((int32_t)r->coeffs[2 * i + 0] >> 31) & Q;
r->coeffs[2 * i + 1] = GAMMA1 - 1 - r->coeffs[2 * i + 1];
r->coeffs[2 * i + 1] += ((int32_t)r->coeffs[2 * i + 1] >> 31) & Q;
}

}

/*************************************************
* Name: PQCLEAN_DILITHIUM4_CLEAN_polyw1_pack
*
* Description: Bit-pack polynomial w1 with coefficients in [0, 15].
* Input coefficients are assumed to be standard representatives.
*
* Arguments: - unsigned char *r: pointer to output byte array with at least
* POLW1_SIZE_PACKED bytes
* - const poly *a: pointer to input polynomial
**************************************************/
void PQCLEAN_DILITHIUM4_CLEAN_polyw1_pack(unsigned char *r, const poly *a) {
unsigned int i;

for (i = 0; i < N / 2; ++i) {
r[i] = (uint8_t) (a->coeffs[2 * i + 0] | (a->coeffs[2 * i + 1] << 4));
}

}

+ 53
- 0
crypto_sign/dilithium4/clean/poly.h View File

@@ -0,0 +1,53 @@
#ifndef POLY_H
#define POLY_H

#include "params.h"
#include <stdint.h>

typedef struct {
uint32_t coeffs[N];
} poly;

void PQCLEAN_DILITHIUM4_CLEAN_poly_reduce(poly *a);
void PQCLEAN_DILITHIUM4_CLEAN_poly_csubq(poly *a);
void PQCLEAN_DILITHIUM4_CLEAN_poly_freeze(poly *a);

void PQCLEAN_DILITHIUM4_CLEAN_poly_add(poly *c, const poly *a, const poly *b);
void PQCLEAN_DILITHIUM4_CLEAN_poly_sub(poly *c, const poly *a, const poly *b);
void PQCLEAN_DILITHIUM4_CLEAN_poly_shiftl(poly *a);

void PQCLEAN_DILITHIUM4_CLEAN_poly_ntt(poly *a);
void PQCLEAN_DILITHIUM4_CLEAN_poly_invntt_montgomery(poly *a);
void PQCLEAN_DILITHIUM4_CLEAN_poly_pointwise_invmontgomery(poly *c, const poly *a, const poly *b);

void PQCLEAN_DILITHIUM4_CLEAN_poly_power2round(poly *a1, poly *a0, const poly *a);
void PQCLEAN_DILITHIUM4_CLEAN_poly_decompose(poly *a1, poly *a0, const poly *a);
unsigned int PQCLEAN_DILITHIUM4_CLEAN_poly_make_hint(poly *h, const poly *a0, const poly *a1);
void PQCLEAN_DILITHIUM4_CLEAN_poly_use_hint(poly *a, const poly *b, const poly *h);

int PQCLEAN_DILITHIUM4_CLEAN_poly_chknorm(const poly *a, uint32_t B);
void PQCLEAN_DILITHIUM4_CLEAN_poly_uniform(poly *a,
const unsigned char seed[SEEDBYTES],
uint16_t nonce);
void PQCLEAN_DILITHIUM4_CLEAN_poly_uniform_eta(poly *a,
const unsigned char seed[SEEDBYTES],
uint16_t nonce);
void PQCLEAN_DILITHIUM4_CLEAN_poly_uniform_gamma1m1(poly *a,
const unsigned char seed[CRHBYTES],
uint16_t nonce);

void PQCLEAN_DILITHIUM4_CLEAN_polyeta_pack(unsigned char *r, const poly *a);
void PQCLEAN_DILITHIUM4_CLEAN_polyeta_unpack(poly *r, const unsigned char *a);

void PQCLEAN_DILITHIUM4_CLEAN_polyt1_pack(unsigned char *r, const poly *a);
void PQCLEAN_DILITHIUM4_CLEAN_polyt1_unpack(poly *r, const unsigned char *a);

void PQCLEAN_DILITHIUM4_CLEAN_polyt0_pack(unsigned char *r, const poly *a);
void PQCLEAN_DILITHIUM4_CLEAN_polyt0_unpack(poly *r, const unsigned char *a);

void PQCLEAN_DILITHIUM4_CLEAN_polyz_pack(unsigned char *r, const poly *a);
void PQCLEAN_DILITHIUM4_CLEAN_polyz_unpack(poly *r, const unsigned char *a);

void PQCLEAN_DILITHIUM4_CLEAN_polyw1_pack(unsigned char *r, const poly *a);

#endif

+ 357
- 0
crypto_sign/dilithium4/clean/polyvec.c View File

@@ -0,0 +1,357 @@
#include "params.h"
#include "poly.h"
#include "polyvec.h"
#include <stdint.h>

/**************************************************************/
/************ Vectors of polynomials of length L **************/
/**************************************************************/

/*************************************************
* Name: polyvecl_freeze
*
* Description: Reduce coefficients of polynomials in vector of length L
* to standard representatives.
*
* Arguments: - polyvecl *v: pointer to input/output vector
**************************************************/
void PQCLEAN_DILITHIUM4_CLEAN_polyvecl_freeze(polyvecl *v) {
unsigned int i;

for (i = 0; i < L; ++i) {
PQCLEAN_DILITHIUM4_CLEAN_poly_freeze(&v->vec[i]);
}
}

/*************************************************
* Name: polyvecl_add
*
* Description: Add vectors of polynomials of length L.
* No modular reduction is performed.
*
* Arguments: - polyvecl *w: pointer to output vector
* - const polyvecl *u: pointer to first summand
* - const polyvecl *v: pointer to second summand
**************************************************/
void PQCLEAN_DILITHIUM4_CLEAN_polyvecl_add(polyvecl *w, const polyvecl *u, const polyvecl *v) {
unsigned int i;

for (i = 0; i < L; ++i) {
PQCLEAN_DILITHIUM4_CLEAN_poly_add(&w->vec[i], &u->vec[i], &v->vec[i]);
}
}

/*************************************************
* Name: polyvecl_ntt
*
* Description: Forward NTT of all polynomials in vector of length L. Output
* coefficients can be up to 16*Q larger than input coefficients.
*
* Arguments: - polyvecl *v: pointer to input/output vector
**************************************************/
void PQCLEAN_DILITHIUM4_CLEAN_polyvecl_ntt(polyvecl *v) {
unsigned int i;

for (i = 0; i < L; ++i) {
PQCLEAN_DILITHIUM4_CLEAN_poly_ntt(&v->vec[i]);
}
}

/*************************************************
* Name: polyvecl_pointwise_acc_invmontgomery
*
* Description: Pointwise multiply vectors of polynomials of length L, multiply
* resulting vector by 2^{-32} and add (accumulate) polynomials
* in it. Input/output vectors are in NTT domain representation.
* Input coefficients are assumed to be less than 22*Q. Output
* coeffcient are less than 2*L*Q.
*
* Arguments: - poly *w: output polynomial
* - const polyvecl *u: pointer to first input vector
* - const polyvecl *v: pointer to second input vector
**************************************************/
void PQCLEAN_DILITHIUM4_CLEAN_polyvecl_pointwise_acc_invmontgomery(poly *w,
const polyvecl *u,
const polyvecl *v) {
unsigned int i;
poly t;

PQCLEAN_DILITHIUM4_CLEAN_poly_pointwise_invmontgomery(w, &u->vec[0], &v->vec[0]);

for (i = 1; i < L; ++i) {
PQCLEAN_DILITHIUM4_CLEAN_poly_pointwise_invmontgomery(&t, &u->vec[i], &v->vec[i]);
PQCLEAN_DILITHIUM4_CLEAN_poly_add(w, w, &t);
}
}

/*************************************************
* Name: polyvecl_chknorm
*
* Description: Check infinity norm of polynomials in vector of length L.
* Assumes input coefficients to be standard representatives.
*
* Arguments: - const polyvecl *v: pointer to vector
* - uint32_t B: norm bound
*
* Returns 0 if norm of all polynomials is strictly smaller than B and 1
* otherwise.
**************************************************/
int PQCLEAN_DILITHIUM4_CLEAN_polyvecl_chknorm(const polyvecl *v, uint32_t bound) {
unsigned int i;

for (i = 0; i < L; ++i) {
if (PQCLEAN_DILITHIUM4_CLEAN_poly_chknorm(&v->vec[i], bound)) {
return 1;
}
}
return 0;
}

/**************************************************************/
/************ Vectors of polynomials of length K **************/
/**************************************************************/


/*************************************************
* Name: polyveck_reduce
*
* Description: Reduce coefficients of polynomials in vector of length K
* to representatives in [0,2*Q[.
*
* Arguments: - polyveck *v: pointer to input/output vector
**************************************************/
void PQCLEAN_DILITHIUM4_CLEAN_polyveck_reduce(polyveck *v) {
unsigned int i;

for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM4_CLEAN_poly_reduce(&v->vec[i]);
}
}

/*************************************************
* Name: polyveck_csubq
*
* Description: For all coefficients of polynomials in vector of length K
* subtract Q if coefficient is bigger than Q.
*
* Arguments: - polyveck *v: pointer to input/output vector
**************************************************/
void PQCLEAN_DILITHIUM4_CLEAN_polyveck_csubq(polyveck *v) {
unsigned int i;

for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM4_CLEAN_poly_csubq(&v->vec[i]);
}
}

/*************************************************
* Name: polyveck_freeze
*
* Description: Reduce coefficients of polynomials in vector of length K
* to standard representatives.
*
* Arguments: - polyveck *v: pointer to input/output vector
**************************************************/
void PQCLEAN_DILITHIUM4_CLEAN_polyveck_freeze(polyveck *v) {
unsigned int i;

for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM4_CLEAN_poly_freeze(&v->vec[i]);
}
}

/*************************************************
* Name: polyveck_add
*
* Description: Add vectors of polynomials of length K.
* No modular reduction is performed.
*
* Arguments: - polyveck *w: pointer to output vector
* - const polyveck *u: pointer to first summand
* - const polyveck *v: pointer to second summand
**************************************************/
void PQCLEAN_DILITHIUM4_CLEAN_polyveck_add(polyveck *w, const polyveck *u, const polyveck *v) {
unsigned int i;

for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM4_CLEAN_poly_add(&w->vec[i], &u->vec[i], &v->vec[i]);
}
}

/*************************************************
* Name: polyveck_sub
*
* Description: Subtract vectors of polynomials of length K.
* Assumes coefficients of polynomials in second input vector
* to be less than 2*Q. No modular reduction is performed.
*
* Arguments: - polyveck *w: pointer to output vector
* - const polyveck *u: pointer to first input vector
* - const polyveck *v: pointer to second input vector to be
* subtracted from first input vector
**************************************************/
void PQCLEAN_DILITHIUM4_CLEAN_polyveck_sub(polyveck *w, const polyveck *u, const polyveck *v) {
unsigned int i;

for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM4_CLEAN_poly_sub(&w->vec[i], &u->vec[i], &v->vec[i]);
}
}

/*************************************************
* Name: polyveck_shiftl
*
* Description: Multiply vector of polynomials of Length K by 2^D without modular
* reduction. Assumes input coefficients to be less than 2^{32-D}.
*
* Arguments: - polyveck *v: pointer to input/output vector
**************************************************/
void PQCLEAN_DILITHIUM4_CLEAN_polyveck_shiftl(polyveck *v) {
unsigned int i;

for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM4_CLEAN_poly_shiftl(&v->vec[i]);
}
}

/*************************************************
* Name: polyveck_ntt
*
* Description: Forward NTT of all polynomials in vector of length K. Output
* coefficients can be up to 16*Q larger than input coefficients.
*
* Arguments: - polyveck *v: pointer to input/output vector
**************************************************/
void PQCLEAN_DILITHIUM4_CLEAN_polyveck_ntt(polyveck *v) {
unsigned int i;

for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM4_CLEAN_poly_ntt(&v->vec[i]);
}
}

/*************************************************
* Name: polyveck_invntt_montgomery
*
* Description: Inverse NTT and multiplication by 2^{32} of polynomials
* in vector of length K. Input coefficients need to be less
* than 2*Q.
*
* Arguments: - polyveck *v: pointer to input/output vector
**************************************************/
void PQCLEAN_DILITHIUM4_CLEAN_polyveck_invntt_montgomery(polyveck *v) {
unsigned int i;

for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM4_CLEAN_poly_invntt_montgomery(&v->vec[i]);
}
}

/*************************************************
* Name: polyveck_chknorm
*
* Description: Check infinity norm of polynomials in vector of length K.
* Assumes input coefficients to be standard representatives.
*
* Arguments: - const polyveck *v: pointer to vector
* - uint32_t B: norm bound
*
* Returns 0 if norm of all polynomials are strictly smaller than B and 1
* otherwise.
**************************************************/
int PQCLEAN_DILITHIUM4_CLEAN_polyveck_chknorm(const polyveck *v, uint32_t bound) {
unsigned int i;

for (i = 0; i < K; ++i) {
if (PQCLEAN_DILITHIUM4_CLEAN_poly_chknorm(&v->vec[i], bound)) {
return 1;
}
}
return 0;
}

/*************************************************
* Name: polyveck_power2round
*
* Description: For all coefficients a of polynomials in vector of length K,
* compute a0, a1 such that a mod Q = a1*2^D + a0
* with -2^{D-1} < a0 <= 2^{D-1}. Assumes coefficients to be
* standard representatives.
*
* Arguments: - polyveck *v1: pointer to output vector of polynomials with
* coefficients a1
* - polyveck *v0: pointer to output vector of polynomials with
* coefficients Q + a0
* - const polyveck *v: pointer to input vector
**************************************************/
void PQCLEAN_DILITHIUM4_CLEAN_polyveck_power2round(polyveck *v1, polyveck *v0, const polyveck *v) {
unsigned int i;

for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM4_CLEAN_poly_power2round(&v1->vec[i], &v0->vec[i], &v->vec[i]);
}
}

/*************************************************
* Name: polyveck_decompose
*
* Description: For all coefficients a of polynomials in vector of length K,
* compute high and low bits a0, a1 such a mod Q = a1*ALPHA + a0
* with -ALPHA/2 < a0 <= ALPHA/2 except a1 = (Q-1)/ALPHA where we
* set a1 = 0 and -ALPHA/2 <= a0 = a mod Q - Q < 0.
* Assumes coefficients to be standard representatives.
*
* Arguments: - polyveck *v1: pointer to output vector of polynomials with
* coefficients a1
* - polyveck *v0: pointer to output vector of polynomials with
* coefficients Q + a0
* - const polyveck *v: pointer to input vector
**************************************************/
void PQCLEAN_DILITHIUM4_CLEAN_polyveck_decompose(polyveck *v1, polyveck *v0, const polyveck *v) {
unsigned int i;

for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM4_CLEAN_poly_decompose(&v1->vec[i], &v0->vec[i], &v->vec[i]);
}
}

/*************************************************
* Name: polyveck_make_hint
*
* Description: Compute hint vector.
*
* Arguments: - polyveck *h: pointer to output vector
* - const polyveck *v0: pointer to low part of input vector
* - const polyveck *v1: pointer to high part of input vector
*
* Returns number of 1 bits.
**************************************************/
unsigned int PQCLEAN_DILITHIUM4_CLEAN_polyveck_make_hint(polyveck *h,
const polyveck *v0,
const polyveck *v1) {
unsigned int i, s = 0;

for (i = 0; i < K; ++i) {
s += PQCLEAN_DILITHIUM4_CLEAN_poly_make_hint(&h->vec[i], &v0->vec[i], &v1->vec[i]);
}

return s;
}

/*************************************************
* Name: polyveck_use_hint
*
* Description: Use hint vector to correct the high bits of input vector.
*
* Arguments: - polyveck *w: pointer to output vector of polynomials with
* corrected high bits
* - const polyveck *u: pointer to input vector
* - const polyveck *h: pointer to input hint vector
**************************************************/
void PQCLEAN_DILITHIUM4_CLEAN_polyveck_use_hint(polyveck *w, const polyveck *u, const polyveck *h) {
unsigned int i;

for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM4_CLEAN_poly_use_hint(&w->vec[i], &u->vec[i], &h->vec[i]);
}
}

+ 51
- 0
crypto_sign/dilithium4/clean/polyvec.h View File

@@ -0,0 +1,51 @@
#ifndef POLYVEC_H
#define POLYVEC_H

#include "params.h"
#include "poly.h"
#include <stdint.h>

/* Vectors of polynomials of length L */
typedef struct {
poly vec[L];
} polyvecl;

void PQCLEAN_DILITHIUM4_CLEAN_polyvecl_freeze(polyvecl *v);

void PQCLEAN_DILITHIUM4_CLEAN_polyvecl_add(polyvecl *w, const polyvecl *u, const polyvecl *v);

void PQCLEAN_DILITHIUM4_CLEAN_polyvecl_ntt(polyvecl *v);
void PQCLEAN_DILITHIUM4_CLEAN_polyvecl_pointwise_acc_invmontgomery(poly *w,
const polyvecl *u,
const polyvecl *v);

int PQCLEAN_DILITHIUM4_CLEAN_polyvecl_chknorm(const polyvecl *v, uint32_t B);



/* Vectors of polynomials of length K */
typedef struct {
poly vec[K];
} polyveck;

void PQCLEAN_DILITHIUM4_CLEAN_polyveck_reduce(polyveck *v);
void PQCLEAN_DILITHIUM4_CLEAN_polyveck_csubq(polyveck *v);
void PQCLEAN_DILITHIUM4_CLEAN_polyveck_freeze(polyveck *v);

void PQCLEAN_DILITHIUM4_CLEAN_polyveck_add(polyveck *w, const polyveck *u, const polyveck *v);
void PQCLEAN_DILITHIUM4_CLEAN_polyveck_sub(polyveck *w, const polyveck *u, const polyveck *v);
void PQCLEAN_DILITHIUM4_CLEAN_polyveck_shiftl(polyveck *v);

void PQCLEAN_DILITHIUM4_CLEAN_polyveck_ntt(polyveck *v);
void PQCLEAN_DILITHIUM4_CLEAN_polyveck_invntt_montgomery(polyveck *v);

int PQCLEAN_DILITHIUM4_CLEAN_polyveck_chknorm(const polyveck *v, uint32_t B);

void PQCLEAN_DILITHIUM4_CLEAN_polyveck_power2round(polyveck *v1, polyveck *v0, const polyveck *v);
void PQCLEAN_DILITHIUM4_CLEAN_polyveck_decompose(polyveck *v1, polyveck *v0, const polyveck *v);
unsigned int PQCLEAN_DILITHIUM4_CLEAN_polyveck_make_hint(polyveck *h,
const polyveck *v0,
const polyveck *v1);
void PQCLEAN_DILITHIUM4_CLEAN_polyveck_use_hint(polyveck *w, const polyveck *u, const polyveck *h);

#endif

+ 74
- 0
crypto_sign/dilithium4/clean/reduce.c View File

@@ -0,0 +1,74 @@
#include "params.h"
#include "reduce.h"
#include <stdint.h>

/*************************************************
* Name: montgomery_reduce
*
* Description: For finite field element a with 0 <= a <= Q*2^32,
* compute r \equiv a*2^{-32} (mod Q) such that 0 <= r < 2*Q.
*
* Arguments: - uint64_t: finite field element a
*
* Returns r.
**************************************************/
uint32_t PQCLEAN_DILITHIUM4_CLEAN_montgomery_reduce(uint64_t a) {
uint64_t t;

t = a * QINV;
t &= (1ULL << 32) - 1;
t *= Q;
t = a + t;
t >>= 32;
return (uint32_t) t;
}

/*************************************************
* Name: reduce32
*
* Description: For finite field element a, compute r \equiv a (mod Q)
* such that 0 <= r < 2*Q.
*
* Arguments: - uint32_t: finite field element a
*
* Returns r.
**************************************************/
uint32_t PQCLEAN_DILITHIUM4_CLEAN_reduce32(uint32_t a) {
uint32_t t;

t = a & 0x7FFFFF;
a >>= 23;
t += (a << 13) - a;
return t;
}

/*************************************************
* Name: csubq
*
* Description: Subtract Q if input coefficient is bigger than Q.
*
* Arguments: - uint32_t: finite field element a
*
* Returns r.
**************************************************/
uint32_t PQCLEAN_DILITHIUM4_CLEAN_csubq(uint32_t a) {
a -= Q;
a += ((int32_t)a >> 31) & Q;
return a;
}

/*************************************************
* Name: freeze
*
* Description: For finite field element a, compute standard
* representative r = a mod Q.
*
* Arguments: - uint32_t: finite field element a
*
* Returns r.
**************************************************/
uint32_t PQCLEAN_DILITHIUM4_CLEAN_freeze(uint32_t a) {
a = PQCLEAN_DILITHIUM4_CLEAN_reduce32(a);
a = PQCLEAN_DILITHIUM4_CLEAN_csubq(a);
return a;
}

+ 21
- 0
crypto_sign/dilithium4/clean/reduce.h View File

@@ -0,0 +1,21 @@
#ifndef REDUCE_H
#define REDUCE_H

#include <stdint.h>

#define MONT 4193792U // 2^32 % Q
#define QINV 4236238847U // -q^(-1) mod 2^32

/* a <= Q*2^32 => r < 2*Q */
uint32_t PQCLEAN_DILITHIUM4_CLEAN_montgomery_reduce(uint64_t a);

/* r < 2*Q */
uint32_t PQCLEAN_DILITHIUM4_CLEAN_reduce32(uint32_t a);

/* a < 2*Q => r < Q */
uint32_t PQCLEAN_DILITHIUM4_CLEAN_csubq(uint32_t a);

/* r < Q */
uint32_t PQCLEAN_DILITHIUM4_CLEAN_freeze(uint32_t a);

#endif

+ 105
- 0
crypto_sign/dilithium4/clean/rounding.c View File

@@ -0,0 +1,105 @@
#include "params.h"
#include "rounding.h"
/*************************************************
* Name: power2round
*
* Description: For finite field element a, compute a0, a1 such that
* a mod Q = a1*2^D + a0 with -2^{D-1} < a0 <= 2^{D-1}.
* Assumes a to be standard representative.
*
* Arguments: - uint32_t a: input element
* - uint32_t *a0: pointer to output element Q + a0
*
* Returns a1.
**************************************************/
uint32_t PQCLEAN_DILITHIUM4_CLEAN_power2round(uint32_t a, uint32_t *a0) {
uint32_t t;

/* Centralized remainder mod 2^D */
t = a & ((1U << D) - 1);
t -= ((1U << (D - 1)) + 1);
t += ((uint32_t)((int32_t)t >> 31) & (1U << D));
t -= ((1U << (D - 1)) - 1);
*a0 = (Q + t);
a = (a - t) >> D;
return a;
}

/*************************************************
* Name: decompose
*
* Description: For finite field element a, compute high and low bits a0, a1 such
* that a mod Q = a1*ALPHA + a0 with -ALPHA/2 < a0 <= ALPHA/2 except
* if a1 = (Q-1)/ALPHA where we set a1 = 0 and
* -ALPHA/2 <= a0 = a mod Q - Q < 0. Assumes a to be standard
* representative.
*
* Arguments: - uint32_t a: input element
* - uint32_t *a0: pointer to output element Q + a0
*
* Returns a1.
**************************************************/
uint32_t PQCLEAN_DILITHIUM4_CLEAN_decompose(uint32_t a, uint32_t *a0) {
int32_t t, u;
/* Centralized remainder mod ALPHA */
t = a & 0x7FFFF;
t += (int32_t) ((a >> 19) << 9);
t -= ALPHA / 2 + 1;
t += (t >> 31) & ALPHA;
t -= ALPHA / 2 - 1;
a -= (uint32_t) t;

/* Divide by ALPHA (possible to avoid) */
u = (int32_t) a - 1;
u >>= 31;
a = (a >> 19) + 1;
a -= u & 1;

/* Border case */
*a0 = Q + (uint32_t)t - (a >> 4);
a &= 0xF;
return a;
}

/*************************************************
* Name: make_hint
*
* Description: Compute hint bit indicating whether the low bits of the
* input element overflow into the high bits. Inputs assumed to be
* standard representatives.
*
* Arguments: - uint32_t a0: low bits of input element
* - uint32_t a1: high bits of input element
*
* Returns 1 if high bits of a and b differ and 0 otherwise.
**************************************************/
unsigned int PQCLEAN_DILITHIUM4_CLEAN_make_hint(uint32_t a0, uint32_t a1) {
if (a0 <= GAMMA2 || a0 > Q - GAMMA2 || (a0 == Q - GAMMA2 && a1 == 0)) {
return 0;
}

return 1;
}

/*************************************************
* Name: use_hint
*
* Description: Correct high bits according to hint.
*
* Arguments: - uint32_t a: input element
* - unsigned int hint: hint bit
*
* Returns corrected high bits.
**************************************************/
uint32_t PQCLEAN_DILITHIUM4_CLEAN_use_hint(uint32_t a, unsigned int hint) {
uint32_t a0, a1;

a1 = PQCLEAN_DILITHIUM4_CLEAN_decompose(a, &a0);
if (hint == 0) {
return a1;
}
if (a0 > Q) {
return (a1 + 1) & 0xF;
}
return (a1 - 1) & 0xF;
}

+ 11
- 0
crypto_sign/dilithium4/clean/rounding.h View File

@@ -0,0 +1,11 @@
#ifndef ROUNDING_H
#define ROUNDING_H

#include <stdint.h>

uint32_t PQCLEAN_DILITHIUM4_CLEAN_power2round(uint32_t a, uint32_t *a0);
uint32_t PQCLEAN_DILITHIUM4_CLEAN_decompose(uint32_t a, uint32_t *a0);
unsigned int PQCLEAN_DILITHIUM4_CLEAN_make_hint(uint32_t a0, uint32_t a1);
uint32_t PQCLEAN_DILITHIUM4_CLEAN_use_hint(uint32_t a, unsigned int hint);

#endif

+ 414
- 0
crypto_sign/dilithium4/clean/sign.c View File

@@ -0,0 +1,414 @@
#include "fips202.h"
#include "packing.h"
#include "params.h"
#include "poly.h"
#include "polyvec.h"
#include "randombytes.h"
#include "sign.h"
#include "symmetric.h"

#include <stdint.h>

/*************************************************
* Name: expand_mat
*
* Description: Implementation of ExpandA. Generates matrix A with uniformly
* random coefficients a_{i,j} by performing rejection
* sampling on the output stream of SHAKE128(rho|i|j).
*
* Arguments: - polyvecl mat[K]: output matrix
* - const unsigned char rho[]: byte array containing seed rho
**************************************************/
void PQCLEAN_DILITHIUM4_CLEAN_expand_mat(polyvecl mat[K], const unsigned char rho[SEEDBYTES]) {
unsigned int i, j;

for (i = 0; i < K; ++i) {
for (j = 0; j < L; ++j) {
PQCLEAN_DILITHIUM4_CLEAN_poly_uniform(&mat[i].vec[j], rho, (uint16_t)((i << 8) + j));
}
}
}

/*************************************************
* Name: challenge
*
* Description: Implementation of H. Samples polynomial with 60 nonzero
* coefficients in {-1,1} using the output stream of
* SHAKE256(mu|w1).
*
* Arguments: - poly *c: pointer to output polynomial
* - const unsigned char mu[]: byte array containing mu
* - const polyveck *w1: pointer to vector w1
**************************************************/
void PQCLEAN_DILITHIUM4_CLEAN_challenge(poly *c,
const unsigned char mu[CRHBYTES],
const polyveck *w1) {
unsigned int i, b, pos;
uint64_t signs;
unsigned char inbuf[CRHBYTES + K * POLW1_SIZE_PACKED];
unsigned char outbuf[SHAKE256_RATE];
shake256ctx state;

for (i = 0; i < CRHBYTES; ++i) {
inbuf[i] = mu[i];
}
for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM4_CLEAN_polyw1_pack(inbuf + CRHBYTES + i * POLW1_SIZE_PACKED, &w1->vec[i]);
}

shake256_absorb(&state, inbuf, sizeof(inbuf));
shake256_squeezeblocks(outbuf, 1, &state);

signs = 0;
for (i = 0; i < 8; ++i) {
signs |= (uint64_t)outbuf[i] << 8 * i;
}

pos = 8;

for (i = 0; i < N; ++i) {
c->coeffs[i] = 0;
}

for (i = 196; i < 256; ++i) {
do {
if (pos >= SHAKE256_RATE) {
shake256_squeezeblocks(outbuf, 1, &state);
pos = 0;
}

b = outbuf[pos++];
} while (b > i);

c->coeffs[i] = c->coeffs[b];
c->coeffs[b] = 1;
c->coeffs[b] ^= -((int32_t)signs & 1) & (1 ^ (Q - 1));
signs >>= 1;
}
}

/*************************************************
* Name: crypto_sign_keypair
*
* Description: Generates public and private key.
*
* Arguments: - unsigned char *pk: pointer to output public key (allocated
* array of CRYPTO_PUBLICKEYBYTES bytes)
* - unsigned char *sk: pointer to output private key (allocated
* array of CRYPTO_SECRETKEYBYTES bytes)
*
* Returns 0 (success)
**************************************************/
int PQCLEAN_DILITHIUM4_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk) {
unsigned int i;
unsigned char seedbuf[3 * SEEDBYTES];
unsigned char tr[CRHBYTES];
const unsigned char *rho, *rhoprime, *key;
uint16_t nonce = 0;
polyvecl mat[K];
polyvecl s1, s1hat;
polyveck s2, t, t1, t0;

/* Expand 32 bytes of randomness into rho, rhoprime and key */
randombytes(seedbuf, 3 * SEEDBYTES);
rho = seedbuf;
rhoprime = seedbuf + SEEDBYTES;
key = seedbuf + 2 * SEEDBYTES;

/* Expand matrix */
PQCLEAN_DILITHIUM4_CLEAN_expand_mat(mat, rho);

/* Sample short vectors s1 and s2 */
for (i = 0; i < L; ++i) {
PQCLEAN_DILITHIUM4_CLEAN_poly_uniform_eta(&s1.vec[i], rhoprime, nonce++);
}
for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM4_CLEAN_poly_uniform_eta(&s2.vec[i], rhoprime, nonce++);
}

/* Matrix-vector multiplication */
s1hat = s1;
PQCLEAN_DILITHIUM4_CLEAN_polyvecl_ntt(&s1hat);
for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM4_CLEAN_polyvecl_pointwise_acc_invmontgomery(&t.vec[i], &mat[i], &s1hat);
PQCLEAN_DILITHIUM4_CLEAN_poly_reduce(&t.vec[i]);
PQCLEAN_DILITHIUM4_CLEAN_poly_invntt_montgomery(&t.vec[i]);
}

/* Add error vector s2 */
PQCLEAN_DILITHIUM4_CLEAN_polyveck_add(&t, &t, &s2);

/* Extract t1 and write public key */
PQCLEAN_DILITHIUM4_CLEAN_polyveck_freeze(&t);
PQCLEAN_DILITHIUM4_CLEAN_polyveck_power2round(&t1, &t0, &t);
PQCLEAN_DILITHIUM4_CLEAN_pack_pk(pk, rho, &t1);

/* Compute CRH(rho, t1) and write secret key */
crh(tr, pk, CRYPTO_PUBLICKEYBYTES);
PQCLEAN_DILITHIUM4_CLEAN_pack_sk(sk, rho, key, tr, &s1, &s2, &t0);

return 0;
}

int PQCLEAN_DILITHIUM4_CLEAN_crypto_sign_signature(
uint8_t *sig, size_t *siglen,
const uint8_t *m, size_t mlen, const uint8_t *sk) {
unsigned long long i;
unsigned int n;
unsigned char seedbuf[2 * SEEDBYTES + 3 * CRHBYTES];
unsigned char *rho, *tr, *key, *mu, *rhoprime;
uint16_t nonce = 0;
poly c, chat;
polyvecl mat[K], s1, y, yhat, z;
polyveck t0, s2, w, w1, w0;
polyveck h, cs2, ct0;

rho = seedbuf;
tr = rho + SEEDBYTES;
key = tr + CRHBYTES;
mu = key + SEEDBYTES;
rhoprime = mu + CRHBYTES;
PQCLEAN_DILITHIUM4_CLEAN_unpack_sk(rho, key, tr, &s1, &s2, &t0, sk);


// use incremental hash API instead of copying around buffers
/* Compute CRH(tr, msg) */
shake256incctx state;
shake256_inc_init(&state);
shake256_inc_absorb(&state, tr, CRHBYTES);
shake256_inc_absorb(&state, m, mlen);
shake256_inc_finalize(&state);
shake256_inc_squeeze(mu, CRHBYTES, &state);


for (i = 0; i < CRHBYTES; ++i) {
sig[CRYPTO_BYTES - CRHBYTES + i] = tr[i];
}

crh(rhoprime, key, SEEDBYTES + CRHBYTES);

/* Expand matrix and transform vectors */
PQCLEAN_DILITHIUM4_CLEAN_expand_mat(mat, rho);
PQCLEAN_DILITHIUM4_CLEAN_polyvecl_ntt(&s1);
PQCLEAN_DILITHIUM4_CLEAN_polyveck_ntt(&s2);
PQCLEAN_DILITHIUM4_CLEAN_polyveck_ntt(&t0);

rej:
/* Sample intermediate vector y */
for (i = 0; i < L; ++i) {
PQCLEAN_DILITHIUM4_CLEAN_poly_uniform_gamma1m1(&y.vec[i], rhoprime, nonce++);
}

/* Matrix-vector multiplication */
yhat = y;
PQCLEAN_DILITHIUM4_CLEAN_polyvecl_ntt(&yhat);
for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM4_CLEAN_polyvecl_pointwise_acc_invmontgomery(&w.vec[i], &mat[i], &yhat);
PQCLEAN_DILITHIUM4_CLEAN_poly_reduce(&w.vec[i]);
PQCLEAN_DILITHIUM4_CLEAN_poly_invntt_montgomery(&w.vec[i]);
}

/* Decompose w and call the random oracle */
PQCLEAN_DILITHIUM4_CLEAN_polyveck_csubq(&w);
PQCLEAN_DILITHIUM4_CLEAN_polyveck_decompose(&w1, &w0, &w);
PQCLEAN_DILITHIUM4_CLEAN_challenge(&c, mu, &w1);
chat = c;
PQCLEAN_DILITHIUM4_CLEAN_poly_ntt(&chat);

/* Check that subtracting cs2 does not change high bits of w and low bits
* do not reveal secret information */
for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM4_CLEAN_poly_pointwise_invmontgomery(&cs2.vec[i], &chat, &s2.vec[i]);
PQCLEAN_DILITHIUM4_CLEAN_poly_invntt_montgomery(&cs2.vec[i]);
}
PQCLEAN_DILITHIUM4_CLEAN_polyveck_sub(&w0, &w0, &cs2);
PQCLEAN_DILITHIUM4_CLEAN_polyveck_freeze(&w0);
if (PQCLEAN_DILITHIUM4_CLEAN_polyveck_chknorm(&w0, GAMMA2 - BETA)) {
goto rej;
}

/* Compute z, reject if it reveals secret */
for (i = 0; i < L; ++i) {
PQCLEAN_DILITHIUM4_CLEAN_poly_pointwise_invmontgomery(&z.vec[i], &chat, &s1.vec[i]);
PQCLEAN_DILITHIUM4_CLEAN_poly_invntt_montgomery(&z.vec[i]);
}
PQCLEAN_DILITHIUM4_CLEAN_polyvecl_add(&z, &z, &y);
PQCLEAN_DILITHIUM4_CLEAN_polyvecl_freeze(&z);
if (PQCLEAN_DILITHIUM4_CLEAN_polyvecl_chknorm(&z, GAMMA1 - BETA)) {
goto rej;
}

/* Compute hints for w1 */
for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM4_CLEAN_poly_pointwise_invmontgomery(&ct0.vec[i], &chat, &t0.vec[i]);
PQCLEAN_DILITHIUM4_CLEAN_poly_invntt_montgomery(&ct0.vec[i]);
}

PQCLEAN_DILITHIUM4_CLEAN_polyveck_csubq(&ct0);
if (PQCLEAN_DILITHIUM4_CLEAN_polyveck_chknorm(&ct0, GAMMA2)) {
goto rej;
}

PQCLEAN_DILITHIUM4_CLEAN_polyveck_add(&w0, &w0, &ct0);
PQCLEAN_DILITHIUM4_CLEAN_polyveck_csubq(&w0);
n = PQCLEAN_DILITHIUM4_CLEAN_polyveck_make_hint(&h, &w0, &w1);
if (n > OMEGA) {
goto rej;
}

/* Write signature */
PQCLEAN_DILITHIUM4_CLEAN_pack_sig(sig, &z, &h, &c);

*siglen = CRYPTO_BYTES;
return 0;
}

int PQCLEAN_DILITHIUM4_CLEAN_crypto_sign_verify(
const uint8_t *sig, size_t siglen,
const uint8_t *m, size_t mlen, const uint8_t *pk) {
unsigned long long i;
unsigned char rho[SEEDBYTES];
unsigned char mu[CRHBYTES];
poly c, chat, cp;
polyvecl mat[K], z;
polyveck t1, w1, h, tmp1, tmp2;

if (siglen < CRYPTO_BYTES) {
return -1;
}

PQCLEAN_DILITHIUM4_CLEAN_unpack_pk(rho, &t1, pk);
if (PQCLEAN_DILITHIUM4_CLEAN_unpack_sig(&z, &h, &c, sig)) {
return -1;
}
if (PQCLEAN_DILITHIUM4_CLEAN_polyvecl_chknorm(&z, GAMMA1 - BETA)) {
return -1;
}

/* Compute CRH(CRH(rho, t1), msg) */
shake256incctx state;
shake256_inc_init(&state);
shake256_inc_absorb(&state, pk, CRYPTO_PUBLICKEYBYTES);
shake256_inc_finalize(&state);
shake256_inc_squeeze(mu, CRHBYTES, &state);

shake256_inc_init(&state);
shake256_inc_absorb(&state, mu, CRHBYTES);
shake256_inc_absorb(&state, m, mlen);
shake256_inc_finalize(&state);
shake256_inc_squeeze(mu, CRHBYTES, &state);


/* Matrix-vector multiplication; compute Az - c2^dt1 */
PQCLEAN_DILITHIUM4_CLEAN_expand_mat(mat, rho);

PQCLEAN_DILITHIUM4_CLEAN_polyvecl_ntt(&z);
for (i = 0; i < K ; ++i) {
PQCLEAN_DILITHIUM4_CLEAN_polyvecl_pointwise_acc_invmontgomery(&tmp1.vec[i], &mat[i], &z);
}

chat = c;
PQCLEAN_DILITHIUM4_CLEAN_poly_ntt(&chat);
PQCLEAN_DILITHIUM4_CLEAN_polyveck_shiftl(&t1);
PQCLEAN_DILITHIUM4_CLEAN_polyveck_ntt(&t1);
for (i = 0; i < K; ++i) {
PQCLEAN_DILITHIUM4_CLEAN_poly_pointwise_invmontgomery(&tmp2.vec[i], &chat, &t1.vec[i]);
}

PQCLEAN_DILITHIUM4_CLEAN_polyveck_sub(&tmp1, &tmp1, &tmp2);
PQCLEAN_DILITHIUM4_CLEAN_polyveck_reduce(&tmp1);
PQCLEAN_DILITHIUM4_CLEAN_polyveck_invntt_montgomery(&tmp1);

/* Reconstruct w1 */
PQCLEAN_DILITHIUM4_CLEAN_polyveck_csubq(&tmp1);
PQCLEAN_DILITHIUM4_CLEAN_polyveck_use_hint(&w1, &tmp1, &h);

/* Call random oracle and verify challenge */
PQCLEAN_DILITHIUM4_CLEAN_challenge(&cp, mu, &w1);
for (i = 0; i < N; ++i) {
if (c.coeffs[i] != cp.coeffs[i]) {
return -1;
}
}

// All good
return 0;
}
/*************************************************
* Name: crypto_sign
*
* Description: Compute signed message.
*
* Arguments: - unsigned char *sm: pointer to output signed message (allocated
* array with CRYPTO_BYTES + mlen bytes),
* can be equal to m
* - unsigned long long *smlen: pointer to output length of signed
* message
* - const unsigned char *m: pointer to message to be signed
* - unsigned long long mlen: length of message
* - const unsigned char *sk: pointer to bit-packed secret key
*
* Returns 0 (success)
**************************************************/
int PQCLEAN_DILITHIUM4_CLEAN_crypto_sign(uint8_t *sm,
size_t *smlen,
const uint8_t *m,
size_t mlen,
const uint8_t *sk) {
size_t i;
int rc;
for (i = 0; i < mlen; i++) {
sm[CRYPTO_BYTES + i] = m[i];
}
rc = PQCLEAN_DILITHIUM4_CLEAN_crypto_sign_signature(sm, smlen, m, mlen, sk);
*smlen += mlen;
return rc;

}

/*************************************************
* Name: crypto_sign_open
*
* Description: Verify signed message.
*
* Arguments: - unsigned char *m: pointer to output message (allocated
* array with smlen bytes), can be equal to sm
* - unsigned long long *mlen: pointer to output length of message
* - const unsigned char *sm: pointer to signed message
* - unsigned long long smlen: length of signed message
* - const unsigned char *sk: pointer to bit-packed public key
*
* Returns 0 if signed message could be verified correctly and -1 otherwise
**************************************************/
int PQCLEAN_DILITHIUM4_CLEAN_crypto_sign_open(uint8_t *m,
size_t *mlen,
const uint8_t *sm,
size_t smlen,
const uint8_t *pk) {
size_t i;
if (smlen < CRYPTO_BYTES) {
goto badsig;
}
*mlen = smlen - CRYPTO_BYTES;

if (PQCLEAN_DILITHIUM4_CLEAN_crypto_sign_verify(sm, CRYPTO_BYTES,
sm + CRYPTO_BYTES, *mlen, pk)) {
goto badsig;
} else {
/* All good, copy msg, return 0 */
for (i = 0; i < *mlen; ++i) {
m[i] = sm[CRYPTO_BYTES + i];
}
return 0;
}

/* Signature verification failed */
badsig:
*mlen = (size_t) -1;
for (i = 0; i < smlen; ++i) {
m[i] = 0;
}

return -1;
}


+ 30
- 0
crypto_sign/dilithium4/clean/sign.h View File

@@ -0,0 +1,30 @@
#ifndef SIGN_H
#define SIGN_H

#include "params.h"
#include "poly.h"
#include "polyvec.h"

void PQCLEAN_DILITHIUM4_CLEAN_expand_mat(polyvecl mat[K], const unsigned char rho[SEEDBYTES]);
void PQCLEAN_DILITHIUM4_CLEAN_challenge(poly *c, const unsigned char mu[CRHBYTES],
const polyveck *w1);

int PQCLEAN_DILITHIUM4_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk);

int PQCLEAN_DILITHIUM4_CLEAN_crypto_sign_signature(
uint8_t *sig, size_t *siglen,
const uint8_t *m, size_t mlen, const uint8_t *sk);

int PQCLEAN_DILITHIUM4_CLEAN_crypto_sign_verify(
const uint8_t *sig, size_t siglen,
const uint8_t *m, size_t mlen, const uint8_t *pk);

int PQCLEAN_DILITHIUM4_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen,
const uint8_t *msg, size_t len,
const uint8_t *sk);

int PQCLEAN_DILITHIUM4_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen,
const uint8_t *sm, size_t smlen,
const uint8_t *pk);

#endif

+ 32
- 0
crypto_sign/dilithium4/clean/symmetric.c View File

@@ -0,0 +1,32 @@
#include "symmetric.h"
#include "fips202.h"

void PQCLEAN_DILITHIUM4_CLEAN_shake128_stream_init(shake128ctx *state,
const unsigned char seed[SEEDBYTES],
uint16_t nonce) {
unsigned int i;
unsigned char buf[SEEDBYTES + 2];

for (i = 0; i < SEEDBYTES; ++i) {
buf[i] = seed[i];
}
buf[SEEDBYTES] = (uint8_t) nonce;
buf[SEEDBYTES + 1] = (uint8_t) (nonce >> 8);

shake128_absorb(state, buf, sizeof(buf));
}

void PQCLEAN_DILITHIUM4_CLEAN_shake256_stream_init(shake256ctx *state,
const unsigned char seed[CRHBYTES],
uint16_t nonce) {
unsigned int i;
unsigned char buf[CRHBYTES + 2];

for (i = 0; i < CRHBYTES; ++i) {
buf[i] = seed[i];
}
buf[CRHBYTES] = (uint8_t) nonce;
buf[CRHBYTES + 1] = (uint8_t) (nonce >> 8);

shake256_absorb(state, buf, sizeof(buf));
}

+ 23
- 0
crypto_sign/dilithium4/clean/symmetric.h View File

@@ -0,0 +1,23 @@
#ifndef SYMMETRIC_H
#define SYMMETRIC_H

#include "fips202.h"
#include "params.h"

#define crh(OUT, IN, INBYTES) shake256(OUT, CRHBYTES, IN, INBYTES)
#define stream128_init(STATE, SEED, NONCE) PQCLEAN_DILITHIUM4_CLEAN_shake128_stream_init(STATE, SEED, NONCE)
#define stream128_squeezeblocks(OUT, OUTBLOCKS, STATE) shake128_squeezeblocks(OUT, OUTBLOCKS, STATE)
#define stream256_init(STATE, SEED, NONCE) PQCLEAN_DILITHIUM4_CLEAN_shake256_stream_init(STATE, SEED, NONCE)
#define stream256_squeezeblocks(OUT, OUTBLOCKS, STATE) shake256_squeezeblocks(OUT, OUTBLOCKS, STATE)

#define STREAM128_BLOCKBYTES SHAKE128_RATE
#define STREAM256_BLOCKBYTES SHAKE256_RATE

void PQCLEAN_DILITHIUM4_CLEAN_shake128_stream_init(shake128ctx *state,
const unsigned char *seed,
uint16_t nonce);
void PQCLEAN_DILITHIUM4_CLEAN_shake256_stream_init(shake256ctx *state,
const unsigned char *seed,
uint16_t nonce);

#endif

+ 40
- 0
test/duplicate_consistency/dilithium2_clean.yml View File

@@ -0,0 +1,40 @@
consistency_checks:
- source:
scheme: dilithium3
implementation: clean
files:
- ntt.c
- ntt.h
- packing.c
- packing.h
- poly.c
- poly.h
- polyvec.c
- polyvec.h
- reduce.c
- reduce.h
- rounding.c
- rounding.h
- sign.c
- sign.h
- symmetric.c
- symmetric.h
- source:
scheme: dilithium4
implementation: clean
files:
- ntt.c
- ntt.h
- packing.c
- packing.h
- poly.h
- polyvec.c
- polyvec.h
- reduce.c
- reduce.h
- rounding.c
- rounding.h
- sign.c
- sign.h
- symmetric.c
- symmetric.h

+ 40
- 0
test/duplicate_consistency/dilithium3_clean.yml View File

@@ -0,0 +1,40 @@
consistency_checks:
- source:
scheme: dilithium2
implementation: clean
files:
- ntt.c
- ntt.h
- packing.c
- packing.h
- poly.c
- poly.h
- polyvec.c
- polyvec.h
- reduce.c
- reduce.h
- rounding.c
- rounding.h
- sign.c
- sign.h
- symmetric.c
- symmetric.h
- source:
scheme: dilithium4
implementation: clean
files:
- ntt.c
- ntt.h
- packing.c
- packing.h
- poly.h
- polyvec.c
- polyvec.h
- reduce.c
- reduce.h
- rounding.c
- rounding.h
- sign.c
- sign.h
- symmetric.c
- symmetric.h

+ 39
- 0
test/duplicate_consistency/dilithium4_clean.yml View File

@@ -0,0 +1,39 @@
consistency_checks:
- source:
scheme: dilithium2
implementation: clean
files:
- ntt.c
- ntt.h
- packing.c
- packing.h
- poly.h
- polyvec.c
- polyvec.h
- reduce.c
- reduce.h
- rounding.c
- rounding.h
- sign.c
- sign.h
- symmetric.c
- symmetric.h
- source:
scheme: dilithium3
implementation: clean
files:
- ntt.c
- ntt.h
- packing.c
- packing.h
- poly.h
- polyvec.c
- polyvec.h
- reduce.c
- reduce.h
- rounding.c
- rounding.h
- sign.c
- sign.h
- symmetric.c
- symmetric.h

+ 1
- 1
test/test_dynamic_memory.py View File

@@ -28,7 +28,7 @@ def check_dynamic_memory(implementation, function):
lines = out.strip().split("\n")

for line in lines:
if 'U {}'.format(function) in line:
if line.endswith('U {}'.format(function)):
raise AssertionError(
"Illegal use of dynamic memory function '{}'".format(function))



Loading…
Cancel
Save