@@ -2,5 +2,6 @@ | |||||
Language: Cpp | Language: Cpp | ||||
BasedOnStyle: LLVM | BasedOnStyle: LLVM | ||||
AllowShortFunctionsOnASingleLine: false | AllowShortFunctionsOnASingleLine: false | ||||
IndentWidth: 4 | |||||
... | ... | ||||
@@ -18,6 +18,10 @@ clean: | |||||
.PHONY: format | .PHONY: format | ||||
format: | format: | ||||
find . -iname *.h -o -iname *.c | xargs clang-format -i -style=file | find . -iname *.h -o -iname *.c | xargs clang-format -i -style=file | ||||
ifneq (,$(shell which dos2unix)) | |||||
# TODO should we make this mandatory? | |||||
find . -iname *.h -o -iname *.c | xargs dos2unix -q | |||||
endif | |||||
.PHONY: tidy | .PHONY: tidy | ||||
tidy: require_scheme | tidy: require_scheme | ||||
@@ -22,14 +22,14 @@ | |||||
* Returns the loaded 64-bit unsigned integer | * Returns the loaded 64-bit unsigned integer | ||||
**************************************************/ | **************************************************/ | ||||
static uint64_t load64(const unsigned char *x) { | static uint64_t load64(const unsigned char *x) { | ||||
unsigned int i; | |||||
uint64_t r = 0; | |||||
unsigned int i; | |||||
uint64_t r = 0; | |||||
for (i = 0; i < 8; ++i) { | |||||
r |= (uint64_t)x[i] << 8 * i; | |||||
} | |||||
for (i = 0; i < 8; ++i) { | |||||
r |= (uint64_t)x[i] << 8 * i; | |||||
} | |||||
return r; | |||||
return r; | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -41,11 +41,11 @@ static uint64_t load64(const unsigned char *x) { | |||||
* - uint64_t u: input 64-bit unsigned integer | * - uint64_t u: input 64-bit unsigned integer | ||||
**************************************************/ | **************************************************/ | ||||
static void store64(uint8_t *x, uint64_t u) { | static void store64(uint8_t *x, uint64_t u) { | ||||
unsigned int i; | |||||
unsigned int i; | |||||
for (i = 0; i < 8; ++i) { | |||||
x[i] = u >> 8 * i; | |||||
} | |||||
for (i = 0; i < 8; ++i) { | |||||
x[i] = u >> 8 * i; | |||||
} | |||||
} | } | ||||
/* Keccak round constants */ | /* Keccak round constants */ | ||||
@@ -71,266 +71,266 @@ static const uint64_t KeccakF_RoundConstants[NROUNDS] = { | |||||
* Arguments: - uint64_t *state: pointer to input/output Keccak state | * Arguments: - uint64_t *state: pointer to input/output Keccak state | ||||
**************************************************/ | **************************************************/ | ||||
static void KeccakF1600_StatePermute(uint64_t *state) { | static void KeccakF1600_StatePermute(uint64_t *state) { | ||||
int round; | |||||
uint64_t Aba, Abe, Abi, Abo, Abu; | |||||
uint64_t Aga, Age, Agi, Ago, Agu; | |||||
uint64_t Aka, Ake, Aki, Ako, Aku; | |||||
uint64_t Ama, Ame, Ami, Amo, Amu; | |||||
uint64_t Asa, Ase, Asi, Aso, Asu; | |||||
uint64_t BCa, BCe, BCi, BCo, BCu; | |||||
uint64_t Da, De, Di, Do, Du; | |||||
uint64_t Eba, Ebe, Ebi, Ebo, Ebu; | |||||
uint64_t Ega, Ege, Egi, Ego, Egu; | |||||
uint64_t Eka, Eke, Eki, Eko, Eku; | |||||
uint64_t Ema, Eme, Emi, Emo, Emu; | |||||
uint64_t Esa, Ese, Esi, Eso, Esu; | |||||
// copyFromState(A, state) | |||||
Aba = state[0]; | |||||
Abe = state[1]; | |||||
Abi = state[2]; | |||||
Abo = state[3]; | |||||
Abu = state[4]; | |||||
Aga = state[5]; | |||||
Age = state[6]; | |||||
Agi = state[7]; | |||||
Ago = state[8]; | |||||
Agu = state[9]; | |||||
Aka = state[10]; | |||||
Ake = state[11]; | |||||
Aki = state[12]; | |||||
Ako = state[13]; | |||||
Aku = state[14]; | |||||
Ama = state[15]; | |||||
Ame = state[16]; | |||||
Ami = state[17]; | |||||
Amo = state[18]; | |||||
Amu = state[19]; | |||||
Asa = state[20]; | |||||
Ase = state[21]; | |||||
Asi = state[22]; | |||||
Aso = state[23]; | |||||
Asu = state[24]; | |||||
for (round = 0; round < NROUNDS; round += 2) { | |||||
// prepareTheta | |||||
BCa = Aba ^ Aga ^ Aka ^ Ama ^ Asa; | |||||
BCe = Abe ^ Age ^ Ake ^ Ame ^ Ase; | |||||
BCi = Abi ^ Agi ^ Aki ^ Ami ^ Asi; | |||||
BCo = Abo ^ Ago ^ Ako ^ Amo ^ Aso; | |||||
BCu = Abu ^ Agu ^ Aku ^ Amu ^ Asu; | |||||
// thetaRhoPiChiIotaPrepareTheta(round , A, E) | |||||
Da = BCu ^ ROL(BCe, 1); | |||||
De = BCa ^ ROL(BCi, 1); | |||||
Di = BCe ^ ROL(BCo, 1); | |||||
Do = BCi ^ ROL(BCu, 1); | |||||
Du = BCo ^ ROL(BCa, 1); | |||||
Aba ^= Da; | |||||
BCa = Aba; | |||||
Age ^= De; | |||||
BCe = ROL(Age, 44); | |||||
Aki ^= Di; | |||||
BCi = ROL(Aki, 43); | |||||
Amo ^= Do; | |||||
BCo = ROL(Amo, 21); | |||||
Asu ^= Du; | |||||
BCu = ROL(Asu, 14); | |||||
Eba = BCa ^ ((~BCe) & BCi); | |||||
Eba ^= KeccakF_RoundConstants[round]; | |||||
Ebe = BCe ^ ((~BCi) & BCo); | |||||
Ebi = BCi ^ ((~BCo) & BCu); | |||||
Ebo = BCo ^ ((~BCu) & BCa); | |||||
Ebu = BCu ^ ((~BCa) & BCe); | |||||
Abo ^= Do; | |||||
BCa = ROL(Abo, 28); | |||||
Agu ^= Du; | |||||
BCe = ROL(Agu, 20); | |||||
Aka ^= Da; | |||||
BCi = ROL(Aka, 3); | |||||
Ame ^= De; | |||||
BCo = ROL(Ame, 45); | |||||
Asi ^= Di; | |||||
BCu = ROL(Asi, 61); | |||||
Ega = BCa ^ ((~BCe) & BCi); | |||||
Ege = BCe ^ ((~BCi) & BCo); | |||||
Egi = BCi ^ ((~BCo) & BCu); | |||||
Ego = BCo ^ ((~BCu) & BCa); | |||||
Egu = BCu ^ ((~BCa) & BCe); | |||||
Abe ^= De; | |||||
BCa = ROL(Abe, 1); | |||||
Agi ^= Di; | |||||
BCe = ROL(Agi, 6); | |||||
Ako ^= Do; | |||||
BCi = ROL(Ako, 25); | |||||
Amu ^= Du; | |||||
BCo = ROL(Amu, 8); | |||||
Asa ^= Da; | |||||
BCu = ROL(Asa, 18); | |||||
Eka = BCa ^ ((~BCe) & BCi); | |||||
Eke = BCe ^ ((~BCi) & BCo); | |||||
Eki = BCi ^ ((~BCo) & BCu); | |||||
Eko = BCo ^ ((~BCu) & BCa); | |||||
Eku = BCu ^ ((~BCa) & BCe); | |||||
Abu ^= Du; | |||||
BCa = ROL(Abu, 27); | |||||
Aga ^= Da; | |||||
BCe = ROL(Aga, 36); | |||||
Ake ^= De; | |||||
BCi = ROL(Ake, 10); | |||||
Ami ^= Di; | |||||
BCo = ROL(Ami, 15); | |||||
Aso ^= Do; | |||||
BCu = ROL(Aso, 56); | |||||
Ema = BCa ^ ((~BCe) & BCi); | |||||
Eme = BCe ^ ((~BCi) & BCo); | |||||
Emi = BCi ^ ((~BCo) & BCu); | |||||
Emo = BCo ^ ((~BCu) & BCa); | |||||
Emu = BCu ^ ((~BCa) & BCe); | |||||
Abi ^= Di; | |||||
BCa = ROL(Abi, 62); | |||||
Ago ^= Do; | |||||
BCe = ROL(Ago, 55); | |||||
Aku ^= Du; | |||||
BCi = ROL(Aku, 39); | |||||
Ama ^= Da; | |||||
BCo = ROL(Ama, 41); | |||||
Ase ^= De; | |||||
BCu = ROL(Ase, 2); | |||||
Esa = BCa ^ ((~BCe) & BCi); | |||||
Ese = BCe ^ ((~BCi) & BCo); | |||||
Esi = BCi ^ ((~BCo) & BCu); | |||||
Eso = BCo ^ ((~BCu) & BCa); | |||||
Esu = BCu ^ ((~BCa) & BCe); | |||||
// prepareTheta | |||||
BCa = Eba ^ Ega ^ Eka ^ Ema ^ Esa; | |||||
BCe = Ebe ^ Ege ^ Eke ^ Eme ^ Ese; | |||||
BCi = Ebi ^ Egi ^ Eki ^ Emi ^ Esi; | |||||
BCo = Ebo ^ Ego ^ Eko ^ Emo ^ Eso; | |||||
BCu = Ebu ^ Egu ^ Eku ^ Emu ^ Esu; | |||||
// thetaRhoPiChiIotaPrepareTheta(round+1, E, A) | |||||
Da = BCu ^ ROL(BCe, 1); | |||||
De = BCa ^ ROL(BCi, 1); | |||||
Di = BCe ^ ROL(BCo, 1); | |||||
Do = BCi ^ ROL(BCu, 1); | |||||
Du = BCo ^ ROL(BCa, 1); | |||||
Eba ^= Da; | |||||
BCa = Eba; | |||||
Ege ^= De; | |||||
BCe = ROL(Ege, 44); | |||||
Eki ^= Di; | |||||
BCi = ROL(Eki, 43); | |||||
Emo ^= Do; | |||||
BCo = ROL(Emo, 21); | |||||
Esu ^= Du; | |||||
BCu = ROL(Esu, 14); | |||||
Aba = BCa ^ ((~BCe) & BCi); | |||||
Aba ^= KeccakF_RoundConstants[round + 1]; | |||||
Abe = BCe ^ ((~BCi) & BCo); | |||||
Abi = BCi ^ ((~BCo) & BCu); | |||||
Abo = BCo ^ ((~BCu) & BCa); | |||||
Abu = BCu ^ ((~BCa) & BCe); | |||||
Ebo ^= Do; | |||||
BCa = ROL(Ebo, 28); | |||||
Egu ^= Du; | |||||
BCe = ROL(Egu, 20); | |||||
Eka ^= Da; | |||||
BCi = ROL(Eka, 3); | |||||
Eme ^= De; | |||||
BCo = ROL(Eme, 45); | |||||
Esi ^= Di; | |||||
BCu = ROL(Esi, 61); | |||||
Aga = BCa ^ ((~BCe) & BCi); | |||||
Age = BCe ^ ((~BCi) & BCo); | |||||
Agi = BCi ^ ((~BCo) & BCu); | |||||
Ago = BCo ^ ((~BCu) & BCa); | |||||
Agu = BCu ^ ((~BCa) & BCe); | |||||
Ebe ^= De; | |||||
BCa = ROL(Ebe, 1); | |||||
Egi ^= Di; | |||||
BCe = ROL(Egi, 6); | |||||
Eko ^= Do; | |||||
BCi = ROL(Eko, 25); | |||||
Emu ^= Du; | |||||
BCo = ROL(Emu, 8); | |||||
Esa ^= Da; | |||||
BCu = ROL(Esa, 18); | |||||
Aka = BCa ^ ((~BCe) & BCi); | |||||
Ake = BCe ^ ((~BCi) & BCo); | |||||
Aki = BCi ^ ((~BCo) & BCu); | |||||
Ako = BCo ^ ((~BCu) & BCa); | |||||
Aku = BCu ^ ((~BCa) & BCe); | |||||
Ebu ^= Du; | |||||
BCa = ROL(Ebu, 27); | |||||
Ega ^= Da; | |||||
BCe = ROL(Ega, 36); | |||||
Eke ^= De; | |||||
BCi = ROL(Eke, 10); | |||||
Emi ^= Di; | |||||
BCo = ROL(Emi, 15); | |||||
Eso ^= Do; | |||||
BCu = ROL(Eso, 56); | |||||
Ama = BCa ^ ((~BCe) & BCi); | |||||
Ame = BCe ^ ((~BCi) & BCo); | |||||
Ami = BCi ^ ((~BCo) & BCu); | |||||
Amo = BCo ^ ((~BCu) & BCa); | |||||
Amu = BCu ^ ((~BCa) & BCe); | |||||
Ebi ^= Di; | |||||
BCa = ROL(Ebi, 62); | |||||
Ego ^= Do; | |||||
BCe = ROL(Ego, 55); | |||||
Eku ^= Du; | |||||
BCi = ROL(Eku, 39); | |||||
Ema ^= Da; | |||||
BCo = ROL(Ema, 41); | |||||
Ese ^= De; | |||||
BCu = ROL(Ese, 2); | |||||
Asa = BCa ^ ((~BCe) & BCi); | |||||
Ase = BCe ^ ((~BCi) & BCo); | |||||
Asi = BCi ^ ((~BCo) & BCu); | |||||
Aso = BCo ^ ((~BCu) & BCa); | |||||
Asu = BCu ^ ((~BCa) & BCe); | |||||
} | |||||
// copyToState(state, A) | |||||
state[0] = Aba; | |||||
state[1] = Abe; | |||||
state[2] = Abi; | |||||
state[3] = Abo; | |||||
state[4] = Abu; | |||||
state[5] = Aga; | |||||
state[6] = Age; | |||||
state[7] = Agi; | |||||
state[8] = Ago; | |||||
state[9] = Agu; | |||||
state[10] = Aka; | |||||
state[11] = Ake; | |||||
state[12] = Aki; | |||||
state[13] = Ako; | |||||
state[14] = Aku; | |||||
state[15] = Ama; | |||||
state[16] = Ame; | |||||
state[17] = Ami; | |||||
state[18] = Amo; | |||||
state[19] = Amu; | |||||
state[20] = Asa; | |||||
state[21] = Ase; | |||||
state[22] = Asi; | |||||
state[23] = Aso; | |||||
state[24] = Asu; | |||||
int round; | |||||
uint64_t Aba, Abe, Abi, Abo, Abu; | |||||
uint64_t Aga, Age, Agi, Ago, Agu; | |||||
uint64_t Aka, Ake, Aki, Ako, Aku; | |||||
uint64_t Ama, Ame, Ami, Amo, Amu; | |||||
uint64_t Asa, Ase, Asi, Aso, Asu; | |||||
uint64_t BCa, BCe, BCi, BCo, BCu; | |||||
uint64_t Da, De, Di, Do, Du; | |||||
uint64_t Eba, Ebe, Ebi, Ebo, Ebu; | |||||
uint64_t Ega, Ege, Egi, Ego, Egu; | |||||
uint64_t Eka, Eke, Eki, Eko, Eku; | |||||
uint64_t Ema, Eme, Emi, Emo, Emu; | |||||
uint64_t Esa, Ese, Esi, Eso, Esu; | |||||
// copyFromState(A, state) | |||||
Aba = state[0]; | |||||
Abe = state[1]; | |||||
Abi = state[2]; | |||||
Abo = state[3]; | |||||
Abu = state[4]; | |||||
Aga = state[5]; | |||||
Age = state[6]; | |||||
Agi = state[7]; | |||||
Ago = state[8]; | |||||
Agu = state[9]; | |||||
Aka = state[10]; | |||||
Ake = state[11]; | |||||
Aki = state[12]; | |||||
Ako = state[13]; | |||||
Aku = state[14]; | |||||
Ama = state[15]; | |||||
Ame = state[16]; | |||||
Ami = state[17]; | |||||
Amo = state[18]; | |||||
Amu = state[19]; | |||||
Asa = state[20]; | |||||
Ase = state[21]; | |||||
Asi = state[22]; | |||||
Aso = state[23]; | |||||
Asu = state[24]; | |||||
for (round = 0; round < NROUNDS; round += 2) { | |||||
// prepareTheta | |||||
BCa = Aba ^ Aga ^ Aka ^ Ama ^ Asa; | |||||
BCe = Abe ^ Age ^ Ake ^ Ame ^ Ase; | |||||
BCi = Abi ^ Agi ^ Aki ^ Ami ^ Asi; | |||||
BCo = Abo ^ Ago ^ Ako ^ Amo ^ Aso; | |||||
BCu = Abu ^ Agu ^ Aku ^ Amu ^ Asu; | |||||
// thetaRhoPiChiIotaPrepareTheta(round , A, E) | |||||
Da = BCu ^ ROL(BCe, 1); | |||||
De = BCa ^ ROL(BCi, 1); | |||||
Di = BCe ^ ROL(BCo, 1); | |||||
Do = BCi ^ ROL(BCu, 1); | |||||
Du = BCo ^ ROL(BCa, 1); | |||||
Aba ^= Da; | |||||
BCa = Aba; | |||||
Age ^= De; | |||||
BCe = ROL(Age, 44); | |||||
Aki ^= Di; | |||||
BCi = ROL(Aki, 43); | |||||
Amo ^= Do; | |||||
BCo = ROL(Amo, 21); | |||||
Asu ^= Du; | |||||
BCu = ROL(Asu, 14); | |||||
Eba = BCa ^ ((~BCe) & BCi); | |||||
Eba ^= KeccakF_RoundConstants[round]; | |||||
Ebe = BCe ^ ((~BCi) & BCo); | |||||
Ebi = BCi ^ ((~BCo) & BCu); | |||||
Ebo = BCo ^ ((~BCu) & BCa); | |||||
Ebu = BCu ^ ((~BCa) & BCe); | |||||
Abo ^= Do; | |||||
BCa = ROL(Abo, 28); | |||||
Agu ^= Du; | |||||
BCe = ROL(Agu, 20); | |||||
Aka ^= Da; | |||||
BCi = ROL(Aka, 3); | |||||
Ame ^= De; | |||||
BCo = ROL(Ame, 45); | |||||
Asi ^= Di; | |||||
BCu = ROL(Asi, 61); | |||||
Ega = BCa ^ ((~BCe) & BCi); | |||||
Ege = BCe ^ ((~BCi) & BCo); | |||||
Egi = BCi ^ ((~BCo) & BCu); | |||||
Ego = BCo ^ ((~BCu) & BCa); | |||||
Egu = BCu ^ ((~BCa) & BCe); | |||||
Abe ^= De; | |||||
BCa = ROL(Abe, 1); | |||||
Agi ^= Di; | |||||
BCe = ROL(Agi, 6); | |||||
Ako ^= Do; | |||||
BCi = ROL(Ako, 25); | |||||
Amu ^= Du; | |||||
BCo = ROL(Amu, 8); | |||||
Asa ^= Da; | |||||
BCu = ROL(Asa, 18); | |||||
Eka = BCa ^ ((~BCe) & BCi); | |||||
Eke = BCe ^ ((~BCi) & BCo); | |||||
Eki = BCi ^ ((~BCo) & BCu); | |||||
Eko = BCo ^ ((~BCu) & BCa); | |||||
Eku = BCu ^ ((~BCa) & BCe); | |||||
Abu ^= Du; | |||||
BCa = ROL(Abu, 27); | |||||
Aga ^= Da; | |||||
BCe = ROL(Aga, 36); | |||||
Ake ^= De; | |||||
BCi = ROL(Ake, 10); | |||||
Ami ^= Di; | |||||
BCo = ROL(Ami, 15); | |||||
Aso ^= Do; | |||||
BCu = ROL(Aso, 56); | |||||
Ema = BCa ^ ((~BCe) & BCi); | |||||
Eme = BCe ^ ((~BCi) & BCo); | |||||
Emi = BCi ^ ((~BCo) & BCu); | |||||
Emo = BCo ^ ((~BCu) & BCa); | |||||
Emu = BCu ^ ((~BCa) & BCe); | |||||
Abi ^= Di; | |||||
BCa = ROL(Abi, 62); | |||||
Ago ^= Do; | |||||
BCe = ROL(Ago, 55); | |||||
Aku ^= Du; | |||||
BCi = ROL(Aku, 39); | |||||
Ama ^= Da; | |||||
BCo = ROL(Ama, 41); | |||||
Ase ^= De; | |||||
BCu = ROL(Ase, 2); | |||||
Esa = BCa ^ ((~BCe) & BCi); | |||||
Ese = BCe ^ ((~BCi) & BCo); | |||||
Esi = BCi ^ ((~BCo) & BCu); | |||||
Eso = BCo ^ ((~BCu) & BCa); | |||||
Esu = BCu ^ ((~BCa) & BCe); | |||||
// prepareTheta | |||||
BCa = Eba ^ Ega ^ Eka ^ Ema ^ Esa; | |||||
BCe = Ebe ^ Ege ^ Eke ^ Eme ^ Ese; | |||||
BCi = Ebi ^ Egi ^ Eki ^ Emi ^ Esi; | |||||
BCo = Ebo ^ Ego ^ Eko ^ Emo ^ Eso; | |||||
BCu = Ebu ^ Egu ^ Eku ^ Emu ^ Esu; | |||||
// thetaRhoPiChiIotaPrepareTheta(round+1, E, A) | |||||
Da = BCu ^ ROL(BCe, 1); | |||||
De = BCa ^ ROL(BCi, 1); | |||||
Di = BCe ^ ROL(BCo, 1); | |||||
Do = BCi ^ ROL(BCu, 1); | |||||
Du = BCo ^ ROL(BCa, 1); | |||||
Eba ^= Da; | |||||
BCa = Eba; | |||||
Ege ^= De; | |||||
BCe = ROL(Ege, 44); | |||||
Eki ^= Di; | |||||
BCi = ROL(Eki, 43); | |||||
Emo ^= Do; | |||||
BCo = ROL(Emo, 21); | |||||
Esu ^= Du; | |||||
BCu = ROL(Esu, 14); | |||||
Aba = BCa ^ ((~BCe) & BCi); | |||||
Aba ^= KeccakF_RoundConstants[round + 1]; | |||||
Abe = BCe ^ ((~BCi) & BCo); | |||||
Abi = BCi ^ ((~BCo) & BCu); | |||||
Abo = BCo ^ ((~BCu) & BCa); | |||||
Abu = BCu ^ ((~BCa) & BCe); | |||||
Ebo ^= Do; | |||||
BCa = ROL(Ebo, 28); | |||||
Egu ^= Du; | |||||
BCe = ROL(Egu, 20); | |||||
Eka ^= Da; | |||||
BCi = ROL(Eka, 3); | |||||
Eme ^= De; | |||||
BCo = ROL(Eme, 45); | |||||
Esi ^= Di; | |||||
BCu = ROL(Esi, 61); | |||||
Aga = BCa ^ ((~BCe) & BCi); | |||||
Age = BCe ^ ((~BCi) & BCo); | |||||
Agi = BCi ^ ((~BCo) & BCu); | |||||
Ago = BCo ^ ((~BCu) & BCa); | |||||
Agu = BCu ^ ((~BCa) & BCe); | |||||
Ebe ^= De; | |||||
BCa = ROL(Ebe, 1); | |||||
Egi ^= Di; | |||||
BCe = ROL(Egi, 6); | |||||
Eko ^= Do; | |||||
BCi = ROL(Eko, 25); | |||||
Emu ^= Du; | |||||
BCo = ROL(Emu, 8); | |||||
Esa ^= Da; | |||||
BCu = ROL(Esa, 18); | |||||
Aka = BCa ^ ((~BCe) & BCi); | |||||
Ake = BCe ^ ((~BCi) & BCo); | |||||
Aki = BCi ^ ((~BCo) & BCu); | |||||
Ako = BCo ^ ((~BCu) & BCa); | |||||
Aku = BCu ^ ((~BCa) & BCe); | |||||
Ebu ^= Du; | |||||
BCa = ROL(Ebu, 27); | |||||
Ega ^= Da; | |||||
BCe = ROL(Ega, 36); | |||||
Eke ^= De; | |||||
BCi = ROL(Eke, 10); | |||||
Emi ^= Di; | |||||
BCo = ROL(Emi, 15); | |||||
Eso ^= Do; | |||||
BCu = ROL(Eso, 56); | |||||
Ama = BCa ^ ((~BCe) & BCi); | |||||
Ame = BCe ^ ((~BCi) & BCo); | |||||
Ami = BCi ^ ((~BCo) & BCu); | |||||
Amo = BCo ^ ((~BCu) & BCa); | |||||
Amu = BCu ^ ((~BCa) & BCe); | |||||
Ebi ^= Di; | |||||
BCa = ROL(Ebi, 62); | |||||
Ego ^= Do; | |||||
BCe = ROL(Ego, 55); | |||||
Eku ^= Du; | |||||
BCi = ROL(Eku, 39); | |||||
Ema ^= Da; | |||||
BCo = ROL(Ema, 41); | |||||
Ese ^= De; | |||||
BCu = ROL(Ese, 2); | |||||
Asa = BCa ^ ((~BCe) & BCi); | |||||
Ase = BCe ^ ((~BCi) & BCo); | |||||
Asi = BCi ^ ((~BCo) & BCu); | |||||
Aso = BCo ^ ((~BCu) & BCa); | |||||
Asu = BCu ^ ((~BCa) & BCe); | |||||
} | |||||
// copyToState(state, A) | |||||
state[0] = Aba; | |||||
state[1] = Abe; | |||||
state[2] = Abi; | |||||
state[3] = Abo; | |||||
state[4] = Abu; | |||||
state[5] = Aga; | |||||
state[6] = Age; | |||||
state[7] = Agi; | |||||
state[8] = Ago; | |||||
state[9] = Agu; | |||||
state[10] = Aka; | |||||
state[11] = Ake; | |||||
state[12] = Aki; | |||||
state[13] = Ako; | |||||
state[14] = Aku; | |||||
state[15] = Ama; | |||||
state[16] = Ame; | |||||
state[17] = Ami; | |||||
state[18] = Amo; | |||||
state[19] = Amu; | |||||
state[20] = Asa; | |||||
state[21] = Ase; | |||||
state[22] = Asi; | |||||
state[23] = Aso; | |||||
state[24] = Asu; | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -348,35 +348,35 @@ static void KeccakF1600_StatePermute(uint64_t *state) { | |||||
**************************************************/ | **************************************************/ | ||||
static void keccak_absorb(uint64_t *s, unsigned int r, const unsigned char *m, | static void keccak_absorb(uint64_t *s, unsigned int r, const unsigned char *m, | ||||
unsigned long long mlen, unsigned char p) { | unsigned long long mlen, unsigned char p) { | ||||
unsigned int i; | |||||
unsigned char t[200]; | |||||
unsigned int i; | |||||
unsigned char t[200]; | |||||
/* Zero state */ | |||||
for (i = 0; i < 25; ++i) { | |||||
s[i] = 0; | |||||
} | |||||
/* Zero state */ | |||||
for (i = 0; i < 25; ++i) { | |||||
s[i] = 0; | |||||
} | |||||
while (mlen >= r) { | |||||
for (i = 0; i < r / 8; ++i) { | |||||
s[i] ^= load64(m + 8 * i); | |||||
} | |||||
while (mlen >= r) { | |||||
for (i = 0; i < r / 8; ++i) { | |||||
s[i] ^= load64(m + 8 * i); | |||||
KeccakF1600_StatePermute(s); | |||||
mlen -= r; | |||||
m += r; | |||||
} | } | ||||
KeccakF1600_StatePermute(s); | |||||
mlen -= r; | |||||
m += r; | |||||
} | |||||
for (i = 0; i < r; ++i) { | |||||
t[i] = 0; | |||||
} | |||||
for (i = 0; i < mlen; ++i) { | |||||
t[i] = m[i]; | |||||
} | |||||
t[i] = p; | |||||
t[r - 1] |= 128; | |||||
for (i = 0; i < r / 8; ++i) { | |||||
s[i] ^= load64(t + 8 * i); | |||||
} | |||||
for (i = 0; i < r; ++i) { | |||||
t[i] = 0; | |||||
} | |||||
for (i = 0; i < mlen; ++i) { | |||||
t[i] = m[i]; | |||||
} | |||||
t[i] = p; | |||||
t[r - 1] |= 128; | |||||
for (i = 0; i < r / 8; ++i) { | |||||
s[i] ^= load64(t + 8 * i); | |||||
} | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -394,16 +394,16 @@ static void keccak_absorb(uint64_t *s, unsigned int r, const unsigned char *m, | |||||
**************************************************/ | **************************************************/ | ||||
static void keccak_squeezeblocks(unsigned char *h, unsigned long nblocks, | static void keccak_squeezeblocks(unsigned char *h, unsigned long nblocks, | ||||
uint64_t *s, unsigned int r) { | uint64_t *s, unsigned int r) { | ||||
unsigned int i; | |||||
while (nblocks > 0) { | |||||
KeccakF1600_StatePermute(s); | |||||
for (i = 0; i < (r >> 3); i++) { | |||||
store64(h + 8 * i, s[i]); | |||||
unsigned int i; | |||||
while (nblocks > 0) { | |||||
KeccakF1600_StatePermute(s); | |||||
for (i = 0; i < (r >> 3); i++) { | |||||
store64(h + 8 * i, s[i]); | |||||
} | |||||
h += r; | |||||
nblocks--; | |||||
} | } | ||||
h += r; | |||||
nblocks--; | |||||
} | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -419,7 +419,7 @@ static void keccak_squeezeblocks(unsigned char *h, unsigned long nblocks, | |||||
**************************************************/ | **************************************************/ | ||||
void shake128_absorb(uint64_t *s, const unsigned char *input, | void shake128_absorb(uint64_t *s, const unsigned char *input, | ||||
unsigned long long inlen) { | unsigned long long inlen) { | ||||
keccak_absorb(s, SHAKE128_RATE, input, inlen, 0x1F); | |||||
keccak_absorb(s, SHAKE128_RATE, input, inlen, 0x1F); | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -436,7 +436,7 @@ void shake128_absorb(uint64_t *s, const unsigned char *input, | |||||
**************************************************/ | **************************************************/ | ||||
void shake128_squeezeblocks(unsigned char *output, unsigned long nblocks, | void shake128_squeezeblocks(unsigned char *output, unsigned long nblocks, | ||||
uint64_t *s) { | uint64_t *s) { | ||||
keccak_squeezeblocks(output, nblocks, s, SHAKE128_RATE); | |||||
keccak_squeezeblocks(output, nblocks, s, SHAKE128_RATE); | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -452,7 +452,7 @@ void shake128_squeezeblocks(unsigned char *output, unsigned long nblocks, | |||||
**************************************************/ | **************************************************/ | ||||
void shake256_absorb(uint64_t *s, const unsigned char *input, | void shake256_absorb(uint64_t *s, const unsigned char *input, | ||||
unsigned long long inlen) { | unsigned long long inlen) { | ||||
keccak_absorb(s, SHAKE256_RATE, input, inlen, 0x1F); | |||||
keccak_absorb(s, SHAKE256_RATE, input, inlen, 0x1F); | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -469,7 +469,7 @@ void shake256_absorb(uint64_t *s, const unsigned char *input, | |||||
**************************************************/ | **************************************************/ | ||||
void shake256_squeezeblocks(unsigned char *output, unsigned long nblocks, | void shake256_squeezeblocks(unsigned char *output, unsigned long nblocks, | ||||
uint64_t *s) { | uint64_t *s) { | ||||
keccak_squeezeblocks(output, nblocks, s, SHAKE256_RATE); | |||||
keccak_squeezeblocks(output, nblocks, s, SHAKE256_RATE); | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -484,23 +484,23 @@ void shake256_squeezeblocks(unsigned char *output, unsigned long nblocks, | |||||
**************************************************/ | **************************************************/ | ||||
void shake128(unsigned char *output, unsigned long long outlen, | void shake128(unsigned char *output, unsigned long long outlen, | ||||
const unsigned char *input, unsigned long long inlen) { | const unsigned char *input, unsigned long long inlen) { | ||||
unsigned int i; | |||||
unsigned long nblocks = outlen / SHAKE128_RATE; | |||||
unsigned char t[SHAKE128_RATE]; | |||||
uint64_t s[25]; | |||||
shake128_absorb(s, input, inlen); | |||||
shake128_squeezeblocks(output, nblocks, s); | |||||
output += nblocks * SHAKE128_RATE; | |||||
outlen -= nblocks * SHAKE128_RATE; | |||||
if (outlen) { | |||||
shake128_squeezeblocks(t, 1, s); | |||||
for (i = 0; i < outlen; ++i) { | |||||
output[i] = t[i]; | |||||
unsigned int i; | |||||
unsigned long nblocks = outlen / SHAKE128_RATE; | |||||
unsigned char t[SHAKE128_RATE]; | |||||
uint64_t s[25]; | |||||
shake128_absorb(s, input, inlen); | |||||
shake128_squeezeblocks(output, nblocks, s); | |||||
output += nblocks * SHAKE128_RATE; | |||||
outlen -= nblocks * SHAKE128_RATE; | |||||
if (outlen) { | |||||
shake128_squeezeblocks(t, 1, s); | |||||
for (i = 0; i < outlen; ++i) { | |||||
output[i] = t[i]; | |||||
} | |||||
} | } | ||||
} | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -515,23 +515,23 @@ void shake128(unsigned char *output, unsigned long long outlen, | |||||
**************************************************/ | **************************************************/ | ||||
void shake256(unsigned char *output, unsigned long long outlen, | void shake256(unsigned char *output, unsigned long long outlen, | ||||
const unsigned char *input, unsigned long long inlen) { | const unsigned char *input, unsigned long long inlen) { | ||||
unsigned int i; | |||||
unsigned long nblocks = outlen / SHAKE256_RATE; | |||||
unsigned char t[SHAKE256_RATE]; | |||||
uint64_t s[25]; | |||||
shake256_absorb(s, input, inlen); | |||||
shake256_squeezeblocks(output, nblocks, s); | |||||
output += nblocks * SHAKE256_RATE; | |||||
outlen -= nblocks * SHAKE256_RATE; | |||||
if (outlen) { | |||||
shake256_squeezeblocks(t, 1, s); | |||||
for (i = 0; i < outlen; ++i) { | |||||
output[i] = t[i]; | |||||
unsigned int i; | |||||
unsigned long nblocks = outlen / SHAKE256_RATE; | |||||
unsigned char t[SHAKE256_RATE]; | |||||
uint64_t s[25]; | |||||
shake256_absorb(s, input, inlen); | |||||
shake256_squeezeblocks(output, nblocks, s); | |||||
output += nblocks * SHAKE256_RATE; | |||||
outlen -= nblocks * SHAKE256_RATE; | |||||
if (outlen) { | |||||
shake256_squeezeblocks(t, 1, s); | |||||
for (i = 0; i < outlen; ++i) { | |||||
output[i] = t[i]; | |||||
} | |||||
} | } | ||||
} | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -545,19 +545,19 @@ void shake256(unsigned char *output, unsigned long long outlen, | |||||
**************************************************/ | **************************************************/ | ||||
void sha3_256(unsigned char *output, const unsigned char *input, | void sha3_256(unsigned char *output, const unsigned char *input, | ||||
unsigned long long inlen) { | unsigned long long inlen) { | ||||
uint64_t s[25]; | |||||
unsigned char t[SHA3_256_RATE]; | |||||
size_t i; | |||||
uint64_t s[25]; | |||||
unsigned char t[SHA3_256_RATE]; | |||||
size_t i; | |||||
/* Absorb input */ | |||||
keccak_absorb(s, SHA3_256_RATE, input, inlen, 0x06); | |||||
/* Absorb input */ | |||||
keccak_absorb(s, SHA3_256_RATE, input, inlen, 0x06); | |||||
/* Squeeze output */ | |||||
keccak_squeezeblocks(t, 1, s, SHA3_256_RATE); | |||||
/* Squeeze output */ | |||||
keccak_squeezeblocks(t, 1, s, SHA3_256_RATE); | |||||
for (i = 0; i < 32; i++) { | |||||
output[i] = t[i]; | |||||
} | |||||
for (i = 0; i < 32; i++) { | |||||
output[i] = t[i]; | |||||
} | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -571,17 +571,17 @@ void sha3_256(unsigned char *output, const unsigned char *input, | |||||
**************************************************/ | **************************************************/ | ||||
void sha3_512(unsigned char *output, const unsigned char *input, | void sha3_512(unsigned char *output, const unsigned char *input, | ||||
unsigned long long inlen) { | unsigned long long inlen) { | ||||
uint64_t s[25]; | |||||
unsigned char t[SHA3_512_RATE]; | |||||
size_t i; | |||||
uint64_t s[25]; | |||||
unsigned char t[SHA3_512_RATE]; | |||||
size_t i; | |||||
/* Absorb input */ | |||||
keccak_absorb(s, SHA3_512_RATE, input, inlen, 0x06); | |||||
/* Absorb input */ | |||||
keccak_absorb(s, SHA3_512_RATE, input, inlen, 0x06); | |||||
/* Squeeze output */ | |||||
keccak_squeezeblocks(t, 1, s, SHA3_512_RATE); | |||||
/* Squeeze output */ | |||||
keccak_squeezeblocks(t, 1, s, SHA3_512_RATE); | |||||
for (i = 0; i < 64; i++) { | |||||
output[i] = t[i]; | |||||
} | |||||
for (i = 0; i < 64; i++) { | |||||
output[i] = t[i]; | |||||
} | |||||
} | } |
@@ -20,57 +20,57 @@ static int32_t outleft = 0; | |||||
#define MUSH(i, b) x = t[i] += (((x ^ seed[i]) + sum) ^ ROTATE(x, b)); | #define MUSH(i, b) x = t[i] += (((x ^ seed[i]) + sum) ^ ROTATE(x, b)); | ||||
static void surf(void) { | static void surf(void) { | ||||
uint32_t t[12]; | |||||
uint32_t x; | |||||
uint32_t sum = 0; | |||||
int32_t r; | |||||
int32_t i; | |||||
int32_t loop; | |||||
uint32_t t[12]; | |||||
uint32_t x; | |||||
uint32_t sum = 0; | |||||
int32_t r; | |||||
int32_t i; | |||||
int32_t loop; | |||||
for (i = 0; i < 12; ++i) { | |||||
t[i] = in[i] ^ seed[12 + i]; | |||||
} | |||||
for (i = 0; i < 8; ++i) { | |||||
out[i] = seed[24 + i]; | |||||
} | |||||
x = t[11]; | |||||
for (loop = 0; loop < 2; ++loop) { | |||||
for (r = 0; r < 16; ++r) { | |||||
sum += 0x9e3779b9; | |||||
MUSH(0, 5) | |||||
MUSH(1, 7) | |||||
MUSH(2, 9) | |||||
MUSH(3, 13) | |||||
MUSH(4, 5) | |||||
MUSH(5, 7) | |||||
MUSH(6, 9) | |||||
MUSH(7, 13) | |||||
MUSH(8, 5) | |||||
MUSH(9, 7) | |||||
MUSH(10, 9) | |||||
MUSH(11, 13) | |||||
for (i = 0; i < 12; ++i) { | |||||
t[i] = in[i] ^ seed[12 + i]; | |||||
} | } | ||||
for (i = 0; i < 8; ++i) { | for (i = 0; i < 8; ++i) { | ||||
out[i] ^= t[i + 4]; | |||||
out[i] = seed[24 + i]; | |||||
} | |||||
x = t[11]; | |||||
for (loop = 0; loop < 2; ++loop) { | |||||
for (r = 0; r < 16; ++r) { | |||||
sum += 0x9e3779b9; | |||||
MUSH(0, 5) | |||||
MUSH(1, 7) | |||||
MUSH(2, 9) | |||||
MUSH(3, 13) | |||||
MUSH(4, 5) | |||||
MUSH(5, 7) | |||||
MUSH(6, 9) | |||||
MUSH(7, 13) | |||||
MUSH(8, 5) | |||||
MUSH(9, 7) | |||||
MUSH(10, 9) | |||||
MUSH(11, 13) | |||||
} | |||||
for (i = 0; i < 8; ++i) { | |||||
out[i] ^= t[i + 4]; | |||||
} | |||||
} | } | ||||
} | |||||
} | } | ||||
void randombytes(uint8_t *x, uint64_t xlen) { | void randombytes(uint8_t *x, uint64_t xlen) { | ||||
while (xlen > 0) { | |||||
if (!outleft) { | |||||
if (!++in[0]) { | |||||
if (!++in[1]) { | |||||
if (!++in[2]) { | |||||
++in[3]; | |||||
} | |||||
while (xlen > 0) { | |||||
if (!outleft) { | |||||
if (!++in[0]) { | |||||
if (!++in[1]) { | |||||
if (!++in[2]) { | |||||
++in[3]; | |||||
} | |||||
} | |||||
} | |||||
surf(); | |||||
outleft = 8; | |||||
} | } | ||||
} | |||||
surf(); | |||||
outleft = 8; | |||||
*x = out[--outleft]; | |||||
++x; | |||||
--xlen; | |||||
} | } | ||||
*x = out[--outleft]; | |||||
++x; | |||||
--xlen; | |||||
} | |||||
} | } |
@@ -7,28 +7,28 @@ | |||||
typedef unsigned long long uint64; | typedef unsigned long long uint64; | ||||
static uint64 load_bigendian(const unsigned char *x) { | static uint64 load_bigendian(const unsigned char *x) { | ||||
return (uint64)(x[7]) | (((uint64)(x[6])) << 8) | (((uint64)(x[5])) << 16) | | |||||
(((uint64)(x[4])) << 24) | (((uint64)(x[3])) << 32) | | |||||
(((uint64)(x[2])) << 40) | (((uint64)(x[1])) << 48) | | |||||
(((uint64)(x[0])) << 56); | |||||
return (uint64)(x[7]) | (((uint64)(x[6])) << 8) | (((uint64)(x[5])) << 16) | | |||||
(((uint64)(x[4])) << 24) | (((uint64)(x[3])) << 32) | | |||||
(((uint64)(x[2])) << 40) | (((uint64)(x[1])) << 48) | | |||||
(((uint64)(x[0])) << 56); | |||||
} | } | ||||
static void store_bigendian(unsigned char *x, uint64 u) { | static void store_bigendian(unsigned char *x, uint64 u) { | ||||
x[7] = u; | |||||
u >>= 8; | |||||
x[6] = u; | |||||
u >>= 8; | |||||
x[5] = u; | |||||
u >>= 8; | |||||
x[4] = u; | |||||
u >>= 8; | |||||
x[3] = u; | |||||
u >>= 8; | |||||
x[2] = u; | |||||
u >>= 8; | |||||
x[1] = u; | |||||
u >>= 8; | |||||
x[0] = u; | |||||
x[7] = u; | |||||
u >>= 8; | |||||
x[6] = u; | |||||
u >>= 8; | |||||
x[5] = u; | |||||
u >>= 8; | |||||
x[4] = u; | |||||
u >>= 8; | |||||
x[3] = u; | |||||
u >>= 8; | |||||
x[2] = u; | |||||
u >>= 8; | |||||
x[1] = u; | |||||
u >>= 8; | |||||
x[0] = u; | |||||
} | } | ||||
#define SHR(x, c) ((x) >> (c)) | #define SHR(x, c) ((x) >> (c)) | ||||
@@ -44,210 +44,210 @@ static void store_bigendian(unsigned char *x, uint64 u) { | |||||
#define M(w0, w14, w9, w1) w0 = sigma1(w14) + (w9) + sigma0(w1) + (w0); | #define M(w0, w14, w9, w1) w0 = sigma1(w14) + (w9) + sigma0(w1) + (w0); | ||||
#define EXPAND \ | #define EXPAND \ | ||||
M(w0, w14, w9, w1) \ | |||||
M(w1, w15, w10, w2) \ | |||||
M(w2, w0, w11, w3) \ | |||||
M(w3, w1, w12, w4) \ | |||||
M(w4, w2, w13, w5) \ | |||||
M(w5, w3, w14, w6) \ | |||||
M(w6, w4, w15, w7) \ | |||||
M(w7, w5, w0, w8) \ | |||||
M(w8, w6, w1, w9) \ | |||||
M(w9, w7, w2, w10) \ | |||||
M(w10, w8, w3, w11) \ | |||||
M(w11, w9, w4, w12) \ | |||||
M(w12, w10, w5, w13) \ | |||||
M(w13, w11, w6, w14) \ | |||||
M(w14, w12, w7, w15) \ | |||||
M(w15, w13, w8, w0) | |||||
M(w0, w14, w9, w1) \ | |||||
M(w1, w15, w10, w2) \ | |||||
M(w2, w0, w11, w3) \ | |||||
M(w3, w1, w12, w4) \ | |||||
M(w4, w2, w13, w5) \ | |||||
M(w5, w3, w14, w6) \ | |||||
M(w6, w4, w15, w7) \ | |||||
M(w7, w5, w0, w8) \ | |||||
M(w8, w6, w1, w9) \ | |||||
M(w9, w7, w2, w10) \ | |||||
M(w10, w8, w3, w11) \ | |||||
M(w11, w9, w4, w12) \ | |||||
M(w12, w10, w5, w13) \ | |||||
M(w13, w11, w6, w14) \ | |||||
M(w14, w12, w7, w15) \ | |||||
M(w15, w13, w8, w0) | |||||
#define F(w, k) \ | #define F(w, k) \ | ||||
T1 = h + Sigma1(e) + Ch(e, f, g) + (k) + (w); \ | |||||
T2 = Sigma0(a) + Maj(a, b, c); \ | |||||
h = g; \ | |||||
g = f; \ | |||||
f = e; \ | |||||
e = d + T1; \ | |||||
d = c; \ | |||||
c = b; \ | |||||
b = a; \ | |||||
a = T1 + T2; | |||||
T1 = h + Sigma1(e) + Ch(e, f, g) + (k) + (w); \ | |||||
T2 = Sigma0(a) + Maj(a, b, c); \ | |||||
h = g; \ | |||||
g = f; \ | |||||
f = e; \ | |||||
e = d + T1; \ | |||||
d = c; \ | |||||
c = b; \ | |||||
b = a; \ | |||||
a = T1 + T2; | |||||
static int crypto_hashblocks_sha512(unsigned char *statebytes, | static int crypto_hashblocks_sha512(unsigned char *statebytes, | ||||
const unsigned char *in, | const unsigned char *in, | ||||
unsigned long long inlen) { | unsigned long long inlen) { | ||||
uint64 state[8]; | |||||
uint64 a; | |||||
uint64 b; | |||||
uint64 c; | |||||
uint64 d; | |||||
uint64 e; | |||||
uint64 f; | |||||
uint64 g; | |||||
uint64 h; | |||||
uint64 T1; | |||||
uint64 T2; | |||||
a = load_bigendian(statebytes + 0); | |||||
state[0] = a; | |||||
b = load_bigendian(statebytes + 8); | |||||
state[1] = b; | |||||
c = load_bigendian(statebytes + 16); | |||||
state[2] = c; | |||||
d = load_bigendian(statebytes + 24); | |||||
state[3] = d; | |||||
e = load_bigendian(statebytes + 32); | |||||
state[4] = e; | |||||
f = load_bigendian(statebytes + 40); | |||||
state[5] = f; | |||||
g = load_bigendian(statebytes + 48); | |||||
state[6] = g; | |||||
h = load_bigendian(statebytes + 56); | |||||
state[7] = h; | |||||
while (inlen >= 128) { | |||||
uint64 w0 = load_bigendian(in + 0); | |||||
uint64 w1 = load_bigendian(in + 8); | |||||
uint64 w2 = load_bigendian(in + 16); | |||||
uint64 w3 = load_bigendian(in + 24); | |||||
uint64 w4 = load_bigendian(in + 32); | |||||
uint64 w5 = load_bigendian(in + 40); | |||||
uint64 w6 = load_bigendian(in + 48); | |||||
uint64 w7 = load_bigendian(in + 56); | |||||
uint64 w8 = load_bigendian(in + 64); | |||||
uint64 w9 = load_bigendian(in + 72); | |||||
uint64 w10 = load_bigendian(in + 80); | |||||
uint64 w11 = load_bigendian(in + 88); | |||||
uint64 w12 = load_bigendian(in + 96); | |||||
uint64 w13 = load_bigendian(in + 104); | |||||
uint64 w14 = load_bigendian(in + 112); | |||||
uint64 w15 = load_bigendian(in + 120); | |||||
F(w0, 0x428a2f98d728ae22ULL) | |||||
F(w1, 0x7137449123ef65cdULL) | |||||
F(w2, 0xb5c0fbcfec4d3b2fULL) | |||||
F(w3, 0xe9b5dba58189dbbcULL) | |||||
F(w4, 0x3956c25bf348b538ULL) | |||||
F(w5, 0x59f111f1b605d019ULL) | |||||
F(w6, 0x923f82a4af194f9bULL) | |||||
F(w7, 0xab1c5ed5da6d8118ULL) | |||||
F(w8, 0xd807aa98a3030242ULL) | |||||
F(w9, 0x12835b0145706fbeULL) | |||||
F(w10, 0x243185be4ee4b28cULL) | |||||
F(w11, 0x550c7dc3d5ffb4e2ULL) | |||||
F(w12, 0x72be5d74f27b896fULL) | |||||
F(w13, 0x80deb1fe3b1696b1ULL) | |||||
F(w14, 0x9bdc06a725c71235ULL) | |||||
F(w15, 0xc19bf174cf692694ULL) | |||||
EXPAND | |||||
F(w0, 0xe49b69c19ef14ad2ULL) | |||||
F(w1, 0xefbe4786384f25e3ULL) | |||||
F(w2, 0x0fc19dc68b8cd5b5ULL) | |||||
F(w3, 0x240ca1cc77ac9c65ULL) | |||||
F(w4, 0x2de92c6f592b0275ULL) | |||||
F(w5, 0x4a7484aa6ea6e483ULL) | |||||
F(w6, 0x5cb0a9dcbd41fbd4ULL) | |||||
F(w7, 0x76f988da831153b5ULL) | |||||
F(w8, 0x983e5152ee66dfabULL) | |||||
F(w9, 0xa831c66d2db43210ULL) | |||||
F(w10, 0xb00327c898fb213fULL) | |||||
F(w11, 0xbf597fc7beef0ee4ULL) | |||||
F(w12, 0xc6e00bf33da88fc2ULL) | |||||
F(w13, 0xd5a79147930aa725ULL) | |||||
F(w14, 0x06ca6351e003826fULL) | |||||
F(w15, 0x142929670a0e6e70ULL) | |||||
EXPAND | |||||
F(w0, 0x27b70a8546d22ffcULL) | |||||
F(w1, 0x2e1b21385c26c926ULL) | |||||
F(w2, 0x4d2c6dfc5ac42aedULL) | |||||
F(w3, 0x53380d139d95b3dfULL) | |||||
F(w4, 0x650a73548baf63deULL) | |||||
F(w5, 0x766a0abb3c77b2a8ULL) | |||||
F(w6, 0x81c2c92e47edaee6ULL) | |||||
F(w7, 0x92722c851482353bULL) | |||||
F(w8, 0xa2bfe8a14cf10364ULL) | |||||
F(w9, 0xa81a664bbc423001ULL) | |||||
F(w10, 0xc24b8b70d0f89791ULL) | |||||
F(w11, 0xc76c51a30654be30ULL) | |||||
F(w12, 0xd192e819d6ef5218ULL) | |||||
F(w13, 0xd69906245565a910ULL) | |||||
F(w14, 0xf40e35855771202aULL) | |||||
F(w15, 0x106aa07032bbd1b8ULL) | |||||
EXPAND | |||||
F(w0, 0x19a4c116b8d2d0c8ULL) | |||||
F(w1, 0x1e376c085141ab53ULL) | |||||
F(w2, 0x2748774cdf8eeb99ULL) | |||||
F(w3, 0x34b0bcb5e19b48a8ULL) | |||||
F(w4, 0x391c0cb3c5c95a63ULL) | |||||
F(w5, 0x4ed8aa4ae3418acbULL) | |||||
F(w6, 0x5b9cca4f7763e373ULL) | |||||
F(w7, 0x682e6ff3d6b2b8a3ULL) | |||||
F(w8, 0x748f82ee5defb2fcULL) | |||||
F(w9, 0x78a5636f43172f60ULL) | |||||
F(w10, 0x84c87814a1f0ab72ULL) | |||||
F(w11, 0x8cc702081a6439ecULL) | |||||
F(w12, 0x90befffa23631e28ULL) | |||||
F(w13, 0xa4506cebde82bde9ULL) | |||||
F(w14, 0xbef9a3f7b2c67915ULL) | |||||
F(w15, 0xc67178f2e372532bULL) | |||||
EXPAND | |||||
F(w0, 0xca273eceea26619cULL) | |||||
F(w1, 0xd186b8c721c0c207ULL) | |||||
F(w2, 0xeada7dd6cde0eb1eULL) | |||||
F(w3, 0xf57d4f7fee6ed178ULL) | |||||
F(w4, 0x06f067aa72176fbaULL) | |||||
F(w5, 0x0a637dc5a2c898a6ULL) | |||||
F(w6, 0x113f9804bef90daeULL) | |||||
F(w7, 0x1b710b35131c471bULL) | |||||
F(w8, 0x28db77f523047d84ULL) | |||||
F(w9, 0x32caab7b40c72493ULL) | |||||
F(w10, 0x3c9ebe0a15c9bebcULL) | |||||
F(w11, 0x431d67c49c100d4cULL) | |||||
F(w12, 0x4cc5d4becb3e42b6ULL) | |||||
F(w13, 0x597f299cfc657e2aULL) | |||||
F(w14, 0x5fcb6fab3ad6faecULL) | |||||
F(w15, 0x6c44198c4a475817ULL) | |||||
a += state[0]; | |||||
b += state[1]; | |||||
c += state[2]; | |||||
d += state[3]; | |||||
e += state[4]; | |||||
f += state[5]; | |||||
g += state[6]; | |||||
h += state[7]; | |||||
uint64 state[8]; | |||||
uint64 a; | |||||
uint64 b; | |||||
uint64 c; | |||||
uint64 d; | |||||
uint64 e; | |||||
uint64 f; | |||||
uint64 g; | |||||
uint64 h; | |||||
uint64 T1; | |||||
uint64 T2; | |||||
a = load_bigendian(statebytes + 0); | |||||
state[0] = a; | state[0] = a; | ||||
b = load_bigendian(statebytes + 8); | |||||
state[1] = b; | state[1] = b; | ||||
c = load_bigendian(statebytes + 16); | |||||
state[2] = c; | state[2] = c; | ||||
d = load_bigendian(statebytes + 24); | |||||
state[3] = d; | state[3] = d; | ||||
e = load_bigendian(statebytes + 32); | |||||
state[4] = e; | state[4] = e; | ||||
f = load_bigendian(statebytes + 40); | |||||
state[5] = f; | state[5] = f; | ||||
g = load_bigendian(statebytes + 48); | |||||
state[6] = g; | state[6] = g; | ||||
h = load_bigendian(statebytes + 56); | |||||
state[7] = h; | state[7] = h; | ||||
in += 128; | |||||
inlen -= 128; | |||||
} | |||||
while (inlen >= 128) { | |||||
uint64 w0 = load_bigendian(in + 0); | |||||
uint64 w1 = load_bigendian(in + 8); | |||||
uint64 w2 = load_bigendian(in + 16); | |||||
uint64 w3 = load_bigendian(in + 24); | |||||
uint64 w4 = load_bigendian(in + 32); | |||||
uint64 w5 = load_bigendian(in + 40); | |||||
uint64 w6 = load_bigendian(in + 48); | |||||
uint64 w7 = load_bigendian(in + 56); | |||||
uint64 w8 = load_bigendian(in + 64); | |||||
uint64 w9 = load_bigendian(in + 72); | |||||
uint64 w10 = load_bigendian(in + 80); | |||||
uint64 w11 = load_bigendian(in + 88); | |||||
uint64 w12 = load_bigendian(in + 96); | |||||
uint64 w13 = load_bigendian(in + 104); | |||||
uint64 w14 = load_bigendian(in + 112); | |||||
uint64 w15 = load_bigendian(in + 120); | |||||
F(w0, 0x428a2f98d728ae22ULL) | |||||
F(w1, 0x7137449123ef65cdULL) | |||||
F(w2, 0xb5c0fbcfec4d3b2fULL) | |||||
F(w3, 0xe9b5dba58189dbbcULL) | |||||
F(w4, 0x3956c25bf348b538ULL) | |||||
F(w5, 0x59f111f1b605d019ULL) | |||||
F(w6, 0x923f82a4af194f9bULL) | |||||
F(w7, 0xab1c5ed5da6d8118ULL) | |||||
F(w8, 0xd807aa98a3030242ULL) | |||||
F(w9, 0x12835b0145706fbeULL) | |||||
F(w10, 0x243185be4ee4b28cULL) | |||||
F(w11, 0x550c7dc3d5ffb4e2ULL) | |||||
F(w12, 0x72be5d74f27b896fULL) | |||||
F(w13, 0x80deb1fe3b1696b1ULL) | |||||
F(w14, 0x9bdc06a725c71235ULL) | |||||
F(w15, 0xc19bf174cf692694ULL) | |||||
EXPAND | |||||
F(w0, 0xe49b69c19ef14ad2ULL) | |||||
F(w1, 0xefbe4786384f25e3ULL) | |||||
F(w2, 0x0fc19dc68b8cd5b5ULL) | |||||
F(w3, 0x240ca1cc77ac9c65ULL) | |||||
F(w4, 0x2de92c6f592b0275ULL) | |||||
F(w5, 0x4a7484aa6ea6e483ULL) | |||||
F(w6, 0x5cb0a9dcbd41fbd4ULL) | |||||
F(w7, 0x76f988da831153b5ULL) | |||||
F(w8, 0x983e5152ee66dfabULL) | |||||
F(w9, 0xa831c66d2db43210ULL) | |||||
F(w10, 0xb00327c898fb213fULL) | |||||
F(w11, 0xbf597fc7beef0ee4ULL) | |||||
F(w12, 0xc6e00bf33da88fc2ULL) | |||||
F(w13, 0xd5a79147930aa725ULL) | |||||
F(w14, 0x06ca6351e003826fULL) | |||||
F(w15, 0x142929670a0e6e70ULL) | |||||
EXPAND | |||||
F(w0, 0x27b70a8546d22ffcULL) | |||||
F(w1, 0x2e1b21385c26c926ULL) | |||||
F(w2, 0x4d2c6dfc5ac42aedULL) | |||||
F(w3, 0x53380d139d95b3dfULL) | |||||
F(w4, 0x650a73548baf63deULL) | |||||
F(w5, 0x766a0abb3c77b2a8ULL) | |||||
F(w6, 0x81c2c92e47edaee6ULL) | |||||
F(w7, 0x92722c851482353bULL) | |||||
F(w8, 0xa2bfe8a14cf10364ULL) | |||||
F(w9, 0xa81a664bbc423001ULL) | |||||
F(w10, 0xc24b8b70d0f89791ULL) | |||||
F(w11, 0xc76c51a30654be30ULL) | |||||
F(w12, 0xd192e819d6ef5218ULL) | |||||
F(w13, 0xd69906245565a910ULL) | |||||
F(w14, 0xf40e35855771202aULL) | |||||
F(w15, 0x106aa07032bbd1b8ULL) | |||||
EXPAND | |||||
F(w0, 0x19a4c116b8d2d0c8ULL) | |||||
F(w1, 0x1e376c085141ab53ULL) | |||||
F(w2, 0x2748774cdf8eeb99ULL) | |||||
F(w3, 0x34b0bcb5e19b48a8ULL) | |||||
F(w4, 0x391c0cb3c5c95a63ULL) | |||||
F(w5, 0x4ed8aa4ae3418acbULL) | |||||
F(w6, 0x5b9cca4f7763e373ULL) | |||||
F(w7, 0x682e6ff3d6b2b8a3ULL) | |||||
F(w8, 0x748f82ee5defb2fcULL) | |||||
F(w9, 0x78a5636f43172f60ULL) | |||||
F(w10, 0x84c87814a1f0ab72ULL) | |||||
F(w11, 0x8cc702081a6439ecULL) | |||||
F(w12, 0x90befffa23631e28ULL) | |||||
F(w13, 0xa4506cebde82bde9ULL) | |||||
F(w14, 0xbef9a3f7b2c67915ULL) | |||||
F(w15, 0xc67178f2e372532bULL) | |||||
EXPAND | |||||
F(w0, 0xca273eceea26619cULL) | |||||
F(w1, 0xd186b8c721c0c207ULL) | |||||
F(w2, 0xeada7dd6cde0eb1eULL) | |||||
F(w3, 0xf57d4f7fee6ed178ULL) | |||||
F(w4, 0x06f067aa72176fbaULL) | |||||
F(w5, 0x0a637dc5a2c898a6ULL) | |||||
F(w6, 0x113f9804bef90daeULL) | |||||
F(w7, 0x1b710b35131c471bULL) | |||||
F(w8, 0x28db77f523047d84ULL) | |||||
F(w9, 0x32caab7b40c72493ULL) | |||||
F(w10, 0x3c9ebe0a15c9bebcULL) | |||||
F(w11, 0x431d67c49c100d4cULL) | |||||
F(w12, 0x4cc5d4becb3e42b6ULL) | |||||
F(w13, 0x597f299cfc657e2aULL) | |||||
F(w14, 0x5fcb6fab3ad6faecULL) | |||||
F(w15, 0x6c44198c4a475817ULL) | |||||
a += state[0]; | |||||
b += state[1]; | |||||
c += state[2]; | |||||
d += state[3]; | |||||
e += state[4]; | |||||
f += state[5]; | |||||
g += state[6]; | |||||
h += state[7]; | |||||
state[0] = a; | |||||
state[1] = b; | |||||
state[2] = c; | |||||
state[3] = d; | |||||
state[4] = e; | |||||
state[5] = f; | |||||
state[6] = g; | |||||
state[7] = h; | |||||
in += 128; | |||||
inlen -= 128; | |||||
} | |||||
store_bigendian(statebytes + 0, state[0]); | |||||
store_bigendian(statebytes + 8, state[1]); | |||||
store_bigendian(statebytes + 16, state[2]); | |||||
store_bigendian(statebytes + 24, state[3]); | |||||
store_bigendian(statebytes + 32, state[4]); | |||||
store_bigendian(statebytes + 40, state[5]); | |||||
store_bigendian(statebytes + 48, state[6]); | |||||
store_bigendian(statebytes + 56, state[7]); | |||||
store_bigendian(statebytes + 0, state[0]); | |||||
store_bigendian(statebytes + 8, state[1]); | |||||
store_bigendian(statebytes + 16, state[2]); | |||||
store_bigendian(statebytes + 24, state[3]); | |||||
store_bigendian(statebytes + 32, state[4]); | |||||
store_bigendian(statebytes + 40, state[5]); | |||||
store_bigendian(statebytes + 48, state[6]); | |||||
store_bigendian(statebytes + 56, state[7]); | |||||
return inlen; | |||||
return inlen; | |||||
} | } | ||||
#define blocks crypto_hashblocks_sha512 | #define blocks crypto_hashblocks_sha512 | ||||
@@ -270,116 +270,116 @@ static const unsigned char iv_512[64] = { | |||||
int sha384(unsigned char *out, const unsigned char *in, | int sha384(unsigned char *out, const unsigned char *in, | ||||
unsigned long long inlen) { | unsigned long long inlen) { | ||||
unsigned char h[64]; | |||||
unsigned char padded[256]; | |||||
unsigned int i; | |||||
unsigned long long bytes = inlen; | |||||
for (i = 0; i < 64; ++i) { | |||||
h[i] = iv_384[i]; | |||||
} | |||||
blocks(h, in, inlen); | |||||
in += inlen; | |||||
inlen &= 127; | |||||
in -= inlen; | |||||
for (i = 0; i < inlen; ++i) { | |||||
padded[i] = in[i]; | |||||
} | |||||
padded[inlen] = 0x80; | |||||
if (inlen < 112) { | |||||
for (i = inlen + 1; i < 119; ++i) { | |||||
padded[i] = 0; | |||||
unsigned char h[64]; | |||||
unsigned char padded[256]; | |||||
unsigned int i; | |||||
unsigned long long bytes = inlen; | |||||
for (i = 0; i < 64; ++i) { | |||||
h[i] = iv_384[i]; | |||||
} | |||||
blocks(h, in, inlen); | |||||
in += inlen; | |||||
inlen &= 127; | |||||
in -= inlen; | |||||
for (i = 0; i < inlen; ++i) { | |||||
padded[i] = in[i]; | |||||
} | } | ||||
padded[119] = bytes >> 61; | |||||
padded[120] = bytes >> 53; | |||||
padded[121] = bytes >> 45; | |||||
padded[122] = bytes >> 37; | |||||
padded[123] = bytes >> 29; | |||||
padded[124] = bytes >> 21; | |||||
padded[125] = bytes >> 13; | |||||
padded[126] = bytes >> 5; | |||||
padded[127] = bytes << 3; | |||||
blocks(h, padded, 128); | |||||
} else { | |||||
for (i = inlen + 1; i < 247; ++i) { | |||||
padded[i] = 0; | |||||
padded[inlen] = 0x80; | |||||
if (inlen < 112) { | |||||
for (i = inlen + 1; i < 119; ++i) { | |||||
padded[i] = 0; | |||||
} | |||||
padded[119] = bytes >> 61; | |||||
padded[120] = bytes >> 53; | |||||
padded[121] = bytes >> 45; | |||||
padded[122] = bytes >> 37; | |||||
padded[123] = bytes >> 29; | |||||
padded[124] = bytes >> 21; | |||||
padded[125] = bytes >> 13; | |||||
padded[126] = bytes >> 5; | |||||
padded[127] = bytes << 3; | |||||
blocks(h, padded, 128); | |||||
} else { | |||||
for (i = inlen + 1; i < 247; ++i) { | |||||
padded[i] = 0; | |||||
} | |||||
padded[247] = bytes >> 61; | |||||
padded[248] = bytes >> 53; | |||||
padded[249] = bytes >> 45; | |||||
padded[250] = bytes >> 37; | |||||
padded[251] = bytes >> 29; | |||||
padded[252] = bytes >> 21; | |||||
padded[253] = bytes >> 13; | |||||
padded[254] = bytes >> 5; | |||||
padded[255] = bytes << 3; | |||||
blocks(h, padded, 256); | |||||
} | |||||
for (i = 0; i < 48; ++i) { | |||||
out[i] = h[i]; | |||||
} | } | ||||
padded[247] = bytes >> 61; | |||||
padded[248] = bytes >> 53; | |||||
padded[249] = bytes >> 45; | |||||
padded[250] = bytes >> 37; | |||||
padded[251] = bytes >> 29; | |||||
padded[252] = bytes >> 21; | |||||
padded[253] = bytes >> 13; | |||||
padded[254] = bytes >> 5; | |||||
padded[255] = bytes << 3; | |||||
blocks(h, padded, 256); | |||||
} | |||||
for (i = 0; i < 48; ++i) { | |||||
out[i] = h[i]; | |||||
} | |||||
return 0; | |||||
return 0; | |||||
} | } | ||||
int sha512(unsigned char *out, const unsigned char *in, | int sha512(unsigned char *out, const unsigned char *in, | ||||
unsigned long long inlen) { | unsigned long long inlen) { | ||||
unsigned char h[64]; | |||||
unsigned char padded[256]; | |||||
unsigned int i; | |||||
unsigned long long bytes = inlen; | |||||
for (i = 0; i < 64; ++i) { | |||||
h[i] = iv_512[i]; | |||||
} | |||||
blocks(h, in, inlen); | |||||
in += inlen; | |||||
inlen &= 127; | |||||
in -= inlen; | |||||
for (i = 0; i < inlen; ++i) { | |||||
padded[i] = in[i]; | |||||
} | |||||
padded[inlen] = 0x80; | |||||
if (inlen < 112) { | |||||
for (i = inlen + 1; i < 119; ++i) { | |||||
padded[i] = 0; | |||||
unsigned char h[64]; | |||||
unsigned char padded[256]; | |||||
unsigned int i; | |||||
unsigned long long bytes = inlen; | |||||
for (i = 0; i < 64; ++i) { | |||||
h[i] = iv_512[i]; | |||||
} | |||||
blocks(h, in, inlen); | |||||
in += inlen; | |||||
inlen &= 127; | |||||
in -= inlen; | |||||
for (i = 0; i < inlen; ++i) { | |||||
padded[i] = in[i]; | |||||
} | |||||
padded[inlen] = 0x80; | |||||
if (inlen < 112) { | |||||
for (i = inlen + 1; i < 119; ++i) { | |||||
padded[i] = 0; | |||||
} | |||||
padded[119] = bytes >> 61; | |||||
padded[120] = bytes >> 53; | |||||
padded[121] = bytes >> 45; | |||||
padded[122] = bytes >> 37; | |||||
padded[123] = bytes >> 29; | |||||
padded[124] = bytes >> 21; | |||||
padded[125] = bytes >> 13; | |||||
padded[126] = bytes >> 5; | |||||
padded[127] = bytes << 3; | |||||
blocks(h, padded, 128); | |||||
} else { | |||||
for (i = inlen + 1; i < 247; ++i) { | |||||
padded[i] = 0; | |||||
} | |||||
padded[247] = bytes >> 61; | |||||
padded[248] = bytes >> 53; | |||||
padded[249] = bytes >> 45; | |||||
padded[250] = bytes >> 37; | |||||
padded[251] = bytes >> 29; | |||||
padded[252] = bytes >> 21; | |||||
padded[253] = bytes >> 13; | |||||
padded[254] = bytes >> 5; | |||||
padded[255] = bytes << 3; | |||||
blocks(h, padded, 256); | |||||
} | } | ||||
padded[119] = bytes >> 61; | |||||
padded[120] = bytes >> 53; | |||||
padded[121] = bytes >> 45; | |||||
padded[122] = bytes >> 37; | |||||
padded[123] = bytes >> 29; | |||||
padded[124] = bytes >> 21; | |||||
padded[125] = bytes >> 13; | |||||
padded[126] = bytes >> 5; | |||||
padded[127] = bytes << 3; | |||||
blocks(h, padded, 128); | |||||
} else { | |||||
for (i = inlen + 1; i < 247; ++i) { | |||||
padded[i] = 0; | |||||
for (i = 0; i < 64; ++i) { | |||||
out[i] = h[i]; | |||||
} | } | ||||
padded[247] = bytes >> 61; | |||||
padded[248] = bytes >> 53; | |||||
padded[249] = bytes >> 45; | |||||
padded[250] = bytes >> 37; | |||||
padded[251] = bytes >> 29; | |||||
padded[252] = bytes >> 21; | |||||
padded[253] = bytes >> 13; | |||||
padded[254] = bytes >> 5; | |||||
padded[255] = bytes << 3; | |||||
blocks(h, padded, 256); | |||||
} | |||||
for (i = 0; i < 64; ++i) { | |||||
out[i] = h[i]; | |||||
} | |||||
return 0; | |||||
return 0; | |||||
} | } |
@@ -13,12 +13,12 @@ | |||||
* Returns 64-bit unsigned integer loaded from x | * Returns 64-bit unsigned integer loaded from x | ||||
**************************************************/ | **************************************************/ | ||||
static uint64_t load_littleendian(const unsigned char *x, int bytes) { | static uint64_t load_littleendian(const unsigned char *x, int bytes) { | ||||
int i; | |||||
uint64_t r = x[0]; | |||||
for (i = 1; i < bytes; i++) { | |||||
r |= (uint64_t)x[i] << (8 * i); | |||||
} | |||||
return r; | |||||
int i; | |||||
uint64_t r = x[0]; | |||||
for (i = 1; i < bytes; i++) { | |||||
r |= (uint64_t)x[i] << (8 * i); | |||||
} | |||||
return r; | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -33,78 +33,78 @@ static uint64_t load_littleendian(const unsigned char *x, int bytes) { | |||||
**************************************************/ | **************************************************/ | ||||
void cbd(poly *r, const unsigned char *buf) { | void cbd(poly *r, const unsigned char *buf) { | ||||
#if KYBER_ETA == 3 | #if KYBER_ETA == 3 | ||||
uint32_t t, d, a[4], b[4]; | |||||
int i, j; | |||||
uint32_t t, d, a[4], b[4]; | |||||
int i, j; | |||||
for (i = 0; i < KYBER_N / 4; i++) { | |||||
t = load_littleendian(buf + 3 * i, 3); | |||||
d = 0; | |||||
for (j = 0; j < 3; j++) | |||||
d += (t >> j) & 0x249249; | |||||
for (i = 0; i < KYBER_N / 4; i++) { | |||||
t = load_littleendian(buf + 3 * i, 3); | |||||
d = 0; | |||||
for (j = 0; j < 3; j++) | |||||
d += (t >> j) & 0x249249; | |||||
a[0] = d & 0x7; | |||||
b[0] = (d >> 3) & 0x7; | |||||
a[1] = (d >> 6) & 0x7; | |||||
b[1] = (d >> 9) & 0x7; | |||||
a[2] = (d >> 12) & 0x7; | |||||
b[2] = (d >> 15) & 0x7; | |||||
a[3] = (d >> 18) & 0x7; | |||||
b[3] = (d >> 21); | |||||
a[0] = d & 0x7; | |||||
b[0] = (d >> 3) & 0x7; | |||||
a[1] = (d >> 6) & 0x7; | |||||
b[1] = (d >> 9) & 0x7; | |||||
a[2] = (d >> 12) & 0x7; | |||||
b[2] = (d >> 15) & 0x7; | |||||
a[3] = (d >> 18) & 0x7; | |||||
b[3] = (d >> 21); | |||||
r->coeffs[4 * i + 0] = a[0] + KYBER_Q - b[0]; | |||||
r->coeffs[4 * i + 1] = a[1] + KYBER_Q - b[1]; | |||||
r->coeffs[4 * i + 2] = a[2] + KYBER_Q - b[2]; | |||||
r->coeffs[4 * i + 3] = a[3] + KYBER_Q - b[3]; | |||||
} | |||||
r->coeffs[4 * i + 0] = a[0] + KYBER_Q - b[0]; | |||||
r->coeffs[4 * i + 1] = a[1] + KYBER_Q - b[1]; | |||||
r->coeffs[4 * i + 2] = a[2] + KYBER_Q - b[2]; | |||||
r->coeffs[4 * i + 3] = a[3] + KYBER_Q - b[3]; | |||||
} | |||||
#elif KYBER_ETA == 4 | #elif KYBER_ETA == 4 | ||||
uint32_t t, d, a[4], b[4]; | |||||
int i, j; | |||||
uint32_t t, d, a[4], b[4]; | |||||
int i, j; | |||||
for (i = 0; i < KYBER_N / 4; i++) { | |||||
t = load_littleendian(buf + 4 * i, 4); | |||||
d = 0; | |||||
for (j = 0; j < 4; j++) { | |||||
d += (t >> j) & 0x11111111; | |||||
} | |||||
for (i = 0; i < KYBER_N / 4; i++) { | |||||
t = load_littleendian(buf + 4 * i, 4); | |||||
d = 0; | |||||
for (j = 0; j < 4; j++) { | |||||
d += (t >> j) & 0x11111111; | |||||
} | |||||
a[0] = d & 0xf; | |||||
b[0] = (d >> 4) & 0xf; | |||||
a[1] = (d >> 8) & 0xf; | |||||
b[1] = (d >> 12) & 0xf; | |||||
a[2] = (d >> 16) & 0xf; | |||||
b[2] = (d >> 20) & 0xf; | |||||
a[3] = (d >> 24) & 0xf; | |||||
b[3] = (d >> 28); | |||||
a[0] = d & 0xf; | |||||
b[0] = (d >> 4) & 0xf; | |||||
a[1] = (d >> 8) & 0xf; | |||||
b[1] = (d >> 12) & 0xf; | |||||
a[2] = (d >> 16) & 0xf; | |||||
b[2] = (d >> 20) & 0xf; | |||||
a[3] = (d >> 24) & 0xf; | |||||
b[3] = (d >> 28); | |||||
r->coeffs[4 * i + 0] = a[0] + KYBER_Q - b[0]; | |||||
r->coeffs[4 * i + 1] = a[1] + KYBER_Q - b[1]; | |||||
r->coeffs[4 * i + 2] = a[2] + KYBER_Q - b[2]; | |||||
r->coeffs[4 * i + 3] = a[3] + KYBER_Q - b[3]; | |||||
} | |||||
r->coeffs[4 * i + 0] = a[0] + KYBER_Q - b[0]; | |||||
r->coeffs[4 * i + 1] = a[1] + KYBER_Q - b[1]; | |||||
r->coeffs[4 * i + 2] = a[2] + KYBER_Q - b[2]; | |||||
r->coeffs[4 * i + 3] = a[3] + KYBER_Q - b[3]; | |||||
} | |||||
#elif KYBER_ETA == 5 | #elif KYBER_ETA == 5 | ||||
uint64_t t, d, a[4], b[4]; | |||||
int i, j; | |||||
uint64_t t, d, a[4], b[4]; | |||||
int i, j; | |||||
for (i = 0; i < KYBER_N / 4; i++) { | |||||
t = load_littleendian(buf + 5 * i, 5); | |||||
d = 0; | |||||
for (j = 0; j < 5; j++) | |||||
d += (t >> j) & 0x0842108421UL; | |||||
for (i = 0; i < KYBER_N / 4; i++) { | |||||
t = load_littleendian(buf + 5 * i, 5); | |||||
d = 0; | |||||
for (j = 0; j < 5; j++) | |||||
d += (t >> j) & 0x0842108421UL; | |||||
a[0] = d & 0x1f; | |||||
b[0] = (d >> 5) & 0x1f; | |||||
a[1] = (d >> 10) & 0x1f; | |||||
b[1] = (d >> 15) & 0x1f; | |||||
a[2] = (d >> 20) & 0x1f; | |||||
b[2] = (d >> 25) & 0x1f; | |||||
a[3] = (d >> 30) & 0x1f; | |||||
b[3] = (d >> 35); | |||||
a[0] = d & 0x1f; | |||||
b[0] = (d >> 5) & 0x1f; | |||||
a[1] = (d >> 10) & 0x1f; | |||||
b[1] = (d >> 15) & 0x1f; | |||||
a[2] = (d >> 20) & 0x1f; | |||||
b[2] = (d >> 25) & 0x1f; | |||||
a[3] = (d >> 30) & 0x1f; | |||||
b[3] = (d >> 35); | |||||
r->coeffs[4 * i + 0] = a[0] + KYBER_Q - b[0]; | |||||
r->coeffs[4 * i + 1] = a[1] + KYBER_Q - b[1]; | |||||
r->coeffs[4 * i + 2] = a[2] + KYBER_Q - b[2]; | |||||
r->coeffs[4 * i + 3] = a[3] + KYBER_Q - b[3]; | |||||
} | |||||
r->coeffs[4 * i + 0] = a[0] + KYBER_Q - b[0]; | |||||
r->coeffs[4 * i + 1] = a[1] + KYBER_Q - b[1]; | |||||
r->coeffs[4 * i + 2] = a[2] + KYBER_Q - b[2]; | |||||
r->coeffs[4 * i + 3] = a[3] + KYBER_Q - b[3]; | |||||
} | |||||
#else | #else | ||||
#error "poly_getnoise in poly.c only supports eta in {3,4,5}" | #error "poly_getnoise in poly.c only supports eta in {3,4,5}" | ||||
#endif | #endif | ||||
@@ -19,11 +19,11 @@ | |||||
**************************************************/ | **************************************************/ | ||||
static void pack_pk(unsigned char *r, const polyvec *pk, | static void pack_pk(unsigned char *r, const polyvec *pk, | ||||
const unsigned char *seed) { | const unsigned char *seed) { | ||||
int i; | |||||
polyvec_compress(r, pk); | |||||
for (i = 0; i < KYBER_SYMBYTES; i++) { | |||||
r[i + KYBER_POLYVECCOMPRESSEDBYTES] = seed[i]; | |||||
} | |||||
int i; | |||||
polyvec_compress(r, pk); | |||||
for (i = 0; i < KYBER_SYMBYTES; i++) { | |||||
r[i + KYBER_POLYVECCOMPRESSEDBYTES] = seed[i]; | |||||
} | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -41,12 +41,12 @@ static void pack_pk(unsigned char *r, const polyvec *pk, | |||||
**************************************************/ | **************************************************/ | ||||
static void unpack_pk(polyvec *pk, unsigned char *seed, | static void unpack_pk(polyvec *pk, unsigned char *seed, | ||||
const unsigned char *packedpk) { | const unsigned char *packedpk) { | ||||
int i; | |||||
polyvec_decompress(pk, packedpk); | |||||
int i; | |||||
polyvec_decompress(pk, packedpk); | |||||
for (i = 0; i < KYBER_SYMBYTES; i++) { | |||||
seed[i] = packedpk[i + KYBER_POLYVECCOMPRESSEDBYTES]; | |||||
} | |||||
for (i = 0; i < KYBER_SYMBYTES; i++) { | |||||
seed[i] = packedpk[i + KYBER_POLYVECCOMPRESSEDBYTES]; | |||||
} | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -61,8 +61,8 @@ static void unpack_pk(polyvec *pk, unsigned char *seed, | |||||
*polynomials b const unsigned char *seed: pointer to the input polynomial v | *polynomials b const unsigned char *seed: pointer to the input polynomial v | ||||
**************************************************/ | **************************************************/ | ||||
static void pack_ciphertext(unsigned char *r, const polyvec *b, const poly *v) { | static void pack_ciphertext(unsigned char *r, const polyvec *b, const poly *v) { | ||||
polyvec_compress(r, b); | |||||
poly_compress(r + KYBER_POLYVECCOMPRESSEDBYTES, v); | |||||
polyvec_compress(r, b); | |||||
poly_compress(r + KYBER_POLYVECCOMPRESSEDBYTES, v); | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -78,8 +78,8 @@ static void pack_ciphertext(unsigned char *r, const polyvec *b, const poly *v) { | |||||
*ciphertext | *ciphertext | ||||
**************************************************/ | **************************************************/ | ||||
static void unpack_ciphertext(polyvec *b, poly *v, const unsigned char *c) { | static void unpack_ciphertext(polyvec *b, poly *v, const unsigned char *c) { | ||||
polyvec_decompress(b, c); | |||||
poly_decompress(v, c + KYBER_POLYVECCOMPRESSEDBYTES); | |||||
polyvec_decompress(b, c); | |||||
poly_decompress(v, c + KYBER_POLYVECCOMPRESSEDBYTES); | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -92,7 +92,7 @@ static void unpack_ciphertext(polyvec *b, poly *v, const unsigned char *c) { | |||||
*(secret key) | *(secret key) | ||||
**************************************************/ | **************************************************/ | ||||
static void pack_sk(unsigned char *r, const polyvec *sk) { | static void pack_sk(unsigned char *r, const polyvec *sk) { | ||||
polyvec_tobytes(r, sk); | |||||
polyvec_tobytes(r, sk); | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -107,7 +107,7 @@ static void pack_sk(unsigned char *r, const polyvec *sk) { | |||||
*secret key | *secret key | ||||
**************************************************/ | **************************************************/ | ||||
static void unpack_sk(polyvec *sk, const unsigned char *packedsk) { | static void unpack_sk(polyvec *sk, const unsigned char *packedsk) { | ||||
polyvec_frombytes(sk, packedsk); | |||||
polyvec_frombytes(sk, packedsk); | |||||
} | } | ||||
#define gen_a(A, B) gen_matrix(A, B, 0) | #define gen_a(A, B) gen_matrix(A, B, 0) | ||||
@@ -129,49 +129,49 @@ static void unpack_sk(polyvec *sk, const unsigned char *packedsk) { | |||||
void gen_matrix(polyvec *a, const unsigned char *seed, | void gen_matrix(polyvec *a, const unsigned char *seed, | ||||
int transposed) // Not static for benchmarking | int transposed) // Not static for benchmarking | ||||
{ | { | ||||
unsigned int pos = 0, ctr; | |||||
uint16_t val; | |||||
unsigned int nblocks; | |||||
const unsigned int maxnblocks = 4; | |||||
uint8_t buf[SHAKE128_RATE * maxnblocks]; | |||||
int i, j; | |||||
uint64_t state[25]; // SHAKE state | |||||
unsigned char extseed[KYBER_SYMBYTES + 2]; | |||||
for (i = 0; i < KYBER_SYMBYTES; i++) { | |||||
extseed[i] = seed[i]; | |||||
} | |||||
for (i = 0; i < KYBER_K; i++) { | |||||
for (j = 0; j < KYBER_K; j++) { | |||||
ctr = pos = 0; | |||||
nblocks = maxnblocks; | |||||
if (transposed) { | |||||
extseed[KYBER_SYMBYTES] = i; | |||||
extseed[KYBER_SYMBYTES + 1] = j; | |||||
} else { | |||||
extseed[KYBER_SYMBYTES] = j; | |||||
extseed[KYBER_SYMBYTES + 1] = i; | |||||
} | |||||
shake128_absorb(state, extseed, KYBER_SYMBYTES + 2); | |||||
shake128_squeezeblocks(buf, nblocks, state); | |||||
while (ctr < KYBER_N) { | |||||
val = (buf[pos] | ((uint16_t)buf[pos + 1] << 8)) & 0x1fff; | |||||
if (val < KYBER_Q) { | |||||
a[i].vec[j].coeffs[ctr++] = val; | |||||
} | |||||
pos += 2; | |||||
unsigned int pos = 0, ctr; | |||||
uint16_t val; | |||||
unsigned int nblocks; | |||||
const unsigned int maxnblocks = 4; | |||||
uint8_t buf[SHAKE128_RATE * maxnblocks]; | |||||
int i, j; | |||||
uint64_t state[25]; // SHAKE state | |||||
unsigned char extseed[KYBER_SYMBYTES + 2]; | |||||
for (i = 0; i < KYBER_SYMBYTES; i++) { | |||||
extseed[i] = seed[i]; | |||||
} | |||||
if (pos > SHAKE128_RATE * nblocks - 2) { | |||||
nblocks = 1; | |||||
shake128_squeezeblocks(buf, nblocks, state); | |||||
pos = 0; | |||||
for (i = 0; i < KYBER_K; i++) { | |||||
for (j = 0; j < KYBER_K; j++) { | |||||
ctr = pos = 0; | |||||
nblocks = maxnblocks; | |||||
if (transposed) { | |||||
extseed[KYBER_SYMBYTES] = i; | |||||
extseed[KYBER_SYMBYTES + 1] = j; | |||||
} else { | |||||
extseed[KYBER_SYMBYTES] = j; | |||||
extseed[KYBER_SYMBYTES + 1] = i; | |||||
} | |||||
shake128_absorb(state, extseed, KYBER_SYMBYTES + 2); | |||||
shake128_squeezeblocks(buf, nblocks, state); | |||||
while (ctr < KYBER_N) { | |||||
val = (buf[pos] | ((uint16_t)buf[pos + 1] << 8)) & 0x1fff; | |||||
if (val < KYBER_Q) { | |||||
a[i].vec[j].coeffs[ctr++] = val; | |||||
} | |||||
pos += 2; | |||||
if (pos > SHAKE128_RATE * nblocks - 2) { | |||||
nblocks = 1; | |||||
shake128_squeezeblocks(buf, nblocks, state); | |||||
pos = 0; | |||||
} | |||||
} | |||||
} | } | ||||
} | |||||
} | } | ||||
} | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -186,38 +186,38 @@ void gen_matrix(polyvec *a, const unsigned char *seed, | |||||
*KYBER_INDCPA_SECRETKEYBYTES bytes) | *KYBER_INDCPA_SECRETKEYBYTES bytes) | ||||
**************************************************/ | **************************************************/ | ||||
void indcpa_keypair(unsigned char *pk, unsigned char *sk) { | void indcpa_keypair(unsigned char *pk, unsigned char *sk) { | ||||
polyvec a[KYBER_K], e, pkpv, skpv; | |||||
unsigned char buf[KYBER_SYMBYTES + KYBER_SYMBYTES]; | |||||
unsigned char *publicseed = buf; | |||||
unsigned char *noiseseed = buf + KYBER_SYMBYTES; | |||||
int i; | |||||
unsigned char nonce = 0; | |||||
polyvec a[KYBER_K], e, pkpv, skpv; | |||||
unsigned char buf[KYBER_SYMBYTES + KYBER_SYMBYTES]; | |||||
unsigned char *publicseed = buf; | |||||
unsigned char *noiseseed = buf + KYBER_SYMBYTES; | |||||
int i; | |||||
unsigned char nonce = 0; | |||||
randombytes(buf, KYBER_SYMBYTES); | |||||
sha3_512(buf, buf, KYBER_SYMBYTES); | |||||
randombytes(buf, KYBER_SYMBYTES); | |||||
sha3_512(buf, buf, KYBER_SYMBYTES); | |||||
gen_a(a, publicseed); | |||||
gen_a(a, publicseed); | |||||
for (i = 0; i < KYBER_K; i++) { | |||||
poly_getnoise(skpv.vec + i, noiseseed, nonce++); | |||||
} | |||||
for (i = 0; i < KYBER_K; i++) { | |||||
poly_getnoise(skpv.vec + i, noiseseed, nonce++); | |||||
} | |||||
polyvec_ntt(&skpv); | |||||
polyvec_ntt(&skpv); | |||||
for (i = 0; i < KYBER_K; i++) { | |||||
poly_getnoise(e.vec + i, noiseseed, nonce++); | |||||
} | |||||
for (i = 0; i < KYBER_K; i++) { | |||||
poly_getnoise(e.vec + i, noiseseed, nonce++); | |||||
} | |||||
// matrix-vector multiplication | |||||
for (i = 0; i < KYBER_K; i++) { | |||||
polyvec_pointwise_acc(&pkpv.vec[i], &skpv, a + i); | |||||
} | |||||
// matrix-vector multiplication | |||||
for (i = 0; i < KYBER_K; i++) { | |||||
polyvec_pointwise_acc(&pkpv.vec[i], &skpv, a + i); | |||||
} | |||||
polyvec_invntt(&pkpv); | |||||
polyvec_add(&pkpv, &pkpv, &e); | |||||
polyvec_invntt(&pkpv); | |||||
polyvec_add(&pkpv, &pkpv, &e); | |||||
pack_sk(sk, &skpv); | |||||
pack_pk(pk, &pkpv, publicseed); | |||||
pack_sk(sk, &skpv); | |||||
pack_pk(pk, &pkpv, publicseed); | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -238,47 +238,47 @@ void indcpa_keypair(unsigned char *pk, unsigned char *sk) { | |||||
**************************************************/ | **************************************************/ | ||||
void indcpa_enc(unsigned char *c, const unsigned char *m, | void indcpa_enc(unsigned char *c, const unsigned char *m, | ||||
const unsigned char *pk, const unsigned char *coins) { | const unsigned char *pk, const unsigned char *coins) { | ||||
polyvec sp, pkpv, ep, at[KYBER_K], bp; | |||||
poly v, k, epp; | |||||
unsigned char seed[KYBER_SYMBYTES]; | |||||
int i; | |||||
unsigned char nonce = 0; | |||||
polyvec sp, pkpv, ep, at[KYBER_K], bp; | |||||
poly v, k, epp; | |||||
unsigned char seed[KYBER_SYMBYTES]; | |||||
int i; | |||||
unsigned char nonce = 0; | |||||
unpack_pk(&pkpv, seed, pk); | |||||
unpack_pk(&pkpv, seed, pk); | |||||
poly_frommsg(&k, m); | |||||
poly_frommsg(&k, m); | |||||
polyvec_ntt(&pkpv); | |||||
polyvec_ntt(&pkpv); | |||||
gen_at(at, seed); | |||||
gen_at(at, seed); | |||||
for (i = 0; i < KYBER_K; i++) { | |||||
poly_getnoise(sp.vec + i, coins, nonce++); | |||||
} | |||||
for (i = 0; i < KYBER_K; i++) { | |||||
poly_getnoise(sp.vec + i, coins, nonce++); | |||||
} | |||||
polyvec_ntt(&sp); | |||||
polyvec_ntt(&sp); | |||||
for (i = 0; i < KYBER_K; i++) { | |||||
poly_getnoise(ep.vec + i, coins, nonce++); | |||||
} | |||||
for (i = 0; i < KYBER_K; i++) { | |||||
poly_getnoise(ep.vec + i, coins, nonce++); | |||||
} | |||||
// matrix-vector multiplication | |||||
for (i = 0; i < KYBER_K; i++) { | |||||
polyvec_pointwise_acc(&bp.vec[i], &sp, at + i); | |||||
} | |||||
// matrix-vector multiplication | |||||
for (i = 0; i < KYBER_K; i++) { | |||||
polyvec_pointwise_acc(&bp.vec[i], &sp, at + i); | |||||
} | |||||
polyvec_invntt(&bp); | |||||
polyvec_add(&bp, &bp, &ep); | |||||
polyvec_invntt(&bp); | |||||
polyvec_add(&bp, &bp, &ep); | |||||
polyvec_pointwise_acc(&v, &pkpv, &sp); | |||||
poly_invntt(&v); | |||||
polyvec_pointwise_acc(&v, &pkpv, &sp); | |||||
poly_invntt(&v); | |||||
poly_getnoise(&epp, coins, nonce++); | |||||
poly_getnoise(&epp, coins, nonce++); | |||||
poly_add(&v, &v, &epp); | |||||
poly_add(&v, &v, &k); | |||||
poly_add(&v, &v, &epp); | |||||
poly_add(&v, &v, &k); | |||||
pack_ciphertext(c, &bp, &v); | |||||
pack_ciphertext(c, &bp, &v); | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -296,18 +296,18 @@ void indcpa_enc(unsigned char *c, const unsigned char *m, | |||||
**************************************************/ | **************************************************/ | ||||
void indcpa_dec(unsigned char *m, const unsigned char *c, | void indcpa_dec(unsigned char *m, const unsigned char *c, | ||||
const unsigned char *sk) { | const unsigned char *sk) { | ||||
polyvec bp, skpv; | |||||
poly v, mp; | |||||
polyvec bp, skpv; | |||||
poly v, mp; | |||||
unpack_ciphertext(&bp, &v, c); | |||||
unpack_sk(&skpv, sk); | |||||
unpack_ciphertext(&bp, &v, c); | |||||
unpack_sk(&skpv, sk); | |||||
polyvec_ntt(&bp); | |||||
polyvec_ntt(&bp); | |||||
polyvec_pointwise_acc(&mp, &skpv, &bp); | |||||
poly_invntt(&mp); | |||||
polyvec_pointwise_acc(&mp, &skpv, &bp); | |||||
poly_invntt(&mp); | |||||
poly_sub(&mp, &mp, &v); | |||||
poly_sub(&mp, &mp, &v); | |||||
poly_tomsg(m, &mp); | |||||
poly_tomsg(m, &mp); | |||||
} | } |
@@ -1,122 +1,126 @@ | |||||
#include "api.h" | |||||
#include "fips202.h" | |||||
#include "indcpa.h" | |||||
#include "params.h" | |||||
#include "randombytes.h" | |||||
#include "verify.h" | |||||
/************************************************* | |||||
* Name: crypto_kem_keypair | |||||
* | |||||
* Description: Generates public and private key | |||||
* for CCA-secure Kyber key encapsulation mechanism | |||||
* | |||||
* Arguments: - unsigned char *pk: pointer to output public key (an already | |||||
*allocated array of CRYPTO_PUBLICKEYBYTES bytes) | |||||
* - unsigned char *sk: pointer to output private key (an already | |||||
*allocated array of CRYPTO_SECRETKEYBYTES bytes) | |||||
* | |||||
* Returns 0 (success) | |||||
**************************************************/ | |||||
int crypto_kem_keypair(unsigned char *pk, unsigned char *sk) { | |||||
size_t i; | |||||
indcpa_keypair(pk, sk); | |||||
for (i = 0; i < KYBER_INDCPA_PUBLICKEYBYTES; i++) { | |||||
sk[i + KYBER_INDCPA_SECRETKEYBYTES] = pk[i]; | |||||
} | |||||
sha3_256(sk + KYBER_SECRETKEYBYTES - 2 * KYBER_SYMBYTES, pk, | |||||
KYBER_PUBLICKEYBYTES); | |||||
randombytes(sk + KYBER_SECRETKEYBYTES - KYBER_SYMBYTES, | |||||
KYBER_SYMBYTES); /* Value z for pseudo-random output on reject */ | |||||
return 0; | |||||
} | |||||
/************************************************* | |||||
* Name: crypto_kem_enc | |||||
* | |||||
* Description: Generates cipher text and shared | |||||
* secret for given public key | |||||
* | |||||
* Arguments: - unsigned char *ct: pointer to output cipher text (an | |||||
*already allocated array of CRYPTO_CIPHERTEXTBYTES bytes) | |||||
* - unsigned char *ss: pointer to output shared secret (an | |||||
*already allocated array of CRYPTO_BYTES bytes) | |||||
* - const unsigned char *pk: pointer to input public key (an | |||||
*already allocated array of CRYPTO_PUBLICKEYBYTES bytes) | |||||
* | |||||
* Returns 0 (success) | |||||
**************************************************/ | |||||
int crypto_kem_enc(unsigned char *ct, unsigned char *ss, | |||||
const unsigned char *pk) { | |||||
unsigned char kr[2 * KYBER_SYMBYTES]; /* Will contain key, coins */ | |||||
unsigned char buf[2 * KYBER_SYMBYTES]; | |||||
randombytes(buf, KYBER_SYMBYTES); | |||||
sha3_256(buf, buf, KYBER_SYMBYTES); /* Don't release system RNG output */ | |||||
sha3_256(buf + KYBER_SYMBYTES, pk, | |||||
KYBER_PUBLICKEYBYTES); /* Multitarget countermeasure for coins + | |||||
contributory KEM */ | |||||
sha3_512(kr, buf, 2 * KYBER_SYMBYTES); | |||||
indcpa_enc(ct, buf, pk, | |||||
kr + KYBER_SYMBYTES); /* coins are in kr+KYBER_SYMBYTES */ | |||||
sha3_256(kr + KYBER_SYMBYTES, ct, | |||||
KYBER_CIPHERTEXTBYTES); /* overwrite coins in kr with H(c) */ | |||||
sha3_256(ss, kr, | |||||
2 * KYBER_SYMBYTES); /* hash concatenation of pre-k and H(c) to k */ | |||||
return 0; | |||||
} | |||||
/************************************************* | |||||
* Name: crypto_kem_dec | |||||
* | |||||
* Description: Generates shared secret for given | |||||
* cipher text and private key | |||||
* | |||||
* Arguments: - unsigned char *ss: pointer to output shared secret (an | |||||
*already allocated array of CRYPTO_BYTES bytes) | |||||
* - const unsigned char *ct: pointer to input cipher text (an | |||||
*already allocated array of CRYPTO_CIPHERTEXTBYTES bytes) | |||||
* - const unsigned char *sk: pointer to input private key (an | |||||
*already allocated array of CRYPTO_SECRETKEYBYTES bytes) | |||||
* | |||||
* Returns 0. | |||||
* | |||||
* On failure, ss will contain a pseudo-random value. | |||||
**************************************************/ | |||||
int crypto_kem_dec(unsigned char *ss, const unsigned char *ct, | |||||
const unsigned char *sk) { | |||||
size_t i; | |||||
int fail; | |||||
unsigned char cmp[KYBER_CIPHERTEXTBYTES]; | |||||
unsigned char buf[2 * KYBER_SYMBYTES]; | |||||
unsigned char kr[2 * KYBER_SYMBYTES]; /* Will contain key, coins, qrom-hash */ | |||||
const unsigned char *pk = sk + KYBER_INDCPA_SECRETKEYBYTES; | |||||
indcpa_dec(buf, ct, sk); | |||||
for (i = 0; i < KYBER_SYMBYTES; | |||||
i++) { /* Multitarget countermeasure for coins + contributory KEM */ | |||||
buf[KYBER_SYMBYTES + i] = sk[KYBER_SECRETKEYBYTES - 2 * KYBER_SYMBYTES + | |||||
i]; /* Save hash by storing H(pk) in sk */ | |||||
} | |||||
sha3_512(kr, buf, 2 * KYBER_SYMBYTES); | |||||
indcpa_enc(cmp, buf, pk, | |||||
kr + KYBER_SYMBYTES); /* coins are in kr+KYBER_SYMBYTES */ | |||||
fail = verify(ct, cmp, KYBER_CIPHERTEXTBYTES); | |||||
sha3_256(kr + KYBER_SYMBYTES, ct, | |||||
KYBER_CIPHERTEXTBYTES); /* overwrite coins in kr with H(c) */ | |||||
cmov(kr, sk + KYBER_SECRETKEYBYTES - KYBER_SYMBYTES, KYBER_SYMBYTES, | |||||
fail); /* Overwrite pre-k with z on re-encryption failure */ | |||||
sha3_256(ss, kr, | |||||
2 * KYBER_SYMBYTES); /* hash concatenation of pre-k and H(c) to k */ | |||||
return 0; | |||||
} | |||||
#include "api.h" | |||||
#include "fips202.h" | |||||
#include "indcpa.h" | |||||
#include "params.h" | |||||
#include "randombytes.h" | |||||
#include "verify.h" | |||||
/************************************************* | |||||
* Name: crypto_kem_keypair | |||||
* | |||||
* Description: Generates public and private key | |||||
* for CCA-secure Kyber key encapsulation mechanism | |||||
* | |||||
* Arguments: - unsigned char *pk: pointer to output public key (an already | |||||
*allocated array of CRYPTO_PUBLICKEYBYTES bytes) | |||||
* - unsigned char *sk: pointer to output private key (an already | |||||
*allocated array of CRYPTO_SECRETKEYBYTES bytes) | |||||
* | |||||
* Returns 0 (success) | |||||
**************************************************/ | |||||
int crypto_kem_keypair(unsigned char *pk, unsigned char *sk) { | |||||
size_t i; | |||||
indcpa_keypair(pk, sk); | |||||
for (i = 0; i < KYBER_INDCPA_PUBLICKEYBYTES; i++) { | |||||
sk[i + KYBER_INDCPA_SECRETKEYBYTES] = pk[i]; | |||||
} | |||||
sha3_256(sk + KYBER_SECRETKEYBYTES - 2 * KYBER_SYMBYTES, pk, | |||||
KYBER_PUBLICKEYBYTES); | |||||
randombytes( | |||||
sk + KYBER_SECRETKEYBYTES - KYBER_SYMBYTES, | |||||
KYBER_SYMBYTES); /* Value z for pseudo-random output on reject */ | |||||
return 0; | |||||
} | |||||
/************************************************* | |||||
* Name: crypto_kem_enc | |||||
* | |||||
* Description: Generates cipher text and shared | |||||
* secret for given public key | |||||
* | |||||
* Arguments: - unsigned char *ct: pointer to output cipher text (an | |||||
*already allocated array of CRYPTO_CIPHERTEXTBYTES bytes) | |||||
* - unsigned char *ss: pointer to output shared secret (an | |||||
*already allocated array of CRYPTO_BYTES bytes) | |||||
* - const unsigned char *pk: pointer to input public key (an | |||||
*already allocated array of CRYPTO_PUBLICKEYBYTES bytes) | |||||
* | |||||
* Returns 0 (success) | |||||
**************************************************/ | |||||
int crypto_kem_enc(unsigned char *ct, unsigned char *ss, | |||||
const unsigned char *pk) { | |||||
unsigned char kr[2 * KYBER_SYMBYTES]; /* Will contain key, coins */ | |||||
unsigned char buf[2 * KYBER_SYMBYTES]; | |||||
randombytes(buf, KYBER_SYMBYTES); | |||||
sha3_256(buf, buf, KYBER_SYMBYTES); /* Don't release system RNG output */ | |||||
sha3_256(buf + KYBER_SYMBYTES, pk, | |||||
KYBER_PUBLICKEYBYTES); /* Multitarget countermeasure for coins + | |||||
contributory KEM */ | |||||
sha3_512(kr, buf, 2 * KYBER_SYMBYTES); | |||||
indcpa_enc(ct, buf, pk, | |||||
kr + KYBER_SYMBYTES); /* coins are in kr+KYBER_SYMBYTES */ | |||||
sha3_256(kr + KYBER_SYMBYTES, ct, | |||||
KYBER_CIPHERTEXTBYTES); /* overwrite coins in kr with H(c) */ | |||||
sha3_256( | |||||
ss, kr, | |||||
2 * KYBER_SYMBYTES); /* hash concatenation of pre-k and H(c) to k */ | |||||
return 0; | |||||
} | |||||
/************************************************* | |||||
* Name: crypto_kem_dec | |||||
* | |||||
* Description: Generates shared secret for given | |||||
* cipher text and private key | |||||
* | |||||
* Arguments: - unsigned char *ss: pointer to output shared secret (an | |||||
*already allocated array of CRYPTO_BYTES bytes) | |||||
* - const unsigned char *ct: pointer to input cipher text (an | |||||
*already allocated array of CRYPTO_CIPHERTEXTBYTES bytes) | |||||
* - const unsigned char *sk: pointer to input private key (an | |||||
*already allocated array of CRYPTO_SECRETKEYBYTES bytes) | |||||
* | |||||
* Returns 0. | |||||
* | |||||
* On failure, ss will contain a pseudo-random value. | |||||
**************************************************/ | |||||
int crypto_kem_dec(unsigned char *ss, const unsigned char *ct, | |||||
const unsigned char *sk) { | |||||
size_t i; | |||||
int fail; | |||||
unsigned char cmp[KYBER_CIPHERTEXTBYTES]; | |||||
unsigned char buf[2 * KYBER_SYMBYTES]; | |||||
unsigned char | |||||
kr[2 * KYBER_SYMBYTES]; /* Will contain key, coins, qrom-hash */ | |||||
const unsigned char *pk = sk + KYBER_INDCPA_SECRETKEYBYTES; | |||||
indcpa_dec(buf, ct, sk); | |||||
for (i = 0; i < KYBER_SYMBYTES; | |||||
i++) { /* Multitarget countermeasure for coins + contributory KEM */ | |||||
buf[KYBER_SYMBYTES + i] = sk[KYBER_SECRETKEYBYTES - 2 * KYBER_SYMBYTES + | |||||
i]; /* Save hash by storing H(pk) in sk */ | |||||
} | |||||
sha3_512(kr, buf, 2 * KYBER_SYMBYTES); | |||||
indcpa_enc(cmp, buf, pk, | |||||
kr + KYBER_SYMBYTES); /* coins are in kr+KYBER_SYMBYTES */ | |||||
fail = verify(ct, cmp, KYBER_CIPHERTEXTBYTES); | |||||
sha3_256(kr + KYBER_SYMBYTES, ct, | |||||
KYBER_CIPHERTEXTBYTES); /* overwrite coins in kr with H(c) */ | |||||
cmov(kr, sk + KYBER_SECRETKEYBYTES - KYBER_SYMBYTES, KYBER_SYMBYTES, | |||||
fail); /* Overwrite pre-k with z on re-encryption failure */ | |||||
sha3_256( | |||||
ss, kr, | |||||
2 * KYBER_SYMBYTES); /* hash concatenation of pre-k and H(c) to k */ | |||||
return 0; | |||||
} |
@@ -3,49 +3,49 @@ | |||||
#include "verify.h" | #include "verify.h" | ||||
void kyber_uake_initA(u8 *send, u8 *tk, u8 *sk, const u8 *pkb) { | void kyber_uake_initA(u8 *send, u8 *tk, u8 *sk, const u8 *pkb) { | ||||
crypto_kem_keypair(send, sk); | |||||
crypto_kem_enc(send + KYBER_PUBLICKEYBYTES, tk, pkb); | |||||
crypto_kem_keypair(send, sk); | |||||
crypto_kem_enc(send + KYBER_PUBLICKEYBYTES, tk, pkb); | |||||
} | } | ||||
void kyber_uake_sharedB(u8 *send, u8 *k, const u8 *recv, const u8 *skb) { | void kyber_uake_sharedB(u8 *send, u8 *k, const u8 *recv, const u8 *skb) { | ||||
unsigned char buf[2 * KYBER_SYMBYTES]; | |||||
crypto_kem_enc(send, buf, recv); | |||||
crypto_kem_dec(buf + KYBER_SYMBYTES, recv + KYBER_PUBLICKEYBYTES, skb); | |||||
shake256(k, KYBER_SYMBYTES, buf, 2 * KYBER_SYMBYTES); | |||||
unsigned char buf[2 * KYBER_SYMBYTES]; | |||||
crypto_kem_enc(send, buf, recv); | |||||
crypto_kem_dec(buf + KYBER_SYMBYTES, recv + KYBER_PUBLICKEYBYTES, skb); | |||||
shake256(k, KYBER_SYMBYTES, buf, 2 * KYBER_SYMBYTES); | |||||
} | } | ||||
void kyber_uake_sharedA(u8 *k, const u8 *recv, const u8 *tk, const u8 *sk) { | void kyber_uake_sharedA(u8 *k, const u8 *recv, const u8 *tk, const u8 *sk) { | ||||
unsigned char buf[2 * KYBER_SYMBYTES]; | |||||
int i; | |||||
crypto_kem_dec(buf, recv, sk); | |||||
for (i = 0; i < KYBER_SYMBYTES; i++) { | |||||
buf[i + KYBER_SYMBYTES] = tk[i]; | |||||
} | |||||
shake256(k, KYBER_SYMBYTES, buf, 2 * KYBER_SYMBYTES); | |||||
unsigned char buf[2 * KYBER_SYMBYTES]; | |||||
int i; | |||||
crypto_kem_dec(buf, recv, sk); | |||||
for (i = 0; i < KYBER_SYMBYTES; i++) { | |||||
buf[i + KYBER_SYMBYTES] = tk[i]; | |||||
} | |||||
shake256(k, KYBER_SYMBYTES, buf, 2 * KYBER_SYMBYTES); | |||||
} | } | ||||
void kyber_ake_initA(u8 *send, u8 *tk, u8 *sk, const u8 *pkb) { | void kyber_ake_initA(u8 *send, u8 *tk, u8 *sk, const u8 *pkb) { | ||||
crypto_kem_keypair(send, sk); | |||||
crypto_kem_enc(send + KYBER_PUBLICKEYBYTES, tk, pkb); | |||||
crypto_kem_keypair(send, sk); | |||||
crypto_kem_enc(send + KYBER_PUBLICKEYBYTES, tk, pkb); | |||||
} | } | ||||
void kyber_ake_sharedB(u8 *send, u8 *k, const u8 *recv, const u8 *skb, | void kyber_ake_sharedB(u8 *send, u8 *k, const u8 *recv, const u8 *skb, | ||||
const u8 *pka) { | const u8 *pka) { | ||||
unsigned char buf[3 * KYBER_SYMBYTES]; | |||||
crypto_kem_enc(send, buf, recv); | |||||
crypto_kem_enc(send + KYBER_CIPHERTEXTBYTES, buf + KYBER_SYMBYTES, pka); | |||||
crypto_kem_dec(buf + 2 * KYBER_SYMBYTES, recv + KYBER_PUBLICKEYBYTES, skb); | |||||
shake256(k, KYBER_SYMBYTES, buf, 3 * KYBER_SYMBYTES); | |||||
unsigned char buf[3 * KYBER_SYMBYTES]; | |||||
crypto_kem_enc(send, buf, recv); | |||||
crypto_kem_enc(send + KYBER_CIPHERTEXTBYTES, buf + KYBER_SYMBYTES, pka); | |||||
crypto_kem_dec(buf + 2 * KYBER_SYMBYTES, recv + KYBER_PUBLICKEYBYTES, skb); | |||||
shake256(k, KYBER_SYMBYTES, buf, 3 * KYBER_SYMBYTES); | |||||
} | } | ||||
void kyber_ake_sharedA(u8 *k, const u8 *recv, const u8 *tk, const u8 *sk, | void kyber_ake_sharedA(u8 *k, const u8 *recv, const u8 *tk, const u8 *sk, | ||||
const u8 *ska) { | const u8 *ska) { | ||||
unsigned char buf[3 * KYBER_SYMBYTES]; | |||||
int i; | |||||
crypto_kem_dec(buf, recv, sk); | |||||
crypto_kem_dec(buf + KYBER_SYMBYTES, recv + KYBER_CIPHERTEXTBYTES, ska); | |||||
for (i = 0; i < KYBER_SYMBYTES; i++) { | |||||
buf[i + 2 * KYBER_SYMBYTES] = tk[i]; | |||||
} | |||||
shake256(k, KYBER_SYMBYTES, buf, 3 * KYBER_SYMBYTES); | |||||
unsigned char buf[3 * KYBER_SYMBYTES]; | |||||
int i; | |||||
crypto_kem_dec(buf, recv, sk); | |||||
crypto_kem_dec(buf + KYBER_SYMBYTES, recv + KYBER_CIPHERTEXTBYTES, ska); | |||||
for (i = 0; i < KYBER_SYMBYTES; i++) { | |||||
buf[i + 2 * KYBER_SYMBYTES] = tk[i]; | |||||
} | |||||
shake256(k, KYBER_SYMBYTES, buf, 3 * KYBER_SYMBYTES); | |||||
} | } |
@@ -1,80 +1,81 @@ | |||||
#include "ntt.h" | |||||
#include "inttypes.h" | |||||
#include "params.h" | |||||
#include "reduce.h" | |||||
extern const uint16_t omegas_inv_bitrev_montgomery[]; | |||||
extern const uint16_t psis_inv_montgomery[]; | |||||
extern const uint16_t zetas[]; | |||||
/************************************************* | |||||
* Name: ntt | |||||
* | |||||
* Description: Computes negacyclic number-theoretic transform (NTT) of | |||||
* a polynomial (vector of 256 coefficients) in place; | |||||
* inputs assumed to be in normal order, output in bitreversed | |||||
*order | |||||
* | |||||
* Arguments: - uint16_t *p: pointer to in/output polynomial | |||||
**************************************************/ | |||||
void ntt(uint16_t *p) { | |||||
int level, start, j, k; | |||||
uint16_t zeta, t; | |||||
k = 1; | |||||
for (level = 7; level >= 0; level--) { | |||||
for (start = 0; start < KYBER_N; start = j + (1 << level)) { | |||||
zeta = zetas[k++]; | |||||
for (j = start; j < start + (1 << level); ++j) { | |||||
t = montgomery_reduce((uint32_t)zeta * p[j + (1 << level)]); | |||||
p[j + (1 << level)] = barrett_reduce(p[j] + 4 * KYBER_Q - t); | |||||
if (level & 1) { /* odd level */ | |||||
p[j] = p[j] + t; /* Omit reduction (be lazy) */ | |||||
} else { | |||||
p[j] = barrett_reduce(p[j] + t); | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} | |||||
/************************************************* | |||||
* Name: invntt | |||||
* | |||||
* Description: Computes inverse of negacyclic number-theoretic transform (NTT) | |||||
*of a polynomial (vector of 256 coefficients) in place; inputs assumed to be in | |||||
*bitreversed order, output in normal order | |||||
* | |||||
* Arguments: - uint16_t *a: pointer to in/output polynomial | |||||
**************************************************/ | |||||
void invntt(uint16_t *a) { | |||||
int start, j, jTwiddle, level; | |||||
uint16_t temp, W; | |||||
uint32_t t; | |||||
for (level = 0; level < 8; level++) { | |||||
for (start = 0; start < (1 << level); start++) { | |||||
jTwiddle = 0; | |||||
for (j = start; j < KYBER_N - 1; j += 2 * (1 << level)) { | |||||
W = omegas_inv_bitrev_montgomery[jTwiddle++]; | |||||
temp = a[j]; | |||||
if (level & 1) { /* odd level */ | |||||
a[j] = barrett_reduce((temp + a[j + (1 << level)])); | |||||
} else { | |||||
a[j] = (temp + a[j + (1 << level)]); /* Omit reduction (be lazy) */ | |||||
} | |||||
t = (W * ((uint32_t)temp + 4 * KYBER_Q - a[j + (1 << level)])); | |||||
a[j + (1 << level)] = montgomery_reduce(t); | |||||
} | |||||
} | |||||
} | |||||
for (j = 0; j < KYBER_N; j++) { | |||||
a[j] = montgomery_reduce((a[j] * psis_inv_montgomery[j])); | |||||
} | |||||
} | |||||
#include "ntt.h" | |||||
#include "inttypes.h" | |||||
#include "params.h" | |||||
#include "reduce.h" | |||||
extern const uint16_t omegas_inv_bitrev_montgomery[]; | |||||
extern const uint16_t psis_inv_montgomery[]; | |||||
extern const uint16_t zetas[]; | |||||
/************************************************* | |||||
* Name: ntt | |||||
* | |||||
* Description: Computes negacyclic number-theoretic transform (NTT) of | |||||
* a polynomial (vector of 256 coefficients) in place; | |||||
* inputs assumed to be in normal order, output in bitreversed | |||||
*order | |||||
* | |||||
* Arguments: - uint16_t *p: pointer to in/output polynomial | |||||
**************************************************/ | |||||
void ntt(uint16_t *p) { | |||||
int level, start, j, k; | |||||
uint16_t zeta, t; | |||||
k = 1; | |||||
for (level = 7; level >= 0; level--) { | |||||
for (start = 0; start < KYBER_N; start = j + (1 << level)) { | |||||
zeta = zetas[k++]; | |||||
for (j = start; j < start + (1 << level); ++j) { | |||||
t = montgomery_reduce((uint32_t)zeta * p[j + (1 << level)]); | |||||
p[j + (1 << level)] = barrett_reduce(p[j] + 4 * KYBER_Q - t); | |||||
if (level & 1) { /* odd level */ | |||||
p[j] = p[j] + t; /* Omit reduction (be lazy) */ | |||||
} else { | |||||
p[j] = barrett_reduce(p[j] + t); | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} | |||||
/************************************************* | |||||
* Name: invntt | |||||
* | |||||
* Description: Computes inverse of negacyclic number-theoretic transform (NTT) | |||||
*of a polynomial (vector of 256 coefficients) in place; inputs assumed to be in | |||||
*bitreversed order, output in normal order | |||||
* | |||||
* Arguments: - uint16_t *a: pointer to in/output polynomial | |||||
**************************************************/ | |||||
void invntt(uint16_t *a) { | |||||
int start, j, jTwiddle, level; | |||||
uint16_t temp, W; | |||||
uint32_t t; | |||||
for (level = 0; level < 8; level++) { | |||||
for (start = 0; start < (1 << level); start++) { | |||||
jTwiddle = 0; | |||||
for (j = start; j < KYBER_N - 1; j += 2 * (1 << level)) { | |||||
W = omegas_inv_bitrev_montgomery[jTwiddle++]; | |||||
temp = a[j]; | |||||
if (level & 1) { /* odd level */ | |||||
a[j] = barrett_reduce((temp + a[j + (1 << level)])); | |||||
} else { | |||||
a[j] = (temp + | |||||
a[j + (1 << level)]); /* Omit reduction (be lazy) */ | |||||
} | |||||
t = (W * ((uint32_t)temp + 4 * KYBER_Q - a[j + (1 << level)])); | |||||
a[j + (1 << level)] = montgomery_reduce(t); | |||||
} | |||||
} | |||||
} | |||||
for (j = 0; j < KYBER_N; j++) { | |||||
a[j] = montgomery_reduce((a[j] * psis_inv_montgomery[j])); | |||||
} | |||||
} |
@@ -1,9 +1,9 @@ | |||||
#ifndef NTT_H | |||||
#define NTT_H | |||||
#include <stdint.h> | |||||
void ntt(uint16_t *poly); | |||||
void invntt(uint16_t *a); | |||||
#endif | |||||
#ifndef NTT_H | |||||
#define NTT_H | |||||
#include <stdint.h> | |||||
void ntt(uint16_t *poly); | |||||
void invntt(uint16_t *a); | |||||
#endif |
@@ -1,31 +1,31 @@ | |||||
#ifndef PARAMS_H | |||||
#define PARAMS_H | |||||
#define KYBER_K 3 | |||||
#define KYBER_N 256 | |||||
#define KYBER_Q 7681 | |||||
#define KYBER_ETA 4 | |||||
#define KYBER_SYMBYTES 32 /* size in bytes of shared key, hashes, and seeds */ | |||||
#define KYBER_POLYBYTES 416 | |||||
#define KYBER_POLYCOMPRESSEDBYTES 96 | |||||
#define KYBER_POLYVECBYTES (KYBER_K * KYBER_POLYBYTES) | |||||
#define KYBER_POLYVECCOMPRESSEDBYTES (KYBER_K * 352) | |||||
#define KYBER_INDCPA_MSGBYTES KYBER_SYMBYTES | |||||
#define KYBER_INDCPA_PUBLICKEYBYTES \ | |||||
(KYBER_POLYVECCOMPRESSEDBYTES + KYBER_SYMBYTES) | |||||
#define KYBER_INDCPA_SECRETKEYBYTES (KYBER_POLYVECBYTES) | |||||
#define KYBER_INDCPA_BYTES \ | |||||
(KYBER_POLYVECCOMPRESSEDBYTES + KYBER_POLYCOMPRESSEDBYTES) | |||||
#define KYBER_PUBLICKEYBYTES (KYBER_INDCPA_PUBLICKEYBYTES) | |||||
#define KYBER_SECRETKEYBYTES \ | |||||
(KYBER_INDCPA_SECRETKEYBYTES + KYBER_INDCPA_PUBLICKEYBYTES + \ | |||||
2 * KYBER_SYMBYTES) /* 32 bytes of additional space to save H(pk) */ | |||||
#define KYBER_CIPHERTEXTBYTES KYBER_INDCPA_BYTES | |||||
#endif | |||||
#ifndef PARAMS_H | |||||
#define PARAMS_H | |||||
#define KYBER_K 3 | |||||
#define KYBER_N 256 | |||||
#define KYBER_Q 7681 | |||||
#define KYBER_ETA 4 | |||||
#define KYBER_SYMBYTES 32 /* size in bytes of shared key, hashes, and seeds */ | |||||
#define KYBER_POLYBYTES 416 | |||||
#define KYBER_POLYCOMPRESSEDBYTES 96 | |||||
#define KYBER_POLYVECBYTES (KYBER_K * KYBER_POLYBYTES) | |||||
#define KYBER_POLYVECCOMPRESSEDBYTES (KYBER_K * 352) | |||||
#define KYBER_INDCPA_MSGBYTES KYBER_SYMBYTES | |||||
#define KYBER_INDCPA_PUBLICKEYBYTES \ | |||||
(KYBER_POLYVECCOMPRESSEDBYTES + KYBER_SYMBYTES) | |||||
#define KYBER_INDCPA_SECRETKEYBYTES (KYBER_POLYVECBYTES) | |||||
#define KYBER_INDCPA_BYTES \ | |||||
(KYBER_POLYVECCOMPRESSEDBYTES + KYBER_POLYCOMPRESSEDBYTES) | |||||
#define KYBER_PUBLICKEYBYTES (KYBER_INDCPA_PUBLICKEYBYTES) | |||||
#define KYBER_SECRETKEYBYTES \ | |||||
(KYBER_INDCPA_SECRETKEYBYTES + KYBER_INDCPA_PUBLICKEYBYTES + \ | |||||
2 * KYBER_SYMBYTES) /* 32 bytes of additional space to save H(pk) */ | |||||
#define KYBER_CIPHERTEXTBYTES KYBER_INDCPA_BYTES | |||||
#endif |
@@ -15,19 +15,20 @@ | |||||
* - const poly *a: pointer to input polynomial | * - const poly *a: pointer to input polynomial | ||||
**************************************************/ | **************************************************/ | ||||
void poly_compress(unsigned char *r, const poly *a) { | void poly_compress(unsigned char *r, const poly *a) { | ||||
uint32_t t[8]; | |||||
unsigned int i, j, k = 0; | |||||
for (i = 0; i < KYBER_N; i += 8) { | |||||
for (j = 0; j < 8; j++) { | |||||
t[j] = (((freeze(a->coeffs[i + j]) << 3) + KYBER_Q / 2) / KYBER_Q) & 7; | |||||
uint32_t t[8]; | |||||
unsigned int i, j, k = 0; | |||||
for (i = 0; i < KYBER_N; i += 8) { | |||||
for (j = 0; j < 8; j++) { | |||||
t[j] = | |||||
(((freeze(a->coeffs[i + j]) << 3) + KYBER_Q / 2) / KYBER_Q) & 7; | |||||
} | |||||
r[k] = t[0] | (t[1] << 3) | (t[2] << 6); | |||||
r[k + 1] = (t[2] >> 2) | (t[3] << 1) | (t[4] << 4) | (t[5] << 7); | |||||
r[k + 2] = (t[5] >> 1) | (t[6] << 2) | (t[7] << 5); | |||||
k += 3; | |||||
} | } | ||||
r[k] = t[0] | (t[1] << 3) | (t[2] << 6); | |||||
r[k + 1] = (t[2] >> 2) | (t[3] << 1) | (t[4] << 4) | (t[5] << 7); | |||||
r[k + 2] = (t[5] >> 1) | (t[6] << 2) | (t[7] << 5); | |||||
k += 3; | |||||
} | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -40,18 +41,20 @@ void poly_compress(unsigned char *r, const poly *a) { | |||||
* - const unsigned char *a: pointer to input byte array | * - const unsigned char *a: pointer to input byte array | ||||
**************************************************/ | **************************************************/ | ||||
void poly_decompress(poly *r, const unsigned char *a) { | void poly_decompress(poly *r, const unsigned char *a) { | ||||
unsigned int i; | |||||
for (i = 0; i < KYBER_N; i += 8) { | |||||
r->coeffs[i + 0] = (((a[0] & 7) * KYBER_Q) + 4) >> 3; | |||||
r->coeffs[i + 1] = ((((a[0] >> 3) & 7) * KYBER_Q) + 4) >> 3; | |||||
r->coeffs[i + 2] = ((((a[0] >> 6) | ((a[1] << 2) & 4)) * KYBER_Q) + 4) >> 3; | |||||
r->coeffs[i + 3] = ((((a[1] >> 1) & 7) * KYBER_Q) + 4) >> 3; | |||||
r->coeffs[i + 4] = ((((a[1] >> 4) & 7) * KYBER_Q) + 4) >> 3; | |||||
r->coeffs[i + 5] = ((((a[1] >> 7) | ((a[2] << 1) & 6)) * KYBER_Q) + 4) >> 3; | |||||
r->coeffs[i + 6] = ((((a[2] >> 2) & 7) * KYBER_Q) + 4) >> 3; | |||||
r->coeffs[i + 7] = ((((a[2] >> 5)) * KYBER_Q) + 4) >> 3; | |||||
a += 3; | |||||
} | |||||
unsigned int i; | |||||
for (i = 0; i < KYBER_N; i += 8) { | |||||
r->coeffs[i + 0] = (((a[0] & 7) * KYBER_Q) + 4) >> 3; | |||||
r->coeffs[i + 1] = ((((a[0] >> 3) & 7) * KYBER_Q) + 4) >> 3; | |||||
r->coeffs[i + 2] = | |||||
((((a[0] >> 6) | ((a[1] << 2) & 4)) * KYBER_Q) + 4) >> 3; | |||||
r->coeffs[i + 3] = ((((a[1] >> 1) & 7) * KYBER_Q) + 4) >> 3; | |||||
r->coeffs[i + 4] = ((((a[1] >> 4) & 7) * KYBER_Q) + 4) >> 3; | |||||
r->coeffs[i + 5] = | |||||
((((a[1] >> 7) | ((a[2] << 1) & 6)) * KYBER_Q) + 4) >> 3; | |||||
r->coeffs[i + 6] = ((((a[2] >> 2) & 7) * KYBER_Q) + 4) >> 3; | |||||
r->coeffs[i + 7] = ((((a[2] >> 5)) * KYBER_Q) + 4) >> 3; | |||||
a += 3; | |||||
} | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -63,28 +66,28 @@ void poly_decompress(poly *r, const unsigned char *a) { | |||||
* - const poly *a: pointer to input polynomial | * - const poly *a: pointer to input polynomial | ||||
**************************************************/ | **************************************************/ | ||||
void poly_tobytes(unsigned char *r, const poly *a) { | void poly_tobytes(unsigned char *r, const poly *a) { | ||||
int i, j; | |||||
uint16_t t[8]; | |||||
for (i = 0; i < KYBER_N / 8; i++) { | |||||
for (j = 0; j < 8; j++) { | |||||
t[j] = freeze(a->coeffs[8 * i + j]); | |||||
int i, j; | |||||
uint16_t t[8]; | |||||
for (i = 0; i < KYBER_N / 8; i++) { | |||||
for (j = 0; j < 8; j++) { | |||||
t[j] = freeze(a->coeffs[8 * i + j]); | |||||
} | |||||
r[13 * i + 0] = t[0] & 0xff; | |||||
r[13 * i + 1] = (t[0] >> 8) | ((t[1] & 0x07) << 5); | |||||
r[13 * i + 2] = (t[1] >> 3) & 0xff; | |||||
r[13 * i + 3] = (t[1] >> 11) | ((t[2] & 0x3f) << 2); | |||||
r[13 * i + 4] = (t[2] >> 6) | ((t[3] & 0x01) << 7); | |||||
r[13 * i + 5] = (t[3] >> 1) & 0xff; | |||||
r[13 * i + 6] = (t[3] >> 9) | ((t[4] & 0x0f) << 4); | |||||
r[13 * i + 7] = (t[4] >> 4) & 0xff; | |||||
r[13 * i + 8] = (t[4] >> 12) | ((t[5] & 0x7f) << 1); | |||||
r[13 * i + 9] = (t[5] >> 7) | ((t[6] & 0x03) << 6); | |||||
r[13 * i + 10] = (t[6] >> 2) & 0xff; | |||||
r[13 * i + 11] = (t[6] >> 10) | ((t[7] & 0x1f) << 3); | |||||
r[13 * i + 12] = (t[7] >> 5); | |||||
} | } | ||||
r[13 * i + 0] = t[0] & 0xff; | |||||
r[13 * i + 1] = (t[0] >> 8) | ((t[1] & 0x07) << 5); | |||||
r[13 * i + 2] = (t[1] >> 3) & 0xff; | |||||
r[13 * i + 3] = (t[1] >> 11) | ((t[2] & 0x3f) << 2); | |||||
r[13 * i + 4] = (t[2] >> 6) | ((t[3] & 0x01) << 7); | |||||
r[13 * i + 5] = (t[3] >> 1) & 0xff; | |||||
r[13 * i + 6] = (t[3] >> 9) | ((t[4] & 0x0f) << 4); | |||||
r[13 * i + 7] = (t[4] >> 4) & 0xff; | |||||
r[13 * i + 8] = (t[4] >> 12) | ((t[5] & 0x7f) << 1); | |||||
r[13 * i + 9] = (t[5] >> 7) | ((t[6] & 0x03) << 6); | |||||
r[13 * i + 10] = (t[6] >> 2) & 0xff; | |||||
r[13 * i + 11] = (t[6] >> 10) | ((t[7] & 0x1f) << 3); | |||||
r[13 * i + 12] = (t[7] >> 5); | |||||
} | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -97,29 +100,29 @@ void poly_tobytes(unsigned char *r, const poly *a) { | |||||
* - const unsigned char *a: pointer to input byte array | * - const unsigned char *a: pointer to input byte array | ||||
**************************************************/ | **************************************************/ | ||||
void poly_frombytes(poly *r, const unsigned char *a) { | void poly_frombytes(poly *r, const unsigned char *a) { | ||||
int i; | |||||
for (i = 0; i < KYBER_N / 8; i++) { | |||||
r->coeffs[8 * i + 0] = | |||||
a[13 * i + 0] | (((uint16_t)a[13 * i + 1] & 0x1f) << 8); | |||||
r->coeffs[8 * i + 1] = (a[13 * i + 1] >> 5) | | |||||
(((uint16_t)a[13 * i + 2]) << 3) | | |||||
(((uint16_t)a[13 * i + 3] & 0x03) << 11); | |||||
r->coeffs[8 * i + 2] = | |||||
(a[13 * i + 3] >> 2) | (((uint16_t)a[13 * i + 4] & 0x7f) << 6); | |||||
r->coeffs[8 * i + 3] = (a[13 * i + 4] >> 7) | | |||||
(((uint16_t)a[13 * i + 5]) << 1) | | |||||
(((uint16_t)a[13 * i + 6] & 0x0f) << 9); | |||||
r->coeffs[8 * i + 4] = (a[13 * i + 6] >> 4) | | |||||
(((uint16_t)a[13 * i + 7]) << 4) | | |||||
(((uint16_t)a[13 * i + 8] & 0x01) << 12); | |||||
r->coeffs[8 * i + 5] = | |||||
(a[13 * i + 8] >> 1) | (((uint16_t)a[13 * i + 9] & 0x3f) << 7); | |||||
r->coeffs[8 * i + 6] = (a[13 * i + 9] >> 6) | | |||||
(((uint16_t)a[13 * i + 10]) << 2) | | |||||
(((uint16_t)a[13 * i + 11] & 0x07) << 10); | |||||
r->coeffs[8 * i + 7] = | |||||
(a[13 * i + 11] >> 3) | (((uint16_t)a[13 * i + 12]) << 5); | |||||
} | |||||
int i; | |||||
for (i = 0; i < KYBER_N / 8; i++) { | |||||
r->coeffs[8 * i + 0] = | |||||
a[13 * i + 0] | (((uint16_t)a[13 * i + 1] & 0x1f) << 8); | |||||
r->coeffs[8 * i + 1] = (a[13 * i + 1] >> 5) | | |||||
(((uint16_t)a[13 * i + 2]) << 3) | | |||||
(((uint16_t)a[13 * i + 3] & 0x03) << 11); | |||||
r->coeffs[8 * i + 2] = | |||||
(a[13 * i + 3] >> 2) | (((uint16_t)a[13 * i + 4] & 0x7f) << 6); | |||||
r->coeffs[8 * i + 3] = (a[13 * i + 4] >> 7) | | |||||
(((uint16_t)a[13 * i + 5]) << 1) | | |||||
(((uint16_t)a[13 * i + 6] & 0x0f) << 9); | |||||
r->coeffs[8 * i + 4] = (a[13 * i + 6] >> 4) | | |||||
(((uint16_t)a[13 * i + 7]) << 4) | | |||||
(((uint16_t)a[13 * i + 8] & 0x01) << 12); | |||||
r->coeffs[8 * i + 5] = | |||||
(a[13 * i + 8] >> 1) | (((uint16_t)a[13 * i + 9] & 0x3f) << 7); | |||||
r->coeffs[8 * i + 6] = (a[13 * i + 9] >> 6) | | |||||
(((uint16_t)a[13 * i + 10]) << 2) | | |||||
(((uint16_t)a[13 * i + 11] & 0x07) << 10); | |||||
r->coeffs[8 * i + 7] = | |||||
(a[13 * i + 11] >> 3) | (((uint16_t)a[13 * i + 12]) << 5); | |||||
} | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -134,18 +137,18 @@ void poly_frombytes(poly *r, const unsigned char *a) { | |||||
* - unsigned char nonce: one-byte input nonce | * - unsigned char nonce: one-byte input nonce | ||||
**************************************************/ | **************************************************/ | ||||
void poly_getnoise(poly *r, const unsigned char *seed, unsigned char nonce) { | void poly_getnoise(poly *r, const unsigned char *seed, unsigned char nonce) { | ||||
unsigned char buf[KYBER_ETA * KYBER_N / 4]; | |||||
unsigned char extseed[KYBER_SYMBYTES + 1]; | |||||
int i; | |||||
unsigned char buf[KYBER_ETA * KYBER_N / 4]; | |||||
unsigned char extseed[KYBER_SYMBYTES + 1]; | |||||
int i; | |||||
for (i = 0; i < KYBER_SYMBYTES; i++) { | |||||
extseed[i] = seed[i]; | |||||
} | |||||
extseed[KYBER_SYMBYTES] = nonce; | |||||
for (i = 0; i < KYBER_SYMBYTES; i++) { | |||||
extseed[i] = seed[i]; | |||||
} | |||||
extseed[KYBER_SYMBYTES] = nonce; | |||||
shake256(buf, KYBER_ETA * KYBER_N / 4, extseed, KYBER_SYMBYTES + 1); | |||||
shake256(buf, KYBER_ETA * KYBER_N / 4, extseed, KYBER_SYMBYTES + 1); | |||||
cbd(r, buf); | |||||
cbd(r, buf); | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -159,7 +162,7 @@ void poly_getnoise(poly *r, const unsigned char *seed, unsigned char nonce) { | |||||
* Arguments: - uint16_t *r: pointer to in/output polynomial | * Arguments: - uint16_t *r: pointer to in/output polynomial | ||||
**************************************************/ | **************************************************/ | ||||
void poly_ntt(poly *r) { | void poly_ntt(poly *r) { | ||||
ntt(r->coeffs); | |||||
ntt(r->coeffs); | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -172,7 +175,7 @@ void poly_ntt(poly *r) { | |||||
* Arguments: - uint16_t *a: pointer to in/output polynomial | * Arguments: - uint16_t *a: pointer to in/output polynomial | ||||
**************************************************/ | **************************************************/ | ||||
void poly_invntt(poly *r) { | void poly_invntt(poly *r) { | ||||
invntt(r->coeffs); | |||||
invntt(r->coeffs); | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -185,10 +188,10 @@ void poly_invntt(poly *r) { | |||||
* - const poly *b: pointer to second input polynomial | * - const poly *b: pointer to second input polynomial | ||||
**************************************************/ | **************************************************/ | ||||
void poly_add(poly *r, const poly *a, const poly *b) { | void poly_add(poly *r, const poly *a, const poly *b) { | ||||
int i; | |||||
for (i = 0; i < KYBER_N; i++) { | |||||
r->coeffs[i] = barrett_reduce(a->coeffs[i] + b->coeffs[i]); | |||||
} | |||||
int i; | |||||
for (i = 0; i < KYBER_N; i++) { | |||||
r->coeffs[i] = barrett_reduce(a->coeffs[i] + b->coeffs[i]); | |||||
} | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -201,10 +204,11 @@ void poly_add(poly *r, const poly *a, const poly *b) { | |||||
* - const poly *b: pointer to second input polynomial | * - const poly *b: pointer to second input polynomial | ||||
**************************************************/ | **************************************************/ | ||||
void poly_sub(poly *r, const poly *a, const poly *b) { | void poly_sub(poly *r, const poly *a, const poly *b) { | ||||
int i; | |||||
for (i = 0; i < KYBER_N; i++) { | |||||
r->coeffs[i] = barrett_reduce(a->coeffs[i] + 3 * KYBER_Q - b->coeffs[i]); | |||||
} | |||||
int i; | |||||
for (i = 0; i < KYBER_N; i++) { | |||||
r->coeffs[i] = | |||||
barrett_reduce(a->coeffs[i] + 3 * KYBER_Q - b->coeffs[i]); | |||||
} | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -216,14 +220,14 @@ void poly_sub(poly *r, const poly *a, const poly *b) { | |||||
* - const unsigned char *msg: pointer to input message | * - const unsigned char *msg: pointer to input message | ||||
**************************************************/ | **************************************************/ | ||||
void poly_frommsg(poly *r, const unsigned char msg[KYBER_SYMBYTES]) { | void poly_frommsg(poly *r, const unsigned char msg[KYBER_SYMBYTES]) { | ||||
uint16_t i, j, mask; | |||||
uint16_t i, j, mask; | |||||
for (i = 0; i < KYBER_SYMBYTES; i++) { | |||||
for (j = 0; j < 8; j++) { | |||||
mask = -((msg[i] >> j) & 1); | |||||
r->coeffs[8 * i + j] = mask & ((KYBER_Q + 1) / 2); | |||||
for (i = 0; i < KYBER_SYMBYTES; i++) { | |||||
for (j = 0; j < 8; j++) { | |||||
mask = -((msg[i] >> j) & 1); | |||||
r->coeffs[8 * i + j] = mask & ((KYBER_Q + 1) / 2); | |||||
} | |||||
} | } | ||||
} | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -235,14 +239,16 @@ void poly_frommsg(poly *r, const unsigned char msg[KYBER_SYMBYTES]) { | |||||
* - const poly *a: pointer to input polynomial | * - const poly *a: pointer to input polynomial | ||||
**************************************************/ | **************************************************/ | ||||
void poly_tomsg(unsigned char msg[KYBER_SYMBYTES], const poly *a) { | void poly_tomsg(unsigned char msg[KYBER_SYMBYTES], const poly *a) { | ||||
uint16_t t; | |||||
int i, j; | |||||
for (i = 0; i < KYBER_SYMBYTES; i++) { | |||||
msg[i] = 0; | |||||
for (j = 0; j < 8; j++) { | |||||
t = (((freeze(a->coeffs[8 * i + j]) << 1) + KYBER_Q / 2) / KYBER_Q) & 1; | |||||
msg[i] |= t << j; | |||||
uint16_t t; | |||||
int i, j; | |||||
for (i = 0; i < KYBER_SYMBYTES; i++) { | |||||
msg[i] = 0; | |||||
for (j = 0; j < 8; j++) { | |||||
t = (((freeze(a->coeffs[8 * i + j]) << 1) + KYBER_Q / 2) / | |||||
KYBER_Q) & | |||||
1; | |||||
msg[i] |= t << j; | |||||
} | |||||
} | } | ||||
} | |||||
} | } |
@@ -9,7 +9,7 @@ | |||||
* coeffs[0] + X*coeffs[1] + X^2*xoeffs[2] + ... + X^{n-1}*coeffs[n-1] | * coeffs[0] + X*coeffs[1] + X^2*xoeffs[2] + ... + X^{n-1}*coeffs[n-1] | ||||
*/ | */ | ||||
typedef struct { | typedef struct { | ||||
uint16_t coeffs[KYBER_N]; | |||||
uint16_t coeffs[KYBER_N]; | |||||
} poly; | } poly; | ||||
void poly_compress(unsigned char *r, const poly *a); | void poly_compress(unsigned char *r, const poly *a); | ||||
@@ -13,31 +13,31 @@ | |||||
* - const polyvec *a: pointer to input vector of polynomials | * - const polyvec *a: pointer to input vector of polynomials | ||||
**************************************************/ | **************************************************/ | ||||
void polyvec_compress(unsigned char *r, const polyvec *a) { | void polyvec_compress(unsigned char *r, const polyvec *a) { | ||||
int i, j, k; | |||||
uint16_t t[8]; | |||||
for (i = 0; i < KYBER_K; i++) { | |||||
for (j = 0; j < KYBER_N / 8; j++) { | |||||
for (k = 0; k < 8; k++) { | |||||
t[k] = ((((uint32_t)freeze(a->vec[i].coeffs[8 * j + k]) << 11) + | |||||
KYBER_Q / 2) / | |||||
KYBER_Q) & | |||||
0x7ff; | |||||
} | |||||
int i, j, k; | |||||
uint16_t t[8]; | |||||
for (i = 0; i < KYBER_K; i++) { | |||||
for (j = 0; j < KYBER_N / 8; j++) { | |||||
for (k = 0; k < 8; k++) { | |||||
t[k] = ((((uint32_t)freeze(a->vec[i].coeffs[8 * j + k]) << 11) + | |||||
KYBER_Q / 2) / | |||||
KYBER_Q) & | |||||
0x7ff; | |||||
} | |||||
r[11 * j + 0] = t[0] & 0xff; | |||||
r[11 * j + 1] = (t[0] >> 8) | ((t[1] & 0x1f) << 3); | |||||
r[11 * j + 2] = (t[1] >> 5) | ((t[2] & 0x03) << 6); | |||||
r[11 * j + 3] = (t[2] >> 2) & 0xff; | |||||
r[11 * j + 4] = (t[2] >> 10) | ((t[3] & 0x7f) << 1); | |||||
r[11 * j + 5] = (t[3] >> 7) | ((t[4] & 0x0f) << 4); | |||||
r[11 * j + 6] = (t[4] >> 4) | ((t[5] & 0x01) << 7); | |||||
r[11 * j + 7] = (t[5] >> 1) & 0xff; | |||||
r[11 * j + 8] = (t[5] >> 9) | ((t[6] & 0x3f) << 2); | |||||
r[11 * j + 9] = (t[6] >> 6) | ((t[7] & 0x07) << 5); | |||||
r[11 * j + 10] = (t[7] >> 3); | |||||
r[11 * j + 0] = t[0] & 0xff; | |||||
r[11 * j + 1] = (t[0] >> 8) | ((t[1] & 0x1f) << 3); | |||||
r[11 * j + 2] = (t[1] >> 5) | ((t[2] & 0x03) << 6); | |||||
r[11 * j + 3] = (t[2] >> 2) & 0xff; | |||||
r[11 * j + 4] = (t[2] >> 10) | ((t[3] & 0x7f) << 1); | |||||
r[11 * j + 5] = (t[3] >> 7) | ((t[4] & 0x0f) << 4); | |||||
r[11 * j + 6] = (t[4] >> 4) | ((t[5] & 0x01) << 7); | |||||
r[11 * j + 7] = (t[5] >> 1) & 0xff; | |||||
r[11 * j + 8] = (t[5] >> 9) | ((t[6] & 0x3f) << 2); | |||||
r[11 * j + 9] = (t[6] >> 6) | ((t[7] & 0x07) << 5); | |||||
r[11 * j + 10] = (t[7] >> 3); | |||||
} | |||||
r += 352; | |||||
} | } | ||||
r += 352; | |||||
} | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -50,54 +50,61 @@ void polyvec_compress(unsigned char *r, const polyvec *a) { | |||||
* - unsigned char *a: pointer to input byte array | * - unsigned char *a: pointer to input byte array | ||||
**************************************************/ | **************************************************/ | ||||
void polyvec_decompress(polyvec *r, const unsigned char *a) { | void polyvec_decompress(polyvec *r, const unsigned char *a) { | ||||
int i, j; | |||||
for (i = 0; i < KYBER_K; i++) { | |||||
for (j = 0; j < KYBER_N / 8; j++) { | |||||
r->vec[i].coeffs[8 * j + 0] = | |||||
(((a[11 * j + 0] | (((uint32_t)a[11 * j + 1] & 0x07) << 8)) * | |||||
KYBER_Q) + | |||||
1024) >> | |||||
11; | |||||
r->vec[i].coeffs[8 * j + 1] = | |||||
((((a[11 * j + 1] >> 3) | (((uint32_t)a[11 * j + 2] & 0x3f) << 5)) * | |||||
KYBER_Q) + | |||||
1024) >> | |||||
11; | |||||
r->vec[i].coeffs[8 * j + 2] = | |||||
((((a[11 * j + 2] >> 6) | (((uint32_t)a[11 * j + 3] & 0xff) << 2) | | |||||
(((uint32_t)a[11 * j + 4] & 0x01) << 10)) * | |||||
KYBER_Q) + | |||||
1024) >> | |||||
11; | |||||
r->vec[i].coeffs[8 * j + 3] = | |||||
((((a[11 * j + 4] >> 1) | (((uint32_t)a[11 * j + 5] & 0x0f) << 7)) * | |||||
KYBER_Q) + | |||||
1024) >> | |||||
11; | |||||
r->vec[i].coeffs[8 * j + 4] = | |||||
((((a[11 * j + 5] >> 4) | (((uint32_t)a[11 * j + 6] & 0x7f) << 4)) * | |||||
KYBER_Q) + | |||||
1024) >> | |||||
11; | |||||
r->vec[i].coeffs[8 * j + 5] = | |||||
((((a[11 * j + 6] >> 7) | (((uint32_t)a[11 * j + 7] & 0xff) << 1) | | |||||
(((uint32_t)a[11 * j + 8] & 0x03) << 9)) * | |||||
KYBER_Q) + | |||||
1024) >> | |||||
11; | |||||
r->vec[i].coeffs[8 * j + 6] = | |||||
((((a[11 * j + 8] >> 2) | (((uint32_t)a[11 * j + 9] & 0x1f) << 6)) * | |||||
KYBER_Q) + | |||||
1024) >> | |||||
11; | |||||
r->vec[i].coeffs[8 * j + 7] = | |||||
((((a[11 * j + 9] >> 5) | (((uint32_t)a[11 * j + 10] & 0xff) << 3)) * | |||||
KYBER_Q) + | |||||
1024) >> | |||||
11; | |||||
int i, j; | |||||
for (i = 0; i < KYBER_K; i++) { | |||||
for (j = 0; j < KYBER_N / 8; j++) { | |||||
r->vec[i].coeffs[8 * j + 0] = | |||||
(((a[11 * j + 0] | (((uint32_t)a[11 * j + 1] & 0x07) << 8)) * | |||||
KYBER_Q) + | |||||
1024) >> | |||||
11; | |||||
r->vec[i].coeffs[8 * j + 1] = | |||||
((((a[11 * j + 1] >> 3) | | |||||
(((uint32_t)a[11 * j + 2] & 0x3f) << 5)) * | |||||
KYBER_Q) + | |||||
1024) >> | |||||
11; | |||||
r->vec[i].coeffs[8 * j + 2] = | |||||
((((a[11 * j + 2] >> 6) | | |||||
(((uint32_t)a[11 * j + 3] & 0xff) << 2) | | |||||
(((uint32_t)a[11 * j + 4] & 0x01) << 10)) * | |||||
KYBER_Q) + | |||||
1024) >> | |||||
11; | |||||
r->vec[i].coeffs[8 * j + 3] = | |||||
((((a[11 * j + 4] >> 1) | | |||||
(((uint32_t)a[11 * j + 5] & 0x0f) << 7)) * | |||||
KYBER_Q) + | |||||
1024) >> | |||||
11; | |||||
r->vec[i].coeffs[8 * j + 4] = | |||||
((((a[11 * j + 5] >> 4) | | |||||
(((uint32_t)a[11 * j + 6] & 0x7f) << 4)) * | |||||
KYBER_Q) + | |||||
1024) >> | |||||
11; | |||||
r->vec[i].coeffs[8 * j + 5] = | |||||
((((a[11 * j + 6] >> 7) | | |||||
(((uint32_t)a[11 * j + 7] & 0xff) << 1) | | |||||
(((uint32_t)a[11 * j + 8] & 0x03) << 9)) * | |||||
KYBER_Q) + | |||||
1024) >> | |||||
11; | |||||
r->vec[i].coeffs[8 * j + 6] = | |||||
((((a[11 * j + 8] >> 2) | | |||||
(((uint32_t)a[11 * j + 9] & 0x1f) << 6)) * | |||||
KYBER_Q) + | |||||
1024) >> | |||||
11; | |||||
r->vec[i].coeffs[8 * j + 7] = | |||||
((((a[11 * j + 9] >> 5) | | |||||
(((uint32_t)a[11 * j + 10] & 0xff) << 3)) * | |||||
KYBER_Q) + | |||||
1024) >> | |||||
11; | |||||
} | |||||
a += 352; | |||||
} | } | ||||
a += 352; | |||||
} | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -109,10 +116,10 @@ void polyvec_decompress(polyvec *r, const unsigned char *a) { | |||||
* - const polyvec *a: pointer to input vector of polynomials | * - const polyvec *a: pointer to input vector of polynomials | ||||
**************************************************/ | **************************************************/ | ||||
void polyvec_tobytes(unsigned char *r, const polyvec *a) { | void polyvec_tobytes(unsigned char *r, const polyvec *a) { | ||||
int i; | |||||
for (i = 0; i < KYBER_K; i++) { | |||||
poly_tobytes(r + i * KYBER_POLYBYTES, &a->vec[i]); | |||||
} | |||||
int i; | |||||
for (i = 0; i < KYBER_K; i++) { | |||||
poly_tobytes(r + i * KYBER_POLYBYTES, &a->vec[i]); | |||||
} | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -125,10 +132,10 @@ void polyvec_tobytes(unsigned char *r, const polyvec *a) { | |||||
* - const polyvec *a: pointer to input vector of polynomials | * - const polyvec *a: pointer to input vector of polynomials | ||||
**************************************************/ | **************************************************/ | ||||
void polyvec_frombytes(polyvec *r, const unsigned char *a) { | void polyvec_frombytes(polyvec *r, const unsigned char *a) { | ||||
int i; | |||||
for (i = 0; i < KYBER_K; i++) { | |||||
poly_frombytes(&r->vec[i], a + i * KYBER_POLYBYTES); | |||||
} | |||||
int i; | |||||
for (i = 0; i < KYBER_K; i++) { | |||||
poly_frombytes(&r->vec[i], a + i * KYBER_POLYBYTES); | |||||
} | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -139,10 +146,10 @@ void polyvec_frombytes(polyvec *r, const unsigned char *a) { | |||||
* Arguments: - polyvec *r: pointer to in/output vector of polynomials | * Arguments: - polyvec *r: pointer to in/output vector of polynomials | ||||
**************************************************/ | **************************************************/ | ||||
void polyvec_ntt(polyvec *r) { | void polyvec_ntt(polyvec *r) { | ||||
int i; | |||||
for (i = 0; i < KYBER_K; i++) { | |||||
poly_ntt(&r->vec[i]); | |||||
} | |||||
int i; | |||||
for (i = 0; i < KYBER_K; i++) { | |||||
poly_ntt(&r->vec[i]); | |||||
} | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -153,10 +160,10 @@ void polyvec_ntt(polyvec *r) { | |||||
* Arguments: - polyvec *r: pointer to in/output vector of polynomials | * Arguments: - polyvec *r: pointer to in/output vector of polynomials | ||||
**************************************************/ | **************************************************/ | ||||
void polyvec_invntt(polyvec *r) { | void polyvec_invntt(polyvec *r) { | ||||
int i; | |||||
for (i = 0; i < KYBER_K; i++) { | |||||
poly_invntt(&r->vec[i]); | |||||
} | |||||
int i; | |||||
for (i = 0; i < KYBER_K; i++) { | |||||
poly_invntt(&r->vec[i]); | |||||
} | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -169,18 +176,18 @@ void polyvec_invntt(polyvec *r) { | |||||
* - const polyvec *b: pointer to second input vector of polynomials | * - const polyvec *b: pointer to second input vector of polynomials | ||||
**************************************************/ | **************************************************/ | ||||
void polyvec_pointwise_acc(poly *r, const polyvec *a, const polyvec *b) { | void polyvec_pointwise_acc(poly *r, const polyvec *a, const polyvec *b) { | ||||
int i, j; | |||||
uint16_t t; | |||||
for (j = 0; j < KYBER_N; j++) { | |||||
t = montgomery_reduce(4613 * | |||||
(uint32_t)b->vec[0].coeffs[j]); // 4613 = 2^{2*18} % q | |||||
r->coeffs[j] = montgomery_reduce(a->vec[0].coeffs[j] * t); | |||||
for (i = 1; i < KYBER_K; i++) { | |||||
t = montgomery_reduce(4613 * (uint32_t)b->vec[i].coeffs[j]); | |||||
r->coeffs[j] += montgomery_reduce(a->vec[i].coeffs[j] * t); | |||||
int i, j; | |||||
uint16_t t; | |||||
for (j = 0; j < KYBER_N; j++) { | |||||
t = montgomery_reduce( | |||||
4613 * (uint32_t)b->vec[0].coeffs[j]); // 4613 = 2^{2*18} % q | |||||
r->coeffs[j] = montgomery_reduce(a->vec[0].coeffs[j] * t); | |||||
for (i = 1; i < KYBER_K; i++) { | |||||
t = montgomery_reduce(4613 * (uint32_t)b->vec[i].coeffs[j]); | |||||
r->coeffs[j] += montgomery_reduce(a->vec[i].coeffs[j] * t); | |||||
} | |||||
r->coeffs[j] = barrett_reduce(r->coeffs[j]); | |||||
} | } | ||||
r->coeffs[j] = barrett_reduce(r->coeffs[j]); | |||||
} | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -193,8 +200,8 @@ void polyvec_pointwise_acc(poly *r, const polyvec *a, const polyvec *b) { | |||||
* - const polyvec *b: pointer to second input vector of polynomials | * - const polyvec *b: pointer to second input vector of polynomials | ||||
**************************************************/ | **************************************************/ | ||||
void polyvec_add(polyvec *r, const polyvec *a, const polyvec *b) { | void polyvec_add(polyvec *r, const polyvec *a, const polyvec *b) { | ||||
int i; | |||||
for (i = 0; i < KYBER_K; i++) { | |||||
poly_add(&r->vec[i], &a->vec[i], &b->vec[i]); | |||||
} | |||||
int i; | |||||
for (i = 0; i < KYBER_K; i++) { | |||||
poly_add(&r->vec[i], &a->vec[i], &b->vec[i]); | |||||
} | |||||
} | } |
@@ -5,7 +5,7 @@ | |||||
#include "poly.h" | #include "poly.h" | ||||
typedef struct { | typedef struct { | ||||
poly vec[KYBER_K]; | |||||
poly vec[KYBER_K]; | |||||
} polyvec; | } polyvec; | ||||
void polyvec_compress(unsigned char *r, const polyvec *a); | void polyvec_compress(unsigned char *r, const polyvec *a); | ||||
@@ -18,13 +18,13 @@ static const uint32_t rlog = 18; | |||||
*q. | *q. | ||||
**************************************************/ | **************************************************/ | ||||
uint16_t montgomery_reduce(uint32_t a) { | uint16_t montgomery_reduce(uint32_t a) { | ||||
uint32_t u; | |||||
uint32_t u; | |||||
u = (a * qinv); | |||||
u &= ((1 << rlog) - 1); | |||||
u *= KYBER_Q; | |||||
a = a + u; | |||||
return a >> rlog; | |||||
u = (a * qinv); | |||||
u &= ((1 << rlog) - 1); | |||||
u *= KYBER_Q; | |||||
a = a + u; | |||||
return a >> rlog; | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -38,12 +38,12 @@ uint16_t montgomery_reduce(uint32_t a) { | |||||
* Returns: unsigned integer in {0,...,11768} congruent to a modulo q. | * Returns: unsigned integer in {0,...,11768} congruent to a modulo q. | ||||
**************************************************/ | **************************************************/ | ||||
uint16_t barrett_reduce(uint16_t a) { | uint16_t barrett_reduce(uint16_t a) { | ||||
uint32_t u; | |||||
uint32_t u; | |||||
u = a >> 13; //((uint32_t) a * sinv) >> 16; | |||||
u *= KYBER_Q; | |||||
a -= u; | |||||
return a; | |||||
u = a >> 13; //((uint32_t) a * sinv) >> 16; | |||||
u *= KYBER_Q; | |||||
a -= u; | |||||
return a; | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -57,14 +57,14 @@ uint16_t barrett_reduce(uint16_t a) { | |||||
* Returns: unsigned integer in {0,...,q-1} congruent to a modulo q. | * Returns: unsigned integer in {0,...,q-1} congruent to a modulo q. | ||||
**************************************************/ | **************************************************/ | ||||
uint16_t freeze(uint16_t x) { | uint16_t freeze(uint16_t x) { | ||||
uint16_t m, r; | |||||
int16_t c; | |||||
r = barrett_reduce(x); | |||||
uint16_t m, r; | |||||
int16_t c; | |||||
r = barrett_reduce(x); | |||||
m = r - KYBER_Q; | |||||
c = m; | |||||
c >>= 15; | |||||
r = m ^ ((r ^ m) & c); | |||||
m = r - KYBER_Q; | |||||
c = m; | |||||
c >>= 15; | |||||
r = m ^ ((r ^ m) & c); | |||||
return r; | |||||
return r; | |||||
} | } |
@@ -13,16 +13,16 @@ | |||||
* Returns 0 if the byte arrays are equal, 1 otherwise | * Returns 0 if the byte arrays are equal, 1 otherwise | ||||
**************************************************/ | **************************************************/ | ||||
int verify(const unsigned char *a, const unsigned char *b, size_t len) { | int verify(const unsigned char *a, const unsigned char *b, size_t len) { | ||||
uint64_t r; | |||||
size_t i; | |||||
r = 0; | |||||
uint64_t r; | |||||
size_t i; | |||||
r = 0; | |||||
for (i = 0; i < len; i++) { | |||||
r |= a[i] ^ b[i]; | |||||
} | |||||
for (i = 0; i < len; i++) { | |||||
r |= a[i] ^ b[i]; | |||||
} | |||||
r = (-r) >> 63; | |||||
return r; | |||||
r = (-r) >> 63; | |||||
return r; | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -40,10 +40,10 @@ int verify(const unsigned char *a, const unsigned char *b, size_t len) { | |||||
**************************************************/ | **************************************************/ | ||||
void cmov(unsigned char *r, const unsigned char *x, size_t len, | void cmov(unsigned char *r, const unsigned char *x, size_t len, | ||||
unsigned char b) { | unsigned char b) { | ||||
size_t i; | |||||
size_t i; | |||||
b = -b; | |||||
for (i = 0; i < len; i++) { | |||||
r[i] ^= b & (x[i] ^ r[i]); | |||||
} | |||||
b = -b; | |||||
for (i = 0; i < len; i++) { | |||||
r[i] ^= b & (x[i] ^ r[i]); | |||||
} | |||||
} | } |
@@ -9,122 +9,126 @@ | |||||
* make sure it is not touched by the implementations. | * make sure it is not touched by the implementations. | ||||
*/ | */ | ||||
static void write_canary(unsigned char *d) { | static void write_canary(unsigned char *d) { | ||||
*((uint64_t *)d) = 0x0123456789ABCDEF; | |||||
*((uint64_t *)d) = 0x0123456789ABCDEF; | |||||
} | } | ||||
static int check_canary(const unsigned char *d) { | static int check_canary(const unsigned char *d) { | ||||
if (*(uint64_t *)d != 0x0123456789ABCDEF) { | |||||
return -1; | |||||
} | |||||
{ return 0; } | |||||
if (*(uint64_t *)d != 0x0123456789ABCDEF) { | |||||
return -1; | |||||
} | |||||
{ return 0; } | |||||
} | } | ||||
static int test_keys(void) { | static int test_keys(void) { | ||||
unsigned char key_a[CRYPTO_BYTES + 16], key_b[CRYPTO_BYTES + 16]; | |||||
unsigned char pk[CRYPTO_PUBLICKEYBYTES + 16]; | |||||
unsigned char sendb[CRYPTO_CIPHERTEXTBYTES + 16]; | |||||
unsigned char sk_a[CRYPTO_SECRETKEYBYTES + 16]; | |||||
write_canary(key_a); | |||||
write_canary(key_a + sizeof(key_a) - 8); | |||||
write_canary(key_b); | |||||
write_canary(key_b + sizeof(key_b) - 8); | |||||
write_canary(pk); | |||||
write_canary(pk + sizeof(pk) - 8); | |||||
write_canary(sendb); | |||||
write_canary(sendb + sizeof(sendb) - 8); | |||||
write_canary(sk_a); | |||||
write_canary(sk_a + sizeof(sk_a) - 8); | |||||
int i; | |||||
for (i = 0; i < NTESTS; i++) { | |||||
// Alice generates a public key | |||||
crypto_kem_keypair(pk + 8, sk_a + 8); | |||||
// Bob derives a secret key and creates a response | |||||
crypto_kem_enc(sendb + 8, key_b + 8, pk + 8); | |||||
// Alice uses Bobs response to get her secret key | |||||
crypto_kem_dec(key_a + 8, sendb + 8, sk_a + 8); | |||||
if (memcmp(key_a + 8, key_b + 8, CRYPTO_BYTES) != 0) { | |||||
printf("ERROR KEYS\n"); | |||||
} else if (check_canary(key_a) || check_canary(key_a + sizeof(key_a) - 8) || | |||||
check_canary(key_b) || check_canary(key_b + sizeof(key_b) - 8) || | |||||
check_canary(pk) || check_canary(pk + sizeof(pk) - 8) || | |||||
check_canary(sendb) || check_canary(sendb + sizeof(sendb) - 8) || | |||||
check_canary(sk_a) || check_canary(sk_a + sizeof(sk_a) - 8)) { | |||||
printf("ERROR canary overwritten\n"); | |||||
unsigned char key_a[CRYPTO_BYTES + 16], key_b[CRYPTO_BYTES + 16]; | |||||
unsigned char pk[CRYPTO_PUBLICKEYBYTES + 16]; | |||||
unsigned char sendb[CRYPTO_CIPHERTEXTBYTES + 16]; | |||||
unsigned char sk_a[CRYPTO_SECRETKEYBYTES + 16]; | |||||
write_canary(key_a); | |||||
write_canary(key_a + sizeof(key_a) - 8); | |||||
write_canary(key_b); | |||||
write_canary(key_b + sizeof(key_b) - 8); | |||||
write_canary(pk); | |||||
write_canary(pk + sizeof(pk) - 8); | |||||
write_canary(sendb); | |||||
write_canary(sendb + sizeof(sendb) - 8); | |||||
write_canary(sk_a); | |||||
write_canary(sk_a + sizeof(sk_a) - 8); | |||||
int i; | |||||
for (i = 0; i < NTESTS; i++) { | |||||
// Alice generates a public key | |||||
crypto_kem_keypair(pk + 8, sk_a + 8); | |||||
// Bob derives a secret key and creates a response | |||||
crypto_kem_enc(sendb + 8, key_b + 8, pk + 8); | |||||
// Alice uses Bobs response to get her secret key | |||||
crypto_kem_dec(key_a + 8, sendb + 8, sk_a + 8); | |||||
if (memcmp(key_a + 8, key_b + 8, CRYPTO_BYTES) != 0) { | |||||
printf("ERROR KEYS\n"); | |||||
} else if (check_canary(key_a) || | |||||
check_canary(key_a + sizeof(key_a) - 8) || | |||||
check_canary(key_b) || | |||||
check_canary(key_b + sizeof(key_b) - 8) || | |||||
check_canary(pk) || check_canary(pk + sizeof(pk) - 8) || | |||||
check_canary(sendb) || | |||||
check_canary(sendb + sizeof(sendb) - 8) || | |||||
check_canary(sk_a) || | |||||
check_canary(sk_a + sizeof(sk_a) - 8)) { | |||||
printf("ERROR canary overwritten\n"); | |||||
} | |||||
} | } | ||||
} | |||||
return 0; | |||||
return 0; | |||||
} | } | ||||
static int test_invalid_sk_a(void) { | static int test_invalid_sk_a(void) { | ||||
unsigned char sk_a[CRYPTO_SECRETKEYBYTES]; | |||||
unsigned char key_a[CRYPTO_BYTES], key_b[CRYPTO_BYTES]; | |||||
unsigned char pk[CRYPTO_PUBLICKEYBYTES]; | |||||
unsigned char sendb[CRYPTO_CIPHERTEXTBYTES]; | |||||
int i; | |||||
unsigned char sk_a[CRYPTO_SECRETKEYBYTES]; | |||||
unsigned char key_a[CRYPTO_BYTES], key_b[CRYPTO_BYTES]; | |||||
unsigned char pk[CRYPTO_PUBLICKEYBYTES]; | |||||
unsigned char sendb[CRYPTO_CIPHERTEXTBYTES]; | |||||
int i; | |||||
for (i = 0; i < NTESTS; i++) { | |||||
// Alice generates a public key | |||||
crypto_kem_keypair(pk, sk_a); | |||||
for (i = 0; i < NTESTS; i++) { | |||||
// Alice generates a public key | |||||
crypto_kem_keypair(pk, sk_a); | |||||
// Bob derives a secret key and creates a response | |||||
crypto_kem_enc(sendb, key_b, pk); | |||||
// Bob derives a secret key and creates a response | |||||
crypto_kem_enc(sendb, key_b, pk); | |||||
// Replace secret key with random values | |||||
randombytes(sk_a, CRYPTO_SECRETKEYBYTES); | |||||
// Replace secret key with random values | |||||
randombytes(sk_a, CRYPTO_SECRETKEYBYTES); | |||||
// Alice uses Bobs response to get her secret key | |||||
crypto_kem_dec(key_a, sendb, sk_a); | |||||
// Alice uses Bobs response to get her secret key | |||||
crypto_kem_dec(key_a, sendb, sk_a); | |||||
if (!memcmp(key_a, key_b, CRYPTO_BYTES)) { | |||||
printf("ERROR invalid sk_a\n"); | |||||
if (!memcmp(key_a, key_b, CRYPTO_BYTES)) { | |||||
printf("ERROR invalid sk_a\n"); | |||||
} | |||||
} | } | ||||
} | |||||
return 0; | |||||
return 0; | |||||
} | } | ||||
static int test_invalid_ciphertext(void) { | static int test_invalid_ciphertext(void) { | ||||
unsigned char sk_a[CRYPTO_SECRETKEYBYTES]; | |||||
unsigned char key_a[CRYPTO_BYTES], key_b[CRYPTO_BYTES]; | |||||
unsigned char pk[CRYPTO_PUBLICKEYBYTES]; | |||||
unsigned char sendb[CRYPTO_CIPHERTEXTBYTES]; | |||||
int i; | |||||
size_t pos; | |||||
unsigned char sk_a[CRYPTO_SECRETKEYBYTES]; | |||||
unsigned char key_a[CRYPTO_BYTES], key_b[CRYPTO_BYTES]; | |||||
unsigned char pk[CRYPTO_PUBLICKEYBYTES]; | |||||
unsigned char sendb[CRYPTO_CIPHERTEXTBYTES]; | |||||
int i; | |||||
size_t pos; | |||||
for (i = 0; i < NTESTS; i++) { | |||||
randombytes((unsigned char *)&pos, sizeof(size_t)); | |||||
for (i = 0; i < NTESTS; i++) { | |||||
randombytes((unsigned char *)&pos, sizeof(size_t)); | |||||
// Alice generates a public key | |||||
crypto_kem_keypair(pk, sk_a); | |||||
// Alice generates a public key | |||||
crypto_kem_keypair(pk, sk_a); | |||||
// Bob derives a secret key and creates a response | |||||
crypto_kem_enc(sendb, key_b, pk); | |||||
// Bob derives a secret key and creates a response | |||||
crypto_kem_enc(sendb, key_b, pk); | |||||
// Change some byte in the ciphertext (i.e., encapsulated key) | |||||
sendb[pos % CRYPTO_CIPHERTEXTBYTES] ^= 23; | |||||
// Change some byte in the ciphertext (i.e., encapsulated key) | |||||
sendb[pos % CRYPTO_CIPHERTEXTBYTES] ^= 23; | |||||
// Alice uses Bobs response to get her secret key | |||||
crypto_kem_dec(key_a, sendb, sk_a); | |||||
// Alice uses Bobs response to get her secret key | |||||
crypto_kem_dec(key_a, sendb, sk_a); | |||||
if (!memcmp(key_a, key_b, CRYPTO_BYTES)) { | |||||
printf("ERROR invalid ciphertext\n"); | |||||
if (!memcmp(key_a, key_b, CRYPTO_BYTES)) { | |||||
printf("ERROR invalid ciphertext\n"); | |||||
} | |||||
} | } | ||||
} | |||||
return 0; | |||||
return 0; | |||||
} | } | ||||
int main(void) { | int main(void) { | ||||
test_keys(); | |||||
test_invalid_sk_a(); | |||||
test_invalid_ciphertext(); | |||||
test_keys(); | |||||
test_invalid_sk_a(); | |||||
test_invalid_ciphertext(); | |||||
return 0; | |||||
return 0; | |||||
} | } |
@@ -84,20 +84,20 @@ static const uint32_t zetas_inv[N] = { | |||||
* Arguments: - uint32_t p[N]: input/output coefficient array | * Arguments: - uint32_t p[N]: input/output coefficient array | ||||
**************************************************/ | **************************************************/ | ||||
void ntt(uint32_t p[N]) { | void ntt(uint32_t p[N]) { | ||||
unsigned int len, start, j, k; | |||||
uint32_t zeta, t; | |||||
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 = montgomery_reduce((uint64_t)zeta * p[j + len]); | |||||
p[j + len] = p[j] + 2 * Q - t; | |||||
p[j] = p[j] + 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 = montgomery_reduce((uint64_t)zeta * p[j + len]); | |||||
p[j + len] = p[j] + 2 * Q - t; | |||||
p[j] = p[j] + t; | |||||
} | |||||
} | |||||
} | } | ||||
} | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -111,25 +111,25 @@ void ntt(uint32_t p[N]) { | |||||
* Arguments: - uint32_t p[N]: input/output coefficient array | * Arguments: - uint32_t p[N]: input/output coefficient array | ||||
**************************************************/ | **************************************************/ | ||||
void invntt_frominvmont(uint32_t p[N]) { | void 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; | |||||
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] = montgomery_reduce((uint64_t)zeta * p[j + len]); | |||||
} | |||||
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] = montgomery_reduce((uint64_t)zeta * p[j + len]); | |||||
} | |||||
} | |||||
} | } | ||||
} | |||||
for (j = 0; j < N; ++j) { | |||||
p[j] = montgomery_reduce((uint64_t)f * p[j]); | |||||
} | |||||
for (j = 0; j < N; ++j) { | |||||
p[j] = montgomery_reduce((uint64_t)f * p[j]); | |||||
} | |||||
} | } |
@@ -14,14 +14,14 @@ | |||||
**************************************************/ | **************************************************/ | ||||
void pack_pk(unsigned char pk[CRYPTO_PUBLICKEYBYTES], | void pack_pk(unsigned char pk[CRYPTO_PUBLICKEYBYTES], | ||||
const unsigned char rho[SEEDBYTES], const polyveck *t1) { | const unsigned char rho[SEEDBYTES], const polyveck *t1) { | ||||
unsigned int i; | |||||
unsigned int i; | |||||
for (i = 0; i < SEEDBYTES; ++i) | |||||
pk[i] = rho[i]; | |||||
pk += SEEDBYTES; | |||||
for (i = 0; i < SEEDBYTES; ++i) | |||||
pk[i] = rho[i]; | |||||
pk += SEEDBYTES; | |||||
for (i = 0; i < K; ++i) | |||||
polyt1_pack(pk + i * POLT1_SIZE_PACKED, t1->vec + i); | |||||
for (i = 0; i < K; ++i) | |||||
polyt1_pack(pk + i * POLT1_SIZE_PACKED, t1->vec + i); | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -35,14 +35,14 @@ void pack_pk(unsigned char pk[CRYPTO_PUBLICKEYBYTES], | |||||
**************************************************/ | **************************************************/ | ||||
void unpack_pk(unsigned char rho[SEEDBYTES], polyveck *t1, | void unpack_pk(unsigned char rho[SEEDBYTES], polyveck *t1, | ||||
const unsigned char pk[CRYPTO_PUBLICKEYBYTES]) { | const unsigned char pk[CRYPTO_PUBLICKEYBYTES]) { | ||||
unsigned int i; | |||||
unsigned int i; | |||||
for (i = 0; i < SEEDBYTES; ++i) | |||||
rho[i] = pk[i]; | |||||
pk += SEEDBYTES; | |||||
for (i = 0; i < SEEDBYTES; ++i) | |||||
rho[i] = pk[i]; | |||||
pk += SEEDBYTES; | |||||
for (i = 0; i < K; ++i) | |||||
polyt1_unpack(t1->vec + i, pk + i * POLT1_SIZE_PACKED); | |||||
for (i = 0; i < K; ++i) | |||||
polyt1_unpack(t1->vec + i, pk + i * POLT1_SIZE_PACKED); | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -63,30 +63,30 @@ void pack_sk(unsigned char sk[CRYPTO_SECRETKEYBYTES], | |||||
const unsigned char key[SEEDBYTES], | const unsigned char key[SEEDBYTES], | ||||
const unsigned char tr[CRHBYTES], const polyvecl *s1, | const unsigned char tr[CRHBYTES], const polyvecl *s1, | ||||
const polyveck *s2, const polyveck *t0) { | const polyveck *s2, const polyveck *t0) { | ||||
unsigned int i; | |||||
unsigned int i; | |||||
for (i = 0; i < SEEDBYTES; ++i) | |||||
sk[i] = rho[i]; | |||||
sk += SEEDBYTES; | |||||
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 < SEEDBYTES; ++i) | |||||
sk[i] = key[i]; | |||||
sk += SEEDBYTES; | |||||
for (i = 0; i < CRHBYTES; ++i) | |||||
sk[i] = tr[i]; | |||||
sk += CRHBYTES; | |||||
for (i = 0; i < CRHBYTES; ++i) | |||||
sk[i] = tr[i]; | |||||
sk += CRHBYTES; | |||||
for (i = 0; i < L; ++i) | |||||
polyeta_pack(sk + i * POLETA_SIZE_PACKED, s1->vec + i); | |||||
sk += L * POLETA_SIZE_PACKED; | |||||
for (i = 0; i < L; ++i) | |||||
polyeta_pack(sk + i * POLETA_SIZE_PACKED, s1->vec + i); | |||||
sk += L * POLETA_SIZE_PACKED; | |||||
for (i = 0; i < K; ++i) | |||||
polyeta_pack(sk + i * POLETA_SIZE_PACKED, s2->vec + i); | |||||
sk += K * POLETA_SIZE_PACKED; | |||||
for (i = 0; i < K; ++i) | |||||
polyeta_pack(sk + i * POLETA_SIZE_PACKED, s2->vec + i); | |||||
sk += K * POLETA_SIZE_PACKED; | |||||
for (i = 0; i < K; ++i) | |||||
polyt0_pack(sk + i * POLT0_SIZE_PACKED, t0->vec + i); | |||||
for (i = 0; i < K; ++i) | |||||
polyt0_pack(sk + i * POLT0_SIZE_PACKED, t0->vec + i); | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -105,30 +105,30 @@ void pack_sk(unsigned char sk[CRYPTO_SECRETKEYBYTES], | |||||
void unpack_sk(unsigned char rho[SEEDBYTES], unsigned char key[SEEDBYTES], | void unpack_sk(unsigned char rho[SEEDBYTES], unsigned char key[SEEDBYTES], | ||||
unsigned char tr[CRHBYTES], polyvecl *s1, polyveck *s2, | unsigned char tr[CRHBYTES], polyvecl *s1, polyveck *s2, | ||||
polyveck *t0, const unsigned char sk[CRYPTO_SECRETKEYBYTES]) { | polyveck *t0, const unsigned char sk[CRYPTO_SECRETKEYBYTES]) { | ||||
unsigned int i; | |||||
unsigned int i; | |||||
for (i = 0; i < SEEDBYTES; ++i) | |||||
rho[i] = sk[i]; | |||||
sk += SEEDBYTES; | |||||
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 < SEEDBYTES; ++i) | |||||
key[i] = sk[i]; | |||||
sk += SEEDBYTES; | |||||
for (i = 0; i < CRHBYTES; ++i) | |||||
tr[i] = sk[i]; | |||||
sk += CRHBYTES; | |||||
for (i = 0; i < CRHBYTES; ++i) | |||||
tr[i] = sk[i]; | |||||
sk += CRHBYTES; | |||||
for (i = 0; i < L; ++i) | |||||
polyeta_unpack(s1->vec + i, sk + i * POLETA_SIZE_PACKED); | |||||
sk += L * POLETA_SIZE_PACKED; | |||||
for (i = 0; i < L; ++i) | |||||
polyeta_unpack(s1->vec + i, sk + i * POLETA_SIZE_PACKED); | |||||
sk += L * POLETA_SIZE_PACKED; | |||||
for (i = 0; i < K; ++i) | |||||
polyeta_unpack(s2->vec + i, sk + i * POLETA_SIZE_PACKED); | |||||
sk += K * POLETA_SIZE_PACKED; | |||||
for (i = 0; i < K; ++i) | |||||
polyeta_unpack(s2->vec + i, sk + i * POLETA_SIZE_PACKED); | |||||
sk += K * POLETA_SIZE_PACKED; | |||||
for (i = 0; i < K; ++i) | |||||
polyt0_unpack(t0->vec + i, sk + i * POLT0_SIZE_PACKED); | |||||
for (i = 0; i < K; ++i) | |||||
polyt0_unpack(t0->vec + i, sk + i * POLT0_SIZE_PACKED); | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -143,43 +143,43 @@ void unpack_sk(unsigned char rho[SEEDBYTES], unsigned char key[SEEDBYTES], | |||||
**************************************************/ | **************************************************/ | ||||
void pack_sig(unsigned char sig[CRYPTO_BYTES], const polyvecl *z, | void pack_sig(unsigned char sig[CRYPTO_BYTES], const polyvecl *z, | ||||
const polyveck *h, const poly *c) { | const polyveck *h, const poly *c) { | ||||
unsigned int i, j, k; | |||||
uint64_t signs, mask; | |||||
for (i = 0; i < L; ++i) | |||||
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++] = j; | |||||
sig[OMEGA + i] = 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] |= (1U << j); | |||||
if (c->coeffs[8 * i + j] == (Q - 1)) | |||||
signs |= mask; | |||||
mask <<= 1; | |||||
} | |||||
unsigned int i, j, k; | |||||
uint64_t signs, mask; | |||||
for (i = 0; i < L; ++i) | |||||
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++] = j; | |||||
sig[OMEGA + i] = k; | |||||
} | } | ||||
} | |||||
sig += N / 8; | |||||
for (i = 0; i < 8; ++i) | |||||
sig[i] = signs >> 8 * i; | |||||
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] |= (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] = signs >> 8 * i; | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -197,60 +197,60 @@ void pack_sig(unsigned char sig[CRYPTO_BYTES], const polyvecl *z, | |||||
**************************************************/ | **************************************************/ | ||||
int unpack_sig(polyvecl *z, polyveck *h, poly *c, | int unpack_sig(polyvecl *z, polyveck *h, poly *c, | ||||
const unsigned char sig[CRYPTO_BYTES]) { | const unsigned char sig[CRYPTO_BYTES]) { | ||||
unsigned int i, j, k; | |||||
uint64_t signs, mask; | |||||
for (i = 0; i < L; ++i) | |||||
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; | |||||
unsigned int i, j, k; | |||||
uint64_t signs, mask; | |||||
for (i = 0; i < L; ++i) | |||||
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]; | |||||
} | } | ||||
k = sig[OMEGA + i]; | |||||
} | |||||
/* Extra indices are zero for strong unforgeability */ | |||||
for (j = k; j < OMEGA; ++j) | |||||
if (sig[j]) | |||||
return 1; | |||||
/* Extra indices are zero for strong unforgeability */ | |||||
for (j = k; j < OMEGA; ++j) | |||||
if (sig[j]) | |||||
return 1; | |||||
sig += OMEGA + K; | |||||
sig += OMEGA + K; | |||||
/* Decode c */ | |||||
for (i = 0; i < N; ++i) | |||||
c->coeffs[i] = 0; | |||||
/* 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; | |||||
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; | |||||
/* Extra sign bits are zero for strong unforgeability */ | |||||
if (signs >> 60) | |||||
return 1; | |||||
mask = 1; | |||||
for (i = 0; i < N / 8; ++i) { | |||||
for (j = 0; j < 8; ++j) { | |||||
if ((sig[i] >> j) & 0x01) { | |||||
c->coeffs[8 * i + j] = (signs & mask) ? Q - 1 : 1; | |||||
mask <<= 1; | |||||
} | |||||
mask = 1; | |||||
for (i = 0; i < N / 8; ++i) { | |||||
for (j = 0; j < 8; ++j) { | |||||
if ((sig[i] >> j) & 0x01) { | |||||
c->coeffs[8 * i + j] = (signs & mask) ? Q - 1 : 1; | |||||
mask <<= 1; | |||||
} | |||||
} | |||||
} | } | ||||
} | |||||
return 0; | |||||
return 0; | |||||
} | } |
@@ -61,8 +61,8 @@ | |||||
#define CRYPTO_PUBLICKEYBYTES (SEEDBYTES + K * POLT1_SIZE_PACKED) | #define CRYPTO_PUBLICKEYBYTES (SEEDBYTES + K * POLT1_SIZE_PACKED) | ||||
#define CRYPTO_SECRETKEYBYTES \ | #define CRYPTO_SECRETKEYBYTES \ | ||||
(2 * SEEDBYTES + (L + K) * POLETA_SIZE_PACKED + CRHBYTES + \ | |||||
K * POLT0_SIZE_PACKED) | |||||
(2 * SEEDBYTES + (L + K) * POLETA_SIZE_PACKED + CRHBYTES + \ | |||||
K * POLT0_SIZE_PACKED) | |||||
#define CRYPTO_BYTES (L * POLZ_SIZE_PACKED + (OMEGA + K) + (N / 8 + 8)) | #define CRYPTO_BYTES (L * POLZ_SIZE_PACKED + (OMEGA + K) + (N / 8 + 8)) | ||||
#endif | #endif |
@@ -15,10 +15,10 @@ | |||||
* Arguments: - poly *a: pointer to input/output polynomial | * Arguments: - poly *a: pointer to input/output polynomial | ||||
**************************************************/ | **************************************************/ | ||||
void poly_reduce(poly *a) { | void poly_reduce(poly *a) { | ||||
unsigned int i; | |||||
unsigned int i; | |||||
for (i = 0; i < N; ++i) | |||||
a->coeffs[i] = reduce32(a->coeffs[i]); | |||||
for (i = 0; i < N; ++i) | |||||
a->coeffs[i] = reduce32(a->coeffs[i]); | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -30,10 +30,10 @@ void poly_reduce(poly *a) { | |||||
* Arguments: - poly *a: pointer to input/output polynomial | * Arguments: - poly *a: pointer to input/output polynomial | ||||
**************************************************/ | **************************************************/ | ||||
void poly_csubq(poly *a) { | void poly_csubq(poly *a) { | ||||
unsigned int i; | |||||
unsigned int i; | |||||
for (i = 0; i < N; ++i) | |||||
a->coeffs[i] = csubq(a->coeffs[i]); | |||||
for (i = 0; i < N; ++i) | |||||
a->coeffs[i] = csubq(a->coeffs[i]); | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -45,10 +45,10 @@ void poly_csubq(poly *a) { | |||||
* Arguments: - poly *a: pointer to input/output polynomial | * Arguments: - poly *a: pointer to input/output polynomial | ||||
**************************************************/ | **************************************************/ | ||||
void poly_freeze(poly *a) { | void poly_freeze(poly *a) { | ||||
unsigned int i; | |||||
unsigned int i; | |||||
for (i = 0; i < N; ++i) | |||||
a->coeffs[i] = freeze(a->coeffs[i]); | |||||
for (i = 0; i < N; ++i) | |||||
a->coeffs[i] = freeze(a->coeffs[i]); | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -61,10 +61,10 @@ void poly_freeze(poly *a) { | |||||
* - const poly *b: pointer to second summand | * - const poly *b: pointer to second summand | ||||
**************************************************/ | **************************************************/ | ||||
void poly_add(poly *c, const poly *a, const poly *b) { | void poly_add(poly *c, const poly *a, const poly *b) { | ||||
unsigned int i; | |||||
unsigned int i; | |||||
for (i = 0; i < N; ++i) | |||||
c->coeffs[i] = a->coeffs[i] + b->coeffs[i]; | |||||
for (i = 0; i < N; ++i) | |||||
c->coeffs[i] = a->coeffs[i] + b->coeffs[i]; | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -80,10 +80,10 @@ void poly_add(poly *c, const poly *a, const poly *b) { | |||||
* subtraced from first input polynomial | * subtraced from first input polynomial | ||||
**************************************************/ | **************************************************/ | ||||
void poly_sub(poly *c, const poly *a, const poly *b) { | void poly_sub(poly *c, const poly *a, const poly *b) { | ||||
unsigned int i; | |||||
unsigned int i; | |||||
for (i = 0; i < N; ++i) | |||||
c->coeffs[i] = a->coeffs[i] + 2 * Q - b->coeffs[i]; | |||||
for (i = 0; i < N; ++i) | |||||
c->coeffs[i] = a->coeffs[i] + 2 * Q - b->coeffs[i]; | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -95,10 +95,10 @@ void poly_sub(poly *c, const poly *a, const poly *b) { | |||||
* Arguments: - poly *a: pointer to input/output polynomial | * Arguments: - poly *a: pointer to input/output polynomial | ||||
**************************************************/ | **************************************************/ | ||||
void poly_neg(poly *a) { | void poly_neg(poly *a) { | ||||
unsigned int i; | |||||
unsigned int i; | |||||
for (i = 0; i < N; ++i) | |||||
a->coeffs[i] = Q - a->coeffs[i]; | |||||
for (i = 0; i < N; ++i) | |||||
a->coeffs[i] = Q - a->coeffs[i]; | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -111,10 +111,10 @@ void poly_neg(poly *a) { | |||||
* - unsigned int k: exponent | * - unsigned int k: exponent | ||||
**************************************************/ | **************************************************/ | ||||
void poly_shiftl(poly *a, unsigned int k) { | void poly_shiftl(poly *a, unsigned int k) { | ||||
unsigned int i; | |||||
unsigned int i; | |||||
for (i = 0; i < N; ++i) | |||||
a->coeffs[i] <<= k; | |||||
for (i = 0; i < N; ++i) | |||||
a->coeffs[i] <<= k; | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -126,7 +126,7 @@ void poly_shiftl(poly *a, unsigned int k) { | |||||
* Arguments: - poly *a: pointer to input/output polynomial | * Arguments: - poly *a: pointer to input/output polynomial | ||||
**************************************************/ | **************************************************/ | ||||
void poly_ntt(poly *a) { | void poly_ntt(poly *a) { | ||||
ntt(a->coeffs); | |||||
ntt(a->coeffs); | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -138,7 +138,7 @@ void poly_ntt(poly *a) { | |||||
* Arguments: - poly *a: pointer to input/output polynomial | * Arguments: - poly *a: pointer to input/output polynomial | ||||
**************************************************/ | **************************************************/ | ||||
void poly_invntt_montgomery(poly *a) { | void poly_invntt_montgomery(poly *a) { | ||||
invntt_frominvmont(a->coeffs); | |||||
invntt_frominvmont(a->coeffs); | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -154,10 +154,10 @@ void poly_invntt_montgomery(poly *a) { | |||||
* - const poly *b: pointer to second input polynomial | * - const poly *b: pointer to second input polynomial | ||||
**************************************************/ | **************************************************/ | ||||
void poly_pointwise_invmontgomery(poly *c, const poly *a, const poly *b) { | void poly_pointwise_invmontgomery(poly *c, const poly *a, const poly *b) { | ||||
unsigned int i; | |||||
unsigned int i; | |||||
for (i = 0; i < N; ++i) | |||||
c->coeffs[i] = montgomery_reduce((uint64_t)a->coeffs[i] * b->coeffs[i]); | |||||
for (i = 0; i < N; ++i) | |||||
c->coeffs[i] = montgomery_reduce((uint64_t)a->coeffs[i] * b->coeffs[i]); | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -174,10 +174,10 @@ void poly_pointwise_invmontgomery(poly *c, const poly *a, const poly *b) { | |||||
* - const poly *v: pointer to input polynomial | * - const poly *v: pointer to input polynomial | ||||
**************************************************/ | **************************************************/ | ||||
void poly_power2round(poly *a1, poly *a0, const poly *a) { | void poly_power2round(poly *a1, poly *a0, const poly *a) { | ||||
unsigned int i; | |||||
unsigned int i; | |||||
for (i = 0; i < N; ++i) | |||||
a1->coeffs[i] = power2round(a->coeffs[i], a0->coeffs + i); | |||||
for (i = 0; i < N; ++i) | |||||
a1->coeffs[i] = power2round(a->coeffs[i], a0->coeffs + i); | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -195,10 +195,10 @@ void poly_power2round(poly *a1, poly *a0, const poly *a) { | |||||
* - const poly *c: pointer to input polynomial | * - const poly *c: pointer to input polynomial | ||||
**************************************************/ | **************************************************/ | ||||
void poly_decompose(poly *a1, poly *a0, const poly *a) { | void poly_decompose(poly *a1, poly *a0, const poly *a) { | ||||
unsigned int i; | |||||
unsigned int i; | |||||
for (i = 0; i < N; ++i) | |||||
a1->coeffs[i] = decompose(a->coeffs[i], a0->coeffs + i); | |||||
for (i = 0; i < N; ++i) | |||||
a1->coeffs[i] = decompose(a->coeffs[i], a0->coeffs + i); | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -216,13 +216,13 @@ void poly_decompose(poly *a1, poly *a0, const poly *a) { | |||||
* Returns number of 1 bits. | * Returns number of 1 bits. | ||||
**************************************************/ | **************************************************/ | ||||
unsigned int poly_make_hint(poly *h, const poly *a, const poly *b) { | unsigned int poly_make_hint(poly *h, const poly *a, const poly *b) { | ||||
unsigned int i, s = 0; | |||||
unsigned int i, s = 0; | |||||
for (i = 0; i < N; ++i) { | |||||
h->coeffs[i] = make_hint(a->coeffs[i], b->coeffs[i]); | |||||
s += h->coeffs[i]; | |||||
} | |||||
return s; | |||||
for (i = 0; i < N; ++i) { | |||||
h->coeffs[i] = make_hint(a->coeffs[i], b->coeffs[i]); | |||||
s += h->coeffs[i]; | |||||
} | |||||
return s; | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -235,10 +235,10 @@ unsigned int poly_make_hint(poly *h, const poly *a, const poly *b) { | |||||
* - const poly *h: pointer to input hint polynomial | * - const poly *h: pointer to input hint polynomial | ||||
**************************************************/ | **************************************************/ | ||||
void poly_use_hint(poly *a, const poly *b, const poly *h) { | void poly_use_hint(poly *a, const poly *b, const poly *h) { | ||||
unsigned int i; | |||||
unsigned int i; | |||||
for (i = 0; i < N; ++i) | |||||
a->coeffs[i] = use_hint(b->coeffs[i], h->coeffs[i]); | |||||
for (i = 0; i < N; ++i) | |||||
a->coeffs[i] = use_hint(b->coeffs[i], h->coeffs[i]); | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -253,23 +253,23 @@ void poly_use_hint(poly *a, const poly *b, const poly *h) { | |||||
* Returns 0 if norm is strictly smaller than B and 1 otherwise. | * Returns 0 if norm is strictly smaller than B and 1 otherwise. | ||||
**************************************************/ | **************************************************/ | ||||
int poly_chknorm(const poly *a, uint32_t B) { | int 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 = (Q - 1) / 2 - a->coeffs[i]; | |||||
t ^= (t >> 31); | |||||
t = (Q - 1) / 2 - t; | |||||
if ((uint32_t)t >= B) { | |||||
return 1; | |||||
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 = (Q - 1) / 2 - a->coeffs[i]; | |||||
t ^= (t >> 31); | |||||
t = (Q - 1) / 2 - t; | |||||
if ((uint32_t)t >= B) { | |||||
return 1; | |||||
} | |||||
} | } | ||||
} | |||||
return 0; | |||||
return 0; | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -283,19 +283,19 @@ int poly_chknorm(const poly *a, uint32_t B) { | |||||
* - const unsigned char *buf: array of random bytes | * - const unsigned char *buf: array of random bytes | ||||
**************************************************/ | **************************************************/ | ||||
void poly_uniform(poly *a, const unsigned char *buf) { | void poly_uniform(poly *a, const unsigned char *buf) { | ||||
unsigned int ctr, pos; | |||||
uint32_t t; | |||||
ctr = pos = 0; | |||||
while (ctr < N) { | |||||
t = buf[pos++]; | |||||
t |= (uint32_t)buf[pos++] << 8; | |||||
t |= (uint32_t)buf[pos++] << 16; | |||||
t &= 0x7FFFFF; | |||||
if (t < Q) | |||||
a->coeffs[ctr++] = t; | |||||
} | |||||
unsigned int ctr, pos; | |||||
uint32_t t; | |||||
ctr = pos = 0; | |||||
while (ctr < N) { | |||||
t = buf[pos++]; | |||||
t |= (uint32_t)buf[pos++] << 8; | |||||
t |= (uint32_t)buf[pos++] << 16; | |||||
t &= 0x7FFFFF; | |||||
if (t < Q) | |||||
a->coeffs[ctr++] = t; | |||||
} | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -317,25 +317,25 @@ static unsigned int rej_eta(uint32_t *a, unsigned int len, | |||||
#if ETA > 7 | #if ETA > 7 | ||||
#error "rej_eta() assumes ETA <= 7" | #error "rej_eta() assumes ETA <= 7" | ||||
#endif | #endif | ||||
unsigned int ctr, pos; | |||||
unsigned char t0, t1; | |||||
unsigned int ctr, pos; | |||||
unsigned char t0, t1; | |||||
ctr = pos = 0; | |||||
while (ctr < len && pos < buflen) { | |||||
ctr = pos = 0; | |||||
while (ctr < len && pos < buflen) { | |||||
#if ETA <= 3 | #if ETA <= 3 | ||||
t0 = buf[pos] & 0x07; | |||||
t1 = buf[pos++] >> 5; | |||||
t0 = buf[pos] & 0x07; | |||||
t1 = buf[pos++] >> 5; | |||||
#else | #else | ||||
t0 = buf[pos] & 0x0F; | |||||
t1 = buf[pos++] >> 4; | |||||
t0 = buf[pos] & 0x0F; | |||||
t1 = buf[pos++] >> 4; | |||||
#endif | #endif | ||||
if (t0 <= 2 * ETA) | |||||
a[ctr++] = Q + ETA - t0; | |||||
if (t1 <= 2 * ETA && ctr < len) | |||||
a[ctr++] = Q + ETA - t1; | |||||
} | |||||
return ctr; | |||||
if (t0 <= 2 * ETA) | |||||
a[ctr++] = Q + ETA - t0; | |||||
if (t1 <= 2 * ETA && ctr < len) | |||||
a[ctr++] = Q + ETA - t1; | |||||
} | |||||
return ctr; | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -352,25 +352,25 @@ static unsigned int rej_eta(uint32_t *a, unsigned int len, | |||||
**************************************************/ | **************************************************/ | ||||
void poly_uniform_eta(poly *a, const unsigned char seed[SEEDBYTES], | void poly_uniform_eta(poly *a, const unsigned char seed[SEEDBYTES], | ||||
unsigned char nonce) { | unsigned char nonce) { | ||||
unsigned int i, ctr; | |||||
unsigned char inbuf[SEEDBYTES + 1]; | |||||
/* Probability that we need more than 2 blocks: < 2^{-84} | |||||
Probability that we need more than 3 blocks: < 2^{-352} */ | |||||
unsigned char outbuf[2 * SHAKE256_RATE]; | |||||
uint64_t state[25]; | |||||
for (i = 0; i < SEEDBYTES; ++i) | |||||
inbuf[i] = seed[i]; | |||||
inbuf[SEEDBYTES] = nonce; | |||||
shake256_absorb(state, inbuf, SEEDBYTES + 1); | |||||
shake256_squeezeblocks(outbuf, 2, state); | |||||
ctr = rej_eta(a->coeffs, N, outbuf, 2 * SHAKE256_RATE); | |||||
if (ctr < N) { | |||||
shake256_squeezeblocks(outbuf, 1, state); | |||||
rej_eta(a->coeffs + ctr, N - ctr, outbuf, SHAKE256_RATE); | |||||
} | |||||
unsigned int i, ctr; | |||||
unsigned char inbuf[SEEDBYTES + 1]; | |||||
/* Probability that we need more than 2 blocks: < 2^{-84} | |||||
Probability that we need more than 3 blocks: < 2^{-352} */ | |||||
unsigned char outbuf[2 * SHAKE256_RATE]; | |||||
uint64_t state[25]; | |||||
for (i = 0; i < SEEDBYTES; ++i) | |||||
inbuf[i] = seed[i]; | |||||
inbuf[SEEDBYTES] = nonce; | |||||
shake256_absorb(state, inbuf, SEEDBYTES + 1); | |||||
shake256_squeezeblocks(outbuf, 2, state); | |||||
ctr = rej_eta(a->coeffs, N, outbuf, 2 * SHAKE256_RATE); | |||||
if (ctr < N) { | |||||
shake256_squeezeblocks(outbuf, 1, state); | |||||
rej_eta(a->coeffs + ctr, N - ctr, outbuf, SHAKE256_RATE); | |||||
} | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -394,29 +394,29 @@ static unsigned int rej_gamma1m1(uint32_t *a, unsigned int len, | |||||
#if GAMMA1 > (1 << 19) | #if GAMMA1 > (1 << 19) | ||||
#error "rej_gamma1m1() assumes GAMMA1 - 1 fits in 19 bits" | #error "rej_gamma1m1() assumes GAMMA1 - 1 fits in 19 bits" | ||||
#endif | #endif | ||||
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; | |||||
} | |||||
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; | |||||
return ctr; | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -434,28 +434,28 @@ static unsigned int rej_gamma1m1(uint32_t *a, unsigned int len, | |||||
void poly_uniform_gamma1m1(poly *a, | void poly_uniform_gamma1m1(poly *a, | ||||
const unsigned char seed[SEEDBYTES + CRHBYTES], | const unsigned char seed[SEEDBYTES + CRHBYTES], | ||||
uint16_t nonce) { | uint16_t nonce) { | ||||
unsigned int i, ctr; | |||||
unsigned char inbuf[SEEDBYTES + CRHBYTES + 2]; | |||||
/* Probability that we need more than 5 blocks: < 2^{-81} | |||||
Probability that we need more than 6 blocks: < 2^{-467} */ | |||||
unsigned char outbuf[5 * SHAKE256_RATE]; | |||||
uint64_t state[25]; | |||||
for (i = 0; i < SEEDBYTES + CRHBYTES; ++i) | |||||
inbuf[i] = seed[i]; | |||||
inbuf[SEEDBYTES + CRHBYTES] = nonce & 0xFF; | |||||
inbuf[SEEDBYTES + CRHBYTES + 1] = nonce >> 8; | |||||
shake256_absorb(state, inbuf, SEEDBYTES + CRHBYTES + 2); | |||||
shake256_squeezeblocks(outbuf, 5, state); | |||||
ctr = rej_gamma1m1(a->coeffs, N, outbuf, 5 * SHAKE256_RATE); | |||||
if (ctr < N) { | |||||
/* There are no bytes left in outbuf | |||||
since 5*SHAKE256_RATE is divisible by 5 */ | |||||
shake256_squeezeblocks(outbuf, 1, state); | |||||
rej_gamma1m1(a->coeffs + ctr, N - ctr, outbuf, SHAKE256_RATE); | |||||
} | |||||
unsigned int i, ctr; | |||||
unsigned char inbuf[SEEDBYTES + CRHBYTES + 2]; | |||||
/* Probability that we need more than 5 blocks: < 2^{-81} | |||||
Probability that we need more than 6 blocks: < 2^{-467} */ | |||||
unsigned char outbuf[5 * SHAKE256_RATE]; | |||||
uint64_t state[25]; | |||||
for (i = 0; i < SEEDBYTES + CRHBYTES; ++i) | |||||
inbuf[i] = seed[i]; | |||||
inbuf[SEEDBYTES + CRHBYTES] = nonce & 0xFF; | |||||
inbuf[SEEDBYTES + CRHBYTES + 1] = nonce >> 8; | |||||
shake256_absorb(state, inbuf, SEEDBYTES + CRHBYTES + 2); | |||||
shake256_squeezeblocks(outbuf, 5, state); | |||||
ctr = rej_gamma1m1(a->coeffs, N, outbuf, 5 * SHAKE256_RATE); | |||||
if (ctr < N) { | |||||
/* There are no bytes left in outbuf | |||||
since 5*SHAKE256_RATE is divisible by 5 */ | |||||
shake256_squeezeblocks(outbuf, 1, state); | |||||
rej_gamma1m1(a->coeffs + ctr, N - ctr, outbuf, SHAKE256_RATE); | |||||
} | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -472,37 +472,37 @@ void polyeta_pack(unsigned char *r, const poly *a) { | |||||
#if ETA > 7 | #if ETA > 7 | ||||
#error "polyeta_pack() assumes ETA <= 7" | #error "polyeta_pack() assumes ETA <= 7" | ||||
#endif | #endif | ||||
unsigned int i; | |||||
unsigned char t[8]; | |||||
unsigned int i; | |||||
unsigned char t[8]; | |||||
#if ETA <= 3 | #if ETA <= 3 | ||||
for (i = 0; i < N / 8; ++i) { | |||||
t[0] = Q + ETA - a->coeffs[8 * i + 0]; | |||||
t[1] = Q + ETA - a->coeffs[8 * i + 1]; | |||||
t[2] = Q + ETA - a->coeffs[8 * i + 2]; | |||||
t[3] = Q + ETA - a->coeffs[8 * i + 3]; | |||||
t[4] = Q + ETA - a->coeffs[8 * i + 4]; | |||||
t[5] = Q + ETA - a->coeffs[8 * i + 5]; | |||||
t[6] = Q + ETA - a->coeffs[8 * i + 6]; | |||||
t[7] = Q + ETA - a->coeffs[8 * i + 7]; | |||||
r[3 * i + 0] = t[0]; | |||||
r[3 * i + 0] |= t[1] << 3; | |||||
r[3 * i + 0] |= t[2] << 6; | |||||
r[3 * i + 1] = t[2] >> 2; | |||||
r[3 * i + 1] |= t[3] << 1; | |||||
r[3 * i + 1] |= t[4] << 4; | |||||
r[3 * i + 1] |= t[5] << 7; | |||||
r[3 * i + 2] = t[5] >> 1; | |||||
r[3 * i + 2] |= t[6] << 2; | |||||
r[3 * i + 2] |= t[7] << 5; | |||||
} | |||||
for (i = 0; i < N / 8; ++i) { | |||||
t[0] = Q + ETA - a->coeffs[8 * i + 0]; | |||||
t[1] = Q + ETA - a->coeffs[8 * i + 1]; | |||||
t[2] = Q + ETA - a->coeffs[8 * i + 2]; | |||||
t[3] = Q + ETA - a->coeffs[8 * i + 3]; | |||||
t[4] = Q + ETA - a->coeffs[8 * i + 4]; | |||||
t[5] = Q + ETA - a->coeffs[8 * i + 5]; | |||||
t[6] = Q + ETA - a->coeffs[8 * i + 6]; | |||||
t[7] = Q + ETA - a->coeffs[8 * i + 7]; | |||||
r[3 * i + 0] = t[0]; | |||||
r[3 * i + 0] |= t[1] << 3; | |||||
r[3 * i + 0] |= t[2] << 6; | |||||
r[3 * i + 1] = t[2] >> 2; | |||||
r[3 * i + 1] |= t[3] << 1; | |||||
r[3 * i + 1] |= t[4] << 4; | |||||
r[3 * i + 1] |= t[5] << 7; | |||||
r[3 * i + 2] = t[5] >> 1; | |||||
r[3 * i + 2] |= t[6] << 2; | |||||
r[3 * i + 2] |= t[7] << 5; | |||||
} | |||||
#else | #else | ||||
for (i = 0; i < N / 2; ++i) { | |||||
t[0] = Q + ETA - a->coeffs[2 * i + 0]; | |||||
t[1] = Q + ETA - a->coeffs[2 * i + 1]; | |||||
r[i] = t[0] | (t[1] << 4); | |||||
} | |||||
for (i = 0; i < N / 2; ++i) { | |||||
t[0] = Q + ETA - a->coeffs[2 * i + 0]; | |||||
t[1] = Q + ETA - a->coeffs[2 * i + 1]; | |||||
r[i] = t[0] | (t[1] << 4); | |||||
} | |||||
#endif | #endif | ||||
} | } | ||||
@@ -516,35 +516,37 @@ void polyeta_pack(unsigned char *r, const poly *a) { | |||||
* - const unsigned char *a: byte array with bit-packed polynomial | * - const unsigned char *a: byte array with bit-packed polynomial | ||||
**************************************************/ | **************************************************/ | ||||
void polyeta_unpack(poly *r, const unsigned char *a) { | void polyeta_unpack(poly *r, const unsigned char *a) { | ||||
unsigned int i; | |||||
unsigned int i; | |||||
#if ETA <= 3 | #if ETA <= 3 | ||||
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] = (a[3 * i + 0] >> 6) | ((a[3 * i + 1] & 0x01) << 2); | |||||
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] = (a[3 * i + 1] >> 7) | ((a[3 * i + 2] & 0x03) << 1); | |||||
r->coeffs[8 * i + 6] = (a[3 * i + 2] >> 2) & 0x07; | |||||
r->coeffs[8 * i + 7] = (a[3 * i + 2] >> 5); | |||||
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]; | |||||
} | |||||
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] = | |||||
(a[3 * i + 0] >> 6) | ((a[3 * i + 1] & 0x01) << 2); | |||||
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] = | |||||
(a[3 * i + 1] >> 7) | ((a[3 * i + 2] & 0x03) << 1); | |||||
r->coeffs[8 * i + 6] = (a[3 * i + 2] >> 2) & 0x07; | |||||
r->coeffs[8 * i + 7] = (a[3 * i + 2] >> 5); | |||||
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]; | |||||
} | |||||
#else | #else | ||||
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]; | |||||
} | |||||
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]; | |||||
} | |||||
#endif | #endif | ||||
} | } | ||||
@@ -562,26 +564,26 @@ void polyt1_pack(unsigned char *r, const poly *a) { | |||||
#if D != 14 | #if D != 14 | ||||
#error "polyt1_pack() assumes D == 14" | #error "polyt1_pack() assumes D == 14" | ||||
#endif | #endif | ||||
unsigned int i; | |||||
for (i = 0; i < N / 8; ++i) { | |||||
r[9 * i + 0] = a->coeffs[8 * i + 0] & 0xFF; | |||||
r[9 * i + 1] = | |||||
(a->coeffs[8 * i + 0] >> 8) | ((a->coeffs[8 * i + 1] & 0x7F) << 1); | |||||
r[9 * i + 2] = | |||||
(a->coeffs[8 * i + 1] >> 7) | ((a->coeffs[8 * i + 2] & 0x3F) << 2); | |||||
r[9 * i + 3] = | |||||
(a->coeffs[8 * i + 2] >> 6) | ((a->coeffs[8 * i + 3] & 0x1F) << 3); | |||||
r[9 * i + 4] = | |||||
(a->coeffs[8 * i + 3] >> 5) | ((a->coeffs[8 * i + 4] & 0x0F) << 4); | |||||
r[9 * i + 5] = | |||||
(a->coeffs[8 * i + 4] >> 4) | ((a->coeffs[8 * i + 5] & 0x07) << 5); | |||||
r[9 * i + 6] = | |||||
(a->coeffs[8 * i + 5] >> 3) | ((a->coeffs[8 * i + 6] & 0x03) << 6); | |||||
r[9 * i + 7] = | |||||
(a->coeffs[8 * i + 6] >> 2) | ((a->coeffs[8 * i + 7] & 0x01) << 7); | |||||
r[9 * i + 8] = a->coeffs[8 * i + 7] >> 1; | |||||
} | |||||
unsigned int i; | |||||
for (i = 0; i < N / 8; ++i) { | |||||
r[9 * i + 0] = a->coeffs[8 * i + 0] & 0xFF; | |||||
r[9 * i + 1] = | |||||
(a->coeffs[8 * i + 0] >> 8) | ((a->coeffs[8 * i + 1] & 0x7F) << 1); | |||||
r[9 * i + 2] = | |||||
(a->coeffs[8 * i + 1] >> 7) | ((a->coeffs[8 * i + 2] & 0x3F) << 2); | |||||
r[9 * i + 3] = | |||||
(a->coeffs[8 * i + 2] >> 6) | ((a->coeffs[8 * i + 3] & 0x1F) << 3); | |||||
r[9 * i + 4] = | |||||
(a->coeffs[8 * i + 3] >> 5) | ((a->coeffs[8 * i + 4] & 0x0F) << 4); | |||||
r[9 * i + 5] = | |||||
(a->coeffs[8 * i + 4] >> 4) | ((a->coeffs[8 * i + 5] & 0x07) << 5); | |||||
r[9 * i + 6] = | |||||
(a->coeffs[8 * i + 5] >> 3) | ((a->coeffs[8 * i + 6] & 0x03) << 6); | |||||
r[9 * i + 7] = | |||||
(a->coeffs[8 * i + 6] >> 2) | ((a->coeffs[8 * i + 7] & 0x01) << 7); | |||||
r[9 * i + 8] = a->coeffs[8 * i + 7] >> 1; | |||||
} | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -594,26 +596,26 @@ void polyt1_pack(unsigned char *r, const poly *a) { | |||||
* - const unsigned char *a: byte array with bit-packed polynomial | * - const unsigned char *a: byte array with bit-packed polynomial | ||||
**************************************************/ | **************************************************/ | ||||
void polyt1_unpack(poly *r, const unsigned char *a) { | void 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] & 0x01) << 8); | |||||
r->coeffs[8 * i + 1] = | |||||
(a[9 * i + 1] >> 1) | ((uint32_t)(a[9 * i + 2] & 0x03) << 7); | |||||
r->coeffs[8 * i + 2] = | |||||
(a[9 * i + 2] >> 2) | ((uint32_t)(a[9 * i + 3] & 0x07) << 6); | |||||
r->coeffs[8 * i + 3] = | |||||
(a[9 * i + 3] >> 3) | ((uint32_t)(a[9 * i + 4] & 0x0F) << 5); | |||||
r->coeffs[8 * i + 4] = | |||||
(a[9 * i + 4] >> 4) | ((uint32_t)(a[9 * i + 5] & 0x1F) << 4); | |||||
r->coeffs[8 * i + 5] = | |||||
(a[9 * i + 5] >> 5) | ((uint32_t)(a[9 * i + 6] & 0x3F) << 3); | |||||
r->coeffs[8 * i + 6] = | |||||
(a[9 * i + 6] >> 6) | ((uint32_t)(a[9 * i + 7] & 0x7F) << 2); | |||||
r->coeffs[8 * i + 7] = | |||||
(a[9 * i + 7] >> 7) | ((uint32_t)(a[9 * i + 8] & 0xFF) << 1); | |||||
} | |||||
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] & 0x01) << 8); | |||||
r->coeffs[8 * i + 1] = | |||||
(a[9 * i + 1] >> 1) | ((uint32_t)(a[9 * i + 2] & 0x03) << 7); | |||||
r->coeffs[8 * i + 2] = | |||||
(a[9 * i + 2] >> 2) | ((uint32_t)(a[9 * i + 3] & 0x07) << 6); | |||||
r->coeffs[8 * i + 3] = | |||||
(a[9 * i + 3] >> 3) | ((uint32_t)(a[9 * i + 4] & 0x0F) << 5); | |||||
r->coeffs[8 * i + 4] = | |||||
(a[9 * i + 4] >> 4) | ((uint32_t)(a[9 * i + 5] & 0x1F) << 4); | |||||
r->coeffs[8 * i + 5] = | |||||
(a[9 * i + 5] >> 5) | ((uint32_t)(a[9 * i + 6] & 0x3F) << 3); | |||||
r->coeffs[8 * i + 6] = | |||||
(a[9 * i + 6] >> 6) | ((uint32_t)(a[9 * i + 7] & 0x7F) << 2); | |||||
r->coeffs[8 * i + 7] = | |||||
(a[9 * i + 7] >> 7) | ((uint32_t)(a[9 * i + 8] & 0xFF) << 1); | |||||
} | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -627,26 +629,26 @@ void polyt1_unpack(poly *r, const unsigned char *a) { | |||||
* - const poly *a: pointer to input polynomial | * - const poly *a: pointer to input polynomial | ||||
**************************************************/ | **************************************************/ | ||||
void polyt0_pack(unsigned char *r, const poly *a) { | void 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 + (1 << (D - 1)) - a->coeffs[4 * i + 0]; | |||||
t[1] = Q + (1 << (D - 1)) - a->coeffs[4 * i + 1]; | |||||
t[2] = Q + (1 << (D - 1)) - a->coeffs[4 * i + 2]; | |||||
t[3] = Q + (1 << (D - 1)) - a->coeffs[4 * i + 3]; | |||||
r[7 * i + 0] = t[0]; | |||||
r[7 * i + 1] = t[0] >> 8; | |||||
r[7 * i + 1] |= t[1] << 6; | |||||
r[7 * i + 2] = t[1] >> 2; | |||||
r[7 * i + 3] = t[1] >> 10; | |||||
r[7 * i + 3] |= t[2] << 4; | |||||
r[7 * i + 4] = t[2] >> 4; | |||||
r[7 * i + 5] = t[2] >> 12; | |||||
r[7 * i + 5] |= t[3] << 2; | |||||
r[7 * i + 6] = t[3] >> 6; | |||||
} | |||||
unsigned int i; | |||||
uint32_t t[4]; | |||||
for (i = 0; i < N / 4; ++i) { | |||||
t[0] = Q + (1 << (D - 1)) - a->coeffs[4 * i + 0]; | |||||
t[1] = Q + (1 << (D - 1)) - a->coeffs[4 * i + 1]; | |||||
t[2] = Q + (1 << (D - 1)) - a->coeffs[4 * i + 2]; | |||||
t[3] = Q + (1 << (D - 1)) - a->coeffs[4 * i + 3]; | |||||
r[7 * i + 0] = t[0]; | |||||
r[7 * i + 1] = t[0] >> 8; | |||||
r[7 * i + 1] |= t[1] << 6; | |||||
r[7 * i + 2] = t[1] >> 2; | |||||
r[7 * i + 3] = t[1] >> 10; | |||||
r[7 * i + 3] |= t[2] << 4; | |||||
r[7 * i + 4] = t[2] >> 4; | |||||
r[7 * i + 5] = t[2] >> 12; | |||||
r[7 * i + 5] |= t[3] << 2; | |||||
r[7 * i + 6] = t[3] >> 6; | |||||
} | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -659,28 +661,28 @@ void polyt0_pack(unsigned char *r, const poly *a) { | |||||
* - const unsigned char *a: byte array with bit-packed polynomial | * - const unsigned char *a: byte array with bit-packed polynomial | ||||
**************************************************/ | **************************************************/ | ||||
void polyt0_unpack(poly *r, const unsigned char *a) { | void polyt0_unpack(poly *r, const unsigned char *a) { | ||||
unsigned int i; | |||||
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; | |||||
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 + 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 + 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 + 3] = a[7 * i + 5] >> 2; | |||||
r->coeffs[4 * i + 3] |= (uint32_t)a[7 * i + 6] << 6; | |||||
r->coeffs[4 * i + 0] = Q + (1 << (D - 1)) - r->coeffs[4 * i + 0]; | |||||
r->coeffs[4 * i + 1] = Q + (1 << (D - 1)) - r->coeffs[4 * i + 1]; | |||||
r->coeffs[4 * i + 2] = Q + (1 << (D - 1)) - r->coeffs[4 * i + 2]; | |||||
r->coeffs[4 * i + 3] = Q + (1 << (D - 1)) - r->coeffs[4 * i + 3]; | |||||
} | |||||
r->coeffs[4 * i + 0] = Q + (1 << (D - 1)) - r->coeffs[4 * i + 0]; | |||||
r->coeffs[4 * i + 1] = Q + (1 << (D - 1)) - r->coeffs[4 * i + 1]; | |||||
r->coeffs[4 * i + 2] = Q + (1 << (D - 1)) - r->coeffs[4 * i + 2]; | |||||
r->coeffs[4 * i + 3] = Q + (1 << (D - 1)) - r->coeffs[4 * i + 3]; | |||||
} | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -698,23 +700,23 @@ void polyz_pack(unsigned char *r, const poly *a) { | |||||
#if GAMMA1 > (1 << 19) | #if GAMMA1 > (1 << 19) | ||||
#error "polyz_pack() assumes GAMMA1 <= 2^{19}" | #error "polyz_pack() assumes GAMMA1 <= 2^{19}" | ||||
#endif | #endif | ||||
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] = t[0]; | |||||
r[5 * i + 1] = t[0] >> 8; | |||||
r[5 * i + 2] = t[0] >> 16; | |||||
r[5 * i + 2] |= t[1] << 4; | |||||
r[5 * i + 3] = t[1] >> 4; | |||||
r[5 * i + 4] = t[1] >> 12; | |||||
} | |||||
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] = t[0]; | |||||
r[5 * i + 1] = t[0] >> 8; | |||||
r[5 * i + 2] = t[0] >> 16; | |||||
r[5 * i + 2] |= t[1] << 4; | |||||
r[5 * i + 3] = t[1] >> 4; | |||||
r[5 * i + 4] = t[1] >> 12; | |||||
} | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -728,22 +730,22 @@ void polyz_pack(unsigned char *r, const poly *a) { | |||||
* - const unsigned char *a: byte array with bit-packed polynomial | * - const unsigned char *a: byte array with bit-packed polynomial | ||||
**************************************************/ | **************************************************/ | ||||
void polyz_unpack(poly *r, const unsigned char *a) { | void 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; | |||||
} | |||||
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; | |||||
} | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -757,8 +759,8 @@ void polyz_unpack(poly *r, const unsigned char *a) { | |||||
* - const poly *a: pointer to input polynomial | * - const poly *a: pointer to input polynomial | ||||
**************************************************/ | **************************************************/ | ||||
void polyw1_pack(unsigned char *r, const poly *a) { | void polyw1_pack(unsigned char *r, const poly *a) { | ||||
unsigned int i; | |||||
unsigned int i; | |||||
for (i = 0; i < N / 2; ++i) | |||||
r[i] = a->coeffs[2 * i + 0] | (a->coeffs[2 * i + 1] << 4); | |||||
for (i = 0; i < N / 2; ++i) | |||||
r[i] = a->coeffs[2 * i + 0] | (a->coeffs[2 * i + 1] << 4); | |||||
} | } |
@@ -6,7 +6,7 @@ | |||||
#include <stdint.h> | #include <stdint.h> | ||||
typedef struct { | typedef struct { | ||||
uint32_t coeffs[N]; | |||||
uint32_t coeffs[N]; | |||||
} poly __attribute__((aligned(32))); | } poly __attribute__((aligned(32))); | ||||
void poly_reduce(poly *a); | void poly_reduce(poly *a); | ||||
@@ -16,10 +16,10 @@ | |||||
* Arguments: - polyvecl *v: pointer to input/output vector | * Arguments: - polyvecl *v: pointer to input/output vector | ||||
**************************************************/ | **************************************************/ | ||||
void polyvecl_freeze(polyvecl *v) { | void polyvecl_freeze(polyvecl *v) { | ||||
unsigned int i; | |||||
unsigned int i; | |||||
for (i = 0; i < L; ++i) | |||||
poly_freeze(v->vec + i); | |||||
for (i = 0; i < L; ++i) | |||||
poly_freeze(v->vec + i); | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -33,10 +33,10 @@ void polyvecl_freeze(polyvecl *v) { | |||||
* - const polyvecl *v: pointer to second summand | * - const polyvecl *v: pointer to second summand | ||||
**************************************************/ | **************************************************/ | ||||
void polyvecl_add(polyvecl *w, const polyvecl *u, const polyvecl *v) { | void polyvecl_add(polyvecl *w, const polyvecl *u, const polyvecl *v) { | ||||
unsigned int i; | |||||
unsigned int i; | |||||
for (i = 0; i < L; ++i) | |||||
poly_add(w->vec + i, u->vec + i, v->vec + i); | |||||
for (i = 0; i < L; ++i) | |||||
poly_add(w->vec + i, u->vec + i, v->vec + i); | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -48,10 +48,10 @@ void polyvecl_add(polyvecl *w, const polyvecl *u, const polyvecl *v) { | |||||
* Arguments: - polyvecl *v: pointer to input/output vector | * Arguments: - polyvecl *v: pointer to input/output vector | ||||
**************************************************/ | **************************************************/ | ||||
void polyvecl_ntt(polyvecl *v) { | void polyvecl_ntt(polyvecl *v) { | ||||
unsigned int i; | |||||
unsigned int i; | |||||
for (i = 0; i < L; ++i) | |||||
poly_ntt(v->vec + i); | |||||
for (i = 0; i < L; ++i) | |||||
poly_ntt(v->vec + i); | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -69,15 +69,15 @@ void polyvecl_ntt(polyvecl *v) { | |||||
**************************************************/ | **************************************************/ | ||||
void polyvecl_pointwise_acc_invmontgomery(poly *w, const polyvecl *u, | void polyvecl_pointwise_acc_invmontgomery(poly *w, const polyvecl *u, | ||||
const polyvecl *v) { | const polyvecl *v) { | ||||
unsigned int i; | |||||
poly t; | |||||
unsigned int i; | |||||
poly t; | |||||
poly_pointwise_invmontgomery(w, u->vec + 0, v->vec + 0); | |||||
poly_pointwise_invmontgomery(w, u->vec + 0, v->vec + 0); | |||||
for (i = 1; i < L; ++i) { | |||||
poly_pointwise_invmontgomery(&t, u->vec + i, v->vec + i); | |||||
poly_add(w, w, &t); | |||||
} | |||||
for (i = 1; i < L; ++i) { | |||||
poly_pointwise_invmontgomery(&t, u->vec + i, v->vec + i); | |||||
poly_add(w, w, &t); | |||||
} | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -93,13 +93,13 @@ void polyvecl_pointwise_acc_invmontgomery(poly *w, const polyvecl *u, | |||||
* otherwise. | * otherwise. | ||||
**************************************************/ | **************************************************/ | ||||
int polyvecl_chknorm(const polyvecl *v, uint32_t bound) { | int polyvecl_chknorm(const polyvecl *v, uint32_t bound) { | ||||
unsigned int i; | |||||
int ret = 0; | |||||
unsigned int i; | |||||
int ret = 0; | |||||
for (i = 0; i < L; ++i) | |||||
ret |= poly_chknorm(v->vec + i, bound); | |||||
for (i = 0; i < L; ++i) | |||||
ret |= poly_chknorm(v->vec + i, bound); | |||||
return ret; | |||||
return ret; | |||||
} | } | ||||
/**************************************************************/ | /**************************************************************/ | ||||
@@ -115,10 +115,10 @@ int polyvecl_chknorm(const polyvecl *v, uint32_t bound) { | |||||
* Arguments: - polyveck *v: pointer to input/output vector | * Arguments: - polyveck *v: pointer to input/output vector | ||||
**************************************************/ | **************************************************/ | ||||
void polyveck_reduce(polyveck *v) { | void polyveck_reduce(polyveck *v) { | ||||
unsigned int i; | |||||
unsigned int i; | |||||
for (i = 0; i < K; ++i) | |||||
poly_reduce(v->vec + i); | |||||
for (i = 0; i < K; ++i) | |||||
poly_reduce(v->vec + i); | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -130,10 +130,10 @@ void polyveck_reduce(polyveck *v) { | |||||
* Arguments: - polyveck *v: pointer to input/output vector | * Arguments: - polyveck *v: pointer to input/output vector | ||||
**************************************************/ | **************************************************/ | ||||
void polyveck_csubq(polyveck *v) { | void polyveck_csubq(polyveck *v) { | ||||
unsigned int i; | |||||
unsigned int i; | |||||
for (i = 0; i < K; ++i) | |||||
poly_csubq(v->vec + i); | |||||
for (i = 0; i < K; ++i) | |||||
poly_csubq(v->vec + i); | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -145,10 +145,10 @@ void polyveck_csubq(polyveck *v) { | |||||
* Arguments: - polyveck *v: pointer to input/output vector | * Arguments: - polyveck *v: pointer to input/output vector | ||||
**************************************************/ | **************************************************/ | ||||
void polyveck_freeze(polyveck *v) { | void polyveck_freeze(polyveck *v) { | ||||
unsigned int i; | |||||
unsigned int i; | |||||
for (i = 0; i < K; ++i) | |||||
poly_freeze(v->vec + i); | |||||
for (i = 0; i < K; ++i) | |||||
poly_freeze(v->vec + i); | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -162,10 +162,10 @@ void polyveck_freeze(polyveck *v) { | |||||
* - const polyveck *v: pointer to second summand | * - const polyveck *v: pointer to second summand | ||||
**************************************************/ | **************************************************/ | ||||
void polyveck_add(polyveck *w, const polyveck *u, const polyveck *v) { | void polyveck_add(polyveck *w, const polyveck *u, const polyveck *v) { | ||||
unsigned int i; | |||||
unsigned int i; | |||||
for (i = 0; i < K; ++i) | |||||
poly_add(w->vec + i, u->vec + i, v->vec + i); | |||||
for (i = 0; i < K; ++i) | |||||
poly_add(w->vec + i, u->vec + i, v->vec + i); | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -181,10 +181,10 @@ void polyveck_add(polyveck *w, const polyveck *u, const polyveck *v) { | |||||
* subtracted from first input vector | * subtracted from first input vector | ||||
**************************************************/ | **************************************************/ | ||||
void polyveck_sub(polyveck *w, const polyveck *u, const polyveck *v) { | void polyveck_sub(polyveck *w, const polyveck *u, const polyveck *v) { | ||||
unsigned int i; | |||||
unsigned int i; | |||||
for (i = 0; i < K; ++i) | |||||
poly_sub(w->vec + i, u->vec + i, v->vec + i); | |||||
for (i = 0; i < K; ++i) | |||||
poly_sub(w->vec + i, u->vec + i, v->vec + i); | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -197,10 +197,10 @@ void polyveck_sub(polyveck *w, const polyveck *u, const polyveck *v) { | |||||
* - unsigned int k: exponent | * - unsigned int k: exponent | ||||
**************************************************/ | **************************************************/ | ||||
void polyveck_shiftl(polyveck *v, unsigned int k) { | void polyveck_shiftl(polyveck *v, unsigned int k) { | ||||
unsigned int i; | |||||
unsigned int i; | |||||
for (i = 0; i < K; ++i) | |||||
poly_shiftl(v->vec + i, k); | |||||
for (i = 0; i < K; ++i) | |||||
poly_shiftl(v->vec + i, k); | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -212,10 +212,10 @@ void polyveck_shiftl(polyveck *v, unsigned int k) { | |||||
* Arguments: - polyveck *v: pointer to input/output vector | * Arguments: - polyveck *v: pointer to input/output vector | ||||
**************************************************/ | **************************************************/ | ||||
void polyveck_ntt(polyveck *v) { | void polyveck_ntt(polyveck *v) { | ||||
unsigned int i; | |||||
unsigned int i; | |||||
for (i = 0; i < K; ++i) | |||||
poly_ntt(v->vec + i); | |||||
for (i = 0; i < K; ++i) | |||||
poly_ntt(v->vec + i); | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -228,10 +228,10 @@ void polyveck_ntt(polyveck *v) { | |||||
* Arguments: - polyveck *v: pointer to input/output vector | * Arguments: - polyveck *v: pointer to input/output vector | ||||
**************************************************/ | **************************************************/ | ||||
void polyveck_invntt_montgomery(polyveck *v) { | void polyveck_invntt_montgomery(polyveck *v) { | ||||
unsigned int i; | |||||
unsigned int i; | |||||
for (i = 0; i < K; ++i) | |||||
poly_invntt_montgomery(v->vec + i); | |||||
for (i = 0; i < K; ++i) | |||||
poly_invntt_montgomery(v->vec + i); | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -247,13 +247,13 @@ void polyveck_invntt_montgomery(polyveck *v) { | |||||
* otherwise. | * otherwise. | ||||
**************************************************/ | **************************************************/ | ||||
int polyveck_chknorm(const polyveck *v, uint32_t bound) { | int polyveck_chknorm(const polyveck *v, uint32_t bound) { | ||||
unsigned int i; | |||||
int ret = 0; | |||||
unsigned int i; | |||||
int ret = 0; | |||||
for (i = 0; i < K; ++i) | |||||
ret |= poly_chknorm(v->vec + i, bound); | |||||
for (i = 0; i < K; ++i) | |||||
ret |= poly_chknorm(v->vec + i, bound); | |||||
return ret; | |||||
return ret; | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -271,10 +271,10 @@ int polyveck_chknorm(const polyveck *v, uint32_t bound) { | |||||
* - const polyveck *v: pointer to input vector | * - const polyveck *v: pointer to input vector | ||||
**************************************************/ | **************************************************/ | ||||
void polyveck_power2round(polyveck *v1, polyveck *v0, const polyveck *v) { | void polyveck_power2round(polyveck *v1, polyveck *v0, const polyveck *v) { | ||||
unsigned int i; | |||||
unsigned int i; | |||||
for (i = 0; i < K; ++i) | |||||
poly_power2round(v1->vec + i, v0->vec + i, v->vec + i); | |||||
for (i = 0; i < K; ++i) | |||||
poly_power2round(v1->vec + i, v0->vec + i, v->vec + i); | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -293,10 +293,10 @@ void polyveck_power2round(polyveck *v1, polyveck *v0, const polyveck *v) { | |||||
* - const polyveck *v: pointer to input vector | * - const polyveck *v: pointer to input vector | ||||
**************************************************/ | **************************************************/ | ||||
void polyveck_decompose(polyveck *v1, polyveck *v0, const polyveck *v) { | void polyveck_decompose(polyveck *v1, polyveck *v0, const polyveck *v) { | ||||
unsigned int i; | |||||
unsigned int i; | |||||
for (i = 0; i < K; ++i) | |||||
poly_decompose(v1->vec + i, v0->vec + i, v->vec + i); | |||||
for (i = 0; i < K; ++i) | |||||
poly_decompose(v1->vec + i, v0->vec + i, v->vec + i); | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -312,12 +312,12 @@ void polyveck_decompose(polyveck *v1, polyveck *v0, const polyveck *v) { | |||||
**************************************************/ | **************************************************/ | ||||
unsigned int polyveck_make_hint(polyveck *h, const polyveck *u, | unsigned int polyveck_make_hint(polyveck *h, const polyveck *u, | ||||
const polyveck *v) { | const polyveck *v) { | ||||
unsigned int i, s = 0; | |||||
unsigned int i, s = 0; | |||||
for (i = 0; i < K; ++i) | |||||
s += poly_make_hint(h->vec + i, u->vec + i, v->vec + i); | |||||
for (i = 0; i < K; ++i) | |||||
s += poly_make_hint(h->vec + i, u->vec + i, v->vec + i); | |||||
return s; | |||||
return s; | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -331,8 +331,8 @@ unsigned int polyveck_make_hint(polyveck *h, const polyveck *u, | |||||
* - const polyveck *h: pointer to input hint vector | * - const polyveck *h: pointer to input hint vector | ||||
**************************************************/ | **************************************************/ | ||||
void polyveck_use_hint(polyveck *w, const polyveck *u, const polyveck *h) { | void polyveck_use_hint(polyveck *w, const polyveck *u, const polyveck *h) { | ||||
unsigned int i; | |||||
unsigned int i; | |||||
for (i = 0; i < K; ++i) | |||||
poly_use_hint(w->vec + i, u->vec + i, h->vec + i); | |||||
for (i = 0; i < K; ++i) | |||||
poly_use_hint(w->vec + i, u->vec + i, h->vec + i); | |||||
} | } |
@@ -7,7 +7,7 @@ | |||||
/* Vectors of polynomials of length L */ | /* Vectors of polynomials of length L */ | ||||
typedef struct { | typedef struct { | ||||
poly vec[L]; | |||||
poly vec[L]; | |||||
} polyvecl; | } polyvecl; | ||||
void polyvecl_freeze(polyvecl *v); | void polyvecl_freeze(polyvecl *v); | ||||
@@ -22,7 +22,7 @@ int polyvecl_chknorm(const polyvecl *v, uint32_t B); | |||||
/* Vectors of polynomials of length K */ | /* Vectors of polynomials of length K */ | ||||
typedef struct { | typedef struct { | ||||
poly vec[K]; | |||||
poly vec[K]; | |||||
} polyveck; | } polyveck; | ||||
void polyveck_reduce(polyveck *v); | void polyveck_reduce(polyveck *v); | ||||
@@ -13,14 +13,14 @@ | |||||
* Returns r. | * Returns r. | ||||
**************************************************/ | **************************************************/ | ||||
uint32_t montgomery_reduce(uint64_t a) { | uint32_t montgomery_reduce(uint64_t a) { | ||||
uint64_t t; | |||||
uint64_t t; | |||||
t = a * QINV; | |||||
t &= (1ULL << 32) - 1; | |||||
t *= Q; | |||||
t = a + t; | |||||
t >>= 32; | |||||
return t; | |||||
t = a * QINV; | |||||
t &= (1ULL << 32) - 1; | |||||
t *= Q; | |||||
t = a + t; | |||||
t >>= 32; | |||||
return t; | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -34,12 +34,12 @@ uint32_t montgomery_reduce(uint64_t a) { | |||||
* Returns r. | * Returns r. | ||||
**************************************************/ | **************************************************/ | ||||
uint32_t reduce32(uint32_t a) { | uint32_t reduce32(uint32_t a) { | ||||
uint32_t t; | |||||
uint32_t t; | |||||
t = a & 0x7FFFFF; | |||||
a >>= 23; | |||||
t += (a << 13) - a; | |||||
return t; | |||||
t = a & 0x7FFFFF; | |||||
a >>= 23; | |||||
t += (a << 13) - a; | |||||
return t; | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -52,9 +52,9 @@ uint32_t reduce32(uint32_t a) { | |||||
* Returns r. | * Returns r. | ||||
**************************************************/ | **************************************************/ | ||||
uint32_t csubq(uint32_t a) { | uint32_t csubq(uint32_t a) { | ||||
a -= Q; | |||||
a += ((int32_t)a >> 31) & Q; | |||||
return a; | |||||
a -= Q; | |||||
a += ((int32_t)a >> 31) & Q; | |||||
return a; | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -68,7 +68,7 @@ uint32_t csubq(uint32_t a) { | |||||
* Returns r. | * Returns r. | ||||
**************************************************/ | **************************************************/ | ||||
uint32_t freeze(uint32_t a) { | uint32_t freeze(uint32_t a) { | ||||
a = reduce32(a); | |||||
a = csubq(a); | |||||
return a; | |||||
a = reduce32(a); | |||||
a = csubq(a); | |||||
return a; | |||||
} | } |
@@ -14,16 +14,16 @@ | |||||
* Returns a1. | * Returns a1. | ||||
**************************************************/ | **************************************************/ | ||||
uint32_t power2round(uint32_t a, uint32_t *a0) { | uint32_t power2round(uint32_t a, uint32_t *a0) { | ||||
int32_t t; | |||||
int32_t t; | |||||
/* Centralized remainder mod 2^D */ | |||||
t = a & ((1 << D) - 1); | |||||
t -= (1 << (D - 1)) + 1; | |||||
t += (t >> 31) & (1 << D); | |||||
t -= (1 << (D - 1)) - 1; | |||||
*a0 = Q + t; | |||||
a = (a - t) >> D; | |||||
return a; | |||||
/* Centralized remainder mod 2^D */ | |||||
t = a & ((1 << D) - 1); | |||||
t -= (1 << (D - 1)) + 1; | |||||
t += (t >> 31) & (1 << D); | |||||
t -= (1 << (D - 1)) - 1; | |||||
*a0 = Q + t; | |||||
a = (a - t) >> D; | |||||
return a; | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -43,26 +43,26 @@ uint32_t decompose(uint32_t a, uint32_t *a0) { | |||||
#if ALPHA != (Q - 1) / 16 | #if ALPHA != (Q - 1) / 16 | ||||
#error "decompose assumes ALPHA == (Q-1)/16" | #error "decompose assumes ALPHA == (Q-1)/16" | ||||
#endif | #endif | ||||
int32_t t, u; | |||||
int32_t t, u; | |||||
/* Centralized remainder mod ALPHA */ | |||||
t = a & 0x7FFFF; | |||||
t += (a >> 19) << 9; | |||||
t -= ALPHA / 2 + 1; | |||||
t += (t >> 31) & ALPHA; | |||||
t -= ALPHA / 2 - 1; | |||||
a -= t; | |||||
/* Centralized remainder mod ALPHA */ | |||||
t = a & 0x7FFFF; | |||||
t += (a >> 19) << 9; | |||||
t -= ALPHA / 2 + 1; | |||||
t += (t >> 31) & ALPHA; | |||||
t -= ALPHA / 2 - 1; | |||||
a -= t; | |||||
/* Divide by ALPHA (possible to avoid) */ | |||||
u = a - 1; | |||||
u >>= 31; | |||||
a = (a >> 19) + 1; | |||||
a -= u & 1; | |||||
/* Divide by ALPHA (possible to avoid) */ | |||||
u = a - 1; | |||||
u >>= 31; | |||||
a = (a >> 19) + 1; | |||||
a -= u & 1; | |||||
/* Border case */ | |||||
*a0 = Q + t - (a >> 4); | |||||
a &= 0xF; | |||||
return a; | |||||
/* Border case */ | |||||
*a0 = Q + t - (a >> 4); | |||||
a &= 0xF; | |||||
return a; | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -78,9 +78,9 @@ uint32_t decompose(uint32_t a, uint32_t *a0) { | |||||
* Returns 1 if high bits of a and b differ and 0 otherwise. | * Returns 1 if high bits of a and b differ and 0 otherwise. | ||||
**************************************************/ | **************************************************/ | ||||
unsigned int make_hint(const uint32_t a, const uint32_t b) { | unsigned int make_hint(const uint32_t a, const uint32_t b) { | ||||
uint32_t t; | |||||
uint32_t t; | |||||
return decompose(a, &t) != decompose(b, &t); | |||||
return decompose(a, &t) != decompose(b, &t); | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -94,22 +94,22 @@ unsigned int make_hint(const uint32_t a, const uint32_t b) { | |||||
* Returns corrected high bits. | * Returns corrected high bits. | ||||
**************************************************/ | **************************************************/ | ||||
uint32_t use_hint(const uint32_t a, const unsigned int hint) { | uint32_t use_hint(const uint32_t a, const unsigned int hint) { | ||||
uint32_t a0, a1; | |||||
uint32_t a0, a1; | |||||
a1 = decompose(a, &a0); | |||||
if (hint == 0) | |||||
return a1; | |||||
else if (a0 > Q) | |||||
return (a1 + 1) & 0xF; | |||||
else | |||||
return (a1 - 1) & 0xF; | |||||
a1 = decompose(a, &a0); | |||||
if (hint == 0) | |||||
return a1; | |||||
else if (a0 > Q) | |||||
return (a1 + 1) & 0xF; | |||||
else | |||||
return (a1 - 1) & 0xF; | |||||
/* If decompose does not divide out ALPHA: | |||||
if(hint == 0) | |||||
return a1; | |||||
else if(a0 > Q) | |||||
return (a1 + ALPHA) % (Q - 1); | |||||
else | |||||
return (a1 - ALPHA) % (Q - 1); | |||||
*/ | |||||
/* If decompose does not divide out ALPHA: | |||||
if(hint == 0) | |||||
return a1; | |||||
else if(a0 > Q) | |||||
return (a1 + ALPHA) % (Q - 1); | |||||
else | |||||
return (a1 - ALPHA) % (Q - 1); | |||||
*/ | |||||
} | } |
@@ -18,24 +18,24 @@ | |||||
* - const unsigned char rho[]: byte array containing seed rho | * - const unsigned char rho[]: byte array containing seed rho | ||||
**************************************************/ | **************************************************/ | ||||
void expand_mat(polyvecl mat[K], const unsigned char rho[SEEDBYTES]) { | void expand_mat(polyvecl mat[K], const unsigned char rho[SEEDBYTES]) { | ||||
unsigned int i, j; | |||||
unsigned char inbuf[SEEDBYTES + 1]; | |||||
/* Don't change this to smaller values, | |||||
* sampling later assumes sufficient SHAKE output! | |||||
* Probability that we need more than 5 blocks: < 2^{-132}. | |||||
* Probability that we need more than 6 blocks: < 2^{-546}. */ | |||||
unsigned char outbuf[5 * SHAKE128_RATE]; | |||||
for (i = 0; i < SEEDBYTES; ++i) | |||||
inbuf[i] = rho[i]; | |||||
for (i = 0; i < K; ++i) { | |||||
for (j = 0; j < L; ++j) { | |||||
inbuf[SEEDBYTES] = i + (j << 4); | |||||
shake128(outbuf, sizeof(outbuf), inbuf, SEEDBYTES + 1); | |||||
poly_uniform(mat[i].vec + j, outbuf); | |||||
unsigned int i, j; | |||||
unsigned char inbuf[SEEDBYTES + 1]; | |||||
/* Don't change this to smaller values, | |||||
* sampling later assumes sufficient SHAKE output! | |||||
* Probability that we need more than 5 blocks: < 2^{-132}. | |||||
* Probability that we need more than 6 blocks: < 2^{-546}. */ | |||||
unsigned char outbuf[5 * SHAKE128_RATE]; | |||||
for (i = 0; i < SEEDBYTES; ++i) | |||||
inbuf[i] = rho[i]; | |||||
for (i = 0; i < K; ++i) { | |||||
for (j = 0; j < L; ++j) { | |||||
inbuf[SEEDBYTES] = i + (j << 4); | |||||
shake128(outbuf, sizeof(outbuf), inbuf, SEEDBYTES + 1); | |||||
poly_uniform(mat[i].vec + j, outbuf); | |||||
} | |||||
} | } | ||||
} | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -50,43 +50,43 @@ void expand_mat(polyvecl mat[K], const unsigned char rho[SEEDBYTES]) { | |||||
* - const polyveck *w1: pointer to vector w1 | * - const polyveck *w1: pointer to vector w1 | ||||
**************************************************/ | **************************************************/ | ||||
void challenge(poly *c, const unsigned char mu[CRHBYTES], const polyveck *w1) { | void challenge(poly *c, const unsigned char mu[CRHBYTES], const polyveck *w1) { | ||||
unsigned int i, b, pos; | |||||
unsigned char inbuf[CRHBYTES + K * POLW1_SIZE_PACKED]; | |||||
unsigned char outbuf[SHAKE256_RATE]; | |||||
uint64_t state[25], signs, mask; | |||||
for (i = 0; i < CRHBYTES; ++i) | |||||
inbuf[i] = mu[i]; | |||||
for (i = 0; i < K; ++i) | |||||
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; | |||||
mask = 1; | |||||
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] = (signs & mask) ? Q - 1 : 1; | |||||
mask <<= 1; | |||||
} | |||||
unsigned int i, b, pos; | |||||
unsigned char inbuf[CRHBYTES + K * POLW1_SIZE_PACKED]; | |||||
unsigned char outbuf[SHAKE256_RATE]; | |||||
uint64_t state[25], signs, mask; | |||||
for (i = 0; i < CRHBYTES; ++i) | |||||
inbuf[i] = mu[i]; | |||||
for (i = 0; i < K; ++i) | |||||
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; | |||||
mask = 1; | |||||
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] = (signs & mask) ? Q - 1 : 1; | |||||
mask <<= 1; | |||||
} | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -102,53 +102,53 @@ void challenge(poly *c, const unsigned char mu[CRHBYTES], const polyveck *w1) { | |||||
* Returns 0 (success) | * Returns 0 (success) | ||||
**************************************************/ | **************************************************/ | ||||
int crypto_sign_keypair(unsigned char *pk, unsigned char *sk) { | int crypto_sign_keypair(unsigned char *pk, unsigned char *sk) { | ||||
unsigned int i; | |||||
unsigned char seedbuf[3 * SEEDBYTES]; | |||||
unsigned char tr[CRHBYTES]; | |||||
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, SEEDBYTES); | |||||
shake256(seedbuf, 3 * SEEDBYTES, seedbuf, SEEDBYTES); | |||||
rho = seedbuf; | |||||
rhoprime = rho + SEEDBYTES; | |||||
key = rho + 2 * SEEDBYTES; | |||||
/* Expand matrix */ | |||||
expand_mat(mat, rho); | |||||
/* Sample short vectors s1 and s2 */ | |||||
for (i = 0; i < L; ++i) | |||||
poly_uniform_eta(s1.vec + i, rhoprime, nonce++); | |||||
for (i = 0; i < K; ++i) | |||||
poly_uniform_eta(s2.vec + i, rhoprime, nonce++); | |||||
/* Matrix-vector multiplication */ | |||||
s1hat = s1; | |||||
polyvecl_ntt(&s1hat); | |||||
for (i = 0; i < K; ++i) { | |||||
polyvecl_pointwise_acc_invmontgomery(t.vec + i, mat + i, &s1hat); | |||||
poly_reduce(t.vec + i); | |||||
poly_invntt_montgomery(t.vec + i); | |||||
} | |||||
/* Add noise vector s2 */ | |||||
polyveck_add(&t, &t, &s2); | |||||
/* Extract t1 and write public key */ | |||||
polyveck_freeze(&t); | |||||
polyveck_power2round(&t1, &t0, &t); | |||||
pack_pk(pk, rho, &t1); | |||||
/* Compute CRH(rho, t1) and write secret key */ | |||||
shake256(tr, CRHBYTES, pk, CRYPTO_PUBLICKEYBYTES); | |||||
pack_sk(sk, rho, key, tr, &s1, &s2, &t0); | |||||
return 0; | |||||
unsigned int i; | |||||
unsigned char seedbuf[3 * SEEDBYTES]; | |||||
unsigned char tr[CRHBYTES]; | |||||
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, SEEDBYTES); | |||||
shake256(seedbuf, 3 * SEEDBYTES, seedbuf, SEEDBYTES); | |||||
rho = seedbuf; | |||||
rhoprime = rho + SEEDBYTES; | |||||
key = rho + 2 * SEEDBYTES; | |||||
/* Expand matrix */ | |||||
expand_mat(mat, rho); | |||||
/* Sample short vectors s1 and s2 */ | |||||
for (i = 0; i < L; ++i) | |||||
poly_uniform_eta(s1.vec + i, rhoprime, nonce++); | |||||
for (i = 0; i < K; ++i) | |||||
poly_uniform_eta(s2.vec + i, rhoprime, nonce++); | |||||
/* Matrix-vector multiplication */ | |||||
s1hat = s1; | |||||
polyvecl_ntt(&s1hat); | |||||
for (i = 0; i < K; ++i) { | |||||
polyvecl_pointwise_acc_invmontgomery(t.vec + i, mat + i, &s1hat); | |||||
poly_reduce(t.vec + i); | |||||
poly_invntt_montgomery(t.vec + i); | |||||
} | |||||
/* Add noise vector s2 */ | |||||
polyveck_add(&t, &t, &s2); | |||||
/* Extract t1 and write public key */ | |||||
polyveck_freeze(&t); | |||||
polyveck_power2round(&t1, &t0, &t); | |||||
pack_pk(pk, rho, &t1); | |||||
/* Compute CRH(rho, t1) and write secret key */ | |||||
shake256(tr, CRHBYTES, pk, CRYPTO_PUBLICKEYBYTES); | |||||
pack_sk(sk, rho, key, tr, &s1, &s2, &t0); | |||||
return 0; | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -170,108 +170,108 @@ int crypto_sign_keypair(unsigned char *pk, unsigned char *sk) { | |||||
int crypto_sign(unsigned char *sm, unsigned long long *smlen, | int crypto_sign(unsigned char *sm, unsigned long long *smlen, | ||||
const unsigned char *m, unsigned long long mlen, | const unsigned char *m, unsigned long long mlen, | ||||
const unsigned char *sk) { | const unsigned char *sk) { | ||||
unsigned long long i, j; | |||||
unsigned int n; | |||||
unsigned char | |||||
seedbuf[2 * SEEDBYTES + CRHBYTES]; // TODO: nonce in seedbuf (2x) | |||||
unsigned char tr[CRHBYTES]; | |||||
unsigned char *rho, *key, *mu; | |||||
uint16_t nonce = 0; | |||||
poly c, chat; | |||||
polyvecl mat[K], s1, y, yhat, z; | |||||
polyveck s2, t0, w, w1; | |||||
polyveck h, wcs2, wcs20, ct0, tmp; | |||||
rho = seedbuf; | |||||
key = seedbuf + SEEDBYTES; | |||||
mu = seedbuf + 2 * SEEDBYTES; | |||||
unpack_sk(rho, key, tr, &s1, &s2, &t0, sk); | |||||
/* Copy tr and message into the sm buffer, | |||||
* backwards since m and sm can be equal in SUPERCOP API */ | |||||
for (i = 1; i <= mlen; ++i) | |||||
sm[CRYPTO_BYTES + mlen - i] = m[mlen - i]; | |||||
for (i = 0; i < CRHBYTES; ++i) | |||||
sm[CRYPTO_BYTES - CRHBYTES + i] = tr[i]; | |||||
/* Compute CRH(tr, msg) */ | |||||
shake256(mu, CRHBYTES, sm + CRYPTO_BYTES - CRHBYTES, CRHBYTES + mlen); | |||||
/* Expand matrix and transform vectors */ | |||||
expand_mat(mat, rho); | |||||
polyvecl_ntt(&s1); | |||||
polyveck_ntt(&s2); | |||||
polyveck_ntt(&t0); | |||||
unsigned long long i, j; | |||||
unsigned int n; | |||||
unsigned char | |||||
seedbuf[2 * SEEDBYTES + CRHBYTES]; // TODO: nonce in seedbuf (2x) | |||||
unsigned char tr[CRHBYTES]; | |||||
unsigned char *rho, *key, *mu; | |||||
uint16_t nonce = 0; | |||||
poly c, chat; | |||||
polyvecl mat[K], s1, y, yhat, z; | |||||
polyveck s2, t0, w, w1; | |||||
polyveck h, wcs2, wcs20, ct0, tmp; | |||||
rho = seedbuf; | |||||
key = seedbuf + SEEDBYTES; | |||||
mu = seedbuf + 2 * SEEDBYTES; | |||||
unpack_sk(rho, key, tr, &s1, &s2, &t0, sk); | |||||
/* Copy tr and message into the sm buffer, | |||||
* backwards since m and sm can be equal in SUPERCOP API */ | |||||
for (i = 1; i <= mlen; ++i) | |||||
sm[CRYPTO_BYTES + mlen - i] = m[mlen - i]; | |||||
for (i = 0; i < CRHBYTES; ++i) | |||||
sm[CRYPTO_BYTES - CRHBYTES + i] = tr[i]; | |||||
/* Compute CRH(tr, msg) */ | |||||
shake256(mu, CRHBYTES, sm + CRYPTO_BYTES - CRHBYTES, CRHBYTES + mlen); | |||||
/* Expand matrix and transform vectors */ | |||||
expand_mat(mat, rho); | |||||
polyvecl_ntt(&s1); | |||||
polyveck_ntt(&s2); | |||||
polyveck_ntt(&t0); | |||||
rej: | rej: | ||||
/* Sample intermediate vector y */ | |||||
for (i = 0; i < L; ++i) | |||||
poly_uniform_gamma1m1(y.vec + i, key, nonce++); | |||||
/* Matrix-vector multiplication */ | |||||
yhat = y; | |||||
polyvecl_ntt(&yhat); | |||||
for (i = 0; i < K; ++i) { | |||||
polyvecl_pointwise_acc_invmontgomery(w.vec + i, mat + i, &yhat); | |||||
poly_reduce(w.vec + i); | |||||
poly_invntt_montgomery(w.vec + i); | |||||
} | |||||
/* Decompose w and call the random oracle */ | |||||
polyveck_csubq(&w); | |||||
polyveck_decompose(&w1, &tmp, &w); | |||||
challenge(&c, mu, &w1); | |||||
/* Compute z, reject if it reveals secret */ | |||||
chat = c; | |||||
poly_ntt(&chat); | |||||
for (i = 0; i < L; ++i) { | |||||
poly_pointwise_invmontgomery(z.vec + i, &chat, s1.vec + i); | |||||
poly_invntt_montgomery(z.vec + i); | |||||
} | |||||
polyvecl_add(&z, &z, &y); | |||||
polyvecl_freeze(&z); | |||||
if (polyvecl_chknorm(&z, GAMMA1 - BETA)) | |||||
goto rej; | |||||
/* Compute w - cs2, reject if w1 can not be computed from it */ | |||||
for (i = 0; i < K; ++i) { | |||||
poly_pointwise_invmontgomery(wcs2.vec + i, &chat, s2.vec + i); | |||||
poly_invntt_montgomery(wcs2.vec + i); | |||||
} | |||||
polyveck_sub(&wcs2, &w, &wcs2); | |||||
polyveck_freeze(&wcs2); | |||||
polyveck_decompose(&tmp, &wcs20, &wcs2); | |||||
polyveck_csubq(&wcs20); | |||||
if (polyveck_chknorm(&wcs20, GAMMA2 - BETA)) | |||||
goto rej; | |||||
for (i = 0; i < K; ++i) | |||||
for (j = 0; j < N; ++j) | |||||
if (tmp.vec[i].coeffs[j] != w1.vec[i].coeffs[j]) | |||||
/* Sample intermediate vector y */ | |||||
for (i = 0; i < L; ++i) | |||||
poly_uniform_gamma1m1(y.vec + i, key, nonce++); | |||||
/* Matrix-vector multiplication */ | |||||
yhat = y; | |||||
polyvecl_ntt(&yhat); | |||||
for (i = 0; i < K; ++i) { | |||||
polyvecl_pointwise_acc_invmontgomery(w.vec + i, mat + i, &yhat); | |||||
poly_reduce(w.vec + i); | |||||
poly_invntt_montgomery(w.vec + i); | |||||
} | |||||
/* Decompose w and call the random oracle */ | |||||
polyveck_csubq(&w); | |||||
polyveck_decompose(&w1, &tmp, &w); | |||||
challenge(&c, mu, &w1); | |||||
/* Compute z, reject if it reveals secret */ | |||||
chat = c; | |||||
poly_ntt(&chat); | |||||
for (i = 0; i < L; ++i) { | |||||
poly_pointwise_invmontgomery(z.vec + i, &chat, s1.vec + i); | |||||
poly_invntt_montgomery(z.vec + i); | |||||
} | |||||
polyvecl_add(&z, &z, &y); | |||||
polyvecl_freeze(&z); | |||||
if (polyvecl_chknorm(&z, GAMMA1 - BETA)) | |||||
goto rej; | goto rej; | ||||
/* Compute hints for w1 */ | |||||
for (i = 0; i < K; ++i) { | |||||
poly_pointwise_invmontgomery(ct0.vec + i, &chat, t0.vec + i); | |||||
poly_invntt_montgomery(ct0.vec + i); | |||||
} | |||||
/* Compute w - cs2, reject if w1 can not be computed from it */ | |||||
for (i = 0; i < K; ++i) { | |||||
poly_pointwise_invmontgomery(wcs2.vec + i, &chat, s2.vec + i); | |||||
poly_invntt_montgomery(wcs2.vec + i); | |||||
} | |||||
polyveck_sub(&wcs2, &w, &wcs2); | |||||
polyveck_freeze(&wcs2); | |||||
polyveck_decompose(&tmp, &wcs20, &wcs2); | |||||
polyveck_csubq(&wcs20); | |||||
if (polyveck_chknorm(&wcs20, GAMMA2 - BETA)) | |||||
goto rej; | |||||
polyveck_csubq(&ct0); | |||||
if (polyveck_chknorm(&ct0, GAMMA2)) | |||||
goto rej; | |||||
for (i = 0; i < K; ++i) | |||||
for (j = 0; j < N; ++j) | |||||
if (tmp.vec[i].coeffs[j] != w1.vec[i].coeffs[j]) | |||||
goto rej; | |||||
polyveck_add(&tmp, &wcs2, &ct0); | |||||
polyveck_csubq(&tmp); | |||||
n = polyveck_make_hint(&h, &wcs2, &tmp); | |||||
if (n > OMEGA) | |||||
goto rej; | |||||
/* Compute hints for w1 */ | |||||
for (i = 0; i < K; ++i) { | |||||
poly_pointwise_invmontgomery(ct0.vec + i, &chat, t0.vec + i); | |||||
poly_invntt_montgomery(ct0.vec + i); | |||||
} | |||||
/* Write signature */ | |||||
pack_sig(sm, &z, &h, &c); | |||||
polyveck_csubq(&ct0); | |||||
if (polyveck_chknorm(&ct0, GAMMA2)) | |||||
goto rej; | |||||
polyveck_add(&tmp, &wcs2, &ct0); | |||||
polyveck_csubq(&tmp); | |||||
n = polyveck_make_hint(&h, &wcs2, &tmp); | |||||
if (n > OMEGA) | |||||
goto rej; | |||||
*smlen = mlen + CRYPTO_BYTES; | |||||
return 0; | |||||
/* Write signature */ | |||||
pack_sig(sm, &z, &h, &c); | |||||
*smlen = mlen + CRYPTO_BYTES; | |||||
return 0; | |||||
} | } | ||||
/************************************************* | /************************************************* | ||||
@@ -291,70 +291,70 @@ rej: | |||||
int crypto_sign_open(unsigned char *m, unsigned long long *mlen, | int crypto_sign_open(unsigned char *m, unsigned long long *mlen, | ||||
const unsigned char *sm, unsigned long long smlen, | const unsigned char *sm, unsigned long long smlen, | ||||
const unsigned char *pk) { | const unsigned char *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 (smlen < CRYPTO_BYTES) | |||||
goto badsig; | |||||
*mlen = smlen - CRYPTO_BYTES; | |||||
unpack_pk(rho, &t1, pk); | |||||
if (unpack_sig(&z, &h, &c, sm)) | |||||
goto badsig; | |||||
if (polyvecl_chknorm(&z, GAMMA1 - BETA)) | |||||
goto badsig; | |||||
/* Compute CRH(CRH(rho, t1), msg) using m as "playground" buffer */ | |||||
if (sm != m) | |||||
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 (smlen < CRYPTO_BYTES) | |||||
goto badsig; | |||||
*mlen = smlen - CRYPTO_BYTES; | |||||
unpack_pk(rho, &t1, pk); | |||||
if (unpack_sig(&z, &h, &c, sm)) | |||||
goto badsig; | |||||
if (polyvecl_chknorm(&z, GAMMA1 - BETA)) | |||||
goto badsig; | |||||
/* Compute CRH(CRH(rho, t1), msg) using m as "playground" buffer */ | |||||
if (sm != m) | |||||
for (i = 0; i < *mlen; ++i) | |||||
m[CRYPTO_BYTES + i] = sm[CRYPTO_BYTES + i]; | |||||
shake256(m + CRYPTO_BYTES - CRHBYTES, CRHBYTES, pk, CRYPTO_PUBLICKEYBYTES); | |||||
shake256(mu, CRHBYTES, m + CRYPTO_BYTES - CRHBYTES, CRHBYTES + *mlen); | |||||
/* Matrix-vector multiplication; compute Az - c2^dt1 */ | |||||
expand_mat(mat, rho); | |||||
polyvecl_ntt(&z); | |||||
for (i = 0; i < K; ++i) | |||||
polyvecl_pointwise_acc_invmontgomery(tmp1.vec + i, mat + i, &z); | |||||
chat = c; | |||||
poly_ntt(&chat); | |||||
polyveck_shiftl(&t1, D); | |||||
polyveck_ntt(&t1); | |||||
for (i = 0; i < K; ++i) | |||||
poly_pointwise_invmontgomery(tmp2.vec + i, &chat, t1.vec + i); | |||||
polyveck_sub(&tmp1, &tmp1, &tmp2); | |||||
polyveck_reduce(&tmp1); | |||||
polyveck_invntt_montgomery(&tmp1); | |||||
/* Reconstruct w1 */ | |||||
polyveck_csubq(&tmp1); | |||||
polyveck_use_hint(&w1, &tmp1, &h); | |||||
/* Call random oracle and verify challenge */ | |||||
challenge(&cp, mu, &w1); | |||||
for (i = 0; i < N; ++i) | |||||
if (c.coeffs[i] != cp.coeffs[i]) | |||||
goto badsig; | |||||
/* All good, copy msg, return 0 */ | |||||
for (i = 0; i < *mlen; ++i) | for (i = 0; i < *mlen; ++i) | ||||
m[CRYPTO_BYTES + i] = sm[CRYPTO_BYTES + i]; | |||||
shake256(m + CRYPTO_BYTES - CRHBYTES, CRHBYTES, pk, CRYPTO_PUBLICKEYBYTES); | |||||
shake256(mu, CRHBYTES, m + CRYPTO_BYTES - CRHBYTES, CRHBYTES + *mlen); | |||||
/* Matrix-vector multiplication; compute Az - c2^dt1 */ | |||||
expand_mat(mat, rho); | |||||
polyvecl_ntt(&z); | |||||
for (i = 0; i < K; ++i) | |||||
polyvecl_pointwise_acc_invmontgomery(tmp1.vec + i, mat + i, &z); | |||||
chat = c; | |||||
poly_ntt(&chat); | |||||
polyveck_shiftl(&t1, D); | |||||
polyveck_ntt(&t1); | |||||
for (i = 0; i < K; ++i) | |||||
poly_pointwise_invmontgomery(tmp2.vec + i, &chat, t1.vec + i); | |||||
polyveck_sub(&tmp1, &tmp1, &tmp2); | |||||
polyveck_reduce(&tmp1); | |||||
polyveck_invntt_montgomery(&tmp1); | |||||
/* Reconstruct w1 */ | |||||
polyveck_csubq(&tmp1); | |||||
polyveck_use_hint(&w1, &tmp1, &h); | |||||
/* Call random oracle and verify challenge */ | |||||
challenge(&cp, mu, &w1); | |||||
for (i = 0; i < N; ++i) | |||||
if (c.coeffs[i] != cp.coeffs[i]) | |||||
goto badsig; | |||||
/* All good, copy msg, return 0 */ | |||||
for (i = 0; i < *mlen; ++i) | |||||
m[i] = sm[CRYPTO_BYTES + i]; | |||||
m[i] = sm[CRYPTO_BYTES + i]; | |||||
return 0; | |||||
return 0; | |||||
/* Signature verification failed */ | /* Signature verification failed */ | ||||
badsig: | badsig: | ||||
*mlen = (unsigned long long)-1; | |||||
for (i = 0; i < smlen; ++i) | |||||
m[i] = 0; | |||||
*mlen = (unsigned long long)-1; | |||||
for (i = 0; i < smlen; ++i) | |||||
m[i] = 0; | |||||
return -1; | |||||
return -1; | |||||
} | } |
@@ -10,86 +10,89 @@ | |||||
* make sure it is not touched by the implementations. | * make sure it is not touched by the implementations. | ||||
*/ | */ | ||||
static void write_canary(unsigned char *d) { | static void write_canary(unsigned char *d) { | ||||
*((uint64_t *)d) = 0x0123456789ABCDEF; | |||||
*((uint64_t *)d) = 0x0123456789ABCDEF; | |||||
} | } | ||||
static int check_canary(unsigned char *d) { | static int check_canary(unsigned char *d) { | ||||
if (*(uint64_t *)d != 0x0123456789ABCDEF) | |||||
return -1; | |||||
else | |||||
return 0; | |||||
if (*(uint64_t *)d != 0x0123456789ABCDEF) | |||||
return -1; | |||||
else | |||||
return 0; | |||||
} | } | ||||
static int test_sign(void) { | static int test_sign(void) { | ||||
unsigned char pk[CRYPTO_PUBLICKEYBYTES + 16]; | |||||
unsigned char sk[CRYPTO_SECRETKEYBYTES + 16]; | |||||
unsigned char sm[MLEN + CRYPTO_BYTES + 16]; | |||||
unsigned char m[MLEN + 16]; | |||||
unsigned long long mlen; | |||||
unsigned long long smlen; | |||||
int i; | |||||
write_canary(pk); | |||||
write_canary(pk + sizeof(pk) - 8); | |||||
write_canary(sk); | |||||
write_canary(sk + sizeof(sk) - 8); | |||||
write_canary(sm); | |||||
write_canary(sm + sizeof(sm) - 8); | |||||
write_canary(m); | |||||
write_canary(m + sizeof(m) - 8); | |||||
for (i = 0; i < NTESTS; i++) { | |||||
crypto_sign_keypair(pk + 8, sk + 8); | |||||
randombytes(m + 8, MLEN); | |||||
crypto_sign(sm + 8, &smlen, m + 8, MLEN, sk + 8); | |||||
// By relying on m == sm we prevent having to allocate CRYPTO_BYTES twice | |||||
if (crypto_sign_open(sm + 8, &mlen, sm + 8, smlen, pk + 8)) { | |||||
printf("ERROR Signature did not verify correctly!\n"); | |||||
} else if (check_canary(pk) || check_canary(pk + sizeof(pk) - 8) || | |||||
check_canary(sk) || check_canary(sk + sizeof(sk) - 8) || | |||||
check_canary(sm) || check_canary(sm + sizeof(sm) - 8) || | |||||
check_canary(m) || check_canary(m + sizeof(m) - 8)) { | |||||
printf("ERROR canary overwritten\n"); | |||||
unsigned char pk[CRYPTO_PUBLICKEYBYTES + 16]; | |||||
unsigned char sk[CRYPTO_SECRETKEYBYTES + 16]; | |||||
unsigned char sm[MLEN + CRYPTO_BYTES + 16]; | |||||
unsigned char m[MLEN + 16]; | |||||
unsigned long long mlen; | |||||
unsigned long long smlen; | |||||
int i; | |||||
write_canary(pk); | |||||
write_canary(pk + sizeof(pk) - 8); | |||||
write_canary(sk); | |||||
write_canary(sk + sizeof(sk) - 8); | |||||
write_canary(sm); | |||||
write_canary(sm + sizeof(sm) - 8); | |||||
write_canary(m); | |||||
write_canary(m + sizeof(m) - 8); | |||||
for (i = 0; i < NTESTS; i++) { | |||||
crypto_sign_keypair(pk + 8, sk + 8); | |||||
randombytes(m + 8, MLEN); | |||||
crypto_sign(sm + 8, &smlen, m + 8, MLEN, sk + 8); | |||||
// By relying on m == sm we prevent having to allocate CRYPTO_BYTES | |||||
// twice | |||||
if (crypto_sign_open(sm + 8, &mlen, sm + 8, smlen, pk + 8)) { | |||||
printf("ERROR Signature did not verify correctly!\n"); | |||||
} else if (check_canary(pk) || check_canary(pk + sizeof(pk) - 8) || | |||||
check_canary(sk) || check_canary(sk + sizeof(sk) - 8) || | |||||
check_canary(sm) || check_canary(sm + sizeof(sm) - 8) || | |||||
check_canary(m) || check_canary(m + sizeof(m) - 8)) { | |||||
printf("ERROR canary overwritten\n"); | |||||
} | |||||
} | } | ||||
} | |||||
return 0; | |||||
return 0; | |||||
} | } | ||||
static int test_wrong_pk(void) { | static int test_wrong_pk(void) { | ||||
unsigned char pk[CRYPTO_PUBLICKEYBYTES]; | |||||
unsigned char pk2[CRYPTO_PUBLICKEYBYTES]; | |||||
unsigned char sk[CRYPTO_SECRETKEYBYTES]; | |||||
unsigned char sm[MLEN + CRYPTO_BYTES]; | |||||
unsigned char m[MLEN]; | |||||
unsigned char pk[CRYPTO_PUBLICKEYBYTES]; | |||||
unsigned char pk2[CRYPTO_PUBLICKEYBYTES]; | |||||
unsigned char sk[CRYPTO_SECRETKEYBYTES]; | |||||
unsigned char sm[MLEN + CRYPTO_BYTES]; | |||||
unsigned char m[MLEN]; | |||||
unsigned long long mlen; | |||||
unsigned long long smlen; | |||||
unsigned long long mlen; | |||||
unsigned long long smlen; | |||||
int i; | |||||
int i; | |||||
for (i = 0; i < NTESTS; i++) { | |||||
crypto_sign_keypair(pk2, sk); | |||||
for (i = 0; i < NTESTS; i++) { | |||||
crypto_sign_keypair(pk2, sk); | |||||
crypto_sign_keypair(pk, sk); | |||||
crypto_sign_keypair(pk, sk); | |||||
randombytes(m, MLEN); | |||||
crypto_sign(sm, &smlen, m, MLEN, sk); | |||||
randombytes(m, MLEN); | |||||
crypto_sign(sm, &smlen, m, MLEN, sk); | |||||
// By relying on m == sm we prevent having to allocate CRYPTO_BYTES twice | |||||
if (!crypto_sign_open(sm, &mlen, sm, smlen, pk2)) { | |||||
printf("ERROR Signature did verify correctly under wrong public key!\n"); | |||||
// By relying on m == sm we prevent having to allocate CRYPTO_BYTES | |||||
// twice | |||||
if (!crypto_sign_open(sm, &mlen, sm, smlen, pk2)) { | |||||
printf("ERROR Signature did verify correctly under wrong public " | |||||
"key!\n"); | |||||
} | |||||
} | } | ||||
} | |||||
return 0; | |||||
return 0; | |||||
} | } | ||||
int main(void) { | int main(void) { | ||||
test_sign(); | |||||
test_wrong_pk(); | |||||
test_sign(); | |||||
test_wrong_pk(); | |||||
return 0; | |||||
return 0; | |||||
} | } |