pqc/crypto_kem/mceliece348864f/clean/benes.c
Thom Wiggers b3f9d4f8d6
Classic McEliece (#259)
* Add McEliece reference implementations

* Add Vec implementations of McEliece

* Add sse implementations

* Add AVX2 implementations

* Get rid of stuff not supported by Mac ABI

* restrict to two cores

* Ditch .data files

* Remove .hidden from all .S files

* speed up duplicate consistency tests by batching

* make cpuinfo more robust

* Hope to stabilize macos cpuinfo without ccache

* Revert "Hope to stabilize macos cpuinfo without ccache"

This reverts commit 6129c3cabe1abbc8b956bc87e902a698e32bf322.

* Just hardcode what's available at travis

* Fixed-size types in api.h

* namespace all header files in mceliece

* Ditch operations.h

* Get rid of static inline functions

* fixup! Ditch operations.h
2020-02-05 13:09:56 +01:00

140 lines
3.3 KiB
C

/*
This file is for Benes network related functions
*/
#include "benes.h"
#include "params.h"
#include "transpose.h"
#include "util.h"
/* one layer of the benes network */
static void layer(uint64_t *data, uint64_t *bits, int lgs) {
int i, j, s;
uint64_t d;
s = 1 << lgs;
for (i = 0; i < 64; i += s * 2) {
for (j = i; j < i + s; j++) {
d = (data[j + 0] ^ data[j + s]);
d &= (*bits++);
data[j + 0] ^= d;
data[j + s] ^= d;
}
}
}
/* input: r, sequence of bits to be permuted */
/* bits, condition bits of the Benes network */
/* rev, 0 for normal application; !0 for inverse */
/* output: r, permuted bits */
void PQCLEAN_MCELIECE348864F_CLEAN_apply_benes(unsigned char *r, const unsigned char *bits, int rev) {
int i;
const unsigned char *cond_ptr;
int inc, low;
uint64_t bs[64];
uint64_t cond[64];
//
for (i = 0; i < 64; i++) {
bs[i] = PQCLEAN_MCELIECE348864F_CLEAN_load8(r + i * 8);
}
if (rev == 0) {
inc = 256;
cond_ptr = bits;
} else {
inc = -256;
cond_ptr = bits + (2 * GFBITS - 2) * 256;
}
//
PQCLEAN_MCELIECE348864F_CLEAN_transpose_64x64(bs, bs);
for (low = 0; low <= 5; low++) {
for (i = 0; i < 64; i++) {
cond[i] = PQCLEAN_MCELIECE348864F_CLEAN_load4(cond_ptr + i * 4);
}
PQCLEAN_MCELIECE348864F_CLEAN_transpose_64x64(cond, cond);
layer(bs, cond, low);
cond_ptr += inc;
}
PQCLEAN_MCELIECE348864F_CLEAN_transpose_64x64(bs, bs);
for (low = 0; low <= 5; low++) {
for (i = 0; i < 32; i++) {
cond[i] = PQCLEAN_MCELIECE348864F_CLEAN_load8(cond_ptr + i * 8);
}
layer(bs, cond, low);
cond_ptr += inc;
}
for (low = 4; low >= 0; low--) {
for (i = 0; i < 32; i++) {
cond[i] = PQCLEAN_MCELIECE348864F_CLEAN_load8(cond_ptr + i * 8);
}
layer(bs, cond, low);
cond_ptr += inc;
}
PQCLEAN_MCELIECE348864F_CLEAN_transpose_64x64(bs, bs);
for (low = 5; low >= 0; low--) {
for (i = 0; i < 64; i++) {
cond[i] = PQCLEAN_MCELIECE348864F_CLEAN_load4(cond_ptr + i * 4);
}
PQCLEAN_MCELIECE348864F_CLEAN_transpose_64x64(cond, cond);
layer(bs, cond, low);
cond_ptr += inc;
}
PQCLEAN_MCELIECE348864F_CLEAN_transpose_64x64(bs, bs);
for (i = 0; i < 64; i++) {
PQCLEAN_MCELIECE348864F_CLEAN_store8(r + i * 8, bs[i]);
}
}
/* input: condition bits c */
/* output: support s */
void PQCLEAN_MCELIECE348864F_CLEAN_support_gen(gf *s, const unsigned char *c) {
gf a;
int i, j;
unsigned char L[ GFBITS ][ (1 << GFBITS) / 8 ];
for (i = 0; i < GFBITS; i++) {
for (j = 0; j < (1 << GFBITS) / 8; j++) {
L[i][j] = 0;
}
}
for (i = 0; i < (1 << GFBITS); i++) {
a = PQCLEAN_MCELIECE348864F_CLEAN_bitrev((gf) i);
for (j = 0; j < GFBITS; j++) {
L[j][ i / 8 ] |= ((a >> j) & 1) << (i % 8);
}
}
for (j = 0; j < GFBITS; j++) {
PQCLEAN_MCELIECE348864F_CLEAN_apply_benes(L[j], c, 0);
}
for (i = 0; i < SYS_N; i++) {
s[i] = 0;
for (j = GFBITS - 1; j >= 0; j--) {
s[i] <<= 1;
s[i] |= (L[j][i / 8] >> (i % 8)) & 1;
}
}
}