untrusted comment: verify with openbsd-77-base.pub
RWSbCCUoGpcxVcR2yj7p2rqaZY69rlIc2phVIq0v6ZrnPB1HTmc2s89VftgZNlcU/zy+81ZZ366hdNYG/zPqhd53pf06Tbj95wQ=

OpenBSD 7.7 errata 033, April 4, 2026:

In iked(8) add stricter checks to avoid out-of-bounds read, NULL
pointer dereference, and keep the state machine consistent.

Apply by doing:
    signify -Vep /etc/signify/openbsd-77-base.pub -x 033_iked.patch.sig \
        -m - | (cd /usr/src && patch -p0)

And then rebuild and install iked:
    cd /usr/src/sbin/iked
    make obj
    make
    make install

Index: sbin/iked/ikev2.c
===================================================================
RCS file: /cvs/src/sbin/iked/ikev2.c,v
diff -u -p -r1.391 ikev2.c
--- sbin/iked/ikev2.c	13 Mar 2025 17:49:37 -0000	1.391
+++ sbin/iked/ikev2.c	30 Mar 2026 17:28:47 -0000
@@ -713,7 +713,7 @@ ikev2_recv(struct iked *env, struct iked
 	}
 
 	if (msg->msg_response) {
-		if (msg->msg_msgid > sa->sa_reqid) {
+		if (msg->msg_msgid + 1 != sa->sa_reqid) {
 			ikestat_inc(env, ikes_msg_rcvd_dropped);
 			return;
 		}
@@ -4448,6 +4448,9 @@ ikev2_init_create_child_sa(struct iked *
 	uint32_t			 spi32;
 	int				 pfs = 0, ret = -1;
 
+	if (!sa_stateok(sa, IKEV2_STATE_ESTABLISHED))
+		return -1;
+
 	if (!ikev2_msg_frompeer(msg) ||
 	    (sa->sa_stateflags & (IKED_REQ_CHILDSA|IKED_REQ_INF)) == 0)
 		return (0);
@@ -4912,6 +4915,9 @@ ikev2_resp_create_child_sa(struct iked *
 	int				 initiator, protoid, rekeying = 1;
 	int				 ret = -1;
 	int				 pfs = 0;
+
+	if (!sa_stateok(sa, IKEV2_STATE_ESTABLISHED))
+		return -1;
 
 	initiator = sa->sa_hdr.sh_initiator ? 1 : 0;
 
Index: sbin/iked/ikev2_pld.c
===================================================================
RCS file: /cvs/src/sbin/iked/ikev2_pld.c,v
diff -u -p -r1.136 ikev2_pld.c
--- sbin/iked/ikev2_pld.c	13 Jul 2024 12:22:46 -0000	1.136
+++ sbin/iked/ikev2_pld.c	30 Mar 2026 17:28:47 -0000
@@ -99,6 +99,8 @@ int	 ikev2_pld_auth(struct iked *, struc
 	    struct iked_message *, size_t, size_t);
 int	 ikev2_pld_e(struct iked *, struct ikev2_payload *,
 	    struct iked_message *, size_t, size_t);
+int	 ikev2_validate_ef(struct iked_message *, size_t, size_t,
+	    struct ikev2_frag_payload *);
 int	 ikev2_pld_ef(struct iked *env, struct ikev2_payload *pld,
 	    struct iked_message *msg, size_t offset, size_t left);
 int	 ikev2_frags_reassemble(struct iked *env,
@@ -1612,6 +1614,22 @@ ikev2_pld_ts(struct iked *env, struct ik
 }
 
 int
+ikev2_validate_ef(struct iked_message *msg, size_t offset, size_t left,
+    struct ikev2_frag_payload *frag)
+{
+	uint8_t		*msgbuf = ibuf_data(msg->msg_data);
+
+	if (left < sizeof(*frag)) {
+		log_debug("%s: malformed payload: too short for header "
+		    "(%zu < %zu)", __func__, left, sizeof(*frag));
+		return (-1);
+	}
+	memcpy(frag, msgbuf + offset, sizeof(*frag));
+
+	return (0);
+}
+
+int
 ikev2_pld_ef(struct iked *env, struct ikev2_payload *pld,
     struct iked_message *msg, size_t offset, size_t left)
 {
@@ -1628,8 +1646,9 @@ ikev2_pld_ef(struct iked *env, struct ik
 	int				 processed = 0;
 	ssize_t				 elen;
 
-	buf = msgbuf + offset;
-	memcpy(&frag, buf, sizeof(frag));
+	if (ikev2_validate_ef(msg, offset, left, &frag) != 0)
+		return (-1);
+
 	frag_num = betoh16(frag.frag_num);
 	frag_total = betoh16(frag.frag_total);
 
@@ -1778,9 +1797,7 @@ ikev2_frags_reassemble(struct iked *env,
 
 	/* Drop the original request's packets from the retransmit queue */
 	if (msg->msg_response)
-		ikev2_msg_dispose(env, &msg->msg_sa->sa_requests,
-		    ikev2_msg_lookup(env, &msg->msg_sa->sa_requests, msg,
-		    msg->msg_exchange));
+		ikev2_msg_flushqueue(env, &msg->msg_sa->sa_requests);
 
 	/*
 	 * Parse decrypted payload
Index: regress/sbin/iked/parser/common.c
===================================================================
RCS file: /cvs/src/regress/sbin/iked/parser/common.c,v
diff -u -p -r1.13 common.c
--- regress/sbin/iked/parser/common.c	3 Dec 2022 22:34:35 -0000	1.13
+++ regress/sbin/iked/parser/common.c	30 Mar 2026 17:28:47 -0000
@@ -210,8 +210,7 @@ ikev2_ike_sa_setreason(struct iked_sa *s
 }
 
 void
-ikev2_msg_dispose(struct iked *env, struct iked_msgqueue *queue,
-    struct iked_msg_retransmit *mr)
+ikev2_msg_flushqueue(struct iked *env, struct iked_msgqueue *queue)
 {
 }
 
