mirror of
https://github.com/henrydcase/pqc.git
synced 2024-11-22 07:35:38 +00:00
update implementations to leda v2.1
This commit is contained in:
parent
9a5caaa95b
commit
ca898f01bc
@ -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
|
||||
|
@ -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],
|
||||
AES_XOF_struct *keys_expander) {
|
||||
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],
|
||||
AES_XOF_struct *keys_expander) {
|
||||
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]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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]);
|
||||
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;
|
||||
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 ]++;
|
||||
}
|
||||
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++;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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[]) {
|
||||
|
||||
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];
|
||||
}
|
||||
static void gf2x_mod(DIGIT out[], const DIGIT in[]) {
|
||||
DIGIT aux[NUM_DIGITS_GF2X_ELEMENT + 1];
|
||||
|
||||
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[],
|
||||
POSITION_T sparse[], unsigned int nPos) {
|
||||
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,9 +463,8 @@ 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],
|
||||
AES_XOF_struct *seed_expander_ctx) {
|
||||
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;
|
||||
int p, polyIndex, exponent;
|
||||
@ -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++) {
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
@ -158,34 +151,41 @@ int PQCLEAN_LEDAKEMLT12_LEAKTIME_niederreiter_decrypt(DIGIT *err, const privateK
|
||||
for (int i = 0; i < N0; i++) {
|
||||
PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_mod_mul_sparse(DV * M, auxSparse,
|
||||
DV, HPosOnes[i],
|
||||
qBlockWeights[i][N0 - 1], &QPosOnes[i][ M - qBlockWeights[i][N0 - 1]]);
|
||||
qBlockWeights[i][N0 - 1], &QPosOnes[i][ M - qBlockWeights[i][N0 - 1] ] );
|
||||
PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_mod_add_sparse(DV * M, Ln0trSparse,
|
||||
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;
|
||||
|
@ -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
|
||||
|
87
crypto_kem/ledakemlt12/leaktime/sort.c
Normal file
87
crypto_kem/ledakemlt12/leaktime/sort.c
Normal 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;
|
||||
}
|
||||
}
|
22
crypto_kem/ledakemlt12/leaktime/sort.h
Normal file
22
crypto_kem/ledakemlt12/leaktime/sort.h
Normal 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
|
@ -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
|
||||
|
@ -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],
|
||||
AES_XOF_struct *keys_expander) {
|
||||
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],
|
||||
AES_XOF_struct *keys_expander) {
|
||||
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]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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]);
|
||||
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;
|
||||
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 ]++;
|
||||
}
|
||||
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++;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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[]) {
|
||||
|
||||
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];
|
||||
}
|
||||
static void gf2x_mod(DIGIT out[], const DIGIT in[]) {
|
||||
DIGIT aux[NUM_DIGITS_GF2X_ELEMENT + 1];
|
||||
|
||||
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[],
|
||||
POSITION_T sparse[], unsigned int nPos) {
|
||||
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,9 +461,8 @@ 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],
|
||||
AES_XOF_struct *seed_expander_ctx) {
|
||||
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;
|
||||
int p, polyIndex, exponent;
|
||||
@ -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++) {
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
@ -158,34 +151,41 @@ int PQCLEAN_LEDAKEMLT32_LEAKTIME_niederreiter_decrypt(DIGIT *err, const privateK
|
||||
for (int i = 0; i < N0; i++) {
|
||||
PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_mod_mul_sparse(DV * M, auxSparse,
|
||||
DV, HPosOnes[i],
|
||||
qBlockWeights[i][N0 - 1], &QPosOnes[i][ M - qBlockWeights[i][N0 - 1]]);
|
||||
qBlockWeights[i][N0 - 1], &QPosOnes[i][ M - qBlockWeights[i][N0 - 1] ] );
|
||||
PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_mod_add_sparse(DV * M, Ln0trSparse,
|
||||
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;
|
||||
|
@ -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
|
||||
|
87
crypto_kem/ledakemlt32/leaktime/sort.c
Normal file
87
crypto_kem/ledakemlt32/leaktime/sort.c
Normal 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;
|
||||
}
|
||||
}
|
22
crypto_kem/ledakemlt32/leaktime/sort.h
Normal file
22
crypto_kem/ledakemlt32/leaktime/sort.h
Normal 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
|
@ -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
|
||||
|
@ -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],
|
||||
AES_XOF_struct *keys_expander) {
|
||||
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],
|
||||
AES_XOF_struct *keys_expander) {
|
||||
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]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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]);
|
||||
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;
|
||||
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 ]++;
|
||||
}
|
||||
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++;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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[]) {
|
||||
|
||||
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];
|
||||
}
|
||||
static void gf2x_mod(DIGIT out[], const DIGIT in[]) {
|
||||
DIGIT aux[NUM_DIGITS_GF2X_ELEMENT + 1];
|
||||
|
||||
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[],
|
||||
POSITION_T sparse[], unsigned int nPos) {
|
||||
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,9 +461,8 @@ 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],
|
||||
AES_XOF_struct *seed_expander_ctx) {
|
||||
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;
|
||||
int p, polyIndex, exponent;
|
||||
@ -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++) {
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
@ -158,34 +151,41 @@ int PQCLEAN_LEDAKEMLT52_LEAKTIME_niederreiter_decrypt(DIGIT *err, const privateK
|
||||
for (int i = 0; i < N0; i++) {
|
||||
PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_mod_mul_sparse(DV * M, auxSparse,
|
||||
DV, HPosOnes[i],
|
||||
qBlockWeights[i][N0 - 1], &QPosOnes[i][ M - qBlockWeights[i][N0 - 1]]);
|
||||
qBlockWeights[i][N0 - 1], &QPosOnes[i][ M - qBlockWeights[i][N0 - 1] ] );
|
||||
PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_mod_add_sparse(DV * M, Ln0trSparse,
|
||||
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;
|
||||
|
@ -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
|
||||
|
87
crypto_kem/ledakemlt52/leaktime/sort.c
Normal file
87
crypto_kem/ledakemlt52/leaktime/sort.c
Normal 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;
|
||||
}
|
||||
}
|
22
crypto_kem/ledakemlt52/leaktime/sort.h
Normal file
22
crypto_kem/ledakemlt52/leaktime/sort.h
Normal 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
|
@ -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')
|
||||
|
Loading…
Reference in New Issue
Block a user