diff options
author | Mike Belopuhov <mikeb@cvs.openbsd.org> | 2010-09-09 13:06:47 +0000 |
---|---|---|
committer | Mike Belopuhov <mikeb@cvs.openbsd.org> | 2010-09-09 13:06:47 +0000 |
commit | 493711f6cd315f0e7960b26c8f106ca234232bb9 (patch) | |
tree | a870a498d4958e6eb3db2ed93f3f3ba125f0bee6 | |
parent | 507a27332a3bb61164670eb5c8f524f89a32dc31 (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.h | 3 | ||||
-rw-r--r-- | sbin/iked/ikev2.c | 68 | ||||
-rw-r--r-- | sbin/iked/parse.y | 20 |
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) { |