
References: bnc#860542, CVE-2013-6466
Upstream: yes

Adopted backport patch for openswan-2.6.16, based on a openswan-2.6.32
backport from libreswan [https://libreswan.org/security/CVE-2013-6467]
by Paul Wouters.

--- include/constants.h
+++ include/constants.h	2014/04/03 09:56:02
@@ -64,6 +64,7 @@ typedef int bool;
  */
 
 typedef unsigned long long lset_t;
+#define LELEM_ROOF  64  /* all elements must be less than this */
 #define LEMPTY 0ULL
 #define LELEM(opt) (1ULL << (opt))
 #define LRANGE(lwb, upb) LRANGES(LELEM(lwb), LELEM(upb))
--- include/ietf_constants.h
+++ include/ietf_constants.h	2014/04/03 09:56:02
@@ -301,6 +301,8 @@ enum next_payload_types {
 	ISAKMP_NEXT_NATOA_DRAFTS = 131   /* NAT-Traversal: NAT-OA (drafts) */
 };
 
+#define ISAKMP_v2PAYLOAD_TYPE_BASE     ISAKMP_NEXT_v2SA        /* lowest value of a v2 payload type */
+
 /* These values are to be used within the Type field of an Attribute (14) 
  *    ISAKMP payload.  */
 #define ISAKMP_CFG_REQUEST         1
--- include/names_constant.h
+++ include/names_constant.h	2014/04/03 09:56:02
@@ -30,7 +30,10 @@ extern enum_names oakley_lifetime_names;
 extern enum_names version_names;
 extern enum_names doi_names;
 extern enum_names payload_names;
+extern enum_names payload_names_ikev2;
 extern const char *const payload_name[];
+extern const char *const payload_name_ikev2[];
+extern const char *const payload_name_ikev2_main[];
 extern enum_names attr_msg_type_names;
 extern enum_names modecfg_attr_names;
 extern enum_names xauth_type_names;
--- include/packet.h
+++ include/packet.h	2014/04/03 09:56:02
@@ -661,7 +661,7 @@ extern struct_desc isakmp_nat_oa;
  * That leaves only Identification payloads as a problem.
  * We make all these entries NULL
  */
-extern struct_desc *const payload_descs[ISAKMP_NEXT_ROOF];
+extern const struct_desc *payload_desc(unsigned p);
 
 /*
  * IKEv2 structures
--- lib/libopenswan/constants.c
+++ lib/libopenswan/constants.c	2014/04/03 09:56:02
@@ -141,7 +141,8 @@ const char *const payload_name[] = {
 	NULL
     };
 
-const char *const payload_names_ikev2[] = {
+/* dual-use: for enum_name and for bitnamesof */
+const char *const payload_name_ikev2_main[] = {
     "ISAKMP_NEXT_v2SA",            /* 33 */
     "ISAKMP_NEXT_v2KE",
     "ISAKMP_NEXT_v2IDi",
@@ -158,22 +159,22 @@ const char *const payload_names_ikev2[]
     "ISAKMP_NEXT_v2E",
     "ISAKMP_NEXT_v2CP",
     "ISAKMP_NEXT_v2EAP",
-    NULL
+    NULL    /* termination for bitnamesof() */
 };
 
-const char *const payload_name_nat_d[] = {
-    "ISAKMP_NEXT_NAT-D",
-    "ISAKMP_NEXT_NAT-OA",
-    NULL
+static enum_names payload_names_ikev2_main =
+{ ISAKMP_NEXT_v2SA, ISAKMP_NEXT_v2EAP, payload_name_ikev2_main, NULL };
+
+const char *const payload_name_ikev2[] = {
+    "ISAKMP_NEXT_v2NONE",            /* 33 */
 };
 
-static enum_names payload_names_nat_d =
-{ ISAKMP_NEXT_NATD_DRAFTS, ISAKMP_NEXT_NATOA_DRAFTS, payload_name_nat_d, NULL };
-static enum_names payload_names_ikev2_d =
-{ ISAKMP_NEXT_v2SA, ISAKMP_NEXT_v2EAP, payload_names_ikev2, &payload_names_nat_d };
+enum_names payload_names_ikev2 =
+{ ISAKMP_NEXT_NONE, ISAKMP_NEXT_NONE, payload_name_ikev2,
+  &payload_names_ikev2_main };
 
 enum_names payload_names =
-{ ISAKMP_NEXT_NONE, ISAKMP_NEXT_NATOA_RFC, payload_name, &payload_names_ikev2_d };
+{ ISAKMP_NEXT_NONE, ISAKMP_NEXT_NATOA_RFC, payload_name, &payload_names_ikev2_main };
 
 
 /* Exchange types (note: two discontinuous ranges) */
--- lib/libpluto/packet.c
+++ lib/libpluto/packet.c	2014/04/03 09:56:02
@@ -1075,7 +1075,7 @@ struct_desc ikev2_e_desc = { "IKEv2 Encr
  * That leaves only Identification payloads as a problem.
  * We make all these entries NULL
  */
-struct_desc *const payload_descs[ISAKMP_NEXT_ROOF] = {
+static struct_desc *const payload_descs[] = {
     NULL,				/* 0 ISAKMP_NEXT_NONE (No other payload following) */
     &isakmp_sa_desc,			/* 1 ISAKMP_NEXT_SA (Security Association) */
     NULL,				/* 2 ISAKMP_NEXT_P (Proposal) */
@@ -1115,6 +1115,11 @@ struct_desc *const payload_descs[ISAKMP_
     &ikev2_e_desc,                      /* 46 */
 };
 
+const struct_desc *payload_desc(unsigned p)
+{
+    return p < elemsof(payload_descs) ? payload_descs[p] : NULL;
+}
+
 void
 init_pbs(pb_stream *pbs, u_int8_t *start, size_t len, const char *name)
 {
--- programs/pluto/demux.h
+++ programs/pluto/demux.h	2014/04/03 09:56:02
@@ -83,8 +83,9 @@ struct msg_digest {
 #   define PAYLIMIT 20
     struct payload_digest
 	digest[PAYLIMIT],
-	*digest_roof,
-	*chain[ISAKMP_NEXT_ROOF];
+	*digest_roof;
+        struct payload_digest
+	    *chain[(unsigned)ISAKMP_NEXT_ROOF];
     struct isakmp_quirks quirks;
 };
 
--- programs/pluto/ikev1.c
+++ programs/pluto/ikev1.c	2014/04/03 10:00:47
@@ -1405,7 +1405,7 @@ void process_packet_tail(struct msg_dige
 
 	while (np != ISAKMP_NEXT_NONE)
 	{
-	    struct_desc *sd = np < ISAKMP_NEXT_ROOF? payload_descs[np] : NULL;
+	    struct_desc *sd = payload_desc(np);
 
 	    if (pd == &md->digest[PAYLIMIT])
 	    {
@@ -1452,12 +1452,12 @@ void process_packet_tail(struct msg_dige
 #ifdef NAT_TRAVERSAL
 		case ISAKMP_NEXT_NATD_DRAFTS:
 		    np = ISAKMP_NEXT_NATD_RFC;  /* NAT-D relocated */
-		    sd = payload_descs[np];
+		    sd = payload_desc(np);
 		    break;
 
 		case ISAKMP_NEXT_NATOA_DRAFTS:
 		    np = ISAKMP_NEXT_NATOA_RFC;  /* NAT-OA relocated */
-		    sd = payload_descs[np];
+		    sd = payload_desc(np);
 		    break;
 
 		case ISAKMP_NEXT_NATD_BADDRAFTS:
@@ -1467,7 +1467,7 @@ void process_packet_tail(struct msg_dige
 			     * the bad drafts of the RFC
 			     */
 		        np = ISAKMP_NEXT_NATD_RFC;  /* NAT-D relocated */
-		        sd = payload_descs[np];
+		        sd = payload_desc(np);
 		        break;
 		    }
 #endif
@@ -1478,6 +1478,7 @@ void process_packet_tail(struct msg_dige
 		    SEND_NOTIFICATION(INVALID_PAYLOAD_TYPE);
 		    return;
 		}
+		passert(sd != NULL);
 	    }
 
 	    {
--- programs/pluto/ikev2.c
+++ programs/pluto/ikev2.c	2014/04/03 10:35:33
@@ -75,20 +75,18 @@ struct state_v2_microcode {
     enum state_kind state, next_state;
     enum isakmp_xchg_types recv_type;
     lset_t flags;
-    lset_t req_payloads;	/* required payloads (allows just one) */
-    lset_t opt_payloads;	/* optional payloads (any mumber) */
+    lset_t req_clear_payloads;  /* required unencrypted payloads (allows just one) for received packet */
+    lset_t opt_clear_payloads;  /* optional unencrypted payloads (none or one) for received packet */
+    lset_t req_enc_payloads;  /* required encrypted payloads (allows just one) for received packet */
+    lset_t opt_enc_payloads;  /* optional encrypted payloads (none or one) for received packet */
     enum event_type timeout_event;
     state_transition_fn *processor;
 };
 
 enum smf2_flags {
     SMF2_INITIATOR = LELEM(1),
-    SMF2_RESPONDER = 0,
-    
-    SMF2_STATENEEDED=LELEM(2),
-    SMF2_NEWSTATE  = 0,
-
-    SMF2_REPLY     = LELEM(3),
+    SMF2_STATENEEDED = LELEM(2),
+    SMF2_REPLY = LELEM(3),
 };
 
 /*
@@ -127,18 +125,26 @@ enum smf2_flags {
  *
  */
 
-/* it is not clear how the flags will be used yet, if at all */
+#define PT(n) ISAKMP_NEXT_v2 ## n
+#define P(n) LELEM(PT(n) - ISAKMP_v2PAYLOAD_TYPE_BASE)
+static const lset_t everywhere_payloads = P(N) | P(V); /* can appear in any packet */
+static const lset_t repeatable_payloads = P(N) | P(D) | P(CP) | P(V);  /* if one can appear, many can appear */
 
-static const struct state_v2_microcode state_microcode_table[] = {
+/* microcode to parent first initiator state: not associated with an input packet */
+const struct state_v2_microcode ikev2_parent_firststate_microcode =
     { .state      = STATE_UNDEFINED,
       .next_state = STATE_PARENT_I1,
       .flags      = SMF2_INITIATOR,
       .processor  = NULL,
-    },
+    };
 
+/* microcode for input packet processing */
+static const struct state_v2_microcode v2_state_microcode_table[] = {
     { .state      = STATE_PARENT_I1,
       .next_state = STATE_PARENT_I2,
       .flags = SMF2_INITIATOR|SMF2_STATENEEDED|SMF2_REPLY,
+      .req_clear_payloads = P(SA) | P(KE) | P(Nr),
+      .opt_clear_payloads = P(CERTREQ),
       .processor  = ikev2parent_inR1outI2,
       .recv_type  = ISAKMP_v2_SA_INIT,
     },
@@ -146,6 +152,9 @@ static const struct state_v2_microcode s
     { .state      = STATE_PARENT_I2,
       .next_state = STATE_PARENT_I3,
       .flags = SMF2_INITIATOR|SMF2_STATENEEDED,
+      .req_clear_payloads = P(E),
+      .req_enc_payloads = P(IDr) | P(AUTH) | P(SA) | P(TSi) | P(TSr),
+      .opt_enc_payloads = P(CERT),
       .processor  = ikev2parent_inR2,
       .recv_type  = ISAKMP_v2_AUTH,
       .timeout_event = EVENT_SA_REPLACE,
@@ -153,14 +162,18 @@ static const struct state_v2_microcode s
 
     { .state      = STATE_UNDEFINED,
       .next_state = STATE_PARENT_R1,
-      .flags = SMF2_RESPONDER|SMF2_NEWSTATE|SMF2_REPLY,
+      .flags =  /* not SMF2_INITIATOR, not SMF2_STATENEEDED */ SMF2_REPLY,
+      .req_clear_payloads = P(SA) | P(KE) | P(Ni),
       .processor  = ikev2parent_inI1outR1,
       .recv_type  = ISAKMP_v2_SA_INIT,
     },
-	
+
     { .state      = STATE_PARENT_R1,
       .next_state = STATE_PARENT_R2,
-      .flags = SMF2_RESPONDER|SMF2_STATENEEDED|SMF2_REPLY,
+      .flags =  /* not SMF2_INITIATOR */ SMF2_STATENEEDED | SMF2_REPLY,
+      .req_clear_payloads = P(E),
+      .req_enc_payloads = P(IDi) | P(AUTH) | P(SA) | P(TSi) | P(TSr),
+      .opt_enc_payloads = P(CERT) | P(CERTREQ) | P(IDr),
       .processor  = ikev2parent_inI2outR2,
       .recv_type  = ISAKMP_v2_AUTH,
       .timeout_event = EVENT_SA_REPLACE,
@@ -170,104 +183,143 @@ static const struct state_v2_microcode s
     { .state      = STATE_IKEv2_ROOF }
 };
 
-
-const struct state_v2_microcode *ikev2_parent_firststate()
-{
-    return &state_microcode_table[0];
-}
-
+#undef P
+#undef PT
 
 /*
  * split up an incoming message into payloads
  */
-stf_status
+static stf_status
 ikev2_process_payloads(struct msg_digest *md,
 			    pb_stream    *in_pbs,
-			    unsigned int from_state,
-			    unsigned int np)
+			    unsigned int np,
+			    lset_t req_payloads,
+			    lset_t opt_payloads)
 {
     struct payload_digest *pd = md->digest_roof;
-    struct state *st = md->st;
-    err_t excuse = "not sure";
-    
-    //lset_t needed = smc->req_payloads;
+    lset_t seen = LEMPTY;
 
-    /* zero out the digest descriptors -- might nuke [v2E] digest! */
+    /* ??? zero out the digest descriptors -- might nuke ISAKMP_NEXT_v2E digest! */
 
     while (np != ISAKMP_NEXT_NONE)
     {
-	struct_desc *sd = np < ISAKMP_NEXT_ROOF? payload_descs[np] : NULL;
-	int thisp = np;
-	bool unknown_payload = FALSE;
-	
+	struct_desc *sd = payload_desc(np);
+
 	memset(pd, 0, sizeof(*pd));
 	
 	if (pd == &md->digest[PAYLIMIT])
 	{
 	    loglog(RC_LOG_SERIOUS, "more than %d payloads in message; ignored", PAYLIMIT);
-	    SEND_NOTIFICATION(PAYLOAD_MALFORMED);
-	    return STF_FAIL;
+	    return STF_FAIL + INVALID_SYNTAX;
 	}
-	
-	if (sd == NULL)
+
+	memset(pd, 0, sizeof(*pd));     /* ??? is this needed? */
+
+	if (sd == NULL || np < ISAKMP_v2PAYLOAD_TYPE_BASE) {
+		/* This payload is unknown to us.
+		 * RFCs 4306 and 5996 2.5 say that if the payload
+		 * has the Critical Bit, we should be upset
+		 * but if it does not, we should just ignore it.
+		 */
+		if (!in_struct(&pd->payload, &ikev2_generic_desc, in_pbs, &pd->pbs)) {
+			loglog(RC_LOG_SERIOUS, "malformed payload in packet");
+			return STF_FAIL + INVALID_SYNTAX;
+		}
+		if (pd->payload.v2gen.isag_critical & ISAKMP_PAYLOAD_CRITICAL) {
+			/* It was critical.
+			 * See RFC 5996 1.5 "Version Numbers and Forward Compatibility"
+			 * ??? we are supposed to send the offending np byte back in the
+			 * notify payload.
+			 */
+			loglog(RC_LOG_SERIOUS,
+				"critical payload (%s) was not understood. Message dropped.",
+				enum_show(&payload_names_ikev2, np));
+			return STF_FAIL + UNSUPPORTED_CRITICAL_PAYLOAD;
+		}
+		loglog(RC_COMMENT, "non-critical payload ignored because it contains an unknown or"
+			" unexpected payload type (%s) at the outermost level",
+			enum_show(&payload_names_ikev2, np));
+		np = pd->payload.generic.isag_np;
+		continue;
+	}
+
+	passert(np - ISAKMP_v2PAYLOAD_TYPE_BASE < LELEM_ROOF);
+
 	{
-	    unknown_payload = TRUE;
-	    sd = &ikev2_generic_desc;
+		lset_t s = LELEM(np - ISAKMP_v2PAYLOAD_TYPE_BASE);
+
+		if (s & seen & ~repeatable_payloads) {
+			/* improperly repeated payload */
+			loglog(RC_LOG_SERIOUS,
+				"payload (%s) unexpectedly repeated. Message dropped.",
+				enum_show(&payload_names_ikev2, np));
+			return STF_FAIL + INVALID_SYNTAX;
+		}
+		if ((s & (req_payloads | opt_payloads | everywhere_payloads)) == LEMPTY) {
+			/* unexpected payload */
+			loglog(RC_LOG_SERIOUS,
+				"payload (%s) unexpected. Message dropped.",
+				enum_show(&payload_names_ikev2, np));
+			return STF_FAIL + INVALID_SYNTAX;
+		}
+		seen |= s;
 	}
-	
+
 	if (!in_struct(&pd->payload, sd, in_pbs, &pd->pbs))
 	{
-	    loglog(RC_LOG_SERIOUS, "%smalformed payload in packet", excuse);
-	    SEND_NOTIFICATION(PAYLOAD_MALFORMED);
-	    return STF_FAIL;
+	    loglog(RC_LOG_SERIOUS, "malformed payload in packet");
+	    return STF_FAIL + INVALID_SYNTAX;
 	}
 
-	if(unknown_payload) {
-	    if(pd->payload.v2gen.isag_critical) {
-		/* it was critical */
-		loglog(RC_LOG_SERIOUS, "critical payload (%s) was not understood. Message dropped."
-		       , enum_show(&payload_names, thisp));
-		return STF_FATAL;
-	    } 
-	    loglog(RC_COMMENT, "non-critical payload ignored because it contains an unknown or" 
-		   " unexpected payload type (%s) at the outermost level"
-		   , enum_show(&payload_names, thisp));
-	}
-		
-	
+
 	DBG(DBG_PARSING
 	    , DBG_log("processing payload: %s (len=%u)\n"
-		      , enum_show(&payload_names, thisp)
+		      , enum_show(&payload_names, np)
 		      , pd->payload.generic.isag_length));
 	
 	/* place this payload at the end of the chain for this type */
 	{
 	    struct payload_digest **p;
 	    
-	    for (p = &md->chain[thisp]; *p != NULL; p = &(*p)->next)
+	    for (p = &md->chain[np]; *p != NULL; p = &(*p)->next)
 		;
 	    *p = pd;
 	    pd->next = NULL;
 	}
 	
-	np = pd->payload.generic.isag_np;
-	
 	/* do payload-type specific things that need to be here. */
-	switch(thisp) {
+	switch(np) {
 	case ISAKMP_NEXT_v2E:
 	    np = ISAKMP_NEXT_NONE;
 	    break;
-	default:   /* nothing special */
+	default:
+	    np = pd->payload.generic.isag_np;
 	    break;
 	}
 	
 	pd++;
     }
-    
+
+    if (req_payloads & ~seen) {
+        /* improperly repeated payload */
+        loglog(RC_LOG_SERIOUS,
+		"missing payload(s) (%s). Message dropped.",
+		bitnamesof(payload_name_ikev2_main, req_payloads & ~seen));
+	return STF_FAIL + INVALID_SYNTAX;
+    }
+
     md->digest_roof = pd;
     return STF_OK;
 }
 
+/* this stub is needed because struct state_v2_microcode is local to this file */
+stf_status ikev2_process_encrypted_payloads(struct msg_digest *md,
+						pb_stream   *in_pbs,
+						unsigned int np)
+{
+	return ikev2_process_payloads(md, in_pbs, np, md->svm->req_enc_payloads, md->svm->opt_enc_payloads);
+}
+
 /*
  * process an input packet, possibly generating a reply.
  *
@@ -394,7 +446,7 @@ process_v2_packet(struct msg_digest **md
 	from_state = st->st_state;
     }
 
-    for(svm = state_microcode_table; svm->state != STATE_IKEv2_ROOF; svm++) {
+    for(svm = v2_state_microcode_table; svm->state != STATE_IKEv2_ROOF; svm++) {
 	if(svm->flags & SMF2_STATENEEDED) {
 	    if(st==NULL) continue;
 	}
@@ -426,11 +478,16 @@ process_v2_packet(struct msg_digest **md
 	return;
     }
 
+    md->svm = svm;
+    md->from_state = from_state;
+    md->st = st;
+
     {
 	stf_status stf;
-	stf = ikev2_process_payloads(md, &md->message_pbs
-				     , from_state, md->hdr.isa_np);
-	
+	stf = ikev2_process_payloads(md, &md->message_pbs,
+			md->hdr.isa_np,
+			svm->req_clear_payloads, svm->opt_clear_payloads);
+
 	if(stf != STF_OK) {
 	    complete_v2_state_transition(mdp, stf);
 	}
@@ -443,26 +500,7 @@ process_v2_packet(struct msg_digest **md
     
     md->message_pbs.roof = md->message_pbs.cur;
     
-#if 0
-    /* check that all mandatory payloads appeared */
-    if (needed != 0)
-    {
-	loglog(RC_LOG_SERIOUS, "message for %s is missing payloads %s"
-	       , enum_show(&state_names, from_state)
-	       , bitnamesof(payload_name, needed));
-	SEND_NOTIFICATION(PAYLOAD_MALFORMED);
-	return;
-#endif
-
-    md->svm = svm;
-    md->from_state = from_state;
-    md->st  = st;
-
-    {
-	stf_status stf;
-	stf = (svm->processor)(md);
-	complete_v2_state_transition(mdp, stf);
-    }
+    complete_v2_state_transition(mdp, (svm->processor)(md));
 }
 
 bool
@@ -960,10 +998,25 @@ void complete_v2_state_transition(struct
 notification_t
 accept_v2_nonce(struct msg_digest *md, chunk_t *dest, const char *name)
 {
-    return accept_nonce(md, dest, name, ISAKMP_NEXT_v2Ni);
-}
+	pb_stream *nonce_pbs;
+	size_t len;
 
+	if(md->chain[ISAKMP_NEXT_v2Ni] == NULL) {
+		loglog(RC_LOG_SERIOUS, "missing nonce Ni");
+		return INVALID_SYNTAX;
+	}
 
+	nonce_pbs = &md->chain[ISAKMP_NEXT_v2Ni]->pbs;
+	len = pbs_left(nonce_pbs);
+
+	if (len < MINIMUM_NONCE_SIZE || MAXIMUM_NONCE_SIZE < len) {
+		loglog(RC_LOG_SERIOUS, "%s length not between %d and %d",
+			name, MINIMUM_NONCE_SIZE, MAXIMUM_NONCE_SIZE);
+		return INVALID_SYNTAX; /* ??? */
+	}
+	clonereplacechunk(*dest, nonce_pbs->cur, len, "nonce");
+	return NOTHING_WRONG;
+}
 
 /*
  * Local Variables:
--- programs/pluto/ikev2.h
+++ programs/pluto/ikev2.h	2014/04/03 10:02:59
@@ -35,7 +35,7 @@ extern stf_status ikev2parent_inR1outI2(
 extern stf_status ikev2parent_inI2outR2(struct msg_digest *md);
 extern stf_status ikev2parent_inR2(struct msg_digest *md);
 
-extern const struct state_v2_microcode *ikev2_parent_firststate(void);
+extern const struct state_v2_microcode ikev2_parent_firststate_microcode;
 
 extern notification_t accept_v2_nonce(struct msg_digest *md, chunk_t *dest
 				      , const char *name);
@@ -83,9 +83,8 @@ extern void send_v2_notification_from_st
 
 extern void send_v2_notification_from_md(struct msg_digest *md,u_int16_t type
    					 , chunk_t *data);
-extern stf_status ikev2_process_payloads(struct msg_digest *md,
+extern stf_status ikev2_process_encrypted_payloads(struct msg_digest *md,
 					 pb_stream   *in_pbs,
-					 unsigned int from_state,
 					 unsigned int np);
 
 extern bool ikev2_decode_peer_id(struct msg_digest *md
--- programs/pluto/ikev2_parent.c
+++ programs/pluto/ikev2_parent.c	2014/04/03 10:06:37
@@ -196,7 +196,7 @@ ikev2parent_outI1(int whack_sock
 
 	ke->md = alloc_md();
 	ke->md->from_state = STATE_IKEv2_BASE;
-	ke->md->svm = ikev2_parent_firststate();
+	ke->md->svm = &ikev2_parent_firststate_microcode;
 	ke->md->st = st;
 	set_suspended(st, ke->md);
 
@@ -823,7 +823,7 @@ stf_status ikev2parent_inR1outI2(struct
 						    st->st_dcookie);
 	        DBG_log("next STATE_PARENT_I1 resend I1 with the dcookie"));
 
-		md->svm = ikev2_parent_firststate();
+		md->svm = &ikev2_parent_firststate_microcode;
 
 		change_state(st, STATE_PARENT_I1);
     	st->st_msgid_lastack = INVALID_MSGID;
@@ -834,21 +834,6 @@ stf_status ikev2parent_inR1outI2(struct
     }
 
     /*
-     * If we did not get a KE payload, we cannot continue. There * should be
-     * a Notify telling us why. We inform the user, but continue to try this
-     * connection via regular retransmit intervals.
-     */
-    if( md->chain[ISAKMP_NEXT_v2N]  && (md->chain[ISAKMP_NEXT_v2KE] == NULL)) 
-	{
-		const char *from_state_name = enum_name(&state_names, st->st_state);
-		const u_int16_t isan_type =  md->chain[ISAKMP_NEXT_v2N]->payload.v2n.isan_type;
-		openswan_log("%s: received %s"
-					, from_state_name 
-					, enum_name(&ikev2_notify_names , isan_type));
-		return STF_FAIL + isan_type;
-	}
-
-    /*
      * the responder sent us back KE, Gr, Nr, and it's our time to calculate
      * the shared key values.
      */
@@ -1130,14 +1115,7 @@ stf_status ikev2_decrypt_msg(struct msg_
 	init_pbs(&md->clr_pbs, encstart, enclen - (padlen+1), "cleartext");
     }
 
-    { stf_status ret;
-	ret = ikev2_process_payloads(md, &md->clr_pbs, st->st_state, np);
-	if(ret != STF_OK) {
-	    return ret;
-	}
-    }
-	    
-    return STF_OK;
+    return ikev2_process_encrypted_payloads(md, &md->clr_pbs, np);
 }
 
 static stf_status ikev2_send_auth(struct connection *c
