Browse Source

remove threebears, ledakem, newhope, mqdss, qtesla

NIST announced the Round 3 finalists and alternate candidates today:
https://groups.google.com/a/list.nist.gov/d/msg/pqc-forum/0ieuPB-b8eg/Cl7Ji8TpCwAJ

Some of the schemes in PQClean did not make it to Round 3 and this commit
removes them.
kyber
Matthias J. Kannwischer 4 years ago
committed by Kris Kwiatkowski
parent
commit
22babfef8a
100 changed files with 0 additions and 7127 deletions
  1. +0
    -14
      crypto_kem/babybear-ephem/META.yml
  2. +0
    -24
      crypto_kem/babybear-ephem/clean/LICENSE
  3. +0
    -21
      crypto_kem/babybear-ephem/clean/Makefile
  4. +0
    -19
      crypto_kem/babybear-ephem/clean/Makefile.Microsoft_nmake
  5. +0
    -18
      crypto_kem/babybear-ephem/clean/api.h
  6. +0
    -22
      crypto_kem/babybear-ephem/clean/kem.c
  7. +0
    -87
      crypto_kem/babybear-ephem/clean/melas_fec.c
  8. +0
    -26
      crypto_kem/babybear-ephem/clean/melas_fec.h
  9. +0
    -29
      crypto_kem/babybear-ephem/clean/params.h
  10. +0
    -107
      crypto_kem/babybear-ephem/clean/ring.c
  11. +0
    -29
      crypto_kem/babybear-ephem/clean/ring.h
  12. +0
    -219
      crypto_kem/babybear-ephem/clean/threebears.c
  13. +0
    -60
      crypto_kem/babybear-ephem/clean/threebears.h
  14. +0
    -14
      crypto_kem/babybear/META.yml
  15. +0
    -24
      crypto_kem/babybear/clean/LICENSE
  16. +0
    -21
      crypto_kem/babybear/clean/Makefile
  17. +0
    -19
      crypto_kem/babybear/clean/Makefile.Microsoft_nmake
  18. +0
    -18
      crypto_kem/babybear/clean/api.h
  19. +0
    -22
      crypto_kem/babybear/clean/kem.c
  20. +0
    -87
      crypto_kem/babybear/clean/melas_fec.c
  21. +0
    -26
      crypto_kem/babybear/clean/melas_fec.h
  22. +0
    -29
      crypto_kem/babybear/clean/params.h
  23. +0
    -107
      crypto_kem/babybear/clean/ring.c
  24. +0
    -29
      crypto_kem/babybear/clean/ring.h
  25. +0
    -231
      crypto_kem/babybear/clean/threebears.c
  26. +0
    -58
      crypto_kem/babybear/clean/threebears.h
  27. +0
    -19
      crypto_kem/ledakemlt12/META.yml
  28. +0
    -52
      crypto_kem/ledakemlt12/leaktime/H_Q_matrices_generation.c
  29. +0
    -13
      crypto_kem/ledakemlt12/leaktime/H_Q_matrices_generation.h
  30. +0
    -31
      crypto_kem/ledakemlt12/leaktime/LICENSE
  31. +0
    -24
      crypto_kem/ledakemlt12/leaktime/Makefile
  32. +0
    -19
      crypto_kem/ledakemlt12/leaktime/Makefile.Microsoft_nmake
  33. +0
    -18
      crypto_kem/ledakemlt12/leaktime/api.h
  34. +0
    -79
      crypto_kem/ledakemlt12/leaktime/bf_decoding.c
  35. +0
    -18
      crypto_kem/ledakemlt12/leaktime/bf_decoding.h
  36. +0
    -88
      crypto_kem/ledakemlt12/leaktime/dfr_test.c
  37. +0
    -6
      crypto_kem/ledakemlt12/leaktime/dfr_test.h
  38. +0
    -252
      crypto_kem/ledakemlt12/leaktime/gf2x_arith.c
  39. +0
    -63
      crypto_kem/ledakemlt12/leaktime/gf2x_arith.h
  40. +0
    -531
      crypto_kem/ledakemlt12/leaktime/gf2x_arith_mod_xPplusOne.c
  41. +0
    -39
      crypto_kem/ledakemlt12/leaktime/gf2x_arith_mod_xPplusOne.h
  42. +0
    -157
      crypto_kem/ledakemlt12/leaktime/kem.c
  43. +0
    -192
      crypto_kem/ledakemlt12/leaktime/niederreiter.c
  44. +0
    -24
      crypto_kem/ledakemlt12/leaktime/niederreiter.h
  45. +0
    -27
      crypto_kem/ledakemlt12/leaktime/qc_ldpc_parameters.h
  46. +0
    -110
      crypto_kem/ledakemlt12/leaktime/rng.c
  47. +0
    -24
      crypto_kem/ledakemlt12/leaktime/rng.h
  48. +0
    -98
      crypto_kem/ledakemlt12/leaktime/sort.c
  49. +0
    -11
      crypto_kem/ledakemlt12/leaktime/sort.h
  50. +0
    -21
      crypto_kem/ledakemlt12/leaktime/utils.c
  51. +0
    -9
      crypto_kem/ledakemlt12/leaktime/utils.h
  52. +0
    -19
      crypto_kem/ledakemlt32/META.yml
  53. +0
    -52
      crypto_kem/ledakemlt32/leaktime/H_Q_matrices_generation.c
  54. +0
    -13
      crypto_kem/ledakemlt32/leaktime/H_Q_matrices_generation.h
  55. +0
    -31
      crypto_kem/ledakemlt32/leaktime/LICENSE
  56. +0
    -24
      crypto_kem/ledakemlt32/leaktime/Makefile
  57. +0
    -19
      crypto_kem/ledakemlt32/leaktime/Makefile.Microsoft_nmake
  58. +0
    -18
      crypto_kem/ledakemlt32/leaktime/api.h
  59. +0
    -79
      crypto_kem/ledakemlt32/leaktime/bf_decoding.c
  60. +0
    -18
      crypto_kem/ledakemlt32/leaktime/bf_decoding.h
  61. +0
    -88
      crypto_kem/ledakemlt32/leaktime/dfr_test.c
  62. +0
    -6
      crypto_kem/ledakemlt32/leaktime/dfr_test.h
  63. +0
    -252
      crypto_kem/ledakemlt32/leaktime/gf2x_arith.c
  64. +0
    -63
      crypto_kem/ledakemlt32/leaktime/gf2x_arith.h
  65. +0
    -529
      crypto_kem/ledakemlt32/leaktime/gf2x_arith_mod_xPplusOne.c
  66. +0
    -39
      crypto_kem/ledakemlt32/leaktime/gf2x_arith_mod_xPplusOne.h
  67. +0
    -157
      crypto_kem/ledakemlt32/leaktime/kem.c
  68. +0
    -192
      crypto_kem/ledakemlt32/leaktime/niederreiter.c
  69. +0
    -24
      crypto_kem/ledakemlt32/leaktime/niederreiter.h
  70. +0
    -27
      crypto_kem/ledakemlt32/leaktime/qc_ldpc_parameters.h
  71. +0
    -110
      crypto_kem/ledakemlt32/leaktime/rng.c
  72. +0
    -24
      crypto_kem/ledakemlt32/leaktime/rng.h
  73. +0
    -98
      crypto_kem/ledakemlt32/leaktime/sort.c
  74. +0
    -11
      crypto_kem/ledakemlt32/leaktime/sort.h
  75. +0
    -21
      crypto_kem/ledakemlt32/leaktime/utils.c
  76. +0
    -9
      crypto_kem/ledakemlt32/leaktime/utils.h
  77. +0
    -19
      crypto_kem/ledakemlt52/META.yml
  78. +0
    -52
      crypto_kem/ledakemlt52/leaktime/H_Q_matrices_generation.c
  79. +0
    -13
      crypto_kem/ledakemlt52/leaktime/H_Q_matrices_generation.h
  80. +0
    -31
      crypto_kem/ledakemlt52/leaktime/LICENSE
  81. +0
    -24
      crypto_kem/ledakemlt52/leaktime/Makefile
  82. +0
    -19
      crypto_kem/ledakemlt52/leaktime/Makefile.Microsoft_nmake
  83. +0
    -18
      crypto_kem/ledakemlt52/leaktime/api.h
  84. +0
    -79
      crypto_kem/ledakemlt52/leaktime/bf_decoding.c
  85. +0
    -18
      crypto_kem/ledakemlt52/leaktime/bf_decoding.h
  86. +0
    -88
      crypto_kem/ledakemlt52/leaktime/dfr_test.c
  87. +0
    -6
      crypto_kem/ledakemlt52/leaktime/dfr_test.h
  88. +0
    -252
      crypto_kem/ledakemlt52/leaktime/gf2x_arith.c
  89. +0
    -68
      crypto_kem/ledakemlt52/leaktime/gf2x_arith.h
  90. +0
    -529
      crypto_kem/ledakemlt52/leaktime/gf2x_arith_mod_xPplusOne.c
  91. +0
    -39
      crypto_kem/ledakemlt52/leaktime/gf2x_arith_mod_xPplusOne.h
  92. +0
    -157
      crypto_kem/ledakemlt52/leaktime/kem.c
  93. +0
    -192
      crypto_kem/ledakemlt52/leaktime/niederreiter.c
  94. +0
    -24
      crypto_kem/ledakemlt52/leaktime/niederreiter.h
  95. +0
    -27
      crypto_kem/ledakemlt52/leaktime/qc_ldpc_parameters.h
  96. +0
    -110
      crypto_kem/ledakemlt52/leaktime/rng.c
  97. +0
    -24
      crypto_kem/ledakemlt52/leaktime/rng.h
  98. +0
    -98
      crypto_kem/ledakemlt52/leaktime/sort.c
  99. +0
    -11
      crypto_kem/ledakemlt52/leaktime/sort.h
  100. +0
    -21
      crypto_kem/ledakemlt52/leaktime/utils.c

+ 0
- 14
crypto_kem/babybear-ephem/META.yml View File

@@ -1,14 +0,0 @@
name: BabyBearEphem
type: kem
claimed-nist-level: 1
claimed-security: IND-CPA
length-public-key: 804
length-ciphertext: 917
length-secret-key: 40
length-shared-secret: 32
nistkat-sha256: 1caf1dc65c7b2923c936ed464574694a8983ed5508dadfc554fd98e1095652e9
principal-submitters:
- Mike Hamburg
implementations:
- name: clean
version: https://sourceforge.net/p/threebears/code/ci/f4ce0ebfc84a5e01a75bfc8297b6d175e993cfa4/

+ 0
- 24
crypto_kem/babybear-ephem/clean/LICENSE View File

@@ -1,24 +0,0 @@
Copyright (c) 2016-2019 Rambus, Inc.
and licensed under the following MIT license.

The MIT License (MIT)

Copyright (c) 2016-2019 Rambus Inc.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

+ 0
- 21
crypto_kem/babybear-ephem/clean/Makefile View File

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

LIB=libbabybear-ephem_clean.a

HEADERS = api.h melas_fec.h params.h ring.h threebears.h
OBJECTS = kem.o melas_fec.o ring.o threebears.o


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

all: $(LIB)

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

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

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

+ 0
- 19
crypto_kem/babybear-ephem/clean/Makefile.Microsoft_nmake View File

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

LIBRARY=libbabybear-ephem_clean.lib
OBJECTS = kem.obj melas_fec.obj ring.obj threebears.obj

CFLAGS=/nologo /I ..\..\..\common /W4 /WX

all: $(LIBRARY)

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

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

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

+ 0
- 18
crypto_kem/babybear-ephem/clean/api.h View File

@@ -1,18 +0,0 @@
#ifndef PQCLEAN_BABYBEAREPHEM_CLEAN_API_H
#define PQCLEAN_BABYBEAREPHEM_CLEAN_API_H

#include <stddef.h>
#include <stdint.h>
#include <string.h>

#define PQCLEAN_BABYBEAREPHEM_CLEAN_CRYPTO_SECRETKEYBYTES 40
#define PQCLEAN_BABYBEAREPHEM_CLEAN_CRYPTO_PUBLICKEYBYTES 804
#define PQCLEAN_BABYBEAREPHEM_CLEAN_CRYPTO_BYTES 32
#define PQCLEAN_BABYBEAREPHEM_CLEAN_CRYPTO_CIPHERTEXTBYTES 917
#define PQCLEAN_BABYBEAREPHEM_CLEAN_CRYPTO_ALGNAME "BabyBearEphem"

int PQCLEAN_BABYBEAREPHEM_CLEAN_crypto_kem_keypair(uint8_t *pk, uint8_t *sk);
int PQCLEAN_BABYBEAREPHEM_CLEAN_crypto_kem_enc(uint8_t *ct, uint8_t *ss, const uint8_t *pk);
int PQCLEAN_BABYBEAREPHEM_CLEAN_crypto_kem_dec(uint8_t *ss, const uint8_t *ct, const uint8_t *sk);

#endif

+ 0
- 22
crypto_kem/babybear-ephem/clean/kem.c View File

@@ -1,22 +0,0 @@
#include "api.h"
#include "params.h"
#include "randombytes.h"
#include "threebears.h"

int PQCLEAN_BABYBEAREPHEM_CLEAN_crypto_kem_keypair(uint8_t *pk, uint8_t *sk) {
randombytes(sk, PRIVATE_KEY_BYTES);
PQCLEAN_BABYBEAREPHEM_CLEAN_get_pubkey(pk, sk);
return 0;
}

int PQCLEAN_BABYBEAREPHEM_CLEAN_crypto_kem_enc(uint8_t *ct, uint8_t *ss, const uint8_t *pk) {
uint8_t seed[ENC_SEED_BYTES + IV_BYTES];
randombytes(seed, sizeof(seed));
encapsulate(ss, ct, pk, seed);
return 0;
}

int PQCLEAN_BABYBEAREPHEM_CLEAN_crypto_kem_dec(uint8_t *ss, const uint8_t *ct, const uint8_t *sk) {
PQCLEAN_BABYBEAREPHEM_CLEAN_decapsulate(ss, ct, sk);
return 0;
}

+ 0
- 87
crypto_kem/babybear-ephem/clean/melas_fec.c View File

@@ -1,87 +0,0 @@
/* Melas forward error correction, reference code (as implemented in the paper) */
#include "melas_fec.h"

/* Return s/2^n mod R */
static fec_gf_t step(size_t n, fec_gf_t R, fec_gf_t s) {
for (; n; n--) {
s = (s ^ ((s & 1) * R)) >> 1;
}
return s;
}

/* Compute syndrome(data), where data has length len */
#define syndrome18(data,len) s18update(0,data,len)
static fec_gf_t s18update(fec_gf_t r, const uint8_t *data, size_t len) {
for (size_t i = 0; i < len; i++) {
r = step(8, 0x46231, r ^ data[i]);
}
return r;
}

/* Append 3 bytes of FEC(data) to data, so that the FEC becomes 0 */
void PQCLEAN_BABYBEAREPHEM_CLEAN_melas_fec_set(
uint8_t out[MELAS_FEC_BYTES],
const uint8_t *data,
size_t len
) {
fec_gf_t fec = syndrome18(data, len);
for (size_t i = 0; i < MELAS_FEC_BYTES; i++, fec >>= 8) {
out[i] = (uint8_t)fec;
}
}

/* Return a*b mod Q */
static fec_gf_t mul(fec_gf_t a, fec_gf_t b) {
fec_gf_t r = 0;
for (size_t i = 0; i < 9; i++) {
r ^= ((b >> (8 - i)) & 1) * a;
a = step(1, Q, a);
}
return r;
}

/* Reverse an 18-bit number x */
static fec_gf_t reverse18(fec_gf_t x) {
fec_gf_t ret = 0;
for (size_t i = 0; i < 18; i++) {
ret ^= ((x >> i) & 1) << (17 - i);
}
return ret;
}

/* Correct data to have the given FEC */
void PQCLEAN_BABYBEAREPHEM_CLEAN_melas_fec_correct (
uint8_t *data,
size_t len,
const uint8_t fec[MELAS_FEC_BYTES]
) {

fec_gf_t a = s18update(syndrome18(data, len), fec, MELAS_FEC_BYTES);
fec_gf_t c, r, htr;
size_t i;
const uint8_t table[9] = {36, 10, 43, 215, 52, 11, 116, 244, 0};
fec_gf_t e0, e1;

/* Form a quadratic equation from the syndrome */
c = mul(step(9, Q, a), step(9, Q, reverse18(a)));
for (i = 0, r = 0x100; i < 510; i++) {
r = mul(r, c);
}
r = step(17, Q, r);
a = step(511 - (len + MELAS_FEC_BYTES) * 8, Q, a);

/* Solve using the half trace */
for (i = 0, htr = 0; i < 9; i++) {
htr ^= ((r >> i) & 1) * table[i];
}
e0 = mul(a, htr);
e1 = e0 ^ a;

/* Correct the errors using the locators */
for (i = 0; i < len; i++) {
data[i] ^= (uint8_t)(e0 & (((e0 & (e0 - 1)) - 1) >> 9));
data[i] ^= (uint8_t)(e1 & (((e1 & (e1 - 1)) - 1) >> 9));
e0 = step(8, Q, e0);
e1 = step(8, Q, e1);
}
}

+ 0
- 26
crypto_kem/babybear-ephem/clean/melas_fec.h View File

@@ -1,26 +0,0 @@
#ifndef __THREEBEARS_MELAS_FEC_H__
#define __THREEBEARS_MELAS_FEC_H__

#include "api.h"

#define MELAS_FEC_BYTES 3
#define MELAS_FEC_BITS 18

typedef uint32_t fec_gf_t;
static const fec_gf_t Q = 0x211;

/* Append 3 bytes of FEC(data) to data, so that the FEC becomes 0 */
void PQCLEAN_BABYBEAREPHEM_CLEAN_melas_fec_set(
uint8_t out[MELAS_FEC_BYTES],
const uint8_t *data,
size_t len
);

/* Append 3 bytes of FEC(data) to data, so that the FEC becomes 0 */
void PQCLEAN_BABYBEAREPHEM_CLEAN_melas_fec_correct(
uint8_t *data,
size_t len,
const uint8_t fec[MELAS_FEC_BYTES]
);

#endif

+ 0
- 29
crypto_kem/babybear-ephem/clean/params.h View File

@@ -1,29 +0,0 @@
#ifndef __THREEBEARS_PARAMS_H__
#define __THREEBEARS_PARAMS_H__

#define VERSION 1
#define MATRIX_SEED_BYTES 24
#define ENC_SEED_BYTES 32
#define IV_BYTES 0
#define LGX 10
#define DIGITS 312
#define DIM 2
#define VAR_TIMES_128 128
#define LPR_BITS 4
#define FEC_BITS 18
#define CCA 0
#define SHARED_SECRET_BYTES 32
#define PRIVATE_KEY_BYTES 40
#define PRF_KEY_BYTES PRIVATE_KEY_BYTES

#define BEAR_NAME "BabyBearEphem"
#define encapsulate PQCLEAN_BABYBEAREPHEM_CLEAN_encapsulate
#define decapsulate PQCLEAN_BABYBEAREPHEM_CLEAN_decapsulate
#define get_pubkey PQCLEAN_BABYBEAREPHEM_CLEAN_get_pubkey

#define GF_BYTES ((LGX*DIGITS+7)/8)
#define PUBLIC_KEY_BYTES (MATRIX_SEED_BYTES + DIM*GF_BYTES)
#define CAPSULE_BYTES \
(DIM*GF_BYTES + IV_BYTES + ((ENC_SEED_BYTES*8+FEC_BITS)*LPR_BITS+7)/8)

#endif

+ 0
- 107
crypto_kem/babybear-ephem/clean/ring.c View File

@@ -1,107 +0,0 @@
/** Ring arithmetic implementation */
#include "ring.h"

/** Return the i'th limb of the modulus */
limb_t PQCLEAN_BABYBEAREPHEM_CLEAN_modulus(size_t i) {
return (i == DIGITS / 2) ? LMASK - 1 : LMASK;
}

/** Multiply and accumulate c += a*b */
void PQCLEAN_BABYBEAREPHEM_CLEAN_mac(gf_t c, const gf_t a, const gf_t b) {
/* Reference non-Karatsuba MAC */
dslimb_t accum[2 * DIGITS] = {0};
dslimb_t chain;
size_t i, j;

/* Initialize accumulator = unclarify(c) */
for (i = 0; i < DIGITS; i++) {
accum[i + DIGITS / 2] = c[i];
}

/* Multiply */
for (i = 0; i < DIGITS; i++) {
for (j = 0; j < DIGITS; j++) {
accum[i + j] += (dslimb_t)a[i] * b[j];
}
}

/* Clarify and reduce */
for (i = 0; i < DIGITS / 2; i++) {
accum[i + DIGITS / 2] -= accum[i];
accum[i + DIGITS] += accum[i];
accum[i + DIGITS / 2] += accum[i + 3 * DIGITS / 2];
accum[i + DIGITS] += accum[i + 3 * DIGITS / 2];
}

/* Carry propagate */
chain = accum[3 * DIGITS / 2 - 1];
accum[3 * DIGITS / 2 - 1] = chain & LMASK;
chain >>= LGX;
accum[DIGITS] += chain;
for (i = DIGITS / 2; i < 3 * DIGITS / 2; i++) {
chain += accum[i];
c[i - DIGITS / 2] = chain & LMASK;
chain >>= LGX;
}
c[0] = (limb_t) (c[0] + chain);
c[DIGITS / 2] = (limb_t) (c[DIGITS / 2] + chain);
}

/** Reduce a gf_t to canonical form, i.e. strictly less than N. */
void PQCLEAN_BABYBEAREPHEM_CLEAN_canon(gf_t c) {
const limb_t DELTA = (limb_t)1 << (LGX - 1);
slimb_t hi;
dslimb_t scarry;
dlimb_t carry;

/* Reduce to 0..2p */
hi = (slimb_t) (c[DIGITS - 1] - DELTA);
c[DIGITS - 1] = (limb_t) ((hi & LMASK) + DELTA);
c[DIGITS / 2] = (limb_t) (c[DIGITS / 2] + (hi >> LGX));

/* Strong reduce. First subtract modulus */
scarry = hi >> LGX;
for (size_t i = 0; i < DIGITS; i++) {
scarry = scarry + (slimb_t)c[i] - PQCLEAN_BABYBEAREPHEM_CLEAN_modulus(i);
c[i] = scarry & LMASK;
scarry >>= LGX;
}

/* add it back */
carry = 0;
for (size_t i = 0; i < DIGITS; i++) {
carry = carry + c[i] + ((dlimb_t)scarry & PQCLEAN_BABYBEAREPHEM_CLEAN_modulus(i));
c[i] = carry & LMASK;
carry >>= LGX;
}
}

/** Serialize a gf_t to bytes */
void PQCLEAN_BABYBEAREPHEM_CLEAN_contract(uint8_t ch[GF_BYTES], gf_t a) {
size_t pos;

PQCLEAN_BABYBEAREPHEM_CLEAN_canon(a);
for (size_t i = 0; i < GF_BYTES; i++) {
pos = (i * 8) / LGX;
ch[i] = (uint8_t)(a[pos] >> ((i * 8) % LGX));
if (i < GF_BYTES - 1) {
ch[i] |= (uint8_t)(a[pos + 1] << (LGX - ((i * 8) % LGX)));
}
}
}

/** Deserialize a gf_t from bytes */
void PQCLEAN_BABYBEAREPHEM_CLEAN_expand(gf_t ll, const uint8_t ch[GF_BYTES]) {
limb_t tmp, buffer = 0;

for (size_t i = 0, j = 0, bbits = 0; i < GF_BYTES; i++) {
tmp = ch[i];
buffer |= (limb_t)(tmp << bbits);
bbits += 8;
if (bbits >= LGX) {
ll[j++] = buffer & LMASK;
buffer = (limb_t)(tmp >> (LGX - (bbits - 8)));
bbits = bbits - LGX;
}
}
}

+ 0
- 29
crypto_kem/babybear-ephem/clean/ring.h View File

@@ -1,29 +0,0 @@
#ifndef __THREEBEARS_RING_H__
#define __THREEBEARS_RING_H__

#include "api.h"
#include "params.h"

typedef uint16_t limb_t;
typedef int16_t slimb_t;
typedef uint32_t dlimb_t;
typedef int32_t dslimb_t;
#define LMASK (((limb_t)1<<LGX)-1)
typedef limb_t gf_t[DIGITS];

/* Serialize a gf_t */
void PQCLEAN_BABYBEAREPHEM_CLEAN_contract(uint8_t ch[GF_BYTES], gf_t a);

/* Deserialize a gf_t */
void PQCLEAN_BABYBEAREPHEM_CLEAN_expand(gf_t ll, const uint8_t ch[GF_BYTES]);

/* Multiply and accumulate c = c + a*b */
void PQCLEAN_BABYBEAREPHEM_CLEAN_mac(gf_t c, const gf_t a, const gf_t b);

/* Reduce ring element to canonical form */
void PQCLEAN_BABYBEAREPHEM_CLEAN_canon(gf_t c);

/** Return the i'th limb of the modulus */
limb_t PQCLEAN_BABYBEAREPHEM_CLEAN_modulus(size_t i);

#endif

+ 0
- 219
crypto_kem/babybear-ephem/clean/threebears.c View File

@@ -1,219 +0,0 @@
/** ThreeBears reference implementation */
#include "api.h"
#include "melas_fec.h"
#include "params.h"
#include "ring.h"
#include "sp800-185.h"
#include "threebears.h"

#define FEC_BYTES ((FEC_BITS+7)/8)
#define ENC_BITS (ENC_SEED_BYTES*8 + FEC_BITS)

enum { HASH_PURPOSE_UNIFORM = 0, HASH_PURPOSE_KEYGEN = 1, HASH_PURPOSE_ENCAPS = 2, HASH_PURPOSE_PRF = 3 };

/** Initialize the hash function with a given purpose */
static void threebears_hash_init(
shake256incctx *ctx,
uint8_t purpose
) {
const unsigned char S[] = "ThreeBears";
const uint8_t pblock[15] = {
VERSION, PRIVATE_KEY_BYTES, MATRIX_SEED_BYTES, ENC_SEED_BYTES,
IV_BYTES, SHARED_SECRET_BYTES, LGX, DIGITS & 0xFF, DIGITS >> 8, DIM,
VAR_TIMES_128 - 1, LPR_BITS, FEC_BITS, CCA, 0 /* padding */
};

cshake256_inc_init(ctx, NULL, 0, (const uint8_t *)S, sizeof(S) - 1);
cshake256_inc_absorb(ctx, (const uint8_t *)pblock, sizeof(pblock));
cshake256_inc_absorb(ctx, &purpose, 1);
}

/** Sample n gf_t's uniformly from a seed */
static void uniform(gf_t matrix, const uint8_t *seed, uint8_t iv) {
uint8_t c[GF_BYTES];
shake256incctx ctx;

threebears_hash_init(&ctx, HASH_PURPOSE_UNIFORM);
cshake256_inc_absorb(&ctx, seed, MATRIX_SEED_BYTES);
cshake256_inc_absorb(&ctx, &iv, 1);
cshake256_inc_finalize(&ctx);
cshake256_inc_squeeze(c, sizeof(c), &ctx);
cshake256_inc_ctx_release(&ctx);
PQCLEAN_BABYBEAREPHEM_CLEAN_expand(matrix, c);
}

/** The ThreeBears error distribution */
static slimb_t psi(uint8_t ci) {
int sample = 0, var = VAR_TIMES_128;

for (; var > 64; var -= 64, ci = (uint8_t)(ci << 2)) {
sample += ((ci + 64) >> 8) + ((ci - 64) >> 8);
}
return (slimb_t)(sample + ((ci + var) >> 8) + ((ci - var) >> 8));
}

/** Sample a vector of n noise elements */
static void noise(gf_t x, const shake256incctx *ctx, uint8_t iv) {
uint8_t c[DIGITS];
shake256incctx ctx2;

cshake256_inc_ctx_clone(&ctx2, ctx);
cshake256_inc_absorb(&ctx2, &iv, 1);
cshake256_inc_finalize(&ctx2);
cshake256_inc_squeeze(c, DIGITS, &ctx2);
for (size_t i = 0; i < DIGITS; i++) {
x[i] = (limb_t)(psi(c[i]) + PQCLEAN_BABYBEAREPHEM_CLEAN_modulus(i));
}
cshake256_inc_ctx_release(&ctx2);
}

/* Expand public key from private key */
void PQCLEAN_BABYBEAREPHEM_CLEAN_get_pubkey(uint8_t *pk, const uint8_t *sk) {
shake256incctx ctx;
shake256incctx ctx2;
gf_t sk_expanded[DIM], b, c;

threebears_hash_init(&ctx, HASH_PURPOSE_KEYGEN);
cshake256_inc_absorb(&ctx, sk, PRIVATE_KEY_BYTES);

cshake256_inc_ctx_clone(&ctx2, &ctx);
cshake256_inc_finalize(&ctx2);
cshake256_inc_squeeze(pk, MATRIX_SEED_BYTES, &ctx2);
cshake256_inc_ctx_release(&ctx2);

for (uint8_t i = 0; i < DIM; i++) {
noise(sk_expanded[i], &ctx, i);
}
for (uint8_t i = 0; i < DIM; i++) {
noise(c, &ctx, (uint8_t)(i + DIM));
for (uint8_t j = 0; j < DIM; j++) {
uniform(b, pk, (uint8_t) (i + DIM * j));
PQCLEAN_BABYBEAREPHEM_CLEAN_mac(c, b, sk_expanded[j]);
}
PQCLEAN_BABYBEAREPHEM_CLEAN_contract(&pk[MATRIX_SEED_BYTES + i * GF_BYTES], c);
}
cshake256_inc_ctx_release(&ctx);
}

/* Encapsulate a shared secret and return it */
void PQCLEAN_BABYBEAREPHEM_CLEAN_encapsulate(
uint8_t *shared_secret,
uint8_t *capsule,
const uint8_t *pk,
const uint8_t *seed
) {
uint8_t *lpr_data = &capsule[GF_BYTES * DIM];
shake256incctx ctx;
gf_t sk_expanded[DIM], b, c;
uint8_t tbi[ENC_SEED_BYTES + FEC_BYTES];
dlimb_t rlimb0, rlimb1;
limb_t h;
uint8_t *iv = &lpr_data[(ENC_BITS * LPR_BITS + 7) / 8];

memcpy(iv, &seed[ENC_SEED_BYTES], IV_BYTES);

threebears_hash_init(&ctx, HASH_PURPOSE_ENCAPS);
cshake256_inc_absorb(&ctx, pk, MATRIX_SEED_BYTES);
cshake256_inc_absorb(&ctx, seed, ENC_SEED_BYTES + IV_BYTES);

for (uint8_t i = 0; i < DIM; i++) {
noise(sk_expanded[i], &ctx, i);
}
for (uint8_t i = 0; i < DIM; i++) {
noise(c, &ctx, (uint8_t)(i + DIM));
for (uint8_t j = 0; j < DIM; j++) {
uniform(b, pk, (uint8_t)(j + DIM * i));
PQCLEAN_BABYBEAREPHEM_CLEAN_mac(c, b, sk_expanded[j]);
}
PQCLEAN_BABYBEAREPHEM_CLEAN_contract(&capsule[i * GF_BYTES], c);
}
noise(c, &ctx, (uint8_t)(2 * DIM));

/* Calculate approximate shared secret */
for (uint8_t i = 0; i < DIM; i++) {
PQCLEAN_BABYBEAREPHEM_CLEAN_expand(b, &pk[MATRIX_SEED_BYTES + i * GF_BYTES]);
PQCLEAN_BABYBEAREPHEM_CLEAN_mac(c, b, sk_expanded[i]);
}
PQCLEAN_BABYBEAREPHEM_CLEAN_canon(c);


cshake256_inc_finalize(&ctx);
cshake256_inc_squeeze(tbi, ENC_SEED_BYTES, &ctx);
cshake256_inc_ctx_release(&ctx);

threebears_hash_init(&ctx, HASH_PURPOSE_ENCAPS);
cshake256_inc_absorb(&ctx, pk, MATRIX_SEED_BYTES);
cshake256_inc_absorb(&ctx, tbi, ENC_SEED_BYTES);
cshake256_inc_absorb(&ctx, iv, IV_BYTES);

PQCLEAN_BABYBEAREPHEM_CLEAN_melas_fec_set(&tbi[ENC_SEED_BYTES], tbi, ENC_SEED_BYTES);

/* Export with rounding */
for (size_t i = 0; i < ENC_BITS; i += 2) {
h = (limb_t)(tbi[i / 8] >> (i % 8));
rlimb0 = (dlimb_t)((c[i / 2] >> (LGX - LPR_BITS)) + (h << 3));
rlimb1 = (dlimb_t)((c[DIGITS - i / 2 - 1] >> (LGX - LPR_BITS)) + ((h >> 1) << 3));
lpr_data[i / 2] = (uint8_t)((rlimb0 & 0xF) | rlimb1 << 4);
}

cshake256_inc_finalize(&ctx);
cshake256_inc_squeeze(shared_secret, SHARED_SECRET_BYTES, &ctx);
cshake256_inc_ctx_release(&ctx);
}

/* Decapsulate a shared secret and return it */
void PQCLEAN_BABYBEAREPHEM_CLEAN_decapsulate(
uint8_t shared_secret[SHARED_SECRET_BYTES],
const uint8_t capsule[CAPSULE_BYTES],
const uint8_t sk[PRIVATE_KEY_BYTES]
) {
const uint8_t *lpr_data = &capsule[GF_BYTES * DIM];
shake256incctx ctx;
gf_t ska, b, c = {0};
uint8_t seed[ENC_SEED_BYTES + FEC_BYTES + IV_BYTES];
limb_t rounding, out;
size_t j;
limb_t our_rlimb, their_rlimb, delta;
uint8_t matrix_seed[MATRIX_SEED_BYTES];

/* Calculate approximate shared secret */
threebears_hash_init(&ctx, HASH_PURPOSE_KEYGEN);
cshake256_inc_absorb(&ctx, sk, PRIVATE_KEY_BYTES);

for (uint8_t i = 0; i < DIM; i++) {
PQCLEAN_BABYBEAREPHEM_CLEAN_expand(b, &capsule[i * GF_BYTES]);
noise(ska, &ctx, i);
PQCLEAN_BABYBEAREPHEM_CLEAN_mac(c, ska, b);
}

/* Recover seed from LPR data */
PQCLEAN_BABYBEAREPHEM_CLEAN_canon(c);
rounding = 1 << (LPR_BITS - 1);
out = 0;
for (int32_t i = ENC_BITS - 1; i >= 0; i--) {
j = (size_t) ((i & 1) ? DIGITS - i / 2 - 1 : i / 2);
our_rlimb = (limb_t)(c[j] >> (LGX - LPR_BITS - 1));
their_rlimb = (limb_t)(lpr_data[i * LPR_BITS / 8] >> ((i * LPR_BITS) % 8));
delta = (limb_t)(their_rlimb * 2 - our_rlimb + rounding);
out |= (limb_t)(((delta >> LPR_BITS) & 1) << (i % 8));
if (i % 8 == 0) {
seed[i / 8] = (uint8_t)out;
out = 0;
}
}
PQCLEAN_BABYBEAREPHEM_CLEAN_melas_fec_correct(seed, ENC_SEED_BYTES, &seed[ENC_SEED_BYTES]);

/* Recalculate matrix seed */
cshake256_inc_finalize(&ctx);
cshake256_inc_squeeze(matrix_seed, MATRIX_SEED_BYTES, &ctx);
cshake256_inc_ctx_release(&ctx);

/* Re-run the key derivation from encaps */
threebears_hash_init(&ctx, HASH_PURPOSE_ENCAPS);
cshake256_inc_absorb(&ctx, matrix_seed, MATRIX_SEED_BYTES);
cshake256_inc_absorb(&ctx, seed, ENC_SEED_BYTES);
cshake256_inc_absorb(&ctx, &lpr_data[(ENC_BITS * LPR_BITS + 7) / 8], IV_BYTES);
cshake256_inc_finalize(&ctx);
cshake256_inc_squeeze(shared_secret, SHARED_SECRET_BYTES, &ctx);
cshake256_inc_ctx_release(&ctx);
}

+ 0
- 60
crypto_kem/babybear-ephem/clean/threebears.h View File

@@ -1,60 +0,0 @@
#ifndef __THREE_BEARS_BABYBEAREPHEM_H__
#define __THREE_BEARS_BABYBEAREPHEM_H__

#include <stddef.h> /* for size_t */
#include <stdint.h>

#define BABYBEAREPHEM_KEYGEN_SEED_BYTES 40
#define BABYBEAREPHEM_PRIVATE_KEY_BYTES BABYBEAREPHEM_KEYGEN_SEED_BYTES
#define BABYBEAREPHEM_SHARED_SECRET_BYTES 32
#define BABYBEAREPHEM_ENC_SEED_AND_IV_BYTES 32
#define BABYBEAREPHEM_PUBLIC_KEY_BYTES 804
#define BABYBEAREPHEM_CAPSULE_BYTES 917

/**
* Expand a secret seed to a public/private keypair.
*
* @param[out] pk The public key.
* @param[in] sk The private key, which must be uniformly random.
*/
void PQCLEAN_BABYBEAREPHEM_CLEAN_get_pubkey (
uint8_t pk[BABYBEAREPHEM_PUBLIC_KEY_BYTES],
const uint8_t sk[BABYBEAREPHEM_PRIVATE_KEY_BYTES]
);

/**
* Create a shared secret using a random seed and another party's public key.
*
* Input and output parameters may not alias.
*
* @param[out] shared_secret The shared secret key.
* @param[out] capsule A ciphertext to send to the other party.
* @param[in] pk The other party's public key.
* @param[in] seed A random seed.
*/
void PQCLEAN_BABYBEAREPHEM_CLEAN_encapsulate (
uint8_t shared_secret[BABYBEAREPHEM_SHARED_SECRET_BYTES],
uint8_t capsule[BABYBEAREPHEM_CAPSULE_BYTES],
const uint8_t pk[BABYBEAREPHEM_PUBLIC_KEY_BYTES],
const uint8_t seed[BABYBEAREPHEM_ENC_SEED_AND_IV_BYTES]
);

/**
* Extract the shared secret from a capsule using the private key.
* Has a negligible but nonzero probability of failure.
*
* Input and output parameters may not alias.
*
* @param[out] shared_secret The shared secret.
* @param[in] capsule The capsule produced by encapsulate_cca2.
* @param[in] sk The private key.
* @return -1 on failure, 0 on success.
* @warning The value of shared_secret must not be used on failure
*/
void PQCLEAN_BABYBEAREPHEM_CLEAN_decapsulate (
uint8_t shared_secret[BABYBEAREPHEM_SHARED_SECRET_BYTES],
const uint8_t capsule[BABYBEAREPHEM_CAPSULE_BYTES],
const uint8_t sk[BABYBEAREPHEM_PRIVATE_KEY_BYTES]
);

#endif

+ 0
- 14
crypto_kem/babybear/META.yml View File

@@ -1,14 +0,0 @@
name: BabyBear
type: kem
claimed-nist-level: 1
claimed-security: IND-CCA2
length-public-key: 804
length-ciphertext: 917
length-secret-key: 40
length-shared-secret: 32
nistkat-sha256: b8442ffaad8e74c6ebfd75d02e13f8db017a7a6dd8458f5d1a5011de6057d775
principal-submitters:
- Mike Hamburg
implementations:
- name: clean
version: https://sourceforge.net/p/threebears/code/ci/f4ce0ebfc84a5e01a75bfc8297b6d175e993cfa4/

+ 0
- 24
crypto_kem/babybear/clean/LICENSE View File

@@ -1,24 +0,0 @@
Copyright (c) 2016-2019 Rambus, Inc.
and licensed under the following MIT license.

The MIT License (MIT)

Copyright (c) 2016-2019 Rambus Inc.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

+ 0
- 21
crypto_kem/babybear/clean/Makefile View File

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

LIB=libbabybear_clean.a

HEADERS = api.h melas_fec.h params.h ring.h threebears.h
OBJECTS = kem.o melas_fec.o ring.o threebears.o


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

all: $(LIB)

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

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

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

+ 0
- 19
crypto_kem/babybear/clean/Makefile.Microsoft_nmake View File

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

LIBRARY=libbabybear_clean.lib
OBJECTS = kem.obj melas_fec.obj ring.obj threebears.obj

CFLAGS=/nologo /I ..\..\..\common /W4 /WX

all: $(LIBRARY)

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

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

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

+ 0
- 18
crypto_kem/babybear/clean/api.h View File

@@ -1,18 +0,0 @@
#ifndef PQCLEAN_BABYBEAR_CLEAN_API_H
#define PQCLEAN_BABYBEAR_CLEAN_API_H

#include <stddef.h>
#include <stdint.h>
#include <string.h>

#define PQCLEAN_BABYBEAR_CLEAN_CRYPTO_SECRETKEYBYTES 40
#define PQCLEAN_BABYBEAR_CLEAN_CRYPTO_PUBLICKEYBYTES 804
#define PQCLEAN_BABYBEAR_CLEAN_CRYPTO_BYTES 32
#define PQCLEAN_BABYBEAR_CLEAN_CRYPTO_CIPHERTEXTBYTES 917
#define PQCLEAN_BABYBEAR_CLEAN_CRYPTO_ALGNAME "BabyBear"

int PQCLEAN_BABYBEAR_CLEAN_crypto_kem_keypair(uint8_t *pk, uint8_t *sk);
int PQCLEAN_BABYBEAR_CLEAN_crypto_kem_enc(uint8_t *ct, uint8_t *ss, const uint8_t *pk);
int PQCLEAN_BABYBEAR_CLEAN_crypto_kem_dec(uint8_t *ss, const uint8_t *ct, const uint8_t *sk);

#endif

+ 0
- 22
crypto_kem/babybear/clean/kem.c View File

@@ -1,22 +0,0 @@
#include "api.h"
#include "params.h"
#include "randombytes.h"
#include "threebears.h"

int PQCLEAN_BABYBEAR_CLEAN_crypto_kem_keypair(uint8_t *pk, uint8_t *sk) {
randombytes(sk, PRIVATE_KEY_BYTES);
PQCLEAN_BABYBEAR_CLEAN_get_pubkey(pk, sk);
return 0;
}

int PQCLEAN_BABYBEAR_CLEAN_crypto_kem_enc(uint8_t *ct, uint8_t *ss, const uint8_t *pk) {
uint8_t seed[ENC_SEED_BYTES + IV_BYTES];
randombytes(seed, sizeof(seed));
encapsulate(ss, ct, pk, seed);
return 0;
}

int PQCLEAN_BABYBEAR_CLEAN_crypto_kem_dec(uint8_t *ss, const uint8_t *ct, const uint8_t *sk) {
PQCLEAN_BABYBEAR_CLEAN_decapsulate(ss, ct, sk);
return 0;
}

+ 0
- 87
crypto_kem/babybear/clean/melas_fec.c View File

@@ -1,87 +0,0 @@
/* Melas forward error correction, reference code (as implemented in the paper) */
#include "melas_fec.h"

/* Return s/2^n mod R */
static fec_gf_t step(size_t n, fec_gf_t R, fec_gf_t s) {
for (; n; n--) {
s = (s ^ ((s & 1) * R)) >> 1;
}
return s;
}

/* Compute syndrome(data), where data has length len */
#define syndrome18(data,len) s18update(0,data,len)
static fec_gf_t s18update(fec_gf_t r, const uint8_t *data, size_t len) {
for (size_t i = 0; i < len; i++) {
r = step(8, 0x46231, r ^ data[i]);
}
return r;
}

/* Append 3 bytes of FEC(data) to data, so that the FEC becomes 0 */
void PQCLEAN_BABYBEAR_CLEAN_melas_fec_set(
uint8_t out[MELAS_FEC_BYTES],
const uint8_t *data,
size_t len
) {
fec_gf_t fec = syndrome18(data, len);
for (size_t i = 0; i < MELAS_FEC_BYTES; i++, fec >>= 8) {
out[i] = (uint8_t)fec;
}
}

/* Return a*b mod Q */
static fec_gf_t mul(fec_gf_t a, fec_gf_t b) {
fec_gf_t r = 0;
for (size_t i = 0; i < 9; i++) {
r ^= ((b >> (8 - i)) & 1) * a;
a = step(1, Q, a);
}
return r;
}

/* Reverse an 18-bit number x */
static fec_gf_t reverse18(fec_gf_t x) {
fec_gf_t ret = 0;
for (size_t i = 0; i < 18; i++) {
ret ^= ((x >> i) & 1) << (17 - i);
}
return ret;
}

/* Correct data to have the given FEC */
void PQCLEAN_BABYBEAR_CLEAN_melas_fec_correct (
uint8_t *data,
size_t len,
const uint8_t fec[MELAS_FEC_BYTES]
) {

fec_gf_t a = s18update(syndrome18(data, len), fec, MELAS_FEC_BYTES);
fec_gf_t c, r, htr;
size_t i;
const uint8_t table[9] = {36, 10, 43, 215, 52, 11, 116, 244, 0};
fec_gf_t e0, e1;

/* Form a quadratic equation from the syndrome */
c = mul(step(9, Q, a), step(9, Q, reverse18(a)));
for (i = 0, r = 0x100; i < 510; i++) {
r = mul(r, c);
}
r = step(17, Q, r);
a = step(511 - (len + MELAS_FEC_BYTES) * 8, Q, a);

/* Solve using the half trace */
for (i = 0, htr = 0; i < 9; i++) {
htr ^= ((r >> i) & 1) * table[i];
}
e0 = mul(a, htr);
e1 = e0 ^ a;

/* Correct the errors using the locators */
for (i = 0; i < len; i++) {
data[i] ^= (uint8_t)(e0 & (((e0 & (e0 - 1)) - 1) >> 9));
data[i] ^= (uint8_t)(e1 & (((e1 & (e1 - 1)) - 1) >> 9));
e0 = step(8, Q, e0);
e1 = step(8, Q, e1);
}
}

+ 0
- 26
crypto_kem/babybear/clean/melas_fec.h View File

@@ -1,26 +0,0 @@
#ifndef __THREEBEARS_MELAS_FEC_H__
#define __THREEBEARS_MELAS_FEC_H__

#include "api.h"

#define MELAS_FEC_BYTES 3
#define MELAS_FEC_BITS 18

typedef uint32_t fec_gf_t;
static const fec_gf_t Q = 0x211;

/* Append 3 bytes of FEC(data) to data, so that the FEC becomes 0 */
void PQCLEAN_BABYBEAR_CLEAN_melas_fec_set(
uint8_t out[MELAS_FEC_BYTES],
const uint8_t *data,
size_t len
);

/* Append 3 bytes of FEC(data) to data, so that the FEC becomes 0 */
void PQCLEAN_BABYBEAR_CLEAN_melas_fec_correct(
uint8_t *data,
size_t len,
const uint8_t fec[MELAS_FEC_BYTES]
);

#endif

+ 0
- 29
crypto_kem/babybear/clean/params.h View File

@@ -1,29 +0,0 @@
#ifndef __THREEBEARS_PARAMS_H__
#define __THREEBEARS_PARAMS_H__

#define VERSION 1
#define MATRIX_SEED_BYTES 24
#define ENC_SEED_BYTES 32
#define IV_BYTES 0
#define LGX 10
#define DIGITS 312
#define DIM 2
#define VAR_TIMES_128 72
#define LPR_BITS 4
#define FEC_BITS 18
#define CCA 1
#define SHARED_SECRET_BYTES 32
#define PRIVATE_KEY_BYTES 40
#define PRF_KEY_BYTES PRIVATE_KEY_BYTES

#define BEAR_NAME "BabyBear"
#define encapsulate PQCLEAN_BABYBEAR_CLEAN_encapsulate
#define decapsulate PQCLEAN_BABYBEAR_CLEAN_decapsulate
#define get_pubkey PQCLEAN_BABYBEAR_CLEAN_get_pubkey

#define GF_BYTES ((LGX*DIGITS+7)/8)
#define PUBLIC_KEY_BYTES (MATRIX_SEED_BYTES + DIM*GF_BYTES)
#define CAPSULE_BYTES \
(DIM*GF_BYTES + IV_BYTES + ((ENC_SEED_BYTES*8+FEC_BITS)*LPR_BITS+7)/8)

#endif

+ 0
- 107
crypto_kem/babybear/clean/ring.c View File

@@ -1,107 +0,0 @@
/** Ring arithmetic implementation */
#include "ring.h"

/** Return the i'th limb of the modulus */
limb_t PQCLEAN_BABYBEAR_CLEAN_modulus(size_t i) {
return (i == DIGITS / 2) ? LMASK - 1 : LMASK;
}

/** Multiply and accumulate c += a*b */
void PQCLEAN_BABYBEAR_CLEAN_mac(gf_t c, const gf_t a, const gf_t b) {
/* Reference non-Karatsuba MAC */
dslimb_t accum[2 * DIGITS] = {0};
dslimb_t chain;
size_t i, j;

/* Initialize accumulator = unclarify(c) */
for (i = 0; i < DIGITS; i++) {
accum[i + DIGITS / 2] = c[i];
}

/* Multiply */
for (i = 0; i < DIGITS; i++) {
for (j = 0; j < DIGITS; j++) {
accum[i + j] += (dslimb_t)a[i] * b[j];
}
}

/* Clarify and reduce */
for (i = 0; i < DIGITS / 2; i++) {
accum[i + DIGITS / 2] -= accum[i];
accum[i + DIGITS] += accum[i];
accum[i + DIGITS / 2] += accum[i + 3 * DIGITS / 2];
accum[i + DIGITS] += accum[i + 3 * DIGITS / 2];
}

/* Carry propagate */
chain = accum[3 * DIGITS / 2 - 1];
accum[3 * DIGITS / 2 - 1] = chain & LMASK;
chain >>= LGX;
accum[DIGITS] += chain;
for (i = DIGITS / 2; i < 3 * DIGITS / 2; i++) {
chain += accum[i];
c[i - DIGITS / 2] = chain & LMASK;
chain >>= LGX;
}
c[0] = (limb_t) (c[0] + chain);
c[DIGITS / 2] = (limb_t) (c[DIGITS / 2] + chain);
}

/** Reduce a gf_t to canonical form, i.e. strictly less than N. */
void PQCLEAN_BABYBEAR_CLEAN_canon(gf_t c) {
const limb_t DELTA = (limb_t)1 << (LGX - 1);
slimb_t hi;
dslimb_t scarry;
dlimb_t carry;

/* Reduce to 0..2p */
hi = (slimb_t) (c[DIGITS - 1] - DELTA);
c[DIGITS - 1] = (limb_t) ((hi & LMASK) + DELTA);
c[DIGITS / 2] = (limb_t) (c[DIGITS / 2] + (hi >> LGX));

/* Strong reduce. First subtract modulus */
scarry = hi >> LGX;
for (size_t i = 0; i < DIGITS; i++) {
scarry = scarry + (slimb_t)c[i] - PQCLEAN_BABYBEAR_CLEAN_modulus(i);
c[i] = scarry & LMASK;
scarry >>= LGX;
}

/* add it back */
carry = 0;
for (size_t i = 0; i < DIGITS; i++) {
carry = carry + c[i] + ((dlimb_t)scarry & PQCLEAN_BABYBEAR_CLEAN_modulus(i));
c[i] = carry & LMASK;
carry >>= LGX;
}
}

/** Serialize a gf_t to bytes */
void PQCLEAN_BABYBEAR_CLEAN_contract(uint8_t ch[GF_BYTES], gf_t a) {
size_t pos;

PQCLEAN_BABYBEAR_CLEAN_canon(a);
for (size_t i = 0; i < GF_BYTES; i++) {
pos = (i * 8) / LGX;
ch[i] = (uint8_t)(a[pos] >> ((i * 8) % LGX));
if (i < GF_BYTES - 1) {
ch[i] |= (uint8_t)(a[pos + 1] << (LGX - ((i * 8) % LGX)));
}
}
}

/** Deserialize a gf_t from bytes */
void PQCLEAN_BABYBEAR_CLEAN_expand(gf_t ll, const uint8_t ch[GF_BYTES]) {
limb_t tmp, buffer = 0;

for (size_t i = 0, j = 0, bbits = 0; i < GF_BYTES; i++) {
tmp = ch[i];
buffer |= (limb_t)(tmp << bbits);
bbits += 8;
if (bbits >= LGX) {
ll[j++] = buffer & LMASK;
buffer = (limb_t)(tmp >> (LGX - (bbits - 8)));
bbits = bbits - LGX;
}
}
}

+ 0
- 29
crypto_kem/babybear/clean/ring.h View File

@@ -1,29 +0,0 @@
#ifndef __THREEBEARS_RING_H__
#define __THREEBEARS_RING_H__

#include "api.h"
#include "params.h"

typedef uint16_t limb_t;
typedef int16_t slimb_t;
typedef uint32_t dlimb_t;
typedef int32_t dslimb_t;
#define LMASK (((limb_t)1<<LGX)-1)
typedef limb_t gf_t[DIGITS];

/* Serialize a gf_t */
void PQCLEAN_BABYBEAR_CLEAN_contract(uint8_t ch[GF_BYTES], gf_t a);

/* Deserialize a gf_t */
void PQCLEAN_BABYBEAR_CLEAN_expand(gf_t ll, const uint8_t ch[GF_BYTES]);

/* Multiply and accumulate c = c + a*b */
void PQCLEAN_BABYBEAR_CLEAN_mac(gf_t c, const gf_t a, const gf_t b);

/* Reduce ring element to canonical form */
void PQCLEAN_BABYBEAR_CLEAN_canon(gf_t c);

/** Return the i'th limb of the modulus */
limb_t PQCLEAN_BABYBEAR_CLEAN_modulus(size_t i);

#endif

+ 0
- 231
crypto_kem/babybear/clean/threebears.c View File

@@ -1,231 +0,0 @@
/** ThreeBears reference implementation */
#include "api.h"
#include "melas_fec.h"
#include "params.h"
#include "ring.h"
#include "sp800-185.h"
#include "threebears.h"

#define FEC_BYTES ((FEC_BITS+7)/8)
#define ENC_BITS (ENC_SEED_BYTES*8 + FEC_BITS)

enum { HASH_PURPOSE_UNIFORM = 0, HASH_PURPOSE_KEYGEN = 1, HASH_PURPOSE_ENCAPS = 2, HASH_PURPOSE_PRF = 3 };

/** Initialize the hash function with a given purpose */
static void threebears_hash_init(
shake256incctx *ctx,
uint8_t purpose
) {
const unsigned char S[] = "ThreeBears";
const uint8_t pblock[15] = {
VERSION, PRIVATE_KEY_BYTES, MATRIX_SEED_BYTES, ENC_SEED_BYTES,
IV_BYTES, SHARED_SECRET_BYTES, LGX, DIGITS & 0xFF, DIGITS >> 8, DIM,
VAR_TIMES_128 - 1, LPR_BITS, FEC_BITS, CCA, 0 /* padding */
};

cshake256_inc_init(ctx, NULL, 0, (const uint8_t *)S, sizeof(S) - 1);
cshake256_inc_absorb(ctx, (const uint8_t *)pblock, sizeof(pblock));
cshake256_inc_absorb(ctx, &purpose, 1);
}

/** Sample n gf_t's uniformly from a seed */
static void uniform(gf_t matrix, const uint8_t *seed, uint8_t iv) {
uint8_t c[GF_BYTES];
shake256incctx ctx;

threebears_hash_init(&ctx, HASH_PURPOSE_UNIFORM);
cshake256_inc_absorb(&ctx, seed, MATRIX_SEED_BYTES);
cshake256_inc_absorb(&ctx, &iv, 1);
cshake256_inc_finalize(&ctx);
cshake256_inc_squeeze(c, sizeof(c), &ctx);
cshake256_inc_ctx_release(&ctx);
PQCLEAN_BABYBEAR_CLEAN_expand(matrix, c);
}

/** The ThreeBears error distribution */
static slimb_t psi(uint8_t ci) {
int sample = 0, var = VAR_TIMES_128;

for (; var > 64; var -= 64, ci = (uint8_t)(ci << 2)) {
sample += ((ci + 64) >> 8) + ((ci - 64) >> 8);
}
return (slimb_t)(sample + ((ci + var) >> 8) + ((ci - var) >> 8));
}

/** Sample a vector of n noise elements */
static void noise(gf_t x, const shake256incctx *ctx, uint8_t iv) {
uint8_t c[DIGITS];
shake256incctx ctx2;

cshake256_inc_ctx_clone(&ctx2, ctx);
cshake256_inc_absorb(&ctx2, &iv, 1);
cshake256_inc_finalize(&ctx2);
cshake256_inc_squeeze(c, DIGITS, &ctx2);
for (size_t i = 0; i < DIGITS; i++) {
x[i] = (limb_t)(psi(c[i]) + PQCLEAN_BABYBEAR_CLEAN_modulus(i));
}
cshake256_inc_ctx_release(&ctx2);
}

/* Expand public key from private key */
void PQCLEAN_BABYBEAR_CLEAN_get_pubkey(uint8_t *pk, const uint8_t *sk) {
shake256incctx ctx;
shake256incctx ctx2;
gf_t sk_expanded[DIM], b, c;

threebears_hash_init(&ctx, HASH_PURPOSE_KEYGEN);
cshake256_inc_absorb(&ctx, sk, PRIVATE_KEY_BYTES);

cshake256_inc_ctx_clone(&ctx2, &ctx);
cshake256_inc_finalize(&ctx2);
cshake256_inc_squeeze(pk, MATRIX_SEED_BYTES, &ctx2);
cshake256_inc_ctx_release(&ctx2);

for (uint8_t i = 0; i < DIM; i++) {
noise(sk_expanded[i], &ctx, i);
}
for (uint8_t i = 0; i < DIM; i++) {
noise(c, &ctx, (uint8_t)(i + DIM));
for (uint8_t j = 0; j < DIM; j++) {
uniform(b, pk, (uint8_t) (i + DIM * j));
PQCLEAN_BABYBEAR_CLEAN_mac(c, b, sk_expanded[j]);
}
PQCLEAN_BABYBEAR_CLEAN_contract(&pk[MATRIX_SEED_BYTES + i * GF_BYTES], c);
}
cshake256_inc_ctx_release(&ctx);
}

/* Encapsulate a shared secret and return it */
void PQCLEAN_BABYBEAR_CLEAN_encapsulate(
uint8_t *shared_secret,
uint8_t *capsule,
const uint8_t *pk,
const uint8_t *seed
) {
uint8_t *lpr_data = &capsule[GF_BYTES * DIM];
shake256incctx ctx;
gf_t sk_expanded[DIM], b, c;
uint8_t tbi[ENC_SEED_BYTES + FEC_BYTES];
dlimb_t rlimb0, rlimb1;
limb_t h;
uint8_t *iv = &lpr_data[(ENC_BITS * LPR_BITS + 7) / 8];

memcpy(iv, &seed[ENC_SEED_BYTES], IV_BYTES);

threebears_hash_init(&ctx, HASH_PURPOSE_ENCAPS);
cshake256_inc_absorb(&ctx, pk, MATRIX_SEED_BYTES);
cshake256_inc_absorb(&ctx, seed, ENC_SEED_BYTES + IV_BYTES);

for (uint8_t i = 0; i < DIM; i++) {
noise(sk_expanded[i], &ctx, i);
}
for (uint8_t i = 0; i < DIM; i++) {
noise(c, &ctx, (uint8_t)(i + DIM));
for (uint8_t j = 0; j < DIM; j++) {
uniform(b, pk, (uint8_t)(j + DIM * i));
PQCLEAN_BABYBEAR_CLEAN_mac(c, b, sk_expanded[j]);
}
PQCLEAN_BABYBEAR_CLEAN_contract(&capsule[i * GF_BYTES], c);
}
noise(c, &ctx, (uint8_t)(2 * DIM));

/* Calculate approximate shared secret */
for (uint8_t i = 0; i < DIM; i++) {
PQCLEAN_BABYBEAR_CLEAN_expand(b, &pk[MATRIX_SEED_BYTES + i * GF_BYTES]);
PQCLEAN_BABYBEAR_CLEAN_mac(c, b, sk_expanded[i]);
}
PQCLEAN_BABYBEAR_CLEAN_canon(c);


memcpy(tbi, seed, ENC_SEED_BYTES);

PQCLEAN_BABYBEAR_CLEAN_melas_fec_set(&tbi[ENC_SEED_BYTES], tbi, ENC_SEED_BYTES);

/* Export with rounding */
for (size_t i = 0; i < ENC_BITS; i += 2) {
h = (limb_t)(tbi[i / 8] >> (i % 8));
rlimb0 = (dlimb_t)((c[i / 2] >> (LGX - LPR_BITS)) + (h << 3));
rlimb1 = (dlimb_t)((c[DIGITS - i / 2 - 1] >> (LGX - LPR_BITS)) + ((h >> 1) << 3));
lpr_data[i / 2] = (uint8_t)((rlimb0 & 0xF) | rlimb1 << 4);
}

cshake256_inc_finalize(&ctx);
cshake256_inc_squeeze(shared_secret, SHARED_SECRET_BYTES, &ctx);
cshake256_inc_ctx_release(&ctx);
}

/* Decapsulate a shared secret and return it */
void PQCLEAN_BABYBEAR_CLEAN_decapsulate(
uint8_t shared_secret[SHARED_SECRET_BYTES],
const uint8_t capsule[CAPSULE_BYTES],
const uint8_t sk[PRIVATE_KEY_BYTES]
) {
const uint8_t *lpr_data = &capsule[GF_BYTES * DIM];
shake256incctx ctx;
gf_t ska, b, c = {0};
uint8_t seed[ENC_SEED_BYTES + FEC_BYTES + IV_BYTES];
limb_t rounding, out;
size_t j;
limb_t our_rlimb, their_rlimb, delta;
uint8_t pk[PUBLIC_KEY_BYTES], capsule2[CAPSULE_BYTES];
uint8_t ret, ok, sep, prfk[PRF_KEY_BYTES];
uint8_t prfout[SHARED_SECRET_BYTES];

/* Calculate approximate shared secret */
threebears_hash_init(&ctx, HASH_PURPOSE_KEYGEN);
cshake256_inc_absorb(&ctx, sk, PRIVATE_KEY_BYTES);

for (uint8_t i = 0; i < DIM; i++) {
PQCLEAN_BABYBEAR_CLEAN_expand(b, &capsule[i * GF_BYTES]);
noise(ska, &ctx, i);
PQCLEAN_BABYBEAR_CLEAN_mac(c, ska, b);
}

/* Recover seed from LPR data */
PQCLEAN_BABYBEAR_CLEAN_canon(c);
rounding = 1 << (LPR_BITS - 1);
out = 0;
for (int32_t i = ENC_BITS - 1; i >= 0; i--) {
j = (size_t) ((i & 1) ? DIGITS - i / 2 - 1 : i / 2);
our_rlimb = (limb_t)(c[j] >> (LGX - LPR_BITS - 1));
their_rlimb = (limb_t)(lpr_data[i * LPR_BITS / 8] >> ((i * LPR_BITS) % 8));
delta = (limb_t)(their_rlimb * 2 - our_rlimb + rounding);
out |= (limb_t)(((delta >> LPR_BITS) & 1) << (i % 8));
if (i % 8 == 0) {
seed[i / 8] = (uint8_t)out;
out = 0;
}
}
PQCLEAN_BABYBEAR_CLEAN_melas_fec_correct(seed, ENC_SEED_BYTES, &seed[ENC_SEED_BYTES]);

/* Re-encapsulate and check; encapsulate will compute the shared secret */
PQCLEAN_BABYBEAR_CLEAN_get_pubkey(pk, sk);
memcpy(&seed[ENC_SEED_BYTES], &lpr_data[(ENC_BITS * LPR_BITS + 7) / 8], IV_BYTES);
PQCLEAN_BABYBEAR_CLEAN_encapsulate(shared_secret, capsule2, pk, seed);

/* Check capsule == capsule2 in constant time */
ret = 0;
for (size_t i = 0; i < CAPSULE_BYTES; i++) {
ret |= capsule[i] ^ capsule2[i];
}
ok = (uint8_t)(((int)ret - 1) >> 8);

/* Calculate PRF key */
sep = 0xFF;
cshake256_inc_absorb(&ctx, &sep, 1);
cshake256_inc_finalize(&ctx);
cshake256_inc_squeeze(prfk, PRF_KEY_BYTES, &ctx);
cshake256_inc_ctx_release(&ctx);

/* Calculate PRF */
threebears_hash_init(&ctx, HASH_PURPOSE_PRF);
cshake256_inc_absorb(&ctx, prfk, PRF_KEY_BYTES);
cshake256_inc_absorb(&ctx, capsule, CAPSULE_BYTES);
cshake256_inc_finalize(&ctx);
cshake256_inc_squeeze(prfout, SHARED_SECRET_BYTES, &ctx);
cshake256_inc_ctx_release(&ctx);

for (size_t i = 0; i < SHARED_SECRET_BYTES; i++) {
shared_secret[i] = (uint8_t)((shared_secret[i] & ok) | (prfout[i] & ~ok));
}
}

+ 0
- 58
crypto_kem/babybear/clean/threebears.h View File

@@ -1,58 +0,0 @@
#ifndef __THREE_BEARS_BABYBEAR_H__
#define __THREE_BEARS_BABYBEAR_H__

#include <stddef.h> /* for size_t */
#include <stdint.h>

#define BABYBEAR_KEYGEN_SEED_BYTES 40
#define BABYBEAR_PRIVATE_KEY_BYTES BABYBEAR_KEYGEN_SEED_BYTES
#define BABYBEAR_SHARED_SECRET_BYTES 32
#define BABYBEAR_ENC_SEED_AND_IV_BYTES 32
#define BABYBEAR_PUBLIC_KEY_BYTES 804
#define BABYBEAR_CAPSULE_BYTES 917

/**
* Expand a secret seed to a public/private keypair.
*
* @param[out] pk The public key.
* @param[in] sk The private key, which must be uniformly random.
*/
void PQCLEAN_BABYBEAR_CLEAN_get_pubkey (
uint8_t pk[BABYBEAR_PUBLIC_KEY_BYTES],
const uint8_t sk[BABYBEAR_PRIVATE_KEY_BYTES]
);

/**
* Create a shared secret using a random seed and another party's public key.
*
* Input and output parameters may not alias.
*
* @param[out] shared_secret The shared secret key.
* @param[out] capsule A ciphertext to send to the other party.
* @param[in] pk The other party's public key.
* @param[in] seed A random seed.
*/
void PQCLEAN_BABYBEAR_CLEAN_encapsulate (
uint8_t shared_secret[BABYBEAR_SHARED_SECRET_BYTES],
uint8_t capsule[BABYBEAR_CAPSULE_BYTES],
const uint8_t pk[BABYBEAR_PUBLIC_KEY_BYTES],
const uint8_t seed[BABYBEAR_ENC_SEED_AND_IV_BYTES]
);

/**
* Extract the shared secret from a capsule using the private key.
* Has a negligible but nonzero probability of failure.
*
* Input and output parameters may not alias.
*
* @param[out] shared_secret The shared secret.
* @param[in] capsule The capsule produced by encapsulate_cca2.
* @param[in] sk The private key.
*/
void PQCLEAN_BABYBEAR_CLEAN_decapsulate (
uint8_t shared_secret[BABYBEAR_SHARED_SECRET_BYTES],
const uint8_t capsule[BABYBEAR_CAPSULE_BYTES],
const uint8_t sk[BABYBEAR_PRIVATE_KEY_BYTES]
);

#endif

+ 0
- 19
crypto_kem/ledakemlt12/META.yml View File

@@ -1,19 +0,0 @@
name: LEDAKEMLT12
type: kem
claimed-nist-level: 1
claimed-security: IND-CCA2
length-public-key: 6520
length-secret-key: 50
length-ciphertext: 6544
length-shared-secret: 32
nistkat-sha256: c0bd75093e2bbae8bf5717939c59c3c695ee9a60d765fcf6fb06d8db385b04c7
principal-submitters:
- Marco Baldi
auxiliary-submitters:
- Alessandro Barenghi
- Franco Chiaraluce
- Gerardo Pelosi
- Paolo Santini
implementations:
- name: leaktime
version: 2.1

+ 0
- 52
crypto_kem/ledakemlt12/leaktime/H_Q_matrices_generation.c View File

@@ -1,52 +0,0 @@
#include "H_Q_matrices_generation.h"
#include "gf2x_arith_mod_xPplusOne.h"

void PQCLEAN_LEDAKEMLT12_LEAKTIME_generateHPosOnes(POSITION_T HPosOnes[N0][DV], AES_XOF_struct *keys_expander) {
for (size_t i = 0; i < N0; i++) {
/* Generate a random block of Htr */
PQCLEAN_LEDAKEMLT12_LEAKTIME_rand_circulant_sparse_block(&HPosOnes[i][0], DV, keys_expander);
}
}

void PQCLEAN_LEDAKEMLT12_LEAKTIME_generateQPosOnes(POSITION_T QPosOnes[N0][M], AES_XOF_struct *keys_expander) {
size_t placed_ones;

for (size_t i = 0; i < N0; i++) {
placed_ones = 0;
for (size_t j = 0; j < N0; j++) {
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], POSITION_T HPosOnes[N0][DV]) {
for (size_t i = 0; i < N0; i++) {
/* Obtain directly the sparse representation of the block of H */
for (size_t k = 0; k < DV; k++) {
HtrPosOnes[i][k] = (P - HPosOnes[i][k]) % P; /* transposes indexes */
}
}
}

void PQCLEAN_LEDAKEMLT12_LEAKTIME_transposeQPosOnes(POSITION_T QtrPosOnes[N0][M], POSITION_T QPosOnes[N0][M]) {
POSITION_T transposed_ones_idx[N0] = {0x00};
size_t currQoneIdx, endQblockIdx;

for (size_t 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]++;
}
}
}
}



+ 0
- 13
crypto_kem/ledakemlt12/leaktime/H_Q_matrices_generation.h View File

@@ -1,13 +0,0 @@
#ifndef H_Q_MATRICES_GENERATION_H
#define H_Q_MATRICES_GENERATION_H

#include "gf2x_arith.h"
#include "qc_ldpc_parameters.h"
#include "rng.h"

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

+ 0
- 31
crypto_kem/ledakemlt12/leaktime/LICENSE View File

@@ -1,31 +0,0 @@
/**
*
* LEDAcryptKEM
*
* @version 2.0 (March 2019)
*
* Adapted code from reference ISO-C11 Implementation of the LEDAcrypt KEM-LT cipher.
*
* In alphabetical order:
*
* @author Marco Baldi <m.baldi@univpm.it>
* @author Alessandro Barenghi <alessandro.barenghi@polimi.it>
* @author Franco Chiaraluce <f.chiaraluce@univpm.it>
* @author Gerardo Pelosi <gerardo.pelosi@polimi.it>
* @author Paolo Santini <p.santini@pm.univpm.it>
*
* This code is hereby placed in the public domain.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
**/

+ 0
- 24
crypto_kem/ledakemlt12/leaktime/Makefile View File

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

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 sort.h utils.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 sort.o utils.o

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

all: $(LIB)

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

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

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

+ 0
- 19
crypto_kem/ledakemlt12/leaktime/Makefile.Microsoft_nmake View File

@@ -1,19 +0,0 @@
# This Makefile can be used with Microsoft Visual Studio's nmake using the command:
# 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 sort.obj utils.obj

CFLAGS=/nologo /O2 /I ..\..\..\common /W4 /WX

all: $(LIBRARY)

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

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

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

+ 0
- 18
crypto_kem/ledakemlt12/leaktime/api.h View File

@@ -1,18 +0,0 @@
#ifndef PQCLEAN_LEDAKEMLT12_LEAKTIME_API_H
#define PQCLEAN_LEDAKEMLT12_LEAKTIME_API_H

#include <stdint.h>

#define PQCLEAN_LEDAKEMLT12_LEAKTIME_CRYPTO_SECRETKEYBYTES 50
#define PQCLEAN_LEDAKEMLT12_LEAKTIME_CRYPTO_PUBLICKEYBYTES 6520
#define PQCLEAN_LEDAKEMLT12_LEAKTIME_CRYPTO_CIPHERTEXTBYTES 6544
#define PQCLEAN_LEDAKEMLT12_LEAKTIME_CRYPTO_BYTES 32

#define PQCLEAN_LEDAKEMLT12_LEAKTIME_CRYPTO_ALGNAME "LEDAKEMLT12"

int PQCLEAN_LEDAKEMLT12_LEAKTIME_crypto_kem_keypair(uint8_t *pk, uint8_t *sk);
int PQCLEAN_LEDAKEMLT12_LEAKTIME_crypto_kem_enc(uint8_t *ct, uint8_t *ss, const uint8_t *pk);
int PQCLEAN_LEDAKEMLT12_LEAKTIME_crypto_kem_dec(uint8_t *ss, const uint8_t *ct, const uint8_t *sk);


#endif

+ 0
- 79
crypto_kem/ledakemlt12/leaktime/bf_decoding.c View File

@@ -1,79 +0,0 @@
#include "bf_decoding.h"
#include "gf2x_arith_mod_xPplusOne.h"

#include <string.h>

int PQCLEAN_LEDAKEMLT12_LEAKTIME_bf_decoding(DIGIT err[],
const POSITION_T HtrPosOnes[N0][DV],
const POSITION_T QtrPosOnes[N0][M],
DIGIT privateSyndrome[],
uint8_t secondIterThreshold) {

DIGIT currSyndrome[NUM_DIGITS_GF2X_ELEMENT];
uint8_t unsatParityChecks[N0 * P];
POSITION_T currQBlkPos[M], currQBitPos[M];
POSITION_T syndromePosToFlip, tmp;
uint32_t correlation, corrt_syndrome_based;
size_t currQoneIdx, endQblockIdx, currblockoffset;
int check;
int iteration = 0;

do {
PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_copy(currSyndrome, privateSyndrome);
memset(unsatParityChecks, 0x00, N0 * P * sizeof(uint8_t));
for (size_t i = 0; i < N0; i++) {
for (POSITION_T valueIdx = 0; valueIdx < P; valueIdx++) {
for (size_t HtrOneIdx = 0; HtrOneIdx < DV; HtrOneIdx++) {
tmp = (HtrPosOnes[i][HtrOneIdx] + valueIdx) >= P ?
(HtrPosOnes[i][HtrOneIdx] + valueIdx) - P :
(HtrPosOnes[i][HtrOneIdx] + valueIdx);
if (PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_get_coeff(currSyndrome, tmp)) {
unsatParityChecks[i * P + valueIdx]++;
}
}
}
}

/* iteration based threshold determination*/
corrt_syndrome_based = iteration * secondIterThreshold + (1 - iteration) * B0;

// Computation of correlation with a full Q matrix
for (size_t i = 0; i < N0; i++) {
for (POSITION_T j = 0; j < P; j++) {
currQoneIdx = endQblockIdx = 0;
correlation = 0;

for (size_t blockIdx = 0; blockIdx < N0; blockIdx++) {
endQblockIdx += qBlockWeights[blockIdx][i];
currblockoffset = blockIdx * P;
for (; currQoneIdx < endQblockIdx; currQoneIdx++) {
tmp = QtrPosOnes[i][currQoneIdx] + j;
tmp = tmp >= P ? tmp - P : tmp;
currQBitPos[currQoneIdx] = tmp;
currQBlkPos[currQoneIdx] = (POSITION_T)blockIdx;
correlation += unsatParityChecks[tmp + currblockoffset];
}
}

/* Correlation based flipping */
if (correlation >= corrt_syndrome_based) {
PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_toggle_coeff(err + NUM_DIGITS_GF2X_ELEMENT * i, j);
for (size_t v = 0; v < M; v++) {
for (size_t HtrOneIdx = 0; HtrOneIdx < DV; HtrOneIdx++) {
syndromePosToFlip = (HtrPosOnes[currQBlkPos[v]][HtrOneIdx] + currQBitPos[v]);
syndromePosToFlip = syndromePosToFlip >= P ? syndromePosToFlip - P : syndromePosToFlip;
PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_toggle_coeff(privateSyndrome, syndromePosToFlip);
}
} // end for v
} // end if
} // end for j
} // end for i

iteration = iteration + 1;
check = 0;
while (check < NUM_DIGITS_GF2X_ELEMENT && privateSyndrome[check++] == 0) {};

} while (iteration < ITERATIONS_MAX && check < NUM_DIGITS_GF2X_ELEMENT);

return (check == NUM_DIGITS_GF2X_ELEMENT);
}

+ 0
- 18
crypto_kem/ledakemlt12/leaktime/bf_decoding.h View File

@@ -1,18 +0,0 @@
#ifndef BF_DECODING_H
#define BF_DECODING_H

#include "gf2x_arith.h"
#include "qc_ldpc_parameters.h"

/* Definitions for DFR level 2^-SL with SL=128 */
#define ITERATIONS_MAX (2)
#define B0 (43)
#define T_BAR (4)

int PQCLEAN_LEDAKEMLT12_LEAKTIME_bf_decoding(DIGIT err[],
const POSITION_T HtrPosOnes[N0][DV],
const POSITION_T QtrPosOnes[N0][M],
DIGIT privateSyndrome[],
uint8_t threshold); // B2

#endif

+ 0
- 88
crypto_kem/ledakemlt12/leaktime/dfr_test.c View File

@@ -1,88 +0,0 @@
#include "bf_decoding.h"
#include "dfr_test.h"
#include "gf2x_arith_mod_xPplusOne.h"
#include "qc_ldpc_parameters.h"
#include "sort.h"

#include <string.h>


int PQCLEAN_LEDAKEMLT12_LEAKTIME_DFR_test(POSITION_T LSparse[N0][DV * M], uint8_t *secondIterThreshold) {

POSITION_T LSparse_loc[N0][DV * M]; /* vector of N_0 sparse blocks */
uint8_t gamma[N0][N0][P] = {{{0}}};
uint32_t gammaHist[N0][DV * M + 1] = {{0}};
size_t maxMut[N0], maxMutMinusOne[N0];
size_t allBlockMaxSumst, allBlockMaxSumstMinusOne;
size_t histIdx, toAdd;

for (size_t i = 0; i < N0; i++) {
for (size_t j = 0; j < DV * M; j++) {
if (LSparse[i][j] != 0) {
LSparse_loc[i][j] = (P - LSparse[i][j]);
}
}
PQCLEAN_LEDAKEMLT12_LEAKTIME_uint32_sort(LSparse_loc[i], DV * M);
}


for (size_t i = 0; i < N0; i++ ) {
for (size_t j = 0; j < N0; j++) {
for (size_t k = 0; k < (DV * M); k++) {
for (size_t l = 0; l < (DV * M); l++) {
gamma[i][j][(P + LSparse_loc[i][k] - LSparse_loc[j][l]) % P]++;
}
}
}
}

for (size_t i = 0; i < N0; i++ ) {
for (size_t j = 0; j < N0; j++ ) {
gamma[i][j][0] = 0;
}
}

/* build histogram of values in gamma */
for (size_t i = 0; i < N0; i++ ) {
for (size_t j = 0; j < N0; j++ ) {
for (size_t k = 0; k < P; k++) {
gammaHist[i][gamma[i][j][k]]++;
}
}
}


for (size_t gammaBlockRowIdx = 0; gammaBlockRowIdx < N0; gammaBlockRowIdx++) {
maxMutMinusOne[gammaBlockRowIdx] = 0;
histIdx = DV * M;
toAdd = T_BAR - 1;
while ( (histIdx > 0) && (toAdd > 0)) {
if (gammaHist[gammaBlockRowIdx][histIdx] > toAdd ) {
maxMutMinusOne[gammaBlockRowIdx] += histIdx * toAdd;
toAdd = 0;
} else {
maxMutMinusOne[gammaBlockRowIdx] += histIdx * gammaHist[gammaBlockRowIdx][histIdx];
toAdd -= gammaHist[gammaBlockRowIdx][histIdx];
histIdx--;
}
}
maxMut[gammaBlockRowIdx] = histIdx + maxMutMinusOne[gammaBlockRowIdx];
}

/*seek max values across all gamma blocks */
allBlockMaxSumst = maxMut[0];
allBlockMaxSumstMinusOne = maxMutMinusOne[0];
for (size_t gammaBlockRowIdx = 0; gammaBlockRowIdx < N0; gammaBlockRowIdx++) {
allBlockMaxSumst = allBlockMaxSumst < maxMut[gammaBlockRowIdx] ?
maxMut[gammaBlockRowIdx] :
allBlockMaxSumst;
allBlockMaxSumstMinusOne = allBlockMaxSumstMinusOne < maxMutMinusOne[gammaBlockRowIdx] ?
maxMutMinusOne[gammaBlockRowIdx] :
allBlockMaxSumstMinusOne;
}
if (DV * M > (allBlockMaxSumstMinusOne + allBlockMaxSumst)) {
*secondIterThreshold = (uint8_t) (allBlockMaxSumst + 1);
return 1;
}
return 0;
}

+ 0
- 6
crypto_kem/ledakemlt12/leaktime/dfr_test.h View File

@@ -1,6 +0,0 @@
#ifndef DFR_TEST_H
#define DFR_TEST_H

int PQCLEAN_LEDAKEMLT12_LEAKTIME_DFR_test(POSITION_T LSparse[N0][DV * M], uint8_t *secondIterThreshold);

#endif

+ 0
- 252
crypto_kem/ledakemlt12/leaktime/gf2x_arith.c View File

@@ -1,252 +0,0 @@
#include "gf2x_arith.h"

#include <string.h> // memset(...)

void PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_add(DIGIT Res[], const DIGIT A[], const DIGIT B[], size_t n) {
for (size_t i = 0; i < n; i++) {
Res[i] = A[i] ^ B[i];
}
}

/* copies len digits from a to r if b == 1 */
void PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_cmov(DIGIT *r, const DIGIT *a, size_t len, int c) {
DIGIT mask = (DIGIT)(-c);
for (size_t i = 0; i < len; i++) {
r[i] ^= mask & (a[i] ^ r[i]);
}
}

/* PRE: MAX ALLOWED ROTATION AMOUNT : DIGIT_SIZE_b */
void PQCLEAN_LEDAKEMLT12_LEAKTIME_right_bit_shift_n(size_t length, DIGIT in[], size_t amount) {
if ( amount == 0 ) {
return;
}
size_t j;
DIGIT mask;
mask = ((DIGIT)0x01 << amount) - 1;
for (j = length - 1; j > 0; j--) {
in[j] >>= amount;
in[j] |= (in[j - 1] & mask) << (DIGIT_SIZE_b - amount);
}
in[j] >>= amount;
}

/* PRE: MAX ALLOWED ROTATION AMOUNT : DIGIT_SIZE_b */
void PQCLEAN_LEDAKEMLT12_LEAKTIME_left_bit_shift_n(size_t length, DIGIT in[], size_t amount) {
if ( amount == 0 ) {
return;
}
size_t j;
DIGIT mask;
mask = ~(((DIGIT)0x01 << (DIGIT_SIZE_b - amount)) - 1);
for (j = 0 ; j < length - 1; j++) {
in[j] <<= amount;
in[j] |= (in[j + 1] & mask) >> (DIGIT_SIZE_b - amount);
}
in[j] <<= amount;
}


static void gf2x_mul1(DIGIT *R, const DIGIT A, const DIGIT B) {
DIGIT tmp;

R[0] = 0;
R[1] = (A & 1) * B;
for (uint8_t i = 1; i < DIGIT_SIZE_b; i++) {
tmp = ((A >> i) & 1) * B;
R[1] ^= tmp << i;
R[0] ^= tmp >> (DIGIT_SIZE_b - i);
}
}

static void gf2x_mul_n(DIGIT *R, const DIGIT *A, const DIGIT *B, size_t n) {
DIGIT tmp[2];

memset(R, 0x00, 2 * n * sizeof(DIGIT));
for (size_t i = 0; i < n; i++) {
for (size_t j = 0; j < n; j++) {
gf2x_mul1(tmp, A[i], B[j]);
R[i + j] ^= tmp[0];
R[i + j + 1] ^= tmp[1];
}
}
}

static void gf2x_cpy(DIGIT *R, const DIGIT *A, size_t len) {
for (size_t i = 0; i < len; i++) {
R[i] = A[i];
}
}

/* Accumulate */
#define gf2x_add(R, A, B, n) PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_add(R, A, B, n)
#define gf2x_acc(R, B, n) PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_add(R, R, B, n)

/* allows the operands to be of different size
* first operand must be the bigger one.
* aligns last array elements */
static inline void gf2x_add_asymm(DIGIT *R,
size_t na, const DIGIT *A,
size_t nb, const DIGIT *B) {
size_t delta = na - nb;
gf2x_cpy(R, A, delta);
gf2x_add(R + delta, A + delta, B, nb);;
}

/* aligns first array elements */
static inline void gf2x_add_asymm2(DIGIT *R,
size_t na, const DIGIT *A,
size_t nb, const DIGIT *B) {
size_t delta = na - nb;
gf2x_add(R, A, B, nb);
gf2x_cpy(R + nb, A + nb, delta);
}

/* Karatsuba with lowered space complexity
* T(n) = 3 * ceil(n/2) + T(ceil(n / 2)) */
static void gf2x_mul_kar(DIGIT *R,
const DIGIT *A,
const DIGIT *B,
size_t n,
DIGIT *stack) {

if (n < MIN_KAR_DIGITS) {
gf2x_mul_n(R, A, B, n);
return;
}

size_t l = (n + 1) / 2; // limb size = ceil(n / 2)
size_t d = n & 1;

const DIGIT *a1 = A; // length n - d
const DIGIT *a0 = A + l - d; // length n
const DIGIT *b1 = B;
const DIGIT *b0 = B + l - d;

DIGIT *aa = stack;
DIGIT *bb = aa + l;
DIGIT *cc = bb + l;
stack = cc + l; // 3l space requirement at each level

DIGIT *c3 = R + l - 2 * d;
DIGIT *c2 = c3 + l;
DIGIT *c1 = c2 + l;

gf2x_mul_kar(c2, a0, b0, l, stack); // L in low part of R
gf2x_mul_kar(R, a1, b1, l - d, stack); // H in higher part of R
gf2x_add_asymm(aa, l, a0, l - d, a1); // AH + AL
gf2x_add_asymm(bb, l, b0, l - d, b1); // BH + BL
gf2x_add(cc, c3, c2, l); // HL + LH in cc
gf2x_mul_kar(c3, aa, bb, l, stack); // M = (AH + AL) x (BH + BL)
gf2x_add_asymm(c3, l, c3, l - 2 * d, R); // add HH
gf2x_acc(c2, c1, l); // add LL
gf2x_acc(c3, cc, l); // add HL + LH
gf2x_acc(c2, cc, l); // add HL + LH
}

static void gf2x_div_w_plus_one(DIGIT *A, size_t n) {
size_t i;
for (i = 0; i < n - 2; i++) {
A[i + 1] ^= A[i]; // runs n - 2 times
}
}

static void gf2x_shift_left_w(DIGIT *A, size_t n) {
size_t i;
for (i = 0; i < n - 1; i++) {
A[i] = A[i + 1];
}
A[i] = 0;
}

/* Word-aligned Toom-Cook 3, source:
* Brent, Richard P., et al. "Faster multiplication in GF (2)[x]."
* International Algorithmic Number Theory Symposium.
* Springer, Berlin, Heidelberg, 2008. */
static void gf2x_mul_tc3w(DIGIT *R,
const DIGIT *A,
const DIGIT *B,
size_t n,
DIGIT *stack) {

if (n < MIN_TOOM_DIGITS) {
gf2x_mul_kar(R, A, B, n, stack);
return;
}

size_t l = (n + 2) / 3; // size of a0, a1, b0, b1
size_t r = n - 2 * l; // remaining sizes (a2, b2)
size_t x = 2 * l + 4; // size of c1, c2, c3, c4
size_t z = r + 2 > l + 1 ? r + 2 : l + 1; // size of c5

const DIGIT *a0 = A;
const DIGIT *a1 = A + l;
const DIGIT *a2 = A + 2 * l;
const DIGIT *b0 = B;
const DIGIT *b1 = B + l;
const DIGIT *b2 = B + 2 * l;

DIGIT *c0 = R; // c0 and c4 in the result
DIGIT *c4 = R + 4 * l;
DIGIT *c1 = stack; // the rest in the stack
DIGIT *c2 = c1 + x;
DIGIT *c3 = c2 + x;
DIGIT *c5 = c3 + x;
stack = c5 + z; // Worst-case 7l + 14

// Evaluation
c0[0] = 0; // c0[z] = a1*W + a2*W^2
c0[l + 1] = 0;
gf2x_cpy(c0 + 1, a1, l);
gf2x_acc(c0 + 2, a2, r);

c4[0] = 0; // c4[z] = b1*W + b2*W^2
c4[l + 1] = 0;
gf2x_cpy(c4 + 1, b1, l);
gf2x_acc(c4 + 2, b2, r);

gf2x_cpy(c5, a0, l); // c5[l] = a0 + a1 + a2
gf2x_acc(c5, a1, l);
gf2x_acc(c5, a2, r);

gf2x_cpy(c2, b0, l); // c2[l] = b0 + b1 + b2
gf2x_acc(c2, b1, l);
gf2x_acc(c2, b2, r);

gf2x_mul_tc3w(c1, c2, c5, l, stack); // c1[2l] = c2 * c5
gf2x_add_asymm2(c5, z, c0, l, c5); // c5[z] += c0, z >= l
gf2x_add_asymm2(c2, z, c4, l, c2); // c2[z] += c4, idem
gf2x_acc(c0, a0, l); // c0[l] += a0
gf2x_acc(c4, b0, l); // c4[l] += b0
gf2x_mul_tc3w(c3, c2, c5, z, stack); // c3[2z] = c2 * c5
gf2x_mul_tc3w(c2, c0, c4, z, stack); // c2[2z] = c0 * c4
gf2x_mul_tc3w(c0, a0, b0, l, stack); // c0[2l] = a0 * b0
gf2x_mul_tc3w(c4, a2, b2, r, stack); // c4[2r] = a2 * b2

// Interpolation
gf2x_acc(c3, c2, 2 * z); // c3[2z] += c2
gf2x_acc(c2, c0, 2 * l); // c2[2z] += c0
gf2x_shift_left_w(c2, 2 * z); // c2[2z] = c2/y + c3
gf2x_acc(c2, c3, 2 * z);
gf2x_acc(c2, c4, 2 * r); // c2[2z] += c4 + c4**3
gf2x_acc(c2 + 3, c4, 2 * r);
gf2x_div_w_plus_one(c2, 2 * z); // c2[2z-1] = c2/(W+1)
gf2x_acc(c1, c0, 2 * l); // c1[2l] += c0
gf2x_acc(c3, c1, 2 * l); // c3[2z] += c1
gf2x_shift_left_w(c3, 2 * z); // c3[2z-2] = c3/(W^2 + W)
gf2x_div_w_plus_one(c3, 2 * z - 1);
gf2x_add_asymm2(c1, 2 * z, c2, 2 * l, c1); // c1[2z-1] += c2 + c4
gf2x_acc(c1, c4, 2 * r); // size c2 >= c1 >= c4
gf2x_acc(c2, c3, 2 * z - 1); // c2[2z-1] += c3

// Recombination
gf2x_cpy(R + 2 * l, c2, 2 * l);
gf2x_acc(R + l, c1, 2 * z - 1);
gf2x_acc(R + 3 * l, c3, 2 * z - 1);
}

void PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_mul(DIGIT *R, const DIGIT *A, const DIGIT *B, size_t n) {
DIGIT stack[STACK_WORDS];
gf2x_mul_tc3w(R, A, B, n, stack);
}


+ 0
- 63
crypto_kem/ledakemlt12/leaktime/gf2x_arith.h View File

@@ -1,63 +0,0 @@
#ifndef GF2X_ARITH_H
#define GF2X_ARITH_H

#include <inttypes.h>
#include <stddef.h>

/*
* Elements of GF(2)[x] are stored in compact dense binary form.
*
* Each bit in a byte is assumed to be the coefficient of a binary
* polynomial f(x), in Big-Endian format (i.e., reading everything from
* left to right, the most significant element is met first):
*
* byte:(0000 0000) == 0x00 ... f(x) == 0
* byte:(0000 0001) == 0x01 ... f(x) == 1
* byte:(0000 0010) == 0x02 ... f(x) == x
* byte:(0000 0011) == 0x03 ... f(x) == x+1
* ... ... ...
* byte:(0000 1111) == 0x0F ... f(x) == x^{3}+x^{2}+x+1
* ... ... ...
* byte:(1111 1111) == 0xFF ... f(x) == x^{7}+x^{6}+x^{5}+x^{4}+x^{3}+x^{2}+x+1
*
*
* A "machine word" (A_i) is considered as a DIGIT.
* Bytes in a DIGIT are assumed in Big-Endian format:
* E.g., if sizeof(DIGIT) == 4:
* A_i: A_{i,3} A_{i,2} A_{i,1} A_{i,0}.
* A_{i,3} denotes the most significant byte, A_{i,0} the least significant one.
* f(x) == x^{31} + ... + x^{24} +
* + x^{23} + ... + x^{16} +
* + x^{15} + ... + x^{8} +
* + x^{7} + ... + x^{0}
*
*
* Multi-precision elements (i.e., with multiple DIGITs) are stored in
* Big-endian format:
* A = A_{n-1} A_{n-2} ... A_1 A_0
*
* position[A_{n-1}] == 0
* position[A_{n-2}] == 1
* ...
* position[A_{1}] == n-2
* position[A_{0}] == n-1
*/

typedef uint64_t DIGIT;
#define DIGIT_SIZE_B (8)
#define DIGIT_SIZE_b (DIGIT_SIZE_B << 3)
#define POSITION_T uint32_t

#define MIN_KAR_DIGITS 10
#define MIN_TOOM_DIGITS 42

#define STACK_KAR_ONLY 2433
#define STACK_WORDS 2892

void PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_add(DIGIT Res[], const DIGIT A[], const DIGIT B[], size_t n);
void PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_cmov(DIGIT *r, const DIGIT *a, size_t len, int c);
void PQCLEAN_LEDAKEMLT12_LEAKTIME_right_bit_shift_n(size_t length, DIGIT in[], size_t amount);
void PQCLEAN_LEDAKEMLT12_LEAKTIME_left_bit_shift_n(size_t length, DIGIT in[], size_t amount);
void PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_mul(DIGIT *R, const DIGIT *A, const DIGIT *B, size_t n);

#endif

+ 0
- 531
crypto_kem/ledakemlt12/leaktime/gf2x_arith_mod_xPplusOne.c View File

@@ -1,531 +0,0 @@
#include "gf2x_arith_mod_xPplusOne.h"
#include "rng.h"
#include "sort.h"

#include <string.h> // memcpy(...), memset(...)

void PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_copy(DIGIT dest[], const DIGIT in[]) {
for (size_t i = 0; i < NUM_DIGITS_GF2X_ELEMENT; i++) {
dest[i] = in[i];
}
}

/* returns the coefficient of the x^exponent term as the LSB of a digit */
DIGIT PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_get_coeff(const DIGIT poly[], size_t exponent) {
size_t straightIdx = (NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_b - 1) - exponent;
size_t digitIdx = straightIdx / DIGIT_SIZE_b;
size_t inDigitIdx = straightIdx % DIGIT_SIZE_b;
return (poly[digitIdx] >> (DIGIT_SIZE_b - 1 - inDigitIdx)) & ((DIGIT) 1) ;
}

/* sets the coefficient of the x^exponent term as the LSB of a digit */
void PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_set_coeff(DIGIT poly[], size_t exponent, DIGIT value) {
size_t straightIdx = (NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_b - 1) - exponent;
size_t digitIdx = straightIdx / DIGIT_SIZE_b;
size_t inDigitIdx = straightIdx % DIGIT_SIZE_b;

/* clear given coefficient */
DIGIT mask = ~(((DIGIT) 1) << (DIGIT_SIZE_b - 1 - inDigitIdx));
poly[digitIdx] = poly[digitIdx] & mask;
poly[digitIdx] = poly[digitIdx] | ((value & ((DIGIT) 1)) << (DIGIT_SIZE_b - 1 - inDigitIdx));
}

/* toggles (flips) the coefficient of the x^exponent term as the LSB of a digit */
void PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_toggle_coeff(DIGIT poly[], size_t exponent) {
size_t straightIdx = (NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_b - 1) - exponent;
size_t digitIdx = straightIdx / DIGIT_SIZE_b;
size_t inDigitIdx = straightIdx % DIGIT_SIZE_b;

/* clear given coefficient */
DIGIT mask = (((DIGIT) 1) << (DIGIT_SIZE_b - 1 - inDigitIdx));
poly[digitIdx] = poly[digitIdx] ^ mask;
}

/* population count for an unsigned 64-bit integer
Source: Hacker's delight, p.66 */
static int popcount_uint64t(uint64_t x) {
x -= (x >> 1) & 0x5555555555555555;
x = (x & 0x3333333333333333) + ((x >> 2) & 0x3333333333333333);
x = (x + (x >> 4)) & 0x0f0f0f0f0f0f0f0f;
return (int)((x * 0x0101010101010101) >> 56);
}

/* population count for a single polynomial */
int PQCLEAN_LEDAKEMLT12_LEAKTIME_population_count(const DIGIT *poly) {
int ret = 0;
for (int i = NUM_DIGITS_GF2X_ELEMENT - 1; i >= 0; i--) {
ret += popcount_uint64t(poly[i]);
}
return ret;
}

void PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_mod_add(DIGIT Res[], const DIGIT A[], const DIGIT B[]) {
PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_add(Res, A, B, NUM_DIGITS_GF2X_ELEMENT);
}

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 right_bit_shift(size_t length, DIGIT in[]) {
size_t j;
for (j = length - 1; j > 0; j--) {
in[j] >>= 1;
in[j] |= (in[j - 1] & (DIGIT)0x01) << (DIGIT_SIZE_b - 1);
}
in[j] >>= 1;
}


/* shifts by whole digits */
static void left_DIGIT_shift_n(size_t length, DIGIT in[], size_t amount) {
size_t j;
for (j = 0; (j + amount) < length; j++) {
in[j] = in[j + amount];
}
for (; j < length; j++) {
in[j] = (DIGIT)0;
}
}

/* may shift by an arbitrary amount*/
static void left_bit_shift_wide_n(size_t length, DIGIT in[], size_t amount) {
left_DIGIT_shift_n(length, in, amount / DIGIT_SIZE_b);
PQCLEAN_LEDAKEMLT12_LEAKTIME_left_bit_shift_n(length, in, amount % DIGIT_SIZE_b);
}

/* Hackers delight, reverses a uint64_t */
static DIGIT reverse_digit(DIGIT x) {
uint64_t t;
x = (x << 31) | (x >> 33);
t = (x ^ (x >> 20)) & 0x00000FFF800007FFLL;
x = (t | (t << 20)) ^ x;
t = (x ^ (x >> 8)) & 0x00F8000F80700807LL;
x = (t | (t << 8)) ^ x;
t = (x ^ (x >> 4)) & 0x0808708080807008LL;
x = (t | (t << 4)) ^ x;
t = (x ^ (x >> 2)) & 0x1111111111111111LL;
x = (t | (t << 2)) ^ x;
return x;
}

void PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_transpose_in_place(DIGIT A[]) {
/* it keeps the lsb in the same position and
* inverts the sequence of the remaining bits */

DIGIT mask = (DIGIT)0x1;
DIGIT rev1, rev2, a00;
int slack_bits_amount = NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_b - P;

a00 = A[NUM_DIGITS_GF2X_ELEMENT - 1] & mask;
right_bit_shift(NUM_DIGITS_GF2X_ELEMENT, A);

for (size_t i = NUM_DIGITS_GF2X_ELEMENT - 1; i >= (NUM_DIGITS_GF2X_ELEMENT + 1) / 2; i--) {
rev1 = reverse_digit(A[i]);
rev2 = reverse_digit(A[NUM_DIGITS_GF2X_ELEMENT - 1 - i]);
A[i] = rev2;
A[NUM_DIGITS_GF2X_ELEMENT - 1 - i] = rev1;
}

A[NUM_DIGITS_GF2X_ELEMENT / 2] = reverse_digit(A[NUM_DIGITS_GF2X_ELEMENT / 2]);

if (slack_bits_amount) {
PQCLEAN_LEDAKEMLT12_LEAKTIME_right_bit_shift_n(NUM_DIGITS_GF2X_ELEMENT, A, slack_bits_amount);
}
A[NUM_DIGITS_GF2X_ELEMENT - 1] = (A[NUM_DIGITS_GF2X_ELEMENT - 1] & (~mask)) | a00;
}

static void rotate_bit_right(DIGIT in[]) { /* x^{-1} * in(x) mod x^P+1 */

DIGIT rotated_bit = in[NUM_DIGITS_GF2X_ELEMENT - 1] & ((DIGIT)0x1);
right_bit_shift(NUM_DIGITS_GF2X_ELEMENT, in);
int msb_offset_in_digit = MSb_POSITION_IN_MSB_DIGIT_OF_MODULUS - 1;
rotated_bit = rotated_bit << msb_offset_in_digit;
in[0] |= rotated_bit;
}

/* cond swap: swaps digits A and B if swap_mask == -1 */
static void gf2x_cswap(DIGIT *a, DIGIT *b, int32_t swap_mask) {
DIGIT t;
for (size_t i = 0; i < NUM_DIGITS_GF2X_ELEMENT; i++) {
t = swap_mask & (a[i] ^ b[i]);
a[i] ^= t;
b[i] ^= t;
}
}

/* returns -1 mask if x != 0, otherwise 0 */
static inline int32_t nonzero(DIGIT x) {
DIGIT t = x;
t = (~t) + 1;
t >>= DIGIT_SIZE_b - 1;
return -((int32_t)t);
}

/* returns -1 mask if x < 0 else 0 */
static inline int32_t negative(int x) {
uint32_t u = x;
u >>= 31;
return -((int32_t)u);
}

/* return f(0) as digit */
static inline DIGIT lsb(const DIGIT *p) {
DIGIT mask = (DIGIT)1;
return p[NUM_DIGITS_GF2X_ELEMENT - 1] & mask;
}

/* multiply poly with scalar and accumulate, expects s all-zero of all-one mask */
static void gf2x_mult_scalar_acc(DIGIT *f, const DIGIT *g, const DIGIT s) {
for (size_t i = 0; i < NUM_DIGITS_GF2X_ELEMENT; i++) {
f[i] = f[i] ^ (s & g[i]);
}
}

/* constant-time inverse, source: gcd.cr.yp.to */
int PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_mod_inverse(DIGIT out[], const DIGIT in[]) {
int32_t swap, delta = 1;
DIGIT g0_mask;

DIGIT f[NUM_DIGITS_GF2X_MODULUS] = {0}; // f = x^P + 1
DIGIT g[NUM_DIGITS_GF2X_ELEMENT]; // g = in
DIGIT *v = out; // v = 0, save space
DIGIT r[NUM_DIGITS_GF2X_ELEMENT] = {0}; // r = 1

f[NUM_DIGITS_GF2X_MODULUS - 1] = 1;
f[0] |= ((DIGIT)1 << MSb_POSITION_IN_MSB_DIGIT_OF_MODULUS);

for (size_t i = 0; i < NUM_DIGITS_GF2X_ELEMENT; i++) {
g[i] = in[i];
}

for (size_t i = 0; i < NUM_DIGITS_GF2X_ELEMENT; i++) {
v[i] = 0;
}

r[NUM_DIGITS_GF2X_ELEMENT - 1] = 1;

for (int loop = 0; loop < 2 * P - 1; ++loop) {

swap = negative(-delta) & nonzero(lsb(g)); // swap = -1 if -delta < 0 AND g(0) != 0
delta ^= swap & (delta ^ -delta); // cond swap delta with -delta if swap
delta++;

gf2x_cswap(f, g, swap);
gf2x_cswap(v, r, swap);

g0_mask = ~lsb(g) + 1;

// g = (g - g0 * f) / x
gf2x_mult_scalar_acc(g, f, g0_mask);
right_bit_shift(NUM_DIGITS_GF2X_ELEMENT, g);

// r = (r - g0 * v) / x
gf2x_mult_scalar_acc(r, v, g0_mask);
rotate_bit_right(r);

}

return nonzero(delta); // -1 if fail, 0 if success
}

void PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_mod_mul(DIGIT Res[], const DIGIT A[], const DIGIT B[]) {

DIGIT aux[2 * NUM_DIGITS_GF2X_ELEMENT];
PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_mul(aux, A, B, NUM_DIGITS_GF2X_ELEMENT);
gf2x_mod(Res, aux);

}

/*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[], size_t 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);

if (sparse[0] != INVALID_POS_VALUE) {
left_bit_shift_wide_n(2 * NUM_DIGITS_GF2X_ELEMENT, resDouble, sparse[0]);
left_bit_shift_wide_n(2 * NUM_DIGITS_GF2X_ELEMENT, aux, sparse[0]);

for (size_t i = 1; i < nPos; i++) {
if (sparse[i] != INVALID_POS_VALUE) {
left_bit_shift_wide_n(2 * NUM_DIGITS_GF2X_ELEMENT, aux, (sparse[i] - sparse[i - 1]) );
PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_add(resDouble, aux, resDouble, 2 * NUM_DIGITS_GF2X_ELEMENT);
}
}
}

gf2x_mod(Res, resDouble);

}

void PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_transpose_in_place_sparse(size_t sizeA, POSITION_T A[]) {
POSITION_T t;
size_t i = 0, j;

if (A[i] == 0) {
i = 1;
}
j = i;

for (; i < sizeA && A[i] != INVALID_POS_VALUE; i++) {
A[i] = P - A[i];
}

for (i -= 1; j < i; j++, i--) {
t = A[j];
A[j] = A[i];
A[i] = t;
}

}

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[]) {

POSITION_T prod;
POSITION_T lastReadPos;
size_t duplicateCount;
size_t write_idx, read_idx;

/* 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++) {
prod = A[i] + B[j];
prod = ( (prod >= P) ? prod - P : prod);
if ((A[i] != INVALID_POS_VALUE) &&
(B[j] != INVALID_POS_VALUE)) {
Res[lastFilledPos] = prod;
} else {
Res[lastFilledPos] = INVALID_POS_VALUE;
}
lastFilledPos++;
}
}
while (lastFilledPos < sizeR) {
Res[lastFilledPos] = INVALID_POS_VALUE;
lastFilledPos++;
}

PQCLEAN_LEDAKEMLT12_LEAKTIME_uint32_sort(Res, sizeR);

/* eliminate duplicates */
write_idx = read_idx = 0;
while (read_idx < sizeR && Res[read_idx] != INVALID_POS_VALUE) {
lastReadPos = Res[read_idx];
read_idx++;
duplicateCount = 1;
while ( (Res[read_idx] == lastReadPos) && (Res[read_idx] != INVALID_POS_VALUE)) {
read_idx++;
duplicateCount++;
}
if (duplicateCount % 2) {
Res[write_idx] = lastReadPos;
write_idx++;
}
}
/* fill remaining cells with INVALID_POS_VALUE */
for (; write_idx < sizeR; write_idx++) {
Res[write_idx] = INVALID_POS_VALUE;
}
}

/* the implementation is safe even in case A or B alias with the result
* PRE: A and B should be sorted, disjunct arrays ending with INVALID_POS_VALUE */
void PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_mod_add_sparse(size_t sizeR, POSITION_T Res[],
size_t sizeA, const POSITION_T A[],
size_t sizeB, const POSITION_T B[]) {

POSITION_T tmpRes[DV * M];
size_t idxA = 0, idxB = 0, idxR = 0;
while ( idxA < sizeA &&
idxB < sizeB &&
A[idxA] != INVALID_POS_VALUE &&
B[idxB] != INVALID_POS_VALUE ) {

if (A[idxA] == B[idxB]) {
idxA++;
idxB++;
} else {
if (A[idxA] < B[idxB]) {
tmpRes[idxR] = A[idxA];
idxA++;
} else {
tmpRes[idxR] = B[idxB];
idxB++;
}
idxR++;
}
}

while (idxA < sizeA && A[idxA] != INVALID_POS_VALUE) {
tmpRes[idxR] = A[idxA];
idxA++;
idxR++;
}

while (idxB < sizeB && B[idxB] != INVALID_POS_VALUE) {
tmpRes[idxR] = B[idxB];
idxB++;
idxR++;
}

while (idxR < sizeR) {
tmpRes[idxR] = INVALID_POS_VALUE;
idxR++;
}
memcpy(Res, tmpRes, sizeof(POSITION_T)*sizeR);

}

/* Return a uniform random value in the range 0..n-1 inclusive,
* applying a rejection sampling strategy and exploiting as a random source
* the NIST seedexpander seeded with the proper key.
* Assumes that the maximum value for the range n is 2^32-1
*/
static uint32_t rand_range(const unsigned int n, const int logn, AES_XOF_struct *seed_expander_ctx) {
unsigned long required_rnd_bytes = (logn + 7) / 8;
unsigned char rnd_char_buffer[4];
uint32_t rnd_value;
uint32_t mask = ( (uint32_t)1 << logn) - 1;

do {
PQCLEAN_LEDAKEMLT12_LEAKTIME_seedexpander(seed_expander_ctx, rnd_char_buffer, required_rnd_bytes);
/* obtain an endianness independent representation of the generated random
bytes into an unsigned integer */
rnd_value = ((uint32_t)rnd_char_buffer[3] << 24) +
((uint32_t)rnd_char_buffer[2] << 16) +
((uint32_t)rnd_char_buffer[1] << 8) +
((uint32_t)rnd_char_buffer[0] << 0) ;
rnd_value = mask & rnd_value;
} while (rnd_value >= n);

return rnd_value;
}

/* Obtains fresh randomness and seed-expands it until all the required positions
* for the '1's in the circulant block are obtained */
void PQCLEAN_LEDAKEMLT12_LEAKTIME_rand_circulant_sparse_block(POSITION_T *pos_ones,
size_t countOnes,
AES_XOF_struct *seed_expander_ctx) {

size_t duplicated, placedOnes = 0;
POSITION_T p;

while (placedOnes < countOnes) {
p = rand_range(NUM_BITS_GF2X_ELEMENT,
P_BITS,
seed_expander_ctx);
duplicated = 0;
for (size_t j = 0; j < placedOnes; j++) {
if (pos_ones[j] == p) {
duplicated = 1;
}
}
if (duplicated == 0) {
pos_ones[placedOnes] = p;
placedOnes++;
}
}
}

/* 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) {

size_t polyIndex, duplicated, counter = 0;
POSITION_T p, exponent, rndPos[NUM_ERRORS_T];

memset(sequence, 0x00, N0 * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B);

while (counter < NUM_ERRORS_T) {
p = rand_range(N0 * NUM_BITS_GF2X_ELEMENT, P_BITS, seed_expander_ctx);
duplicated = 0;
for (size_t j = 0; j < counter; j++) {
if (rndPos[j] == p) {
duplicated = 1;
}
}
if (duplicated == 0) {
rndPos[counter] = p;
counter++;
}
}
for (size_t j = 0; j < counter; j++) {
polyIndex = rndPos[j] / P;
exponent = rndPos[j] % P;
PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_set_coeff( sequence + NUM_DIGITS_GF2X_ELEMENT * polyIndex, exponent,
( (DIGIT) 1));
}

}


void PQCLEAN_LEDAKEMLT12_LEAKTIME_rand_error_pos(POSITION_T errorPos[NUM_ERRORS_T],
AES_XOF_struct *seed_expander_ctx) {

int duplicated;
size_t counter = 0;

while (counter < NUM_ERRORS_T) {
POSITION_T p = rand_range(N0 * NUM_BITS_GF2X_ELEMENT, P_BITS, seed_expander_ctx);
duplicated = 0;
for (size_t 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],
const POSITION_T errorPos[NUM_ERRORS_T]) {

size_t polyIndex;
POSITION_T exponent;

memset(sequence, 0x00, N0 * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B);
for (int j = 0; j < NUM_ERRORS_T; j++) {
polyIndex = errorPos[j] / P;
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++) {
for (j = 0; j < DIGIT_SIZE_B; j++) {
bytes[i * DIGIT_SIZE_B + j] = (uint8_t) (poly[i] >> 8 * j);
}
}
}

void PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_frombytes(DIGIT *poly, const uint8_t *poly_bytes) {
size_t i, j;
for (i = 0; i < NUM_DIGITS_GF2X_ELEMENT; i++) {
poly[i] = (DIGIT) 0;
for (j = 0; j < DIGIT_SIZE_B; j++) {
poly[i] |= (DIGIT) poly_bytes[i * DIGIT_SIZE_B + j] << 8 * j;
}
}
}

+ 0
- 39
crypto_kem/ledakemlt12/leaktime/gf2x_arith_mod_xPplusOne.h View File

@@ -1,39 +0,0 @@
#ifndef GF2X_ARITH_MOD_XPLUSONE_H
#define GF2X_ARITH_MOD_XPLUSONE_H

#include "qc_ldpc_parameters.h"

#include "gf2x_arith.h"
#include "rng.h"

#define NUM_BITS_GF2X_ELEMENT (P) // 52147
#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)
#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 (16) // log_2(p) = 15.6703

void PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_copy(DIGIT dest[], const DIGIT in[]);
DIGIT PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_get_coeff(const DIGIT poly[], size_t exponent);
void PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_set_coeff(DIGIT poly[], size_t exponent, DIGIT value);
void PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_toggle_coeff(DIGIT poly[], size_t exponent);
int PQCLEAN_LEDAKEMLT12_LEAKTIME_population_count(const DIGIT *poly);
void PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_mod_add(DIGIT Res[], const DIGIT A[], const DIGIT B[]);
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, size_t 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], const POSITION_T errorPos[NUM_ERRORS_T]);
void PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_mod_add_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_transpose_in_place_sparse(size_t 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_dense_to_sparse(DIGIT Res[], const DIGIT dense[], POSITION_T sparse[], size_t 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);


#endif

+ 0
- 157
crypto_kem/ledakemlt12/leaktime/kem.c View File

@@ -1,157 +0,0 @@
#include "api.h"
#include "niederreiter.h"
#include "randombytes.h"
#include "rng.h"
#include "utils.h"

#include <string.h>


#define pack_ct(sk_bytes, ct) PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_tobytes(sk_bytes, ct);
#define unpack_ct(ct, ct_bytes) PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_frombytes(ct, ct_bytes)

static void pack_pk(uint8_t *pk_bytes, publicKeyNiederreiter_t *pk) {
for (size_t i = 0; i < N0 - 1; i++) {
PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_tobytes(pk_bytes + i * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B,
pk->Mtr + i * NUM_DIGITS_GF2X_ELEMENT);
}
}

static void unpack_pk(publicKeyNiederreiter_t *pk, const uint8_t *pk_bytes) {
for (size_t i = 0; i < N0 - 1; i++) {
PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_frombytes(pk->Mtr + i * NUM_DIGITS_GF2X_ELEMENT,
pk_bytes + i * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B);
}
}

static void pack_error(uint8_t *error_bytes, DIGIT *error_digits) {
size_t i;
for (i = 0; i < N0; i++) {
PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_tobytes(error_bytes + i * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B,
error_digits + i * NUM_DIGITS_GF2X_ELEMENT);
}
}

/* IND-CCA2 Keygen */
int PQCLEAN_LEDAKEMLT12_LEAKTIME_crypto_kem_keypair(uint8_t *pk, uint8_t *sk) {
publicKeyNiederreiter_t niederreiter_pk;

PQCLEAN_LEDAKEMLT12_LEAKTIME_niederreiter_keygen(&niederreiter_pk, (privateKeyNiederreiter_t *) sk);

pack_pk(pk, &niederreiter_pk);

return 0;
}

/* IND-CCA2 Encapsulation */
int PQCLEAN_LEDAKEMLT12_LEAKTIME_crypto_kem_enc(uint8_t *ct, uint8_t *ss, const uint8_t *pk) {
publicKeyNiederreiter_t niederreiter_pk;
DIGIT syndrome[NUM_DIGITS_GF2X_ELEMENT];
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];
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];

unpack_pk(&niederreiter_pk, 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);

memcpy(hashedAndTruncatedSeed, hashedSeed, TRNG_BYTE_LENGTH);

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);

pack_error(error_bytes, error_vector);
HASH_FUNCTION(hashedErrorVector, error_bytes, (N0 * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B));

memcpy(hashedAndTruncatedErrorVector, hashedErrorVector, TRNG_BYTE_LENGTH);

for (size_t i = 0; i < TRNG_BYTE_LENGTH; ++i) {
maskedSeed[i] = seed[i] ^ hashedAndTruncatedErrorVector[i];
}

PQCLEAN_LEDAKEMLT12_LEAKTIME_niederreiter_encrypt(syndrome,
(const publicKeyNiederreiter_t *) &niederreiter_pk, error_vector);

pack_ct(ct, syndrome);
memcpy(ct + (NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B), maskedSeed, TRNG_BYTE_LENGTH);

return 0;
}


/* IND-CCA2 Decapsulation */
int PQCLEAN_LEDAKEMLT12_LEAKTIME_crypto_kem_dec(uint8_t *ss, const uint8_t *ct, const uint8_t *sk) {
DIGIT syndrome[NUM_DIGITS_GF2X_ELEMENT];
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];
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};
int decode_ok, decrypt_ok, equal;

unpack_ct(syndrome, ct);

decode_ok = PQCLEAN_LEDAKEMLT12_LEAKTIME_niederreiter_decrypt(decoded_error_vector,
(const privateKeyNiederreiter_t *)sk, syndrome);

pack_error(decoded_error_bytes, decoded_error_vector);
HASH_FUNCTION(hashedErrorVector, decoded_error_bytes, N0 * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B);

memcpy(hashedAndTruncatedErrorVector, hashedErrorVector, TRNG_BYTE_LENGTH);

for (size_t 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);

equal = PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_verify(decoded_error_vector,
reconstructed_error_vector, N0 * NUM_DIGITS_GF2X_ELEMENT);
// equal == 0, if the reconstructed error vector match !!!

decrypt_ok = (decode_ok == 1 && equal == 0);

memcpy(ss_input, decoded_seed, TRNG_BYTE_LENGTH);
memcpy(ss_input + sizeof(decoded_seed), tail, TRNG_BYTE_LENGTH);

// Overwrite on failure
PQCLEAN_LEDAKEMLT12_LEAKTIME_cmov(ss_input + sizeof(decoded_seed),
((const privateKeyNiederreiter_t *) sk)->decryption_failure_secret,
TRNG_BYTE_LENGTH,
!decrypt_ok);

HASH_FUNCTION(ss, ss_input, 2 * TRNG_BYTE_LENGTH);

return 0;
}

+ 0
- 192
crypto_kem/ledakemlt12/leaktime/niederreiter.c View File

@@ -1,192 +0,0 @@
#include "H_Q_matrices_generation.h"
#include "bf_decoding.h"
#include "dfr_test.h"
#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;
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] = {0};
DIGIT Ln0Inv[NUM_DIGITS_GF2X_ELEMENT] = {0};
int is_L_full;
int isDFRok = 0;

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(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;
}
}

memset(processedQOnes, 0x00, sizeof(processedQOnes));
for (int colQ = 0; colQ < N0; colQ++) {
for (int i = 0; i < N0; i++) {
PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_mod_mul_sparse(DV * M, auxPosOnes,
DV, HPosOnes[i],
qBlockWeights[i][colQ], QPosOnes[i] + processedQOnes[i]);
PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_mod_add_sparse(DV * M, LPosOnes[colQ],
DV * M, LPosOnes[colQ],
DV * M, auxPosOnes);
processedQOnes[i] += qBlockWeights[i][colQ];
}
}
is_L_full = 1;
for (size_t i = 0; i < N0; i++) {
is_L_full = is_L_full && (LPosOnes[i][DV * M - 1] != INVALID_POS_VALUE);
}
sk->rejections = sk->rejections + 1;
if (is_L_full) {
isDFRok = PQCLEAN_LEDAKEMLT12_LEAKTIME_DFR_test(LPosOnes, &(sk->secondIterThreshold));
}
} while (!is_L_full || !isDFRok);
sk->rejections = sk->rejections - 1;

PQCLEAN_LEDAKEMLT12_LEAKTIME_seedexpander(&keys_expander,
sk->decryption_failure_secret,
(unsigned long)TRNG_BYTE_LENGTH);

for (size_t 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);
}
}

PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_mod_inverse(Ln0Inv, Ln0dense);
for (size_t i = 0; i < N0 - 1; i++) {
PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_mod_mul_dense_to_sparse(pk->Mtr + i * NUM_DIGITS_GF2X_ELEMENT,
Ln0Inv,
LPosOnes[i],
DV * M);
}

for (size_t i = 0; i < N0 - 1; i++) {
PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_transpose_in_place(pk->Mtr + i * NUM_DIGITS_GF2X_ELEMENT);
}
}

void PQCLEAN_LEDAKEMLT12_LEAKTIME_niederreiter_encrypt(DIGIT syndrome[],
const publicKeyNiederreiter_t *pk,
const DIGIT err[]) {

DIGIT saux[NUM_DIGITS_GF2X_ELEMENT];

memset(syndrome, 0x00, NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B);
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 QPosOnes[N0][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];
DIGIT err_computed[N0 * NUM_DIGITS_GF2X_ELEMENT] = {0};
DIGIT err_mockup[N0 * NUM_DIGITS_GF2X_ELEMENT];
DIGIT privateSyndrome[NUM_DIGITS_GF2X_ELEMENT];
uint8_t processedQOnes[N0];
int rejections = sk->rejections;
int decrypt_ok = 0;
int err_weight;

PQCLEAN_LEDAKEMLT12_LEAKTIME_seedexpander_from_trng(&niederreiter_decrypt_expander, sk->prng_seed);
do {
PQCLEAN_LEDAKEMLT12_LEAKTIME_generateHPosOnes(HPosOnes, &niederreiter_decrypt_expander);
PQCLEAN_LEDAKEMLT12_LEAKTIME_generateQPosOnes(QPosOnes, &niederreiter_decrypt_expander);

for (size_t i = 0; i < N0; i++) {
for (size_t j = 0; j < DV * M; j++) {
LPosOnes[i][j] = INVALID_POS_VALUE;
}
}

memset(processedQOnes, 0x00, sizeof(processedQOnes));
for (size_t colQ = 0; colQ < N0; colQ++) {
for (size_t i = 0; i < N0; i++) {
PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_mod_mul_sparse(DV * M, auxPosOnes,
DV, HPosOnes[i],
qBlockWeights[i][colQ], QPosOnes[i] + processedQOnes[i]);
PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_mod_add_sparse(DV * M, LPosOnes[colQ],
DV * M, LPosOnes[colQ],
DV * M, auxPosOnes);
processedQOnes[i] += qBlockWeights[i][colQ];
}
}
rejections--;
} while (rejections >= 0);

PQCLEAN_LEDAKEMLT12_LEAKTIME_transposeHPosOnes(HtrPosOnes, HPosOnes);
PQCLEAN_LEDAKEMLT12_LEAKTIME_transposeQPosOnes(QtrPosOnes, QPosOnes);

for (size_t i = 0; i < DV * M; i++) {
Ln0trSparse[i] = INVALID_POS_VALUE;
auxSparse[i] = INVALID_POS_VALUE;
}

for (size_t 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]]);
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);

decrypt_ok = PQCLEAN_LEDAKEMLT12_LEAKTIME_bf_decoding(err_computed,
(const POSITION_T (*)[DV]) HtrPosOnes,
(const POSITION_T (*)[M]) QtrPosOnes,
privateSyndrome, sk->secondIterThreshold);

err_weight = 0;
for (size_t i = 0 ; i < N0; i++) {
err_weight += PQCLEAN_LEDAKEMLT12_LEAKTIME_population_count(err_computed + (NUM_DIGITS_GF2X_ELEMENT * i));
}
decrypt_ok = decrypt_ok && (err_weight == NUM_ERRORS_T);

/* prepare mockup error vector in case a decoding failure occurs */
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);

memcpy(err, err_computed, N0 * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B);

// Overwrite on decryption failure
PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_cmov(err, err_mockup, N0 * NUM_DIGITS_GF2X_ELEMENT, !decrypt_ok);

return decrypt_ok;
}

+ 0
- 24
crypto_kem/ledakemlt12/leaktime/niederreiter.h View File

@@ -1,24 +0,0 @@
#ifndef NIEDERREITER_H
#define NIEDERREITER_H

#include "gf2x_arith_mod_xPplusOne.h"
#include "qc_ldpc_parameters.h"
#include "rng.h"

typedef struct {
unsigned char prng_seed[TRNG_BYTE_LENGTH];
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];
} publicKeyNiederreiter_t;


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

+ 0
- 27
crypto_kem/ledakemlt12/leaktime/qc_ldpc_parameters.h View File

@@ -1,27 +0,0 @@
#ifndef QC_LDPC_PARAMETERS_H
#define QC_LDPC_PARAMETERS_H

#include "fips202.h"

#define TRNG_BYTE_LENGTH (24)
#define HASH_BYTE_LENGTH (32)
#define HASH_FUNCTION sha3_256

#define N0 (2)
#define P (52147) // modulus(x) = x^P-1
#define DV (9) // odd number
#define M (9)
#define M0 (5)
#define M1 (4)
#define NUM_ERRORS_T (136)

// Derived parameters, they are useful for QC-LDPC algorithms
#define HASH_BIT_LENGTH (HASH_BYTE_LENGTH << 3)
#define K ((N0-1)*P)
#define N (N0*P)
#define DC (N0*DV)

#define Q_BLOCK_WEIGHTS {{M0,M1},{M1,M0}}
static const unsigned char qBlockWeights[N0][N0] = Q_BLOCK_WEIGHTS;

#endif

+ 0
- 110
crypto_kem/ledakemlt12/leaktime/rng.c View File

@@ -1,110 +0,0 @@
#include "rng.h"

#include <string.h> // void *memset(void *s, int c, size_t n);

#include "aes.h"
#include "qc_ldpc_parameters.h"

/*
seedexpander_init()
ctx - stores the current state of an instance of the seed expander
seed - a 32 byte random value
diversifier - an 8 byte diversifier
maxlen - maximum number of bytes (less than 2**32) generated under this seed and diversifier
*/
static void seedexpander_init(AES_XOF_struct *ctx,
uint8_t *seed,
uint8_t *diversifier,
size_t maxlen) {

ctx->length_remaining = maxlen;

memset(ctx->key, 0, 32);
int max_accessible_seed_len = TRNG_BYTE_LENGTH < 32 ? 32 : TRNG_BYTE_LENGTH;
memcpy(ctx->key, seed, max_accessible_seed_len);

memcpy(ctx->ctr, diversifier, 8);
ctx->ctr[11] = maxlen % 256;
maxlen >>= 8;
ctx->ctr[10] = maxlen % 256;
maxlen >>= 8;
ctx->ctr[9] = maxlen % 256;
maxlen >>= 8;
ctx->ctr[8] = maxlen % 256;
memset(ctx->ctr + 12, 0x00, 4);

ctx->buffer_pos = 16;
memset(ctx->buffer, 0x00, 16);
}

void PQCLEAN_LEDAKEMLT12_LEAKTIME_seedexpander_from_trng(AES_XOF_struct *ctx,
const uint8_t *trng_entropy
/* TRNG_BYTE_LENGTH wide buffer */) {

/*the NIST seedexpander will however access 32B from this buffer */
unsigned int prng_buffer_size = TRNG_BYTE_LENGTH < 32 ? 32 : TRNG_BYTE_LENGTH;
uint8_t prng_buffer[TRNG_BYTE_LENGTH < 32 ? 32 : TRNG_BYTE_LENGTH] = {0x00};
uint8_t diversifier[8] = {0};

memcpy(prng_buffer,
trng_entropy,
TRNG_BYTE_LENGTH < prng_buffer_size ? TRNG_BYTE_LENGTH : prng_buffer_size);

/* the required seed expansion will be quite small, set the max number of
* bytes conservatively to 10 MiB*/
seedexpander_init(ctx, prng_buffer, diversifier, RNG_MAXLEN);
}

/*
seedexpander()
ctx - stores the current state of an instance of the seed expander
x - returns the XOF data
xlen - number of bytes to return
*/
int PQCLEAN_LEDAKEMLT12_LEAKTIME_seedexpander(AES_XOF_struct *ctx, uint8_t *x, size_t xlen) {
size_t offset;
aes256ctx ctx256;

if ( x == NULL ) {
return RNG_BAD_OUTBUF;
}
if ( xlen >= ctx->length_remaining ) {
return RNG_BAD_REQ_LEN;
}

aes256_ecb_keyexp(&ctx256, ctx->key);
ctx->length_remaining -= xlen;

offset = 0;
while ( xlen > 0 ) {
if ( xlen <= (16 - ctx->buffer_pos) ) { // buffer has what we need
memcpy(x + offset, ctx->buffer + ctx->buffer_pos, xlen);
ctx->buffer_pos += xlen;

goto end;
}

// take what's in the buffer
memcpy(x + offset, ctx->buffer + ctx->buffer_pos, 16 - ctx->buffer_pos);
xlen -= 16 - ctx->buffer_pos;
offset += 16 - ctx->buffer_pos;

aes256_ecb(ctx->buffer, ctx->ctr, 16 / AES_BLOCKBYTES, &ctx256);
ctx->buffer_pos = 0;

//increment the counter
for (int i = 15; i >= 12; i--) {
if ( ctx->ctr[i] == 0xff ) {
ctx->ctr[i] = 0x00;
} else {
ctx->ctr[i]++;
break;
}
}

}
end:
aes256_ctx_release(&ctx256);

return RNG_SUCCESS;
}

+ 0
- 24
crypto_kem/ledakemlt12/leaktime/rng.h View File

@@ -1,24 +0,0 @@
#ifndef RNG_H
#define RNG_H

#include <stddef.h>
#include <stdint.h>

#define RNG_SUCCESS ( 0)
#define RNG_BAD_MAXLEN (-1)
#define RNG_BAD_OUTBUF (-2)
#define RNG_BAD_REQ_LEN (-3)
#define RNG_MAXLEN (10 * 1024 * 1024)

typedef struct {
unsigned char buffer[16];
size_t buffer_pos;
size_t length_remaining;
unsigned char key[32];
unsigned char ctr[16];
} AES_XOF_struct;

int PQCLEAN_LEDAKEMLT12_LEAKTIME_seedexpander(AES_XOF_struct *ctx, unsigned char *x, size_t xlen);
void PQCLEAN_LEDAKEMLT12_LEAKTIME_seedexpander_from_trng(AES_XOF_struct *ctx, const unsigned char *trng_entropy);

#endif

+ 0
- 98
crypto_kem/ledakemlt12/leaktime/sort.c View File

@@ -1,98 +0,0 @@
#include "sort.h"

/*
Constant-time uint32_t sorting by Daniel J. Bernstein
Source: https://sorting.cr.yp.to
*/

#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)

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;
}
}

+ 0
- 11
crypto_kem/ledakemlt12/leaktime/sort.h View File

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

#include <stddef.h>
#include <stdint.h>

#define int32 int32_t

void PQCLEAN_LEDAKEMLT12_LEAKTIME_uint32_sort(uint32_t *x, size_t n);

#endif

+ 0
- 21
crypto_kem/ledakemlt12/leaktime/utils.c View File

@@ -1,21 +0,0 @@
#include "gf2x_arith.h"
#include "utils.h"

/* compares DIGIT sequences, returns 0 if they are equal */
int PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_verify(const DIGIT *a, const DIGIT *b, size_t len) {
DIGIT x = 0;
for (size_t i = 0; i < len; i++) {
x |= a[i] ^ b[i];
}
x = (~x) + 1;
x >>= (DIGIT_SIZE_b - 1);
return (int)x;
}

/* conditionally move a into r if cond */
void PQCLEAN_LEDAKEMLT12_LEAKTIME_cmov(uint8_t *r, const uint8_t *a, size_t len, int cond) {
uint8_t mask = (uint8_t)(-cond);
for (size_t i = 0; i < len; i++) {
r[i] ^= mask & (r[i] ^ a[i]);
}
}

+ 0
- 9
crypto_kem/ledakemlt12/leaktime/utils.h View File

@@ -1,9 +0,0 @@
#ifndef UTILS_H
#define UTILS_H

#include <stdint.h>

int PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_verify(const DIGIT *a, const DIGIT *b, size_t len);
void PQCLEAN_LEDAKEMLT12_LEAKTIME_cmov(uint8_t *r, const uint8_t *a, size_t len, int cond);

#endif

+ 0
- 19
crypto_kem/ledakemlt32/META.yml View File

@@ -1,19 +0,0 @@
name: LEDAKEMLT32
type: kem
claimed-nist-level: 3
claimed-security: IND-CCA2
length-public-key: 12032
length-secret-key: 66
length-ciphertext: 12064
length-shared-secret: 48
nistkat-sha256: b8b17dbb77aa3c3c77f738be053b355185388859ae6baa5655bf7e8413020b7f
principal-submitters:
- Marco Baldi
auxiliary-submitters:
- Alessandro Barenghi
- Franco Chiaraluce
- Gerardo Pelosi
- Paolo Santini
implementations:
- name: leaktime
version: 2.1

+ 0
- 52
crypto_kem/ledakemlt32/leaktime/H_Q_matrices_generation.c View File

@@ -1,52 +0,0 @@
#include "H_Q_matrices_generation.h"
#include "gf2x_arith_mod_xPplusOne.h"

void PQCLEAN_LEDAKEMLT32_LEAKTIME_generateHPosOnes(POSITION_T HPosOnes[N0][DV], AES_XOF_struct *keys_expander) {
for (size_t i = 0; i < N0; i++) {
/* Generate a random block of Htr */
PQCLEAN_LEDAKEMLT32_LEAKTIME_rand_circulant_sparse_block(&HPosOnes[i][0], DV, keys_expander);
}
}

void PQCLEAN_LEDAKEMLT32_LEAKTIME_generateQPosOnes(POSITION_T QPosOnes[N0][M], AES_XOF_struct *keys_expander) {
size_t placed_ones;

for (size_t i = 0; i < N0; i++) {
placed_ones = 0;
for (size_t j = 0; j < N0; j++) {
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], POSITION_T HPosOnes[N0][DV]) {
for (size_t i = 0; i < N0; i++) {
/* Obtain directly the sparse representation of the block of H */
for (size_t k = 0; k < DV; k++) {
HtrPosOnes[i][k] = (P - HPosOnes[i][k]) % P; /* transposes indexes */
}
}
}

void PQCLEAN_LEDAKEMLT32_LEAKTIME_transposeQPosOnes(POSITION_T QtrPosOnes[N0][M], POSITION_T QPosOnes[N0][M]) {
POSITION_T transposed_ones_idx[N0] = {0x00};
size_t currQoneIdx, endQblockIdx;

for (size_t 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]++;
}
}
}
}



+ 0
- 13
crypto_kem/ledakemlt32/leaktime/H_Q_matrices_generation.h View File

@@ -1,13 +0,0 @@
#ifndef H_Q_MATRICES_GENERATION_H
#define H_Q_MATRICES_GENERATION_H

#include "gf2x_arith.h"
#include "qc_ldpc_parameters.h"
#include "rng.h"

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

+ 0
- 31
crypto_kem/ledakemlt32/leaktime/LICENSE View File

@@ -1,31 +0,0 @@
/**
*
* LEDAcryptKEM
*
* @version 2.0 (March 2019)
*
* Adapted code from reference ISO-C11 Implementation of the LEDAcrypt KEM-LT cipher.
*
* In alphabetical order:
*
* @author Marco Baldi <m.baldi@univpm.it>
* @author Alessandro Barenghi <alessandro.barenghi@polimi.it>
* @author Franco Chiaraluce <f.chiaraluce@univpm.it>
* @author Gerardo Pelosi <gerardo.pelosi@polimi.it>
* @author Paolo Santini <p.santini@pm.univpm.it>
*
* This code is hereby placed in the public domain.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
**/

+ 0
- 24
crypto_kem/ledakemlt32/leaktime/Makefile View File

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

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 sort.h utils.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 sort.o utils.o

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

all: $(LIB)

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

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

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

+ 0
- 19
crypto_kem/ledakemlt32/leaktime/Makefile.Microsoft_nmake View File

@@ -1,19 +0,0 @@
# This Makefile can be used with Microsoft Visual Studio's nmake using the command:
# 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 sort.obj utils.obj

CFLAGS=/nologo /O2 /I ..\..\..\common /W4 /WX

all: $(LIBRARY)

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

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

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

+ 0
- 18
crypto_kem/ledakemlt32/leaktime/api.h View File

@@ -1,18 +0,0 @@
#ifndef PQCLEAN_LEDAKEMLT32_LEAKTIME_API_H
#define PQCLEAN_LEDAKEMLT32_LEAKTIME_API_H

#include <stdint.h>

#define PQCLEAN_LEDAKEMLT32_LEAKTIME_CRYPTO_SECRETKEYBYTES 66
#define PQCLEAN_LEDAKEMLT32_LEAKTIME_CRYPTO_PUBLICKEYBYTES 12032
#define PQCLEAN_LEDAKEMLT32_LEAKTIME_CRYPTO_CIPHERTEXTBYTES 12064
#define PQCLEAN_LEDAKEMLT32_LEAKTIME_CRYPTO_BYTES 48

#define PQCLEAN_LEDAKEMLT32_LEAKTIME_CRYPTO_ALGNAME "LEDAKEMLT32"

int PQCLEAN_LEDAKEMLT32_LEAKTIME_crypto_kem_keypair(uint8_t *pk, uint8_t *sk);
int PQCLEAN_LEDAKEMLT32_LEAKTIME_crypto_kem_enc(uint8_t *ct, uint8_t *ss, const uint8_t *pk);
int PQCLEAN_LEDAKEMLT32_LEAKTIME_crypto_kem_dec(uint8_t *ss, const uint8_t *ct, const uint8_t *sk);


#endif

+ 0
- 79
crypto_kem/ledakemlt32/leaktime/bf_decoding.c View File

@@ -1,79 +0,0 @@
#include "bf_decoding.h"
#include "gf2x_arith_mod_xPplusOne.h"

#include <string.h>

int PQCLEAN_LEDAKEMLT32_LEAKTIME_bf_decoding(DIGIT err[],
const POSITION_T HtrPosOnes[N0][DV],
const POSITION_T QtrPosOnes[N0][M],
DIGIT privateSyndrome[],
uint8_t secondIterThreshold) {

DIGIT currSyndrome[NUM_DIGITS_GF2X_ELEMENT];
uint8_t unsatParityChecks[N0 * P];
POSITION_T currQBlkPos[M], currQBitPos[M];
POSITION_T syndromePosToFlip, tmp;
uint32_t correlation, corrt_syndrome_based;
size_t currQoneIdx, endQblockIdx, currblockoffset;
int check;
int iteration = 0;

do {
PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_copy(currSyndrome, privateSyndrome);
memset(unsatParityChecks, 0x00, N0 * P * sizeof(uint8_t));
for (size_t i = 0; i < N0; i++) {
for (POSITION_T valueIdx = 0; valueIdx < P; valueIdx++) {
for (size_t HtrOneIdx = 0; HtrOneIdx < DV; HtrOneIdx++) {
tmp = (HtrPosOnes[i][HtrOneIdx] + valueIdx) >= P ?
(HtrPosOnes[i][HtrOneIdx] + valueIdx) - P :
(HtrPosOnes[i][HtrOneIdx] + valueIdx);
if (PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_get_coeff(currSyndrome, tmp)) {
unsatParityChecks[i * P + valueIdx]++;
}
}
}
}

/* iteration based threshold determination*/
corrt_syndrome_based = iteration * secondIterThreshold + (1 - iteration) * B0;

// Computation of correlation with a full Q matrix
for (size_t i = 0; i < N0; i++) {
for (POSITION_T j = 0; j < P; j++) {
currQoneIdx = endQblockIdx = 0;
correlation = 0;

for (size_t blockIdx = 0; blockIdx < N0; blockIdx++) {
endQblockIdx += qBlockWeights[blockIdx][i];
currblockoffset = blockIdx * P;
for (; currQoneIdx < endQblockIdx; currQoneIdx++) {
tmp = QtrPosOnes[i][currQoneIdx] + j;
tmp = tmp >= P ? tmp - P : tmp;
currQBitPos[currQoneIdx] = tmp;
currQBlkPos[currQoneIdx] = (POSITION_T)blockIdx;
correlation += unsatParityChecks[tmp + currblockoffset];
}
}

/* Correlation based flipping */
if (correlation >= corrt_syndrome_based) {
PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_toggle_coeff(err + NUM_DIGITS_GF2X_ELEMENT * i, j);
for (size_t v = 0; v < M; v++) {
for (size_t HtrOneIdx = 0; HtrOneIdx < DV; HtrOneIdx++) {
syndromePosToFlip = (HtrPosOnes[currQBlkPos[v]][HtrOneIdx] + currQBitPos[v]);
syndromePosToFlip = syndromePosToFlip >= P ? syndromePosToFlip - P : syndromePosToFlip;
PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_toggle_coeff(privateSyndrome, syndromePosToFlip);
}
} // end for v
} // end if
} // end for j
} // end for i

iteration = iteration + 1;
check = 0;
while (check < NUM_DIGITS_GF2X_ELEMENT && privateSyndrome[check++] == 0) {};

} while (iteration < ITERATIONS_MAX && check < NUM_DIGITS_GF2X_ELEMENT);

return (check == NUM_DIGITS_GF2X_ELEMENT);
}

+ 0
- 18
crypto_kem/ledakemlt32/leaktime/bf_decoding.h View File

@@ -1,18 +0,0 @@
#ifndef BF_DECODING_H
#define BF_DECODING_H

#include "gf2x_arith.h"
#include "qc_ldpc_parameters.h"

/* Definitions for DFR level 2^-SL with SL=128 */
#define ITERATIONS_MAX (2)
#define B0 (64)
#define T_BAR (5)

int PQCLEAN_LEDAKEMLT32_LEAKTIME_bf_decoding(DIGIT err[],
const POSITION_T HtrPosOnes[N0][DV],
const POSITION_T QtrPosOnes[N0][M],
DIGIT privateSyndrome[],
uint8_t threshold);

#endif

+ 0
- 88
crypto_kem/ledakemlt32/leaktime/dfr_test.c View File

@@ -1,88 +0,0 @@
#include "bf_decoding.h"
#include "dfr_test.h"
#include "gf2x_arith_mod_xPplusOne.h"
#include "qc_ldpc_parameters.h"
#include "sort.h"

#include <string.h>


int PQCLEAN_LEDAKEMLT32_LEAKTIME_DFR_test(POSITION_T LSparse[N0][DV * M], uint8_t *secondIterThreshold) {

POSITION_T LSparse_loc[N0][DV * M]; /* vector of N_0 sparse blocks */
uint8_t gamma[N0][N0][P] = {{{0}}};
uint32_t gammaHist[N0][DV * M + 1] = {{0}};
size_t maxMut[N0], maxMutMinusOne[N0];
size_t allBlockMaxSumst, allBlockMaxSumstMinusOne;
size_t histIdx, toAdd;

for (size_t i = 0; i < N0; i++) {
for (size_t j = 0; j < DV * M; j++) {
if (LSparse[i][j] != 0) {
LSparse_loc[i][j] = (P - LSparse[i][j]);
}
}
PQCLEAN_LEDAKEMLT32_LEAKTIME_uint32_sort(LSparse_loc[i], DV * M);
}


for (size_t i = 0; i < N0; i++ ) {
for (size_t j = 0; j < N0; j++) {
for (size_t k = 0; k < (DV * M); k++) {
for (size_t l = 0; l < (DV * M); l++) {
gamma[i][j][(P + LSparse_loc[i][k] - LSparse_loc[j][l]) % P]++;
}
}
}
}

for (size_t i = 0; i < N0; i++ ) {
for (size_t j = 0; j < N0; j++ ) {
gamma[i][j][0] = 0;
}
}

/* build histogram of values in gamma */
for (size_t i = 0; i < N0; i++ ) {
for (size_t j = 0; j < N0; j++ ) {
for (size_t k = 0; k < P; k++) {
gammaHist[i][gamma[i][j][k]]++;
}
}
}


for (size_t gammaBlockRowIdx = 0; gammaBlockRowIdx < N0; gammaBlockRowIdx++) {
maxMutMinusOne[gammaBlockRowIdx] = 0;
histIdx = DV * M;
toAdd = T_BAR - 1;
while ( (histIdx > 0) && (toAdd > 0)) {
if (gammaHist[gammaBlockRowIdx][histIdx] > toAdd ) {
maxMutMinusOne[gammaBlockRowIdx] += histIdx * toAdd;
toAdd = 0;
} else {
maxMutMinusOne[gammaBlockRowIdx] += histIdx * gammaHist[gammaBlockRowIdx][histIdx];
toAdd -= gammaHist[gammaBlockRowIdx][histIdx];
histIdx--;
}
}
maxMut[gammaBlockRowIdx] = histIdx + maxMutMinusOne[gammaBlockRowIdx];
}

/*seek max values across all gamma blocks */
allBlockMaxSumst = maxMut[0];
allBlockMaxSumstMinusOne = maxMutMinusOne[0];
for (size_t gammaBlockRowIdx = 0; gammaBlockRowIdx < N0; gammaBlockRowIdx++) {
allBlockMaxSumst = allBlockMaxSumst < maxMut[gammaBlockRowIdx] ?
maxMut[gammaBlockRowIdx] :
allBlockMaxSumst;
allBlockMaxSumstMinusOne = allBlockMaxSumstMinusOne < maxMutMinusOne[gammaBlockRowIdx] ?
maxMutMinusOne[gammaBlockRowIdx] :
allBlockMaxSumstMinusOne;
}
if (DV * M > (allBlockMaxSumstMinusOne + allBlockMaxSumst)) {
*secondIterThreshold = (uint8_t) (allBlockMaxSumst + 1);
return 1;
}
return 0;
}

+ 0
- 6
crypto_kem/ledakemlt32/leaktime/dfr_test.h View File

@@ -1,6 +0,0 @@
#ifndef DFR_TEST_H
#define DFR_TEST_H

int PQCLEAN_LEDAKEMLT32_LEAKTIME_DFR_test(POSITION_T LSparse[N0][DV * M], uint8_t *secondIterThreshold);

#endif

+ 0
- 252
crypto_kem/ledakemlt32/leaktime/gf2x_arith.c View File

@@ -1,252 +0,0 @@
#include "gf2x_arith.h"

#include <string.h> // memset(...)

void PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_add(DIGIT Res[], const DIGIT A[], const DIGIT B[], size_t n) {
for (size_t i = 0; i < n; i++) {
Res[i] = A[i] ^ B[i];
}
}

/* copies len digits from a to r if b == 1 */
void PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_cmov(DIGIT *r, const DIGIT *a, size_t len, int c) {
DIGIT mask = (DIGIT)(-c);
for (size_t i = 0; i < len; i++) {
r[i] ^= mask & (a[i] ^ r[i]);
}
}

/* PRE: MAX ALLOWED ROTATION AMOUNT : DIGIT_SIZE_b */
void PQCLEAN_LEDAKEMLT32_LEAKTIME_right_bit_shift_n(size_t length, DIGIT in[], size_t amount) {
if ( amount == 0 ) {
return;
}
size_t j;
DIGIT mask;
mask = ((DIGIT)0x01 << amount) - 1;
for (j = length - 1; j > 0; j--) {
in[j] >>= amount;
in[j] |= (in[j - 1] & mask) << (DIGIT_SIZE_b - amount);
}
in[j] >>= amount;
}

/* PRE: MAX ALLOWED ROTATION AMOUNT : DIGIT_SIZE_b */
void PQCLEAN_LEDAKEMLT32_LEAKTIME_left_bit_shift_n(size_t length, DIGIT in[], size_t amount) {
if ( amount == 0 ) {
return;
}
size_t j;
DIGIT mask;
mask = ~(((DIGIT)0x01 << (DIGIT_SIZE_b - amount)) - 1);
for (j = 0 ; j < length - 1; j++) {
in[j] <<= amount;
in[j] |= (in[j + 1] & mask) >> (DIGIT_SIZE_b - amount);
}
in[j] <<= amount;
}


static void gf2x_mul1(DIGIT *R, const DIGIT A, const DIGIT B) {
DIGIT tmp;

R[0] = 0;
R[1] = (A & 1) * B;
for (uint8_t i = 1; i < DIGIT_SIZE_b; i++) {
tmp = ((A >> i) & 1) * B;
R[1] ^= tmp << i;
R[0] ^= tmp >> (DIGIT_SIZE_b - i);
}
}

static void gf2x_mul_n(DIGIT *R, const DIGIT *A, const DIGIT *B, size_t n) {
DIGIT tmp[2];

memset(R, 0x00, 2 * n * sizeof(DIGIT));
for (size_t i = 0; i < n; i++) {
for (size_t j = 0; j < n; j++) {
gf2x_mul1(tmp, A[i], B[j]);
R[i + j] ^= tmp[0];
R[i + j + 1] ^= tmp[1];
}
}
}

static void gf2x_cpy(DIGIT *R, const DIGIT *A, size_t len) {
for (size_t i = 0; i < len; i++) {
R[i] = A[i];
}
}

/* Accumulate */
#define gf2x_add(R, A, B, n) PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_add(R, A, B, n)
#define gf2x_acc(R, B, n) PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_add(R, R, B, n)

/* allows the operands to be of different size
* first operand must be the bigger one.
* aligns last array elements */
static inline void gf2x_add_asymm(DIGIT *R,
size_t na, const DIGIT *A,
size_t nb, const DIGIT *B) {
size_t delta = na - nb;
gf2x_cpy(R, A, delta);
gf2x_add(R + delta, A + delta, B, nb);;
}

/* aligns first array elements */
static inline void gf2x_add_asymm2(DIGIT *R,
size_t na, const DIGIT *A,
size_t nb, const DIGIT *B) {
size_t delta = na - nb;
gf2x_add(R, A, B, nb);
gf2x_cpy(R + nb, A + nb, delta);
}

/* Karatsuba with lowered space complexity
* T(n) = 3 * ceil(n/2) + T(ceil(n / 2)) */
static void gf2x_mul_kar(DIGIT *R,
const DIGIT *A,
const DIGIT *B,
size_t n,
DIGIT *stack) {

if (n < MIN_KAR_DIGITS) {
gf2x_mul_n(R, A, B, n);
return;
}

size_t l = (n + 1) / 2; // limb size = ceil(n / 2)
size_t d = n & 1;

const DIGIT *a1 = A; // length n - d
const DIGIT *a0 = A + l - d; // length n
const DIGIT *b1 = B;
const DIGIT *b0 = B + l - d;

DIGIT *aa = stack;
DIGIT *bb = aa + l;
DIGIT *cc = bb + l;
stack = cc + l; // 3l space requirement at each level

DIGIT *c3 = R + l - 2 * d;
DIGIT *c2 = c3 + l;
DIGIT *c1 = c2 + l;

gf2x_mul_kar(c2, a0, b0, l, stack); // L in low part of R
gf2x_mul_kar(R, a1, b1, l - d, stack); // H in higher part of R
gf2x_add_asymm(aa, l, a0, l - d, a1); // AH + AL
gf2x_add_asymm(bb, l, b0, l - d, b1); // BH + BL
gf2x_add(cc, c3, c2, l); // HL + LH in cc
gf2x_mul_kar(c3, aa, bb, l, stack); // M = (AH + AL) x (BH + BL)
gf2x_add_asymm(c3, l, c3, l - 2 * d, R); // add HH
gf2x_acc(c2, c1, l); // add LL
gf2x_acc(c3, cc, l); // add HL + LH
gf2x_acc(c2, cc, l); // add HL + LH
}

static void gf2x_div_w_plus_one(DIGIT *A, size_t n) {
size_t i;
for (i = 0; i < n - 2; i++) {
A[i + 1] ^= A[i]; // runs n - 2 times
}
}

static void gf2x_shift_left_w(DIGIT *A, size_t n) {
size_t i;
for (i = 0; i < n - 1; i++) {
A[i] = A[i + 1];
}
A[i] = 0;
}

/* Word-aligned Toom-Cook 3, source:
* Brent, Richard P., et al. "Faster multiplication in GF (2)[x]."
* International Algorithmic Number Theory Symposium.
* Springer, Berlin, Heidelberg, 2008. */
static void gf2x_mul_tc3w(DIGIT *R,
const DIGIT *A,
const DIGIT *B,
size_t n,
DIGIT *stack) {

if (n < MIN_TOOM_DIGITS) {
gf2x_mul_kar(R, A, B, n, stack);
return;
}

size_t l = (n + 2) / 3; // size of a0, a1, b0, b1
size_t r = n - 2 * l; // remaining sizes (a2, b2)
size_t x = 2 * l + 4; // size of c1, c2, c3, c4
size_t z = r + 2 > l + 1 ? r + 2 : l + 1; // size of c5

const DIGIT *a0 = A;
const DIGIT *a1 = A + l;
const DIGIT *a2 = A + 2 * l;
const DIGIT *b0 = B;
const DIGIT *b1 = B + l;
const DIGIT *b2 = B + 2 * l;

DIGIT *c0 = R; // c0 and c4 in the result
DIGIT *c4 = R + 4 * l;
DIGIT *c1 = stack; // the rest in the stack
DIGIT *c2 = c1 + x;
DIGIT *c3 = c2 + x;
DIGIT *c5 = c3 + x;
stack = c5 + z; // Worst-case 7l + 14

// Evaluation
c0[0] = 0; // c0[z] = a1*W + a2*W^2
c0[l + 1] = 0;
gf2x_cpy(c0 + 1, a1, l);
gf2x_acc(c0 + 2, a2, r);

c4[0] = 0; // c4[z] = b1*W + b2*W^2
c4[l + 1] = 0;
gf2x_cpy(c4 + 1, b1, l);
gf2x_acc(c4 + 2, b2, r);

gf2x_cpy(c5, a0, l); // c5[l] = a0 + a1 + a2
gf2x_acc(c5, a1, l);
gf2x_acc(c5, a2, r);

gf2x_cpy(c2, b0, l); // c2[l] = b0 + b1 + b2
gf2x_acc(c2, b1, l);
gf2x_acc(c2, b2, r);

gf2x_mul_tc3w(c1, c2, c5, l, stack); // c1[2l] = c2 * c5
gf2x_add_asymm2(c5, z, c0, l, c5); // c5[z] += c0, z >= l
gf2x_add_asymm2(c2, z, c4, l, c2); // c2[z] += c4, idem
gf2x_acc(c0, a0, l); // c0[l] += a0
gf2x_acc(c4, b0, l); // c4[l] += b0
gf2x_mul_tc3w(c3, c2, c5, z, stack); // c3[2z] = c2 * c5
gf2x_mul_tc3w(c2, c0, c4, z, stack); // c2[2z] = c0 * c4
gf2x_mul_tc3w(c0, a0, b0, l, stack); // c0[2l] = a0 * b0
gf2x_mul_tc3w(c4, a2, b2, r, stack); // c4[2r] = a2 * b2

// Interpolation
gf2x_acc(c3, c2, 2 * z); // c3[2z] += c2
gf2x_acc(c2, c0, 2 * l); // c2[2z] += c0
gf2x_shift_left_w(c2, 2 * z); // c2[2z] = c2/y + c3
gf2x_acc(c2, c3, 2 * z);
gf2x_acc(c2, c4, 2 * r); // c2[2z] += c4 + c4**3
gf2x_acc(c2 + 3, c4, 2 * r);
gf2x_div_w_plus_one(c2, 2 * z); // c2[2z-1] = c2/(W+1)
gf2x_acc(c1, c0, 2 * l); // c1[2l] += c0
gf2x_acc(c3, c1, 2 * l); // c3[2z] += c1
gf2x_shift_left_w(c3, 2 * z); // c3[2z-2] = c3/(W^2 + W)
gf2x_div_w_plus_one(c3, 2 * z - 1);
gf2x_add_asymm2(c1, 2 * z, c2, 2 * l, c1); // c1[2z-1] += c2 + c4
gf2x_acc(c1, c4, 2 * r); // size c2 >= c1 >= c4
gf2x_acc(c2, c3, 2 * z - 1); // c2[2z-1] += c3

// Recombination
gf2x_cpy(R + 2 * l, c2, 2 * l);
gf2x_acc(R + l, c1, 2 * z - 1);
gf2x_acc(R + 3 * l, c3, 2 * z - 1);
}

void PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_mul(DIGIT *R, const DIGIT *A, const DIGIT *B, size_t n) {
DIGIT stack[STACK_WORDS];
gf2x_mul_tc3w(R, A, B, n, stack);
}


+ 0
- 63
crypto_kem/ledakemlt32/leaktime/gf2x_arith.h View File

@@ -1,63 +0,0 @@
#ifndef GF2X_ARITH_H
#define GF2X_ARITH_H

#include <inttypes.h>
#include <stddef.h>

/*
* Elements of GF(2)[x] are stored in compact dense binary form.
*
* Each bit in a byte is assumed to be the coefficient of a binary
* polynomial f(x), in Big-Endian format (i.e., reading everything from
* left to right, the most significant element is met first):
*
* byte:(0000 0000) == 0x00 ... f(x) == 0
* byte:(0000 0001) == 0x01 ... f(x) == 1
* byte:(0000 0010) == 0x02 ... f(x) == x
* byte:(0000 0011) == 0x03 ... f(x) == x+1
* ... ... ...
* byte:(0000 1111) == 0x0F ... f(x) == x^{3}+x^{2}+x+1
* ... ... ...
* byte:(1111 1111) == 0xFF ... f(x) == x^{7}+x^{6}+x^{5}+x^{4}+x^{3}+x^{2}+x+1
*
*
* A "machine word" (A_i) is considered as a DIGIT.
* Bytes in a DIGIT are assumed in Big-Endian format:
* E.g., if sizeof(DIGIT) == 4:
* A_i: A_{i,3} A_{i,2} A_{i,1} A_{i,0}.
* A_{i,3} denotes the most significant byte, A_{i,0} the least significant one.
* f(x) == x^{31} + ... + x^{24} +
* + x^{23} + ... + x^{16} +
* + x^{15} + ... + x^{8} +
* + x^{7} + ... + x^{0}
*
*
* Multi-precision elements (i.e., with multiple DIGITs) are stored in
* Big-endian format:
* A = A_{n-1} A_{n-2} ... A_1 A_0
*
* position[A_{n-1}] == 0
* position[A_{n-2}] == 1
* ...
* position[A_{1}] == n-2
* position[A_{0}] == n-1
*/

typedef uint64_t DIGIT;
#define DIGIT_SIZE_B (8)
#define DIGIT_SIZE_b (DIGIT_SIZE_B << 3)
#define POSITION_T uint32_t

#define MIN_KAR_DIGITS 10
#define MIN_TOOM_DIGITS 42

#define STACK_KAR_ONLY 4497
#define STACK_WORDS 5336

void PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_add(DIGIT Res[], const DIGIT A[], const DIGIT B[], size_t n);
void PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_cmov(DIGIT *r, const DIGIT *a, size_t len, int c);
void PQCLEAN_LEDAKEMLT32_LEAKTIME_right_bit_shift_n(size_t length, DIGIT in[], size_t amount);
void PQCLEAN_LEDAKEMLT32_LEAKTIME_left_bit_shift_n(size_t length, DIGIT in[], size_t amount);
void PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_mul(DIGIT *R, const DIGIT *A, const DIGIT *B, size_t n);

#endif

+ 0
- 529
crypto_kem/ledakemlt32/leaktime/gf2x_arith_mod_xPplusOne.c View File

@@ -1,529 +0,0 @@
#include "gf2x_arith_mod_xPplusOne.h"
#include "rng.h"
#include "sort.h"

#include <string.h> // memcpy(...), memset(...)

void PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_copy(DIGIT dest[], const DIGIT in[]) {
for (size_t i = 0; i < NUM_DIGITS_GF2X_ELEMENT; i++) {
dest[i] = in[i];
}
}

/* returns the coefficient of the x^exponent term as the LSB of a digit */
DIGIT PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_get_coeff(const DIGIT poly[], size_t exponent) {
size_t straightIdx = (NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_b - 1) - exponent;
size_t digitIdx = straightIdx / DIGIT_SIZE_b;
size_t inDigitIdx = straightIdx % DIGIT_SIZE_b;
return (poly[digitIdx] >> (DIGIT_SIZE_b - 1 - inDigitIdx)) & ((DIGIT) 1) ;
}

/* sets the coefficient of the x^exponent term as the LSB of a digit */
void PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_set_coeff(DIGIT poly[], size_t exponent, DIGIT value) {
size_t straightIdx = (NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_b - 1) - exponent;
size_t digitIdx = straightIdx / DIGIT_SIZE_b;
size_t inDigitIdx = straightIdx % DIGIT_SIZE_b;

/* clear given coefficient */
DIGIT mask = ~(((DIGIT) 1) << (DIGIT_SIZE_b - 1 - inDigitIdx));
poly[digitIdx] = poly[digitIdx] & mask;
poly[digitIdx] = poly[digitIdx] | ((value & ((DIGIT) 1)) << (DIGIT_SIZE_b - 1 - inDigitIdx));
}

/* toggles (flips) the coefficient of the x^exponent term as the LSB of a digit */
void PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_toggle_coeff(DIGIT poly[], size_t exponent) {
size_t straightIdx = (NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_b - 1) - exponent;
size_t digitIdx = straightIdx / DIGIT_SIZE_b;
size_t inDigitIdx = straightIdx % DIGIT_SIZE_b;

/* clear given coefficient */
DIGIT mask = (((DIGIT) 1) << (DIGIT_SIZE_b - 1 - inDigitIdx));
poly[digitIdx] = poly[digitIdx] ^ mask;
}

/* population count for an unsigned 64-bit integer
Source: Hacker's delight, p.66 */
static int popcount_uint64t(uint64_t x) {
x -= (x >> 1) & 0x5555555555555555;
x = (x & 0x3333333333333333) + ((x >> 2) & 0x3333333333333333);
x = (x + (x >> 4)) & 0x0f0f0f0f0f0f0f0f;
return (int)((x * 0x0101010101010101) >> 56);
}

/* population count for a single polynomial */
int PQCLEAN_LEDAKEMLT32_LEAKTIME_population_count(const DIGIT *poly) {
int ret = 0;
for (int i = NUM_DIGITS_GF2X_ELEMENT - 1; i >= 0; i--) {
ret += popcount_uint64t(poly[i]);
}
return ret;
}

void PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_mod_add(DIGIT Res[], const DIGIT A[], const DIGIT B[]) {
PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_add(Res, A, B, NUM_DIGITS_GF2X_ELEMENT);
}

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 right_bit_shift(size_t length, DIGIT in[]) {
size_t j;
for (j = length - 1; j > 0; j--) {
in[j] >>= 1;
in[j] |= (in[j - 1] & (DIGIT)0x01) << (DIGIT_SIZE_b - 1);
}
in[j] >>= 1;
}


/* shifts by whole digits */
static void left_DIGIT_shift_n(size_t length, DIGIT in[], size_t amount) {
size_t j;
for (j = 0; (j + amount) < length; j++) {
in[j] = in[j + amount];
}
for (; j < length; j++) {
in[j] = (DIGIT)0;
}
}

/* may shift by an arbitrary amount*/
static void left_bit_shift_wide_n(size_t length, DIGIT in[], size_t amount) {
left_DIGIT_shift_n(length, in, amount / DIGIT_SIZE_b);
PQCLEAN_LEDAKEMLT32_LEAKTIME_left_bit_shift_n(length, in, amount % DIGIT_SIZE_b);
}

/* Hackers delight, reverses a uint64_t */
static DIGIT reverse_digit(DIGIT x) {
uint64_t t;
x = (x << 31) | (x >> 33);
t = (x ^ (x >> 20)) & 0x00000FFF800007FFLL;
x = (t | (t << 20)) ^ x;
t = (x ^ (x >> 8)) & 0x00F8000F80700807LL;
x = (t | (t << 8)) ^ x;
t = (x ^ (x >> 4)) & 0x0808708080807008LL;
x = (t | (t << 4)) ^ x;
t = (x ^ (x >> 2)) & 0x1111111111111111LL;
x = (t | (t << 2)) ^ x;
return x;
}

void PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_transpose_in_place(DIGIT A[]) {
/* it keeps the lsb in the same position and
* inverts the sequence of the remaining bits */

DIGIT mask = (DIGIT)0x1;
DIGIT rev1, rev2, a00;
int slack_bits_amount = NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_b - P;

a00 = A[NUM_DIGITS_GF2X_ELEMENT - 1] & mask;
right_bit_shift(NUM_DIGITS_GF2X_ELEMENT, A);

for (size_t i = NUM_DIGITS_GF2X_ELEMENT - 1; i >= (NUM_DIGITS_GF2X_ELEMENT + 1) / 2; i--) {
rev1 = reverse_digit(A[i]);
rev2 = reverse_digit(A[NUM_DIGITS_GF2X_ELEMENT - 1 - i]);
A[i] = rev2;
A[NUM_DIGITS_GF2X_ELEMENT - 1 - i] = rev1;
}

if (slack_bits_amount) {
PQCLEAN_LEDAKEMLT32_LEAKTIME_right_bit_shift_n(NUM_DIGITS_GF2X_ELEMENT, A, slack_bits_amount);
}
A[NUM_DIGITS_GF2X_ELEMENT - 1] = (A[NUM_DIGITS_GF2X_ELEMENT - 1] & (~mask)) | a00;
}

static void rotate_bit_right(DIGIT in[]) { /* x^{-1} * in(x) mod x^P+1 */

DIGIT rotated_bit = in[NUM_DIGITS_GF2X_ELEMENT - 1] & ((DIGIT)0x1);
right_bit_shift(NUM_DIGITS_GF2X_ELEMENT, in);
int msb_offset_in_digit = MSb_POSITION_IN_MSB_DIGIT_OF_MODULUS - 1;
rotated_bit = rotated_bit << msb_offset_in_digit;
in[0] |= rotated_bit;
}

/* cond swap: swaps digits A and B if swap_mask == -1 */
static void gf2x_cswap(DIGIT *a, DIGIT *b, int32_t swap_mask) {
DIGIT t;
for (size_t i = 0; i < NUM_DIGITS_GF2X_ELEMENT; i++) {
t = swap_mask & (a[i] ^ b[i]);
a[i] ^= t;
b[i] ^= t;
}
}

/* returns -1 mask if x != 0, otherwise 0 */
static inline int32_t nonzero(DIGIT x) {
DIGIT t = x;
t = (~t) + 1;
t >>= DIGIT_SIZE_b - 1;
return -((int32_t)t);
}

/* returns -1 mask if x < 0 else 0 */
static inline int32_t negative(int x) {
uint32_t u = x;
u >>= 31;
return -((int32_t)u);
}

/* return f(0) as digit */
static inline DIGIT lsb(const DIGIT *p) {
DIGIT mask = (DIGIT)1;
return p[NUM_DIGITS_GF2X_ELEMENT - 1] & mask;
}

/* multiply poly with scalar and accumulate, expects s all-zero of all-one mask */
static void gf2x_mult_scalar_acc(DIGIT *f, const DIGIT *g, const DIGIT s) {
for (size_t i = 0; i < NUM_DIGITS_GF2X_ELEMENT; i++) {
f[i] = f[i] ^ (s & g[i]);
}
}

/* constant-time inverse, source: gcd.cr.yp.to */
int PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_mod_inverse(DIGIT out[], const DIGIT in[]) {
int32_t swap, delta = 1;
DIGIT g0_mask;

DIGIT f[NUM_DIGITS_GF2X_MODULUS] = {0}; // f = x^P + 1
DIGIT g[NUM_DIGITS_GF2X_ELEMENT]; // g = in
DIGIT *v = out; // v = 0, save space
DIGIT r[NUM_DIGITS_GF2X_ELEMENT] = {0}; // r = 1

f[NUM_DIGITS_GF2X_MODULUS - 1] = 1;
f[0] |= ((DIGIT)1 << MSb_POSITION_IN_MSB_DIGIT_OF_MODULUS);

for (size_t i = 0; i < NUM_DIGITS_GF2X_ELEMENT; i++) {
g[i] = in[i];
}

for (size_t i = 0; i < NUM_DIGITS_GF2X_ELEMENT; i++) {
v[i] = 0;
}

r[NUM_DIGITS_GF2X_ELEMENT - 1] = 1;

for (int loop = 0; loop < 2 * P - 1; ++loop) {

swap = negative(-delta) & nonzero(lsb(g)); // swap = -1 if -delta < 0 AND g(0) != 0
delta ^= swap & (delta ^ -delta); // cond swap delta with -delta if swap
delta++;

gf2x_cswap(f, g, swap);
gf2x_cswap(v, r, swap);

g0_mask = ~lsb(g) + 1;

// g = (g - g0 * f) / x
gf2x_mult_scalar_acc(g, f, g0_mask);
right_bit_shift(NUM_DIGITS_GF2X_ELEMENT, g);

// r = (r - g0 * v) / x
gf2x_mult_scalar_acc(r, v, g0_mask);
rotate_bit_right(r);

}

return nonzero(delta); // -1 if fail, 0 if success
}

void PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_mod_mul(DIGIT Res[], const DIGIT A[], const DIGIT B[]) {

DIGIT aux[2 * NUM_DIGITS_GF2X_ELEMENT];
PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_mul(aux, A, B, NUM_DIGITS_GF2X_ELEMENT);
gf2x_mod(Res, aux);

}

/*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[], size_t 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);

if (sparse[0] != INVALID_POS_VALUE) {
left_bit_shift_wide_n(2 * NUM_DIGITS_GF2X_ELEMENT, resDouble, sparse[0]);
left_bit_shift_wide_n(2 * NUM_DIGITS_GF2X_ELEMENT, aux, sparse[0]);

for (size_t i = 1; i < nPos; i++) {
if (sparse[i] != INVALID_POS_VALUE) {
left_bit_shift_wide_n(2 * NUM_DIGITS_GF2X_ELEMENT, aux, (sparse[i] - sparse[i - 1]) );
PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_add(resDouble, aux, resDouble, 2 * NUM_DIGITS_GF2X_ELEMENT);
}
}
}

gf2x_mod(Res, resDouble);

}

void PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_transpose_in_place_sparse(size_t sizeA, POSITION_T A[]) {
POSITION_T t;
size_t i = 0, j;

if (A[i] == 0) {
i = 1;
}
j = i;

for (; i < sizeA && A[i] != INVALID_POS_VALUE; i++) {
A[i] = P - A[i];
}

for (i -= 1; j < i; j++, i--) {
t = A[j];
A[j] = A[i];
A[i] = t;
}

}

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[]) {

POSITION_T prod;
POSITION_T lastReadPos;
size_t duplicateCount;
size_t write_idx, read_idx;

/* 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++) {
prod = A[i] + B[j];
prod = ( (prod >= P) ? prod - P : prod);
if ((A[i] != INVALID_POS_VALUE) &&
(B[j] != INVALID_POS_VALUE)) {
Res[lastFilledPos] = prod;
} else {
Res[lastFilledPos] = INVALID_POS_VALUE;
}
lastFilledPos++;
}
}
while (lastFilledPos < sizeR) {
Res[lastFilledPos] = INVALID_POS_VALUE;
lastFilledPos++;
}

PQCLEAN_LEDAKEMLT32_LEAKTIME_uint32_sort(Res, sizeR);

/* eliminate duplicates */
write_idx = read_idx = 0;
while (read_idx < sizeR && Res[read_idx] != INVALID_POS_VALUE) {
lastReadPos = Res[read_idx];
read_idx++;
duplicateCount = 1;
while ( (Res[read_idx] == lastReadPos) && (Res[read_idx] != INVALID_POS_VALUE)) {
read_idx++;
duplicateCount++;
}
if (duplicateCount % 2) {
Res[write_idx] = lastReadPos;
write_idx++;
}
}
/* fill remaining cells with INVALID_POS_VALUE */
for (; write_idx < sizeR; write_idx++) {
Res[write_idx] = INVALID_POS_VALUE;
}
}

/* the implementation is safe even in case A or B alias with the result
* PRE: A and B should be sorted, disjunct arrays ending with INVALID_POS_VALUE */
void PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_mod_add_sparse(size_t sizeR, POSITION_T Res[],
size_t sizeA, const POSITION_T A[],
size_t sizeB, const POSITION_T B[]) {

POSITION_T tmpRes[DV * M];
size_t idxA = 0, idxB = 0, idxR = 0;
while ( idxA < sizeA &&
idxB < sizeB &&
A[idxA] != INVALID_POS_VALUE &&
B[idxB] != INVALID_POS_VALUE ) {

if (A[idxA] == B[idxB]) {
idxA++;
idxB++;
} else {
if (A[idxA] < B[idxB]) {
tmpRes[idxR] = A[idxA];
idxA++;
} else {
tmpRes[idxR] = B[idxB];
idxB++;
}
idxR++;
}
}

while (idxA < sizeA && A[idxA] != INVALID_POS_VALUE) {
tmpRes[idxR] = A[idxA];
idxA++;
idxR++;
}

while (idxB < sizeB && B[idxB] != INVALID_POS_VALUE) {
tmpRes[idxR] = B[idxB];
idxB++;
idxR++;
}

while (idxR < sizeR) {
tmpRes[idxR] = INVALID_POS_VALUE;
idxR++;
}
memcpy(Res, tmpRes, sizeof(POSITION_T)*sizeR);

}

/* Return a uniform random value in the range 0..n-1 inclusive,
* applying a rejection sampling strategy and exploiting as a random source
* the NIST seedexpander seeded with the proper key.
* Assumes that the maximum value for the range n is 2^32-1
*/
static uint32_t rand_range(const unsigned int n, const int logn, AES_XOF_struct *seed_expander_ctx) {
unsigned long required_rnd_bytes = (logn + 7) / 8;
unsigned char rnd_char_buffer[4];
uint32_t rnd_value;
uint32_t mask = ( (uint32_t)1 << logn) - 1;

do {
PQCLEAN_LEDAKEMLT32_LEAKTIME_seedexpander(seed_expander_ctx, rnd_char_buffer, required_rnd_bytes);
/* obtain an endianness independent representation of the generated random
bytes into an unsigned integer */
rnd_value = ((uint32_t)rnd_char_buffer[3] << 24) +
((uint32_t)rnd_char_buffer[2] << 16) +
((uint32_t)rnd_char_buffer[1] << 8) +
((uint32_t)rnd_char_buffer[0] << 0) ;
rnd_value = mask & rnd_value;
} while (rnd_value >= n);

return rnd_value;
}

/* Obtains fresh randomness and seed-expands it until all the required positions
* for the '1's in the circulant block are obtained */
void PQCLEAN_LEDAKEMLT32_LEAKTIME_rand_circulant_sparse_block(POSITION_T *pos_ones,
size_t countOnes,
AES_XOF_struct *seed_expander_ctx) {

size_t duplicated, placedOnes = 0;
POSITION_T p;

while (placedOnes < countOnes) {
p = rand_range(NUM_BITS_GF2X_ELEMENT,
P_BITS,
seed_expander_ctx);
duplicated = 0;
for (size_t j = 0; j < placedOnes; j++) {
if (pos_ones[j] == p) {
duplicated = 1;
}
}
if (duplicated == 0) {
pos_ones[placedOnes] = p;
placedOnes++;
}
}
}

/* 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) {

size_t polyIndex, duplicated, counter = 0;
POSITION_T p, exponent, rndPos[NUM_ERRORS_T];

memset(sequence, 0x00, N0 * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B);

while (counter < NUM_ERRORS_T) {
p = rand_range(N0 * NUM_BITS_GF2X_ELEMENT, P_BITS, seed_expander_ctx);
duplicated = 0;
for (size_t j = 0; j < counter; j++) {
if (rndPos[j] == p) {
duplicated = 1;
}
}
if (duplicated == 0) {
rndPos[counter] = p;
counter++;
}
}
for (size_t j = 0; j < counter; j++) {
polyIndex = rndPos[j] / P;
exponent = rndPos[j] % P;
PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_set_coeff( sequence + NUM_DIGITS_GF2X_ELEMENT * polyIndex, exponent,
( (DIGIT) 1));
}

}


void PQCLEAN_LEDAKEMLT32_LEAKTIME_rand_error_pos(POSITION_T errorPos[NUM_ERRORS_T],
AES_XOF_struct *seed_expander_ctx) {

int duplicated;
size_t counter = 0;

while (counter < NUM_ERRORS_T) {
POSITION_T p = rand_range(N0 * NUM_BITS_GF2X_ELEMENT, P_BITS, seed_expander_ctx);
duplicated = 0;
for (size_t 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],
const POSITION_T errorPos[NUM_ERRORS_T]) {

size_t polyIndex;
POSITION_T exponent;

memset(sequence, 0x00, N0 * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B);
for (int j = 0; j < NUM_ERRORS_T; j++) {
polyIndex = errorPos[j] / P;
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++) {
for (j = 0; j < DIGIT_SIZE_B; j++) {
bytes[i * DIGIT_SIZE_B + j] = (uint8_t) (poly[i] >> 8 * j);
}
}
}

void PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_frombytes(DIGIT *poly, const uint8_t *poly_bytes) {
size_t i, j;
for (i = 0; i < NUM_DIGITS_GF2X_ELEMENT; i++) {
poly[i] = (DIGIT) 0;
for (j = 0; j < DIGIT_SIZE_B; j++) {
poly[i] |= (DIGIT) poly_bytes[i * DIGIT_SIZE_B + j] << 8 * j;
}
}
}

+ 0
- 39
crypto_kem/ledakemlt32/leaktime/gf2x_arith_mod_xPplusOne.h View File

@@ -1,39 +0,0 @@
#ifndef GF2X_ARITH_MOD_XPLUSONE_H
#define GF2X_ARITH_MOD_XPLUSONE_H

#include "qc_ldpc_parameters.h"

#include "gf2x_arith.h"
#include "rng.h"

#define NUM_BITS_GF2X_ELEMENT (P)
#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)
#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)

void PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_copy(DIGIT dest[], const DIGIT in[]);
DIGIT PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_get_coeff(const DIGIT poly[], size_t exponent);
void PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_set_coeff(DIGIT poly[], size_t exponent, DIGIT value);
void PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_toggle_coeff(DIGIT poly[], size_t exponent);
int PQCLEAN_LEDAKEMLT32_LEAKTIME_population_count(const DIGIT *poly);
void PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_mod_add(DIGIT Res[], const DIGIT A[], const DIGIT B[]);
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, size_t 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], const POSITION_T errorPos[NUM_ERRORS_T]);
void PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_mod_add_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_transpose_in_place_sparse(size_t 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_dense_to_sparse(DIGIT Res[], const DIGIT dense[], POSITION_T sparse[], size_t 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);


#endif

+ 0
- 157
crypto_kem/ledakemlt32/leaktime/kem.c View File

@@ -1,157 +0,0 @@
#include "api.h"
#include "niederreiter.h"
#include "randombytes.h"
#include "rng.h"
#include "utils.h"

#include <string.h>


#define pack_ct(sk_bytes, ct) PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_tobytes(sk_bytes, ct);
#define unpack_ct(ct, ct_bytes) PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_frombytes(ct, ct_bytes)

static void pack_pk(uint8_t *pk_bytes, publicKeyNiederreiter_t *pk) {
for (size_t i = 0; i < N0 - 1; i++) {
PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_tobytes(pk_bytes + i * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B,
pk->Mtr + i * NUM_DIGITS_GF2X_ELEMENT);
}
}

static void unpack_pk(publicKeyNiederreiter_t *pk, const uint8_t *pk_bytes) {
for (size_t i = 0; i < N0 - 1; i++) {
PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_frombytes(pk->Mtr + i * NUM_DIGITS_GF2X_ELEMENT,
pk_bytes + i * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B);
}
}

static void pack_error(uint8_t *error_bytes, DIGIT *error_digits) {
size_t i;
for (i = 0; i < N0; i++) {
PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_tobytes(error_bytes + i * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B,
error_digits + i * NUM_DIGITS_GF2X_ELEMENT);
}
}

/* IND-CCA2 Keygen */
int PQCLEAN_LEDAKEMLT32_LEAKTIME_crypto_kem_keypair(uint8_t *pk, uint8_t *sk) {
publicKeyNiederreiter_t niederreiter_pk;

PQCLEAN_LEDAKEMLT32_LEAKTIME_niederreiter_keygen(&niederreiter_pk, (privateKeyNiederreiter_t *) sk);

pack_pk(pk, &niederreiter_pk);

return 0;
}

/* IND-CCA2 Encapsulation */
int PQCLEAN_LEDAKEMLT32_LEAKTIME_crypto_kem_enc(uint8_t *ct, uint8_t *ss, const uint8_t *pk) {
publicKeyNiederreiter_t niederreiter_pk;
DIGIT syndrome[NUM_DIGITS_GF2X_ELEMENT];
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];
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];

unpack_pk(&niederreiter_pk, 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);

memcpy(hashedAndTruncatedSeed, hashedSeed, TRNG_BYTE_LENGTH);

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);

pack_error(error_bytes, error_vector);
HASH_FUNCTION(hashedErrorVector, error_bytes, (N0 * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B));

memcpy(hashedAndTruncatedErrorVector, hashedErrorVector, TRNG_BYTE_LENGTH);

for (size_t i = 0; i < TRNG_BYTE_LENGTH; ++i) {
maskedSeed[i] = seed[i] ^ hashedAndTruncatedErrorVector[i];
}

PQCLEAN_LEDAKEMLT32_LEAKTIME_niederreiter_encrypt(syndrome,
(const publicKeyNiederreiter_t *) &niederreiter_pk, error_vector);

pack_ct(ct, syndrome);
memcpy(ct + (NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B), maskedSeed, TRNG_BYTE_LENGTH);

return 0;
}


/* IND-CCA2 Decapsulation */
int PQCLEAN_LEDAKEMLT32_LEAKTIME_crypto_kem_dec(uint8_t *ss, const uint8_t *ct, const uint8_t *sk) {
DIGIT syndrome[NUM_DIGITS_GF2X_ELEMENT];
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];
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};
int decode_ok, decrypt_ok, equal;

unpack_ct(syndrome, ct);

decode_ok = PQCLEAN_LEDAKEMLT32_LEAKTIME_niederreiter_decrypt(decoded_error_vector,
(const privateKeyNiederreiter_t *)sk, syndrome);

pack_error(decoded_error_bytes, decoded_error_vector);
HASH_FUNCTION(hashedErrorVector, decoded_error_bytes, N0 * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B);

memcpy(hashedAndTruncatedErrorVector, hashedErrorVector, TRNG_BYTE_LENGTH);

for (size_t 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);

equal = PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_verify(decoded_error_vector,
reconstructed_error_vector, N0 * NUM_DIGITS_GF2X_ELEMENT);
// equal == 0, if the reconstructed error vector match !!!

decrypt_ok = (decode_ok == 1 && equal == 0);

memcpy(ss_input, decoded_seed, TRNG_BYTE_LENGTH);
memcpy(ss_input + sizeof(decoded_seed), tail, TRNG_BYTE_LENGTH);

// Overwrite on failure
PQCLEAN_LEDAKEMLT32_LEAKTIME_cmov(ss_input + sizeof(decoded_seed),
((const privateKeyNiederreiter_t *) sk)->decryption_failure_secret,
TRNG_BYTE_LENGTH,
!decrypt_ok);

HASH_FUNCTION(ss, ss_input, 2 * TRNG_BYTE_LENGTH);

return 0;
}

+ 0
- 192
crypto_kem/ledakemlt32/leaktime/niederreiter.c View File

@@ -1,192 +0,0 @@
#include "H_Q_matrices_generation.h"
#include "bf_decoding.h"
#include "dfr_test.h"
#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;
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] = {0};
DIGIT Ln0Inv[NUM_DIGITS_GF2X_ELEMENT] = {0};
int is_L_full;
int isDFRok = 0;

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(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;
}
}

memset(processedQOnes, 0x00, sizeof(processedQOnes));
for (int colQ = 0; colQ < N0; colQ++) {
for (int i = 0; i < N0; i++) {
PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_mod_mul_sparse(DV * M, auxPosOnes,
DV, HPosOnes[i],
qBlockWeights[i][colQ], QPosOnes[i] + processedQOnes[i]);
PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_mod_add_sparse(DV * M, LPosOnes[colQ],
DV * M, LPosOnes[colQ],
DV * M, auxPosOnes);
processedQOnes[i] += qBlockWeights[i][colQ];
}
}
is_L_full = 1;
for (size_t i = 0; i < N0; i++) {
is_L_full = is_L_full && (LPosOnes[i][DV * M - 1] != INVALID_POS_VALUE);
}
sk->rejections = sk->rejections + 1;
if (is_L_full) {
isDFRok = PQCLEAN_LEDAKEMLT32_LEAKTIME_DFR_test(LPosOnes, &(sk->secondIterThreshold));
}
} while (!is_L_full || !isDFRok);
sk->rejections = sk->rejections - 1;

PQCLEAN_LEDAKEMLT32_LEAKTIME_seedexpander(&keys_expander,
sk->decryption_failure_secret,
(unsigned long)TRNG_BYTE_LENGTH);

for (size_t 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);
}
}

PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_mod_inverse(Ln0Inv, Ln0dense);
for (size_t i = 0; i < N0 - 1; i++) {
PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_mod_mul_dense_to_sparse(pk->Mtr + i * NUM_DIGITS_GF2X_ELEMENT,
Ln0Inv,
LPosOnes[i],
DV * M);
}

for (size_t i = 0; i < N0 - 1; i++) {
PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_transpose_in_place(pk->Mtr + i * NUM_DIGITS_GF2X_ELEMENT);
}
}

void PQCLEAN_LEDAKEMLT32_LEAKTIME_niederreiter_encrypt(DIGIT syndrome[],
const publicKeyNiederreiter_t *pk,
const DIGIT err[]) {

DIGIT saux[NUM_DIGITS_GF2X_ELEMENT];

memset(syndrome, 0x00, NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B);
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 QPosOnes[N0][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];
DIGIT err_computed[N0 * NUM_DIGITS_GF2X_ELEMENT] = {0};
DIGIT err_mockup[N0 * NUM_DIGITS_GF2X_ELEMENT];
DIGIT privateSyndrome[NUM_DIGITS_GF2X_ELEMENT];
uint8_t processedQOnes[N0];
int rejections = sk->rejections;
int decrypt_ok = 0;
int err_weight;

PQCLEAN_LEDAKEMLT32_LEAKTIME_seedexpander_from_trng(&niederreiter_decrypt_expander, sk->prng_seed);
do {
PQCLEAN_LEDAKEMLT32_LEAKTIME_generateHPosOnes(HPosOnes, &niederreiter_decrypt_expander);
PQCLEAN_LEDAKEMLT32_LEAKTIME_generateQPosOnes(QPosOnes, &niederreiter_decrypt_expander);

for (size_t i = 0; i < N0; i++) {
for (size_t j = 0; j < DV * M; j++) {
LPosOnes[i][j] = INVALID_POS_VALUE;
}
}

memset(processedQOnes, 0x00, sizeof(processedQOnes));
for (size_t colQ = 0; colQ < N0; colQ++) {
for (size_t i = 0; i < N0; i++) {
PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_mod_mul_sparse(DV * M, auxPosOnes,
DV, HPosOnes[i],
qBlockWeights[i][colQ], QPosOnes[i] + processedQOnes[i]);
PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_mod_add_sparse(DV * M, LPosOnes[colQ],
DV * M, LPosOnes[colQ],
DV * M, auxPosOnes);
processedQOnes[i] += qBlockWeights[i][colQ];
}
}
rejections--;
} while (rejections >= 0);

PQCLEAN_LEDAKEMLT32_LEAKTIME_transposeHPosOnes(HtrPosOnes, HPosOnes);
PQCLEAN_LEDAKEMLT32_LEAKTIME_transposeQPosOnes(QtrPosOnes, QPosOnes);

for (size_t i = 0; i < DV * M; i++) {
Ln0trSparse[i] = INVALID_POS_VALUE;
auxSparse[i] = INVALID_POS_VALUE;
}

for (size_t 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]]);
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);

decrypt_ok = PQCLEAN_LEDAKEMLT32_LEAKTIME_bf_decoding(err_computed,
(const POSITION_T (*)[DV]) HtrPosOnes,
(const POSITION_T (*)[M]) QtrPosOnes,
privateSyndrome, sk->secondIterThreshold);

err_weight = 0;
for (size_t i = 0 ; i < N0; i++) {
err_weight += PQCLEAN_LEDAKEMLT32_LEAKTIME_population_count(err_computed + (NUM_DIGITS_GF2X_ELEMENT * i));
}
decrypt_ok = decrypt_ok && (err_weight == NUM_ERRORS_T);

/* prepare mockup error vector in case a decoding failure occurs */
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);

memcpy(err, err_computed, N0 * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B);

// Overwrite on decryption failure
PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_cmov(err, err_mockup, N0 * NUM_DIGITS_GF2X_ELEMENT, !decrypt_ok);

return decrypt_ok;
}

+ 0
- 24
crypto_kem/ledakemlt32/leaktime/niederreiter.h View File

@@ -1,24 +0,0 @@
#ifndef NIEDERREITER_H
#define NIEDERREITER_H

#include "gf2x_arith_mod_xPplusOne.h"
#include "qc_ldpc_parameters.h"
#include "rng.h"

typedef struct {
unsigned char prng_seed[TRNG_BYTE_LENGTH];
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];
} publicKeyNiederreiter_t;


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

+ 0
- 27
crypto_kem/ledakemlt32/leaktime/qc_ldpc_parameters.h View File

@@ -1,27 +0,0 @@
#ifndef QC_LDPC_PARAMETERS_H
#define QC_LDPC_PARAMETERS_H

#include "fips202.h"

#define TRNG_BYTE_LENGTH (32)
#define HASH_BYTE_LENGTH (48)
#define HASH_FUNCTION sha3_384

#define N0 (2)
#define P (96221) // modulus(x) = x^P-1
#define DV (11) // odd number
#define M (11)
#define M0 (6)
#define M1 (5)
#define NUM_ERRORS_T (199)

// Derived parameters, they are useful for QC-LDPC algorithms
#define HASH_BIT_LENGTH (HASH_BYTE_LENGTH << 3)
#define K ((N0-1)*P)
#define N (N0*P)
#define DC (N0*DV)

#define Q_BLOCK_WEIGHTS {{M0,M1},{M1,M0}}
static const unsigned char qBlockWeights[N0][N0] = Q_BLOCK_WEIGHTS;

#endif

+ 0
- 110
crypto_kem/ledakemlt32/leaktime/rng.c View File

@@ -1,110 +0,0 @@
#include "rng.h"

#include <string.h> // void *memset(void *s, int c, size_t n);

#include "aes.h"
#include "qc_ldpc_parameters.h"

/*
seedexpander_init()
ctx - stores the current state of an instance of the seed expander
seed - a 32 byte random value
diversifier - an 8 byte diversifier
maxlen - maximum number of bytes (less than 2**32) generated under this seed and diversifier
*/
static void seedexpander_init(AES_XOF_struct *ctx,
uint8_t *seed,
uint8_t *diversifier,
size_t maxlen) {

ctx->length_remaining = maxlen;

memset(ctx->key, 0, 32);
int max_accessible_seed_len = TRNG_BYTE_LENGTH < 32 ? 32 : TRNG_BYTE_LENGTH;
memcpy(ctx->key, seed, max_accessible_seed_len);

memcpy(ctx->ctr, diversifier, 8);
ctx->ctr[11] = maxlen % 256;
maxlen >>= 8;
ctx->ctr[10] = maxlen % 256;
maxlen >>= 8;
ctx->ctr[9] = maxlen % 256;
maxlen >>= 8;
ctx->ctr[8] = maxlen % 256;
memset(ctx->ctr + 12, 0x00, 4);

ctx->buffer_pos = 16;
memset(ctx->buffer, 0x00, 16);
}

void PQCLEAN_LEDAKEMLT32_LEAKTIME_seedexpander_from_trng(AES_XOF_struct *ctx,
const uint8_t *trng_entropy
/* TRNG_BYTE_LENGTH wide buffer */) {

/*the NIST seedexpander will however access 32B from this buffer */
unsigned int prng_buffer_size = TRNG_BYTE_LENGTH < 32 ? 32 : TRNG_BYTE_LENGTH;
uint8_t prng_buffer[TRNG_BYTE_LENGTH < 32 ? 32 : TRNG_BYTE_LENGTH] = {0x00};
uint8_t diversifier[8] = {0};

memcpy(prng_buffer,
trng_entropy,
TRNG_BYTE_LENGTH < prng_buffer_size ? TRNG_BYTE_LENGTH : prng_buffer_size);

/* the required seed expansion will be quite small, set the max number of
* bytes conservatively to 10 MiB*/
seedexpander_init(ctx, prng_buffer, diversifier, RNG_MAXLEN);
}

/*
seedexpander()
ctx - stores the current state of an instance of the seed expander
x - returns the XOF data
xlen - number of bytes to return
*/
int PQCLEAN_LEDAKEMLT32_LEAKTIME_seedexpander(AES_XOF_struct *ctx, uint8_t *x, size_t xlen) {
size_t offset;
aes256ctx ctx256;

if ( x == NULL ) {
return RNG_BAD_OUTBUF;
}
if ( xlen >= ctx->length_remaining ) {
return RNG_BAD_REQ_LEN;
}

aes256_ecb_keyexp(&ctx256, ctx->key);
ctx->length_remaining -= xlen;

offset = 0;
while ( xlen > 0 ) {
if ( xlen <= (16 - ctx->buffer_pos) ) { // buffer has what we need
memcpy(x + offset, ctx->buffer + ctx->buffer_pos, xlen);
ctx->buffer_pos += xlen;

goto end;
}

// take what's in the buffer
memcpy(x + offset, ctx->buffer + ctx->buffer_pos, 16 - ctx->buffer_pos);
xlen -= 16 - ctx->buffer_pos;
offset += 16 - ctx->buffer_pos;

aes256_ecb(ctx->buffer, ctx->ctr, 16 / AES_BLOCKBYTES, &ctx256);
ctx->buffer_pos = 0;

//increment the counter
for (int i = 15; i >= 12; i--) {
if ( ctx->ctr[i] == 0xff ) {
ctx->ctr[i] = 0x00;
} else {
ctx->ctr[i]++;
break;
}
}

}
end:
aes256_ctx_release(&ctx256);

return RNG_SUCCESS;
}

+ 0
- 24
crypto_kem/ledakemlt32/leaktime/rng.h View File

@@ -1,24 +0,0 @@
#ifndef RNG_H
#define RNG_H

#include <stddef.h>
#include <stdint.h>

#define RNG_SUCCESS ( 0)
#define RNG_BAD_MAXLEN (-1)
#define RNG_BAD_OUTBUF (-2)
#define RNG_BAD_REQ_LEN (-3)
#define RNG_MAXLEN (10 * 1024 * 1024)

typedef struct {
unsigned char buffer[16];
size_t buffer_pos;
size_t length_remaining;
unsigned char key[32];
unsigned char ctr[16];
} AES_XOF_struct;

int PQCLEAN_LEDAKEMLT32_LEAKTIME_seedexpander(AES_XOF_struct *ctx, unsigned char *x, size_t xlen);
void PQCLEAN_LEDAKEMLT32_LEAKTIME_seedexpander_from_trng(AES_XOF_struct *ctx, const unsigned char *trng_entropy);

#endif

+ 0
- 98
crypto_kem/ledakemlt32/leaktime/sort.c View File

@@ -1,98 +0,0 @@
#include "sort.h"

/*
Constant-time uint32_t sorting by Daniel J. Bernstein
Source: https://sorting.cr.yp.to
*/

#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)

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;
}
}

+ 0
- 11
crypto_kem/ledakemlt32/leaktime/sort.h View File

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

#include <stddef.h>
#include <stdint.h>

#define int32 int32_t

void PQCLEAN_LEDAKEMLT32_LEAKTIME_uint32_sort(uint32_t *x, size_t n);

#endif

+ 0
- 21
crypto_kem/ledakemlt32/leaktime/utils.c View File

@@ -1,21 +0,0 @@
#include "gf2x_arith.h"
#include "utils.h"

/* compares DIGIT sequences, returns 0 if they are equal */
int PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_verify(const DIGIT *a, const DIGIT *b, size_t len) {
DIGIT x = 0;
for (size_t i = 0; i < len; i++) {
x |= a[i] ^ b[i];
}
x = (~x) + 1;
x >>= (DIGIT_SIZE_b - 1);
return (int)x;
}

/* conditionally move a into r if cond */
void PQCLEAN_LEDAKEMLT32_LEAKTIME_cmov(uint8_t *r, const uint8_t *a, size_t len, int cond) {
uint8_t mask = (uint8_t)(-cond);
for (size_t i = 0; i < len; i++) {
r[i] ^= mask & (r[i] ^ a[i]);
}
}

+ 0
- 9
crypto_kem/ledakemlt32/leaktime/utils.h View File

@@ -1,9 +0,0 @@
#ifndef UTILS_H
#define UTILS_H

#include <stdint.h>

int PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_verify(const DIGIT *a, const DIGIT *b, size_t len);
void PQCLEAN_LEDAKEMLT32_LEAKTIME_cmov(uint8_t *r, const uint8_t *a, size_t len, int cond);

#endif

+ 0
- 19
crypto_kem/ledakemlt52/META.yml View File

@@ -1,19 +0,0 @@
name: LEDAKEMLT52
type: kem
claimed-nist-level: 5
claimed-security: IND-CCA2
length-public-key: 19040
length-secret-key: 82
length-ciphertext: 19080
length-shared-secret: 64
nistkat-sha256: 7a8d7c623bd3a8935861ec088e77a6701a254ac521d5e5150dc4537df4da8fd5
principal-submitters:
- Marco Baldi
auxiliary-submitters:
- Alessandro Barenghi
- Franco Chiaraluce
- Gerardo Pelosi
- Paolo Santini
implementations:
- name: leaktime
version: 2.1

+ 0
- 52
crypto_kem/ledakemlt52/leaktime/H_Q_matrices_generation.c View File

@@ -1,52 +0,0 @@
#include "H_Q_matrices_generation.h"
#include "gf2x_arith_mod_xPplusOne.h"

void PQCLEAN_LEDAKEMLT52_LEAKTIME_generateHPosOnes(POSITION_T HPosOnes[N0][DV], AES_XOF_struct *keys_expander) {
for (size_t i = 0; i < N0; i++) {
/* Generate a random block of Htr */
PQCLEAN_LEDAKEMLT52_LEAKTIME_rand_circulant_sparse_block(&HPosOnes[i][0], DV, keys_expander);
}
}

void PQCLEAN_LEDAKEMLT52_LEAKTIME_generateQPosOnes(POSITION_T QPosOnes[N0][M], AES_XOF_struct *keys_expander) {
size_t placed_ones;

for (size_t i = 0; i < N0; i++) {
placed_ones = 0;
for (size_t j = 0; j < N0; j++) {
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], POSITION_T HPosOnes[N0][DV]) {
for (size_t i = 0; i < N0; i++) {
/* Obtain directly the sparse representation of the block of H */
for (size_t k = 0; k < DV; k++) {
HtrPosOnes[i][k] = (P - HPosOnes[i][k]) % P; /* transposes indexes */
}
}
}

void PQCLEAN_LEDAKEMLT52_LEAKTIME_transposeQPosOnes(POSITION_T QtrPosOnes[N0][M], POSITION_T QPosOnes[N0][M]) {
POSITION_T transposed_ones_idx[N0] = {0x00};
size_t currQoneIdx, endQblockIdx;

for (size_t 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]++;
}
}
}
}



+ 0
- 13
crypto_kem/ledakemlt52/leaktime/H_Q_matrices_generation.h View File

@@ -1,13 +0,0 @@
#ifndef H_Q_MATRICES_GENERATION_H
#define H_Q_MATRICES_GENERATION_H

#include "gf2x_arith.h"
#include "qc_ldpc_parameters.h"
#include "rng.h"

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

+ 0
- 31
crypto_kem/ledakemlt52/leaktime/LICENSE View File

@@ -1,31 +0,0 @@
/**
*
* LEDAcryptKEM
*
* @version 2.0 (March 2019)
*
* Adapted code from reference ISO-C11 Implementation of the LEDAcrypt KEM-LT cipher.
*
* In alphabetical order:
*
* @author Marco Baldi <m.baldi@univpm.it>
* @author Alessandro Barenghi <alessandro.barenghi@polimi.it>
* @author Franco Chiaraluce <f.chiaraluce@univpm.it>
* @author Gerardo Pelosi <gerardo.pelosi@polimi.it>
* @author Paolo Santini <p.santini@pm.univpm.it>
*
* This code is hereby placed in the public domain.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
**/

+ 0
- 24
crypto_kem/ledakemlt52/leaktime/Makefile View File

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

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 sort.h utils.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 sort.o utils.o

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

all: $(LIB)

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

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

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

+ 0
- 19
crypto_kem/ledakemlt52/leaktime/Makefile.Microsoft_nmake View File

@@ -1,19 +0,0 @@
# This Makefile can be used with Microsoft Visual Studio's nmake using the command:
# 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 sort.obj utils.obj

CFLAGS=/nologo /O2 /I ..\..\..\common /W4 /WX

all: $(LIBRARY)

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

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

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

+ 0
- 18
crypto_kem/ledakemlt52/leaktime/api.h View File

@@ -1,18 +0,0 @@
#ifndef PQCLEAN_LEDAKEMLT52_LEAKTIME_API_H
#define PQCLEAN_LEDAKEMLT52_LEAKTIME_API_H

#include <stdint.h>

#define PQCLEAN_LEDAKEMLT52_LEAKTIME_CRYPTO_SECRETKEYBYTES 82
#define PQCLEAN_LEDAKEMLT52_LEAKTIME_CRYPTO_PUBLICKEYBYTES 19040
#define PQCLEAN_LEDAKEMLT52_LEAKTIME_CRYPTO_CIPHERTEXTBYTES 19080
#define PQCLEAN_LEDAKEMLT52_LEAKTIME_CRYPTO_BYTES 64

#define PQCLEAN_LEDAKEMLT52_LEAKTIME_CRYPTO_ALGNAME "LEDAKEMLT52"

int PQCLEAN_LEDAKEMLT52_LEAKTIME_crypto_kem_keypair(uint8_t *pk, uint8_t *sk);
int PQCLEAN_LEDAKEMLT52_LEAKTIME_crypto_kem_enc(uint8_t *ct, uint8_t *ss, const uint8_t *pk);
int PQCLEAN_LEDAKEMLT52_LEAKTIME_crypto_kem_dec(uint8_t *ss, const uint8_t *ct, const uint8_t *sk);


#endif

+ 0
- 79
crypto_kem/ledakemlt52/leaktime/bf_decoding.c View File

@@ -1,79 +0,0 @@
#include "bf_decoding.h"
#include "gf2x_arith_mod_xPplusOne.h"

#include <string.h>

int PQCLEAN_LEDAKEMLT52_LEAKTIME_bf_decoding(DIGIT err[],
const POSITION_T HtrPosOnes[N0][DV],
const POSITION_T QtrPosOnes[N0][M],
DIGIT privateSyndrome[],
uint8_t secondIterThreshold) {

DIGIT currSyndrome[NUM_DIGITS_GF2X_ELEMENT];
uint8_t unsatParityChecks[N0 * P];
POSITION_T currQBlkPos[M], currQBitPos[M];
POSITION_T syndromePosToFlip, tmp;
uint32_t correlation, corrt_syndrome_based;
size_t currQoneIdx, endQblockIdx, currblockoffset;
int check;
int iteration = 0;

do {
PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_copy(currSyndrome, privateSyndrome);
memset(unsatParityChecks, 0x00, N0 * P * sizeof(uint8_t));
for (size_t i = 0; i < N0; i++) {
for (POSITION_T valueIdx = 0; valueIdx < P; valueIdx++) {
for (size_t HtrOneIdx = 0; HtrOneIdx < DV; HtrOneIdx++) {
tmp = (HtrPosOnes[i][HtrOneIdx] + valueIdx) >= P ?
(HtrPosOnes[i][HtrOneIdx] + valueIdx) - P :
(HtrPosOnes[i][HtrOneIdx] + valueIdx);
if (PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_get_coeff(currSyndrome, tmp)) {
unsatParityChecks[i * P + valueIdx]++;
}
}
}
}

/* iteration based threshold determination*/
corrt_syndrome_based = iteration * secondIterThreshold + (1 - iteration) * B0;

// Computation of correlation with a full Q matrix
for (size_t i = 0; i < N0; i++) {
for (POSITION_T j = 0; j < P; j++) {
currQoneIdx = endQblockIdx = 0;
correlation = 0;

for (size_t blockIdx = 0; blockIdx < N0; blockIdx++) {
endQblockIdx += qBlockWeights[blockIdx][i];
currblockoffset = blockIdx * P;
for (; currQoneIdx < endQblockIdx; currQoneIdx++) {
tmp = QtrPosOnes[i][currQoneIdx] + j;
tmp = tmp >= P ? tmp - P : tmp;
currQBitPos[currQoneIdx] = tmp;
currQBlkPos[currQoneIdx] = (POSITION_T)blockIdx;
correlation += unsatParityChecks[tmp + currblockoffset];
}
}

/* Correlation based flipping */
if (correlation >= corrt_syndrome_based) {
PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_toggle_coeff(err + NUM_DIGITS_GF2X_ELEMENT * i, j);
for (size_t v = 0; v < M; v++) {
for (size_t HtrOneIdx = 0; HtrOneIdx < DV; HtrOneIdx++) {
syndromePosToFlip = (HtrPosOnes[currQBlkPos[v]][HtrOneIdx] + currQBitPos[v]);
syndromePosToFlip = syndromePosToFlip >= P ? syndromePosToFlip - P : syndromePosToFlip;
PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_toggle_coeff(privateSyndrome, syndromePosToFlip);
}
} // end for v
} // end if
} // end for j
} // end for i

iteration = iteration + 1;
check = 0;
while (check < NUM_DIGITS_GF2X_ELEMENT && privateSyndrome[check++] == 0) {};

} while (iteration < ITERATIONS_MAX && check < NUM_DIGITS_GF2X_ELEMENT);

return (check == NUM_DIGITS_GF2X_ELEMENT);
}

+ 0
- 18
crypto_kem/ledakemlt52/leaktime/bf_decoding.h View File

@@ -1,18 +0,0 @@
#ifndef BF_DECODING_H
#define BF_DECODING_H

#include "gf2x_arith.h"
#include "qc_ldpc_parameters.h"

/* Definitions for DFR level 2^-SL with SL=128 */
#define ITERATIONS_MAX (2)
#define B0 (88)
#define T_BAR (6)

int PQCLEAN_LEDAKEMLT52_LEAKTIME_bf_decoding(DIGIT err[],
const POSITION_T HtrPosOnes[N0][DV],
const POSITION_T QtrPosOnes[N0][M],
DIGIT privateSyndrome[],
uint8_t threshold);

#endif

+ 0
- 88
crypto_kem/ledakemlt52/leaktime/dfr_test.c View File

@@ -1,88 +0,0 @@
#include "bf_decoding.h"
#include "dfr_test.h"
#include "gf2x_arith_mod_xPplusOne.h"
#include "qc_ldpc_parameters.h"
#include "sort.h"

#include <string.h>


int PQCLEAN_LEDAKEMLT52_LEAKTIME_DFR_test(POSITION_T LSparse[N0][DV * M], uint8_t *secondIterThreshold) {

POSITION_T LSparse_loc[N0][DV * M]; /* vector of N_0 sparse blocks */
uint8_t gamma[N0][N0][P] = {{{0}}};
uint32_t gammaHist[N0][DV * M + 1] = {{0}};
size_t maxMut[N0], maxMutMinusOne[N0];
size_t allBlockMaxSumst, allBlockMaxSumstMinusOne;
size_t histIdx, toAdd;

for (size_t i = 0; i < N0; i++) {
for (size_t j = 0; j < DV * M; j++) {
if (LSparse[i][j] != 0) {
LSparse_loc[i][j] = (P - LSparse[i][j]);
}
}
PQCLEAN_LEDAKEMLT52_LEAKTIME_uint32_sort(LSparse_loc[i], DV * M);
}


for (size_t i = 0; i < N0; i++ ) {
for (size_t j = 0; j < N0; j++) {
for (size_t k = 0; k < (DV * M); k++) {
for (size_t l = 0; l < (DV * M); l++) {
gamma[i][j][(P + LSparse_loc[i][k] - LSparse_loc[j][l]) % P]++;
}
}
}
}

for (size_t i = 0; i < N0; i++ ) {
for (size_t j = 0; j < N0; j++ ) {
gamma[i][j][0] = 0;
}
}

/* build histogram of values in gamma */
for (size_t i = 0; i < N0; i++ ) {
for (size_t j = 0; j < N0; j++ ) {
for (size_t k = 0; k < P; k++) {
gammaHist[i][gamma[i][j][k]]++;
}
}
}


for (size_t gammaBlockRowIdx = 0; gammaBlockRowIdx < N0; gammaBlockRowIdx++) {
maxMutMinusOne[gammaBlockRowIdx] = 0;
histIdx = DV * M;
toAdd = T_BAR - 1;
while ( (histIdx > 0) && (toAdd > 0)) {
if (gammaHist[gammaBlockRowIdx][histIdx] > toAdd ) {
maxMutMinusOne[gammaBlockRowIdx] += histIdx * toAdd;
toAdd = 0;
} else {
maxMutMinusOne[gammaBlockRowIdx] += histIdx * gammaHist[gammaBlockRowIdx][histIdx];
toAdd -= gammaHist[gammaBlockRowIdx][histIdx];
histIdx--;
}
}
maxMut[gammaBlockRowIdx] = histIdx + maxMutMinusOne[gammaBlockRowIdx];
}

/*seek max values across all gamma blocks */
allBlockMaxSumst = maxMut[0];
allBlockMaxSumstMinusOne = maxMutMinusOne[0];
for (size_t gammaBlockRowIdx = 0; gammaBlockRowIdx < N0; gammaBlockRowIdx++) {
allBlockMaxSumst = allBlockMaxSumst < maxMut[gammaBlockRowIdx] ?
maxMut[gammaBlockRowIdx] :
allBlockMaxSumst;
allBlockMaxSumstMinusOne = allBlockMaxSumstMinusOne < maxMutMinusOne[gammaBlockRowIdx] ?
maxMutMinusOne[gammaBlockRowIdx] :
allBlockMaxSumstMinusOne;
}
if (DV * M > (allBlockMaxSumstMinusOne + allBlockMaxSumst)) {
*secondIterThreshold = (uint8_t) (allBlockMaxSumst + 1);
return 1;
}
return 0;
}

+ 0
- 6
crypto_kem/ledakemlt52/leaktime/dfr_test.h View File

@@ -1,6 +0,0 @@
#ifndef DFR_TEST_H
#define DFR_TEST_H

int PQCLEAN_LEDAKEMLT52_LEAKTIME_DFR_test(POSITION_T LSparse[N0][DV * M], uint8_t *secondIterThreshold);

#endif

+ 0
- 252
crypto_kem/ledakemlt52/leaktime/gf2x_arith.c View File

@@ -1,252 +0,0 @@
#include "gf2x_arith.h"

#include <string.h> // memset(...)

void PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_add(DIGIT Res[], const DIGIT A[], const DIGIT B[], size_t n) {
for (size_t i = 0; i < n; i++) {
Res[i] = A[i] ^ B[i];
}
}

/* copies len digits from a to r if b == 1 */
void PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_cmov(DIGIT *r, const DIGIT *a, size_t len, int c) {
DIGIT mask = (DIGIT)(-c);
for (size_t i = 0; i < len; i++) {
r[i] ^= mask & (a[i] ^ r[i]);
}
}

/* PRE: MAX ALLOWED ROTATION AMOUNT : DIGIT_SIZE_b */
void PQCLEAN_LEDAKEMLT52_LEAKTIME_right_bit_shift_n(size_t length, DIGIT in[], size_t amount) {
if ( amount == 0 ) {
return;
}
size_t j;
DIGIT mask;
mask = ((DIGIT)0x01 << amount) - 1;
for (j = length - 1; j > 0; j--) {
in[j] >>= amount;
in[j] |= (in[j - 1] & mask) << (DIGIT_SIZE_b - amount);
}
in[j] >>= amount;
}

/* PRE: MAX ALLOWED ROTATION AMOUNT : DIGIT_SIZE_b */
void PQCLEAN_LEDAKEMLT52_LEAKTIME_left_bit_shift_n(size_t length, DIGIT in[], size_t amount) {
if ( amount == 0 ) {
return;
}
size_t j;
DIGIT mask;
mask = ~(((DIGIT)0x01 << (DIGIT_SIZE_b - amount)) - 1);
for (j = 0 ; j < length - 1; j++) {
in[j] <<= amount;
in[j] |= (in[j + 1] & mask) >> (DIGIT_SIZE_b - amount);
}
in[j] <<= amount;
}


static void gf2x_mul1(DIGIT *R, const DIGIT A, const DIGIT B) {
DIGIT tmp;

R[0] = 0;
R[1] = (A & 1) * B;
for (uint8_t i = 1; i < DIGIT_SIZE_b; i++) {
tmp = ((A >> i) & 1) * B;
R[1] ^= tmp << i;
R[0] ^= tmp >> (DIGIT_SIZE_b - i);
}
}

static void gf2x_mul_n(DIGIT *R, const DIGIT *A, const DIGIT *B, size_t n) {
DIGIT tmp[2];

memset(R, 0x00, 2 * n * sizeof(DIGIT));
for (size_t i = 0; i < n; i++) {
for (size_t j = 0; j < n; j++) {
gf2x_mul1(tmp, A[i], B[j]);
R[i + j] ^= tmp[0];
R[i + j + 1] ^= tmp[1];
}
}
}

static void gf2x_cpy(DIGIT *R, const DIGIT *A, size_t len) {
for (size_t i = 0; i < len; i++) {
R[i] = A[i];
}
}

/* Accumulate */
#define gf2x_add(R, A, B, n) PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_add(R, A, B, n)
#define gf2x_acc(R, B, n) PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_add(R, R, B, n)

/* allows the operands to be of different size
* first operand must be the bigger one.
* aligns last array elements */
static inline void gf2x_add_asymm(DIGIT *R,
size_t na, const DIGIT *A,
size_t nb, const DIGIT *B) {
size_t delta = na - nb;
gf2x_cpy(R, A, delta);
gf2x_add(R + delta, A + delta, B, nb);;
}

/* aligns first array elements */
static inline void gf2x_add_asymm2(DIGIT *R,
size_t na, const DIGIT *A,
size_t nb, const DIGIT *B) {
size_t delta = na - nb;
gf2x_add(R, A, B, nb);
gf2x_cpy(R + nb, A + nb, delta);
}

/* Karatsuba with lowered space complexity
* T(n) = 3 * ceil(n/2) + T(ceil(n / 2)) */
static void gf2x_mul_kar(DIGIT *R,
const DIGIT *A,
const DIGIT *B,
size_t n,
DIGIT *stack) {

if (n < MIN_KAR_DIGITS) {
gf2x_mul_n(R, A, B, n);
return;
}

size_t l = (n + 1) / 2; // limb size = ceil(n / 2)
size_t d = n & 1;

const DIGIT *a1 = A; // length n - d
const DIGIT *a0 = A + l - d; // length n
const DIGIT *b1 = B;
const DIGIT *b0 = B + l - d;

DIGIT *aa = stack;
DIGIT *bb = aa + l;
DIGIT *cc = bb + l;
stack = cc + l; // 3l space requirement at each level

DIGIT *c3 = R + l - 2 * d;
DIGIT *c2 = c3 + l;
DIGIT *c1 = c2 + l;

gf2x_mul_kar(c2, a0, b0, l, stack); // L in low part of R
gf2x_mul_kar(R, a1, b1, l - d, stack); // H in higher part of R
gf2x_add_asymm(aa, l, a0, l - d, a1); // AH + AL
gf2x_add_asymm(bb, l, b0, l - d, b1); // BH + BL
gf2x_add(cc, c3, c2, l); // HL + LH in cc
gf2x_mul_kar(c3, aa, bb, l, stack); // M = (AH + AL) x (BH + BL)
gf2x_add_asymm(c3, l, c3, l - 2 * d, R); // add HH
gf2x_acc(c2, c1, l); // add LL
gf2x_acc(c3, cc, l); // add HL + LH
gf2x_acc(c2, cc, l); // add HL + LH
}

static void gf2x_div_w_plus_one(DIGIT *A, size_t n) {
size_t i;
for (i = 0; i < n - 2; i++) {
A[i + 1] ^= A[i]; // runs n - 2 times
}
}

static void gf2x_shift_left_w(DIGIT *A, size_t n) {
size_t i;
for (i = 0; i < n - 1; i++) {
A[i] = A[i + 1];
}
A[i] = 0;
}

/* Word-aligned Toom-Cook 3, source:
* Brent, Richard P., et al. "Faster multiplication in GF (2)[x]."
* International Algorithmic Number Theory Symposium.
* Springer, Berlin, Heidelberg, 2008. */
static void gf2x_mul_tc3w(DIGIT *R,
const DIGIT *A,
const DIGIT *B,
size_t n,
DIGIT *stack) {

if (n < MIN_TOOM_DIGITS) {
gf2x_mul_kar(R, A, B, n, stack);
return;
}

size_t l = (n + 2) / 3; // size of a0, a1, b0, b1
size_t r = n - 2 * l; // remaining sizes (a2, b2)
size_t x = 2 * l + 4; // size of c1, c2, c3, c4
size_t z = r + 2 > l + 1 ? r + 2 : l + 1; // size of c5

const DIGIT *a0 = A;
const DIGIT *a1 = A + l;
const DIGIT *a2 = A + 2 * l;
const DIGIT *b0 = B;
const DIGIT *b1 = B + l;
const DIGIT *b2 = B + 2 * l;

DIGIT *c0 = R; // c0 and c4 in the result
DIGIT *c4 = R + 4 * l;
DIGIT *c1 = stack; // the rest in the stack
DIGIT *c2 = c1 + x;
DIGIT *c3 = c2 + x;
DIGIT *c5 = c3 + x;
stack = c5 + z; // Worst-case 7l + 14

// Evaluation
c0[0] = 0; // c0[z] = a1*W + a2*W^2
c0[l + 1] = 0;
gf2x_cpy(c0 + 1, a1, l);
gf2x_acc(c0 + 2, a2, r);

c4[0] = 0; // c4[z] = b1*W + b2*W^2
c4[l + 1] = 0;
gf2x_cpy(c4 + 1, b1, l);
gf2x_acc(c4 + 2, b2, r);

gf2x_cpy(c5, a0, l); // c5[l] = a0 + a1 + a2
gf2x_acc(c5, a1, l);
gf2x_acc(c5, a2, r);

gf2x_cpy(c2, b0, l); // c2[l] = b0 + b1 + b2
gf2x_acc(c2, b1, l);
gf2x_acc(c2, b2, r);

gf2x_mul_tc3w(c1, c2, c5, l, stack); // c1[2l] = c2 * c5
gf2x_add_asymm2(c5, z, c0, l, c5); // c5[z] += c0, z >= l
gf2x_add_asymm2(c2, z, c4, l, c2); // c2[z] += c4, idem
gf2x_acc(c0, a0, l); // c0[l] += a0
gf2x_acc(c4, b0, l); // c4[l] += b0
gf2x_mul_tc3w(c3, c2, c5, z, stack); // c3[2z] = c2 * c5
gf2x_mul_tc3w(c2, c0, c4, z, stack); // c2[2z] = c0 * c4
gf2x_mul_tc3w(c0, a0, b0, l, stack); // c0[2l] = a0 * b0
gf2x_mul_tc3w(c4, a2, b2, r, stack); // c4[2r] = a2 * b2

// Interpolation
gf2x_acc(c3, c2, 2 * z); // c3[2z] += c2
gf2x_acc(c2, c0, 2 * l); // c2[2z] += c0
gf2x_shift_left_w(c2, 2 * z); // c2[2z] = c2/y + c3
gf2x_acc(c2, c3, 2 * z);
gf2x_acc(c2, c4, 2 * r); // c2[2z] += c4 + c4**3
gf2x_acc(c2 + 3, c4, 2 * r);
gf2x_div_w_plus_one(c2, 2 * z); // c2[2z-1] = c2/(W+1)
gf2x_acc(c1, c0, 2 * l); // c1[2l] += c0
gf2x_acc(c3, c1, 2 * l); // c3[2z] += c1
gf2x_shift_left_w(c3, 2 * z); // c3[2z-2] = c3/(W^2 + W)
gf2x_div_w_plus_one(c3, 2 * z - 1);
gf2x_add_asymm2(c1, 2 * z, c2, 2 * l, c1); // c1[2z-1] += c2 + c4
gf2x_acc(c1, c4, 2 * r); // size c2 >= c1 >= c4
gf2x_acc(c2, c3, 2 * z - 1); // c2[2z-1] += c3

// Recombination
gf2x_cpy(R + 2 * l, c2, 2 * l);
gf2x_acc(R + l, c1, 2 * z - 1);
gf2x_acc(R + 3 * l, c3, 2 * z - 1);
}

void PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_mul(DIGIT *R, const DIGIT *A, const DIGIT *B, size_t n) {
DIGIT stack[STACK_WORDS];
gf2x_mul_tc3w(R, A, B, n, stack);
}


+ 0
- 68
crypto_kem/ledakemlt52/leaktime/gf2x_arith.h View File

@@ -1,68 +0,0 @@
#ifndef GF2X_ARITH_H
#define GF2X_ARITH_H

#include <inttypes.h>
#include <stddef.h>

/*
* Elements of GF(2)[x] are stored in compact dense binary form.
*
* Each bit in a byte is assumed to be the coefficient of a binary
* polynomial f(x), in Big-Endian format (i.e., reading everything from
* left to right, the most significant element is met first):
*
* byte:(0000 0000) == 0x00 ... f(x) == 0
* byte:(0000 0001) == 0x01 ... f(x) == 1
* byte:(0000 0010) == 0x02 ... f(x) == x
* byte:(0000 0011) == 0x03 ... f(x) == x+1
* ... ... ...
* byte:(0000 1111) == 0x0F ... f(x) == x^{3}+x^{2}+x+1
* ... ... ...
* byte:(1111 1111) == 0xFF ... f(x) == x^{7}+x^{6}+x^{5}+x^{4}+x^{3}+x^{2}+x+1
*
*
* A "machine word" (A_i) is considered as a DIGIT.
* Bytes in a DIGIT are assumed in Big-Endian format:
* E.g., if sizeof(DIGIT) == 4:
* A_i: A_{i,3} A_{i,2} A_{i,1} A_{i,0}.
* A_{i,3} denotes the most significant byte, A_{i,0} the least significant one.
* f(x) == x^{31} + ... + x^{24} +
* + x^{23} + ... + x^{16} +
* + x^{15} + ... + x^{8} +
* + x^{7} + ... + x^{0}
*
*
* Multi-precision elements (i.e., with multiple DIGITs) are stored in
* Big-endian format:
* A = A_{n-1} A_{n-2} ... A_1 A_0
*
* position[A_{n-1}] == 0
* position[A_{n-2}] == 1
* ...
* position[A_{1}] == n-2
* position[A_{0}] == n-1
*/

typedef uint64_t DIGIT;
#define DIGIT_SIZE_B (8)
#define DIGIT_SIZE_b (DIGIT_SIZE_B << 3)
#define POSITION_T uint32_t

#define MIN_KAR_DIGITS 10
#define MIN_TOOM_DIGITS 42

#define STACK_KAR_ONLY 7137
#define STACK_WORDS 8401

void PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_add(DIGIT Res[], const DIGIT A[], const DIGIT B[], size_t n);
void PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_cmov(DIGIT *r, const DIGIT *a, size_t len, int c);
void PQCLEAN_LEDAKEMLT52_LEAKTIME_right_bit_shift_n(size_t length, DIGIT in[], size_t amount);
void PQCLEAN_LEDAKEMLT52_LEAKTIME_left_bit_shift_n(size_t length, DIGIT in[], size_t amount);
void PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_mul(DIGIT *R, const DIGIT *A, const DIGIT *B, size_t n);






#endif

+ 0
- 529
crypto_kem/ledakemlt52/leaktime/gf2x_arith_mod_xPplusOne.c View File

@@ -1,529 +0,0 @@
#include "gf2x_arith_mod_xPplusOne.h"
#include "rng.h"
#include "sort.h"

#include <string.h> // memcpy(...), memset(...)

void PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_copy(DIGIT dest[], const DIGIT in[]) {
for (size_t i = 0; i < NUM_DIGITS_GF2X_ELEMENT; i++) {
dest[i] = in[i];
}
}

/* returns the coefficient of the x^exponent term as the LSB of a digit */
DIGIT PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_get_coeff(const DIGIT poly[], size_t exponent) {
size_t straightIdx = (NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_b - 1) - exponent;
size_t digitIdx = straightIdx / DIGIT_SIZE_b;
size_t inDigitIdx = straightIdx % DIGIT_SIZE_b;
return (poly[digitIdx] >> (DIGIT_SIZE_b - 1 - inDigitIdx)) & ((DIGIT) 1) ;
}

/* sets the coefficient of the x^exponent term as the LSB of a digit */
void PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_set_coeff(DIGIT poly[], size_t exponent, DIGIT value) {
size_t straightIdx = (NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_b - 1) - exponent;
size_t digitIdx = straightIdx / DIGIT_SIZE_b;
size_t inDigitIdx = straightIdx % DIGIT_SIZE_b;

/* clear given coefficient */
DIGIT mask = ~(((DIGIT) 1) << (DIGIT_SIZE_b - 1 - inDigitIdx));
poly[digitIdx] = poly[digitIdx] & mask;
poly[digitIdx] = poly[digitIdx] | ((value & ((DIGIT) 1)) << (DIGIT_SIZE_b - 1 - inDigitIdx));
}

/* toggles (flips) the coefficient of the x^exponent term as the LSB of a digit */
void PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_toggle_coeff(DIGIT poly[], size_t exponent) {
size_t straightIdx = (NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_b - 1) - exponent;
size_t digitIdx = straightIdx / DIGIT_SIZE_b;
size_t inDigitIdx = straightIdx % DIGIT_SIZE_b;

/* clear given coefficient */
DIGIT mask = (((DIGIT) 1) << (DIGIT_SIZE_b - 1 - inDigitIdx));
poly[digitIdx] = poly[digitIdx] ^ mask;
}

/* population count for an unsigned 64-bit integer
Source: Hacker's delight, p.66 */
static int popcount_uint64t(uint64_t x) {
x -= (x >> 1) & 0x5555555555555555;
x = (x & 0x3333333333333333) + ((x >> 2) & 0x3333333333333333);
x = (x + (x >> 4)) & 0x0f0f0f0f0f0f0f0f;
return (int)((x * 0x0101010101010101) >> 56);
}

/* population count for a single polynomial */
int PQCLEAN_LEDAKEMLT52_LEAKTIME_population_count(const DIGIT *poly) {
int ret = 0;
for (int i = NUM_DIGITS_GF2X_ELEMENT - 1; i >= 0; i--) {
ret += popcount_uint64t(poly[i]);
}
return ret;
}

void PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_mod_add(DIGIT Res[], const DIGIT A[], const DIGIT B[]) {
PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_add(Res, A, B, NUM_DIGITS_GF2X_ELEMENT);
}

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 right_bit_shift(size_t length, DIGIT in[]) {
size_t j;
for (j = length - 1; j > 0; j--) {
in[j] >>= 1;
in[j] |= (in[j - 1] & (DIGIT)0x01) << (DIGIT_SIZE_b - 1);
}
in[j] >>= 1;
}


/* shifts by whole digits */
static void left_DIGIT_shift_n(size_t length, DIGIT in[], size_t amount) {
size_t j;
for (j = 0; (j + amount) < length; j++) {
in[j] = in[j + amount];
}
for (; j < length; j++) {
in[j] = (DIGIT)0;
}
}

/* may shift by an arbitrary amount*/
static void left_bit_shift_wide_n(size_t length, DIGIT in[], size_t amount) {
left_DIGIT_shift_n(length, in, amount / DIGIT_SIZE_b);
PQCLEAN_LEDAKEMLT52_LEAKTIME_left_bit_shift_n(length, in, amount % DIGIT_SIZE_b);
}

/* Hackers delight, reverses a uint64_t */
static DIGIT reverse_digit(DIGIT x) {
uint64_t t;
x = (x << 31) | (x >> 33);
t = (x ^ (x >> 20)) & 0x00000FFF800007FFLL;
x = (t | (t << 20)) ^ x;
t = (x ^ (x >> 8)) & 0x00F8000F80700807LL;
x = (t | (t << 8)) ^ x;
t = (x ^ (x >> 4)) & 0x0808708080807008LL;
x = (t | (t << 4)) ^ x;
t = (x ^ (x >> 2)) & 0x1111111111111111LL;
x = (t | (t << 2)) ^ x;
return x;
}

void PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_transpose_in_place(DIGIT A[]) {
/* it keeps the lsb in the same position and
* inverts the sequence of the remaining bits */

DIGIT mask = (DIGIT)0x1;
DIGIT rev1, rev2, a00;
int slack_bits_amount = NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_b - P;

a00 = A[NUM_DIGITS_GF2X_ELEMENT - 1] & mask;
right_bit_shift(NUM_DIGITS_GF2X_ELEMENT, A);

for (size_t i = NUM_DIGITS_GF2X_ELEMENT - 1; i >= (NUM_DIGITS_GF2X_ELEMENT + 1) / 2; i--) {
rev1 = reverse_digit(A[i]);
rev2 = reverse_digit(A[NUM_DIGITS_GF2X_ELEMENT - 1 - i]);
A[i] = rev2;
A[NUM_DIGITS_GF2X_ELEMENT - 1 - i] = rev1;
}

if (slack_bits_amount) {
PQCLEAN_LEDAKEMLT52_LEAKTIME_right_bit_shift_n(NUM_DIGITS_GF2X_ELEMENT, A, slack_bits_amount);
}
A[NUM_DIGITS_GF2X_ELEMENT - 1] = (A[NUM_DIGITS_GF2X_ELEMENT - 1] & (~mask)) | a00;
}

static void rotate_bit_right(DIGIT in[]) { /* x^{-1} * in(x) mod x^P+1 */

DIGIT rotated_bit = in[NUM_DIGITS_GF2X_ELEMENT - 1] & ((DIGIT)0x1);
right_bit_shift(NUM_DIGITS_GF2X_ELEMENT, in);
int msb_offset_in_digit = MSb_POSITION_IN_MSB_DIGIT_OF_MODULUS - 1;
rotated_bit = rotated_bit << msb_offset_in_digit;
in[0] |= rotated_bit;
}

/* cond swap: swaps digits A and B if swap_mask == -1 */
static void gf2x_cswap(DIGIT *a, DIGIT *b, int32_t swap_mask) {
DIGIT t;
for (size_t i = 0; i < NUM_DIGITS_GF2X_ELEMENT; i++) {
t = swap_mask & (a[i] ^ b[i]);
a[i] ^= t;
b[i] ^= t;
}
}

/* returns -1 mask if x != 0, otherwise 0 */
static inline int32_t nonzero(DIGIT x) {
DIGIT t = x;
t = (~t) + 1;
t >>= DIGIT_SIZE_b - 1;
return -((int32_t)t);
}

/* returns -1 mask if x < 0 else 0 */
static inline int32_t negative(int x) {
uint32_t u = x;
u >>= 31;
return -((int32_t)u);
}

/* return f(0) as digit */
static inline DIGIT lsb(const DIGIT *p) {
DIGIT mask = (DIGIT)1;
return p[NUM_DIGITS_GF2X_ELEMENT - 1] & mask;
}

/* multiply poly with scalar and accumulate, expects s all-zero of all-one mask */
static void gf2x_mult_scalar_acc(DIGIT *f, const DIGIT *g, const DIGIT s) {
for (size_t i = 0; i < NUM_DIGITS_GF2X_ELEMENT; i++) {
f[i] = f[i] ^ (s & g[i]);
}
}

/* constant-time inverse, source: gcd.cr.yp.to */
int PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_mod_inverse(DIGIT out[], const DIGIT in[]) {
int32_t swap, delta = 1;
DIGIT g0_mask;

DIGIT f[NUM_DIGITS_GF2X_MODULUS] = {0}; // f = x^P + 1
DIGIT g[NUM_DIGITS_GF2X_ELEMENT]; // g = in
DIGIT *v = out; // v = 0, save space
DIGIT r[NUM_DIGITS_GF2X_ELEMENT] = {0}; // r = 1

f[NUM_DIGITS_GF2X_MODULUS - 1] = 1;
f[0] |= ((DIGIT)1 << MSb_POSITION_IN_MSB_DIGIT_OF_MODULUS);

for (size_t i = 0; i < NUM_DIGITS_GF2X_ELEMENT; i++) {
g[i] = in[i];
}

for (size_t i = 0; i < NUM_DIGITS_GF2X_ELEMENT; i++) {
v[i] = 0;
}

r[NUM_DIGITS_GF2X_ELEMENT - 1] = 1;

for (int loop = 0; loop < 2 * P - 1; ++loop) {

swap = negative(-delta) & nonzero(lsb(g)); // swap = -1 if -delta < 0 AND g(0) != 0
delta ^= swap & (delta ^ -delta); // cond swap delta with -delta if swap
delta++;

gf2x_cswap(f, g, swap);
gf2x_cswap(v, r, swap);

g0_mask = ~lsb(g) + 1;

// g = (g - g0 * f) / x
gf2x_mult_scalar_acc(g, f, g0_mask);
right_bit_shift(NUM_DIGITS_GF2X_ELEMENT, g);

// r = (r - g0 * v) / x
gf2x_mult_scalar_acc(r, v, g0_mask);
rotate_bit_right(r);

}

return nonzero(delta); // -1 if fail, 0 if success
}

void PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_mod_mul(DIGIT Res[], const DIGIT A[], const DIGIT B[]) {

DIGIT aux[2 * NUM_DIGITS_GF2X_ELEMENT];
PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_mul(aux, A, B, NUM_DIGITS_GF2X_ELEMENT);
gf2x_mod(Res, aux);

}

/*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[], size_t 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);

if (sparse[0] != INVALID_POS_VALUE) {
left_bit_shift_wide_n(2 * NUM_DIGITS_GF2X_ELEMENT, resDouble, sparse[0]);
left_bit_shift_wide_n(2 * NUM_DIGITS_GF2X_ELEMENT, aux, sparse[0]);

for (size_t i = 1; i < nPos; i++) {
if (sparse[i] != INVALID_POS_VALUE) {
left_bit_shift_wide_n(2 * NUM_DIGITS_GF2X_ELEMENT, aux, (sparse[i] - sparse[i - 1]) );
PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_add(resDouble, aux, resDouble, 2 * NUM_DIGITS_GF2X_ELEMENT);
}
}
}

gf2x_mod(Res, resDouble);

}

void PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_transpose_in_place_sparse(size_t sizeA, POSITION_T A[]) {
POSITION_T t;
size_t i = 0, j;

if (A[i] == 0) {
i = 1;
}
j = i;

for (; i < sizeA && A[i] != INVALID_POS_VALUE; i++) {
A[i] = P - A[i];
}

for (i -= 1; j < i; j++, i--) {
t = A[j];
A[j] = A[i];
A[i] = t;
}

}

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[]) {

POSITION_T prod;
POSITION_T lastReadPos;
size_t duplicateCount;
size_t write_idx, read_idx;

/* 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++) {
prod = A[i] + B[j];
prod = ( (prod >= P) ? prod - P : prod);
if ((A[i] != INVALID_POS_VALUE) &&
(B[j] != INVALID_POS_VALUE)) {
Res[lastFilledPos] = prod;
} else {
Res[lastFilledPos] = INVALID_POS_VALUE;
}
lastFilledPos++;
}
}
while (lastFilledPos < sizeR) {
Res[lastFilledPos] = INVALID_POS_VALUE;
lastFilledPos++;
}

PQCLEAN_LEDAKEMLT52_LEAKTIME_uint32_sort(Res, sizeR);

/* eliminate duplicates */
write_idx = read_idx = 0;
while (read_idx < sizeR && Res[read_idx] != INVALID_POS_VALUE) {
lastReadPos = Res[read_idx];
read_idx++;
duplicateCount = 1;
while ( (Res[read_idx] == lastReadPos) && (Res[read_idx] != INVALID_POS_VALUE)) {
read_idx++;
duplicateCount++;
}
if (duplicateCount % 2) {
Res[write_idx] = lastReadPos;
write_idx++;
}
}
/* fill remaining cells with INVALID_POS_VALUE */
for (; write_idx < sizeR; write_idx++) {
Res[write_idx] = INVALID_POS_VALUE;
}
}

/* the implementation is safe even in case A or B alias with the result
* PRE: A and B should be sorted, disjunct arrays ending with INVALID_POS_VALUE */
void PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_mod_add_sparse(size_t sizeR, POSITION_T Res[],
size_t sizeA, const POSITION_T A[],
size_t sizeB, const POSITION_T B[]) {

POSITION_T tmpRes[DV * M];
size_t idxA = 0, idxB = 0, idxR = 0;
while ( idxA < sizeA &&
idxB < sizeB &&
A[idxA] != INVALID_POS_VALUE &&
B[idxB] != INVALID_POS_VALUE ) {

if (A[idxA] == B[idxB]) {
idxA++;
idxB++;
} else {
if (A[idxA] < B[idxB]) {
tmpRes[idxR] = A[idxA];
idxA++;
} else {
tmpRes[idxR] = B[idxB];
idxB++;
}
idxR++;
}
}

while (idxA < sizeA && A[idxA] != INVALID_POS_VALUE) {
tmpRes[idxR] = A[idxA];
idxA++;
idxR++;
}

while (idxB < sizeB && B[idxB] != INVALID_POS_VALUE) {
tmpRes[idxR] = B[idxB];
idxB++;
idxR++;
}

while (idxR < sizeR) {
tmpRes[idxR] = INVALID_POS_VALUE;
idxR++;
}
memcpy(Res, tmpRes, sizeof(POSITION_T)*sizeR);

}

/* Return a uniform random value in the range 0..n-1 inclusive,
* applying a rejection sampling strategy and exploiting as a random source
* the NIST seedexpander seeded with the proper key.
* Assumes that the maximum value for the range n is 2^32-1
*/
static uint32_t rand_range(const unsigned int n, const int logn, AES_XOF_struct *seed_expander_ctx) {
unsigned long required_rnd_bytes = (logn + 7) / 8;
unsigned char rnd_char_buffer[4];
uint32_t rnd_value;
uint32_t mask = ( (uint32_t)1 << logn) - 1;

do {
PQCLEAN_LEDAKEMLT52_LEAKTIME_seedexpander(seed_expander_ctx, rnd_char_buffer, required_rnd_bytes);
/* obtain an endianness independent representation of the generated random
bytes into an unsigned integer */
rnd_value = ((uint32_t)rnd_char_buffer[3] << 24) +
((uint32_t)rnd_char_buffer[2] << 16) +
((uint32_t)rnd_char_buffer[1] << 8) +
((uint32_t)rnd_char_buffer[0] << 0) ;
rnd_value = mask & rnd_value;
} while (rnd_value >= n);

return rnd_value;
}

/* Obtains fresh randomness and seed-expands it until all the required positions
* for the '1's in the circulant block are obtained */
void PQCLEAN_LEDAKEMLT52_LEAKTIME_rand_circulant_sparse_block(POSITION_T *pos_ones,
size_t countOnes,
AES_XOF_struct *seed_expander_ctx) {

size_t duplicated, placedOnes = 0;
POSITION_T p;

while (placedOnes < countOnes) {
p = rand_range(NUM_BITS_GF2X_ELEMENT,
P_BITS,
seed_expander_ctx);
duplicated = 0;
for (size_t j = 0; j < placedOnes; j++) {
if (pos_ones[j] == p) {
duplicated = 1;
}
}
if (duplicated == 0) {
pos_ones[placedOnes] = p;
placedOnes++;
}
}
}

/* 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) {

size_t polyIndex, duplicated, counter = 0;
POSITION_T p, exponent, rndPos[NUM_ERRORS_T];

memset(sequence, 0x00, N0 * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B);

while (counter < NUM_ERRORS_T) {
p = rand_range(N0 * NUM_BITS_GF2X_ELEMENT, P_BITS, seed_expander_ctx);
duplicated = 0;
for (size_t j = 0; j < counter; j++) {
if (rndPos[j] == p) {
duplicated = 1;
}
}
if (duplicated == 0) {
rndPos[counter] = p;
counter++;
}
}
for (size_t j = 0; j < counter; j++) {
polyIndex = rndPos[j] / P;
exponent = rndPos[j] % P;
PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_set_coeff( sequence + NUM_DIGITS_GF2X_ELEMENT * polyIndex, exponent,
( (DIGIT) 1));
}

}


void PQCLEAN_LEDAKEMLT52_LEAKTIME_rand_error_pos(POSITION_T errorPos[NUM_ERRORS_T],
AES_XOF_struct *seed_expander_ctx) {

int duplicated;
size_t counter = 0;

while (counter < NUM_ERRORS_T) {
POSITION_T p = rand_range(N0 * NUM_BITS_GF2X_ELEMENT, P_BITS, seed_expander_ctx);
duplicated = 0;
for (size_t 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],
const POSITION_T errorPos[NUM_ERRORS_T]) {

size_t polyIndex;
POSITION_T exponent;

memset(sequence, 0x00, N0 * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B);
for (int j = 0; j < NUM_ERRORS_T; j++) {
polyIndex = errorPos[j] / P;
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++) {
for (j = 0; j < DIGIT_SIZE_B; j++) {
bytes[i * DIGIT_SIZE_B + j] = (uint8_t) (poly[i] >> 8 * j);
}
}
}

void PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_frombytes(DIGIT *poly, const uint8_t *poly_bytes) {
size_t i, j;
for (i = 0; i < NUM_DIGITS_GF2X_ELEMENT; i++) {
poly[i] = (DIGIT) 0;
for (j = 0; j < DIGIT_SIZE_B; j++) {
poly[i] |= (DIGIT) poly_bytes[i * DIGIT_SIZE_B + j] << 8 * j;
}
}
}

+ 0
- 39
crypto_kem/ledakemlt52/leaktime/gf2x_arith_mod_xPplusOne.h View File

@@ -1,39 +0,0 @@
#ifndef GF2X_ARITH_MOD_XPLUSONE_H
#define GF2X_ARITH_MOD_XPLUSONE_H

#include "qc_ldpc_parameters.h"

#include "gf2x_arith.h"
#include "rng.h"

#define NUM_BITS_GF2X_ELEMENT (P)
#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)
#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)

void PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_copy(DIGIT dest[], const DIGIT in[]);
DIGIT PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_get_coeff(const DIGIT poly[], size_t exponent);
void PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_set_coeff(DIGIT poly[], size_t exponent, DIGIT value);
void PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_toggle_coeff(DIGIT poly[], size_t exponent);
int PQCLEAN_LEDAKEMLT52_LEAKTIME_population_count(const DIGIT *poly);
void PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_mod_add(DIGIT Res[], const DIGIT A[], const DIGIT B[]);
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, size_t 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], const POSITION_T errorPos[NUM_ERRORS_T]);
void PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_mod_add_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_transpose_in_place_sparse(size_t 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_dense_to_sparse(DIGIT Res[], const DIGIT dense[], POSITION_T sparse[], size_t 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

+ 0
- 157
crypto_kem/ledakemlt52/leaktime/kem.c View File

@@ -1,157 +0,0 @@
#include "api.h"
#include "niederreiter.h"
#include "randombytes.h"
#include "rng.h"
#include "utils.h"

#include <string.h>


#define pack_ct(sk_bytes, ct) PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_tobytes(sk_bytes, ct);
#define unpack_ct(ct, ct_bytes) PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_frombytes(ct, ct_bytes)

static void pack_pk(uint8_t *pk_bytes, publicKeyNiederreiter_t *pk) {
for (size_t i = 0; i < N0 - 1; i++) {
PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_tobytes(pk_bytes + i * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B,
pk->Mtr + i * NUM_DIGITS_GF2X_ELEMENT);
}
}

static void unpack_pk(publicKeyNiederreiter_t *pk, const uint8_t *pk_bytes) {
for (size_t i = 0; i < N0 - 1; i++) {
PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_frombytes(pk->Mtr + i * NUM_DIGITS_GF2X_ELEMENT,
pk_bytes + i * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B);
}
}

static void pack_error(uint8_t *error_bytes, DIGIT *error_digits) {
size_t i;
for (i = 0; i < N0; i++) {
PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_tobytes(error_bytes + i * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B,
error_digits + i * NUM_DIGITS_GF2X_ELEMENT);
}
}

/* IND-CCA2 Keygen */
int PQCLEAN_LEDAKEMLT52_LEAKTIME_crypto_kem_keypair(uint8_t *pk, uint8_t *sk) {
publicKeyNiederreiter_t niederreiter_pk;

PQCLEAN_LEDAKEMLT52_LEAKTIME_niederreiter_keygen(&niederreiter_pk, (privateKeyNiederreiter_t *) sk);

pack_pk(pk, &niederreiter_pk);

return 0;
}

/* IND-CCA2 Encapsulation */
int PQCLEAN_LEDAKEMLT52_LEAKTIME_crypto_kem_enc(uint8_t *ct, uint8_t *ss, const uint8_t *pk) {
publicKeyNiederreiter_t niederreiter_pk;
DIGIT syndrome[NUM_DIGITS_GF2X_ELEMENT];
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];
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];

unpack_pk(&niederreiter_pk, 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);

memcpy(hashedAndTruncatedSeed, hashedSeed, TRNG_BYTE_LENGTH);

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);

pack_error(error_bytes, error_vector);
HASH_FUNCTION(hashedErrorVector, error_bytes, (N0 * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B));

memcpy(hashedAndTruncatedErrorVector, hashedErrorVector, TRNG_BYTE_LENGTH);

for (size_t i = 0; i < TRNG_BYTE_LENGTH; ++i) {
maskedSeed[i] = seed[i] ^ hashedAndTruncatedErrorVector[i];
}

PQCLEAN_LEDAKEMLT52_LEAKTIME_niederreiter_encrypt(syndrome,
(const publicKeyNiederreiter_t *) &niederreiter_pk, error_vector);

pack_ct(ct, syndrome);
memcpy(ct + (NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B), maskedSeed, TRNG_BYTE_LENGTH);

return 0;
}


/* IND-CCA2 Decapsulation */
int PQCLEAN_LEDAKEMLT52_LEAKTIME_crypto_kem_dec(uint8_t *ss, const uint8_t *ct, const uint8_t *sk) {
DIGIT syndrome[NUM_DIGITS_GF2X_ELEMENT];
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];
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};
int decode_ok, decrypt_ok, equal;

unpack_ct(syndrome, ct);

decode_ok = PQCLEAN_LEDAKEMLT52_LEAKTIME_niederreiter_decrypt(decoded_error_vector,
(const privateKeyNiederreiter_t *)sk, syndrome);

pack_error(decoded_error_bytes, decoded_error_vector);
HASH_FUNCTION(hashedErrorVector, decoded_error_bytes, N0 * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B);

memcpy(hashedAndTruncatedErrorVector, hashedErrorVector, TRNG_BYTE_LENGTH);

for (size_t 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);

equal = PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_verify(decoded_error_vector,
reconstructed_error_vector, N0 * NUM_DIGITS_GF2X_ELEMENT);
// equal == 0, if the reconstructed error vector match !!!

decrypt_ok = (decode_ok == 1 && equal == 0);

memcpy(ss_input, decoded_seed, TRNG_BYTE_LENGTH);
memcpy(ss_input + sizeof(decoded_seed), tail, TRNG_BYTE_LENGTH);

// Overwrite on failure
PQCLEAN_LEDAKEMLT52_LEAKTIME_cmov(ss_input + sizeof(decoded_seed),
((const privateKeyNiederreiter_t *) sk)->decryption_failure_secret,
TRNG_BYTE_LENGTH,
!decrypt_ok);

HASH_FUNCTION(ss, ss_input, 2 * TRNG_BYTE_LENGTH);

return 0;
}

+ 0
- 192
crypto_kem/ledakemlt52/leaktime/niederreiter.c View File

@@ -1,192 +0,0 @@
#include "H_Q_matrices_generation.h"
#include "bf_decoding.h"
#include "dfr_test.h"
#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;
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] = {0};
DIGIT Ln0Inv[NUM_DIGITS_GF2X_ELEMENT] = {0};
int is_L_full;
int isDFRok = 0;

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(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;
}
}

memset(processedQOnes, 0x00, sizeof(processedQOnes));
for (int colQ = 0; colQ < N0; colQ++) {
for (int i = 0; i < N0; i++) {
PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_mod_mul_sparse(DV * M, auxPosOnes,
DV, HPosOnes[i],
qBlockWeights[i][colQ], QPosOnes[i] + processedQOnes[i]);
PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_mod_add_sparse(DV * M, LPosOnes[colQ],
DV * M, LPosOnes[colQ],
DV * M, auxPosOnes);
processedQOnes[i] += qBlockWeights[i][colQ];
}
}
is_L_full = 1;
for (size_t i = 0; i < N0; i++) {
is_L_full = is_L_full && (LPosOnes[i][DV * M - 1] != INVALID_POS_VALUE);
}
sk->rejections = sk->rejections + 1;
if (is_L_full) {
isDFRok = PQCLEAN_LEDAKEMLT52_LEAKTIME_DFR_test(LPosOnes, &(sk->secondIterThreshold));
}
} while (!is_L_full || !isDFRok);
sk->rejections = sk->rejections - 1;

PQCLEAN_LEDAKEMLT52_LEAKTIME_seedexpander(&keys_expander,
sk->decryption_failure_secret,
(unsigned long)TRNG_BYTE_LENGTH);

for (size_t 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);
}
}

PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_mod_inverse(Ln0Inv, Ln0dense);
for (size_t i = 0; i < N0 - 1; i++) {
PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_mod_mul_dense_to_sparse(pk->Mtr + i * NUM_DIGITS_GF2X_ELEMENT,
Ln0Inv,
LPosOnes[i],
DV * M);
}

for (size_t i = 0; i < N0 - 1; i++) {
PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_transpose_in_place(pk->Mtr + i * NUM_DIGITS_GF2X_ELEMENT);
}
}

void PQCLEAN_LEDAKEMLT52_LEAKTIME_niederreiter_encrypt(DIGIT syndrome[],
const publicKeyNiederreiter_t *pk,
const DIGIT err[]) {

DIGIT saux[NUM_DIGITS_GF2X_ELEMENT];

memset(syndrome, 0x00, NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B);
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 QPosOnes[N0][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];
DIGIT err_computed[N0 * NUM_DIGITS_GF2X_ELEMENT] = {0};
DIGIT err_mockup[N0 * NUM_DIGITS_GF2X_ELEMENT];
DIGIT privateSyndrome[NUM_DIGITS_GF2X_ELEMENT];
uint8_t processedQOnes[N0];
int rejections = sk->rejections;
int decrypt_ok = 0;
int err_weight;

PQCLEAN_LEDAKEMLT52_LEAKTIME_seedexpander_from_trng(&niederreiter_decrypt_expander, sk->prng_seed);
do {
PQCLEAN_LEDAKEMLT52_LEAKTIME_generateHPosOnes(HPosOnes, &niederreiter_decrypt_expander);
PQCLEAN_LEDAKEMLT52_LEAKTIME_generateQPosOnes(QPosOnes, &niederreiter_decrypt_expander);

for (size_t i = 0; i < N0; i++) {
for (size_t j = 0; j < DV * M; j++) {
LPosOnes[i][j] = INVALID_POS_VALUE;
}
}

memset(processedQOnes, 0x00, sizeof(processedQOnes));
for (size_t colQ = 0; colQ < N0; colQ++) {
for (size_t i = 0; i < N0; i++) {
PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_mod_mul_sparse(DV * M, auxPosOnes,
DV, HPosOnes[i],
qBlockWeights[i][colQ], QPosOnes[i] + processedQOnes[i]);
PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_mod_add_sparse(DV * M, LPosOnes[colQ],
DV * M, LPosOnes[colQ],
DV * M, auxPosOnes);
processedQOnes[i] += qBlockWeights[i][colQ];
}
}
rejections--;
} while (rejections >= 0);

PQCLEAN_LEDAKEMLT52_LEAKTIME_transposeHPosOnes(HtrPosOnes, HPosOnes);
PQCLEAN_LEDAKEMLT52_LEAKTIME_transposeQPosOnes(QtrPosOnes, QPosOnes);

for (size_t i = 0; i < DV * M; i++) {
Ln0trSparse[i] = INVALID_POS_VALUE;
auxSparse[i] = INVALID_POS_VALUE;
}

for (size_t 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]]);
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);

decrypt_ok = PQCLEAN_LEDAKEMLT52_LEAKTIME_bf_decoding(err_computed,
(const POSITION_T (*)[DV]) HtrPosOnes,
(const POSITION_T (*)[M]) QtrPosOnes,
privateSyndrome, sk->secondIterThreshold);

err_weight = 0;
for (size_t i = 0 ; i < N0; i++) {
err_weight += PQCLEAN_LEDAKEMLT52_LEAKTIME_population_count(err_computed + (NUM_DIGITS_GF2X_ELEMENT * i));
}
decrypt_ok = decrypt_ok && (err_weight == NUM_ERRORS_T);

/* prepare mockup error vector in case a decoding failure occurs */
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);

memcpy(err, err_computed, N0 * NUM_DIGITS_GF2X_ELEMENT * DIGIT_SIZE_B);

// Overwrite on decryption failure
PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_cmov(err, err_mockup, N0 * NUM_DIGITS_GF2X_ELEMENT, !decrypt_ok);

return decrypt_ok;
}

+ 0
- 24
crypto_kem/ledakemlt52/leaktime/niederreiter.h View File

@@ -1,24 +0,0 @@
#ifndef NIEDERREITER_H
#define NIEDERREITER_H

#include "gf2x_arith_mod_xPplusOne.h"
#include "qc_ldpc_parameters.h"
#include "rng.h"

typedef struct {
unsigned char prng_seed[TRNG_BYTE_LENGTH];
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];
} publicKeyNiederreiter_t;


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

+ 0
- 27
crypto_kem/ledakemlt52/leaktime/qc_ldpc_parameters.h View File

@@ -1,27 +0,0 @@
#ifndef QC_LDPC_PARAMETERS_H
#define QC_LDPC_PARAMETERS_H

#include "fips202.h"

#define TRNG_BYTE_LENGTH (40)
#define HASH_BYTE_LENGTH (64)
#define HASH_FUNCTION sha3_512

#define N0 (2)
#define P (152267) // modulus(x) = x^P-1
#define DV (13) // odd number
#define M (13)
#define M0 (7)
#define M1 (6)
#define NUM_ERRORS_T (267)

// Derived parameters, they are useful for QC-LDPC algorithms
#define HASH_BIT_LENGTH (HASH_BYTE_LENGTH << 3)
#define K ((N0-1)*P)
#define N (N0*P)
#define DC (N0*DV)

#define Q_BLOCK_WEIGHTS {{M0,M1},{M1,M0}}
static const unsigned char qBlockWeights[N0][N0] = Q_BLOCK_WEIGHTS;

#endif

+ 0
- 110
crypto_kem/ledakemlt52/leaktime/rng.c View File

@@ -1,110 +0,0 @@
#include "rng.h"

#include <string.h> // void *memset(void *s, int c, size_t n);

#include "aes.h"
#include "qc_ldpc_parameters.h"

/*
seedexpander_init()
ctx - stores the current state of an instance of the seed expander
seed - a 32 byte random value
diversifier - an 8 byte diversifier
maxlen - maximum number of bytes (less than 2**32) generated under this seed and diversifier
*/
static void seedexpander_init(AES_XOF_struct *ctx,
uint8_t *seed,
uint8_t *diversifier,
size_t maxlen) {

ctx->length_remaining = maxlen;

memset(ctx->key, 0, 32);
int max_accessible_seed_len = TRNG_BYTE_LENGTH < 32 ? 32 : TRNG_BYTE_LENGTH;
memcpy(ctx->key, seed, max_accessible_seed_len);

memcpy(ctx->ctr, diversifier, 8);
ctx->ctr[11] = maxlen % 256;
maxlen >>= 8;
ctx->ctr[10] = maxlen % 256;
maxlen >>= 8;
ctx->ctr[9] = maxlen % 256;
maxlen >>= 8;
ctx->ctr[8] = maxlen % 256;
memset(ctx->ctr + 12, 0x00, 4);

ctx->buffer_pos = 16;
memset(ctx->buffer, 0x00, 16);
}

void PQCLEAN_LEDAKEMLT52_LEAKTIME_seedexpander_from_trng(AES_XOF_struct *ctx,
const uint8_t *trng_entropy
/* TRNG_BYTE_LENGTH wide buffer */) {

/*the NIST seedexpander will however access 32B from this buffer */
unsigned int prng_buffer_size = TRNG_BYTE_LENGTH < 32 ? 32 : TRNG_BYTE_LENGTH;
uint8_t prng_buffer[TRNG_BYTE_LENGTH < 32 ? 32 : TRNG_BYTE_LENGTH] = {0x00};
uint8_t *diversifier = (uint8_t *)trng_entropy + 32;

memcpy(prng_buffer,
trng_entropy,
TRNG_BYTE_LENGTH < prng_buffer_size ? TRNG_BYTE_LENGTH : prng_buffer_size);

/* the required seed expansion will be quite small, set the max number of
* bytes conservatively to 10 MiB*/
seedexpander_init(ctx, prng_buffer, diversifier, RNG_MAXLEN);
}

/*
seedexpander()
ctx - stores the current state of an instance of the seed expander
x - returns the XOF data
xlen - number of bytes to return
*/
int PQCLEAN_LEDAKEMLT52_LEAKTIME_seedexpander(AES_XOF_struct *ctx, uint8_t *x, size_t xlen) {
size_t offset;
aes256ctx ctx256;

if ( x == NULL ) {
return RNG_BAD_OUTBUF;
}
if ( xlen >= ctx->length_remaining ) {
return RNG_BAD_REQ_LEN;
}

aes256_ecb_keyexp(&ctx256, ctx->key);
ctx->length_remaining -= xlen;

offset = 0;
while ( xlen > 0 ) {
if ( xlen <= (16 - ctx->buffer_pos) ) { // buffer has what we need
memcpy(x + offset, ctx->buffer + ctx->buffer_pos, xlen);
ctx->buffer_pos += xlen;

goto end;
}

// take what's in the buffer
memcpy(x + offset, ctx->buffer + ctx->buffer_pos, 16 - ctx->buffer_pos);
xlen -= 16 - ctx->buffer_pos;
offset += 16 - ctx->buffer_pos;

aes256_ecb(ctx->buffer, ctx->ctr, 16 / AES_BLOCKBYTES, &ctx256);
ctx->buffer_pos = 0;

//increment the counter
for (int i = 15; i >= 12; i--) {
if ( ctx->ctr[i] == 0xff ) {
ctx->ctr[i] = 0x00;
} else {
ctx->ctr[i]++;
break;
}
}

}
end:
aes256_ctx_release(&ctx256);

return RNG_SUCCESS;
}

+ 0
- 24
crypto_kem/ledakemlt52/leaktime/rng.h View File

@@ -1,24 +0,0 @@
#ifndef RNG_H
#define RNG_H

#include <stddef.h>
#include <stdint.h>

#define RNG_SUCCESS ( 0)
#define RNG_BAD_MAXLEN (-1)
#define RNG_BAD_OUTBUF (-2)
#define RNG_BAD_REQ_LEN (-3)
#define RNG_MAXLEN (10 * 1024 * 1024)

typedef struct {
unsigned char buffer[16];
size_t buffer_pos;
size_t length_remaining;
unsigned char key[32];
unsigned char ctr[16];
} AES_XOF_struct;

int PQCLEAN_LEDAKEMLT52_LEAKTIME_seedexpander(AES_XOF_struct *ctx, unsigned char *x, size_t xlen);
void PQCLEAN_LEDAKEMLT52_LEAKTIME_seedexpander_from_trng(AES_XOF_struct *ctx, const unsigned char *trng_entropy);

#endif

+ 0
- 98
crypto_kem/ledakemlt52/leaktime/sort.c View File

@@ -1,98 +0,0 @@
#include "sort.h"

/*
Constant-time uint32_t sorting by Daniel J. Bernstein
Source: https://sorting.cr.yp.to
*/

#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)

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;
}
}

+ 0
- 11
crypto_kem/ledakemlt52/leaktime/sort.h View File

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

#include <stddef.h>
#include <stdint.h>

#define int32 int32_t

void PQCLEAN_LEDAKEMLT52_LEAKTIME_uint32_sort(uint32_t *x, size_t n);

#endif

+ 0
- 21
crypto_kem/ledakemlt52/leaktime/utils.c View File

@@ -1,21 +0,0 @@
#include "gf2x_arith.h"
#include "utils.h"

/* compares DIGIT sequences, returns 0 if they are equal */
int PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_verify(const DIGIT *a, const DIGIT *b, size_t len) {
DIGIT x = 0;
for (size_t i = 0; i < len; i++) {
x |= a[i] ^ b[i];
}
x = (~x) + 1;
x >>= (DIGIT_SIZE_b - 1);
return (int)x;
}

/* conditionally move a into r if cond */
void PQCLEAN_LEDAKEMLT52_LEAKTIME_cmov(uint8_t *r, const uint8_t *a, size_t len, int cond) {
uint8_t mask = (uint8_t)(-cond);
for (size_t i = 0; i < len; i++) {
r[i] ^= mask & (r[i] ^ a[i]);
}
}

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save