1
1
mirror of https://github.com/henrydcase/pqc.git synced 2024-11-22 15:39:07 +00:00

update implementations to leda v2.1

This commit is contained in:
Leon Botros 2019-08-21 14:28:31 +02:00
parent 9a5caaa95b
commit ca898f01bc
46 changed files with 1207 additions and 825 deletions

View File

@ -3,10 +3,10 @@ type: kem
claimed-nist-level: 1
claimed-security: IND-CCA2
length-public-key: 6520
length-secret-key: 26
length-ciphertext: 6520
length-secret-key: 50
length-ciphertext: 6544
length-shared-secret: 32
nistkat-sha256: c49a3f0ff5f3e7d6b41995649d7003daf7c06d9539fc28cb3b93ed02dcbe09d4
nistkat-sha256: c0bd75093e2bbae8bf5717939c59c3c695ee9a60d765fcf6fb06d8db385b04c7
principal-submitters:
- Marco Baldi
auxiliary-submitters:
@ -16,4 +16,4 @@ auxiliary-submitters:
- Paolo Santini
implementations:
- name: leaktime
version: 2.?
version: 2.1

View File

@ -1,32 +1,58 @@
#include "H_Q_matrices_generation.h"
#include "gf2x_arith_mod_xPplusOne.h"
void PQCLEAN_LEDAKEMLT12_LEAKTIME_generateHPosOnes_HtrPosOnes(
POSITION_T HPosOnes[N0][DV],
POSITION_T HtrPosOnes[N0][DV],
void PQCLEAN_LEDAKEMLT12_LEAKTIME_generateHPosOnes(POSITION_T HPosOnes[N0][DV],
AES_XOF_struct *keys_expander) {
for (int i = 0; i < N0; i++) {
/* Generate a random block of Htr */
PQCLEAN_LEDAKEMLT12_LEAKTIME_rand_circulant_sparse_block(&HtrPosOnes[i][0], DV, keys_expander);
}
for (int i = 0; i < N0; i++) {
/* Obtain directly the sparse representation of the block of H */
for (int k = 0; k < DV; k++) {
HPosOnes[i][k] = (P - HtrPosOnes[i][k]) % P; /* transposes indexes */
}
PQCLEAN_LEDAKEMLT12_LEAKTIME_rand_circulant_sparse_block(&HPosOnes[i][0],
DV,
keys_expander);
}
}
void PQCLEAN_LEDAKEMLT12_LEAKTIME_generateQsparse(
POSITION_T pos_ones[N0][M],
void PQCLEAN_LEDAKEMLT12_LEAKTIME_generateQPosOnes(POSITION_T QPosOnes[N0][M],
AES_XOF_struct *keys_expander) {
for (int i = 0; i < N0; i++) {
int placed_ones = 0;
for (int j = 0; j < N0; j++) {
PQCLEAN_LEDAKEMLT12_LEAKTIME_rand_circulant_sparse_block(&pos_ones[i][placed_ones],
PQCLEAN_LEDAKEMLT12_LEAKTIME_rand_circulant_sparse_block(&QPosOnes[i][placed_ones],
qBlockWeights[i][j],
keys_expander);
placed_ones += qBlockWeights[i][j];
}
}
}
void PQCLEAN_LEDAKEMLT12_LEAKTIME_transposeHPosOnes(POSITION_T HtrPosOnes[N0][DV], /* output*/
POSITION_T HPosOnes[N0][DV]) {
for (int i = 0; i < N0; i++) {
/* Obtain directly the sparse representation of the block of H */
for (int k = 0; k < DV; k++) {
HtrPosOnes[i][k] = (P - HPosOnes[i][k]) % P; /* transposes indexes */
}// end for k
}
}
void PQCLEAN_LEDAKEMLT12_LEAKTIME_transposeQPosOnes(POSITION_T QtrPosOnes[N0][M], /* output*/
POSITION_T QPosOnes[N0][M]) {
unsigned transposed_ones_idx[N0] = {0x00};
for (unsigned source_row_idx = 0; source_row_idx < N0 ; source_row_idx++) {
int currQoneIdx = 0; // position in the column of QtrPosOnes[][...]
int endQblockIdx = 0;
for (int blockIdx = 0; blockIdx < N0; blockIdx++) {
endQblockIdx += qBlockWeights[source_row_idx][blockIdx];
for (; currQoneIdx < endQblockIdx; currQoneIdx++) {
QtrPosOnes[blockIdx][transposed_ones_idx[blockIdx]] = (P -
QPosOnes[source_row_idx][currQoneIdx]) % P;
transposed_ones_idx[blockIdx]++;
}
}
}
}

View File

@ -5,7 +5,9 @@
#include "qc_ldpc_parameters.h"
#include "rng.h"
void PQCLEAN_LEDAKEMLT12_LEAKTIME_generateHPosOnes_HtrPosOnes(POSITION_T HPosOnes[N0][DV], POSITION_T HtrPosOnes[N0][DV], AES_XOF_struct *niederreiter_keys_expander);
void PQCLEAN_LEDAKEMLT12_LEAKTIME_generateQsparse(POSITION_T pos_ones[N0][M], AES_XOF_struct *niederreiter_keys_expander);
void PQCLEAN_LEDAKEMLT12_LEAKTIME_generateHPosOnes(POSITION_T HPosOnes[N0][DV], AES_XOF_struct *keys_expander);
void PQCLEAN_LEDAKEMLT12_LEAKTIME_generateQPosOnes(POSITION_T QPosOnes[N0][M], AES_XOF_struct *keys_expander);
void PQCLEAN_LEDAKEMLT12_LEAKTIME_transposeHPosOnes(POSITION_T HtrPosOnes[N0][DV], POSITION_T HPosOnes[N0][DV]);
void PQCLEAN_LEDAKEMLT12_LEAKTIME_transposeQPosOnes(POSITION_T QtrPosOnes[N0][M], POSITION_T QPosOnes[N0][M]);
#endif

View File

@ -3,10 +3,10 @@
LIB=libledakemlt12_leaktime.a
HEADERS=api.h bf_decoding.h dfr_test.h gf2x_arith_mod_xPplusOne.h \
gf2x_arith.h H_Q_matrices_generation.h \
niederreiter.h qc_ldpc_parameters.h rng.h
niederreiter.h qc_ldpc_parameters.h rng.h sort.h
OBJECTS=bf_decoding.o dfr_test.o gf2x_arith_mod_xPplusOne.o \
gf2x_arith.o H_Q_matrices_generation.o kem.o niederreiter.o rng.o
gf2x_arith.o H_Q_matrices_generation.o kem.o niederreiter.o rng.o sort.o
CFLAGS=-O3 -Wall -Werror -Wextra -Wvla -Wpedantic -Wmissing-prototypes -std=c99 \
-I../../../common $(EXTRAFLAGS)

View File

@ -2,7 +2,7 @@
# nmake /f Makefile.Microsoft_nmake
LIBRARY=libledakemlt12_leaktime.lib
OBJECTS=bf_decoding.obj dfr_test.obj gf2x_arith_mod_xPplusOne.obj gf2x_arith.obj H_Q_matrices_generation.obj kem.obj niederreiter.obj rng.obj
OBJECTS=bf_decoding.obj dfr_test.obj gf2x_arith_mod_xPplusOne.obj gf2x_arith.obj H_Q_matrices_generation.obj kem.obj niederreiter.obj rng.obj sort.obj
CFLAGS=/nologo /I ..\..\..\common /W4 /WX

View File

@ -3,9 +3,9 @@
#include <stdint.h>
#define PQCLEAN_LEDAKEMLT12_LEAKTIME_CRYPTO_SECRETKEYBYTES 26
#define PQCLEAN_LEDAKEMLT12_LEAKTIME_CRYPTO_SECRETKEYBYTES 50
#define PQCLEAN_LEDAKEMLT12_LEAKTIME_CRYPTO_PUBLICKEYBYTES 6520
#define PQCLEAN_LEDAKEMLT12_LEAKTIME_CRYPTO_CIPHERTEXTBYTES 6520
#define PQCLEAN_LEDAKEMLT12_LEAKTIME_CRYPTO_CIPHERTEXTBYTES 6544
#define PQCLEAN_LEDAKEMLT12_LEAKTIME_CRYPTO_BYTES 32
#define PQCLEAN_LEDAKEMLT12_LEAKTIME_CRYPTO_ALGNAME "LEDAKEMLT12"

View File

@ -2,70 +2,45 @@
#include "dfr_test.h"
#include "gf2x_arith_mod_xPplusOne.h"
#include "qc_ldpc_parameters.h"
#include "sort.h"
#include <string.h>
/* Tests if the current code attains the desired DFR. If that is the case,
* computes the threshold for the second iteration of the decoder and returns this values
* (max DV * M), on failure it returns 255 >> DV * M */
uint8_t PQCLEAN_LEDAKEMLT12_LEAKTIME_DFR_test(POSITION_T LSparse[N0][DV * M]) {
int PQCLEAN_LEDAKEMLT12_LEAKTIME_DFR_test(POSITION_T LSparse[N0][DV * M], uint8_t *secondIterThreshold) {
POSITION_T LSparse_loc[N0][DV * M];
POSITION_T rotated_column[DV * M];
/* Gamma matrix: an N0 x N0 block circulant matrix with block size p
* gamma[a][b][c] stores the intersection of the first column of the a-th
* block of L with the c-th column of the b-th block of L.
* Gamma computation can be accelerated employing symmetry and QC properties */
unsigned int gamma[N0][N0][P] = {{{0}}};
POSITION_T LSparse_loc[N0][DV * M]; /* vector of N_0 sparse blocks */
int gamma[N0][N0][P] = {{{0}}};
int maxMut[N0], maxMutMinusOne[N0];
int allBlockMaxSumst, allBlockMaxSumstMinusOne;
unsigned int gammaHist[N0][DV * M + 1] = {{0}};
unsigned int maxMut[N0], maxMutMinusOne[N0];
unsigned int firstidx, secondidx, intersectionval;
unsigned int allBlockMaxSumst, allBlockMaxSumstMinusOne;
unsigned int toAdd, histIdx;
/*transpose blocks of L, we need its columns */
for (int i = 0; i < N0; i++) {
for (int j = 0; j < DV * M; j++) {
if (LSparse[i][j] != 0) {
LSparse_loc[i][j] = (P - LSparse[i][j]) ;
}
}
PQCLEAN_LEDAKEMLT12_LEAKTIME_quicksort_sparse(LSparse_loc[i]);
PQCLEAN_LEDAKEMLT12_LEAKTIME_uint32_sort(LSparse_loc[i], DV * M);
}
for (int i = 0; i < N0; i++ ) {
for (int j = 0; j < N0; j++ ) {
for (int k = 0; k < P; k++) {
/* compute the rotated sparse column needed */
for (int idxToRotate = 0; idxToRotate < (DV * M); idxToRotate++) {
rotated_column[idxToRotate] = (LSparse_loc[j][idxToRotate] + k) % P;
}
PQCLEAN_LEDAKEMLT12_LEAKTIME_quicksort_sparse(rotated_column);
/* compute the intersection amount */
firstidx = 0, secondidx = 0;
intersectionval = 0;
while ( (firstidx < DV * M) && (secondidx < DV * M) ) {
if ( LSparse_loc[i][firstidx] == rotated_column[secondidx] ) {
intersectionval++;
firstidx++;
secondidx++;
} else if ( LSparse_loc[i][firstidx] > rotated_column[secondidx] ) {
secondidx++;
} else { /*if ( LSparse_loc[i][firstidx] < rotated_column[secondidx] ) */
firstidx++;
for (int k = 0; k < (DV * M); k++) {
for (int l = 0; l < (DV * M); l++) {
gamma[i][j][ (P + LSparse_loc[i][k] - LSparse_loc[j][l]) % P ]++;
}
}
}
}
gamma[i][j][k] = intersectionval;
}
}
}
for (int i = 0; i < N0; i++ ) {
for (int j = 0; j < N0; j++ ) {
gamma[i][j][0] = 0;
}
}
/* build histogram of values in gamma */
for (int i = 0; i < N0; i++ ) {
for (int j = 0; j < N0; j++ ) {
@ -77,9 +52,9 @@ uint8_t PQCLEAN_LEDAKEMLT12_LEAKTIME_DFR_test(POSITION_T LSparse[N0][DV * M]) {
for (int gammaBlockRowIdx = 0; gammaBlockRowIdx < N0; gammaBlockRowIdx++) {
toAdd = T_BAR - 1;
unsigned int toAdd = T_BAR - 1;
maxMutMinusOne[gammaBlockRowIdx] = 0;
histIdx = DV * M;
unsigned int histIdx = DV * M;
while ( (histIdx > 0) && (toAdd > 0)) {
if (gammaHist[gammaBlockRowIdx][histIdx] > toAdd ) {
maxMutMinusOne[gammaBlockRowIdx] += histIdx * toAdd;
@ -93,7 +68,6 @@ uint8_t PQCLEAN_LEDAKEMLT12_LEAKTIME_DFR_test(POSITION_T LSparse[N0][DV * M]) {
maxMut[gammaBlockRowIdx] = histIdx + maxMutMinusOne[gammaBlockRowIdx];
}
/*seek max values across all gamma blocks */
allBlockMaxSumst = maxMut[0];
allBlockMaxSumstMinusOne = maxMutMinusOne[0];
@ -106,7 +80,8 @@ uint8_t PQCLEAN_LEDAKEMLT12_LEAKTIME_DFR_test(POSITION_T LSparse[N0][DV * M]) {
allBlockMaxSumstMinusOne;
}
if (DV * M > (allBlockMaxSumstMinusOne + allBlockMaxSumst)) {
return (uint8_t) allBlockMaxSumst + 1;
*secondIterThreshold = allBlockMaxSumst + 1;
return 1;
}
return DFR_TEST_FAIL;
return 0;
}

View File

@ -1,8 +1,6 @@
#ifndef DFR_TEST_H
#define DFR_TEST_H
#define DFR_TEST_FAIL (255)
uint8_t PQCLEAN_LEDAKEMLT12_LEAKTIME_DFR_test(POSITION_T LSparse[N0][DV * M]);
int PQCLEAN_LEDAKEMLT12_LEAKTIME_DFR_test(POSITION_T LSparse[N0][DV * M], uint8_t *secondIterThreshold);
#endif

View File

@ -1,5 +1,6 @@
#include "gf2x_arith_mod_xPplusOne.h"
#include "rng.h"
#include "sort.h"
#include <string.h> // memcpy(...), memset(...)
@ -62,81 +63,15 @@ void PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_mod_add(DIGIT Res[], const DIGIT A[], con
PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_add(Res, A, B, NUM_DIGITS_GF2X_ELEMENT);
}
static int partition(POSITION_T arr[], int lo, int hi) {
POSITION_T x = arr[hi];
POSITION_T tmp;
int i = (lo - 1);
for (int j = lo; j <= hi - 1; j++) {
if (arr[j] <= x) {
i++;
tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}
tmp = arr[i + 1];
arr[i + 1] = arr[hi];
arr[hi] = tmp;
return i + 1;
}
void PQCLEAN_LEDAKEMLT12_LEAKTIME_quicksort_sparse(POSITION_T Res[]) {
int stack[DV * M];
int hi, lo, pivot, tos = -1;
stack[++tos] = 0;
stack[++tos] = (DV * M) - 1;
while (tos >= 0 ) {
hi = stack[tos--];
lo = stack[tos--];
pivot = partition(Res, lo, hi);
if ( (pivot - 1) > lo) {
stack[++tos] = lo;
stack[++tos] = pivot - 1;
}
if ( (pivot + 1) < hi) {
stack[++tos] = pivot + 1;
stack[++tos] = hi;
}
}
}
static void gf2x_mod(DIGIT out[], const DIGIT in[]) {
DIGIT aux[NUM_DIGITS_GF2X_ELEMENT + 1];
int i, j, posTrailingBit, maskOffset;
DIGIT mask, aux[2 * NUM_DIGITS_GF2X_ELEMENT];
memcpy(aux, in, 2 * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B);
memset(out, 0x00, NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B);
for (i = 0; i < (2 * NUM_DIGITS_GF2X_ELEMENT) - NUM_DIGITS_GF2X_MODULUS; i += 1) {
for (j = DIGIT_SIZE_b - 1; j >= 0; j--) {
mask = ((DIGIT)0x1) << j;
if (aux[i] & mask) {
aux[i] ^= mask;
posTrailingBit = (DIGIT_SIZE_b - 1 - j) + i * DIGIT_SIZE_b + P;
maskOffset = (DIGIT_SIZE_b - 1 - (posTrailingBit % DIGIT_SIZE_b));
mask = (DIGIT) 0x1 << maskOffset;
aux[posTrailingBit / DIGIT_SIZE_b] ^= mask;
}
}
}
for (j = DIGIT_SIZE_b - 1; j >= MSb_POSITION_IN_MSB_DIGIT_OF_MODULUS; j--) {
mask = ((DIGIT)0x1) << j;
if (aux[i] & mask) {
aux[i] ^= mask;
posTrailingBit = (DIGIT_SIZE_b - 1 - j) + i * DIGIT_SIZE_b + P;
maskOffset = (DIGIT_SIZE_b - 1 - (posTrailingBit % DIGIT_SIZE_b));
mask = (DIGIT) 0x1 << maskOffset;
aux[posTrailingBit / DIGIT_SIZE_b] ^= mask;
}
}
for (i = 0; i < NUM_DIGITS_GF2X_ELEMENT; i++) {
out[NUM_DIGITS_GF2X_ELEMENT - 1 - i] = aux[2 * NUM_DIGITS_GF2X_ELEMENT - 1 - i];
}
memcpy(aux, in, (NUM_DIGITS_GF2X_ELEMENT + 1)*DIGIT_SIZE_B);
PQCLEAN_LEDAKEMLT12_LEAKTIME_right_bit_shift_n(NUM_DIGITS_GF2X_ELEMENT + 1, aux,
MSb_POSITION_IN_MSB_DIGIT_OF_MODULUS);
PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_add(out, aux + 1, in + NUM_DIGITS_GF2X_ELEMENT,
NUM_DIGITS_GF2X_ELEMENT);
out[0] &= ((DIGIT)1 << MSb_POSITION_IN_MSB_DIGIT_OF_MODULUS) - 1;
}
static void left_bit_shift(const int length, DIGIT in[]) {
@ -333,16 +268,13 @@ void PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_mod_mul(DIGIT Res[], const DIGIT A[], con
/*PRE: the representation of the sparse coefficients is sorted in increasing
order of the coefficients themselves */
void PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_mod_mul_dense_to_sparse(
DIGIT Res[],
const DIGIT dense[],
void PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_mod_mul_dense_to_sparse(DIGIT Res[], const DIGIT dense[],
POSITION_T sparse[], unsigned int nPos) {
DIGIT aux[2 * NUM_DIGITS_GF2X_ELEMENT] = {0x00};
DIGIT resDouble[2 * NUM_DIGITS_GF2X_ELEMENT] = {0x00};
memcpy(aux + NUM_DIGITS_GF2X_ELEMENT, dense, NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B);
memcpy(resDouble + NUM_DIGITS_GF2X_ELEMENT, dense,
NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B);
memcpy(resDouble + NUM_DIGITS_GF2X_ELEMENT, dense, NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B);
if (sparse[0] != INVALID_POS_VALUE) {
left_bit_shift_wide_n(2 * NUM_DIGITS_GF2X_ELEMENT, resDouble, sparse[0]);
@ -382,15 +314,15 @@ void PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_transpose_in_place_sparse(int sizeA, POSI
}
void PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_mod_mul_sparse(size_t sizeR, POSITION_T Res[],
size_t sizeA, const POSITION_T A[],
size_t sizeB, const POSITION_T B[]) {
void PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_mod_mul_sparse(int sizeR, POSITION_T Res[],
int sizeA, const POSITION_T A[],
int sizeB, const POSITION_T B[]) {
/* compute all the coefficients, filling invalid positions with P*/
size_t lastFilledPos = 0;
for (size_t i = 0 ; i < sizeA ; i++) {
for (size_t j = 0 ; j < sizeB ; j++) {
uint32_t prod = A[i] + B[j];
int lastFilledPos = 0;
for (int i = 0 ; i < sizeA ; i++) {
for (int j = 0 ; j < sizeB ; j++) {
uint32_t prod = ((uint32_t) A[i]) + ((uint32_t) B[j]);
prod = ( (prod >= P) ? prod - P : prod);
if ((A[i] != INVALID_POS_VALUE) &&
(B[j] != INVALID_POS_VALUE)) {
@ -405,12 +337,12 @@ void PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_mod_mul_sparse(size_t sizeR, POSITION_T R
Res[lastFilledPos] = INVALID_POS_VALUE;
lastFilledPos++;
}
PQCLEAN_LEDAKEMLT12_LEAKTIME_quicksort_sparse(Res);
PQCLEAN_LEDAKEMLT12_LEAKTIME_uint32_sort(Res, sizeR);
/* eliminate duplicates */
POSITION_T lastReadPos = Res[0];
int duplicateCount;
size_t write_idx = 0;
size_t read_idx = 0;
int write_idx = 0;
int read_idx = 0;
while (read_idx < sizeR && Res[read_idx] != INVALID_POS_VALUE) {
lastReadPos = Res[read_idx];
read_idx++;
@ -531,8 +463,7 @@ void PQCLEAN_LEDAKEMLT12_LEAKTIME_rand_circulant_sparse_block(POSITION_T *pos_on
}
/* Returns random weight-t circulant block */
void PQCLEAN_LEDAKEMLT12_LEAKTIME_rand_circulant_blocks_sequence(
DIGIT sequence[N0 * NUM_DIGITS_GF2X_ELEMENT],
void PQCLEAN_LEDAKEMLT12_LEAKTIME_rand_circulant_blocks_sequence(DIGIT sequence[N0 * NUM_DIGITS_GF2X_ELEMENT],
AES_XOF_struct *seed_expander_ctx) {
int rndPos[NUM_ERRORS_T], duplicated, counter = 0;
@ -563,6 +494,39 @@ void PQCLEAN_LEDAKEMLT12_LEAKTIME_rand_circulant_blocks_sequence(
}
void PQCLEAN_LEDAKEMLT12_LEAKTIME_rand_error_pos(POSITION_T errorPos[NUM_ERRORS_T],
AES_XOF_struct *seed_expander_ctx) {
int duplicated, counter = 0;
while (counter < NUM_ERRORS_T) {
uint32_t p = rand_range(N0 * NUM_BITS_GF2X_ELEMENT, P_BITS, seed_expander_ctx);
duplicated = 0;
for (int j = 0; j < counter; j++) if (errorPos[j] == p) {
duplicated = 1;
}
if (duplicated == 0) {
errorPos[counter] = p;
counter++;
}
}
}
void PQCLEAN_LEDAKEMLT12_LEAKTIME_expand_error(DIGIT sequence[N0 * NUM_DIGITS_GF2X_ELEMENT],
POSITION_T errorPos[NUM_ERRORS_T]) {
memset(sequence, 0x00, N0 * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B);
for (int j = 0; j < NUM_ERRORS_T; j++) {
int polyIndex = errorPos[j] / P;
int exponent = errorPos[j] % P;
PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_set_coeff( sequence + NUM_DIGITS_GF2X_ELEMENT * polyIndex, exponent,
( (DIGIT) 1));
}
}
void PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_tobytes(uint8_t *bytes, const DIGIT *poly) {
size_t i, j;
for (i = 0; i < NUM_DIGITS_GF2X_ELEMENT; i++) {

View File

@ -21,15 +21,16 @@ void PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_set_coeff(DIGIT poly[], unsigned int expo
void PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_toggle_coeff(DIGIT poly[], unsigned int exponent);
int PQCLEAN_LEDAKEMLT12_LEAKTIME_population_count(DIGIT *poly);
void PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_mod_add(DIGIT Res[], const DIGIT A[], const DIGIT B[]);
void PQCLEAN_LEDAKEMLT12_LEAKTIME_quicksort_sparse(POSITION_T Res[]);
void PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_mod_mul(DIGIT Res[], const DIGIT A[], const DIGIT B[]);
void PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_transpose_in_place(DIGIT A[]);
void PQCLEAN_LEDAKEMLT12_LEAKTIME_rand_circulant_sparse_block(POSITION_T *pos_ones, int countOnes, AES_XOF_struct *seed_expander_ctx);
void PQCLEAN_LEDAKEMLT12_LEAKTIME_rand_circulant_blocks_sequence(DIGIT *sequence, AES_XOF_struct *seed_expander_ctx);
void PQCLEAN_LEDAKEMLT12_LEAKTIME_rand_error_pos(POSITION_T errorPos[NUM_ERRORS_T], AES_XOF_struct *seed_expander_ctx);
void PQCLEAN_LEDAKEMLT12_LEAKTIME_expand_error(DIGIT sequence[N0 * NUM_DIGITS_GF2X_ELEMENT], POSITION_T errorPos[NUM_ERRORS_T]);
void PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_mod_add_sparse(int sizeR, POSITION_T Res[], int sizeA, const POSITION_T A[], int sizeB, const POSITION_T B[]);
void PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_transpose_in_place_sparse(int sizeA, POSITION_T A[]);
int PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_mod_inverse(DIGIT out[], const DIGIT in[]);
void PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_mod_mul_sparse(size_t sizeR, POSITION_T Res[], size_t sizeA, const POSITION_T A[], size_t sizeB, const POSITION_T B[]);
void PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_mod_mul_sparse(int sizeR, POSITION_T Res[], int sizeA, const POSITION_T A[], int sizeB, const POSITION_T B[]);
void PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_mod_mul_dense_to_sparse(DIGIT Res[], const DIGIT dense[], POSITION_T sparse[], unsigned int nPos);
void PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_tobytes(uint8_t *bytes, const DIGIT *poly);
void PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_frombytes(DIGIT *poly, const uint8_t *poly_bytes);

View File

@ -5,6 +5,7 @@
#include <string.h>
/*
static void pack_pk(uint8_t *pk_bytes, publicKeyNiederreiter_t *pk) {
size_t i;
for (i = 0; i < N0 - 1; i++) {
@ -36,57 +37,113 @@ static void pack_error(uint8_t *error_bytes, DIGIT *error_digits) {
error_digits + i * NUM_DIGITS_GF2X_ELEMENT);
}
}
*/
/* Generates a keypair - pk is the public key and sk is the secret key. */
int PQCLEAN_LEDAKEMLT12_LEAKTIME_crypto_kem_keypair(unsigned char *pk, unsigned char *sk) {
AES_XOF_struct niederreiter_keys_expander;
publicKeyNiederreiter_t pk_nie;
/* IND-CCA2 Keygen */
int PQCLEAN_LEDAKEMLT12_LEAKTIME_crypto_kem_keypair(uint8_t *pk, uint8_t *sk) {
randombytes(((privateKeyNiederreiter_t *)sk)->prng_seed, TRNG_BYTE_LENGTH);
PQCLEAN_LEDAKEMLT12_LEAKTIME_seedexpander_from_trng(&niederreiter_keys_expander, ((privateKeyNiederreiter_t *)sk)->prng_seed);
PQCLEAN_LEDAKEMLT12_LEAKTIME_niederreiter_keygen(&pk_nie, (privateKeyNiederreiter_t *) sk, &niederreiter_keys_expander);
pack_pk(pk, &pk_nie);
PQCLEAN_LEDAKEMLT12_LEAKTIME_niederreiter_keygen((publicKeyNiederreiter_t *) pk,
(privateKeyNiederreiter_t *) sk);
return 0;
}
/* Encrypt - pk is the public key, ct is a key encapsulation message
(ciphertext), ss is the shared secret.*/
int PQCLEAN_LEDAKEMLT12_LEAKTIME_crypto_kem_enc(unsigned char *ct, unsigned char *ss, const unsigned char *pk) {
AES_XOF_struct niederreiter_encap_key_expander;
unsigned char encapsulated_key_seed[TRNG_BYTE_LENGTH];
/* IND-CCA2 Encapsulation */
int PQCLEAN_LEDAKEMLT12_LEAKTIME_crypto_kem_enc(uint8_t *ct, uint8_t *ss, const uint8_t *pk) {
AES_XOF_struct hashedAndTruncatedSeed_expander;
POSITION_T errorPos[NUM_ERRORS_T];
DIGIT error_vector[N0 * NUM_DIGITS_GF2X_ELEMENT];
uint8_t error_bytes[N0 * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B];
DIGIT syndrome[NUM_DIGITS_GF2X_ELEMENT];
publicKeyNiederreiter_t pk_nie;
uint8_t seed[TRNG_BYTE_LENGTH];
uint8_t ss_input[2 * TRNG_BYTE_LENGTH] = {0};
uint8_t hashedSeed[HASH_BYTE_LENGTH];
uint8_t hashedAndTruncatedSeed[TRNG_BYTE_LENGTH] = {0};
uint8_t hashedErrorVector[HASH_BYTE_LENGTH];
uint8_t hashedAndTruncatedErrorVector[TRNG_BYTE_LENGTH] = {0};
uint8_t maskedSeed[TRNG_BYTE_LENGTH];
randombytes(encapsulated_key_seed, TRNG_BYTE_LENGTH);
unpack_pk(&pk_nie, pk);
randombytes(seed, TRNG_BYTE_LENGTH);
memcpy(ss_input, seed, TRNG_BYTE_LENGTH);
HASH_FUNCTION(ss, ss_input, 2 * TRNG_BYTE_LENGTH);
HASH_FUNCTION(hashedSeed, seed, TRNG_BYTE_LENGTH);
PQCLEAN_LEDAKEMLT12_LEAKTIME_seedexpander_from_trng(&niederreiter_encap_key_expander, encapsulated_key_seed);
PQCLEAN_LEDAKEMLT12_LEAKTIME_rand_circulant_blocks_sequence(error_vector, &niederreiter_encap_key_expander);
pack_error(error_bytes, error_vector);
HASH_FUNCTION(ss, error_bytes, (N0 * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B));
PQCLEAN_LEDAKEMLT12_LEAKTIME_niederreiter_encrypt(syndrome, &pk_nie, error_vector);
memcpy(hashedAndTruncatedSeed, hashedSeed, TRNG_BYTE_LENGTH);
pack_ct(ct, syndrome);
memset(&hashedAndTruncatedSeed_expander, 0x00, sizeof(AES_XOF_struct));
PQCLEAN_LEDAKEMLT12_LEAKTIME_seedexpander_from_trng(&hashedAndTruncatedSeed_expander, hashedAndTruncatedSeed);
PQCLEAN_LEDAKEMLT12_LEAKTIME_rand_error_pos(errorPos, &hashedAndTruncatedSeed_expander);
PQCLEAN_LEDAKEMLT12_LEAKTIME_expand_error(error_vector, errorPos);
HASH_FUNCTION(hashedErrorVector, (const uint8_t *) error_vector, (N0 * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B));
memcpy(hashedAndTruncatedErrorVector, hashedErrorVector, TRNG_BYTE_LENGTH);
for (int i = 0; i < TRNG_BYTE_LENGTH; ++i) {
maskedSeed[i] = seed[i] ^ hashedAndTruncatedErrorVector[i];
}
PQCLEAN_LEDAKEMLT12_LEAKTIME_niederreiter_encrypt((DIGIT *) ct, (const publicKeyNiederreiter_t *)pk, error_vector);
memcpy(ct + (NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B), maskedSeed, TRNG_BYTE_LENGTH);
return 0;
}
/* Decrypt - ct is a key encapsulation message (ciphertext), sk is the private
key, ss is the shared secret */
int PQCLEAN_LEDAKEMLT12_LEAKTIME_crypto_kem_dec(unsigned char *ss, const unsigned char *ct, const unsigned char *sk) {
/* INDCCA2 Decapsulation */
int PQCLEAN_LEDAKEMLT12_LEAKTIME_crypto_kem_dec(uint8_t *ss, const uint8_t *ct, const uint8_t *sk) {
AES_XOF_struct hashedAndTruncatedSeed_expander;
POSITION_T reconstructed_errorPos[NUM_ERRORS_T];
DIGIT reconstructed_error_vector[N0 * NUM_DIGITS_GF2X_ELEMENT];
DIGIT decoded_error_vector[N0 * NUM_DIGITS_GF2X_ELEMENT];
uint8_t decoded_error_bytes[N0 * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B];
DIGIT syndrome[NUM_DIGITS_GF2X_ELEMENT];
uint8_t hashedErrorVector[HASH_BYTE_LENGTH];
uint8_t hashedAndTruncatedErrorVector[TRNG_BYTE_LENGTH] = {0};
uint8_t decoded_seed[TRNG_BYTE_LENGTH];
uint8_t hashed_decoded_seed[HASH_BYTE_LENGTH];
uint8_t hashedAndTruncated_decoded_seed[TRNG_BYTE_LENGTH] = {0};
uint8_t ss_input[2 * TRNG_BYTE_LENGTH], tail[TRNG_BYTE_LENGTH] = {0};
unpack_ct(syndrome, ct);
PQCLEAN_LEDAKEMLT12_LEAKTIME_niederreiter_decrypt(decoded_error_vector, (privateKeyNiederreiter_t *)sk, syndrome);
pack_error(decoded_error_bytes, decoded_error_vector);
HASH_FUNCTION(ss, decoded_error_bytes, (N0 * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B));
int decode_ok = PQCLEAN_LEDAKEMLT12_LEAKTIME_niederreiter_decrypt(decoded_error_vector,
(const privateKeyNiederreiter_t *)sk,
(DIGIT *)ct);
HASH_FUNCTION(hashedErrorVector,
(const uint8_t *) decoded_error_vector,
(N0 * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B));
memcpy(hashedAndTruncatedErrorVector, hashedErrorVector, TRNG_BYTE_LENGTH);
for (int i = 0; i < TRNG_BYTE_LENGTH; ++i) {
decoded_seed[i] = ct[(NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B) + i] ^
hashedAndTruncatedErrorVector[i];
}
HASH_FUNCTION(hashed_decoded_seed, decoded_seed, TRNG_BYTE_LENGTH);
memcpy(hashedAndTruncated_decoded_seed, hashed_decoded_seed, TRNG_BYTE_LENGTH);
memset(&hashedAndTruncatedSeed_expander, 0x00, sizeof(AES_XOF_struct));
PQCLEAN_LEDAKEMLT12_LEAKTIME_seedexpander_from_trng(&hashedAndTruncatedSeed_expander,
hashed_decoded_seed);
PQCLEAN_LEDAKEMLT12_LEAKTIME_rand_error_pos(reconstructed_errorPos, &hashedAndTruncatedSeed_expander);
PQCLEAN_LEDAKEMLT12_LEAKTIME_expand_error(reconstructed_error_vector, reconstructed_errorPos);
int equal = (0 == memcmp((const uint8_t *) decoded_error_vector,
(const uint8_t *) reconstructed_error_vector,
N0 * NUM_DIGITS_GF2X_ELEMENT));
// equal == 1, if the reconstructed error vector match !!!
int decryptOk = (decode_ok == 1 && equal == 1);
memcpy(ss_input, decoded_seed, TRNG_BYTE_LENGTH);
if (decryptOk == 1) {
memcpy(ss_input + sizeof(decoded_seed), tail, TRNG_BYTE_LENGTH);
} else { // decryption failure
memcpy(ss_input + sizeof(decoded_seed), ((const privateKeyNiederreiter_t *)sk)->decryption_failure_secret, TRNG_BYTE_LENGTH);
}
HASH_FUNCTION(ss, ss_input, 2 * TRNG_BYTE_LENGTH);
return 0;
}

View File

@ -4,27 +4,32 @@
#include "gf2x_arith_mod_xPplusOne.h"
#include "niederreiter.h"
#include "qc_ldpc_parameters.h"
#include "randombytes.h"
#include "rng.h"
#include <string.h>
void PQCLEAN_LEDAKEMLT12_LEAKTIME_niederreiter_keygen(publicKeyNiederreiter_t *pk, privateKeyNiederreiter_t *sk, AES_XOF_struct *keys_expander) {
void PQCLEAN_LEDAKEMLT12_LEAKTIME_niederreiter_keygen(publicKeyNiederreiter_t *pk, privateKeyNiederreiter_t *sk) {
POSITION_T HPosOnes[N0][DV]; // sequence of N0 circ block matrices (p x p): Hi
POSITION_T HtrPosOnes[N0][DV]; // Sparse tranposed circulant H
POSITION_T QPosOnes[N0][M]; // Sparse Q, Each row contains the position of the ones of all the blocks of a row of Q as exponent+P*block_position
AES_XOF_struct keys_expander;
POSITION_T HPosOnes[N0][DV];
POSITION_T QPosOnes[N0][M];
POSITION_T LPosOnes[N0][DV * M];
POSITION_T auxPosOnes[DV * M];
unsigned char processedQOnes[N0];
DIGIT Ln0dense[NUM_DIGITS_GF2X_ELEMENT];
DIGIT Ln0Inv[NUM_DIGITS_GF2X_ELEMENT];
int is_L_full = 0;
uint8_t threshold = (DV * M) / 2 + 1; // threshold for round 2
sk->rejections = (int8_t) 0;
DIGIT Ln0dense[NUM_DIGITS_GF2X_ELEMENT] = {0};
DIGIT Ln0Inv[NUM_DIGITS_GF2X_ELEMENT] = {0};
int is_L_full;
int isDFRok;
memset(&keys_expander, 0x00, sizeof(AES_XOF_struct));
randombytes(sk->prng_seed, TRNG_BYTE_LENGTH);
PQCLEAN_LEDAKEMLT12_LEAKTIME_seedexpander_from_trng(&keys_expander, sk->prng_seed);
sk->rejections = (uint8_t) 0;
do {
PQCLEAN_LEDAKEMLT12_LEAKTIME_generateHPosOnes_HtrPosOnes(HPosOnes, HtrPosOnes, keys_expander);
PQCLEAN_LEDAKEMLT12_LEAKTIME_generateQsparse(QPosOnes, keys_expander);
PQCLEAN_LEDAKEMLT12_LEAKTIME_generateHPosOnes(HPosOnes, &keys_expander);
PQCLEAN_LEDAKEMLT12_LEAKTIME_generateQPosOnes(QPosOnes, &keys_expander);
for (int i = 0; i < N0; i++) {
for (int j = 0; j < DV * M; j++) {
LPosOnes[i][j] = INVALID_POS_VALUE;
@ -49,20 +54,21 @@ void PQCLEAN_LEDAKEMLT12_LEAKTIME_niederreiter_keygen(publicKeyNiederreiter_t *p
}
sk->rejections = sk->rejections + 1;
if (is_L_full) {
threshold = PQCLEAN_LEDAKEMLT12_LEAKTIME_DFR_test(LPosOnes);
isDFRok = PQCLEAN_LEDAKEMLT12_LEAKTIME_DFR_test(LPosOnes, &(sk->secondIterThreshold));
}
} while (!is_L_full || threshold == DFR_TEST_FAIL);
} while (!is_L_full || !isDFRok);
sk->rejections = sk->rejections - 1;
sk->threshold = threshold;
memset(Ln0dense, 0x00, sizeof(Ln0dense));
PQCLEAN_LEDAKEMLT12_LEAKTIME_seedexpander(&keys_expander,
sk->decryption_failure_secret,
(unsigned long)TRNG_BYTE_LENGTH);
for (int j = 0; j < DV * M; j++) {
if (LPosOnes[N0 - 1][j] != INVALID_POS_VALUE) {
PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_set_coeff(Ln0dense, LPosOnes[N0 - 1][j], 1);
}
}
memset(Ln0Inv, 0x00, sizeof(Ln0Inv));
PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_mod_inverse(Ln0Inv, Ln0dense);
for (int i = 0; i < N0 - 1; i++) {
PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_mod_mul_dense_to_sparse(pk->Mtr + i * NUM_DIGITS_GF2X_ELEMENT,
@ -76,45 +82,43 @@ void PQCLEAN_LEDAKEMLT12_LEAKTIME_niederreiter_keygen(publicKeyNiederreiter_t *p
}
}
void PQCLEAN_LEDAKEMLT12_LEAKTIME_niederreiter_encrypt(DIGIT syndrome[],
const publicKeyNiederreiter_t *pk,
const DIGIT err[]) {
void PQCLEAN_LEDAKEMLT12_LEAKTIME_niederreiter_encrypt(DIGIT *syndrome, const publicKeyNiederreiter_t *pk, const DIGIT *err) {
int i;
DIGIT saux[NUM_DIGITS_GF2X_ELEMENT];
memset(syndrome, 0x00, NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B);
for (i = 0; i < N0 - 1; i++) {
for (size_t i = 0; i < N0 - 1; i++) {
PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_mod_mul(saux,
pk->Mtr + i * NUM_DIGITS_GF2X_ELEMENT,
err + i * NUM_DIGITS_GF2X_ELEMENT);
PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_mod_add(syndrome, syndrome, saux);
}
PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_mod_add(syndrome, syndrome, err + (N0 - 1)*NUM_DIGITS_GF2X_ELEMENT);
}
int PQCLEAN_LEDAKEMLT12_LEAKTIME_niederreiter_decrypt(DIGIT *err, const privateKeyNiederreiter_t *sk, const DIGIT *syndrome) {
AES_XOF_struct niederreiter_decrypt_expander;
POSITION_T HPosOnes[N0][DV];
POSITION_T HtrPosOnes[N0][DV];
POSITION_T QPosOnes[N0][M];
POSITION_T QtrPosOnes[N0][M];
POSITION_T auxPosOnes[DV * M];
POSITION_T LPosOnes[N0][DV * M];
POSITION_T auxPosOnes[DV * M];
POSITION_T HtrPosOnes[N0][DV];
POSITION_T QtrPosOnes[N0][M];
POSITION_T auxSparse[DV * M];
POSITION_T Ln0trSparse[DV * M];
unsigned char processedQOnes[N0];
unsigned transposed_ones_idx[N0];
DIGIT err_computed[N0 * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B] = {0};
DIGIT privateSyndrome[NUM_DIGITS_GF2X_ELEMENT];
DIGIT mockup_error_vector[N0 * NUM_DIGITS_GF2X_ELEMENT];
unsigned char processedQOnes[N0];
int rejections = sk->rejections;
int currQoneIdx, endQblockIdx;
int decryptOk, err_weight;
PQCLEAN_LEDAKEMLT12_LEAKTIME_seedexpander_from_trng(&niederreiter_decrypt_expander, sk->prng_seed);
do {
PQCLEAN_LEDAKEMLT12_LEAKTIME_generateHPosOnes_HtrPosOnes(HPosOnes, HtrPosOnes, &niederreiter_decrypt_expander);
PQCLEAN_LEDAKEMLT12_LEAKTIME_generateQsparse(QPosOnes, &niederreiter_decrypt_expander);
PQCLEAN_LEDAKEMLT12_LEAKTIME_generateHPosOnes(HPosOnes, &niederreiter_decrypt_expander);
PQCLEAN_LEDAKEMLT12_LEAKTIME_generateQPosOnes(QPosOnes, &niederreiter_decrypt_expander);
for (int i = 0; i < N0; i++) {
for (int j = 0; j < DV * M; j++) {
LPosOnes[i][j] = INVALID_POS_VALUE;
@ -136,19 +140,8 @@ int PQCLEAN_LEDAKEMLT12_LEAKTIME_niederreiter_decrypt(DIGIT *err, const privateK
rejections--;
} while (rejections >= 0);
memset(transposed_ones_idx, 0x00, sizeof(transposed_ones_idx));
for (unsigned source_row_idx = 0; source_row_idx < N0 ; source_row_idx++) {
currQoneIdx = 0; // position in the column of QtrPosOnes[][...]
endQblockIdx = 0;
for (int blockIdx = 0; blockIdx < N0; blockIdx++) {
endQblockIdx += qBlockWeights[source_row_idx][blockIdx];
for (; currQoneIdx < endQblockIdx; currQoneIdx++) {
QtrPosOnes[blockIdx][transposed_ones_idx[blockIdx]] = (P -
QPosOnes[source_row_idx][currQoneIdx]) % P;
transposed_ones_idx[blockIdx]++;
}
}
}
PQCLEAN_LEDAKEMLT12_LEAKTIME_transposeHPosOnes(HtrPosOnes, HPosOnes);
PQCLEAN_LEDAKEMLT12_LEAKTIME_transposeQPosOnes(QtrPosOnes, QPosOnes);
for (int i = 0; i < DV * M; i++) {
Ln0trSparse[i] = INVALID_POS_VALUE;
@ -163,29 +156,36 @@ int PQCLEAN_LEDAKEMLT12_LEAKTIME_niederreiter_decrypt(DIGIT *err, const privateK
DV * M, Ln0trSparse,
DV * M, auxSparse);
}
PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_transpose_in_place_sparse(DV * M, Ln0trSparse);
PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_mod_mul_dense_to_sparse(privateSyndrome, syndrome, Ln0trSparse, DV * M);
/* prepare mockup error vector in case a decoding failure occurs */
memset(mockup_error_vector, 0x00, N0 * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B);
memcpy(mockup_error_vector, syndrome, NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B);
PQCLEAN_LEDAKEMLT12_LEAKTIME_seedexpander(&niederreiter_decrypt_expander,
((unsigned char *) mockup_error_vector) + (NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B),
TRNG_BYTE_LENGTH);
PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_mod_mul_dense_to_sparse(privateSyndrome,
syndrome,
Ln0trSparse,
DV * M);
memset(err, 0x00, N0 * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B);
decryptOk = PQCLEAN_LEDAKEMLT12_LEAKTIME_bf_decoding(err, (const POSITION_T (*)[DV]) HtrPosOnes,
(const POSITION_T (*)[M]) QtrPosOnes, privateSyndrome, sk->threshold);
int decryptOk = 0;
decryptOk = PQCLEAN_LEDAKEMLT12_LEAKTIME_bf_decoding(err_computed,
(const POSITION_T (*)[DV]) HtrPosOnes,
(const POSITION_T (*)[M]) QtrPosOnes,
privateSyndrome, sk->secondIterThreshold);
err_weight = 0;
int err_weight = 0;
for (int i = 0 ; i < N0; i++) {
err_weight += PQCLEAN_LEDAKEMLT12_LEAKTIME_population_count(err + (NUM_DIGITS_GF2X_ELEMENT * i));
err_weight += PQCLEAN_LEDAKEMLT12_LEAKTIME_population_count(err_computed + (NUM_DIGITS_GF2X_ELEMENT * i));
}
decryptOk = decryptOk && (err_weight == NUM_ERRORS_T);
if (!decryptOk) { // TODO: not constant time, replace with cmov?
memcpy(err, mockup_error_vector, N0 * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B);
/* prepare mockup error vector in case a decoding failure occurs */
DIGIT err_mockup[N0 * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B];
memcpy(err_mockup, syndrome, NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B);
memcpy(err_mockup + NUM_DIGITS_GF2X_ELEMENT, sk->decryption_failure_secret, TRNG_BYTE_LENGTH);
memset(((unsigned char *) err_mockup) + (NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B) + TRNG_BYTE_LENGTH, 0x00,
(N0 - 1)*NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B - TRNG_BYTE_LENGTH);
if (!decryptOk) {
memcpy(err, err_mockup, N0 * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B);
} else {
memcpy(err, err_computed, N0 * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B);
}
return decryptOk;

View File

@ -6,24 +6,19 @@
#include "rng.h"
typedef struct {
/* raw entropy extracted from TRNG, will be deterministically expanded into
* H and Q during decryption */
unsigned char prng_seed[TRNG_BYTE_LENGTH];
int8_t rejections;
uint8_t threshold; // for round 2
uint8_t rejections;
uint8_t secondIterThreshold;
uint8_t decryption_failure_secret[TRNG_BYTE_LENGTH];
} privateKeyNiederreiter_t;
typedef struct {
DIGIT Mtr[(N0 - 1)*NUM_DIGITS_GF2X_ELEMENT];
// Dense representation of the matrix M=Ln0*L,
// An array including a sequence of (N0-1) gf2x elements;
// each gf2x element is stored as a binary polynomial(mod x^P+1)
// with P coefficients.
} publicKeyNiederreiter_t;
void PQCLEAN_LEDAKEMLT12_LEAKTIME_niederreiter_keygen(publicKeyNiederreiter_t *pk, privateKeyNiederreiter_t *sk, AES_XOF_struct *keys_expander);
void PQCLEAN_LEDAKEMLT12_LEAKTIME_niederreiter_encrypt(DIGIT syndrome[], const publicKeyNiederreiter_t *pk, const DIGIT *err);
void PQCLEAN_LEDAKEMLT12_LEAKTIME_niederreiter_keygen(publicKeyNiederreiter_t *pk, privateKeyNiederreiter_t *sk);
void PQCLEAN_LEDAKEMLT12_LEAKTIME_niederreiter_encrypt(DIGIT syndrome[], const publicKeyNiederreiter_t *pk, const DIGIT err[]);
int PQCLEAN_LEDAKEMLT12_LEAKTIME_niederreiter_decrypt(DIGIT *err, const privateKeyNiederreiter_t *sk, const DIGIT *syndrome);
#endif

View File

@ -0,0 +1,87 @@
#include "sort.h"
/*
Constant-time uint32_t sorting by Daniel J. Bernstein
Source: https://sorting.cr.yp.to
*/
static void int32_sort(int32 *x, size_t n) {
size_t top, p, q, r, i, j;
if (n < 2) {
return;
}
top = 1;
while (top < n - top) {
top += top;
}
for (p = top; p >= 1; p >>= 1) {
i = 0;
while (i + 2 * p <= n) {
for (j = i; j < i + p; ++j) {
int32_MINMAX(x[j], x[j + p]);
}
i += 2 * p;
}
for (j = i; j < n - p; ++j) {
int32_MINMAX(x[j], x[j + p]);
}
i = 0;
j = 0;
for (q = top; q > p; q >>= 1) {
if (j != i) {
for (;;) {
if (j == n - q) {
goto done;
}
int32 a = x[j + p];
for (r = q; r > p; r >>= 1) {
int32_MINMAX(a, x[j + r]);
}
x[j + p] = a;
++j;
if (j == i + p) {
i += 2 * p;
break;
}
}
}
while (i + p <= n - q) {
for (j = i; j < i + p; ++j) {
int32 a = x[j + p];
for (r = q; r > p; r >>= 1) {
int32_MINMAX(a, x[j + r]);
}
x[j + p] = a;
}
i += 2 * p;
}
/* now i + p > n - q */
j = i;
while (j < n - q) {
int32 a = x[j + p];
for (r = q; r > p; r >>= 1) {
int32_MINMAX(a, x[j + r]);
}
x[j + p] = a;
++j;
}
done:
;
}
}
}
/* can save time by integrating xor loops with int32_sort */
void PQCLEAN_LEDAKEMLT12_LEAKTIME_uint32_sort(uint32_t *x, size_t n) {
size_t j;
for (j = 0; j < n; ++j) {
x[j] ^= 0x80000000;
}
int32_sort((int32_t *) x, n);
for (j = 0; j < n; ++j) {
x[j] ^= 0x80000000;
}
}

View File

@ -0,0 +1,22 @@
#ifndef SORT_H
#define SORT_H
#include <stddef.h>
#include <stdint.h>
#define int32 int32_t
#define int32_MINMAX(a,b) \
do { \
int32 ab = (b) ^ (a); \
int32 c = (b) - (a); \
c ^= ab & (c ^ (b)); \
c >>= 31; \
c &= ab; \
(a) ^= c; \
(b) ^= c; \
} while(0)
void PQCLEAN_LEDAKEMLT12_LEAKTIME_uint32_sort(uint32_t *x, size_t n);
#endif

View File

@ -3,10 +3,10 @@ type: kem
claimed-nist-level: 3
claimed-security: IND-CCA2
length-public-key: 12032
length-secret-key: 34
length-ciphertext: 12032
length-secret-key: 66
length-ciphertext: 12064
length-shared-secret: 48
nistkat-sha256: 455dc69ee95196fe0526c3289fe46792acd55ac380b3c66be48eb3e3e10ad4e6
nistkat-sha256: b8b17dbb77aa3c3c77f738be053b355185388859ae6baa5655bf7e8413020b7f
principal-submitters:
- Marco Baldi
auxiliary-submitters:
@ -16,4 +16,4 @@ auxiliary-submitters:
- Paolo Santini
implementations:
- name: leaktime
version: 2.?
version: 2.1

View File

@ -1,32 +1,58 @@
#include "H_Q_matrices_generation.h"
#include "gf2x_arith_mod_xPplusOne.h"
void PQCLEAN_LEDAKEMLT32_LEAKTIME_generateHPosOnes_HtrPosOnes(
POSITION_T HPosOnes[N0][DV],
POSITION_T HtrPosOnes[N0][DV],
void PQCLEAN_LEDAKEMLT32_LEAKTIME_generateHPosOnes(POSITION_T HPosOnes[N0][DV],
AES_XOF_struct *keys_expander) {
for (int i = 0; i < N0; i++) {
/* Generate a random block of Htr */
PQCLEAN_LEDAKEMLT32_LEAKTIME_rand_circulant_sparse_block(&HtrPosOnes[i][0], DV, keys_expander);
}
for (int i = 0; i < N0; i++) {
/* Obtain directly the sparse representation of the block of H */
for (int k = 0; k < DV; k++) {
HPosOnes[i][k] = (P - HtrPosOnes[i][k]) % P; /* transposes indexes */
}
PQCLEAN_LEDAKEMLT32_LEAKTIME_rand_circulant_sparse_block(&HPosOnes[i][0],
DV,
keys_expander);
}
}
void PQCLEAN_LEDAKEMLT32_LEAKTIME_generateQsparse(
POSITION_T pos_ones[N0][M],
void PQCLEAN_LEDAKEMLT32_LEAKTIME_generateQPosOnes(POSITION_T QPosOnes[N0][M],
AES_XOF_struct *keys_expander) {
for (int i = 0; i < N0; i++) {
int placed_ones = 0;
for (int j = 0; j < N0; j++) {
PQCLEAN_LEDAKEMLT32_LEAKTIME_rand_circulant_sparse_block(&pos_ones[i][placed_ones],
PQCLEAN_LEDAKEMLT32_LEAKTIME_rand_circulant_sparse_block(&QPosOnes[i][placed_ones],
qBlockWeights[i][j],
keys_expander);
placed_ones += qBlockWeights[i][j];
}
}
}
void PQCLEAN_LEDAKEMLT32_LEAKTIME_transposeHPosOnes(POSITION_T HtrPosOnes[N0][DV], /* output*/
POSITION_T HPosOnes[N0][DV]) {
for (int i = 0; i < N0; i++) {
/* Obtain directly the sparse representation of the block of H */
for (int k = 0; k < DV; k++) {
HtrPosOnes[i][k] = (P - HPosOnes[i][k]) % P; /* transposes indexes */
}// end for k
}
}
void PQCLEAN_LEDAKEMLT32_LEAKTIME_transposeQPosOnes(POSITION_T QtrPosOnes[N0][M], /* output*/
POSITION_T QPosOnes[N0][M]) {
unsigned transposed_ones_idx[N0] = {0x00};
for (unsigned source_row_idx = 0; source_row_idx < N0 ; source_row_idx++) {
int currQoneIdx = 0; // position in the column of QtrPosOnes[][...]
int endQblockIdx = 0;
for (int blockIdx = 0; blockIdx < N0; blockIdx++) {
endQblockIdx += qBlockWeights[source_row_idx][blockIdx];
for (; currQoneIdx < endQblockIdx; currQoneIdx++) {
QtrPosOnes[blockIdx][transposed_ones_idx[blockIdx]] = (P -
QPosOnes[source_row_idx][currQoneIdx]) % P;
transposed_ones_idx[blockIdx]++;
}
}
}
}

View File

@ -5,7 +5,9 @@
#include "qc_ldpc_parameters.h"
#include "rng.h"
void PQCLEAN_LEDAKEMLT32_LEAKTIME_generateHPosOnes_HtrPosOnes(POSITION_T HPosOnes[N0][DV], POSITION_T HtrPosOnes[N0][DV], AES_XOF_struct *niederreiter_keys_expander);
void PQCLEAN_LEDAKEMLT32_LEAKTIME_generateQsparse(POSITION_T pos_ones[N0][M], AES_XOF_struct *niederreiter_keys_expander);
void PQCLEAN_LEDAKEMLT32_LEAKTIME_generateHPosOnes(POSITION_T HPosOnes[N0][DV], AES_XOF_struct *keys_expander);
void PQCLEAN_LEDAKEMLT32_LEAKTIME_generateQPosOnes(POSITION_T QPosOnes[N0][M], AES_XOF_struct *keys_expander);
void PQCLEAN_LEDAKEMLT32_LEAKTIME_transposeHPosOnes(POSITION_T HtrPosOnes[N0][DV], POSITION_T HPosOnes[N0][DV]);
void PQCLEAN_LEDAKEMLT32_LEAKTIME_transposeQPosOnes(POSITION_T QtrPosOnes[N0][M], POSITION_T QPosOnes[N0][M]);
#endif

View File

@ -3,10 +3,10 @@
LIB=libledakemlt32_leaktime.a
HEADERS=api.h bf_decoding.h dfr_test.h gf2x_arith_mod_xPplusOne.h \
gf2x_arith.h H_Q_matrices_generation.h \
niederreiter.h qc_ldpc_parameters.h rng.h
niederreiter.h qc_ldpc_parameters.h rng.h sort.h
OBJECTS=bf_decoding.o dfr_test.o gf2x_arith_mod_xPplusOne.o \
gf2x_arith.o H_Q_matrices_generation.o kem.o niederreiter.o rng.o
gf2x_arith.o H_Q_matrices_generation.o kem.o niederreiter.o rng.o sort.o
CFLAGS=-O3 -Wall -Werror -Wextra -Wvla -Wpedantic -Wmissing-prototypes -std=c99 \
-I../../../common $(EXTRAFLAGS)

View File

@ -2,7 +2,7 @@
# nmake /f Makefile.Microsoft_nmake
LIBRARY=libledakemlt32_leaktime.lib
OBJECTS=bf_decoding.obj dfr_test.obj gf2x_arith_mod_xPplusOne.obj gf2x_arith.obj H_Q_matrices_generation.obj kem.obj niederreiter.obj rng.obj
OBJECTS=bf_decoding.obj dfr_test.obj gf2x_arith_mod_xPplusOne.obj gf2x_arith.obj H_Q_matrices_generation.obj kem.obj niederreiter.obj rng.obj sort.obj
CFLAGS=/nologo /I ..\..\..\common /W4 /WX

View File

@ -3,9 +3,9 @@
#include <stdint.h>
#define PQCLEAN_LEDAKEMLT32_LEAKTIME_CRYPTO_SECRETKEYBYTES 34
#define PQCLEAN_LEDAKEMLT32_LEAKTIME_CRYPTO_SECRETKEYBYTES 66
#define PQCLEAN_LEDAKEMLT32_LEAKTIME_CRYPTO_PUBLICKEYBYTES 12032
#define PQCLEAN_LEDAKEMLT32_LEAKTIME_CRYPTO_CIPHERTEXTBYTES 12032
#define PQCLEAN_LEDAKEMLT32_LEAKTIME_CRYPTO_CIPHERTEXTBYTES 12064
#define PQCLEAN_LEDAKEMLT32_LEAKTIME_CRYPTO_BYTES 48
#define PQCLEAN_LEDAKEMLT32_LEAKTIME_CRYPTO_ALGNAME "LEDAKEMLT32"

View File

@ -2,70 +2,45 @@
#include "dfr_test.h"
#include "gf2x_arith_mod_xPplusOne.h"
#include "qc_ldpc_parameters.h"
#include "sort.h"
#include <string.h>
/* Tests if the current code attains the desired DFR. If that is the case,
* computes the threshold for the second iteration of the decoder and returns this values
* (max DV * M), on failure it returns 255 >> DV * M */
uint8_t PQCLEAN_LEDAKEMLT32_LEAKTIME_DFR_test(POSITION_T LSparse[N0][DV * M]) {
int PQCLEAN_LEDAKEMLT32_LEAKTIME_DFR_test(POSITION_T LSparse[N0][DV * M], uint8_t *secondIterThreshold) {
POSITION_T LSparse_loc[N0][DV * M];
POSITION_T rotated_column[DV * M];
/* Gamma matrix: an N0 x N0 block circulant matrix with block size p
* gamma[a][b][c] stores the intersection of the first column of the a-th
* block of L with the c-th column of the b-th block of L.
* Gamma computation can be accelerated employing symmetry and QC properties */
unsigned int gamma[N0][N0][P] = {{{0}}};
POSITION_T LSparse_loc[N0][DV * M]; /* vector of N_0 sparse blocks */
int gamma[N0][N0][P] = {{{0}}};
int maxMut[N0], maxMutMinusOne[N0];
int allBlockMaxSumst, allBlockMaxSumstMinusOne;
unsigned int gammaHist[N0][DV * M + 1] = {{0}};
unsigned int maxMut[N0], maxMutMinusOne[N0];
unsigned int firstidx, secondidx, intersectionval;
unsigned int allBlockMaxSumst, allBlockMaxSumstMinusOne;
unsigned int toAdd, histIdx;
/*transpose blocks of L, we need its columns */
for (int i = 0; i < N0; i++) {
for (int j = 0; j < DV * M; j++) {
if (LSparse[i][j] != 0) {
LSparse_loc[i][j] = (P - LSparse[i][j]) ;
}
}
PQCLEAN_LEDAKEMLT32_LEAKTIME_quicksort_sparse(LSparse_loc[i]);
PQCLEAN_LEDAKEMLT32_LEAKTIME_uint32_sort(LSparse_loc[i], DV * M);
}
for (int i = 0; i < N0; i++ ) {
for (int j = 0; j < N0; j++ ) {
for (int k = 0; k < P; k++) {
/* compute the rotated sparse column needed */
for (int idxToRotate = 0; idxToRotate < (DV * M); idxToRotate++) {
rotated_column[idxToRotate] = (LSparse_loc[j][idxToRotate] + k) % P;
}
PQCLEAN_LEDAKEMLT32_LEAKTIME_quicksort_sparse(rotated_column);
/* compute the intersection amount */
firstidx = 0, secondidx = 0;
intersectionval = 0;
while ( (firstidx < DV * M) && (secondidx < DV * M) ) {
if ( LSparse_loc[i][firstidx] == rotated_column[secondidx] ) {
intersectionval++;
firstidx++;
secondidx++;
} else if ( LSparse_loc[i][firstidx] > rotated_column[secondidx] ) {
secondidx++;
} else { /*if ( LSparse_loc[i][firstidx] < rotated_column[secondidx] ) */
firstidx++;
for (int k = 0; k < (DV * M); k++) {
for (int l = 0; l < (DV * M); l++) {
gamma[i][j][ (P + LSparse_loc[i][k] - LSparse_loc[j][l]) % P ]++;
}
}
}
}
gamma[i][j][k] = intersectionval;
}
}
}
for (int i = 0; i < N0; i++ ) {
for (int j = 0; j < N0; j++ ) {
gamma[i][j][0] = 0;
}
}
/* build histogram of values in gamma */
for (int i = 0; i < N0; i++ ) {
for (int j = 0; j < N0; j++ ) {
@ -77,9 +52,9 @@ uint8_t PQCLEAN_LEDAKEMLT32_LEAKTIME_DFR_test(POSITION_T LSparse[N0][DV * M]) {
for (int gammaBlockRowIdx = 0; gammaBlockRowIdx < N0; gammaBlockRowIdx++) {
toAdd = T_BAR - 1;
unsigned int toAdd = T_BAR - 1;
maxMutMinusOne[gammaBlockRowIdx] = 0;
histIdx = DV * M;
unsigned int histIdx = DV * M;
while ( (histIdx > 0) && (toAdd > 0)) {
if (gammaHist[gammaBlockRowIdx][histIdx] > toAdd ) {
maxMutMinusOne[gammaBlockRowIdx] += histIdx * toAdd;
@ -93,7 +68,6 @@ uint8_t PQCLEAN_LEDAKEMLT32_LEAKTIME_DFR_test(POSITION_T LSparse[N0][DV * M]) {
maxMut[gammaBlockRowIdx] = histIdx + maxMutMinusOne[gammaBlockRowIdx];
}
/*seek max values across all gamma blocks */
allBlockMaxSumst = maxMut[0];
allBlockMaxSumstMinusOne = maxMutMinusOne[0];
@ -106,7 +80,8 @@ uint8_t PQCLEAN_LEDAKEMLT32_LEAKTIME_DFR_test(POSITION_T LSparse[N0][DV * M]) {
allBlockMaxSumstMinusOne;
}
if (DV * M > (allBlockMaxSumstMinusOne + allBlockMaxSumst)) {
return (uint8_t) allBlockMaxSumst + 1;
*secondIterThreshold = allBlockMaxSumst + 1;
return 1;
}
return DFR_TEST_FAIL;
return 0;
}

View File

@ -1,8 +1,6 @@
#ifndef DFR_TEST_H
#define DFR_TEST_H
#define DFR_TEST_FAIL (255)
uint8_t PQCLEAN_LEDAKEMLT32_LEAKTIME_DFR_test(POSITION_T LSparse[N0][DV * M]);
int PQCLEAN_LEDAKEMLT32_LEAKTIME_DFR_test(POSITION_T LSparse[N0][DV * M], uint8_t *secondIterThreshold);
#endif

View File

@ -1,5 +1,6 @@
#include "gf2x_arith_mod_xPplusOne.h"
#include "rng.h"
#include "sort.h"
#include <string.h> // memcpy(...), memset(...)
@ -62,81 +63,15 @@ void PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_mod_add(DIGIT Res[], const DIGIT A[], con
PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_add(Res, A, B, NUM_DIGITS_GF2X_ELEMENT);
}
static int partition(POSITION_T arr[], int lo, int hi) {
POSITION_T x = arr[hi];
POSITION_T tmp;
int i = (lo - 1);
for (int j = lo; j <= hi - 1; j++) {
if (arr[j] <= x) {
i++;
tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}
tmp = arr[i + 1];
arr[i + 1] = arr[hi];
arr[hi] = tmp;
return i + 1;
}
void PQCLEAN_LEDAKEMLT32_LEAKTIME_quicksort_sparse(POSITION_T Res[]) {
int stack[DV * M];
int hi, lo, pivot, tos = -1;
stack[++tos] = 0;
stack[++tos] = (DV * M) - 1;
while (tos >= 0 ) {
hi = stack[tos--];
lo = stack[tos--];
pivot = partition(Res, lo, hi);
if ( (pivot - 1) > lo) {
stack[++tos] = lo;
stack[++tos] = pivot - 1;
}
if ( (pivot + 1) < hi) {
stack[++tos] = pivot + 1;
stack[++tos] = hi;
}
}
}
static void gf2x_mod(DIGIT out[], const DIGIT in[]) {
DIGIT aux[NUM_DIGITS_GF2X_ELEMENT + 1];
int i, j, posTrailingBit, maskOffset;
DIGIT mask, aux[2 * NUM_DIGITS_GF2X_ELEMENT];
memcpy(aux, in, 2 * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B);
memset(out, 0x00, NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B);
for (i = 0; i < (2 * NUM_DIGITS_GF2X_ELEMENT) - NUM_DIGITS_GF2X_MODULUS; i += 1) {
for (j = DIGIT_SIZE_b - 1; j >= 0; j--) {
mask = ((DIGIT)0x1) << j;
if (aux[i] & mask) {
aux[i] ^= mask;
posTrailingBit = (DIGIT_SIZE_b - 1 - j) + i * DIGIT_SIZE_b + P;
maskOffset = (DIGIT_SIZE_b - 1 - (posTrailingBit % DIGIT_SIZE_b));
mask = (DIGIT) 0x1 << maskOffset;
aux[posTrailingBit / DIGIT_SIZE_b] ^= mask;
}
}
}
for (j = DIGIT_SIZE_b - 1; j >= MSb_POSITION_IN_MSB_DIGIT_OF_MODULUS; j--) {
mask = ((DIGIT)0x1) << j;
if (aux[i] & mask) {
aux[i] ^= mask;
posTrailingBit = (DIGIT_SIZE_b - 1 - j) + i * DIGIT_SIZE_b + P;
maskOffset = (DIGIT_SIZE_b - 1 - (posTrailingBit % DIGIT_SIZE_b));
mask = (DIGIT) 0x1 << maskOffset;
aux[posTrailingBit / DIGIT_SIZE_b] ^= mask;
}
}
for (i = 0; i < NUM_DIGITS_GF2X_ELEMENT; i++) {
out[NUM_DIGITS_GF2X_ELEMENT - 1 - i] = aux[2 * NUM_DIGITS_GF2X_ELEMENT - 1 - i];
}
memcpy(aux, in, (NUM_DIGITS_GF2X_ELEMENT + 1)*DIGIT_SIZE_B);
PQCLEAN_LEDAKEMLT32_LEAKTIME_right_bit_shift_n(NUM_DIGITS_GF2X_ELEMENT + 1, aux,
MSb_POSITION_IN_MSB_DIGIT_OF_MODULUS);
PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_add(out, aux + 1, in + NUM_DIGITS_GF2X_ELEMENT,
NUM_DIGITS_GF2X_ELEMENT);
out[0] &= ((DIGIT)1 << MSb_POSITION_IN_MSB_DIGIT_OF_MODULUS) - 1;
}
static void left_bit_shift(const int length, DIGIT in[]) {
@ -331,16 +266,13 @@ void PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_mod_mul(DIGIT Res[], const DIGIT A[], con
/*PRE: the representation of the sparse coefficients is sorted in increasing
order of the coefficients themselves */
void PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_mod_mul_dense_to_sparse(
DIGIT Res[],
const DIGIT dense[],
void PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_mod_mul_dense_to_sparse(DIGIT Res[], const DIGIT dense[],
POSITION_T sparse[], unsigned int nPos) {
DIGIT aux[2 * NUM_DIGITS_GF2X_ELEMENT] = {0x00};
DIGIT resDouble[2 * NUM_DIGITS_GF2X_ELEMENT] = {0x00};
memcpy(aux + NUM_DIGITS_GF2X_ELEMENT, dense, NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B);
memcpy(resDouble + NUM_DIGITS_GF2X_ELEMENT, dense,
NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B);
memcpy(resDouble + NUM_DIGITS_GF2X_ELEMENT, dense, NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B);
if (sparse[0] != INVALID_POS_VALUE) {
left_bit_shift_wide_n(2 * NUM_DIGITS_GF2X_ELEMENT, resDouble, sparse[0]);
@ -380,15 +312,15 @@ void PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_transpose_in_place_sparse(int sizeA, POSI
}
void PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_mod_mul_sparse(size_t sizeR, POSITION_T Res[],
size_t sizeA, const POSITION_T A[],
size_t sizeB, const POSITION_T B[]) {
void PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_mod_mul_sparse(int sizeR, POSITION_T Res[],
int sizeA, const POSITION_T A[],
int sizeB, const POSITION_T B[]) {
/* compute all the coefficients, filling invalid positions with P*/
size_t lastFilledPos = 0;
for (size_t i = 0 ; i < sizeA ; i++) {
for (size_t j = 0 ; j < sizeB ; j++) {
uint32_t prod = A[i] + B[j];
int lastFilledPos = 0;
for (int i = 0 ; i < sizeA ; i++) {
for (int j = 0 ; j < sizeB ; j++) {
uint32_t prod = ((uint32_t) A[i]) + ((uint32_t) B[j]);
prod = ( (prod >= P) ? prod - P : prod);
if ((A[i] != INVALID_POS_VALUE) &&
(B[j] != INVALID_POS_VALUE)) {
@ -403,12 +335,12 @@ void PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_mod_mul_sparse(size_t sizeR, POSITION_T R
Res[lastFilledPos] = INVALID_POS_VALUE;
lastFilledPos++;
}
PQCLEAN_LEDAKEMLT32_LEAKTIME_quicksort_sparse(Res);
PQCLEAN_LEDAKEMLT32_LEAKTIME_uint32_sort(Res, sizeR);
/* eliminate duplicates */
POSITION_T lastReadPos = Res[0];
int duplicateCount;
size_t write_idx = 0;
size_t read_idx = 0;
int write_idx = 0;
int read_idx = 0;
while (read_idx < sizeR && Res[read_idx] != INVALID_POS_VALUE) {
lastReadPos = Res[read_idx];
read_idx++;
@ -529,8 +461,7 @@ void PQCLEAN_LEDAKEMLT32_LEAKTIME_rand_circulant_sparse_block(POSITION_T *pos_on
}
/* Returns random weight-t circulant block */
void PQCLEAN_LEDAKEMLT32_LEAKTIME_rand_circulant_blocks_sequence(
DIGIT sequence[N0 * NUM_DIGITS_GF2X_ELEMENT],
void PQCLEAN_LEDAKEMLT32_LEAKTIME_rand_circulant_blocks_sequence(DIGIT sequence[N0 * NUM_DIGITS_GF2X_ELEMENT],
AES_XOF_struct *seed_expander_ctx) {
int rndPos[NUM_ERRORS_T], duplicated, counter = 0;
@ -561,6 +492,39 @@ void PQCLEAN_LEDAKEMLT32_LEAKTIME_rand_circulant_blocks_sequence(
}
void PQCLEAN_LEDAKEMLT32_LEAKTIME_rand_error_pos(POSITION_T errorPos[NUM_ERRORS_T],
AES_XOF_struct *seed_expander_ctx) {
int duplicated, counter = 0;
while (counter < NUM_ERRORS_T) {
uint32_t p = rand_range(N0 * NUM_BITS_GF2X_ELEMENT, P_BITS, seed_expander_ctx);
duplicated = 0;
for (int j = 0; j < counter; j++) if (errorPos[j] == p) {
duplicated = 1;
}
if (duplicated == 0) {
errorPos[counter] = p;
counter++;
}
}
}
void PQCLEAN_LEDAKEMLT32_LEAKTIME_expand_error(DIGIT sequence[N0 * NUM_DIGITS_GF2X_ELEMENT],
POSITION_T errorPos[NUM_ERRORS_T]) {
memset(sequence, 0x00, N0 * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B);
for (int j = 0; j < NUM_ERRORS_T; j++) {
int polyIndex = errorPos[j] / P;
int exponent = errorPos[j] % P;
PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_set_coeff( sequence + NUM_DIGITS_GF2X_ELEMENT * polyIndex, exponent,
( (DIGIT) 1));
}
}
void PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_tobytes(uint8_t *bytes, const DIGIT *poly) {
size_t i, j;
for (i = 0; i < NUM_DIGITS_GF2X_ELEMENT; i++) {

View File

@ -13,7 +13,7 @@
#define NUM_DIGITS_GF2X_MODULUS ((P+1+DIGIT_SIZE_b-1)/DIGIT_SIZE_b)
#define MSb_POSITION_IN_MSB_DIGIT_OF_MODULUS (P-DIGIT_SIZE_b*(NUM_DIGITS_GF2X_MODULUS-1))
#define INVALID_POS_VALUE (P)
#define P_BITS (17) // log_2(p) = 16.55406417
#define P_BITS (17)
void PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_copy(DIGIT dest[], const DIGIT in[]);
DIGIT PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_get_coeff(const DIGIT poly[], unsigned int exponent);
@ -21,15 +21,16 @@ void PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_set_coeff(DIGIT poly[], unsigned int expo
void PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_toggle_coeff(DIGIT poly[], unsigned int exponent);
int PQCLEAN_LEDAKEMLT32_LEAKTIME_population_count(DIGIT *poly);
void PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_mod_add(DIGIT Res[], const DIGIT A[], const DIGIT B[]);
void PQCLEAN_LEDAKEMLT32_LEAKTIME_quicksort_sparse(POSITION_T Res[]);
void PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_mod_mul(DIGIT Res[], const DIGIT A[], const DIGIT B[]);
void PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_transpose_in_place(DIGIT A[]);
void PQCLEAN_LEDAKEMLT32_LEAKTIME_rand_circulant_sparse_block(POSITION_T *pos_ones, int countOnes, AES_XOF_struct *seed_expander_ctx);
void PQCLEAN_LEDAKEMLT32_LEAKTIME_rand_circulant_blocks_sequence(DIGIT *sequence, AES_XOF_struct *seed_expander_ctx);
void PQCLEAN_LEDAKEMLT32_LEAKTIME_rand_error_pos(POSITION_T errorPos[NUM_ERRORS_T], AES_XOF_struct *seed_expander_ctx);
void PQCLEAN_LEDAKEMLT32_LEAKTIME_expand_error(DIGIT sequence[N0 * NUM_DIGITS_GF2X_ELEMENT], POSITION_T errorPos[NUM_ERRORS_T]);
void PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_mod_add_sparse(int sizeR, POSITION_T Res[], int sizeA, const POSITION_T A[], int sizeB, const POSITION_T B[]);
void PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_transpose_in_place_sparse(int sizeA, POSITION_T A[]);
int PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_mod_inverse(DIGIT out[], const DIGIT in[]);
void PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_mod_mul_sparse(size_t sizeR, POSITION_T Res[], size_t sizeA, const POSITION_T A[], size_t sizeB, const POSITION_T B[]);
void PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_mod_mul_sparse(int sizeR, POSITION_T Res[], int sizeA, const POSITION_T A[], int sizeB, const POSITION_T B[]);
void PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_mod_mul_dense_to_sparse(DIGIT Res[], const DIGIT dense[], POSITION_T sparse[], unsigned int nPos);
void PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_tobytes(uint8_t *bytes, const DIGIT *poly);
void PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_frombytes(DIGIT *poly, const uint8_t *poly_bytes);

View File

@ -5,6 +5,7 @@
#include <string.h>
/*
static void pack_pk(uint8_t *pk_bytes, publicKeyNiederreiter_t *pk) {
size_t i;
for (i = 0; i < N0 - 1; i++) {
@ -36,57 +37,113 @@ static void pack_error(uint8_t *error_bytes, DIGIT *error_digits) {
error_digits + i * NUM_DIGITS_GF2X_ELEMENT);
}
}
*/
/* Generates a keypair - pk is the public key and sk is the secret key. */
int PQCLEAN_LEDAKEMLT32_LEAKTIME_crypto_kem_keypair(unsigned char *pk, unsigned char *sk) {
AES_XOF_struct niederreiter_keys_expander;
publicKeyNiederreiter_t pk_nie;
/* IND-CCA2 Keygen */
int PQCLEAN_LEDAKEMLT32_LEAKTIME_crypto_kem_keypair(uint8_t *pk, uint8_t *sk) {
randombytes(((privateKeyNiederreiter_t *)sk)->prng_seed, TRNG_BYTE_LENGTH);
PQCLEAN_LEDAKEMLT32_LEAKTIME_seedexpander_from_trng(&niederreiter_keys_expander, ((privateKeyNiederreiter_t *)sk)->prng_seed);
PQCLEAN_LEDAKEMLT32_LEAKTIME_niederreiter_keygen(&pk_nie, (privateKeyNiederreiter_t *) sk, &niederreiter_keys_expander);
pack_pk(pk, &pk_nie);
PQCLEAN_LEDAKEMLT32_LEAKTIME_niederreiter_keygen((publicKeyNiederreiter_t *) pk,
(privateKeyNiederreiter_t *) sk);
return 0;
}
/* Encrypt - pk is the public key, ct is a key encapsulation message
(ciphertext), ss is the shared secret.*/
int PQCLEAN_LEDAKEMLT32_LEAKTIME_crypto_kem_enc(unsigned char *ct, unsigned char *ss, const unsigned char *pk) {
AES_XOF_struct niederreiter_encap_key_expander;
unsigned char encapsulated_key_seed[TRNG_BYTE_LENGTH];
/* IND-CCA2 Encapsulation */
int PQCLEAN_LEDAKEMLT32_LEAKTIME_crypto_kem_enc(uint8_t *ct, uint8_t *ss, const uint8_t *pk) {
AES_XOF_struct hashedAndTruncatedSeed_expander;
POSITION_T errorPos[NUM_ERRORS_T];
DIGIT error_vector[N0 * NUM_DIGITS_GF2X_ELEMENT];
uint8_t error_bytes[N0 * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B];
DIGIT syndrome[NUM_DIGITS_GF2X_ELEMENT];
publicKeyNiederreiter_t pk_nie;
uint8_t seed[TRNG_BYTE_LENGTH];
uint8_t ss_input[2 * TRNG_BYTE_LENGTH] = {0};
uint8_t hashedSeed[HASH_BYTE_LENGTH];
uint8_t hashedAndTruncatedSeed[TRNG_BYTE_LENGTH] = {0};
uint8_t hashedErrorVector[HASH_BYTE_LENGTH];
uint8_t hashedAndTruncatedErrorVector[TRNG_BYTE_LENGTH] = {0};
uint8_t maskedSeed[TRNG_BYTE_LENGTH];
randombytes(encapsulated_key_seed, TRNG_BYTE_LENGTH);
unpack_pk(&pk_nie, pk);
randombytes(seed, TRNG_BYTE_LENGTH);
memcpy(ss_input, seed, TRNG_BYTE_LENGTH);
HASH_FUNCTION(ss, ss_input, 2 * TRNG_BYTE_LENGTH);
HASH_FUNCTION(hashedSeed, seed, TRNG_BYTE_LENGTH);
PQCLEAN_LEDAKEMLT32_LEAKTIME_seedexpander_from_trng(&niederreiter_encap_key_expander, encapsulated_key_seed);
PQCLEAN_LEDAKEMLT32_LEAKTIME_rand_circulant_blocks_sequence(error_vector, &niederreiter_encap_key_expander);
pack_error(error_bytes, error_vector);
HASH_FUNCTION(ss, error_bytes, (N0 * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B));
PQCLEAN_LEDAKEMLT32_LEAKTIME_niederreiter_encrypt(syndrome, &pk_nie, error_vector);
memcpy(hashedAndTruncatedSeed, hashedSeed, TRNG_BYTE_LENGTH);
pack_ct(ct, syndrome);
memset(&hashedAndTruncatedSeed_expander, 0x00, sizeof(AES_XOF_struct));
PQCLEAN_LEDAKEMLT32_LEAKTIME_seedexpander_from_trng(&hashedAndTruncatedSeed_expander, hashedAndTruncatedSeed);
PQCLEAN_LEDAKEMLT32_LEAKTIME_rand_error_pos(errorPos, &hashedAndTruncatedSeed_expander);
PQCLEAN_LEDAKEMLT32_LEAKTIME_expand_error(error_vector, errorPos);
HASH_FUNCTION(hashedErrorVector, (const uint8_t *) error_vector, (N0 * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B));
memcpy(hashedAndTruncatedErrorVector, hashedErrorVector, TRNG_BYTE_LENGTH);
for (int i = 0; i < TRNG_BYTE_LENGTH; ++i) {
maskedSeed[i] = seed[i] ^ hashedAndTruncatedErrorVector[i];
}
PQCLEAN_LEDAKEMLT32_LEAKTIME_niederreiter_encrypt((DIGIT *) ct, (const publicKeyNiederreiter_t *)pk, error_vector);
memcpy(ct + (NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B), maskedSeed, TRNG_BYTE_LENGTH);
return 0;
}
/* Decrypt - ct is a key encapsulation message (ciphertext), sk is the private
key, ss is the shared secret */
int PQCLEAN_LEDAKEMLT32_LEAKTIME_crypto_kem_dec(unsigned char *ss, const unsigned char *ct, const unsigned char *sk) {
/* INDCCA2 Decapsulation */
int PQCLEAN_LEDAKEMLT32_LEAKTIME_crypto_kem_dec(uint8_t *ss, const uint8_t *ct, const uint8_t *sk) {
AES_XOF_struct hashedAndTruncatedSeed_expander;
POSITION_T reconstructed_errorPos[NUM_ERRORS_T];
DIGIT reconstructed_error_vector[N0 * NUM_DIGITS_GF2X_ELEMENT];
DIGIT decoded_error_vector[N0 * NUM_DIGITS_GF2X_ELEMENT];
uint8_t decoded_error_bytes[N0 * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B];
DIGIT syndrome[NUM_DIGITS_GF2X_ELEMENT];
uint8_t hashedErrorVector[HASH_BYTE_LENGTH];
uint8_t hashedAndTruncatedErrorVector[TRNG_BYTE_LENGTH] = {0};
uint8_t decoded_seed[TRNG_BYTE_LENGTH];
uint8_t hashed_decoded_seed[HASH_BYTE_LENGTH];
uint8_t hashedAndTruncated_decoded_seed[TRNG_BYTE_LENGTH] = {0};
uint8_t ss_input[2 * TRNG_BYTE_LENGTH], tail[TRNG_BYTE_LENGTH] = {0};
unpack_ct(syndrome, ct);
PQCLEAN_LEDAKEMLT32_LEAKTIME_niederreiter_decrypt(decoded_error_vector, (privateKeyNiederreiter_t *)sk, syndrome);
pack_error(decoded_error_bytes, decoded_error_vector);
HASH_FUNCTION(ss, decoded_error_bytes, (N0 * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B));
int decode_ok = PQCLEAN_LEDAKEMLT32_LEAKTIME_niederreiter_decrypt(decoded_error_vector,
(const privateKeyNiederreiter_t *)sk,
(DIGIT *)ct);
HASH_FUNCTION(hashedErrorVector,
(const uint8_t *) decoded_error_vector,
(N0 * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B));
memcpy(hashedAndTruncatedErrorVector, hashedErrorVector, TRNG_BYTE_LENGTH);
for (int i = 0; i < TRNG_BYTE_LENGTH; ++i) {
decoded_seed[i] = ct[(NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B) + i] ^
hashedAndTruncatedErrorVector[i];
}
HASH_FUNCTION(hashed_decoded_seed, decoded_seed, TRNG_BYTE_LENGTH);
memcpy(hashedAndTruncated_decoded_seed, hashed_decoded_seed, TRNG_BYTE_LENGTH);
memset(&hashedAndTruncatedSeed_expander, 0x00, sizeof(AES_XOF_struct));
PQCLEAN_LEDAKEMLT32_LEAKTIME_seedexpander_from_trng(&hashedAndTruncatedSeed_expander,
hashed_decoded_seed);
PQCLEAN_LEDAKEMLT32_LEAKTIME_rand_error_pos(reconstructed_errorPos, &hashedAndTruncatedSeed_expander);
PQCLEAN_LEDAKEMLT32_LEAKTIME_expand_error(reconstructed_error_vector, reconstructed_errorPos);
int equal = (0 == memcmp((const uint8_t *) decoded_error_vector,
(const uint8_t *) reconstructed_error_vector,
N0 * NUM_DIGITS_GF2X_ELEMENT));
// equal == 1, if the reconstructed error vector match !!!
int decryptOk = (decode_ok == 1 && equal == 1);
memcpy(ss_input, decoded_seed, TRNG_BYTE_LENGTH);
if (decryptOk == 1) {
memcpy(ss_input + sizeof(decoded_seed), tail, TRNG_BYTE_LENGTH);
} else { // decryption failure
memcpy(ss_input + sizeof(decoded_seed), ((const privateKeyNiederreiter_t *)sk)->decryption_failure_secret, TRNG_BYTE_LENGTH);
}
HASH_FUNCTION(ss, ss_input, 2 * TRNG_BYTE_LENGTH);
return 0;
}

View File

@ -4,27 +4,32 @@
#include "gf2x_arith_mod_xPplusOne.h"
#include "niederreiter.h"
#include "qc_ldpc_parameters.h"
#include "randombytes.h"
#include "rng.h"
#include <string.h>
void PQCLEAN_LEDAKEMLT32_LEAKTIME_niederreiter_keygen(publicKeyNiederreiter_t *pk, privateKeyNiederreiter_t *sk, AES_XOF_struct *keys_expander) {
void PQCLEAN_LEDAKEMLT32_LEAKTIME_niederreiter_keygen(publicKeyNiederreiter_t *pk, privateKeyNiederreiter_t *sk) {
POSITION_T HPosOnes[N0][DV]; // sequence of N0 circ block matrices (p x p): Hi
POSITION_T HtrPosOnes[N0][DV]; // Sparse tranposed circulant H
POSITION_T QPosOnes[N0][M]; // Sparse Q, Each row contains the position of the ones of all the blocks of a row of Q as exponent+P*block_position
AES_XOF_struct keys_expander;
POSITION_T HPosOnes[N0][DV];
POSITION_T QPosOnes[N0][M];
POSITION_T LPosOnes[N0][DV * M];
POSITION_T auxPosOnes[DV * M];
unsigned char processedQOnes[N0];
DIGIT Ln0dense[NUM_DIGITS_GF2X_ELEMENT];
DIGIT Ln0Inv[NUM_DIGITS_GF2X_ELEMENT];
int is_L_full = 0;
uint8_t threshold = (DV * M) / 2 + 1; // threshold for round 2
sk->rejections = (int8_t) 0;
DIGIT Ln0dense[NUM_DIGITS_GF2X_ELEMENT] = {0};
DIGIT Ln0Inv[NUM_DIGITS_GF2X_ELEMENT] = {0};
int is_L_full;
int isDFRok;
memset(&keys_expander, 0x00, sizeof(AES_XOF_struct));
randombytes(sk->prng_seed, TRNG_BYTE_LENGTH);
PQCLEAN_LEDAKEMLT32_LEAKTIME_seedexpander_from_trng(&keys_expander, sk->prng_seed);
sk->rejections = (uint8_t) 0;
do {
PQCLEAN_LEDAKEMLT32_LEAKTIME_generateHPosOnes_HtrPosOnes(HPosOnes, HtrPosOnes, keys_expander);
PQCLEAN_LEDAKEMLT32_LEAKTIME_generateQsparse(QPosOnes, keys_expander);
PQCLEAN_LEDAKEMLT32_LEAKTIME_generateHPosOnes(HPosOnes, &keys_expander);
PQCLEAN_LEDAKEMLT32_LEAKTIME_generateQPosOnes(QPosOnes, &keys_expander);
for (int i = 0; i < N0; i++) {
for (int j = 0; j < DV * M; j++) {
LPosOnes[i][j] = INVALID_POS_VALUE;
@ -49,20 +54,21 @@ void PQCLEAN_LEDAKEMLT32_LEAKTIME_niederreiter_keygen(publicKeyNiederreiter_t *p
}
sk->rejections = sk->rejections + 1;
if (is_L_full) {
threshold = PQCLEAN_LEDAKEMLT32_LEAKTIME_DFR_test(LPosOnes);
isDFRok = PQCLEAN_LEDAKEMLT32_LEAKTIME_DFR_test(LPosOnes, &(sk->secondIterThreshold));
}
} while (!is_L_full || threshold == DFR_TEST_FAIL);
} while (!is_L_full || !isDFRok);
sk->rejections = sk->rejections - 1;
sk->threshold = threshold;
memset(Ln0dense, 0x00, sizeof(Ln0dense));
PQCLEAN_LEDAKEMLT32_LEAKTIME_seedexpander(&keys_expander,
sk->decryption_failure_secret,
(unsigned long)TRNG_BYTE_LENGTH);
for (int j = 0; j < DV * M; j++) {
if (LPosOnes[N0 - 1][j] != INVALID_POS_VALUE) {
PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_set_coeff(Ln0dense, LPosOnes[N0 - 1][j], 1);
}
}
memset(Ln0Inv, 0x00, sizeof(Ln0Inv));
PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_mod_inverse(Ln0Inv, Ln0dense);
for (int i = 0; i < N0 - 1; i++) {
PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_mod_mul_dense_to_sparse(pk->Mtr + i * NUM_DIGITS_GF2X_ELEMENT,
@ -76,45 +82,43 @@ void PQCLEAN_LEDAKEMLT32_LEAKTIME_niederreiter_keygen(publicKeyNiederreiter_t *p
}
}
void PQCLEAN_LEDAKEMLT32_LEAKTIME_niederreiter_encrypt(DIGIT syndrome[],
const publicKeyNiederreiter_t *pk,
const DIGIT err[]) {
void PQCLEAN_LEDAKEMLT32_LEAKTIME_niederreiter_encrypt(DIGIT *syndrome, const publicKeyNiederreiter_t *pk, const DIGIT *err) {
int i;
DIGIT saux[NUM_DIGITS_GF2X_ELEMENT];
memset(syndrome, 0x00, NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B);
for (i = 0; i < N0 - 1; i++) {
for (size_t i = 0; i < N0 - 1; i++) {
PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_mod_mul(saux,
pk->Mtr + i * NUM_DIGITS_GF2X_ELEMENT,
err + i * NUM_DIGITS_GF2X_ELEMENT);
PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_mod_add(syndrome, syndrome, saux);
}
PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_mod_add(syndrome, syndrome, err + (N0 - 1)*NUM_DIGITS_GF2X_ELEMENT);
}
int PQCLEAN_LEDAKEMLT32_LEAKTIME_niederreiter_decrypt(DIGIT *err, const privateKeyNiederreiter_t *sk, const DIGIT *syndrome) {
AES_XOF_struct niederreiter_decrypt_expander;
POSITION_T HPosOnes[N0][DV];
POSITION_T HtrPosOnes[N0][DV];
POSITION_T QPosOnes[N0][M];
POSITION_T QtrPosOnes[N0][M];
POSITION_T auxPosOnes[DV * M];
POSITION_T LPosOnes[N0][DV * M];
POSITION_T auxPosOnes[DV * M];
POSITION_T HtrPosOnes[N0][DV];
POSITION_T QtrPosOnes[N0][M];
POSITION_T auxSparse[DV * M];
POSITION_T Ln0trSparse[DV * M];
unsigned char processedQOnes[N0];
unsigned transposed_ones_idx[N0];
DIGIT err_computed[N0 * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B] = {0};
DIGIT privateSyndrome[NUM_DIGITS_GF2X_ELEMENT];
DIGIT mockup_error_vector[N0 * NUM_DIGITS_GF2X_ELEMENT];
unsigned char processedQOnes[N0];
int rejections = sk->rejections;
int currQoneIdx, endQblockIdx;
int decryptOk, err_weight;
PQCLEAN_LEDAKEMLT32_LEAKTIME_seedexpander_from_trng(&niederreiter_decrypt_expander, sk->prng_seed);
do {
PQCLEAN_LEDAKEMLT32_LEAKTIME_generateHPosOnes_HtrPosOnes(HPosOnes, HtrPosOnes, &niederreiter_decrypt_expander);
PQCLEAN_LEDAKEMLT32_LEAKTIME_generateQsparse(QPosOnes, &niederreiter_decrypt_expander);
PQCLEAN_LEDAKEMLT32_LEAKTIME_generateHPosOnes(HPosOnes, &niederreiter_decrypt_expander);
PQCLEAN_LEDAKEMLT32_LEAKTIME_generateQPosOnes(QPosOnes, &niederreiter_decrypt_expander);
for (int i = 0; i < N0; i++) {
for (int j = 0; j < DV * M; j++) {
LPosOnes[i][j] = INVALID_POS_VALUE;
@ -136,19 +140,8 @@ int PQCLEAN_LEDAKEMLT32_LEAKTIME_niederreiter_decrypt(DIGIT *err, const privateK
rejections--;
} while (rejections >= 0);
memset(transposed_ones_idx, 0x00, sizeof(transposed_ones_idx));
for (unsigned source_row_idx = 0; source_row_idx < N0 ; source_row_idx++) {
currQoneIdx = 0; // position in the column of QtrPosOnes[][...]
endQblockIdx = 0;
for (int blockIdx = 0; blockIdx < N0; blockIdx++) {
endQblockIdx += qBlockWeights[source_row_idx][blockIdx];
for (; currQoneIdx < endQblockIdx; currQoneIdx++) {
QtrPosOnes[blockIdx][transposed_ones_idx[blockIdx]] = (P -
QPosOnes[source_row_idx][currQoneIdx]) % P;
transposed_ones_idx[blockIdx]++;
}
}
}
PQCLEAN_LEDAKEMLT32_LEAKTIME_transposeHPosOnes(HtrPosOnes, HPosOnes);
PQCLEAN_LEDAKEMLT32_LEAKTIME_transposeQPosOnes(QtrPosOnes, QPosOnes);
for (int i = 0; i < DV * M; i++) {
Ln0trSparse[i] = INVALID_POS_VALUE;
@ -163,29 +156,36 @@ int PQCLEAN_LEDAKEMLT32_LEAKTIME_niederreiter_decrypt(DIGIT *err, const privateK
DV * M, Ln0trSparse,
DV * M, auxSparse);
}
PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_transpose_in_place_sparse(DV * M, Ln0trSparse);
PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_mod_mul_dense_to_sparse(privateSyndrome, syndrome, Ln0trSparse, DV * M);
/* prepare mockup error vector in case a decoding failure occurs */
memset(mockup_error_vector, 0x00, N0 * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B);
memcpy(mockup_error_vector, syndrome, NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B);
PQCLEAN_LEDAKEMLT32_LEAKTIME_seedexpander(&niederreiter_decrypt_expander,
((unsigned char *) mockup_error_vector) + (NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B),
TRNG_BYTE_LENGTH);
PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_mod_mul_dense_to_sparse(privateSyndrome,
syndrome,
Ln0trSparse,
DV * M);
memset(err, 0x00, N0 * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B);
decryptOk = PQCLEAN_LEDAKEMLT32_LEAKTIME_bf_decoding(err, (const POSITION_T (*)[DV]) HtrPosOnes,
(const POSITION_T (*)[M]) QtrPosOnes, privateSyndrome, sk->threshold);
int decryptOk = 0;
decryptOk = PQCLEAN_LEDAKEMLT32_LEAKTIME_bf_decoding(err_computed,
(const POSITION_T (*)[DV]) HtrPosOnes,
(const POSITION_T (*)[M]) QtrPosOnes,
privateSyndrome, sk->secondIterThreshold);
err_weight = 0;
int err_weight = 0;
for (int i = 0 ; i < N0; i++) {
err_weight += PQCLEAN_LEDAKEMLT32_LEAKTIME_population_count(err + (NUM_DIGITS_GF2X_ELEMENT * i));
err_weight += PQCLEAN_LEDAKEMLT32_LEAKTIME_population_count(err_computed + (NUM_DIGITS_GF2X_ELEMENT * i));
}
decryptOk = decryptOk && (err_weight == NUM_ERRORS_T);
if (!decryptOk) { // TODO: not constant time, replace with cmov?
memcpy(err, mockup_error_vector, N0 * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B);
/* prepare mockup error vector in case a decoding failure occurs */
DIGIT err_mockup[N0 * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B];
memcpy(err_mockup, syndrome, NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B);
memcpy(err_mockup + NUM_DIGITS_GF2X_ELEMENT, sk->decryption_failure_secret, TRNG_BYTE_LENGTH);
memset(((unsigned char *) err_mockup) + (NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B) + TRNG_BYTE_LENGTH, 0x00,
(N0 - 1)*NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B - TRNG_BYTE_LENGTH);
if (!decryptOk) {
memcpy(err, err_mockup, N0 * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B);
} else {
memcpy(err, err_computed, N0 * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B);
}
return decryptOk;

View File

@ -6,24 +6,19 @@
#include "rng.h"
typedef struct {
/* raw entropy extracted from TRNG, will be deterministically expanded into
* H and Q during decryption */
unsigned char prng_seed[TRNG_BYTE_LENGTH];
int8_t rejections;
uint8_t threshold; // for round 2
uint8_t rejections;
uint8_t secondIterThreshold;
uint8_t decryption_failure_secret[TRNG_BYTE_LENGTH];
} privateKeyNiederreiter_t;
typedef struct {
DIGIT Mtr[(N0 - 1)*NUM_DIGITS_GF2X_ELEMENT];
// Dense representation of the matrix M=Ln0*L,
// An array including a sequence of (N0-1) gf2x elements;
// each gf2x element is stored as a binary polynomial(mod x^P+1)
// with P coefficients.
} publicKeyNiederreiter_t;
void PQCLEAN_LEDAKEMLT32_LEAKTIME_niederreiter_keygen(publicKeyNiederreiter_t *pk, privateKeyNiederreiter_t *sk, AES_XOF_struct *keys_expander);
void PQCLEAN_LEDAKEMLT32_LEAKTIME_niederreiter_encrypt(DIGIT syndrome[], const publicKeyNiederreiter_t *pk, const DIGIT *err);
void PQCLEAN_LEDAKEMLT32_LEAKTIME_niederreiter_keygen(publicKeyNiederreiter_t *pk, privateKeyNiederreiter_t *sk);
void PQCLEAN_LEDAKEMLT32_LEAKTIME_niederreiter_encrypt(DIGIT syndrome[], const publicKeyNiederreiter_t *pk, const DIGIT err[]);
int PQCLEAN_LEDAKEMLT32_LEAKTIME_niederreiter_decrypt(DIGIT *err, const privateKeyNiederreiter_t *sk, const DIGIT *syndrome);
#endif

View File

@ -0,0 +1,87 @@
#include "sort.h"
/*
Constant-time uint32_t sorting by Daniel J. Bernstein
Source: https://sorting.cr.yp.to
*/
static void int32_sort(int32 *x, size_t n) {
size_t top, p, q, r, i, j;
if (n < 2) {
return;
}
top = 1;
while (top < n - top) {
top += top;
}
for (p = top; p >= 1; p >>= 1) {
i = 0;
while (i + 2 * p <= n) {
for (j = i; j < i + p; ++j) {
int32_MINMAX(x[j], x[j + p]);
}
i += 2 * p;
}
for (j = i; j < n - p; ++j) {
int32_MINMAX(x[j], x[j + p]);
}
i = 0;
j = 0;
for (q = top; q > p; q >>= 1) {
if (j != i) {
for (;;) {
if (j == n - q) {
goto done;
}
int32 a = x[j + p];
for (r = q; r > p; r >>= 1) {
int32_MINMAX(a, x[j + r]);
}
x[j + p] = a;
++j;
if (j == i + p) {
i += 2 * p;
break;
}
}
}
while (i + p <= n - q) {
for (j = i; j < i + p; ++j) {
int32 a = x[j + p];
for (r = q; r > p; r >>= 1) {
int32_MINMAX(a, x[j + r]);
}
x[j + p] = a;
}
i += 2 * p;
}
/* now i + p > n - q */
j = i;
while (j < n - q) {
int32 a = x[j + p];
for (r = q; r > p; r >>= 1) {
int32_MINMAX(a, x[j + r]);
}
x[j + p] = a;
++j;
}
done:
;
}
}
}
/* can save time by integrating xor loops with int32_sort */
void PQCLEAN_LEDAKEMLT32_LEAKTIME_uint32_sort(uint32_t *x, size_t n) {
size_t j;
for (j = 0; j < n; ++j) {
x[j] ^= 0x80000000;
}
int32_sort((int32_t *) x, n);
for (j = 0; j < n; ++j) {
x[j] ^= 0x80000000;
}
}

View File

@ -0,0 +1,22 @@
#ifndef SORT_H
#define SORT_H
#include <stddef.h>
#include <stdint.h>
#define int32 int32_t
#define int32_MINMAX(a,b) \
do { \
int32 ab = (b) ^ (a); \
int32 c = (b) - (a); \
c ^= ab & (c ^ (b)); \
c >>= 31; \
c &= ab; \
(a) ^= c; \
(b) ^= c; \
} while(0)
void PQCLEAN_LEDAKEMLT32_LEAKTIME_uint32_sort(uint32_t *x, size_t n);
#endif

View File

@ -3,10 +3,10 @@ type: kem
claimed-nist-level: 5
claimed-security: IND-CCA2
length-public-key: 19040
length-secret-key: 42
length-ciphertext: 19040
length-secret-key: 82
length-ciphertext: 19080
length-shared-secret: 64
nistkat-sha256: 9cd9299d20a1c8c242730d3795683a9e87c6bcd0e691dc1fd54cd6a418266c36
nistkat-sha256: 7a8d7c623bd3a8935861ec088e77a6701a254ac521d5e5150dc4537df4da8fd5
principal-submitters:
- Marco Baldi
auxiliary-submitters:
@ -16,4 +16,4 @@ auxiliary-submitters:
- Paolo Santini
implementations:
- name: leaktime
version: 2.?
version: 2.1

View File

@ -1,32 +1,58 @@
#include "H_Q_matrices_generation.h"
#include "gf2x_arith_mod_xPplusOne.h"
void PQCLEAN_LEDAKEMLT52_LEAKTIME_generateHPosOnes_HtrPosOnes(
POSITION_T HPosOnes[N0][DV],
POSITION_T HtrPosOnes[N0][DV],
void PQCLEAN_LEDAKEMLT52_LEAKTIME_generateHPosOnes(POSITION_T HPosOnes[N0][DV],
AES_XOF_struct *keys_expander) {
for (int i = 0; i < N0; i++) {
/* Generate a random block of Htr */
PQCLEAN_LEDAKEMLT52_LEAKTIME_rand_circulant_sparse_block(&HtrPosOnes[i][0], DV, keys_expander);
}
for (int i = 0; i < N0; i++) {
/* Obtain directly the sparse representation of the block of H */
for (int k = 0; k < DV; k++) {
HPosOnes[i][k] = (P - HtrPosOnes[i][k]) % P; /* transposes indexes */
}
PQCLEAN_LEDAKEMLT52_LEAKTIME_rand_circulant_sparse_block(&HPosOnes[i][0],
DV,
keys_expander);
}
}
void PQCLEAN_LEDAKEMLT52_LEAKTIME_generateQsparse(
POSITION_T pos_ones[N0][M],
void PQCLEAN_LEDAKEMLT52_LEAKTIME_generateQPosOnes(POSITION_T QPosOnes[N0][M],
AES_XOF_struct *keys_expander) {
for (int i = 0; i < N0; i++) {
int placed_ones = 0;
for (int j = 0; j < N0; j++) {
PQCLEAN_LEDAKEMLT52_LEAKTIME_rand_circulant_sparse_block(&pos_ones[i][placed_ones],
PQCLEAN_LEDAKEMLT52_LEAKTIME_rand_circulant_sparse_block(&QPosOnes[i][placed_ones],
qBlockWeights[i][j],
keys_expander);
placed_ones += qBlockWeights[i][j];
}
}
}
void PQCLEAN_LEDAKEMLT52_LEAKTIME_transposeHPosOnes(POSITION_T HtrPosOnes[N0][DV], /* output*/
POSITION_T HPosOnes[N0][DV]) {
for (int i = 0; i < N0; i++) {
/* Obtain directly the sparse representation of the block of H */
for (int k = 0; k < DV; k++) {
HtrPosOnes[i][k] = (P - HPosOnes[i][k]) % P; /* transposes indexes */
}// end for k
}
}
void PQCLEAN_LEDAKEMLT52_LEAKTIME_transposeQPosOnes(POSITION_T QtrPosOnes[N0][M], /* output*/
POSITION_T QPosOnes[N0][M]) {
unsigned transposed_ones_idx[N0] = {0x00};
for (unsigned source_row_idx = 0; source_row_idx < N0 ; source_row_idx++) {
int currQoneIdx = 0; // position in the column of QtrPosOnes[][...]
int endQblockIdx = 0;
for (int blockIdx = 0; blockIdx < N0; blockIdx++) {
endQblockIdx += qBlockWeights[source_row_idx][blockIdx];
for (; currQoneIdx < endQblockIdx; currQoneIdx++) {
QtrPosOnes[blockIdx][transposed_ones_idx[blockIdx]] = (P -
QPosOnes[source_row_idx][currQoneIdx]) % P;
transposed_ones_idx[blockIdx]++;
}
}
}
}

View File

@ -5,7 +5,9 @@
#include "qc_ldpc_parameters.h"
#include "rng.h"
void PQCLEAN_LEDAKEMLT52_LEAKTIME_generateHPosOnes_HtrPosOnes(POSITION_T HPosOnes[N0][DV], POSITION_T HtrPosOnes[N0][DV], AES_XOF_struct *niederreiter_keys_expander);
void PQCLEAN_LEDAKEMLT52_LEAKTIME_generateQsparse(POSITION_T pos_ones[N0][M], AES_XOF_struct *niederreiter_keys_expander);
void PQCLEAN_LEDAKEMLT52_LEAKTIME_generateHPosOnes(POSITION_T HPosOnes[N0][DV], AES_XOF_struct *keys_expander);
void PQCLEAN_LEDAKEMLT52_LEAKTIME_generateQPosOnes(POSITION_T QPosOnes[N0][M], AES_XOF_struct *keys_expander);
void PQCLEAN_LEDAKEMLT52_LEAKTIME_transposeHPosOnes(POSITION_T HtrPosOnes[N0][DV], POSITION_T HPosOnes[N0][DV]);
void PQCLEAN_LEDAKEMLT52_LEAKTIME_transposeQPosOnes(POSITION_T QtrPosOnes[N0][M], POSITION_T QPosOnes[N0][M]);
#endif

View File

@ -3,10 +3,10 @@
LIB=libledakemlt52_leaktime.a
HEADERS=api.h bf_decoding.h dfr_test.h gf2x_arith_mod_xPplusOne.h \
gf2x_arith.h H_Q_matrices_generation.h \
niederreiter.h qc_ldpc_parameters.h rng.h
niederreiter.h qc_ldpc_parameters.h rng.h sort.h
OBJECTS=bf_decoding.o dfr_test.o gf2x_arith_mod_xPplusOne.o \
gf2x_arith.o H_Q_matrices_generation.o kem.o niederreiter.o rng.o
gf2x_arith.o H_Q_matrices_generation.o kem.o niederreiter.o rng.o sort.o
CFLAGS=-O3 -Wall -Werror -Wextra -Wvla -Wpedantic -Wmissing-prototypes -std=c99 \
-I../../../common $(EXTRAFLAGS)

View File

@ -2,7 +2,7 @@
# nmake /f Makefile.Microsoft_nmake
LIBRARY=libledakemlt52_leaktime.lib
OBJECTS=bf_decoding.obj dfr_test.obj gf2x_arith_mod_xPplusOne.obj gf2x_arith.obj H_Q_matrices_generation.obj kem.obj niederreiter.obj rng.obj
OBJECTS=bf_decoding.obj dfr_test.obj gf2x_arith_mod_xPplusOne.obj gf2x_arith.obj H_Q_matrices_generation.obj kem.obj niederreiter.obj rng.obj sort.obj
CFLAGS=/nologo /I ..\..\..\common /W4 /WX

View File

@ -3,9 +3,9 @@
#include <stdint.h>
#define PQCLEAN_LEDAKEMLT52_LEAKTIME_CRYPTO_SECRETKEYBYTES 42
#define PQCLEAN_LEDAKEMLT52_LEAKTIME_CRYPTO_SECRETKEYBYTES 82
#define PQCLEAN_LEDAKEMLT52_LEAKTIME_CRYPTO_PUBLICKEYBYTES 19040
#define PQCLEAN_LEDAKEMLT52_LEAKTIME_CRYPTO_CIPHERTEXTBYTES 19040
#define PQCLEAN_LEDAKEMLT52_LEAKTIME_CRYPTO_CIPHERTEXTBYTES 19080
#define PQCLEAN_LEDAKEMLT52_LEAKTIME_CRYPTO_BYTES 64
#define PQCLEAN_LEDAKEMLT52_LEAKTIME_CRYPTO_ALGNAME "LEDAKEMLT52"

View File

@ -2,70 +2,45 @@
#include "dfr_test.h"
#include "gf2x_arith_mod_xPplusOne.h"
#include "qc_ldpc_parameters.h"
#include "sort.h"
#include <string.h>
/* Tests if the current code attains the desired DFR. If that is the case,
* computes the threshold for the second iteration of the decoder and returns this values
* (max DV * M), on failure it returns 255 >> DV * M */
uint8_t PQCLEAN_LEDAKEMLT52_LEAKTIME_DFR_test(POSITION_T LSparse[N0][DV * M]) {
int PQCLEAN_LEDAKEMLT52_LEAKTIME_DFR_test(POSITION_T LSparse[N0][DV * M], uint8_t *secondIterThreshold) {
POSITION_T LSparse_loc[N0][DV * M];
POSITION_T rotated_column[DV * M];
/* Gamma matrix: an N0 x N0 block circulant matrix with block size p
* gamma[a][b][c] stores the intersection of the first column of the a-th
* block of L with the c-th column of the b-th block of L.
* Gamma computation can be accelerated employing symmetry and QC properties */
unsigned int gamma[N0][N0][P] = {{{0}}};
POSITION_T LSparse_loc[N0][DV * M]; /* vector of N_0 sparse blocks */
int gamma[N0][N0][P] = {{{0}}};
int maxMut[N0], maxMutMinusOne[N0];
int allBlockMaxSumst, allBlockMaxSumstMinusOne;
unsigned int gammaHist[N0][DV * M + 1] = {{0}};
unsigned int maxMut[N0], maxMutMinusOne[N0];
unsigned int firstidx, secondidx, intersectionval;
unsigned int allBlockMaxSumst, allBlockMaxSumstMinusOne;
unsigned int toAdd, histIdx;
/*transpose blocks of L, we need its columns */
for (int i = 0; i < N0; i++) {
for (int j = 0; j < DV * M; j++) {
if (LSparse[i][j] != 0) {
LSparse_loc[i][j] = (P - LSparse[i][j]) ;
}
}
PQCLEAN_LEDAKEMLT52_LEAKTIME_quicksort_sparse(LSparse_loc[i]);
PQCLEAN_LEDAKEMLT52_LEAKTIME_uint32_sort(LSparse_loc[i], DV * M);
}
for (int i = 0; i < N0; i++ ) {
for (int j = 0; j < N0; j++ ) {
for (int k = 0; k < P; k++) {
/* compute the rotated sparse column needed */
for (int idxToRotate = 0; idxToRotate < (DV * M); idxToRotate++) {
rotated_column[idxToRotate] = (LSparse_loc[j][idxToRotate] + k) % P;
}
PQCLEAN_LEDAKEMLT52_LEAKTIME_quicksort_sparse(rotated_column);
/* compute the intersection amount */
firstidx = 0, secondidx = 0;
intersectionval = 0;
while ( (firstidx < DV * M) && (secondidx < DV * M) ) {
if ( LSparse_loc[i][firstidx] == rotated_column[secondidx] ) {
intersectionval++;
firstidx++;
secondidx++;
} else if ( LSparse_loc[i][firstidx] > rotated_column[secondidx] ) {
secondidx++;
} else { /*if ( LSparse_loc[i][firstidx] < rotated_column[secondidx] ) */
firstidx++;
for (int k = 0; k < (DV * M); k++) {
for (int l = 0; l < (DV * M); l++) {
gamma[i][j][ (P + LSparse_loc[i][k] - LSparse_loc[j][l]) % P ]++;
}
}
}
}
gamma[i][j][k] = intersectionval;
}
}
}
for (int i = 0; i < N0; i++ ) {
for (int j = 0; j < N0; j++ ) {
gamma[i][j][0] = 0;
}
}
/* build histogram of values in gamma */
for (int i = 0; i < N0; i++ ) {
for (int j = 0; j < N0; j++ ) {
@ -77,9 +52,9 @@ uint8_t PQCLEAN_LEDAKEMLT52_LEAKTIME_DFR_test(POSITION_T LSparse[N0][DV * M]) {
for (int gammaBlockRowIdx = 0; gammaBlockRowIdx < N0; gammaBlockRowIdx++) {
toAdd = T_BAR - 1;
unsigned int toAdd = T_BAR - 1;
maxMutMinusOne[gammaBlockRowIdx] = 0;
histIdx = DV * M;
unsigned int histIdx = DV * M;
while ( (histIdx > 0) && (toAdd > 0)) {
if (gammaHist[gammaBlockRowIdx][histIdx] > toAdd ) {
maxMutMinusOne[gammaBlockRowIdx] += histIdx * toAdd;
@ -93,7 +68,6 @@ uint8_t PQCLEAN_LEDAKEMLT52_LEAKTIME_DFR_test(POSITION_T LSparse[N0][DV * M]) {
maxMut[gammaBlockRowIdx] = histIdx + maxMutMinusOne[gammaBlockRowIdx];
}
/*seek max values across all gamma blocks */
allBlockMaxSumst = maxMut[0];
allBlockMaxSumstMinusOne = maxMutMinusOne[0];
@ -106,7 +80,8 @@ uint8_t PQCLEAN_LEDAKEMLT52_LEAKTIME_DFR_test(POSITION_T LSparse[N0][DV * M]) {
allBlockMaxSumstMinusOne;
}
if (DV * M > (allBlockMaxSumstMinusOne + allBlockMaxSumst)) {
return (uint8_t) allBlockMaxSumst + 1;
*secondIterThreshold = allBlockMaxSumst + 1;
return 1;
}
return DFR_TEST_FAIL;
return 0;
}

View File

@ -1,8 +1,6 @@
#ifndef DFR_TEST_H
#define DFR_TEST_H
#define DFR_TEST_FAIL (255)
uint8_t PQCLEAN_LEDAKEMLT52_LEAKTIME_DFR_test(POSITION_T LSparse[N0][DV * M]);
int PQCLEAN_LEDAKEMLT52_LEAKTIME_DFR_test(POSITION_T LSparse[N0][DV * M], uint8_t *secondIterThreshold);
#endif

View File

@ -1,5 +1,6 @@
#include "gf2x_arith_mod_xPplusOne.h"
#include "rng.h"
#include "sort.h"
#include <string.h> // memcpy(...), memset(...)
@ -62,81 +63,15 @@ void PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_mod_add(DIGIT Res[], const DIGIT A[], con
PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_add(Res, A, B, NUM_DIGITS_GF2X_ELEMENT);
}
static int partition(POSITION_T arr[], int lo, int hi) {
POSITION_T x = arr[hi];
POSITION_T tmp;
int i = (lo - 1);
for (int j = lo; j <= hi - 1; j++) {
if (arr[j] <= x) {
i++;
tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}
tmp = arr[i + 1];
arr[i + 1] = arr[hi];
arr[hi] = tmp;
return i + 1;
}
void PQCLEAN_LEDAKEMLT52_LEAKTIME_quicksort_sparse(POSITION_T Res[]) {
int stack[DV * M];
int hi, lo, pivot, tos = -1;
stack[++tos] = 0;
stack[++tos] = (DV * M) - 1;
while (tos >= 0 ) {
hi = stack[tos--];
lo = stack[tos--];
pivot = partition(Res, lo, hi);
if ( (pivot - 1) > lo) {
stack[++tos] = lo;
stack[++tos] = pivot - 1;
}
if ( (pivot + 1) < hi) {
stack[++tos] = pivot + 1;
stack[++tos] = hi;
}
}
}
static void gf2x_mod(DIGIT out[], const DIGIT in[]) {
DIGIT aux[NUM_DIGITS_GF2X_ELEMENT + 1];
int i, j, posTrailingBit, maskOffset;
DIGIT mask, aux[2 * NUM_DIGITS_GF2X_ELEMENT];
memcpy(aux, in, 2 * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B);
memset(out, 0x00, NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B);
for (i = 0; i < (2 * NUM_DIGITS_GF2X_ELEMENT) - NUM_DIGITS_GF2X_MODULUS; i += 1) {
for (j = DIGIT_SIZE_b - 1; j >= 0; j--) {
mask = ((DIGIT)0x1) << j;
if (aux[i] & mask) {
aux[i] ^= mask;
posTrailingBit = (DIGIT_SIZE_b - 1 - j) + i * DIGIT_SIZE_b + P;
maskOffset = (DIGIT_SIZE_b - 1 - (posTrailingBit % DIGIT_SIZE_b));
mask = (DIGIT) 0x1 << maskOffset;
aux[posTrailingBit / DIGIT_SIZE_b] ^= mask;
}
}
}
for (j = DIGIT_SIZE_b - 1; j >= MSb_POSITION_IN_MSB_DIGIT_OF_MODULUS; j--) {
mask = ((DIGIT)0x1) << j;
if (aux[i] & mask) {
aux[i] ^= mask;
posTrailingBit = (DIGIT_SIZE_b - 1 - j) + i * DIGIT_SIZE_b + P;
maskOffset = (DIGIT_SIZE_b - 1 - (posTrailingBit % DIGIT_SIZE_b));
mask = (DIGIT) 0x1 << maskOffset;
aux[posTrailingBit / DIGIT_SIZE_b] ^= mask;
}
}
for (i = 0; i < NUM_DIGITS_GF2X_ELEMENT; i++) {
out[NUM_DIGITS_GF2X_ELEMENT - 1 - i] = aux[2 * NUM_DIGITS_GF2X_ELEMENT - 1 - i];
}
memcpy(aux, in, (NUM_DIGITS_GF2X_ELEMENT + 1)*DIGIT_SIZE_B);
PQCLEAN_LEDAKEMLT52_LEAKTIME_right_bit_shift_n(NUM_DIGITS_GF2X_ELEMENT + 1, aux,
MSb_POSITION_IN_MSB_DIGIT_OF_MODULUS);
PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_add(out, aux + 1, in + NUM_DIGITS_GF2X_ELEMENT,
NUM_DIGITS_GF2X_ELEMENT);
out[0] &= ((DIGIT)1 << MSb_POSITION_IN_MSB_DIGIT_OF_MODULUS) - 1;
}
static void left_bit_shift(const int length, DIGIT in[]) {
@ -331,16 +266,13 @@ void PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_mod_mul(DIGIT Res[], const DIGIT A[], con
/*PRE: the representation of the sparse coefficients is sorted in increasing
order of the coefficients themselves */
void PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_mod_mul_dense_to_sparse(
DIGIT Res[],
const DIGIT dense[],
void PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_mod_mul_dense_to_sparse(DIGIT Res[], const DIGIT dense[],
POSITION_T sparse[], unsigned int nPos) {
DIGIT aux[2 * NUM_DIGITS_GF2X_ELEMENT] = {0x00};
DIGIT resDouble[2 * NUM_DIGITS_GF2X_ELEMENT] = {0x00};
memcpy(aux + NUM_DIGITS_GF2X_ELEMENT, dense, NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B);
memcpy(resDouble + NUM_DIGITS_GF2X_ELEMENT, dense,
NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B);
memcpy(resDouble + NUM_DIGITS_GF2X_ELEMENT, dense, NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B);
if (sparse[0] != INVALID_POS_VALUE) {
left_bit_shift_wide_n(2 * NUM_DIGITS_GF2X_ELEMENT, resDouble, sparse[0]);
@ -380,15 +312,15 @@ void PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_transpose_in_place_sparse(int sizeA, POSI
}
void PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_mod_mul_sparse(size_t sizeR, POSITION_T Res[],
size_t sizeA, const POSITION_T A[],
size_t sizeB, const POSITION_T B[]) {
void PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_mod_mul_sparse(int sizeR, POSITION_T Res[],
int sizeA, const POSITION_T A[],
int sizeB, const POSITION_T B[]) {
/* compute all the coefficients, filling invalid positions with P*/
size_t lastFilledPos = 0;
for (size_t i = 0 ; i < sizeA ; i++) {
for (size_t j = 0 ; j < sizeB ; j++) {
uint32_t prod = A[i] + B[j];
int lastFilledPos = 0;
for (int i = 0 ; i < sizeA ; i++) {
for (int j = 0 ; j < sizeB ; j++) {
uint32_t prod = ((uint32_t) A[i]) + ((uint32_t) B[j]);
prod = ( (prod >= P) ? prod - P : prod);
if ((A[i] != INVALID_POS_VALUE) &&
(B[j] != INVALID_POS_VALUE)) {
@ -403,12 +335,12 @@ void PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_mod_mul_sparse(size_t sizeR, POSITION_T R
Res[lastFilledPos] = INVALID_POS_VALUE;
lastFilledPos++;
}
PQCLEAN_LEDAKEMLT52_LEAKTIME_quicksort_sparse(Res);
PQCLEAN_LEDAKEMLT52_LEAKTIME_uint32_sort(Res, sizeR);
/* eliminate duplicates */
POSITION_T lastReadPos = Res[0];
int duplicateCount;
size_t write_idx = 0;
size_t read_idx = 0;
int write_idx = 0;
int read_idx = 0;
while (read_idx < sizeR && Res[read_idx] != INVALID_POS_VALUE) {
lastReadPos = Res[read_idx];
read_idx++;
@ -529,8 +461,7 @@ void PQCLEAN_LEDAKEMLT52_LEAKTIME_rand_circulant_sparse_block(POSITION_T *pos_on
}
/* Returns random weight-t circulant block */
void PQCLEAN_LEDAKEMLT52_LEAKTIME_rand_circulant_blocks_sequence(
DIGIT sequence[N0 * NUM_DIGITS_GF2X_ELEMENT],
void PQCLEAN_LEDAKEMLT52_LEAKTIME_rand_circulant_blocks_sequence(DIGIT sequence[N0 * NUM_DIGITS_GF2X_ELEMENT],
AES_XOF_struct *seed_expander_ctx) {
int rndPos[NUM_ERRORS_T], duplicated, counter = 0;
@ -561,6 +492,39 @@ void PQCLEAN_LEDAKEMLT52_LEAKTIME_rand_circulant_blocks_sequence(
}
void PQCLEAN_LEDAKEMLT52_LEAKTIME_rand_error_pos(POSITION_T errorPos[NUM_ERRORS_T],
AES_XOF_struct *seed_expander_ctx) {
int duplicated, counter = 0;
while (counter < NUM_ERRORS_T) {
uint32_t p = rand_range(N0 * NUM_BITS_GF2X_ELEMENT, P_BITS, seed_expander_ctx);
duplicated = 0;
for (int j = 0; j < counter; j++) if (errorPos[j] == p) {
duplicated = 1;
}
if (duplicated == 0) {
errorPos[counter] = p;
counter++;
}
}
}
void PQCLEAN_LEDAKEMLT52_LEAKTIME_expand_error(DIGIT sequence[N0 * NUM_DIGITS_GF2X_ELEMENT],
POSITION_T errorPos[NUM_ERRORS_T]) {
memset(sequence, 0x00, N0 * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B);
for (int j = 0; j < NUM_ERRORS_T; j++) {
int polyIndex = errorPos[j] / P;
int exponent = errorPos[j] % P;
PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_set_coeff( sequence + NUM_DIGITS_GF2X_ELEMENT * polyIndex, exponent,
( (DIGIT) 1));
}
}
void PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_tobytes(uint8_t *bytes, const DIGIT *poly) {
size_t i, j;
for (i = 0; i < NUM_DIGITS_GF2X_ELEMENT; i++) {

View File

@ -7,13 +7,13 @@
#include "rng.h"
#define NUM_BITS_GF2X_ELEMENT (P) // 152267
#define NUM_DIGITS_GF2X_ELEMENT ((P+DIGIT_SIZE_b-1)/DIGIT_SIZE_b) // 2380
#define NUM_DIGITS_GF2X_ELEMENT ((P+DIGIT_SIZE_b-1)/DIGIT_SIZE_b)
#define MSb_POSITION_IN_MSB_DIGIT_OF_ELEMENT ((P % DIGIT_SIZE_b) ? (P % DIGIT_SIZE_b)-1 : DIGIT_SIZE_b-1)
#define NUM_BITS_GF2X_MODULUS (P+1)
#define NUM_DIGITS_GF2X_MODULUS ((P+1+DIGIT_SIZE_b-1)/DIGIT_SIZE_b) // 2380
#define NUM_DIGITS_GF2X_MODULUS ((P+1+DIGIT_SIZE_b-1)/DIGIT_SIZE_b)
#define MSb_POSITION_IN_MSB_DIGIT_OF_MODULUS (P-DIGIT_SIZE_b*(NUM_DIGITS_GF2X_MODULUS-1))
#define INVALID_POS_VALUE (P)
#define P_BITS (18) // log_2(p) = 17.216243783
#define P_BITS (18)
void PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_copy(DIGIT dest[], const DIGIT in[]);
DIGIT PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_get_coeff(const DIGIT poly[], unsigned int exponent);
@ -21,17 +21,19 @@ void PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_set_coeff(DIGIT poly[], unsigned int expo
void PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_toggle_coeff(DIGIT poly[], unsigned int exponent);
int PQCLEAN_LEDAKEMLT52_LEAKTIME_population_count(DIGIT *poly);
void PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_mod_add(DIGIT Res[], const DIGIT A[], const DIGIT B[]);
void PQCLEAN_LEDAKEMLT52_LEAKTIME_quicksort_sparse(POSITION_T Res[]);
void PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_mod_mul(DIGIT Res[], const DIGIT A[], const DIGIT B[]);
void PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_transpose_in_place(DIGIT A[]);
void PQCLEAN_LEDAKEMLT52_LEAKTIME_rand_circulant_sparse_block(POSITION_T *pos_ones, int countOnes, AES_XOF_struct *seed_expander_ctx);
void PQCLEAN_LEDAKEMLT52_LEAKTIME_rand_circulant_blocks_sequence(DIGIT *sequence, AES_XOF_struct *seed_expander_ctx);
void PQCLEAN_LEDAKEMLT52_LEAKTIME_rand_error_pos(POSITION_T errorPos[NUM_ERRORS_T], AES_XOF_struct *seed_expander_ctx);
void PQCLEAN_LEDAKEMLT52_LEAKTIME_expand_error(DIGIT sequence[N0 * NUM_DIGITS_GF2X_ELEMENT], POSITION_T errorPos[NUM_ERRORS_T]);
void PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_mod_add_sparse(int sizeR, POSITION_T Res[], int sizeA, const POSITION_T A[], int sizeB, const POSITION_T B[]);
void PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_transpose_in_place_sparse(int sizeA, POSITION_T A[]);
int PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_mod_inverse(DIGIT out[], const DIGIT in[]);
void PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_mod_mul_sparse(size_t sizeR, POSITION_T Res[], size_t sizeA, const POSITION_T A[], size_t sizeB, const POSITION_T B[]);
void PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_mod_mul_sparse(int sizeR, POSITION_T Res[], int sizeA, const POSITION_T A[], int sizeB, const POSITION_T B[]);
void PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_mod_mul_dense_to_sparse(DIGIT Res[], const DIGIT dense[], POSITION_T sparse[], unsigned int nPos);
void PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_tobytes(uint8_t *bytes, const DIGIT *poly);
void PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_frombytes(DIGIT *poly, const uint8_t *poly_bytes);
#endif

View File

@ -5,6 +5,7 @@
#include <string.h>
/*
static void pack_pk(uint8_t *pk_bytes, publicKeyNiederreiter_t *pk) {
size_t i;
for (i = 0; i < N0 - 1; i++) {
@ -36,57 +37,113 @@ static void pack_error(uint8_t *error_bytes, DIGIT *error_digits) {
error_digits + i * NUM_DIGITS_GF2X_ELEMENT);
}
}
*/
/* Generates a keypair - pk is the public key and sk is the secret key. */
int PQCLEAN_LEDAKEMLT52_LEAKTIME_crypto_kem_keypair(unsigned char *pk, unsigned char *sk) {
AES_XOF_struct niederreiter_keys_expander;
publicKeyNiederreiter_t pk_nie;
/* IND-CCA2 Keygen */
int PQCLEAN_LEDAKEMLT52_LEAKTIME_crypto_kem_keypair(uint8_t *pk, uint8_t *sk) {
randombytes(((privateKeyNiederreiter_t *)sk)->prng_seed, TRNG_BYTE_LENGTH);
PQCLEAN_LEDAKEMLT52_LEAKTIME_seedexpander_from_trng(&niederreiter_keys_expander, ((privateKeyNiederreiter_t *)sk)->prng_seed);
PQCLEAN_LEDAKEMLT52_LEAKTIME_niederreiter_keygen(&pk_nie, (privateKeyNiederreiter_t *) sk, &niederreiter_keys_expander);
pack_pk(pk, &pk_nie);
PQCLEAN_LEDAKEMLT52_LEAKTIME_niederreiter_keygen((publicKeyNiederreiter_t *) pk,
(privateKeyNiederreiter_t *) sk);
return 0;
}
/* Encrypt - pk is the public key, ct is a key encapsulation message
(ciphertext), ss is the shared secret.*/
int PQCLEAN_LEDAKEMLT52_LEAKTIME_crypto_kem_enc(unsigned char *ct, unsigned char *ss, const unsigned char *pk) {
AES_XOF_struct niederreiter_encap_key_expander;
unsigned char encapsulated_key_seed[TRNG_BYTE_LENGTH];
/* IND-CCA2 Encapsulation */
int PQCLEAN_LEDAKEMLT52_LEAKTIME_crypto_kem_enc(uint8_t *ct, uint8_t *ss, const uint8_t *pk) {
AES_XOF_struct hashedAndTruncatedSeed_expander;
POSITION_T errorPos[NUM_ERRORS_T];
DIGIT error_vector[N0 * NUM_DIGITS_GF2X_ELEMENT];
uint8_t error_bytes[N0 * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B];
DIGIT syndrome[NUM_DIGITS_GF2X_ELEMENT];
publicKeyNiederreiter_t pk_nie;
uint8_t seed[TRNG_BYTE_LENGTH];
uint8_t ss_input[2 * TRNG_BYTE_LENGTH] = {0};
uint8_t hashedSeed[HASH_BYTE_LENGTH];
uint8_t hashedAndTruncatedSeed[TRNG_BYTE_LENGTH] = {0};
uint8_t hashedErrorVector[HASH_BYTE_LENGTH];
uint8_t hashedAndTruncatedErrorVector[TRNG_BYTE_LENGTH] = {0};
uint8_t maskedSeed[TRNG_BYTE_LENGTH];
randombytes(encapsulated_key_seed, TRNG_BYTE_LENGTH);
unpack_pk(&pk_nie, pk);
randombytes(seed, TRNG_BYTE_LENGTH);
memcpy(ss_input, seed, TRNG_BYTE_LENGTH);
HASH_FUNCTION(ss, ss_input, 2 * TRNG_BYTE_LENGTH);
HASH_FUNCTION(hashedSeed, seed, TRNG_BYTE_LENGTH);
PQCLEAN_LEDAKEMLT52_LEAKTIME_seedexpander_from_trng(&niederreiter_encap_key_expander, encapsulated_key_seed);
PQCLEAN_LEDAKEMLT52_LEAKTIME_rand_circulant_blocks_sequence(error_vector, &niederreiter_encap_key_expander);
pack_error(error_bytes, error_vector);
HASH_FUNCTION(ss, error_bytes, (N0 * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B));
PQCLEAN_LEDAKEMLT52_LEAKTIME_niederreiter_encrypt(syndrome, &pk_nie, error_vector);
memcpy(hashedAndTruncatedSeed, hashedSeed, TRNG_BYTE_LENGTH);
pack_ct(ct, syndrome);
memset(&hashedAndTruncatedSeed_expander, 0x00, sizeof(AES_XOF_struct));
PQCLEAN_LEDAKEMLT52_LEAKTIME_seedexpander_from_trng(&hashedAndTruncatedSeed_expander, hashedAndTruncatedSeed);
PQCLEAN_LEDAKEMLT52_LEAKTIME_rand_error_pos(errorPos, &hashedAndTruncatedSeed_expander);
PQCLEAN_LEDAKEMLT52_LEAKTIME_expand_error(error_vector, errorPos);
HASH_FUNCTION(hashedErrorVector, (const uint8_t *) error_vector, (N0 * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B));
memcpy(hashedAndTruncatedErrorVector, hashedErrorVector, TRNG_BYTE_LENGTH);
for (int i = 0; i < TRNG_BYTE_LENGTH; ++i) {
maskedSeed[i] = seed[i] ^ hashedAndTruncatedErrorVector[i];
}
PQCLEAN_LEDAKEMLT52_LEAKTIME_niederreiter_encrypt((DIGIT *) ct, (const publicKeyNiederreiter_t *)pk, error_vector);
memcpy(ct + (NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B), maskedSeed, TRNG_BYTE_LENGTH);
return 0;
}
/* Decrypt - ct is a key encapsulation message (ciphertext), sk is the private
key, ss is the shared secret */
int PQCLEAN_LEDAKEMLT52_LEAKTIME_crypto_kem_dec(unsigned char *ss, const unsigned char *ct, const unsigned char *sk) {
/* INDCCA2 Decapsulation */
int PQCLEAN_LEDAKEMLT52_LEAKTIME_crypto_kem_dec(uint8_t *ss, const uint8_t *ct, const uint8_t *sk) {
AES_XOF_struct hashedAndTruncatedSeed_expander;
POSITION_T reconstructed_errorPos[NUM_ERRORS_T];
DIGIT reconstructed_error_vector[N0 * NUM_DIGITS_GF2X_ELEMENT];
DIGIT decoded_error_vector[N0 * NUM_DIGITS_GF2X_ELEMENT];
uint8_t decoded_error_bytes[N0 * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B];
DIGIT syndrome[NUM_DIGITS_GF2X_ELEMENT];
uint8_t hashedErrorVector[HASH_BYTE_LENGTH];
uint8_t hashedAndTruncatedErrorVector[TRNG_BYTE_LENGTH] = {0};
uint8_t decoded_seed[TRNG_BYTE_LENGTH];
uint8_t hashed_decoded_seed[HASH_BYTE_LENGTH];
uint8_t hashedAndTruncated_decoded_seed[TRNG_BYTE_LENGTH] = {0};
uint8_t ss_input[2 * TRNG_BYTE_LENGTH], tail[TRNG_BYTE_LENGTH] = {0};
unpack_ct(syndrome, ct);
PQCLEAN_LEDAKEMLT52_LEAKTIME_niederreiter_decrypt(decoded_error_vector, (privateKeyNiederreiter_t *)sk, syndrome);
pack_error(decoded_error_bytes, decoded_error_vector);
HASH_FUNCTION(ss, decoded_error_bytes, (N0 * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B));
int decode_ok = PQCLEAN_LEDAKEMLT52_LEAKTIME_niederreiter_decrypt(decoded_error_vector,
(const privateKeyNiederreiter_t *)sk,
(DIGIT *)ct);
HASH_FUNCTION(hashedErrorVector,
(const uint8_t *) decoded_error_vector,
(N0 * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B));
memcpy(hashedAndTruncatedErrorVector, hashedErrorVector, TRNG_BYTE_LENGTH);
for (int i = 0; i < TRNG_BYTE_LENGTH; ++i) {
decoded_seed[i] = ct[(NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B) + i] ^
hashedAndTruncatedErrorVector[i];
}
HASH_FUNCTION(hashed_decoded_seed, decoded_seed, TRNG_BYTE_LENGTH);
memcpy(hashedAndTruncated_decoded_seed, hashed_decoded_seed, TRNG_BYTE_LENGTH);
memset(&hashedAndTruncatedSeed_expander, 0x00, sizeof(AES_XOF_struct));
PQCLEAN_LEDAKEMLT52_LEAKTIME_seedexpander_from_trng(&hashedAndTruncatedSeed_expander,
hashed_decoded_seed);
PQCLEAN_LEDAKEMLT52_LEAKTIME_rand_error_pos(reconstructed_errorPos, &hashedAndTruncatedSeed_expander);
PQCLEAN_LEDAKEMLT52_LEAKTIME_expand_error(reconstructed_error_vector, reconstructed_errorPos);
int equal = (0 == memcmp((const uint8_t *) decoded_error_vector,
(const uint8_t *) reconstructed_error_vector,
N0 * NUM_DIGITS_GF2X_ELEMENT));
// equal == 1, if the reconstructed error vector match !!!
int decryptOk = (decode_ok == 1 && equal == 1);
memcpy(ss_input, decoded_seed, TRNG_BYTE_LENGTH);
if (decryptOk == 1) {
memcpy(ss_input + sizeof(decoded_seed), tail, TRNG_BYTE_LENGTH);
} else { // decryption failure
memcpy(ss_input + sizeof(decoded_seed), ((const privateKeyNiederreiter_t *)sk)->decryption_failure_secret, TRNG_BYTE_LENGTH);
}
HASH_FUNCTION(ss, ss_input, 2 * TRNG_BYTE_LENGTH);
return 0;
}

View File

@ -4,27 +4,32 @@
#include "gf2x_arith_mod_xPplusOne.h"
#include "niederreiter.h"
#include "qc_ldpc_parameters.h"
#include "randombytes.h"
#include "rng.h"
#include <string.h>
void PQCLEAN_LEDAKEMLT52_LEAKTIME_niederreiter_keygen(publicKeyNiederreiter_t *pk, privateKeyNiederreiter_t *sk, AES_XOF_struct *keys_expander) {
void PQCLEAN_LEDAKEMLT52_LEAKTIME_niederreiter_keygen(publicKeyNiederreiter_t *pk, privateKeyNiederreiter_t *sk) {
POSITION_T HPosOnes[N0][DV]; // sequence of N0 circ block matrices (p x p): Hi
POSITION_T HtrPosOnes[N0][DV]; // Sparse tranposed circulant H
POSITION_T QPosOnes[N0][M]; // Sparse Q, Each row contains the position of the ones of all the blocks of a row of Q as exponent+P*block_position
AES_XOF_struct keys_expander;
POSITION_T HPosOnes[N0][DV];
POSITION_T QPosOnes[N0][M];
POSITION_T LPosOnes[N0][DV * M];
POSITION_T auxPosOnes[DV * M];
unsigned char processedQOnes[N0];
DIGIT Ln0dense[NUM_DIGITS_GF2X_ELEMENT];
DIGIT Ln0Inv[NUM_DIGITS_GF2X_ELEMENT];
int is_L_full = 0;
uint8_t threshold = (DV * M) / 2 + 1; // threshold for round 2
sk->rejections = (int8_t) 0;
DIGIT Ln0dense[NUM_DIGITS_GF2X_ELEMENT] = {0};
DIGIT Ln0Inv[NUM_DIGITS_GF2X_ELEMENT] = {0};
int is_L_full;
int isDFRok;
memset(&keys_expander, 0x00, sizeof(AES_XOF_struct));
randombytes(sk->prng_seed, TRNG_BYTE_LENGTH);
PQCLEAN_LEDAKEMLT52_LEAKTIME_seedexpander_from_trng(&keys_expander, sk->prng_seed);
sk->rejections = (uint8_t) 0;
do {
PQCLEAN_LEDAKEMLT52_LEAKTIME_generateHPosOnes_HtrPosOnes(HPosOnes, HtrPosOnes, keys_expander);
PQCLEAN_LEDAKEMLT52_LEAKTIME_generateQsparse(QPosOnes, keys_expander);
PQCLEAN_LEDAKEMLT52_LEAKTIME_generateHPosOnes(HPosOnes, &keys_expander);
PQCLEAN_LEDAKEMLT52_LEAKTIME_generateQPosOnes(QPosOnes, &keys_expander);
for (int i = 0; i < N0; i++) {
for (int j = 0; j < DV * M; j++) {
LPosOnes[i][j] = INVALID_POS_VALUE;
@ -49,20 +54,21 @@ void PQCLEAN_LEDAKEMLT52_LEAKTIME_niederreiter_keygen(publicKeyNiederreiter_t *p
}
sk->rejections = sk->rejections + 1;
if (is_L_full) {
threshold = PQCLEAN_LEDAKEMLT52_LEAKTIME_DFR_test(LPosOnes);
isDFRok = PQCLEAN_LEDAKEMLT52_LEAKTIME_DFR_test(LPosOnes, &(sk->secondIterThreshold));
}
} while (!is_L_full || threshold == DFR_TEST_FAIL);
} while (!is_L_full || !isDFRok);
sk->rejections = sk->rejections - 1;
sk->threshold = threshold;
memset(Ln0dense, 0x00, sizeof(Ln0dense));
PQCLEAN_LEDAKEMLT52_LEAKTIME_seedexpander(&keys_expander,
sk->decryption_failure_secret,
(unsigned long)TRNG_BYTE_LENGTH);
for (int j = 0; j < DV * M; j++) {
if (LPosOnes[N0 - 1][j] != INVALID_POS_VALUE) {
PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_set_coeff(Ln0dense, LPosOnes[N0 - 1][j], 1);
}
}
memset(Ln0Inv, 0x00, sizeof(Ln0Inv));
PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_mod_inverse(Ln0Inv, Ln0dense);
for (int i = 0; i < N0 - 1; i++) {
PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_mod_mul_dense_to_sparse(pk->Mtr + i * NUM_DIGITS_GF2X_ELEMENT,
@ -76,45 +82,43 @@ void PQCLEAN_LEDAKEMLT52_LEAKTIME_niederreiter_keygen(publicKeyNiederreiter_t *p
}
}
void PQCLEAN_LEDAKEMLT52_LEAKTIME_niederreiter_encrypt(DIGIT syndrome[],
const publicKeyNiederreiter_t *pk,
const DIGIT err[]) {
void PQCLEAN_LEDAKEMLT52_LEAKTIME_niederreiter_encrypt(DIGIT *syndrome, const publicKeyNiederreiter_t *pk, const DIGIT *err) {
int i;
DIGIT saux[NUM_DIGITS_GF2X_ELEMENT];
memset(syndrome, 0x00, NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B);
for (i = 0; i < N0 - 1; i++) {
for (size_t i = 0; i < N0 - 1; i++) {
PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_mod_mul(saux,
pk->Mtr + i * NUM_DIGITS_GF2X_ELEMENT,
err + i * NUM_DIGITS_GF2X_ELEMENT);
PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_mod_add(syndrome, syndrome, saux);
}
PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_mod_add(syndrome, syndrome, err + (N0 - 1)*NUM_DIGITS_GF2X_ELEMENT);
}
int PQCLEAN_LEDAKEMLT52_LEAKTIME_niederreiter_decrypt(DIGIT *err, const privateKeyNiederreiter_t *sk, const DIGIT *syndrome) {
AES_XOF_struct niederreiter_decrypt_expander;
POSITION_T HPosOnes[N0][DV];
POSITION_T HtrPosOnes[N0][DV];
POSITION_T QPosOnes[N0][M];
POSITION_T QtrPosOnes[N0][M];
POSITION_T auxPosOnes[DV * M];
POSITION_T LPosOnes[N0][DV * M];
POSITION_T auxPosOnes[DV * M];
POSITION_T HtrPosOnes[N0][DV];
POSITION_T QtrPosOnes[N0][M];
POSITION_T auxSparse[DV * M];
POSITION_T Ln0trSparse[DV * M];
unsigned char processedQOnes[N0];
unsigned transposed_ones_idx[N0];
DIGIT err_computed[N0 * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B] = {0};
DIGIT privateSyndrome[NUM_DIGITS_GF2X_ELEMENT];
DIGIT mockup_error_vector[N0 * NUM_DIGITS_GF2X_ELEMENT];
unsigned char processedQOnes[N0];
int rejections = sk->rejections;
int currQoneIdx, endQblockIdx;
int decryptOk, err_weight;
PQCLEAN_LEDAKEMLT52_LEAKTIME_seedexpander_from_trng(&niederreiter_decrypt_expander, sk->prng_seed);
do {
PQCLEAN_LEDAKEMLT52_LEAKTIME_generateHPosOnes_HtrPosOnes(HPosOnes, HtrPosOnes, &niederreiter_decrypt_expander);
PQCLEAN_LEDAKEMLT52_LEAKTIME_generateQsparse(QPosOnes, &niederreiter_decrypt_expander);
PQCLEAN_LEDAKEMLT52_LEAKTIME_generateHPosOnes(HPosOnes, &niederreiter_decrypt_expander);
PQCLEAN_LEDAKEMLT52_LEAKTIME_generateQPosOnes(QPosOnes, &niederreiter_decrypt_expander);
for (int i = 0; i < N0; i++) {
for (int j = 0; j < DV * M; j++) {
LPosOnes[i][j] = INVALID_POS_VALUE;
@ -136,19 +140,8 @@ int PQCLEAN_LEDAKEMLT52_LEAKTIME_niederreiter_decrypt(DIGIT *err, const privateK
rejections--;
} while (rejections >= 0);
memset(transposed_ones_idx, 0x00, sizeof(transposed_ones_idx));
for (unsigned source_row_idx = 0; source_row_idx < N0 ; source_row_idx++) {
currQoneIdx = 0; // position in the column of QtrPosOnes[][...]
endQblockIdx = 0;
for (int blockIdx = 0; blockIdx < N0; blockIdx++) {
endQblockIdx += qBlockWeights[source_row_idx][blockIdx];
for (; currQoneIdx < endQblockIdx; currQoneIdx++) {
QtrPosOnes[blockIdx][transposed_ones_idx[blockIdx]] = (P -
QPosOnes[source_row_idx][currQoneIdx]) % P;
transposed_ones_idx[blockIdx]++;
}
}
}
PQCLEAN_LEDAKEMLT52_LEAKTIME_transposeHPosOnes(HtrPosOnes, HPosOnes);
PQCLEAN_LEDAKEMLT52_LEAKTIME_transposeQPosOnes(QtrPosOnes, QPosOnes);
for (int i = 0; i < DV * M; i++) {
Ln0trSparse[i] = INVALID_POS_VALUE;
@ -163,29 +156,36 @@ int PQCLEAN_LEDAKEMLT52_LEAKTIME_niederreiter_decrypt(DIGIT *err, const privateK
DV * M, Ln0trSparse,
DV * M, auxSparse);
}
PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_transpose_in_place_sparse(DV * M, Ln0trSparse);
PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_mod_mul_dense_to_sparse(privateSyndrome, syndrome, Ln0trSparse, DV * M);
/* prepare mockup error vector in case a decoding failure occurs */
memset(mockup_error_vector, 0x00, N0 * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B);
memcpy(mockup_error_vector, syndrome, NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B);
PQCLEAN_LEDAKEMLT52_LEAKTIME_seedexpander(&niederreiter_decrypt_expander,
((unsigned char *) mockup_error_vector) + (NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B),
TRNG_BYTE_LENGTH);
PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_mod_mul_dense_to_sparse(privateSyndrome,
syndrome,
Ln0trSparse,
DV * M);
memset(err, 0x00, N0 * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B);
decryptOk = PQCLEAN_LEDAKEMLT52_LEAKTIME_bf_decoding(err, (const POSITION_T (*)[DV]) HtrPosOnes,
(const POSITION_T (*)[M]) QtrPosOnes, privateSyndrome, sk->threshold);
int decryptOk = 0;
decryptOk = PQCLEAN_LEDAKEMLT52_LEAKTIME_bf_decoding(err_computed,
(const POSITION_T (*)[DV]) HtrPosOnes,
(const POSITION_T (*)[M]) QtrPosOnes,
privateSyndrome, sk->secondIterThreshold);
err_weight = 0;
int err_weight = 0;
for (int i = 0 ; i < N0; i++) {
err_weight += PQCLEAN_LEDAKEMLT52_LEAKTIME_population_count(err + (NUM_DIGITS_GF2X_ELEMENT * i));
err_weight += PQCLEAN_LEDAKEMLT52_LEAKTIME_population_count(err_computed + (NUM_DIGITS_GF2X_ELEMENT * i));
}
decryptOk = decryptOk && (err_weight == NUM_ERRORS_T);
if (!decryptOk) { // TODO: not constant time, replace with cmov?
memcpy(err, mockup_error_vector, N0 * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B);
/* prepare mockup error vector in case a decoding failure occurs */
DIGIT err_mockup[N0 * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B];
memcpy(err_mockup, syndrome, NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B);
memcpy(err_mockup + NUM_DIGITS_GF2X_ELEMENT, sk->decryption_failure_secret, TRNG_BYTE_LENGTH);
memset(((unsigned char *) err_mockup) + (NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B) + TRNG_BYTE_LENGTH, 0x00,
(N0 - 1)*NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B - TRNG_BYTE_LENGTH);
if (!decryptOk) {
memcpy(err, err_mockup, N0 * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B);
} else {
memcpy(err, err_computed, N0 * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B);
}
return decryptOk;

View File

@ -6,24 +6,19 @@
#include "rng.h"
typedef struct {
/* raw entropy extracted from TRNG, will be deterministically expanded into
* H and Q during decryption */
unsigned char prng_seed[TRNG_BYTE_LENGTH];
int8_t rejections;
uint8_t threshold; // for round 2
uint8_t rejections;
uint8_t secondIterThreshold;
uint8_t decryption_failure_secret[TRNG_BYTE_LENGTH];
} privateKeyNiederreiter_t;
typedef struct {
DIGIT Mtr[(N0 - 1)*NUM_DIGITS_GF2X_ELEMENT];
// Dense representation of the matrix M=Ln0*L,
// An array including a sequence of (N0-1) gf2x elements;
// each gf2x element is stored as a binary polynomial(mod x^P+1)
// with P coefficients.
} publicKeyNiederreiter_t;
void PQCLEAN_LEDAKEMLT52_LEAKTIME_niederreiter_keygen(publicKeyNiederreiter_t *pk, privateKeyNiederreiter_t *sk, AES_XOF_struct *keys_expander);
void PQCLEAN_LEDAKEMLT52_LEAKTIME_niederreiter_encrypt(DIGIT syndrome[], const publicKeyNiederreiter_t *pk, const DIGIT *err);
void PQCLEAN_LEDAKEMLT52_LEAKTIME_niederreiter_keygen(publicKeyNiederreiter_t *pk, privateKeyNiederreiter_t *sk);
void PQCLEAN_LEDAKEMLT52_LEAKTIME_niederreiter_encrypt(DIGIT syndrome[], const publicKeyNiederreiter_t *pk, const DIGIT err[]);
int PQCLEAN_LEDAKEMLT52_LEAKTIME_niederreiter_decrypt(DIGIT *err, const privateKeyNiederreiter_t *sk, const DIGIT *syndrome);
#endif

View File

@ -0,0 +1,87 @@
#include "sort.h"
/*
Constant-time uint32_t sorting by Daniel J. Bernstein
Source: https://sorting.cr.yp.to
*/
static void int32_sort(int32 *x, size_t n) {
size_t top, p, q, r, i, j;
if (n < 2) {
return;
}
top = 1;
while (top < n - top) {
top += top;
}
for (p = top; p >= 1; p >>= 1) {
i = 0;
while (i + 2 * p <= n) {
for (j = i; j < i + p; ++j) {
int32_MINMAX(x[j], x[j + p]);
}
i += 2 * p;
}
for (j = i; j < n - p; ++j) {
int32_MINMAX(x[j], x[j + p]);
}
i = 0;
j = 0;
for (q = top; q > p; q >>= 1) {
if (j != i) {
for (;;) {
if (j == n - q) {
goto done;
}
int32 a = x[j + p];
for (r = q; r > p; r >>= 1) {
int32_MINMAX(a, x[j + r]);
}
x[j + p] = a;
++j;
if (j == i + p) {
i += 2 * p;
break;
}
}
}
while (i + p <= n - q) {
for (j = i; j < i + p; ++j) {
int32 a = x[j + p];
for (r = q; r > p; r >>= 1) {
int32_MINMAX(a, x[j + r]);
}
x[j + p] = a;
}
i += 2 * p;
}
/* now i + p > n - q */
j = i;
while (j < n - q) {
int32 a = x[j + p];
for (r = q; r > p; r >>= 1) {
int32_MINMAX(a, x[j + r]);
}
x[j + p] = a;
++j;
}
done:
;
}
}
}
/* can save time by integrating xor loops with int32_sort */
void PQCLEAN_LEDAKEMLT52_LEAKTIME_uint32_sort(uint32_t *x, size_t n) {
size_t j;
for (j = 0; j < n; ++j) {
x[j] ^= 0x80000000;
}
int32_sort((int32_t *) x, n);
for (j = 0; j < n; ++j) {
x[j] ^= 0x80000000;
}
}

View File

@ -0,0 +1,22 @@
#ifndef SORT_H
#define SORT_H
#include <stddef.h>
#include <stdint.h>
#define int32 int32_t
#define int32_MINMAX(a,b) \
do { \
int32 ab = (b) ^ (a); \
int32 c = (b) - (a); \
c ^= ab & (c ^ (b)); \
c >>= 31; \
c &= ab; \
(a) ^= c; \
(b) ^= c; \
} while(0)
void PQCLEAN_LEDAKEMLT52_LEAKTIME_uint32_sort(uint32_t *x, size_t n);
#endif

View File

@ -2,8 +2,8 @@
# override as desired
TYPE=kem
SCHEME=kyber768
IMPLEMENTATION=clean
SCHEME=ledakemlt12
IMPLEMENTATION=leaktime
SCHEME_DIR="../crypto_$(TYPE)/$(SCHEME)/$(IMPLEMENTATION)"
SCHEME_UPPERCASE=$(shell echo $(SCHEME) | tr a-z A-Z | sed 's/-//g')