Hi,

turns out that, as specified in the RFC, the initial Child SA does not
do PFS and is assumed to be secured using the DH exchange in the first
handshake.  Thus there is no KE/N payload in the IKE_AUTH exchange and
we must not include a DH group other than None, which essentially means
we must not supply any DH transforms in the IKE_AUTH messages.

The diff skips adding the DH transforms for initiating and responding
to IKE_AUTH messages.  With this I have a bit more luck with connecting
to Strongswan, as Strongswan throws a no proposal chosen if we include
a DH transform.

ok?

Patrick

diff --git a/sbin/iked/ikev2.c b/sbin/iked/ikev2.c
index b505f763153..286e605fc32 100644
--- a/sbin/iked/ikev2.c
+++ b/sbin/iked/ikev2.c
@@ -114,7 +114,7 @@ int  ikev2_valid_proposal(struct iked_proposal *,
            struct iked_transform **, struct iked_transform **, int *);
 
 ssize_t         ikev2_add_proposals(struct iked *, struct iked_sa *, struct 
ibuf *,
-           struct iked_proposals *, uint8_t, int, int);
+           struct iked_proposals *, uint8_t, int, int, int);
 ssize_t         ikev2_add_cp(struct iked *, struct iked_sa *, struct ibuf *);
 ssize_t         ikev2_add_transform(struct ibuf *,
            uint8_t, uint8_t, uint16_t, uint16_t);
@@ -971,7 +971,7 @@ ikev2_init_ike_sa_peer(struct iked *env, struct iked_policy 
*pol,
        if ((pld = ikev2_add_payload(buf)) == NULL)
                goto done;
        if ((len = ikev2_add_proposals(env, sa, buf, &pol->pol_proposals,
-           IKEV2_SAPROTO_IKE, sa->sa_hdr.sh_initiator, 0)) == -1)
+           IKEV2_SAPROTO_IKE, sa->sa_hdr.sh_initiator, 0, 0)) == -1)
                goto done;
 
        if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_KE) == -1)
@@ -1173,7 +1173,7 @@ ikev2_init_ike_auth(struct iked *env, struct iked_sa *sa)
        if ((pld = ikev2_add_payload(e)) == NULL)
                goto done;
        if ((len = ikev2_add_proposals(env, sa, e, &pol->pol_proposals, 0,
-           sa->sa_hdr.sh_initiator, 0)) == -1)
+           sa->sa_hdr.sh_initiator, 0, 1)) == -1)
                goto done;
 
        if ((len = ikev2_add_ts(e, &pld, len, sa, 0)) == -1)
@@ -1940,7 +1940,7 @@ ikev2_add_cp(struct iked *env, struct iked_sa *sa, struct 
ibuf *buf)
 ssize_t
 ikev2_add_proposals(struct iked *env, struct iked_sa *sa, struct ibuf *buf,
     struct iked_proposals *proposals, uint8_t protoid, int initiator,
-    int sendikespi)
+    int sendikespi, int skipdh)
 {
        struct ikev2_sa_proposal        *sap;
        struct iked_transform           *xform;
@@ -1949,7 +1949,7 @@ ikev2_add_proposals(struct iked *env, struct iked_sa *sa, 
struct ibuf *buf,
        ssize_t                          length = 0, saplength, xflen;
        uint64_t                         spi64;
        uint32_t                         spi32, spi;
-       unsigned int                     i;
+       unsigned int                     i, xfi, nxforms;
 
        TAILQ_FOREACH(prop, proposals, prop_entry) {
                if ((protoid && prop->prop_protoid != protoid) ||
@@ -1984,10 +1984,26 @@ ikev2_add_proposals(struct iked *env, struct iked_sa 
*sa, struct ibuf *buf,
                        prop->prop_localspi.spi_protoid = IKEV2_SAPROTO_IKE;
                }
 
+               /*
+                * RFC 7296: 1.2. The Initial Exchanges
+                * IKE_AUTH messages do not contain KE/N payloads, thus
+                * SA payloads cannot contain groups.
+                */
+               if (skipdh) {
+                       nxforms = 0;
+                       for (i = 0; i < prop->prop_nxforms; i++) {
+                               xform = prop->prop_xforms + i;
+                               if (xform->xform_type == IKEV2_XFORMTYPE_DH)
+                                       continue;
+                               nxforms++;
+                       }
+               } else
+                       nxforms = prop->prop_nxforms;
+
                sap->sap_proposalnr = prop->prop_id;
                sap->sap_protoid = prop->prop_protoid;
                sap->sap_spisize = prop->prop_localspi.spi_size;
-               sap->sap_transforms = prop->prop_nxforms;
+               sap->sap_transforms = nxforms;
                saplength = sizeof(*sap);
 
                switch (prop->prop_localspi.spi_size) {
@@ -2007,16 +2023,20 @@ ikev2_add_proposals(struct iked *env, struct iked_sa 
*sa, struct ibuf *buf,
                        break;
                }
 
-               for (i = 0; i < prop->prop_nxforms; i++) {
+               for (i = 0, xfi = 0; i < prop->prop_nxforms; i++) {
                        xform = prop->prop_xforms + i;
 
+                       if (skipdh && xform->xform_type == IKEV2_XFORMTYPE_DH)
+                               continue;
+
                        if ((xflen = ikev2_add_transform(buf,
-                           i == prop->prop_nxforms - 1 ?
+                           xfi == nxforms - 1 ?
                            IKEV2_XFORM_LAST : IKEV2_XFORM_MORE,
                            xform->xform_type, xform->xform_id,
                            xform->xform_length)) == -1)
                                return (-1);
 
+                       xfi++;
                        saplength += xflen;
                }
 
@@ -2310,7 +2330,7 @@ ikev2_resp_ike_sa_init(struct iked *env, struct 
iked_message *msg)
        if ((pld = ikev2_add_payload(buf)) == NULL)
                goto done;
        if ((len = ikev2_add_proposals(env, sa, buf, &sa->sa_proposals,
-           IKEV2_SAPROTO_IKE, sa->sa_hdr.sh_initiator, 0)) == -1)
+           IKEV2_SAPROTO_IKE, sa->sa_hdr.sh_initiator, 0, 0)) == -1)
                goto done;
 
        if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_KE) == -1)
@@ -2570,7 +2590,7 @@ ikev2_resp_ike_auth(struct iked *env, struct iked_sa *sa)
        if ((pld = ikev2_add_payload(e)) == NULL)
                goto done;
        if ((len = ikev2_add_proposals(env, sa, e, &sa->sa_proposals, 0,
-           sa->sa_hdr.sh_initiator, 0)) == -1)
+           sa->sa_hdr.sh_initiator, 0, 1)) == -1)
                goto done;
 
        if ((len = ikev2_add_ts(e, &pld, len, sa, 0)) == -1)
@@ -2831,7 +2851,7 @@ ikev2_send_create_child_sa(struct iked *env, struct 
iked_sa *sa,
        }
 
        if ((len = ikev2_add_proposals(env, sa, e, &sa->sa_proposals,
-           protoid, 1, 0)) == -1)
+           protoid, 1, 0, 0)) == -1)
                goto done;
 
        if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_NONCE) == -1)
@@ -2971,7 +2991,7 @@ ikev2_ike_sa_rekey(struct iked *env, void *arg)
 
        /* just reuse the old IKE SA proposals */
        if ((len = ikev2_add_proposals(env, nsa, e, &sa->sa_proposals,
-           IKEV2_SAPROTO_IKE, 1, 1)) == -1)
+           IKEV2_SAPROTO_IKE, 1, 1, 0)) == -1)
                goto done;
 
        if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_NONCE) == -1)
@@ -3611,7 +3631,7 @@ ikev2_resp_create_child_sa(struct iked *env, struct 
iked_message *msg)
 
        if ((len = ikev2_add_proposals(env, nsa ? nsa : sa, e,
                nsa ? &nsa->sa_proposals : &proposals,
-               protoid, 0, nsa ? 1 : 0)) == -1)
+               protoid, 0, nsa ? 1 : 0, 0)) == -1)
                goto done;
 
        if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_NONCE) == -1)

Reply via email to