use the Diffie-Hellman functionality of libstrongswan

This commit is contained in:
Andreas Steffen
2009-05-24 11:26:00 +02:00
parent 770b408902
commit 52ccea657b
12 changed files with 210 additions and 253 deletions
+24 -57
View File
@@ -122,37 +122,11 @@ echo_hdr(struct msg_digest *md, bool enc, u_int8_t np)
* We make the leap that the length should be that of the group
* (see quoted passage at start of ACCEPT_KE).
*/
static void compute_dh_shared(struct state *st, const chunk_t g,
const struct oakley_group_desc *group)
static void compute_dh_shared(struct state *st, const chunk_t g)
{
MP_INT mp_g, mp_shared;
struct timeval tv0, tv1;
unsigned long tv_diff;
gettimeofday(&tv0, NULL);
passert(st->st_sec_in_use);
n_to_mpz(&mp_g, g.ptr, g.len);
mpz_init(&mp_shared);
mpz_powm(&mp_shared, &mp_g, &st->st_sec, group->modulus);
mpz_clear(&mp_g);
free(st->st_shared.ptr); /* happens in odd error cases */
st->st_shared = mpz_to_n(&mp_shared, group->bytes);
mpz_clear(&mp_shared);
gettimeofday(&tv1, NULL);
tv_diff=(tv1.tv_sec - tv0.tv_sec) * 1000000 + (tv1.tv_usec - tv0.tv_usec);
DBG(DBG_CRYPT,
DBG_log("compute_dh_shared(): time elapsed (%s): %ld usec"
, enum_show(&oakley_group_names, st->st_oakley.group->group)
, tv_diff);
);
/* if took more than 200 msec ... */
if (tv_diff > 200000) {
loglog(RC_LOG_SERIOUS, "WARNING: compute_dh_shared(): for %s took "
"%ld usec"
, enum_show(&oakley_group_names, st->st_oakley.group->group)
, tv_diff);
}
passert(st->st_dh);
st->st_dh->set_other_public_value(st->st_dh, g);
st->st_dh->get_shared_secret(st->st_dh, &st->st_shared);
DBG_cond_dump_chunk(DBG_CRYPT, "DH shared secret:\n", st->st_shared);
}
@@ -160,30 +134,23 @@ static void compute_dh_shared(struct state *st, const chunk_t g,
* the corresponding public value (g). This is emitted as a KE payload.
*/
static bool build_and_ship_KE(struct state *st, chunk_t *g,
const struct oakley_group_desc *group,
const struct dh_desc *group,
pb_stream *outs, u_int8_t np)
{
if (!st->st_sec_in_use)
if (st->st_dh == NULL)
{
u_char tmp[LOCALSECRETSIZE];
MP_INT mp_g;
rng_t *rng;
rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG);
rng->get_bytes(rng, LOCALSECRETSIZE, tmp);
rng->destroy(rng);
st->st_sec_in_use = TRUE;
n_to_mpz(&st->st_sec, tmp, LOCALSECRETSIZE);
mpz_init(&mp_g);
mpz_powm(&mp_g, &groupgenerator, &st->st_sec, group->modulus);
free(g->ptr); /* happens in odd error cases */
*g = mpz_to_n(&mp_g, group->bytes);
mpz_clear(&mp_g);
DBG(DBG_CRYPT,
DBG_dump("Local DH secret:\n", tmp, LOCALSECRETSIZE);
DBG_dump_chunk("Public DH value sent:\n", *g));
st->st_dh = lib->crypto->create_dh(lib->crypto, group->algo_id);
if (st->st_dh == NULL)
{
plog("Diffie Hellman group %N is not available",
diffie_hellman_group_names, group->algo_id);
return FALSE;
}
}
st->st_dh->get_my_public_value(st->st_dh, g);
DBG(DBG_CRYPT,
DBG_dump_chunk("Public DH value sent:\n", *g)
)
return out_generic_chunk(np, &isakmp_keyex_desc, outs, *g, "keyex value");
}
@@ -197,13 +164,13 @@ static bool build_and_ship_KE(struct state *st, chunk_t *g,
* value with zeros.
*/
static notification_t accept_KE(chunk_t *dest, const char *val_name,
const struct oakley_group_desc *gr,
const struct dh_desc *gr,
pb_stream *pbs)
{
if (pbs_left(pbs) != gr->bytes)
if (pbs_left(pbs) != gr->modulus_size)
{
loglog(RC_LOG_SERIOUS, "KE has %u byte DH public value; %u required"
, (unsigned) pbs_left(pbs), (unsigned) gr->bytes);
, (unsigned) pbs_left(pbs), gr->modulus_size);
/* XXX Could send notification back */
return INVALID_KEY_INFORMATION;
}
@@ -3473,7 +3440,7 @@ stf_status main_inI2_outR2(struct msg_digest *md)
/* next message will be encrypted, but not this one.
* We could defer this calculation.
*/
compute_dh_shared(st, st->st_gi, st->st_oakley.group);
compute_dh_shared(st, st->st_gi);
if (!generate_skeyids_iv(st))
return STF_FAIL + AUTHENTICATION_FAILED;
update_iv(st);
@@ -3535,7 +3502,7 @@ stf_status main_inR2_outI3(struct msg_digest *md)
send_cr = !no_cr_send && send_cert && !has_preloaded_public_key(st);
/* done parsing; initialize crypto */
compute_dh_shared(st, st->st_gr, st->st_oakley.group);
compute_dh_shared(st, st->st_gr);
if (!generate_skeyids_iv(st))
return STF_FAIL + AUTHENTICATION_FAILED;
@@ -4946,7 +4913,7 @@ static stf_status quick_inI1_outR1_tail(struct verify_oppo_bundle *b,
return STF_INTERNAL_ERROR;
/* MPZ-Operations might be done after sending the packet... */
compute_dh_shared(st, st->st_gi, st->st_pfs_group);
compute_dh_shared(st, st->st_gi);
}
/* [ IDci, IDcr ] out */
@@ -5061,7 +5028,7 @@ stf_status quick_inR1_outI2(struct msg_digest *md)
RETURN_STF_FAILURE(accept_PFS_KE(md, &st->st_gr, "Gr", "Quick Mode R1"));
if (st->st_pfs_group != NULL)
compute_dh_shared(st, st->st_gr, st->st_pfs_group);
compute_dh_shared(st, st->st_gr);
/* [ IDci, IDcr ] in; these must match what we sent */