void DH_compute_key(DH_CTX *dh_ctx) { BI_CTX *bi_ctx = bi_initialize(); int len = dh_ctx->len; bigint *p = bi_import(bi_ctx, dh_ctx->p, len); //p modulus bigint *x = bi_import(bi_ctx, dh_ctx->x, len); //private key bigint *gy = bi_import(bi_ctx, dh_ctx->gy, len); //public key(peer) bigint *k; //negotiated(session) key bi_permanent(x); bi_permanent(gy); //calculate session key k = gy^x mod p bi_set_mod(bi_ctx, p, BIGINT_M_OFFSET); bi_ctx->mod_offset = BIGINT_M_OFFSET; k = bi_mod_power(bi_ctx, gy, x); bi_permanent(k); bi_export(bi_ctx, k, dh_ctx->k, len); bi_depermanent(x); bi_depermanent(gy); bi_depermanent(k); bi_free(bi_ctx, x); bi_free(bi_ctx, gy); bi_free(bi_ctx, k); bi_free_mod(bi_ctx, BIGINT_M_OFFSET); bi_terminate(bi_ctx); }
void DH_generate_key(DH_CTX *dh_ctx) { BI_CTX *bi_ctx = bi_initialize(); int len = dh_ctx->len; bigint *p = bi_import(bi_ctx, dh_ctx->p, len); //p modulus bigint *g = bi_import(bi_ctx, dh_ctx->g, dh_ctx->glen); //generator bigint *x, *gx; bi_permanent(g); //generate private key X get_random_NZ(len, dh_ctx->x); x = bi_import(bi_ctx, dh_ctx->x, len); bi_permanent(x); //calculate public key gx = g^x mod p bi_set_mod(bi_ctx, p, BIGINT_M_OFFSET); bi_ctx->mod_offset = BIGINT_M_OFFSET; gx = bi_mod_power(bi_ctx, g, x); bi_permanent(gx); bi_export(bi_ctx, x, dh_ctx->x, len); bi_export(bi_ctx, gx, dh_ctx->gx, len); bi_depermanent(g); bi_depermanent(x); bi_depermanent(gx); bi_free(bi_ctx, g); bi_free(bi_ctx, x); bi_free(bi_ctx, gx); bi_free_mod(bi_ctx, BIGINT_M_OFFSET); bi_terminate(bi_ctx); }
void RSA_priv_key_new(RSA_CTX **ctx, const uint8_t *modulus, int mod_len, const uint8_t *pub_exp, int pub_len, const uint8_t *priv_exp, int priv_len, const uint8_t *p, int p_len, const uint8_t *q, int q_len, const uint8_t *dP, int dP_len, const uint8_t *dQ, int dQ_len, const uint8_t *qInv, int qInv_len) { RSA_CTX *rsa_ctx; BI_CTX *bi_ctx; RSA_pub_key_new(ctx, modulus, mod_len, pub_exp, pub_len); rsa_ctx = *ctx; bi_ctx = rsa_ctx->bi_ctx; rsa_ctx->d = bi_import(bi_ctx, priv_exp, priv_len); bi_permanent(rsa_ctx->d); rsa_ctx->p = bi_import(bi_ctx, p, p_len); rsa_ctx->q = bi_import(bi_ctx, q, q_len); rsa_ctx->dP = bi_import(bi_ctx, dP, dP_len); rsa_ctx->dQ = bi_import(bi_ctx, dQ, dQ_len); rsa_ctx->qInv = bi_import(bi_ctx, qInv, qInv_len); bi_permanent(rsa_ctx->dP); bi_permanent(rsa_ctx->dQ); bi_permanent(rsa_ctx->qInv); bi_set_mod(bi_ctx, rsa_ctx->p, BIGINT_P_OFFSET); bi_set_mod(bi_ctx, rsa_ctx->q, BIGINT_Q_OFFSET); }
/** * @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 Start a new bigint context. * @return A bigint context. */ BI_CTX *ICACHE_FLASH_ATTR bi_initialize(void) { /* calloc() sets everything to zero */ BI_CTX *ctx = (BI_CTX *)os_zalloc(sizeof(BI_CTX)); /* the radix */ ctx->bi_radix = alloc(ctx, 2); ctx->bi_radix->comps[0] = 0; ctx->bi_radix->comps[1] = 1; bi_permanent(ctx->bi_radix); return ctx; }
/* * Work out g1, g3, g5, g7... etc for the sliding-window algorithm */ static void ICACHE_FLASH_ATTR precompute_slide_window(BI_CTX *ctx, int window, bigint *g1) { int k = 1, i; bigint *g2; for (i = 0; i < window - 1; i++) { /* compute 2^(window-1) */ k <<= 1; } ctx->g = (bigint **)os_malloc(k * sizeof(bigint *)); ctx->g[0] = bi_clone(ctx, g1); bi_permanent(ctx->g[0]); g2 = bi_residue(ctx, bi_square(ctx, ctx->g[0])); /* g^2 */ for (i = 1; i < k; i++) { ctx->g[i] = bi_residue(ctx, bi_multiply(ctx, ctx->g[i - 1], bi_copy(g2))); bi_permanent(ctx->g[i]); } bi_free(ctx, g2); ctx->window = k; }
void RSA_pub_key_new(RSA_CTX **ctx, const uint8_t *modulus, int mod_len, const uint8_t *pub_exp, int pub_len) { RSA_CTX *rsa_ctx; BI_CTX *bi_ctx = bi_initialize(); *ctx = (RSA_CTX *)calloc(1, sizeof(RSA_CTX)); rsa_ctx = *ctx; rsa_ctx->bi_ctx = bi_ctx; rsa_ctx->num_octets = (mod_len & 0xFFF0); rsa_ctx->m = bi_import(bi_ctx, modulus, mod_len); bi_set_mod(bi_ctx, rsa_ctx->m, BIGINT_M_OFFSET); rsa_ctx->e = bi_import(bi_ctx, pub_exp, pub_len); bi_permanent(rsa_ctx->e); }
void RSA_pub_key_new(RSA_CTX **ctx, const uint8_t *modulus, int mod_len, const uint8_t *pub_exp, int pub_len) { RSA_CTX *rsa_ctx; BI_CTX *bi_ctx; if (*ctx) /* if we load multiple certs, dump the old one */ RSA_free(*ctx); bi_ctx = bi_initialize(); *ctx = (RSA_CTX *) calloc(1, sizeof(RSA_CTX)); rsa_ctx = *ctx; rsa_ctx->bi_ctx = bi_ctx; rsa_ctx->num_octets = mod_len; rsa_ctx->m = bi_import(bi_ctx, modulus, mod_len); bi_set_mod(bi_ctx, rsa_ctx->m, BIGINT_M_OFFSET); rsa_ctx->e = bi_import(bi_ctx, pub_exp, pub_len); bi_permanent(rsa_ctx->e); }
/** * @brief Perform a modular exponentiation. * * This function requires bi_set_mod() to have been called previously. This is * one of the optimisations used for performance. * @param ctx [in] The bigint session context. * @param bi [in] The bigint on which to perform the mod power operation. * @param biexp [in] The bigint exponent. * @return The result of the mod exponentiation operation * @see bi_set_mod(). */ bigint * ICACHE_FLASH_ATTR bi_mod_power(BI_CTX *ctx, bigint *bi, bigint *biexp) { int i = find_max_exp_index(biexp), j, window_size = 1; bigint *biR = int_to_bi(ctx, 1); #if defined(CONFIG_BIGINT_MONTGOMERY) uint8_t mod_offset = ctx->mod_offset; if (!ctx->use_classical) { /* preconvert */ bi = bi_mont(ctx, bi_multiply(ctx, bi, ctx->bi_RR_mod_m[mod_offset])); /* x' */ bi_free(ctx, biR); biR = ctx->bi_R_mod_m[mod_offset]; /* A */ } #endif check(bi); check(biexp); #ifdef CONFIG_BIGINT_SLIDING_WINDOW for (j = i; j > 32; j /= 5) /* work out an optimum size */ window_size++; /* work out the slide constants */ precompute_slide_window(ctx, window_size, bi); #else /* just one constant */ ctx->g = (bigint **)SSL_MALLOC(sizeof(bigint *)); ctx->g[0] = bi_clone(ctx, bi); ctx->window = 1; bi_permanent(ctx->g[0]); #endif /* if sliding-window is off, then only one bit will be done at a time and * will reduce to standard left-to-right exponentiation */ do { if (exp_bit_is_one(biexp, i)) { int l = i-window_size+1; int part_exp = 0; if (l < 0) /* LSB of exponent will always be 1 */ l = 0; else { while (exp_bit_is_one(biexp, l) == 0) l++; /* go back up */ } /* build up the section of the exponent */ for (j = i; j >= l; j--) { biR = bi_residue(ctx, bi_square(ctx, biR)); if (exp_bit_is_one(biexp, j)) part_exp++; if (j != l) part_exp <<= 1; } part_exp = (part_exp-1)/2; /* adjust for array */ biR = bi_residue(ctx, bi_multiply(ctx, biR, ctx->g[part_exp])); i = l-1; } else /* square it */ { biR = bi_residue(ctx, bi_square(ctx, biR)); i--; } } while (i >= 0); /* cleanup */ for (i = 0; i < ctx->window; i++) { bi_depermanent(ctx->g[i]); bi_free(ctx, ctx->g[i]); } SSL_FREE(ctx->g); bi_free(ctx, bi); bi_free(ctx, biexp); #if defined CONFIG_BIGINT_MONTGOMERY return ctx->use_classical ? biR : bi_mont(ctx, biR); /* convert back */ #else /* CONFIG_BIGINT_CLASSICAL or CONFIG_BIGINT_BARRETT */ return biR; #endif }