/** * @brief Pre-calculate some of the expensive steps in reduction. * * This function should only be called once (normally when a session starts). * When the session is over, bi_free_mod() should be called. bi_mod_power() * relies on this function being called. * @param ctx [in] The bigint session context. * @param bim [in] The bigint modulus that will be used. * @param mod_offset [in] There are three moduluii that can be stored - the * standard modulus, and its two primes p and q. This offset refers to which * modulus we are referring to. * @see bi_free_mod(), bi_mod_power(). */ void ICACHE_FLASH_ATTR bi_set_mod(BI_CTX *ctx, bigint *bim, int mod_offset) { int k = bim->size; comp d = (comp)((long_comp)COMP_RADIX/(bim->comps[k-1]+1)); #ifdef CONFIG_BIGINT_MONTGOMERY bigint *R, *R2; #endif ctx->bi_mod[mod_offset] = bim; bi_permanent(ctx->bi_mod[mod_offset]); ctx->bi_normalised_mod[mod_offset] = bi_int_multiply(ctx, bim, d); bi_permanent(ctx->bi_normalised_mod[mod_offset]); #if defined(CONFIG_BIGINT_MONTGOMERY) /* set montgomery variables */ R = comp_left_shift(bi_clone(ctx, ctx->bi_radix), k-1); /* R */ R2 = comp_left_shift(bi_clone(ctx, ctx->bi_radix), k*2-1); /* R^2 */ ctx->bi_RR_mod_m[mod_offset] = bi_mod(ctx, R2); /* R^2 mod m */ ctx->bi_R_mod_m[mod_offset] = bi_mod(ctx, R); /* R mod m */ bi_permanent(ctx->bi_RR_mod_m[mod_offset]); bi_permanent(ctx->bi_R_mod_m[mod_offset]); ctx->N0_dash[mod_offset] = modular_inverse(ctx->bi_mod[mod_offset]); #elif defined (CONFIG_BIGINT_BARRETT) ctx->bi_mu[mod_offset] = bi_divide(ctx, comp_left_shift( bi_clone(ctx, ctx->bi_radix), k*2-1), ctx->bi_mod[mod_offset], 0); bi_permanent(ctx->bi_mu[mod_offset]); #endif }
/** * @brief Perform a single Barrett reduction. * @param ctx [in] The bigint session context. * @param bi [in] A bigint. * @return The result of the Barrett reduction. */ bigint * ICACHE_FLASH_ATTR bi_barrett(BI_CTX *ctx, bigint *bi) { bigint *q1, *q2, *q3, *r1, *r2, *r; uint8_t mod_offset = ctx->mod_offset; bigint *bim = ctx->bi_mod[mod_offset]; int k = bim->size; check(bi); check(bim); /* use Classical method instead - Barrett cannot help here */ if (bi->size > k*2) { return bi_mod(ctx, bi); } q1 = comp_right_shift(bi_clone(ctx, bi), k-1); /* do outer partial multiply */ q2 = regular_multiply(ctx, q1, ctx->bi_mu[mod_offset], 0, k-1); q3 = comp_right_shift(q2, k+1); r1 = comp_mod(bi, k+1); /* do inner partial multiply */ r2 = comp_mod(regular_multiply(ctx, q3, bim, k+1, 0), k+1); r = bi_subtract(ctx, r1, r2, NULL); /* if (r >= m) r = r - m; */ if (bi_compare(r, bim) >= 0) { r = bi_subtract(ctx, r, bim, NULL); } return r; }
/** * @brief Perform a single montgomery reduction. * @param ctx [in] The bigint session context. * @param bixy [in] A bigint. * @return The result of the montgomery reduction. */ bigint * ICACHE_FLASH_ATTR bi_mont(BI_CTX *ctx, bigint *bixy) { int i = 0, n; uint8_t mod_offset = ctx->mod_offset; bigint *bim = ctx->bi_mod[mod_offset]; comp mod_inv = ctx->N0_dash[mod_offset]; check(bixy); if (ctx->use_classical) /* just use classical instead */ { return bi_mod(ctx, bixy); } n = bim->size; do { bixy = bi_add(ctx, bixy, comp_left_shift( bi_int_multiply(ctx, bim, bixy->comps[i]*mod_inv), i)); } while (++i < n); comp_right_shift(bixy, n); if (bi_compare(bixy, bim) >= 0) { bixy = bi_subtract(ctx, bixy, bim, NULL); } return bixy; }
inline bi_ptr apply_challenge( bi_ptr value, bi_ptr delta, bi_ptr c, bi_ptr capital_gamma) { bi_ptr delta_tilde = bi_new_ptr(); bi_t c_negate; if( delta_tilde == NULL) return NULL; bi_new( c_negate); bi_set( c_negate, c); bi_negate( c_negate); // delta_tilde = ( delta ^ (-c)) % capital_gamma bi_mod_exp( delta_tilde, delta, c_negate, capital_gamma); bi_free( c_negate); // delta_tilde = (delta_tilde * value) % capital_gamma return bi_mod( delta_tilde, bi_mul( delta_tilde, delta_tilde, value), capital_gamma); }