/* This file is for public-key generation */ #include #include #include #include #include "controlbits.h" #include "benes.h" #include "params.h" #include "pk_gen.h" #include "root.h" #include "util.h" /* input: secret key sk */ /* output: public key pk */ int PQCLEAN_MCELIECE6960119_CLEAN_pk_gen(uint8_t *pk, uint32_t *perm, const uint8_t *sk) { unsigned char *pk_ptr = pk; int i, j, k; int row, c, tail; uint64_t buf[ 1 << GFBITS ]; unsigned char mat[ GFBITS * SYS_T ][ SYS_N / 8 ]; unsigned char mask; unsigned char 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_MCELIECE6960119_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_MCELIECE6960119_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_MCELIECE6960119_CLEAN_bitrev((gf)perm[i]); } // filling the matrix PQCLEAN_MCELIECE6960119_CLEAN_root(inv, g, L); for (i = 0; i < SYS_N; i++) { inv[i] = PQCLEAN_MCELIECE6960119_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_MCELIECE6960119_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; } } } } } tail = (GFBITS * SYS_T) % 8; for (i = 0; i < GFBITS * SYS_T; i++) { for (j = (GFBITS * SYS_T - 1) / 8; j < SYS_N / 8 - 1; j++) { *pk_ptr++ = (mat[i][j] >> tail) | (mat[i][j + 1] << (8 - tail)); } *pk_ptr++ = (mat[i][j] >> tail); } return 0; }