Hi,
now that we finally have AES-GCM in IKE and ESP I would like to add them as
defaults.
This is a bit more complicated than one might think because AEADs and non-AEADs
can not be sent in the same proposal. Instead we must send one proposal
for each and adjust the config parser a bit.
Test feedback welcome. ok?
diff --git a/sbin/iked/parse.y b/sbin/iked/parse.y
index 2cb00c29833..b92a4306e5d 100644
--- a/sbin/iked/parse.y
+++ b/sbin/iked/parse.y
@@ -159,6 +159,28 @@ struct iked_transform ikev2_default_ike_transforms[] = {
size_t ikev2_default_nike_transforms = ((sizeof(ikev2_default_ike_transforms) /
sizeof(ikev2_default_ike_transforms[0])) - 1);
+struct iked_transform ikev2_default_ike_transforms_noauth[] = {
+ { IKEV2_XFORMTYPE_ENCR, IKEV2_XFORMENCR_AES_GCM_16, 256 },
+ { IKEV2_XFORMTYPE_ENCR, IKEV2_XFORMENCR_AES_GCM_16, 128 },
+ { IKEV2_XFORMTYPE_PRF, IKEV2_XFORMPRF_HMAC_SHA2_512 },
+ { IKEV2_XFORMTYPE_PRF, IKEV2_XFORMPRF_HMAC_SHA2_384 },
+ { IKEV2_XFORMTYPE_PRF, IKEV2_XFORMPRF_HMAC_SHA2_256 },
+ { IKEV2_XFORMTYPE_PRF, IKEV2_XFORMPRF_HMAC_SHA1 },
+ { IKEV2_XFORMTYPE_DH, IKEV2_XFORMDH_CURVE25519 },
+ { IKEV2_XFORMTYPE_DH, IKEV2_XFORMDH_ECP_521 },
+ { IKEV2_XFORMTYPE_DH, IKEV2_XFORMDH_ECP_384 },
+ { IKEV2_XFORMTYPE_DH, IKEV2_XFORMDH_ECP_256 },
+ { IKEV2_XFORMTYPE_DH, IKEV2_XFORMDH_MODP_4096 },
+ { IKEV2_XFORMTYPE_DH, IKEV2_XFORMDH_MODP_3072 },
+ { IKEV2_XFORMTYPE_DH, IKEV2_XFORMDH_MODP_2048 },
+ { IKEV2_XFORMTYPE_DH, IKEV2_XFORMDH_MODP_1536 },
+ { IKEV2_XFORMTYPE_DH, IKEV2_XFORMDH_MODP_1024 },
+ { 0 }
+};
+size_t ikev2_default_nike_transforms_noauth =
+ ((sizeof(ikev2_default_ike_transforms_noauth) /
+ sizeof(ikev2_default_ike_transforms_noauth[0])) - 1);
+
struct iked_transform ikev2_default_esp_transforms[] = {
{ IKEV2_XFORMTYPE_ENCR, IKEV2_XFORMENCR_AES_CBC, 256 },
{ IKEV2_XFORMTYPE_ENCR, IKEV2_XFORMENCR_AES_CBC, 192 },
@@ -172,6 +194,17 @@ struct iked_transform ikev2_default_esp_transforms[] = {
size_t ikev2_default_nesp_transforms = ((sizeof(ikev2_default_esp_transforms) /
sizeof(ikev2_default_esp_transforms[0])) - 1);
+struct iked_transform ikev2_default_esp_transforms_noauth[] = {
+ { IKEV2_XFORMTYPE_ENCR, IKEV2_XFORMENCR_AES_GCM_16, 256 },
+ { IKEV2_XFORMTYPE_ENCR, IKEV2_XFORMENCR_AES_GCM_16, 128 },
+ { IKEV2_XFORMTYPE_ESN, IKEV2_XFORMESN_ESN },
+ { IKEV2_XFORMTYPE_ESN, IKEV2_XFORMESN_NONE },
+ { 0 }
+};
+size_t ikev2_default_nesp_transforms_noauth =
+ ((sizeof(ikev2_default_esp_transforms_noauth) /
+ sizeof(ikev2_default_esp_transforms_noauth[0])) - 1);
+
const struct ipsec_xf authxfs[] = {
{ "hmac-md5", IKEV2_XFORMAUTH_HMAC_MD5_96, 16 },
{ "hmac-sha1", IKEV2_XFORMAUTH_HMAC_SHA1_96, 20 },
@@ -2727,7 +2760,7 @@ create_ike(char *name, int af, uint8_t ipproto,
struct iked_policy pol;
struct iked_proposal *p, *ptmp;
struct iked_transform *xf;
- unsigned int i, j, xfi, noauth;
+ unsigned int i, j, xfi, noauth, auth;
unsigned int ikepropid = 1, ipsecpropid = 1;
struct iked_flow *flow, *ftmp;
static unsigned int policy_id = 0;
@@ -2857,6 +2890,17 @@ create_ike(char *name, int af, uint8_t ipproto,
RB_INIT(&pol.pol_flows);
if (ike_sa == NULL || ike_sa->nxfs == 0) {
+ /* AES-GCM proposal */
+ if ((p = calloc(1, sizeof(*p))) == NULL)
+ err(1, "%s", __func__);
+ p->prop_id = ikepropid++;
+ p->prop_protoid = IKEV2_SAPROTO_IKE;
+ p->prop_nxforms = ikev2_default_nike_transforms_noauth;
+ p->prop_xforms = ikev2_default_ike_transforms_noauth;
+ TAILQ_INSERT_TAIL(&pol.pol_proposals, p, prop_entry);
+ pol.pol_nproposals++;
+
+ /* Non GCM proposal */
if ((p = calloc(1, sizeof(*p))) == NULL)
err(1, "%s", __func__);
p->prop_id = ikepropid++;
@@ -2867,11 +2911,16 @@ create_ike(char *name, int af, uint8_t ipproto,
pol.pol_nproposals++;
} else {
for (i = 0; i < ike_sa->nxfs; i++) {
- noauth = 0;
+ noauth = auth = 0;
for (j = 0; j < ike_sa->xfs[i]->nencxf; j++) {
if (ike_sa->xfs[i]->encxf[j]->noauth)
noauth++;
+ else
+ auth++;
}
+ if (ike_sa->xfs[i]->nauthxf)
+ auth++;
+
if (ike_sa->xfs[i]->nesnxf) {
yyerror("cannot use ESN with ikesa.");
goto done;
@@ -2887,43 +2936,82 @@ create_ike(char *name, int af, uint8_t ipproto,
goto done;
}
- if ((p = calloc(1, sizeof(*p))) == NULL)
- err(1, "%s", __func__);
+ if (!auth) {
+ if ((p = calloc(1, sizeof(*p))) == NULL)
+ err(1, "%s", __func__);
+
+ xf = NULL;
+ xfi = 0;
+ copy_transforms(IKEV2_XFORMTYPE_ENCR,
+ ike_sa->xfs[i]->encxf,
+ ike_sa->xfs[i]->nencxf, &xf, &xfi,
+ ikev2_default_ike_transforms_noauth,
+ ikev2_default_nike_transforms_noauth);
+ copy_transforms(IKEV2_XFORMTYPE_DH,
+ ike_sa->xfs[i]->groupxf,
+ ike_sa->xfs[i]->ngroupxf, &xf, &xfi,
+ ikev2_default_ike_transforms_noauth,
+ ikev2_default_nike_transforms_noauth);
+ copy_transforms(IKEV2_XFORMTYPE_PRF,
+ ike_sa->xfs[i]->prfxf,
+ ike_sa->xfs[i]->nprfxf, &xf, &xfi,
+ ikev2_default_ike_transforms_noauth,
+ ikev2_default_nike_transforms_noauth);
+
+ p->prop_id = ikepropid++;
+ p->prop_protoid = IKEV2_SAPROTO_IKE;
+ p->prop_xforms = xf;
+ p->prop_nxforms = xfi;
+ TAILQ_INSERT_TAIL(&pol.pol_proposals, p,
prop_entry);
+ pol.pol_nproposals++;
+ }
+ if (!noauth) {
+ if ((p = calloc(1, sizeof(*p))) == NULL)
+ err(1, "%s", __func__);
- xf = NULL;
- xfi = 0;
- if (!ike_sa->xfs[i]->nencxf || !noauth)
+ xf = NULL;
+ xfi = 0;
copy_transforms(IKEV2_XFORMTYPE_INTEGR,
ike_sa->xfs[i]->authxf,
ike_sa->xfs[i]->nauthxf, &xf, &xfi,
ikev2_default_ike_transforms,
ikev2_default_nike_transforms);
- copy_transforms(IKEV2_XFORMTYPE_ENCR,
- ike_sa->xfs[i]->encxf,
- ike_sa->xfs[i]->nencxf, &xf, &xfi,
- ikev2_default_ike_transforms,
- ikev2_default_nike_transforms);
- copy_transforms(IKEV2_XFORMTYPE_DH,
- ike_sa->xfs[i]->groupxf,
- ike_sa->xfs[i]->ngroupxf, &xf, &xfi,
- ikev2_default_ike_transforms,
- ikev2_default_nike_transforms);
- copy_transforms(IKEV2_XFORMTYPE_PRF,
- ike_sa->xfs[i]->prfxf,
- ike_sa->xfs[i]->nprfxf, &xf, &xfi,
- ikev2_default_ike_transforms,
- ikev2_default_nike_transforms);
-
- p->prop_id = ikepropid++;
- p->prop_protoid = IKEV2_SAPROTO_IKE;
- p->prop_xforms = xf;
- p->prop_nxforms = xfi;
- TAILQ_INSERT_TAIL(&pol.pol_proposals, p, prop_entry);
- pol.pol_nproposals++;
+ copy_transforms(IKEV2_XFORMTYPE_ENCR,
+ ike_sa->xfs[i]->encxf,
+ ike_sa->xfs[i]->nencxf, &xf, &xfi,
+ ikev2_default_ike_transforms,
+ ikev2_default_nike_transforms);
+ copy_transforms(IKEV2_XFORMTYPE_DH,
+ ike_sa->xfs[i]->groupxf,
+ ike_sa->xfs[i]->ngroupxf, &xf, &xfi,
+ ikev2_default_ike_transforms,
+ ikev2_default_nike_transforms);
+ copy_transforms(IKEV2_XFORMTYPE_PRF,
+ ike_sa->xfs[i]->prfxf,
+ ike_sa->xfs[i]->nprfxf, &xf, &xfi,
+ ikev2_default_ike_transforms,
+ ikev2_default_nike_transforms);
+
+ p->prop_id = ikepropid++;
+ p->prop_protoid = IKEV2_SAPROTO_IKE;
+ p->prop_xforms = xf;
+ p->prop_nxforms = xfi;
+ TAILQ_INSERT_TAIL(&pol.pol_proposals, p,
prop_entry);
+ pol.pol_nproposals++;
+ }
}
}
if (ipsec_sa == NULL || ipsec_sa->nxfs == 0) {
+ if ((p = calloc(1, sizeof(*p))) == NULL)
+ err(1, "%s", __func__);
+ p->prop_id = ipsecpropid++;
+ p->prop_protoid = saproto;
+ p->prop_nxforms = ikev2_default_nesp_transforms_noauth;
+ p->prop_xforms = ikev2_default_esp_transforms_noauth;
+ TAILQ_INSERT_TAIL(&pol.pol_proposals, p, prop_entry);
+ pol.pol_nproposals++;
+
if ((p = calloc(1, sizeof(*p))) == NULL)
err(1, "%s", __func__);
p->prop_id = ipsecpropid++;
@@ -2934,11 +3022,16 @@ create_ike(char *name, int af, uint8_t ipproto,
pol.pol_nproposals++;
} else {
for (i = 0; i < ipsec_sa->nxfs; i++) {
- noauth = 0;
+ noauth = auth = 0;
for (j = 0; j < ipsec_sa->xfs[i]->nencxf; j++) {
if (ipsec_sa->xfs[i]->encxf[j]->noauth)
noauth++;
+ else
+ auth++;
}
+ if (ipsec_sa->xfs[i]->nauthxf)
+ auth++;
+
if (noauth && noauth != ipsec_sa->xfs[i]->nencxf) {
yyerror("cannot mix encryption transforms with "
"implicit and non-implicit authentication");
@@ -2950,39 +3043,69 @@ create_ike(char *name, int af, uint8_t ipproto,
goto done;
}
- if ((p = calloc(1, sizeof(*p))) == NULL)
- err(1, "%s", __func__);
+ if (!auth) {
+ if ((p = calloc(1, sizeof(*p))) == NULL)
+ err(1, "%s", __func__);
+
+ xf = NULL;
+ xfi = 0;
+ copy_transforms(IKEV2_XFORMTYPE_ENCR,
+ ipsec_sa->xfs[i]->encxf,
+ ipsec_sa->xfs[i]->nencxf, &xf, &xfi,
+ ikev2_default_esp_transforms_noauth,
+ ikev2_default_nesp_transforms_noauth);
+ copy_transforms(IKEV2_XFORMTYPE_DH,
+ ipsec_sa->xfs[i]->groupxf,
+ ipsec_sa->xfs[i]->ngroupxf, &xf, &xfi,
+ ikev2_default_esp_transforms_noauth,
+ ikev2_default_nesp_transforms_noauth);
+ copy_transforms(IKEV2_XFORMTYPE_ESN,
+ ipsec_sa->xfs[i]->esnxf,
+ ipsec_sa->xfs[i]->nesnxf, &xf, &xfi,
+ ikev2_default_esp_transforms_noauth,
+ ikev2_default_nesp_transforms_noauth);
+
+ p->prop_id = ipsecpropid++;
+ p->prop_protoid = saproto;
+ p->prop_xforms = xf;
+ p->prop_nxforms = xfi;
+ TAILQ_INSERT_TAIL(&pol.pol_proposals, p,
prop_entry);
+ pol.pol_nproposals++;
+ }
+ if (!noauth) {
+ if ((p = calloc(1, sizeof(*p))) == NULL)
+ err(1, "%s", __func__);
- xf = NULL;
- xfi = 0;
- if (!ipsec_sa->xfs[i]->nencxf || !noauth)
+ xf = NULL;
+ xfi = 0;
copy_transforms(IKEV2_XFORMTYPE_INTEGR,
ipsec_sa->xfs[i]->authxf,
ipsec_sa->xfs[i]->nauthxf, &xf, &xfi,
ikev2_default_esp_transforms,
ikev2_default_nesp_transforms);
- copy_transforms(IKEV2_XFORMTYPE_ENCR,
- ipsec_sa->xfs[i]->encxf,
- ipsec_sa->xfs[i]->nencxf, &xf, &xfi,
- ikev2_default_esp_transforms,
- ikev2_default_nesp_transforms);
- copy_transforms(IKEV2_XFORMTYPE_DH,
- ipsec_sa->xfs[i]->groupxf,
- ipsec_sa->xfs[i]->ngroupxf, &xf, &xfi,
- ikev2_default_esp_transforms,
- ikev2_default_nesp_transforms);
- copy_transforms(IKEV2_XFORMTYPE_ESN,
- ipsec_sa->xfs[i]->esnxf,
- ipsec_sa->xfs[i]->nesnxf, &xf, &xfi,
- ikev2_default_esp_transforms,
- ikev2_default_nesp_transforms);
-
- p->prop_id = ipsecpropid++;
- p->prop_protoid = saproto;
- p->prop_xforms = xf;
- p->prop_nxforms = xfi;
- TAILQ_INSERT_TAIL(&pol.pol_proposals, p, prop_entry);
- pol.pol_nproposals++;
+ copy_transforms(IKEV2_XFORMTYPE_ENCR,
+ ipsec_sa->xfs[i]->encxf,
+ ipsec_sa->xfs[i]->nencxf, &xf, &xfi,
+ ikev2_default_esp_transforms,
+ ikev2_default_nesp_transforms);
+ copy_transforms(IKEV2_XFORMTYPE_DH,
+ ipsec_sa->xfs[i]->groupxf,
+ ipsec_sa->xfs[i]->ngroupxf, &xf, &xfi,
+ ikev2_default_esp_transforms,
+ ikev2_default_nesp_transforms);
+ copy_transforms(IKEV2_XFORMTYPE_ESN,
+ ipsec_sa->xfs[i]->esnxf,
+ ipsec_sa->xfs[i]->nesnxf, &xf, &xfi,
+ ikev2_default_esp_transforms,
+ ikev2_default_nesp_transforms);
+
+ p->prop_id = ipsecpropid++;
+ p->prop_protoid = saproto;
+ p->prop_xforms = xf;
+ p->prop_nxforms = xfi;
+ TAILQ_INSERT_TAIL(&pol.pol_proposals, p,
prop_entry);
+ pol.pol_nproposals++;
+ }
}
}
@@ -3099,7 +3222,9 @@ done:
}
TAILQ_FOREACH_SAFE(p, &pol.pol_proposals, prop_entry, ptmp) {
if (p->prop_xforms != ikev2_default_ike_transforms &&
- p->prop_xforms != ikev2_default_esp_transforms)
+ p->prop_xforms != ikev2_default_ike_transforms_noauth &&
+ p->prop_xforms != ikev2_default_esp_transforms &&
+ p->prop_xforms != ikev2_default_esp_transforms_noauth)
free(p->prop_xforms);
free(p);
}