ac2c20045c
* 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
145 lines
3.4 KiB
C
145 lines
3.4 KiB
C
/*
|
|
This file is for public-key generation
|
|
*/
|
|
|
|
#include <string.h>
|
|
|
|
#include "benes.h"
|
|
#include "controlbits.h"
|
|
#include "gf.h"
|
|
#include "params.h"
|
|
#include "pk_gen.h"
|
|
#include "root.h"
|
|
#include "util.h"
|
|
|
|
/* input: secret key sk */
|
|
/* output: public key pk */
|
|
int PQCLEAN_MCELIECE348864_CLEAN_pk_gen(uint8_t *pk, uint32_t *perm, const uint8_t *sk) {
|
|
int i, j, k;
|
|
int row, c;
|
|
|
|
uint64_t buf[ 1 << GFBITS ];
|
|
|
|
uint8_t mat[ GFBITS * SYS_T ][ SYS_N / 8 ];
|
|
uint8_t mask;
|
|
uint8_t b;
|
|
|
|
gf g[ SYS_T + 1 ]; // Goppa polynomial
|
|
gf L[ SYS_N ]; // support
|
|
gf inv[ SYS_N ];
|
|
|
|
//
|
|
|
|
g[ SYS_T ] = 1;
|
|
|
|
for (i = 0; i < SYS_T; i++) {
|
|
g[i] = PQCLEAN_MCELIECE348864_CLEAN_load2(sk);
|
|
g[i] &= GFMASK;
|
|
sk += 2;
|
|
}
|
|
|
|
for (i = 0; i < (1 << GFBITS); i++) {
|
|
buf[i] = perm[i];
|
|
buf[i] <<= 31;
|
|
buf[i] |= i;
|
|
}
|
|
|
|
PQCLEAN_MCELIECE348864_CLEAN_sort_63b(1 << GFBITS, buf);
|
|
|
|
for (i = 0; i < (1 << GFBITS); i++) {
|
|
perm[i] = buf[i] & GFMASK;
|
|
}
|
|
for (i = 0; i < SYS_N; i++) {
|
|
L[i] = PQCLEAN_MCELIECE348864_CLEAN_bitrev((gf)perm[i]);
|
|
}
|
|
|
|
// filling the matrix
|
|
|
|
PQCLEAN_MCELIECE348864_CLEAN_root(inv, g, L);
|
|
|
|
for (i = 0; i < SYS_N; i++) {
|
|
inv[i] = PQCLEAN_MCELIECE348864_CLEAN_gf_inv(inv[i]);
|
|
}
|
|
|
|
for (i = 0; i < PK_NROWS; i++) {
|
|
for (j = 0; j < SYS_N / 8; j++) {
|
|
mat[i][j] = 0;
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < SYS_T; i++) {
|
|
for (j = 0; j < SYS_N; j += 8) {
|
|
for (k = 0; k < GFBITS; k++) {
|
|
b = (inv[j + 7] >> k) & 1;
|
|
b <<= 1;
|
|
b |= (inv[j + 6] >> k) & 1;
|
|
b <<= 1;
|
|
b |= (inv[j + 5] >> k) & 1;
|
|
b <<= 1;
|
|
b |= (inv[j + 4] >> k) & 1;
|
|
b <<= 1;
|
|
b |= (inv[j + 3] >> k) & 1;
|
|
b <<= 1;
|
|
b |= (inv[j + 2] >> k) & 1;
|
|
b <<= 1;
|
|
b |= (inv[j + 1] >> k) & 1;
|
|
b <<= 1;
|
|
b |= (inv[j + 0] >> k) & 1;
|
|
|
|
mat[ i * GFBITS + k ][ j / 8 ] = b;
|
|
}
|
|
}
|
|
|
|
for (j = 0; j < SYS_N; j++) {
|
|
inv[j] = PQCLEAN_MCELIECE348864_CLEAN_gf_mul(inv[j], L[j]);
|
|
}
|
|
|
|
}
|
|
|
|
// gaussian elimination
|
|
|
|
for (i = 0; i < (GFBITS * SYS_T + 7) / 8; i++) {
|
|
for (j = 0; j < 8; j++) {
|
|
row = i * 8 + j;
|
|
|
|
if (row >= GFBITS * SYS_T) {
|
|
break;
|
|
}
|
|
|
|
for (k = row + 1; k < GFBITS * SYS_T; k++) {
|
|
mask = mat[ row ][ i ] ^ mat[ k ][ i ];
|
|
mask >>= j;
|
|
mask &= 1;
|
|
mask = -mask;
|
|
|
|
for (c = 0; c < SYS_N / 8; c++) {
|
|
mat[ row ][ c ] ^= mat[ k ][ c ] & mask;
|
|
}
|
|
}
|
|
|
|
if ( ((mat[ row ][ i ] >> j) & 1) == 0 ) { // return if not systematic
|
|
return -1;
|
|
}
|
|
|
|
for (k = 0; k < GFBITS * SYS_T; k++) {
|
|
if (k != row) {
|
|
mask = mat[ k ][ i ] >> j;
|
|
mask &= 1;
|
|
mask = -mask;
|
|
|
|
for (c = 0; c < SYS_N / 8; c++) {
|
|
mat[ k ][ c ] ^= mat[ row ][ c ] & mask;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < PK_NROWS; i++) {
|
|
memcpy(pk + i * PK_ROW_BYTES, mat[i] + PK_NROWS / 8, PK_ROW_BYTES);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|