summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Belopuhov <mikeb@cvs.openbsd.org>2010-09-09 13:06:47 +0000
committerMike Belopuhov <mikeb@cvs.openbsd.org>2010-09-09 13:06:47 +0000
commit493711f6cd315f0e7960b26c8f106ca234232bb9 (patch)
treea870a498d4958e6eb3db2ed93f3f3ba125f0bee6
parent507a27332a3bb61164670eb5c8f524f89a32dc31 (diff)
- allow esp proposals without integrity and ah proposals without
encryption; - add additional nonce length field, use that for the ciphers that require additional keying material; - setup right flow direction depending on the mode: fixes up iked working as an initiator against charon. tested by me and jsg. ok reyk
-rw-r--r--sbin/iked/iked.h3
-rw-r--r--sbin/iked/ikev2.c68
-rw-r--r--sbin/iked/parse.y20
3 files changed, 68 insertions, 23 deletions
diff --git a/sbin/iked/iked.h b/sbin/iked/iked.h
index 75f8011e014..95f4f40c03a 100644
--- a/sbin/iked/iked.h
+++ b/sbin/iked/iked.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: iked.h,v 1.18 2010/07/01 02:15:08 reyk Exp $ */
+/* $OpenBSD: iked.h,v 1.19 2010/09/09 13:06:46 mikeb Exp $ */
/* $vantronix: iked.h,v 1.61 2010/06/03 07:57:33 reyk Exp $ */
/*
@@ -772,5 +772,6 @@ int parse_config(const char *, struct iked *);
void print_user(struct iked_user *);
void print_policy(struct iked_policy *);
size_t keylength_xf(u_int, u_int, u_int);
+size_t noncelength_xf(u_int, u_int);
#endif /* _IKED_H */
diff --git a/sbin/iked/ikev2.c b/sbin/iked/ikev2.c
index 2e074397a8b..5d7245e3351 100644
--- a/sbin/iked/ikev2.c
+++ b/sbin/iked/ikev2.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ikev2.c,v 1.23 2010/07/29 14:41:21 jsg Exp $ */
+/* $OpenBSD: ikev2.c,v 1.24 2010/09/09 13:06:46 mikeb Exp $ */
/* $vantronix: ikev2.c,v 1.101 2010/06/03 07:57:33 reyk Exp $ */
/*
@@ -2257,13 +2257,18 @@ ikev2_sa_negotiate(struct iked_sa *sa, struct iked_proposals *local,
(i == IKEV2_XFORMTYPE_DH))) {
match_score = 0;
break;
- } else if (protoid != IKEV2_SAPROTO_IKE &&
+ } else if (protoid == IKEV2_SAPROTO_AH &&
(match[i] == NULL) && (
- (i == IKEV2_XFORMTYPE_ENCR) ||
(i == IKEV2_XFORMTYPE_INTEGR) ||
(i == IKEV2_XFORMTYPE_ESN))) {
match_score = 0;
break;
+ } else if (protoid == IKEV2_SAPROTO_ESP &&
+ (match[i] == NULL) && (
+ (i == IKEV2_XFORMTYPE_ENCR) ||
+ (i == IKEV2_XFORMTYPE_ESN))) {
+ match_score = 0;
+ break;
} else if (match[i] == NULL)
continue;
@@ -2956,6 +2961,9 @@ ikev2_childsa_negotiate(struct iked *env, struct iked_sa *sa,
if (xform->xform_length)
xform->xform_keylength =
xform->xform_length;
+ xform->xform_keylength +=
+ noncelength_xf(xform->xform_type,
+ xform->xform_id);
ilen += xform->xform_keylength / 8;
break;
}
@@ -3036,7 +3044,8 @@ ikev2_childsa_negotiate(struct iked *env, struct iked_sa *sa,
}
memcpy(flowa, flow, sizeof(*flow));
- flowa->flow_dir = IPSP_DIRECTION_IN;
+ flowa->flow_dir = sa->sa_hdr.sh_initiator ?
+ IPSP_DIRECTION_OUT : IPSP_DIRECTION_IN;
flowa->flow_saproto = prop->prop_protoid;
flowa->flow_srcid = localid;
flowa->flow_dstid = peerid;
@@ -3056,7 +3065,8 @@ ikev2_childsa_negotiate(struct iked *env, struct iked_sa *sa,
memcpy(flowb, flowa, sizeof(*flow));
- flowb->flow_dir = IPSP_DIRECTION_OUT;
+ flowb->flow_dir = sa->sa_hdr.sh_initiator ?
+ IPSP_DIRECTION_IN : IPSP_DIRECTION_OUT;
memcpy(&flowb->flow_src, &flow->flow_dst,
sizeof(flow->flow_dst));
memcpy(&flowb->flow_dst, &flow->flow_src,
@@ -3105,11 +3115,17 @@ ikev2_childsa_negotiate(struct iked *env, struct iked_sa *sa,
csa->csa_allocated = 1;
}
- if ((csa->csa_encrkey = ibuf_copy(keymat,
- encrxf->xform_keylength / 8)) == NULL ||
- (csa->csa_integrkey = ibuf_copy(keymat,
+ if (encrxf && (csa->csa_encrkey = ibuf_copy(keymat,
+ encrxf->xform_keylength / 8)) == NULL) {
+ log_debug("%s: failed to get CHILD SA encryption key",
+ __func__);
+ childsa_free(csa);
+ goto done;
+ }
+ if (integrxf && (csa->csa_integrkey = ibuf_copy(keymat,
integrxf->xform_keylength / 8)) == NULL) {
- log_debug("%s: failed to get CHILD SA keys", __func__);
+ log_debug("%s: failed to get CHILD SA integrity key",
+ __func__);
childsa_free(csa);
goto done;
}
@@ -3132,11 +3148,17 @@ ikev2_childsa_negotiate(struct iked *env, struct iked_sa *sa,
csb->csa_local = csa->csa_peer;
csb->csa_peer = csa->csa_local;
- if ((csb->csa_encrkey = ibuf_copy(keymat,
- encrxf->xform_keylength / 8)) == NULL ||
- (csb->csa_integrkey = ibuf_copy(keymat,
+ if (encrxf && (csb->csa_encrkey = ibuf_copy(keymat,
+ encrxf->xform_keylength / 8)) == NULL) {
+ log_debug("%s: failed to get CHILD SA encryption key",
+ __func__);
+ childsa_free(csb);
+ goto done;
+ }
+ if (integrxf && (csb->csa_integrkey = ibuf_copy(keymat,
integrxf->xform_keylength / 8)) == NULL) {
- log_debug("%s: failed to get CHILD SA keys", __func__);
+ log_debug("%s: failed to get CHILD SA integrity key",
+ __func__);
childsa_free(csb);
goto done;
}
@@ -3273,16 +3295,22 @@ ikev2_valid_proposal(struct iked_proposal *prop,
encrxf = integrxf = NULL;
for (i = 0; i < prop->prop_nxforms; i++) {
xform = prop->prop_xforms + i;
- if (xform->xform_type ==
- IKEV2_XFORMTYPE_ENCR)
+ if (xform->xform_type == IKEV2_XFORMTYPE_ENCR)
encrxf = xform;
- else if (xform->xform_type ==
- IKEV2_XFORMTYPE_INTEGR)
+ else if (xform->xform_type == IKEV2_XFORMTYPE_INTEGR)
integrxf = xform;
}
- /* XXX support non-auth / non-enc proposals */
- if (encrxf == NULL || integrxf == NULL)
- return (-1);
+
+ if (prop->prop_protoid == IKEV2_SAPROTO_IKE) {
+ if (encrxf == NULL || integrxf == NULL)
+ return (-1);
+ } else if (prop->prop_protoid == IKEV2_SAPROTO_AH) {
+ if (integrxf == NULL)
+ return (-1);
+ } else if (prop->prop_protoid == IKEV2_SAPROTO_ESP) {
+ if (encrxf == NULL)
+ return (-1);
+ }
if (exf)
*exf = encrxf;
diff --git a/sbin/iked/parse.y b/sbin/iked/parse.y
index 6f64fa039de..614f039d33c 100644
--- a/sbin/iked/parse.y
+++ b/sbin/iked/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.11 2010/08/03 18:42:40 henning Exp $ */
+/* $OpenBSD: parse.y,v 1.12 2010/09/09 13:06:46 mikeb Exp $ */
/* $vantronix: parse.y,v 1.22 2010/06/03 11:08:34 reyk Exp $ */
/*
@@ -100,6 +100,7 @@ struct ipsec_xf {
u_int id;
u_int length;
u_int keylength;
+ u_int nonce;
};
struct ipsec_transforms {
@@ -150,7 +151,7 @@ const struct ipsec_xf ipsecencxfs[] = {
{ "aes-128", IKEV2_XFORMENCR_AES_CBC, 16, 16 },
{ "aes-192", IKEV2_XFORMENCR_AES_CBC, 24, 24 },
{ "aes-256", IKEV2_XFORMENCR_AES_CBC, 32, 32 },
- { "aes-ctr", IKEV2_XFORMENCR_AES_CTR, 20, 20 },
+ { "aes-ctr", IKEV2_XFORMENCR_AES_CTR, 16, 16, 4 },
{ "blowfish", IKEV2_XFORMENCR_BLOWFISH, 20, 20 },
{ "cast", IKEV2_XFORMENCR_CAST, 16, 16 },
{ "null", IKEV2_XFORMENCR_NULL, 0, 0 },
@@ -1957,6 +1958,21 @@ keylength_xf(u_int saproto, u_int type, u_int id)
return (0);
}
+size_t
+noncelength_xf(u_int type, u_int id)
+{
+ const struct ipsec_xf *xfs = ipsecencxfs;
+ int i;
+
+ if (type != IKEV2_XFORMTYPE_ENCR)
+ return (0);
+
+ for (i = 0; xfs[i].name != NULL; i++)
+ if (xfs[i].id == id)
+ return (xfs[i].nonce * 8);
+ return (0);
+}
+
void
print_user(struct iked_user *usr)
{