untrusted comment: verify with openbsd-80-base.pub RWSMSt0erHTctfMBcDFr5GXIeAQbByFHfLMP4VVip0DQ6h2z6rsCnf1pmpnmqulkVv/AeBOnI6klMoXhb3RXG9gztGfTujPwpwg= OpenBSD 8.0 errata 006, November 5, 2026: By sending crafted IKEv1 messages, an unauthenticated remote attacker could crash isakmpd(8) due to a NULL pointer dereference, out-of-bounds memory accesses or a double free. Apply by doing: signify -Vep /etc/signify/openbsd-80-base.pub -x 006_isakmpd.patch.sig \ -m - | (cd /usr/src && patch -p0) And then rebuild and install isakmpd: cd /usr/src/sbin/isakmpd make obj make make install Index: sbin/isakmpd/crypto.c =================================================================== RCS file: /cvs/src/sbin/isakmpd/crypto.c,v diff -u -p -r1.36 crypto.c --- sbin/isakmpd/crypto.c 24 Jun 2026 09:57:32 -0000 1.36 +++ sbin/isakmpd/crypto.c 23 Oct 2026 21:58:21 -0000 @@ -188,8 +188,9 @@ cast1_decrypt(struct keystate *ks, u_int enum cryptoerr aes_init(struct keystate *ks, u_int8_t *key, u_int16_t len) { - AES_set_encrypt_key(key, len << 3, &ks->ks_aes[0]); - AES_set_decrypt_key(key, len << 3, &ks->ks_aes[1]); + if (AES_set_encrypt_key(key, len << 3, &ks->ks_aes[0]) != 0 || + AES_set_decrypt_key(key, len << 3, &ks->ks_aes[1]) != 0) + return EKEYLEN; return EOKAY; } @@ -252,8 +253,8 @@ crypto_init(struct crypto_xf *xf, u_int8 *err = xf->init(ks, key, len); if (*err != EOKAY) { - LOG_DBG((LOG_CRYPTO, 30, "crypto_init: weak key found for %s", - xf->name)); + LOG_DBG((LOG_CRYPTO, 30, "crypto_init: %s key setup failed " + "(key length %u, error %d)", xf->name, len, *err)); freezero(ks, sizeof *ks); return 0; } Index: sbin/isakmpd/dpd.c =================================================================== RCS file: /cvs/src/sbin/isakmpd/dpd.c,v diff -u -p -r1.20 dpd.c --- sbin/isakmpd/dpd.c 5 Dec 2017 20:31:45 -0000 1.20 +++ sbin/isakmpd/dpd.c 23 Oct 2026 21:58:21 -0000 @@ -139,7 +139,9 @@ dpd_start(struct sa *isakmp_sa) } /* - * All incoming DPD Notify messages enter here. Message has been validated. + * All incoming DPD Notify messages enter here. The generic Notify + * payload has been validated; authentication and the DPD payload + * format are checked here. */ void dpd_handle_notify(struct message *msg, struct payload *p) @@ -147,6 +149,23 @@ dpd_handle_notify(struct message *msg, s struct sa *isakmp_sa = msg->isakmp_sa; u_int16_t notify = GET_ISAKMP_NOTIFY_MSG_TYPE(p->p); u_int32_t p_seq; + + if (!isakmp_sa || (msg->flags & MSG_AUTHENTICATED) == 0) { + LOG_DBG((LOG_MESSAGE, 10, + "dpd_handle_notify: got unauthenticated %s", + constant_name(isakmp_notify_cst, notify))); + return; + } + + if (GET_ISAKMP_NOTIFY_PROTO(p->p) != ISAKMP_PROTO_ISAKMP || + GET_ISAKMP_NOTIFY_SPI_SZ(p->p) != ISAKMP_HDR_COOKIES_LEN || + GET_ISAKMP_GEN_LENGTH(p->p) < ISAKMP_NOTIFY_SPI_OFF + + ISAKMP_HDR_COOKIES_LEN + sizeof p_seq) { + LOG_DBG((LOG_MESSAGE, 10, + "dpd_handle_notify: malformed %s payload", + constant_name(isakmp_notify_cst, notify))); + return; + } /* Extract the sequence number. */ memcpy(&p_seq, p->p + ISAKMP_NOTIFY_SPI_OFF + ISAKMP_HDR_COOKIES_LEN, Index: sbin/isakmpd/exchange.c =================================================================== RCS file: /cvs/src/sbin/isakmpd/exchange.c,v diff -u -p -r1.146 exchange.c --- sbin/isakmpd/exchange.c 3 Oct 2026 01:31:30 -0000 1.146 +++ sbin/isakmpd/exchange.c 23 Oct 2026 21:58:22 -0000 @@ -1430,6 +1430,8 @@ exchange_finalize(struct message *msg) /* If we have nothing to retransmit we can safely remove ourselves. */ if (!exchange->last_sent) exchange_free(exchange); + else + exchange->flags |= EXCHANGE_FLAG_FINALIZED; } /* Stash a nonce into the exchange data. */ Index: sbin/isakmpd/exchange.h =================================================================== RCS file: /cvs/src/sbin/isakmpd/exchange.h,v diff -u -p -r1.38 exchange.h --- sbin/isakmpd/exchange.h 3 Oct 2026 01:31:30 -0000 1.38 +++ sbin/isakmpd/exchange.h 23 Oct 2026 21:58:22 -0000 @@ -224,6 +224,7 @@ struct exchange { #define EXCHANGE_FLAG_NAT_T_RFC 0x0080 /* Peer does RFC NAT-T. */ #define EXCHANGE_FLAG_NAT_T_DRAFT 0x0100 /* Peer does draft NAT-T.*/ #define EXCHANGE_FLAG_OPENBSD 0x0200 /* Peer is OpenBSD */ +#define EXCHANGE_FLAG_FINALIZED 0x0400 /* Finalize function called. */ extern int exchange_add_certs(struct message *); extern int exchange_add_certreqs(struct message *); Index: sbin/isakmpd/isakmpd.8 =================================================================== RCS file: /cvs/src/sbin/isakmpd/isakmpd.8,v diff -u -p -r1.124 isakmpd.8 --- sbin/isakmpd/isakmpd.8 3 Oct 2026 01:31:30 -0000 1.124 +++ sbin/isakmpd/isakmpd.8 23 Oct 2026 21:58:22 -0000 @@ -669,7 +669,7 @@ The FIFO used to manually control .Xr isakmpd.policy 5 , .Xr iked 8 , .Xr sasyncd 8 , -.Xr ssl 8 , +.Xr ssl 8 .Sh STANDARDS .Rs .%A D. Piper Index: sbin/isakmpd/message.c =================================================================== RCS file: /cvs/src/sbin/isakmpd/message.c,v diff -u -p -r1.137 message.c --- sbin/isakmpd/message.c 3 Oct 2026 01:31:30 -0000 1.137 +++ sbin/isakmpd/message.c 23 Oct 2026 21:58:23 -0000 @@ -905,6 +905,15 @@ message_validate_notify(struct message * return -1; } + if (GET_ISAKMP_GEN_LENGTH(p->p) < + ISAKMP_NOTIFY_SPI_OFF + GET_ISAKMP_NOTIFY_SPI_SZ(p->p)) { + LOG_DBG((LOG_MESSAGE, 50, "message_validate_notify: " + "payload too short for SPI size %u", + GET_ISAKMP_NOTIFY_SPI_SZ(p->p))); + message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 1); + return -1; + } + /* Validate the SPI. XXX Just ISAKMP for now. */ if (proto == ISAKMP_PROTO_ISAKMP && GET_ISAKMP_NOTIFY_SPI_SZ(p->p) == ISAKMP_HDR_COOKIES_LEN && @@ -1411,6 +1420,17 @@ message_recv(struct message *msg) message_free(msg); return -1; } + /* + * Encrypted data must be a non-zero multiple of the + * block size. + */ + if (sz - ISAKMP_HDR_SZ == 0 || + (sz - ISAKMP_HDR_SZ) % ks->xf->blocksize != 0) { + log_print("message_recv: bad encrypted message length"); + message_free(msg); + freezero(ks, sizeof(*ks)); + return -1; + } msg->orig = malloc(sz); if (!msg->orig) { message_free(msg); @@ -1993,6 +2013,17 @@ message_check_duplicate(struct message * message_free(msg); return -1; } + } + /* + * A finalized exchange only answers retransmits of the peer's + * last message. Anything else is not ours. + */ + if (exchange->flags & EXCHANGE_FLAG_FINALIZED) { + LOG_DBG((LOG_MESSAGE, 80, + "message_check_duplicate: ignoring message for finalized " + "exchange %p", exchange)); + message_free(msg); + return -1; } /* * As this new message is an indication that state is moving forward Index: sbin/isakmpd/udp.c =================================================================== RCS file: /cvs/src/sbin/isakmpd/udp.c,v diff -u -p -r1.96 udp.c --- sbin/isakmpd/udp.c 3 Oct 2026 01:31:30 -0000 1.96 +++ sbin/isakmpd/udp.c 23 Oct 2026 21:58:23 -0000 @@ -507,12 +507,12 @@ udp_decode_ids(struct transport *t) if (getnameinfo(src, SA_LEN(src), idsrc, sizeof idsrc, NULL, 0, NI_NUMERICHOST) != 0) { log_print("udp_decode_ids: getnameinfo () failed for 'src'"); - strlcpy(idsrc, "", 256); + strlcpy(idsrc, "", sizeof idsrc); } if (getnameinfo(dst, SA_LEN(dst), iddst, sizeof iddst, NULL, 0, NI_NUMERICHOST) != 0) { log_print("udp_decode_ids: getnameinfo () failed for 'dst'"); - strlcpy(iddst, "", 256); + strlcpy(iddst, "", sizeof iddst); } snprintf(result, sizeof result, "src: %s dst: %s", idsrc, iddst); Index: sbin/isakmpd/x509.c =================================================================== RCS file: /cvs/src/sbin/isakmpd/x509.c,v diff -u -p -r1.129 x509.c --- sbin/isakmpd/x509.c 3 Oct 2026 01:15:47 -0000 1.129 +++ sbin/isakmpd/x509.c 23 Oct 2026 21:58:23 -0000 @@ -1279,12 +1279,15 @@ x509_cert_get_key(void *scert, void *key X509 *cert = scert; EVP_PKEY *key; - key = X509_get_pubkey(cert); + key = X509_get0_pubkey(cert); + if (key == NULL) { + log_print("x509_cert_get_key: failed to get public key"); + return 0; + } /* Check if we got the right key type. */ if (EVP_PKEY_id(key) != EVP_PKEY_RSA) { log_print("x509_cert_get_key: public key is not a RSA key"); - X509_free(cert); return 0; } *(RSA **)keyp = RSAPublicKey_dup(EVP_PKEY_get0_RSA(key));