/* This file is for Benes network related functions */ #include "benes.h" #include "params.h" #include "transpose.h" #include "util.h" #include "vec.h" /* middle layers of the benes network */ static void layer_in(uint64_t data[2][64], 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[0][j + 0] ^ data[0][j + s]); d &= (*bits++); data[0][j + 0] ^= d; data[0][j + s] ^= d; d = (data[1][j + 0] ^ data[1][j + s]); d &= (*bits++); data[1][j + 0] ^= d; data[1][j + s] ^= d; } } } /* first and last layers of the benes network */ static void layer_ex(uint64_t *data, uint64_t *bits, int lgs) { int i, j, s; uint64_t d; s = 1 << lgs; for (i = 0; i < 128; 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_MCELIECE460896F_VEC_benes(vec *r, const unsigned char *bits, int rev) { int i, iter, inc; const unsigned char *bits_ptr; uint64_t r_int_v[2][64]; uint64_t r_int_h[2][64]; uint64_t b_int_v[64]; uint64_t b_int_h[64]; // if (rev) { bits_ptr = bits + 12288; inc = -1024; } else { bits_ptr = bits; inc = 0; } for (i = 0; i < 64; i++) { r_int_v[0][i] = r[i * 2 + 0]; r_int_v[1][i] = r[i * 2 + 1]; } PQCLEAN_MCELIECE460896F_VEC_transpose_64x64(r_int_h[0], r_int_v[0]); PQCLEAN_MCELIECE460896F_VEC_transpose_64x64(r_int_h[1], r_int_v[1]); for (iter = 0; iter <= 6; iter++) { for (i = 0; i < 64; i++) { b_int_v[i] = PQCLEAN_MCELIECE460896F_VEC_load8(bits_ptr); bits_ptr += 8; } bits_ptr += inc; PQCLEAN_MCELIECE460896F_VEC_transpose_64x64(b_int_h, b_int_v); layer_ex(r_int_h[0], b_int_h, iter); } PQCLEAN_MCELIECE460896F_VEC_transpose_64x64(r_int_v[0], r_int_h[0]); PQCLEAN_MCELIECE460896F_VEC_transpose_64x64(r_int_v[1], r_int_h[1]); for (iter = 0; iter <= 5; iter++) { for (i = 0; i < 64; i++) { b_int_v[i] = PQCLEAN_MCELIECE460896F_VEC_load8(bits_ptr); bits_ptr += 8; } bits_ptr += inc; layer_in(r_int_v, b_int_v, iter); } for (iter = 4; iter >= 0; iter--) { for (i = 0; i < 64; i++) { b_int_v[i] = PQCLEAN_MCELIECE460896F_VEC_load8(bits_ptr); bits_ptr += 8; } bits_ptr += inc; layer_in(r_int_v, b_int_v, iter); } PQCLEAN_MCELIECE460896F_VEC_transpose_64x64(r_int_h[0], r_int_v[0]); PQCLEAN_MCELIECE460896F_VEC_transpose_64x64(r_int_h[1], r_int_v[1]); for (iter = 6; iter >= 0; iter--) { for (i = 0; i < 64; i++) { b_int_v[i] = PQCLEAN_MCELIECE460896F_VEC_load8(bits_ptr); bits_ptr += 8; } bits_ptr += inc; PQCLEAN_MCELIECE460896F_VEC_transpose_64x64(b_int_h, b_int_v); layer_ex(r_int_h[0], b_int_h, iter); } PQCLEAN_MCELIECE460896F_VEC_transpose_64x64(r_int_v[0], r_int_h[0]); PQCLEAN_MCELIECE460896F_VEC_transpose_64x64(r_int_v[1], r_int_h[1]); for (i = 0; i < 64; i++) { r[i * 2 + 0] = r_int_v[0][i]; r[i * 2 + 1] = r_int_v[1][i]; } }