X-Git-Url: https://git.distorted.org.uk/~mdw/secnet/blobdiff_plain/088f80a16f384041909c6df6c5fbc98c0d76427f..9c6af4eca6bfb7bed6f86b1f32479f933979c080:/site.c diff --git a/site.c b/site.c index 4f954e6..4da99e3 100644 --- a/site.c +++ b/site.c @@ -107,7 +107,7 @@ #define SITE_SENTMSG5 7 #define SITE_WAIT 8 -#define CASES_MSG3_KNOWN LABEL_MSG3: case LABEL_MSG3BIS +#define CASES_MSG3_KNOWN LABEL_MSG3: case LABEL_MSG3BIS: case LABEL_MSG3TER int32_t site_max_start_pad = 4*4; @@ -316,7 +316,8 @@ struct site { struct rsapubkey_if *pubkey; struct transform_if **transforms; int ntransforms; - struct dh_if *dh; + struct dh_if **dhs; + int ndhs; struct hash_if *hash; uint32_t index; /* Index of this site */ @@ -361,6 +362,7 @@ struct site { uint32_t remote_capabilities; uint16_t remote_adv_mtu; struct transform_if *chosen_transform; + struct dh_if *chosen_dh; uint32_t setup_session_id; transport_peers setup_peers; uint8_t localN[NONCELEN]; /* Nonces for key exchange */ @@ -528,6 +530,7 @@ struct msg { uint32_t remote_capabilities; uint16_t remote_mtu; int capab_transformnum; + int capab_dhnum; uint8_t *nR; uint8_t *nL; int32_t pklen; @@ -553,16 +556,20 @@ static _Bool set_new_transform(struct site *st, char *pk) /* Generate the shared key */ assert(!st->sharedsecret); - st->sharedsecret = safe_malloc(st->dh->shared_len, "site:sharedsecret"); - if (!st->dh->makeshared(st->dh->st,st->dhsecret,st->dh->secret_len, - pk, st->sharedsecret,st->dh->shared_len)) + st->sharedsecret = safe_malloc(st->chosen_dh->shared_len, + "site:sharedsecret"); + if (!st->chosen_dh->makeshared(st->chosen_dh->st, + st->dhsecret,st->chosen_dh->secret_len, + pk, + st->sharedsecret, + st->chosen_dh->shared_len)) return False; /* Set up the transform */ struct transform_if *generator=st->chosen_transform; struct transform_inst_if *generated=generator->create(generator->st); ok = generated->setkey(generated->st,st->sharedsecret, - st->dh->shared_len,st->our_name_later); + st->chosen_dh->shared_len,st->our_name_later); dispose_transform(&st->new_transform); if (!ok) return False; @@ -643,9 +650,12 @@ static bool_t generate_msg(struct site *st, uint32_t type, cstring_t what) minor = MSGMINOR(type); if (minor < 1) break; buf_append_uint8(&st->buffer,st->chosen_transform->capab_bit); + if (minor < 2) break; + buf_append_uint8(&st->buffer,st->chosen_dh->capab_bit); } while (0); - dhpub=st->dh->makepublic(st->dh->st,st->dhsecret,st->dh->secret_len); + dhpub=st->chosen_dh->makepublic(st->chosen_dh->st, + st->dhsecret,st->chosen_dh->secret_len); buf_append_string(&st->buffer,dhpub); free(dhpub); hash=safe_malloc(st->hash->len, "generate_msg"); @@ -680,7 +690,7 @@ static bool_t unpick_msg(struct site *st, uint32_t type, { unsigned minor; - m->capab_transformnum=-1; + m->capab_transformnum=m->capab_dhnum=-1; m->hashstart=msg->start; CHECK_AVAIL(msg,4); m->dest=buf_unprepend_uint32(msg); @@ -726,6 +736,7 @@ static bool_t unpick_msg(struct site *st, uint32_t type, } \ } while (0) MAYBE_READ_CAP(1, transform, CAPAB_BIT_ANCIENTTRANSFORM); + MAYBE_READ_CAP(2, dh, CAPAB_BIT_TRADZP); #undef MAYBE_READ_CAP } while (0); CHECK_AVAIL(msg,2); @@ -831,12 +842,17 @@ static bool_t process_msg2(struct site *st, struct buffer_if *msg2, st->setup_session_id=m.source; st->remote_capabilities=m.remote_capabilities; - /* Select the transform to use */ + /* Select the transform and DH group to use */ - uint32_t remote_crypto_caps = st->remote_capabilities & CAPAB_TRANSFORM_MASK; + uint32_t remote_crypto_caps = st->remote_capabilities; + if (!(remote_crypto_caps & CAPAB_EXPLICIT_TRANSFORM_DH)) + remote_crypto_caps &= CAPAB_INEXPLICIT_TRANSFORM_MASK; if (!remote_crypto_caps) /* old secnets only had this one transform */ remote_crypto_caps = 1UL << CAPAB_BIT_ANCIENTTRANSFORM; + if (!(remote_crypto_caps & CAPAB_EXPLICIT_TRANSFORM_DH)) + /* old secnets only had this one kind of group */ + remote_crypto_caps |= 1UL << CAPAB_BIT_TRADZP; #define CHOOSE_CRYPTO(kind, whats) do { \ struct kind##_if *iface; \ @@ -857,6 +873,7 @@ kind##_found: \ } while (0) CHOOSE_CRYPTO(transform, "transforms"); + CHOOSE_CRYPTO(dh, "Diffie--Hellman groups"); #undef CHOOSE_CRYPTO @@ -866,9 +883,14 @@ kind##_found: \ static void generate_dhsecret(struct site *st) { + slog(st,LOG_SETUP_INIT,"key exchange negotiated DH group" + " %d (capabilities ours=%#"PRIx32" theirs=%#"PRIx32")", + st->chosen_dh->capab_bit, + st->local_capabilities, st->remote_capabilities); assert(!st->dhsecret); - st->dhsecret = safe_malloc(st->dh->secret_len, "site:dhsecret"); - st->random->generate(st->random->st, st->dh->secret_len,st->dhsecret); + st->dhsecret = safe_malloc(st->chosen_dh->secret_len, "site:dhsecret"); + st->random->generate(st->random->st, + st->chosen_dh->secret_len,st->dhsecret); } static bool_t generate_msg3(struct site *st) @@ -877,7 +899,11 @@ static bool_t generate_msg3(struct site *st) and create message number 3. */ generate_dhsecret(st); return generate_msg(st, - (st->remote_capabilities & CAPAB_TRANSFORM_MASK) + (st->remote_capabilities & + CAPAB_EXPLICIT_TRANSFORM_DH) + ? LABEL_MSG3TER + : (st->remote_capabilities & + CAPAB_INEXPLICIT_TRANSFORM_MASK) ? LABEL_MSG3BIS : LABEL_MSG3, "site:MSG3"); @@ -949,6 +975,7 @@ kind##_found: \ } while (0) CHOSE_CRYPTO(transform, "transform"); + CHOSE_CRYPTO(dh, "Diffie--Hellman group"); #undef CHOSE_CRYPTO @@ -1520,12 +1547,12 @@ static void enter_state_run(struct site *st) FILLZERO(st->remoteN); dispose_transform(&st->new_transform); if (st->dhsecret) { - memset(st->dhsecret, 0, st->dh->secret_len); + memset(st->dhsecret, 0, st->chosen_dh->secret_len); free(st->dhsecret); st->dhsecret = 0; } if (st->sharedsecret) { - memset(st->sharedsecret, 0, st->dh->shared_len); + memset(st->sharedsecret, 0, st->chosen_dh->shared_len); free(st->sharedsecret); st->sharedsecret = 0; } @@ -2151,7 +2178,7 @@ static list_t *site_apply(closure_t *self, struct cloc loc, dict_t *context, assert(index_sequence < 0xffffffffUL); st->index = ++index_sequence; - st->local_capabilities = 0; + st->local_capabilities = CAPAB_EXPLICIT_TRANSFORM_DH; st->early_capabilities = CAPAB_PRIORITY_MOBILE; st->netlink=find_cl_if(dict,"link",CL_NETLINK,True,"site",loc); @@ -2195,8 +2222,8 @@ static list_t *site_apply(closure_t *self, struct cloc loc, dict_t *context, st->pubkey=find_cl_if(dict,"key",CL_RSAPUBKEY,True,"site",loc); GET_CLOSURE_LIST("transform",transforms,ntransforms,CL_TRANSFORM); + GET_CLOSURE_LIST("dh",dhs,ndhs,CL_DH); - st->dh=find_cl_if(dict,"dh",CL_DH,True,"site",loc); st->hash=find_cl_if(dict,"hash",CL_HASH,True,"site",loc); #define DEFAULT(D) (st->peer_mobile || st->local_mobile \ @@ -2260,6 +2287,7 @@ static list_t *site_apply(closure_t *self, struct cloc loc, dict_t *context, st->remote_capabilities=0; st->chosen_transform=0; + st->chosen_dh=0; st->current.key_timeout=0; st->auxiliary_key.key_timeout=0; transport_peers_clear(st,&st->peers); @@ -2277,6 +2305,8 @@ static list_t *site_apply(closure_t *self, struct cloc loc, dict_t *context, for (i=0; intransforms; i++) SET_CAPBIT(st->transforms[i]->capab_bit); + for (i=0; indhs; i++) + SET_CAPBIT(st->dhs[i]->capab_bit); #undef SET_CAPBIT