#include "cleanup.h"
#include "gf2x.h"
#include "gf2x_internal.h"
_INLINE_ void gf2x_mod_sqr_in_place(IN OUT pad_r_t *a,
OUT dbl_pad_r_t *secure_buffer,
IN const gf2x_ctx *ctx)
{
ctx->sqr(secure_buffer, a);
ctx->red(a, secure_buffer);
}
_INLINE_ void repeated_squaring(OUT pad_r_t *c,
IN pad_r_t * a,
IN const size_t num_sqrs,
OUT dbl_pad_r_t *sec_buf,
IN const gf2x_ctx *ctx)
{
c->val = a->val;
for(size_t i = 0; i < num_sqrs; i++) {
gf2x_mod_sqr_in_place(c, sec_buf, ctx);
}
}
#define K_SQR_THR (64)
#if(LEVEL == 1)
bike_static_assert((R_BITS == 12323), gf2x_inv_r_doesnt_match_parameters);
# define MAX_I (14)
# define EXP0_K_VALS \
1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192
# define EXP0_L_VALS \
6162, 3081, 3851, 5632, 22, 484, 119, 1838, 1742, 3106, 10650, 1608, 10157, 8816
# define EXP1_K_VALS 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 33, 4129
# define EXP1_L_VALS 0, 0, 0, 0, 0, 6162, 0, 0, 0, 0, 0, 0, 242, 5717
#elif(LEVEL == 3)
bike_static_assert((R_BITS == 24659), gf2x_inv_r_doesnt_match_parameters);
# define MAX_I (15)
# define EXP0_K_VALS \
1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384
# define EXP0_L_VALS \
12330, 6165, 7706, 3564, 2711, 1139, 15053, 1258, 4388, 20524, 9538, 6393, \
10486, 1715, 6804
# define EXP1_K_VALS 0, 0, 0, 0, 1, 0, 17, 0, 0, 0, 0, 0, 0, 81, 8273
# define EXP1_L_VALS 0, 0, 0, 0, 12330, 0, 13685, 0, 0, 0, 0, 0, 0, 23678, 19056
#else
bike_static_assert((R_BITS == 40973), gf2x_inv_r_doesnt_match_parameters);
# define MAX_I (16)
# define EXP0_K_VALS \
1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768
# define EXP0_L_VALS \
20487, 30730, 28169, 9443, 13001, 12376, 8302, 6618, 38760, 21582, 1660, \
10409, 14669, 30338, 17745, 7520
# define EXP1_K_VALS 0, 1, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 8203
# define EXP1_L_VALS 0, 20487, 0, 15365, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6302, 0, 10058
#endif
void gf2x_mod_inv(OUT pad_r_t *c, IN const pad_r_t *a)
{
gf2x_ctx ctx;
gf2x_ctx_init(&ctx);
const size_t exp0_k[MAX_I] = {EXP0_K_VALS};
const size_t exp0_l[MAX_I] = {EXP0_L_VALS};
const size_t exp1_k[MAX_I] = {EXP1_K_VALS};
const size_t exp1_l[MAX_I] = {EXP1_L_VALS};
DEFER_CLEANUP(pad_r_t f = {0}, pad_r_cleanup);
DEFER_CLEANUP(pad_r_t g = {0}, pad_r_cleanup);
DEFER_CLEANUP(pad_r_t t = {0}, pad_r_cleanup);
DEFER_CLEANUP(dbl_pad_r_t sec_buf = {0}, dbl_pad_r_cleanup);
f.val = a->val;
t.val = a->val;
for(size_t i = 1; i < MAX_I; i++) {
if(exp0_k[i - 1] <= K_SQR_THR) {
repeated_squaring(&g, &f, exp0_k[i - 1], &sec_buf, &ctx);
} else {
ctx.k_sqr(&g, &f, exp0_l[i - 1]);
}
gf2x_mod_mul_with_ctx(&f, &g, &f, &ctx);
if(exp1_k[i] != 0) {
if(exp1_k[i] <= K_SQR_THR) {
repeated_squaring(&g, &f, exp1_k[i], &sec_buf, &ctx);
} else {
ctx.k_sqr(&g, &f, exp1_l[i]);
}
gf2x_mod_mul_with_ctx(&t, &g, &t, &ctx);
}
}
gf2x_mod_sqr_in_place(&t, &sec_buf, &ctx);
c->val = t.val;
}