From 6034278a08a6dad7d1af5425eb1698bb91e1dbe2 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Tue, 5 Nov 2019 13:48:41 -0500 Subject: [PATCH] import libreswan-3.29-6.el8 --- .gitignore | 4 + .libreswan.metadata | 4 + ...ibreswan-3.25-1724200-halfopen-shunt.patch | 13 + ...n-3.28-maintain-different-v1v2-split.patch | 68 + SOURCES/libreswan-3.29-1699318-show.patch | 38 + SOURCES/libreswan-3.29-1714331-nss-kdf.patch | 770 +++++++ SOURCES/libreswan-3.29-1723957-audit.patch | 301 +++ ...ibreswan-3.29-CVE-2019-10155-testing.patch | 1830 +++++++++++++++++ SPECS/libreswan.spec | 469 +++++ 9 files changed, 3497 insertions(+) create mode 100644 .gitignore create mode 100644 .libreswan.metadata create mode 100644 SOURCES/libreswan-3.25-1724200-halfopen-shunt.patch create mode 100644 SOURCES/libreswan-3.28-maintain-different-v1v2-split.patch create mode 100644 SOURCES/libreswan-3.29-1699318-show.patch create mode 100644 SOURCES/libreswan-3.29-1714331-nss-kdf.patch create mode 100644 SOURCES/libreswan-3.29-1723957-audit.patch create mode 100644 SOURCES/libreswan-3.29-CVE-2019-10155-testing.patch create mode 100644 SPECS/libreswan.spec diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..af4b6ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +SOURCES/ikev1_dsa.fax.bz2 +SOURCES/ikev1_psk.fax.bz2 +SOURCES/ikev2.fax.bz2 +SOURCES/libreswan-3.29.tar.gz diff --git a/.libreswan.metadata b/.libreswan.metadata new file mode 100644 index 0000000..01d8128 --- /dev/null +++ b/.libreswan.metadata @@ -0,0 +1,4 @@ +b35cd50b8bc0a08b9c07713bf19c72d53bfe66bb SOURCES/ikev1_dsa.fax.bz2 +861d97bf488f9e296cad8c43ab72f111a5b1a848 SOURCES/ikev1_psk.fax.bz2 +fcaf77f3deae3d8e99cdb3b1f8abea63167a0633 SOURCES/ikev2.fax.bz2 +492cd1cf18c06e47b2864a57a355a7f5393f80cc SOURCES/libreswan-3.29.tar.gz diff --git a/SOURCES/libreswan-3.25-1724200-halfopen-shunt.patch b/SOURCES/libreswan-3.25-1724200-halfopen-shunt.patch new file mode 100644 index 0000000..839b7c3 --- /dev/null +++ b/SOURCES/libreswan-3.25-1724200-halfopen-shunt.patch @@ -0,0 +1,13 @@ +diff -Naur libreswan-3.25-orig/programs/pluto/state.c libreswan-3.25/programs/pluto/state.c +--- libreswan-3.25-orig/programs/pluto/state.c 2019-07-03 15:52:47.246474906 -0400 ++++ libreswan-3.25/programs/pluto/state.c 2019-07-03 15:54:37.671850020 -0400 +@@ -1101,7 +1101,8 @@ + #endif + + /* If we are failed OE initiator, make shunt bare */ +- if (IS_IKE_SA(st) && (c->policy & POLICY_OPPORTUNISTIC) && ++ if (IS_IKE_SA(st) && c->newest_isakmp_sa == st->st_serialno && ++ (c->policy & POLICY_OPPORTUNISTIC) && + (st->st_state == STATE_PARENT_I1 || st->st_state == STATE_PARENT_I2)) { + ipsec_spi_t failure_shunt = shunt_policy_spi(c, FALSE /* failure_shunt */); + ipsec_spi_t nego_shunt = shunt_policy_spi(c, TRUE /* negotiation shunt */); diff --git a/SOURCES/libreswan-3.28-maintain-different-v1v2-split.patch b/SOURCES/libreswan-3.28-maintain-different-v1v2-split.patch new file mode 100644 index 0000000..dd53f19 --- /dev/null +++ b/SOURCES/libreswan-3.28-maintain-different-v1v2-split.patch @@ -0,0 +1,68 @@ +diff -Naur libreswan-3.28-orig/lib/libipsecconf/confread.c libreswan-3.28/lib/libipsecconf/confread.c +--- libreswan-3.28-orig/lib/libipsecconf/confread.c 2019-05-20 23:01:54.000000000 -0400 ++++ libreswan-3.28/lib/libipsecconf/confread.c 2019-05-21 16:59:20.861415770 -0400 +@@ -1273,13 +1273,16 @@ + + switch (conn->options[KNCF_IKEv2]) { + case fo_never: +- case fo_permit: + conn->policy |= POLICY_IKEV1_ALLOW; + /* clear any inherited default */ + conn->policy &= ~POLICY_IKEV2_ALLOW; + break; +- ++ case fo_permit: ++ starter_error_append(perrl, "ikev2=permit is no longer accepted. Use ikev2=insist or ikev2=no|never"); ++ return TRUE; + case fo_propose: ++ starter_error_append(perrl, "ikev2=propose or ikev2=yes is no longer accepted. Use ikev2=insist or ikev2=no|never"); ++ return TRUE; + case fo_insist: + conn->policy |= POLICY_IKEV2_ALLOW; + /* clear any inherited default */ +diff -Naur libreswan-3.28-orig/programs/configs/d.ipsec.conf/ikev2.xml libreswan-3.28/programs/configs/d.ipsec.conf/ikev2.xml +--- libreswan-3.28-orig/programs/configs/d.ipsec.conf/ikev2.xml 2019-05-20 23:01:54.000000000 -0400 ++++ libreswan-3.28/programs/configs/d.ipsec.conf/ikev2.xml 2019-05-21 16:54:07.584141191 -0400 +@@ -1,13 +1,15 @@ + + ikev2 + +-Whether to use IKEv1 (RFC 4301) or IKEv2 (RFC 7296) settings to be used. +-Currently the accepted values are no(the default), +-signifying only IKEv1 is accepted, or yes, ++Wether to use IKEv1 (RFC 4301) or IKEv2 (RFC 7296) as the Internet Key Exchange (IKE) protcol. ++Currently the accepted values are no (or never) ++signifying only IKEv1 is accepted, or insist(the default), + signifying only IKEv2 is accepted. Previous versions allowed the keywords +-propose or permit +-that would allow either IKEv1 or IKEv2, but this is no longer supported. The +-permit option is interpreted as no and the propose option is interpreted as yes. ++propose, yes or permit ++that would allow either IKEv1 or IKEv2, but this is no longer supported and both options ++now cause the connection to fail to load. WARNING: This behaviour differs from upstream ++libreswan, which only accepts yes or no where yes means ++the same as insist. + + + +diff -Naur libreswan-3.28-orig/programs/whack/whack.c libreswan-3.28/programs/whack/whack.c +--- libreswan-3.28-orig/programs/whack/whack.c 2019-05-20 23:01:54.000000000 -0400 ++++ libreswan-3.28/programs/whack/whack.c 2019-05-21 17:01:37.868865569 -0400 +@@ -741,7 +741,7 @@ + + PS("ikev1-allow", IKEV1_ALLOW), + PS("ikev2-allow", IKEV2_ALLOW), +- PS("ikev2-propose", IKEV2_ALLOW), /* map onto allow */ ++ /* not in RHEL8 PS("ikev2-propose", IKEV2_ALLOW),*/ + + PS("allow-narrowing", IKEV2_ALLOW_NARROWING), + #ifdef XAUTH_HAVE_PAM +@@ -1683,7 +1683,7 @@ + + /* --ikev1-allow */ + case CDP_SINGLETON + POLICY_IKEV1_ALLOW_IX: +- /* --ikev2-allow (now also --ikev2-propose) */ ++ /* --ikev2-allow */ + case CDP_SINGLETON + POLICY_IKEV2_ALLOW_IX: + + /* --allow-narrowing */ diff --git a/SOURCES/libreswan-3.29-1699318-show.patch b/SOURCES/libreswan-3.29-1699318-show.patch new file mode 100644 index 0000000..dff8604 --- /dev/null +++ b/SOURCES/libreswan-3.29-1699318-show.patch @@ -0,0 +1,38 @@ +diff -Naur libreswan-3.29-orig/programs/show/show.in libreswan-3.29/programs/show/show.in +--- libreswan-3.29-orig/programs/show/show.in 2019-07-31 20:03:51.794714920 -0400 ++++ libreswan-3.29/programs/show/show.in 2019-07-31 20:02:38.792224647 -0400 +@@ -1,7 +1,7 @@ + #!/usr/bin/python + + import sys +-import commands ++import subprocess + import argparse + try: + import ipaddress +@@ -42,14 +42,14 @@ + source = args.source + else: + getsrccmd = "ip -o ro get %s" % dest +- status, output = commands.getstatusoutput(getsrccmd) ++ output = subprocess.getoutput([getsrccmd]) + try: + source = output.split("src")[1].strip().split(" ")[0] + except Exception: + sys.exit("failed to find source ip for destination %s" % dest) + + if args.debug: +- print "Need to find matching IPsec policy for %s/32 <=> %s/32" % (source, dest) ++ print("Need to find matching IPsec policy for %s/32 <=> %s/32" % (source, dest)) + + if dest: + if "/" in source: +@@ -65,7 +65,7 @@ + sys.exit(1) + + ipxfrmcmd = 'ip -o xfrm pol | grep -v socket | grep "dir out"' +- status, output = commands.getstatusoutput(ipxfrmcmd) ++ output = subprocess.getoutput([ipxfrmcmd]) + polsrc = "" + poldst = "" + for line in output.split("\n"): diff --git a/SOURCES/libreswan-3.29-1714331-nss-kdf.patch b/SOURCES/libreswan-3.29-1714331-nss-kdf.patch new file mode 100644 index 0000000..16b8a5a --- /dev/null +++ b/SOURCES/libreswan-3.29-1714331-nss-kdf.patch @@ -0,0 +1,770 @@ +diff -Naur libreswan-3.29-orig/lib/libswan/ike_alg_aes.c libreswan-3.29/lib/libswan/ike_alg_aes.c +--- libreswan-3.29-orig/lib/libswan/ike_alg_aes.c 2019-06-10 10:22:04.000000000 -0400 ++++ libreswan-3.29/lib/libswan/ike_alg_aes.c 2019-08-11 13:31:13.849294693 -0400 +@@ -23,14 +23,21 @@ + + #include "constants.h" /* for BYTES_FOR_BITS() */ + #include "ietf_constants.h" ++ + #include "ike_alg.h" ++#include "ike_alg_encrypt.h" ++#include "ike_alg_integ.h" ++#include "ike_alg_prf.h" ++ + #include "ike_alg_encrypt_nss_cbc_ops.h" + #include "ike_alg_encrypt_nss_ctr_ops.h" + #include "ike_alg_encrypt_nss_gcm_ops.h" ++#ifdef CKM_AES_XCBC_MAC ++#include "ike_alg_prf_nss_ops.h" ++#else + #include "ike_alg_prf_nss_xcbc_ops.h" +-#include "ike_alg_encrypt.h" +-#include "ike_alg_integ.h" +-#include "ike_alg_prf.h" ++#endif ++ + #include "sadb.h" + + const struct encrypt_desc ike_alg_encrypt_aes_cbc = { +@@ -313,6 +320,7 @@ + .encrypt_kernel_audit_name = "AES_CCM_C", + }; + ++#ifdef USE_PRF_AES_XCBC + const struct prf_desc ike_alg_prf_aes_xcbc = { + .common = { + .name = "aes_xcbc", +@@ -326,14 +334,23 @@ + }, + .fips = false, + }, ++#ifdef CKM_AES_XCBC_MAC ++ .nss = { ++ .mechanism = CKM_AES_XCBC_MAC, ++ }, ++ .prf_ops = &ike_alg_prf_nss_ops, ++#else ++ /* XXX: NSS encryption algorithm used by custom XCBC */ + .nss = { + .mechanism = CKM_AES_ECB, + }, ++ .prf_ops = &ike_alg_prf_nss_xcbc_ops, ++#endif + .prf_key_size = BYTES_FOR_BITS(128), + .prf_output_size = BYTES_FOR_BITS(128), +- .prf_ops = &ike_alg_prf_nss_xcbc_ops, + .prf_ike_audit_name = "aes_xcbc", + }; ++#endif + + const struct integ_desc ike_alg_integ_aes_xcbc = { + .common = { +@@ -351,7 +368,7 @@ + .integ_keymat_size = AES_XCBC_DIGEST_SIZE, + .integ_output_size = AES_XCBC_DIGEST_SIZE_TRUNC, /* XXX 96 */ + .integ_ikev1_ah_transform = AH_AES_XCBC_MAC, +-#ifdef USE_XCBC ++#ifdef USE_PRF_AES_XCBC + .prf = &ike_alg_prf_aes_xcbc, + #endif + #ifdef SADB_X_AALG_AES_XCBC_MAC +diff -Naur libreswan-3.29-orig/lib/libswan/ike_alg.c libreswan-3.29/lib/libswan/ike_alg.c +--- libreswan-3.29-orig/lib/libswan/ike_alg.c 2019-06-10 10:22:04.000000000 -0400 ++++ libreswan-3.29/lib/libswan/ike_alg.c 2019-08-11 13:31:13.850294706 -0400 +@@ -478,7 +478,7 @@ + &ike_alg_prf_sha2_384, + &ike_alg_prf_sha2_512, + #endif +-#ifdef USE_XCBC ++#ifdef USE_PRF_AES_XCBC + &ike_alg_prf_aes_xcbc, + #endif + }; +diff -Naur libreswan-3.29-orig/lib/libswan/ike_alg_md5.c libreswan-3.29/lib/libswan/ike_alg_md5.c +--- libreswan-3.29-orig/lib/libswan/ike_alg_md5.c 2019-06-10 10:22:04.000000000 -0400 ++++ libreswan-3.29/lib/libswan/ike_alg_md5.c 2019-08-11 13:31:13.851294720 -0400 +@@ -26,7 +26,7 @@ + #include "ike_alg_hash.h" + #include "ike_alg_prf.h" + #include "ike_alg_hash_nss_ops.h" +-#include "ike_alg_prf_hmac_ops.h" ++#include "ike_alg_prf_nss_ops.h" + #include "sadb.h" + + const struct hash_desc ike_alg_hash_md5 = { +@@ -63,10 +63,13 @@ + [IKEv2_ALG_ID] = IKEv2_PRF_HMAC_MD5, + }, + }, ++ .nss = { ++ .mechanism = CKM_MD5_HMAC, ++ }, + .prf_key_size = MD5_DIGEST_SIZE, + .prf_output_size = MD5_DIGEST_SIZE, + .hasher = &ike_alg_hash_md5, +- .prf_ops = &ike_alg_prf_hmac_ops, ++ .prf_ops = &ike_alg_prf_nss_ops, + .prf_ike_audit_name = "md5", + }; + +diff -Naur libreswan-3.29-orig/mk/config.mk libreswan-3.29/mk/config.mk +--- libreswan-3.29-orig/mk/config.mk 2019-08-11 13:30:45.756906229 -0400 ++++ libreswan-3.29/mk/config.mk 2019-08-11 13:31:13.852294734 -0400 +@@ -239,6 +239,18 @@ + NSS_UTIL_LDFLAGS ?= -lnssutil3 + NSPR_LDFLAGS ?= -lnspr4 + ++# Use the NSS Key Derivation Function (KDF) instead of using the NSS ++# secure hash functions to build our own PRF. With this enabled, ++# libreswan itself no longer needs to be FIPS validated. ++# Requires NSS >= 3.44 ++USE_NSS_PRF?=false ++ifeq ($(USE_NSS_PRF),true) ++NSSFLAGS+=-DUSE_NSS_PRF ++USE_NSS_AVA_COPY=false ++endif ++ ++# ++# + # Use local copy of nss function CERT_CompareAVA + # See https://bugzilla.mozilla.org/show_bug.cgi?id=1336487 + # This work-around is needed with nss versions before 3.30. +diff -Naur libreswan-3.29-orig/mk/userland-cflags.mk libreswan-3.29/mk/userland-cflags.mk +--- libreswan-3.29-orig/mk/userland-cflags.mk 2019-06-10 10:22:04.000000000 -0400 ++++ libreswan-3.29/mk/userland-cflags.mk 2019-08-11 13:31:13.853294748 -0400 +@@ -269,9 +269,10 @@ + LIBTWOFISH= ${OBJDIRTOP}/lib/libcrypto/libtwofish/libtwofish.a + endif + +-USE_XCBC ?= true +-ifeq ($(USE_XCBC),true) +-USERLAND_CFLAGS += -DUSE_XCBC ++# Requires NSS >= 3.44 or backport ++USE_PRF_AES_XCBC ?= true ++ifeq ($(USE_PRF_AES_XCBC),true) ++USERLAND_CFLAGS += -DUSE_PRF_AES_XCBC + endif + + # +diff -Naur libreswan-3.29-orig/programs/pluto/crypt_symkey.c libreswan-3.29/programs/pluto/crypt_symkey.c +--- libreswan-3.29-orig/programs/pluto/crypt_symkey.c 2019-06-10 10:22:04.000000000 -0400 ++++ libreswan-3.29/programs/pluto/crypt_symkey.c 2019-08-11 13:31:13.854294762 -0400 +@@ -15,7 +15,6 @@ + * for more details. + */ + +-#include "libreswan.h" + #include "lswalloc.h" + #include "lswlog.h" + #include "ike_alg.h" +@@ -23,6 +22,7 @@ + #include "crypto.h" + #include "lswfips.h" + #include "lswnss.h" ++#include "crypt_prf.h" /* hack */ + + #define SPACES " " + +@@ -590,9 +590,51 @@ + + PK11SymKey *prf_key_from_symkey_bytes(const char *name, + const struct prf_desc *prf, +- size_t symkey_start_byte, size_t sizeof_symkey, ++ size_t symkey_start_byte, size_t symkey_size, + PK11SymKey *source_key) + { ++#ifdef CKM_AES_XCBC_MAC ++ if (prf->nss.mechanism == CKM_AES_XCBC_MAC && ++ symkey_size != prf->prf_key_size) { ++ PK11SymKey *tmp = symkey_from_symkey("tmp", source_key, ++ CKM_VENDOR_DEFINED, /*flags*/0, ++ symkey_start_byte, symkey_size); ++ /* ++ * code lifted from ike_alg_prf_nss_xcbc_ops.c ++ */ ++ size_t dkey_sz = sizeof_symkey(tmp); ++ if (dkey_sz < prf->prf_key_size) { ++ DBGF(DBG_CRYPT, "XCBC: Key %zd<%zd too small, padding with zeros", ++ dkey_sz, prf->prf_key_size); ++ /* ++ * right pad with zeros ++ */ ++ chunk_t zeros = alloc_chunk(prf->prf_key_size - dkey_sz, "zeros"); ++ append_symkey_chunk(&tmp, zeros); ++ freeanychunk(zeros); ++ } else { ++ pexpect(dkey_sz > prf->prf_key_size); ++ DBGF(DBG_CRYPT, "XCBC: Key %zd>%zd too big, rehashing to size", ++ dkey_sz, prf->prf_key_size); ++ /* ++ * put the key through the mac with a zero ++ * key; recursive ++ */ ++ chunk_t zeros = alloc_chunk(prf->prf_key_size, "zeros"); ++ PK11SymKey *zero_key = prf_key_from_bytes("zeros", prf, zeros.ptr, zeros.len); ++ freeanychunk(zeros); ++ struct crypt_prf *xmac = crypt_prf_init_symkey("xmac", prf, "zero", zero_key); ++ crypt_prf_update_symkey(xmac, "tmp", tmp); ++ PK11SymKey *tmp2 = crypt_prf_final_symkey(&xmac); ++ release_symkey(name, "tmp2", &tmp); ++ tmp = tmp2; ++ } ++ PK11SymKey *key = symkey_from_symkey(name, tmp, CKM_AES_XCBC_MAC, CKF_SIGN, ++ 0, prf->prf_key_size); ++ release_symkey(name, "tmp", &tmp); ++ return key; ++ } ++#endif + /* + * NSS expects a key's mechanism to match the NSS algorithm + * the key is intended for. If this is wrong then the +@@ -614,7 +656,7 @@ + mechanism = prf->nss.mechanism; + } + return symkey_from_symkey(name, source_key, mechanism, flags, +- symkey_start_byte, sizeof_symkey); ++ symkey_start_byte, symkey_size); + } + + /* +@@ -656,9 +698,13 @@ + PK11SymKey *key_from_symkey_bytes(PK11SymKey *source_key, + size_t next_byte, size_t sizeof_key) + { +- return symkey_from_symkey("result", source_key, +- CKM_EXTRACT_KEY_FROM_KEY, +- 0, next_byte, sizeof_key); ++ if (sizeof_key == 0) { ++ return NULL; ++ } else { ++ return symkey_from_symkey("result", source_key, ++ CKM_EXTRACT_KEY_FROM_KEY, ++ 0, next_byte, sizeof_key); ++ } + } + + /* +diff -Naur libreswan-3.29-orig/programs/pluto/ikev1_prf.c libreswan-3.29/programs/pluto/ikev1_prf.c +--- libreswan-3.29-orig/programs/pluto/ikev1_prf.c 2019-06-10 10:22:04.000000000 -0400 ++++ libreswan-3.29/programs/pluto/ikev1_prf.c 2019-08-11 13:31:13.855294776 -0400 +@@ -17,8 +17,11 @@ + * for more details. + */ + ++#include "lswlog.h" /* for LSWLOG_PEXPECT() */ ++ + #include "ikev1_prf.h" + ++#include "ike_alg.h" + #include "crypt_prf.h" + #include "crypt_symkey.h" + +@@ -32,6 +35,25 @@ + const chunk_t Nr, + /*const*/ PK11SymKey *dh_secret /* NSS doesn't do const */) + { ++#ifdef USE_NSS_PRF ++ CK_NSS_IKE_PRF_DERIVE_PARAMS ike_prf_params = { ++ .prfMechanism = prf_desc->nss.mechanism, ++ .bDataAsKey = CK_TRUE, ++ .bRekey = CK_FALSE, ++ .pNi = Ni.ptr, ++ .ulNiLen = Ni.len, ++ .pNr = Nr.ptr, ++ .ulNrLen = Nr.len, ++ }; ++ SECItem params = { ++ .data = (unsigned char *)&ike_prf_params, ++ .len = sizeof(ike_prf_params), ++ }; ++ ++ return PK11_Derive(dh_secret, CKM_NSS_IKE_PRF_DERIVE, ¶ms, ++ CKM_NSS_IKE1_PRF_DERIVE, CKA_DERIVE, ++ 0); ++#else + /* key = Ni|Nr */ + chunk_t key = clone_chunk_chunk(Ni, Nr, "key = Ni|Nr"); + struct crypt_prf *prf = crypt_prf_init_chunk("SKEYID sig", +@@ -42,6 +64,7 @@ + crypt_prf_update_symkey(prf, "g^xy", dh_secret); + /* generate */ + return crypt_prf_final_symkey(&prf); ++#endif + } + + /* +@@ -51,6 +74,33 @@ + chunk_t pre_shared_key, + chunk_t Ni, chunk_t Nr) + { ++#ifdef USE_NSS_PRF ++ PK11SymKey *psk = prf_key_from_bytes("psk", prf_desc, ++ pre_shared_key.ptr, pre_shared_key.len); ++ PK11SymKey *skeyid; ++ if (psk == NULL) { ++ return NULL; ++ } ++ ++ CK_NSS_IKE_PRF_DERIVE_PARAMS ike_prf_params = { ++ .prfMechanism = prf_desc->nss.mechanism, ++ .bDataAsKey = CK_FALSE, ++ .bRekey = CK_FALSE, ++ .pNi = Ni.ptr, ++ .ulNiLen = Ni.len, ++ .pNr = Nr.ptr, ++ .ulNrLen = Nr.len, ++ }; ++ SECItem params = { ++ .data = (unsigned char *)&ike_prf_params, ++ .len = sizeof(ike_prf_params), ++ }; ++ skeyid = PK11_Derive(psk, CKM_NSS_IKE_PRF_DERIVE, ¶ms, ++ CKM_NSS_IKE1_PRF_DERIVE, CKA_DERIVE, ++ 0 ); ++ release_symkey("SKEYID psk", "psk", &psk); ++ return skeyid; ++#else + /* key = pre-shared-key */ + struct crypt_prf *prf = crypt_prf_init_chunk("SKEYID psk", prf_desc, + "psk", pre_shared_key); +@@ -59,6 +109,7 @@ + crypt_prf_update_chunk(prf, "Nr", Nr); + /* generate */ + return crypt_prf_final_symkey(&prf); ++#endif + } + + /* +@@ -69,6 +120,26 @@ + PK11SymKey *dh_secret, + chunk_t cky_i, chunk_t cky_r) + { ++#ifdef USE_NSS_PRF ++ CK_NSS_IKE1_PRF_DERIVE_PARAMS ike1_prf_params = { ++ .prfMechanism = prf_desc->nss.mechanism, ++ .bHasPrevKey = CK_FALSE, ++ .hKeygxy = PK11_GetSymKeyHandle(dh_secret), ++ .pCKYi = cky_i.ptr, ++ .ulCKYiLen = cky_i.len, ++ .pCKYr = cky_r.ptr, ++ .ulCKYrLen = cky_r.len, ++ .keyNumber = 0, ++ }; ++ SECItem params = { ++ .data = (unsigned char *)&ike1_prf_params, ++ .len = sizeof(ike1_prf_params), ++ }; ++ ++ return PK11_Derive(skeyid, CKM_NSS_IKE1_PRF_DERIVE, ¶ms, ++ CKM_EXTRACT_KEY_FROM_KEY, CKA_DERIVE, ++ 0); ++#else + /* key = SKEYID */ + struct crypt_prf *prf = crypt_prf_init_symkey("SKEYID_d", prf_desc, + "SKEYID", skeyid); +@@ -79,6 +150,7 @@ + crypt_prf_update_byte(prf, "0", 0); + /* generate */ + return crypt_prf_final_symkey(&prf); ++#endif + } + + /* +@@ -89,6 +161,27 @@ + PK11SymKey *skeyid_d, PK11SymKey *dh_secret, + chunk_t cky_i, chunk_t cky_r) + { ++#ifdef USE_NSS_PRF ++ CK_NSS_IKE1_PRF_DERIVE_PARAMS ike1_prf_params = { ++ .prfMechanism = prf_desc->nss.mechanism, ++ .bHasPrevKey = CK_TRUE, ++ .hKeygxy = PK11_GetSymKeyHandle(dh_secret), ++ .hPrevKey = PK11_GetSymKeyHandle(skeyid_d), ++ .pCKYi = cky_i.ptr, ++ .ulCKYiLen = cky_i.len, ++ .pCKYr = cky_r.ptr, ++ .ulCKYrLen = cky_r.len, ++ .keyNumber = 1, ++ }; ++ SECItem params = { ++ .data = (unsigned char *)&ike1_prf_params, ++ .len = sizeof(ike1_prf_params), ++ }; ++ ++ return PK11_Derive(skeyid, CKM_NSS_IKE1_PRF_DERIVE, ¶ms, ++ CKM_EXTRACT_KEY_FROM_KEY, CKA_DERIVE, ++ 0); ++#else + /* key = SKEYID */ + struct crypt_prf *prf = crypt_prf_init_symkey("SKEYID_a", prf_desc, + "SKEYID", skeyid); +@@ -100,6 +193,7 @@ + crypt_prf_update_byte(prf, "1", 1); + /* generate */ + return crypt_prf_final_symkey(&prf); ++#endif + } + + /* +@@ -110,6 +204,27 @@ + PK11SymKey *skeyid_a, PK11SymKey *dh_secret, + chunk_t cky_i, chunk_t cky_r) + { ++#ifdef USE_NSS_PRF ++ CK_NSS_IKE1_PRF_DERIVE_PARAMS ike1_prf_params = { ++ .prfMechanism = prf_desc->nss.mechanism, ++ .bHasPrevKey = CK_TRUE, ++ .hKeygxy = PK11_GetSymKeyHandle(dh_secret), ++ .hPrevKey = PK11_GetSymKeyHandle(skeyid_a), ++ .pCKYi = cky_i.ptr, ++ .ulCKYiLen = cky_i.len, ++ .pCKYr = cky_r.ptr, ++ .ulCKYrLen = cky_r.len, ++ .keyNumber = 2, ++ }; ++ SECItem params = { ++ .data = (unsigned char *)&ike1_prf_params, ++ .len = sizeof(ike1_prf_params), ++ }; ++ ++ return PK11_Derive(skeyid, CKM_NSS_IKE1_PRF_DERIVE, ¶ms, ++ CKM_EXTRACT_KEY_FROM_KEY, CKA_DERIVE, ++ 0); ++#else + /* key = SKEYID */ + struct crypt_prf *prf = crypt_prf_init_symkey("SKEYID_e", prf_desc, + "SKEYID", skeyid); +@@ -121,6 +236,7 @@ + crypt_prf_update_byte(prf, "2", 2); + /* generate */ + return crypt_prf_final_symkey(&prf); ++#endif + } + + PK11SymKey *appendix_b_keymat_e(const struct prf_desc *prf_desc, +@@ -128,6 +244,20 @@ + PK11SymKey *skeyid_e, + unsigned required_keymat) + { ++#ifdef USE_NSS_PRF ++ CK_MECHANISM_TYPE mechanism = prf_desc->nss.mechanism; ++ CK_MECHANISM_TYPE target = encrypter->nss.mechanism; ++ SECItem params = { ++ .data = (unsigned char *)&mechanism, ++ .len = sizeof(mechanism), ++ }; ++ /* for when ENCRYPTER isn't NSS */ ++ if (target == 0) target = CKM_EXTRACT_KEY_FROM_KEY; ++ ++ return PK11_DeriveWithFlags(skeyid_e, CKM_NSS_IKE1_APP_B_PRF_DERIVE, ++ ¶ms, target, CKA_ENCRYPT, ++ required_keymat, CKF_DECRYPT); ++#else + if (sizeof_symkey(skeyid_e) >= required_keymat) { + return encrypt_key_from_symkey_bytes("keymat", encrypter, + 0, required_keymat, +@@ -160,4 +290,5 @@ + keymat); + release_symkey(__func__, "keymat", &keymat); + return cryptkey; ++#endif + } +diff -Naur libreswan-3.29-orig/programs/pluto/ikev2_prf.c libreswan-3.29/programs/pluto/ikev2_prf.c +--- libreswan-3.29-orig/programs/pluto/ikev2_prf.c 2019-06-10 10:22:04.000000000 -0400 ++++ libreswan-3.29/programs/pluto/ikev2_prf.c 2019-08-11 13:33:13.680951735 -0400 +@@ -32,12 +32,44 @@ + /* + * IKEv2 - RFC4306 2.14 SKEYSEED - calculation. + */ ++#ifdef USE_NSS_PRF ++static PK11SymKey *ikev2_prfplus_key_data( ++ const struct prf_desc *prf_desc, ++ PK11SymKey *key, ++ PK11SymKey *seed_key, ++ chunk_t seed_data, ++ size_t required_keymat) ++{ ++ CK_NSS_IKE_PRF_PLUS_DERIVE_PARAMS ike_prf_plus_params = { ++ .pSeedData = seed_data.ptr, ++ .ulSeedDataLen = seed_data.len, ++ .prfMechanism = prf_desc->nss.mechanism, ++ }; ++ if (seed_key == NULL) { ++ ike_prf_plus_params.bHasSeedKey = CK_FALSE; ++ } else { ++ ike_prf_plus_params.bHasSeedKey = CK_TRUE; ++ ike_prf_plus_params.hSeedKey = PK11_GetSymKeyHandle(seed_key); ++ } ++ SECItem params = { ++ .data = (unsigned char *)&ike_prf_plus_params, ++ .len = sizeof(ike_prf_plus_params), ++ }; ++ ++ return PK11_Derive(key, CKM_NSS_IKE_PRF_PLUS_DERIVE, ¶ms, ++ CKM_EXTRACT_KEY_FROM_KEY, CKA_DERIVE, ++ required_keymat); ++} ++#endif + + PK11SymKey *ikev2_prfplus(const struct prf_desc *prf_desc, + PK11SymKey *key, + PK11SymKey *seed, + size_t required_keymat) + { ++#ifdef USE_NSS_PRF ++ return ikev2_prfplus_key_data(prf_desc, key, seed, empty_chunk, required_keymat); ++#else + uint8_t count = 1; + + /* T1(prfplus) = prf(KEY, SEED|1) */ +@@ -66,6 +98,7 @@ + } + release_symkey(__func__, "old_t[final]", &old_t); + return prfplus; ++#endif + } + + /* +@@ -77,6 +110,33 @@ + const chunk_t Ni, const chunk_t Nr, + PK11SymKey *dh_secret) + { ++ ++#ifdef USE_NSS_PRF ++ int is_aes_prf = 0; ++ switch (prf_desc->common.id[IKEv2_ALG_ID]) { ++ case IKEv2_PRF_AES128_CMAC: ++ case IKEv2_PRF_AES128_XCBC: ++ is_aes_prf = 1; ++ } ++ ++ CK_NSS_IKE_PRF_DERIVE_PARAMS ike_prf_params = { ++ .prfMechanism = prf_desc->nss.mechanism, ++ .bDataAsKey = CK_TRUE, ++ .bRekey = CK_FALSE, ++ .pNi = Ni.ptr, ++ .ulNiLen = is_aes_prf ? BYTES_FOR_BITS(64) : Ni.len, ++ .pNr = Nr.ptr, ++ .ulNrLen = is_aes_prf ? BYTES_FOR_BITS(64) : Nr.len, ++ }; ++ SECItem params = { ++ .data = (unsigned char *)&ike_prf_params, ++ .len = sizeof(ike_prf_params), ++ }; ++ ++ return PK11_Derive(dh_secret, CKM_NSS_IKE_PRF_DERIVE, ¶ms, ++ CKM_NSS_IKE_PRF_PLUS_DERIVE, CKA_DERIVE, ++ 0); ++#else + /* + * 2.14. Generating Keying Material for the IKE SA + * +@@ -117,6 +177,7 @@ + crypt_prf_update_symkey(prf, "g^ir", dh_secret); + /* generate */ + return crypt_prf_final_symkey(&prf); ++#endif + } + + /* +@@ -127,6 +188,26 @@ + PK11SymKey *new_dh_secret, + const chunk_t Ni, const chunk_t Nr) + { ++#ifdef USE_NSS_PRF ++ CK_NSS_IKE_PRF_DERIVE_PARAMS ike_prf_params = { ++ .prfMechanism = prf_desc->nss.mechanism, ++ .bDataAsKey = CK_FALSE, ++ .bRekey = CK_TRUE, ++ .hNewKey = PK11_GetSymKeyHandle(new_dh_secret), ++ .pNi = Ni.ptr, ++ .ulNiLen = Ni.len, ++ .pNr = Nr.ptr, ++ .ulNrLen = Nr.len, ++ }; ++ SECItem params = { ++ .data = (unsigned char *)&ike_prf_params, ++ .len = sizeof(ike_prf_params), ++ }; ++ ++ return PK11_Derive(SK_d_old, CKM_NSS_IKE_PRF_DERIVE, ¶ms, ++ CKM_NSS_IKE_PRF_PLUS_DERIVE, CKA_DERIVE, ++ 0); ++#else + /* key = SK_d (old) */ + struct crypt_prf *prf = crypt_prf_init_symkey("ike sa rekey skeyseed", prf_desc, + "SK_d (old)", SK_d_old); +@@ -141,6 +222,7 @@ + crypt_prf_update_chunk(prf, "Nr", Nr); + /* generate */ + return crypt_prf_final_symkey(&prf); ++#endif + } + + /* +@@ -152,6 +234,17 @@ + const ike_spis_t *SPIir, + size_t required_bytes) + { ++#ifdef USE_NSS_PRF ++ chunk_t seed_data; ++ PK11SymKey *prf_plus; ++ ++ seed_data = clone_chunk_chunk(Ni, Nr, "seed_data = Ni || Nr"); ++ append_chunk_bytes("seed_data = Nir || SPIi", &seed_data, &SPIir->initiator, sizeof(SPIir->initiator)); ++ append_chunk_bytes("seed_data = Nir || SPIir", &seed_data, &SPIir->responder, sizeof(SPIir->responder)); ++ prf_plus = ikev2_prfplus_key_data(prf_desc, skeyseed, NULL, seed_data, required_bytes); ++ freeanychunk(seed_data); ++ return prf_plus; ++#else + PK11SymKey *data = symkey_from_chunk("data", Ni); + append_symkey_chunk(&data, Nr); + append_symkey_bytes(&data, &SPIir->initiator, sizeof(SPIir->initiator)); +@@ -161,6 +254,7 @@ + required_bytes); + release_symkey(__func__, "data", &data); + return prfplus; ++#endif + } + + /* +@@ -172,6 +266,24 @@ + const chunk_t Ni, const chunk_t Nr, + size_t required_bytes) + { ++ if (required_bytes == 0) { ++ /* ++ * For instance esp=null-none. Caller should ++ * interpret NULL to mean empty (NSS doesn't create ++ * zero length keys). ++ */ ++ dbg("No CHILD SA KEMAT is required"); ++ return NULL; ++ } ++#ifdef USE_NSS_PRF ++ chunk_t seed_data; ++ PK11SymKey *prf_plus; ++ ++ seed_data = clone_chunk_chunk(Ni, Nr, "seed_data = Ni || Nr"); ++ prf_plus = ikev2_prfplus_key_data(prf_desc, SK_d, new_dh_secret, seed_data, required_bytes); ++ freeanychunk(seed_data); ++ return prf_plus; ++#else + PK11SymKey *data; + if (new_dh_secret == NULL) { + data = symkey_from_chunk("data", Ni); +@@ -185,4 +297,5 @@ + required_bytes); + release_symkey(__func__, "data", &data); + return prfplus; ++#endif + } +diff -Naur libreswan-3.29-orig/programs/pluto/ikev2_psk.c libreswan-3.29/programs/pluto/ikev2_psk.c +--- libreswan-3.29-orig/programs/pluto/ikev2_psk.c 2019-06-10 10:22:04.000000000 -0400 ++++ libreswan-3.29/programs/pluto/ikev2_psk.c 2019-08-11 13:31:13.858294817 -0400 +@@ -181,6 +181,36 @@ + PK11SymKey *prf_psk; + + { ++ static const char psk_key_pad_str[] = "Key Pad for IKEv2"; /* RFC 4306 2:15 */ ++#ifdef USE_NSS_PRF ++ CK_NSS_IKE_PRF_DERIVE_PARAMS ike_prf_params; ++ SECItem params; ++ CK_MECHANISM_TYPE prf_mech = st->st_oakley.ta_prf->nss.mechanism; ++ PK11SymKey *pss_key = prf_key_from_bytes("pss", st->st_oakley.ta_prf, ++ pss->ptr, pss->len); ++ if (pss_key == NULL) { ++ if (libreswan_fipsmode()) { ++ PASSERT_FAIL("FIPS: failure creating %s PRF context for digesting PSK", ++ st->st_oakley.ta_prf->common.name); ++ } ++ loglog(RC_LOG_SERIOUS, ++ "failure creating %s PRF context for digesting PSK", ++ st->st_oakley.ta_prf->common.name); ++ return FALSE; ++ } ++ ++ ike_prf_params.prfMechanism = prf_mech; ++ ike_prf_params.bDataAsKey = CK_FALSE; ++ ike_prf_params.bRekey = CK_FALSE; ++ ike_prf_params.pNi = (CK_BYTE_PTR) psk_key_pad_str; ++ ike_prf_params.ulNiLen = sizeof(psk_key_pad_str) - 1; ++ ike_prf_params.pNr = NULL; ++ ike_prf_params.ulNrLen = 0; ++ params.data = (unsigned char *)&ike_prf_params; ++ params.len = sizeof(ike_prf_params); ++ prf_psk = PK11_Derive(pss_key, CKM_NSS_IKE_PRF_DERIVE, ¶ms, prf_mech, CKA_SIGN, 0); ++ release_symkey("psk pss_key", "pss_key", &pss_key); ++#else + struct crypt_prf *prf = + crypt_prf_init_chunk(" = prf(,\"Key Pad for IKEv2\")", + st->st_oakley.ta_prf, +@@ -196,12 +226,11 @@ + return FALSE; + } + +- static const char psk_key_pad_str[] = "Key Pad for IKEv2"; /* RFC 4306 2:15 */ +- + crypt_prf_update_bytes(prf, psk_key_pad_str, /* name */ + psk_key_pad_str, + sizeof(psk_key_pad_str) - 1); + prf_psk = crypt_prf_final_symkey(&prf); ++#endif + } + + /* calculate outer prf */ +diff -Naur libreswan-3.29-orig/programs/pluto/plutomain.c libreswan-3.29/programs/pluto/plutomain.c +--- libreswan-3.29-orig/programs/pluto/plutomain.c 2019-06-10 10:22:04.000000000 -0400 ++++ libreswan-3.29/programs/pluto/plutomain.c 2019-08-11 13:31:13.859294831 -0400 +@@ -189,6 +189,11 @@ + #ifdef NSS_IPSEC_PROFILE + " (IPsec profile)" + #endif ++#ifdef USE_NSS_PRF ++ " (NSS-PRF)" ++#else ++ " (native-PRF)" ++#endif + #ifdef USE_DNSSEC + " DNSSEC" + #endif +diff -Naur libreswan-3.29-orig/programs/pluto/prf_test_vectors.c libreswan-3.29/programs/pluto/prf_test_vectors.c +--- libreswan-3.29-orig/programs/pluto/prf_test_vectors.c 2019-06-10 10:22:04.000000000 -0400 ++++ libreswan-3.29/programs/pluto/prf_test_vectors.c 2019-08-11 13:31:13.860294845 -0400 +@@ -34,6 +34,7 @@ + * Ref: https://tools.ietf.org/html/rfc4435: Test Vectors + */ + ++#ifdef USE_PRF_AES_XCBC + const struct prf_test_vectors aes_xcbc_prf_tests = { + .prf = &ike_alg_prf_aes_xcbc, + .tests = { +@@ -105,6 +106,10 @@ + .message = "0x000102030405060708090a0b0c0d0e0f10111213", + .prf_output = "0x47f51b4564966215b8985c63055ed308", + }, ++ /* ++ * XXX: for some reason NSS explodes when trying to ++ * create a non-standard AES_XCBC_MAC key. ++ */ + { + .description = "Test Case AES-XCBC-PRF-128 with 20-byte input (key length 10)", + .key = "0x00010203040506070809", +@@ -124,7 +129,9 @@ + } + }, + }; ++#endif + ++/* So far we only have AES_XCBC PRF test vectors :/ */ + static bool test_prf_vector(const struct prf_desc *prf, + const struct prf_test_vector *test) + { +@@ -137,7 +144,6 @@ + : alloc_chunk(test->message_size, __func__); + chunk_t prf_output = decode_to_chunk(__func__, test->prf_output); + +- + /* chunk interface */ + struct crypt_prf *chunk_prf = crypt_prf_init_chunk("PRF chunk interface", prf, + "key", chunk_key); diff --git a/SOURCES/libreswan-3.29-1723957-audit.patch b/SOURCES/libreswan-3.29-1723957-audit.patch new file mode 100644 index 0000000..785630d --- /dev/null +++ b/SOURCES/libreswan-3.29-1723957-audit.patch @@ -0,0 +1,301 @@ +diff -Naur libreswan-3.29-orig/programs/pluto/ikev1.c libreswan-3.29/programs/pluto/ikev1.c +--- libreswan-3.29-orig/programs/pluto/ikev1.c 2019-06-26 22:03:27.801184503 -0400 ++++ libreswan-3.29/programs/pluto/ikev1.c 2019-06-27 13:26:11.443969779 -0400 +@@ -2675,6 +2675,12 @@ + passert(st != NULL); + pexpect(!state_is_busy(st)); + ++ if (result > STF_OK) { ++ if (st != NULL) { ++ linux_audit_conn(md->st, IS_IKE_SA_ESTABLISHED(md->st) ? LAK_CHILD_FAIL : LAK_PARENT_FAIL); ++ } ++ } ++ + switch (result) { + case STF_OK: + { +diff -Naur libreswan-3.29-orig/programs/pluto/ikev1_quick.c libreswan-3.29/programs/pluto/ikev1_quick.c +--- libreswan-3.29-orig/programs/pluto/ikev1_quick.c 2019-06-26 22:03:27.803184531 -0400 ++++ libreswan-3.29/programs/pluto/ikev1_quick.c 2019-06-27 13:23:53.787080070 -0400 +@@ -1663,6 +1663,9 @@ + if (!install_inbound_ipsec_sa(st)) + return STF_INTERNAL_ERROR; /* ??? we may be partly committed */ + ++ /* we only audit once for IPsec SA's, we picked the inbound SA */ ++ linux_audit_conn(st, LAK_CHILD_START); ++ + /* encrypt message, except for fixed part of header */ + + if (!ikev1_encrypt_message(&rbody, st)) { +diff -Naur libreswan-3.29-orig/programs/pluto/ikev2.c libreswan-3.29/programs/pluto/ikev2.c +--- libreswan-3.29-orig/programs/pluto/ikev2.c 2019-06-10 10:22:04.000000000 -0400 ++++ libreswan-3.29/programs/pluto/ikev2.c 2019-06-27 13:25:16.529215928 -0400 +@@ -3204,6 +3204,13 @@ + lswlog_v2_stf_status(buf, result); + } + ++ /* audit log failures - success is audit logged in ikev2_ike_sa_established() */ ++ if (result > STF_OK) { ++ if (st != NULL) { ++ linux_audit_conn(st, IS_IKE_SA_ESTABLISHED(st) ? LAK_CHILD_FAIL : LAK_PARENT_FAIL); ++ } ++ } ++ + switch (result) { + + case STF_SUSPEND: +diff -Naur libreswan-3.29-orig/programs/pluto/ikev2_child.c libreswan-3.29/programs/pluto/ikev2_child.c +--- libreswan-3.29-orig/programs/pluto/ikev2_child.c 2019-06-10 10:22:04.000000000 -0400 ++++ libreswan-3.29/programs/pluto/ikev2_child.c 2019-06-27 13:23:53.788080084 -0400 +@@ -102,6 +102,10 @@ + return STF_OK; + } + ++/* ++ * The caller could have done the linux_audit_conn() call, except one case ++ * here deletes the state before returning an STF error ++ */ + stf_status ikev2_child_sa_respond(struct msg_digest *md, + pb_stream *outpbs, + enum isakmp_xchg_types isa_xchg) +diff -Naur libreswan-3.29-orig/programs/pluto/ikev2_parent.c libreswan-3.29/programs/pluto/ikev2_parent.c +--- libreswan-3.29-orig/programs/pluto/ikev2_parent.c 2019-06-10 10:22:04.000000000 -0400 ++++ libreswan-3.29/programs/pluto/ikev2_parent.c 2019-06-27 13:23:53.789080097 -0400 +@@ -239,6 +239,7 @@ + c->newest_isakmp_sa = ike->sa.st_serialno; + v2_schedule_replace_event(&ike->sa); + ike->sa.st_viable_parent = TRUE; ++ linux_audit_conn(&ike->sa, LAK_PARENT_START); + pstat_sa_established(&ike->sa); + } + +@@ -1581,6 +1582,24 @@ + libreswan_log("IKE_AUTH response contained an unknown error notification (%d)", n); + } else { + libreswan_log("IKE_AUTH response contained the error notification %s", name); ++ /* ++ * There won't be a child state transition, so log if error is child related. ++ * see RFC 7296 Section 1.2 ++ */ ++ switch(n) { ++ case v2N_NO_PROPOSAL_CHOSEN: ++ case v2N_SINGLE_PAIR_REQUIRED: ++ case v2N_NO_ADDITIONAL_SAS: ++ case v2N_INTERNAL_ADDRESS_FAILURE: ++ case v2N_FAILED_CP_REQUIRED: ++ case v2N_TS_UNACCEPTABLE: ++ case v2N_INVALID_SELECTORS: ++ /* fallthrough */ ++ linux_audit_conn(st, LAK_CHILD_FAIL); ++ break; ++ default: ++ break; ++ } + } + } + } +@@ -3063,10 +3082,6 @@ + ikev2_ike_sa_established(pexpect_ike_sa(st), md->svm, + STATE_PARENT_R2); + +-#ifdef USE_LINUX_AUDIT +- linux_audit_conn(st, LAK_PARENT_START); +-#endif +- + if (LHAS(st->hidden_variables.st_nat_traversal, NATED_HOST)) { + /* ensure we run keepalives if needed */ + if (c->nat_keepalive) +@@ -3801,10 +3816,6 @@ + ikev2_ike_sa_established(pexpect_ike_sa(pst), md->svm, + STATE_PARENT_I3); + +-#ifdef USE_LINUX_AUDIT +- linux_audit_conn(st, LAK_PARENT_START); +-#endif +- + if (LHAS(st->hidden_variables.st_nat_traversal, NATED_HOST)) { + /* ensure we run keepalives if needed */ + if (c->nat_keepalive) +diff -Naur libreswan-3.29-orig/programs/pluto/kernel.c libreswan-3.29/programs/pluto/kernel.c +--- libreswan-3.29-orig/programs/pluto/kernel.c 2019-06-10 10:22:04.000000000 -0400 ++++ libreswan-3.29/programs/pluto/kernel.c 2019-06-27 13:23:53.790080111 -0400 +@@ -3334,7 +3334,8 @@ + } + + #ifdef USE_LINUX_AUDIT +- linux_audit_conn(st, LAK_CHILD_START); ++ if (inbound_also) ++ linux_audit_conn(st, LAK_CHILD_START); + #endif + statetime_stop(&start, "%s()", __func__); + +@@ -3378,8 +3379,13 @@ + { + #ifdef USE_LINUX_AUDIT + /* XXX in IKEv2 we get a spurious call with a parent st :( */ +- if (IS_CHILD_SA(st)) +- linux_audit_conn(st, LAK_CHILD_DESTROY); ++ if (IS_CHILD_SA(st)) { ++ /* child destruction already logged for STATE_CHILDSA_DEL state */ ++ if (st->st_esp.present || st->st_ah.present) { ++ /* ESP or AH means this was an established IPsec SA */ ++ linux_audit_conn(st, LAK_CHILD_DESTROY); ++ } ++ } + #endif + switch (kern_interface) { + case USE_KLIPS: +diff -Naur libreswan-3.29-orig/programs/pluto/linux_audit.c libreswan-3.29/programs/pluto/linux_audit.c +--- libreswan-3.29-orig/programs/pluto/linux_audit.c 2019-06-10 10:22:04.000000000 -0400 ++++ libreswan-3.29/programs/pluto/linux_audit.c 2019-06-27 13:24:21.474460154 -0400 +@@ -176,12 +176,16 @@ + zero(&cipher_str); /* OK: no pointer fields */ + zero(&spi_str); /* OK: no pointer fields */ + ++ ip_address_buf raddr_buf; ++ const char *raddr = ipstr(&c->spd.that.host_addr, &raddr_buf); ++ + switch (op) { + case LAK_PARENT_START: + case LAK_PARENT_DESTROY: ++ case LAK_PARENT_FAIL: + initiator = (st->st_original_role == ORIGINAL_INITIATOR) || IS_PHASE1_INIT(st->st_state); + snprintf(head, sizeof(head), "op=%s direction=%s %s connstate=%lu ike-version=%s auth=%s", +- op == LAK_PARENT_START ? "start" : "destroy", ++ op == LAK_PARENT_DESTROY ? "destroy" : "start", /* fail to start logged under op=start */ + initiator ? "initiator" : "responder", + conn_encode, + st->st_serialno, +@@ -191,7 +195,8 @@ + st->st_oakley.auth, &esb)); + + snprintf(prfname, sizeof(prfname), "%s", +- st->st_oakley.ta_prf->prf_ike_audit_name); ++ st->st_oakley.ta_prf == NULL ? "none" : ++ st->st_oakley.ta_prf->prf_ike_audit_name); + + if (st->st_oakley.ta_integ == &ike_alg_integ_none) { + if (st->st_ike_version == IKEv1) { +@@ -220,18 +225,21 @@ + } + + snprintf(cipher_str, sizeof(cipher_str), +- "cipher=%s ksize=%d integ=%s prf=%s pfs=%s", +- st->st_oakley.ta_encrypt->encrypt_ike_audit_name, ++ "cipher=%s ksize=%d integ=%s prf=%s pfs=%s raddr=%s", ++ st->st_oakley.ta_encrypt == NULL ? "none" : ++ st->st_oakley.ta_encrypt->encrypt_ike_audit_name, + st->st_oakley.enckeylen, + integname, prfname, +- st->st_oakley.ta_dh->common.name); ++ st->st_oakley.ta_dh == NULL ? "none" : ++ st->st_oakley.ta_dh->common.name, raddr); + break; + + case LAK_CHILD_START: + case LAK_CHILD_DESTROY: ++ case LAK_CHILD_FAIL: + { + snprintf(head, sizeof(head), "op=%s %s connstate=%lu, satype=%s samode=%s", +- op == LAK_CHILD_START ? "start" : "destroy", ++ op == LAK_CHILD_DESTROY ? "destroy" : "start", /* fail to start logged under op=start */ + conn_encode, + st->st_serialno, + st->st_esp.present ? "ipsec-esp" : (st->st_ah.present ? "ipsec-ah" : "ipsec-policy"), +@@ -274,7 +282,7 @@ + + /* note: each arg appears twice because it is printed two ways */ + snprintf(spi_str, sizeof(spi_str), +- "in-spi=%" PRIu32 "(0x%08" PRIu32 ") out-spi=%" PRIu32 "(0x%08" PRIu32 ") in-ipcomp=%" PRIu32 "(0x%08" PRIu32 ") out-ipcomp=%" PRIu32 "(0x%08" PRIu32 ")", ++ "in-spi=%" PRIu32 "(0x%08" PRIu32 ") out-spi=%" PRIu32 "(0x%08" PRIu32 ") in-ipcomp=%" PRIu32 "(0x%08" PRIu32 ") out-ipcomp=%" PRIu32 "(0x%08" PRIu32 ") raddr=%s", + ntohl(pi->attrs.spi), + ntohl(pi->attrs.spi), + ntohl(pi->our_spi), +@@ -282,7 +290,8 @@ + ntohl(st->st_ipcomp.attrs.spi), /* zero if missing */ + ntohl(st->st_ipcomp.attrs.spi), /* zero if missing */ + ntohl(st->st_ipcomp.our_spi), /* zero if missing */ +- ntohl(st->st_ipcomp.our_spi)); /* zero if missing */ ++ ntohl(st->st_ipcomp.our_spi), /* zero if missing */ ++ raddr); + break; + } + default: +@@ -290,21 +299,18 @@ + } + free(conn_encode); /* allocated by audit_encode_nv_string() */ + +- ip_address_buf laddr_buf; +- const char *laddr = ipstr(&c->spd.this.host_addr, &laddr_buf); +- +- ip_address_buf raddr_buf; +- const char *raddr = ipstr(&c->spd.that.host_addr, &raddr_buf); +- +- snprintf(audit_str, sizeof(audit_str), "%s %s %s laddr=%s", ++ snprintf(audit_str, sizeof(audit_str), "%s %s %s", + head, + cipher_str, +- spi_str, +- laddr); ++ spi_str); ++ ++ ip_address_buf laddr_buf; ++ const char *laddr = ipstr(&c->spd.this.host_addr, &laddr_buf); + +- linux_audit((op == LAK_CHILD_START || op == LAK_CHILD_DESTROY) ? ++ linux_audit((op == LAK_CHILD_START || op == LAK_CHILD_DESTROY || op == LAK_CHILD_FAIL) ? + AUDIT_CRYPTO_IPSEC_SA : AUDIT_CRYPTO_IKE_SA, +- audit_str, raddr, AUDIT_RESULT_OK); ++ audit_str, laddr, ++ (op == LAK_PARENT_FAIL || op == LAK_CHILD_FAIL) ? AUDIT_RESULT_FAIL : AUDIT_RESULT_OK); + } + #if __GNUC__ >= 7 + #pragma GCC diagnostic pop +diff -Naur libreswan-3.29-orig/programs/pluto/log.h libreswan-3.29/programs/pluto/log.h +--- libreswan-3.29-orig/programs/pluto/log.h 2019-06-10 10:22:04.000000000 -0400 ++++ libreswan-3.29/programs/pluto/log.h 2019-06-27 13:23:53.791080125 -0400 +@@ -174,7 +174,9 @@ + LAK_PARENT_START, + LAK_CHILD_START, + LAK_PARENT_DESTROY, +- LAK_CHILD_DESTROY ++ LAK_CHILD_DESTROY, ++ LAK_PARENT_FAIL, ++ LAK_CHILD_FAIL + }; + extern void linux_audit_init(void); + extern void linux_audit(const int type, const char *message, +diff -Naur libreswan-3.29-orig/programs/pluto/retry.c libreswan-3.29/programs/pluto/retry.c +--- libreswan-3.29-orig/programs/pluto/retry.c 2019-06-10 10:22:04.000000000 -0400 ++++ libreswan-3.29/programs/pluto/retry.c 2019-06-27 13:25:27.536367032 -0400 +@@ -123,6 +123,10 @@ + + set_cur_state(st); /* ipsecdoi_replace would reset cur_state, set it again */ + pstat_sa_failed(st, REASON_TOO_MANY_RETRANSMITS); ++ ++ /* placed here because IKEv1 doesn't do a proper state change to STF_FAIL/STF_FATAL */ ++ linux_audit_conn(st, IS_IKE_SA(st) ? LAK_PARENT_FAIL : LAK_CHILD_FAIL); ++ + delete_state(st); + /* note: no md->st to clear */ + } +diff -Naur libreswan-3.29-orig/programs/pluto/state.c libreswan-3.29/programs/pluto/state.c +--- libreswan-3.29-orig/programs/pluto/state.c 2019-06-10 10:22:04.000000000 -0400 ++++ libreswan-3.29/programs/pluto/state.c 2019-06-27 13:23:53.792080138 -0400 +@@ -875,6 +875,16 @@ + + #ifdef USE_LINUX_AUDIT + /* ++ * IKEv2 IKE failures are logged in the state transition conpletion. ++ * IKEv1 IKE failures do not go through a transition, so we catch ++ * these in delete_state() ++ */ ++ if (IS_IKE_SA(st) && st->st_ike_version == IKEv1 && ++ !IS_IKE_SA_ESTABLISHED(st)) { ++ linux_audit_conn(st, LAK_PARENT_FAIL); ++ } ++ ++ /* + * only log parent state deletes, we log children in + * ipsec_delete_sa() + */ diff --git a/SOURCES/libreswan-3.29-CVE-2019-10155-testing.patch b/SOURCES/libreswan-3.29-CVE-2019-10155-testing.patch new file mode 100644 index 0000000..0384489 --- /dev/null +++ b/SOURCES/libreswan-3.29-CVE-2019-10155-testing.patch @@ -0,0 +1,1830 @@ +diff -Naur libreswan-3.29-orig/include/impair.h libreswan-3.29/include/impair.h +--- libreswan-3.29-orig/include/impair.h 2019-06-10 10:22:04.000000000 -0400 ++++ libreswan-3.29/include/impair.h 2019-06-11 19:22:39.786283961 -0400 +@@ -1,6 +1,6 @@ +-/* impair operation ++/* impair operation, for libreswan + * +- * Copyright (C) 2019 Andrew Cagney ++ * Copyright (C) 2018-2019 Andrew Cagney + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the +@@ -22,9 +22,7 @@ + #include "lswcdefs.h" + + /* +- * How to impair something. This is just the start ... +- * +- * Extra enums go here. ++ * Meddle with the contents of a payload. + */ + + enum send_impairment { +@@ -35,6 +33,21 @@ + SEND_ROOF, /* >= ROOF -> */ + }; + ++/* ++ * Meddle with a specific exchange. ++ */ ++ ++enum exchange_impairment { ++ NO_EXCHANGE = 0, ++ NOTIFICATION_EXCHANGE, ++ QUICK_EXCHANGE, ++ XAUTH_EXCHANGE, ++ DELETE_EXCHANGE, ++}; ++ ++/* ++ * add more here ++ */ + #if 0 + enum xxx_impair ...; + #endif +@@ -53,6 +66,10 @@ + extern enum send_impairment impair_ike_key_length_attribute; + extern enum send_impairment impair_child_key_length_attribute; + ++extern enum send_impairment impair_v1_hash_payload; ++extern enum exchange_impairment impair_v1_hash_exchange; ++extern bool impair_v1_hash_check; ++ + /* + * What whack sends across the wire for a impair. + */ +diff -Naur libreswan-3.29-orig/lib/libswan/impair.c libreswan-3.29/lib/libswan/impair.c +--- libreswan-3.29-orig/lib/libswan/impair.c 2019-06-10 10:22:04.000000000 -0400 ++++ libreswan-3.29/lib/libswan/impair.c 2019-06-11 19:22:54.290445191 -0400 +@@ -1,5 +1,4 @@ +-/* +- * impair constants, for libreswan ++/* impair constants, for libreswan + * + * Copyright (C) 2017-2019 Andrew Cagney + * Copyright (C) 2019-2019 Paul Wouters +@@ -125,6 +124,19 @@ + static const struct keywords send_impairment_keywords = + DIRECT_KEYWORDS("send impaired content", send_impairment_value); + ++static const struct keyword exchange_impairment_value[] = { ++#define S(E, H) [E##_EXCHANGE] = { .name = "SEND_" #E, .sname = #E, .value = E##_EXCHANGE, .details = H, } ++ S(NO, "do not modify exchanges"), ++ S(QUICK, "modify IKEv1 QUICK exchanges"), ++ S(XAUTH, "modify IKEv1 XAUTH exchanges"), ++ S(NOTIFICATION, "modify notification (informational) exchanges"), ++ S(DELETE, "modify delete exchanges"), ++#undef S ++}; ++ ++static const struct keywords exchange_impairment_keywords = ++ DIRECT_KEYWORDS("impaire exchange content", exchange_impairment_value); ++ + struct impairment { + const char *what; + const char *help; +@@ -182,6 +194,27 @@ + .how_keynum = &send_impairment_keywords, + V(impair_child_key_length_attribute), + }, ++ ++ /* ++ * IKEv1: hash payloads ++ */ ++ { ++ .what = "v1-hash-check", ++ .help = "disable check of incoming IKEv1 hash payload", ++ V(impair_emitting), ++ }, ++ { ++ .what = "v1-hash-payload", ++ .help = "corrupt the outgoing HASH payload", ++ .how_keynum = &send_impairment_keywords, ++ V(impair_v1_hash_payload), ++ }, ++ { ++ .what = "v1-hash-exchange", ++ .help = "the outgoing exchange that should contain the corrupted HASH payload", ++ .how_keynum = &exchange_impairment_keywords, ++ V(impair_v1_hash_exchange), ++ }, + }; + + static void help(const char *prefix, const struct impairment *cr) +@@ -522,8 +555,9 @@ + } + + /* +- * declare these last so that all references are forced to use the +- * declaration in the header. ++ * XXX: define these at the end of the file so that all references are ++ * forced to use the declaration in the header (help stop code ++ * refering to the wrong variable?). + */ + + bool impair_revival; +@@ -531,3 +565,6 @@ + enum send_impairment impair_ke_payload; + enum send_impairment impair_ike_key_length_attribute; + enum send_impairment impair_child_key_length_attribute; ++bool impair_v1_hash_check; ++enum send_impairment impair_v1_hash_payload; ++enum exchange_impairment impair_v1_hash_exchange; +diff -Naur libreswan-3.29-orig/programs/pluto/ikev1.c libreswan-3.29/programs/pluto/ikev1.c +--- libreswan-3.29-orig/programs/pluto/ikev1.c 2019-06-10 10:22:04.000000000 -0400 ++++ libreswan-3.29/programs/pluto/ikev1.c 2019-06-11 19:27:44.516665524 -0400 +@@ -157,6 +157,7 @@ + #include "ikev1_dpd.h" + #include "hostpair.h" + #include "ip_address.h" ++#include "ikev1_hash.h" + + #ifdef HAVE_NM + #include "kernel.h" +@@ -181,6 +182,8 @@ + lset_t opt_payloads; /* optional payloads (any mumber) */ + enum event_type timeout_event; + ikev1_state_transition_fn *processor; ++ const char *message; ++ enum v1_hash_type hash_type; + }; + + /* State Microcode Flags, in several groups */ +@@ -255,6 +258,7 @@ + static const struct state_v1_microcode v1_state_microcode_table[] = { + + #define P(n) LELEM(ISAKMP_NEXT_ ##n) ++#define FM(F) .processor = F, .message = #F + + /***** Phase 1 Main Mode *****/ + +@@ -266,7 +270,9 @@ + { STATE_MAIN_R0, STATE_MAIN_R1, + SMF_ALL_AUTH | SMF_REPLY, + P(SA), P(VID) | P(CR), +- EVENT_SO_DISCARD, main_inI1_outR1 }, ++ EVENT_SO_DISCARD, ++ FM(main_inI1_outR1), ++ .hash_type = V1_HASH_NONE, }, + + /* STATE_MAIN_I1: R1 --> I2 + * HDR, SA --> auth dependent +@@ -281,7 +287,9 @@ + { STATE_MAIN_I1, STATE_MAIN_I2, + SMF_ALL_AUTH | SMF_INITIATOR | SMF_REPLY, + P(SA), P(VID) | P(CR), +- EVENT_RETRANSMIT, main_inR1_outI2 }, ++ EVENT_RETRANSMIT, ++ FM(main_inR1_outI2), ++ .hash_type = V1_HASH_NONE, }, + + /* STATE_MAIN_R1: I2 --> R2 + * SMF_PSK_AUTH, SMF_DS_AUTH: HDR, KE, Ni --> HDR, KE, Nr +@@ -294,17 +302,23 @@ + { STATE_MAIN_R1, STATE_MAIN_R2, + SMF_PSK_AUTH | SMF_DS_AUTH | SMF_REPLY | SMF_RETRANSMIT_ON_DUPLICATE, + P(KE) | P(NONCE), P(VID) | P(CR) | P(NATD_RFC), +- EVENT_RETRANSMIT, main_inI2_outR2 }, ++ EVENT_RETRANSMIT, ++ FM(main_inI2_outR2), ++ .hash_type = V1_HASH_NONE, }, + + { STATE_MAIN_R1, STATE_UNDEFINED, + SMF_PKE_AUTH | SMF_REPLY | SMF_RETRANSMIT_ON_DUPLICATE, + P(KE) | P(ID) | P(NONCE), P(VID) | P(CR) | P(HASH), +- EVENT_RETRANSMIT, unexpected /* ??? not yet implemented */ }, ++ EVENT_RETRANSMIT, ++ FM(unexpected) /* ??? not yet implemented */, ++ .hash_type = V1_HASH_NONE, }, + + { STATE_MAIN_R1, STATE_UNDEFINED, + SMF_RPKE_AUTH | SMF_REPLY | SMF_RETRANSMIT_ON_DUPLICATE, + P(NONCE) | P(KE) | P(ID), P(VID) | P(CR) | P(HASH) | P(CERT), +- EVENT_RETRANSMIT, unexpected /* ??? not yet implemented */ }, ++ EVENT_RETRANSMIT, ++ FM(unexpected) /* ??? not yet implemented */, ++ .hash_type = V1_HASH_NONE, }, + + /* for states from here on, output message must be encrypted */ + +@@ -319,17 +333,24 @@ + { STATE_MAIN_I2, STATE_MAIN_I3, + SMF_PSK_AUTH | SMF_DS_AUTH | SMF_INITIATOR | SMF_OUTPUT_ENCRYPTED | SMF_REPLY, + P(KE) | P(NONCE), P(VID) | P(CR) | P(NATD_RFC), +- EVENT_RETRANSMIT, main_inR2_outI3 }, ++ EVENT_RETRANSMIT, ++ FM(main_inR2_outI3), ++ /* calls main_mode_hash() after DH */ ++ .hash_type = V1_HASH_NONE, }, + + { STATE_MAIN_I2, STATE_UNDEFINED, + SMF_PKE_AUTH | SMF_INITIATOR | SMF_OUTPUT_ENCRYPTED | SMF_REPLY, + P(KE) | P(ID) | P(NONCE), P(VID) | P(CR), +- EVENT_RETRANSMIT, unexpected /* ??? not yet implemented */ }, ++ EVENT_RETRANSMIT, ++ FM(unexpected) /* ??? not yet implemented */, ++ .hash_type = V1_HASH_NONE, }, + + { STATE_MAIN_I2, STATE_UNDEFINED, + SMF_ALL_AUTH | SMF_INITIATOR | SMF_OUTPUT_ENCRYPTED | SMF_REPLY, + P(NONCE) | P(KE) | P(ID), P(VID) | P(CR), +- EVENT_RETRANSMIT, unexpected /* ??? not yet implemented */ }, ++ EVENT_RETRANSMIT, ++ FM(unexpected) /* ??? not yet implemented */, ++ .hash_type = V1_HASH_NONE, }, + + /* for states from here on, input message must be encrypted */ + +@@ -342,20 +363,34 @@ + SMF_PSK_AUTH | SMF_FIRST_ENCRYPTED_INPUT | SMF_ENCRYPTED | + SMF_REPLY | SMF_RELEASE_PENDING_P2, + P(ID) | P(HASH), P(VID) | P(CR), +- EVENT_SA_REPLACE, main_inI3_outR3 }, ++ EVENT_SA_REPLACE, ++ FM(main_inI3_outR3), ++ /* calls oakley_id_and_auth() which calls main_mode_hash() */ ++ /* RFC 2409: 5. Exchanges & 5.2 Phase 1 Authenticated With Public Key Encryption ++ HASH_I = prf(SKEYID, g^xi | g^xr | CKY-I | CKY-R | SAi_b | IDii_b ) */ ++ .hash_type = V1_HASH_NONE, }, + + { STATE_MAIN_R2, STATE_MAIN_R3, + SMF_DS_AUTH | SMF_FIRST_ENCRYPTED_INPUT | SMF_ENCRYPTED | + SMF_REPLY | SMF_RELEASE_PENDING_P2, + P(ID) | P(SIG), P(VID) | P(CR) | P(CERT), +- EVENT_SA_REPLACE, main_inI3_outR3 }, ++ EVENT_SA_REPLACE, ++ FM(main_inI3_outR3), ++ /* calls oakley_id_and_auth() which calls main_mode_hash() */ ++ /* RFC 2409: 5. Exchanges & 5.1 IKE Phase 1 Authenticated With Signatures ++ HASH_I = prf(SKEYID, g^xi | g^xr | CKY-I | CKY-R | SAi_b | IDii_b ) ++ SIG_I = SIGN(HASH_I) *", ++ SIG_I = SIGN(HASH_I) */ ++ .hash_type = V1_HASH_NONE, }, + + { STATE_MAIN_R2, STATE_UNDEFINED, + SMF_PKE_AUTH | SMF_RPKE_AUTH | SMF_FIRST_ENCRYPTED_INPUT | + SMF_ENCRYPTED | + SMF_REPLY | SMF_RELEASE_PENDING_P2, + P(HASH), P(VID) | P(CR), +- EVENT_SA_REPLACE, unexpected /* ??? not yet implemented */ }, ++ EVENT_SA_REPLACE, ++ FM(unexpected) /* ??? not yet implemented */, ++ .hash_type = V1_HASH_NONE, }, + + /* STATE_MAIN_I3: R3 --> done + * SMF_PSK_AUTH: HDR*, IDr1, HASH_R --> done +@@ -367,31 +402,48 @@ + SMF_PSK_AUTH | SMF_INITIATOR | + SMF_FIRST_ENCRYPTED_INPUT | SMF_ENCRYPTED | SMF_RELEASE_PENDING_P2, + P(ID) | P(HASH), P(VID) | P(CR), +- EVENT_SA_REPLACE, main_inR3 }, ++ EVENT_SA_REPLACE, ++ FM(main_inR3), ++ /* calls oakley_id_and_auth() which calls main_mode_hash() */ ++ /* RFC 2409: 5. Exchanges & 5.2 Phase 1 Authenticated With Public Key Encryption ++ HASH_R = prf(SKEYID, g^xr | g^xi | CKY-R | CKY-I | SAi_b | IDir_b ) */ ++ .hash_type = V1_HASH_NONE, }, + + { STATE_MAIN_I3, STATE_MAIN_I4, + SMF_DS_AUTH | SMF_INITIATOR | + SMF_FIRST_ENCRYPTED_INPUT | SMF_ENCRYPTED | SMF_RELEASE_PENDING_P2, + P(ID) | P(SIG), P(VID) | P(CR) | P(CERT), +- EVENT_SA_REPLACE, main_inR3 }, ++ EVENT_SA_REPLACE, ++ FM(main_inR3), ++ /* calls oakley_id_and_auth() which calls main_mode_hash() */ ++ /* RFC 2409: 5. Exchanges & 5.1 IKE Phase 1 Authenticated With Signatures ++ HASH_R = prf(SKEYID, g^xr | g^xi | CKY-R | CKY-I | SAi_b | IDir_b ) ++ SIG_R = SIGN(HASH_R) */ ++ .hash_type = V1_HASH_NONE, }, + + { STATE_MAIN_I3, STATE_UNDEFINED, + SMF_PKE_AUTH | SMF_RPKE_AUTH | SMF_INITIATOR | + SMF_FIRST_ENCRYPTED_INPUT | SMF_ENCRYPTED | SMF_RELEASE_PENDING_P2, + P(HASH), P(VID) | P(CR), +- EVENT_SA_REPLACE, unexpected /* ??? not yet implemented */ }, ++ EVENT_SA_REPLACE, ++ FM(unexpected) /* ??? not yet implemented */, ++ .hash_type = V1_HASH_NONE, }, + + /* STATE_MAIN_R3: can only get here due to packet loss */ + { STATE_MAIN_R3, STATE_UNDEFINED, + SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_RETRANSMIT_ON_DUPLICATE, + LEMPTY, LEMPTY, +- EVENT_NULL, unexpected }, ++ EVENT_NULL, ++ FM(unexpected), ++ .hash_type = V1_HASH_NONE, }, + + /* STATE_MAIN_I4: can only get here due to packet loss */ + { STATE_MAIN_I4, STATE_UNDEFINED, + SMF_ALL_AUTH | SMF_INITIATOR | SMF_ENCRYPTED, + LEMPTY, LEMPTY, +- EVENT_NULL, unexpected }, ++ EVENT_NULL, ++ FM(unexpected), ++ .hash_type = V1_HASH_NONE, }, + + /***** Phase 1 Aggressive Mode *****/ + +@@ -413,7 +465,10 @@ + { STATE_AGGR_R0, STATE_AGGR_R1, + SMF_PSK_AUTH | SMF_DS_AUTH | SMF_REPLY, + P(SA) | P(KE) | P(NONCE) | P(ID), P(VID) | P(NATD_RFC), +- EVENT_SO_DISCARD, aggr_inI1_outR1 }, ++ EVENT_SO_DISCARD, ++ FM(aggr_inI1_outR1), ++ /* N/A */ ++ .hash_type = V1_HASH_NONE, }, + + /* STATE_AGGR_I1: + * SMF_PSK_AUTH: HDR, SA, KE, Nr, IDir, HASH_R +@@ -425,13 +480,24 @@ + SMF_PSK_AUTH | SMF_INITIATOR | SMF_OUTPUT_ENCRYPTED | SMF_REPLY | + SMF_RELEASE_PENDING_P2, + P(SA) | P(KE) | P(NONCE) | P(ID) | P(HASH), P(VID) | P(NATD_RFC), +- EVENT_SA_REPLACE, aggr_inR1_outI2 }, ++ EVENT_SA_REPLACE, ++ FM(aggr_inR1_outI2), ++ /* after DH calls oakley_id_and_auth() which calls main_mode_hash() */ ++ /* RFC 2409: 5. Exchanges & 5.2 Phase 1 Authenticated With Public Key Encryption ++ HASH_R = prf(SKEYID, g^xr | g^xi | CKY-R | CKY-I | SAi_b | IDir_b ) */ ++ .hash_type = V1_HASH_NONE, }, + + { STATE_AGGR_I1, STATE_AGGR_I2, + SMF_DS_AUTH | SMF_INITIATOR | SMF_OUTPUT_ENCRYPTED | SMF_REPLY | + SMF_RELEASE_PENDING_P2, + P(SA) | P(KE) | P(NONCE) | P(ID) | P(SIG), P(VID) | P(NATD_RFC), +- EVENT_SA_REPLACE, aggr_inR1_outI2 }, ++ EVENT_SA_REPLACE, ++ FM(aggr_inR1_outI2), ++ /* after DH calls oakley_id_and_auth() which calls main_mode_hash() */ ++ /* RFC 2409: 5. Exchanges & 5.1 IKE Phase 1 Authenticated With Signatures ++ HASH_R = prf(SKEYID, g^xr | g^xi | CKY-R | CKY-I | SAi_b | IDir_b ) ++ SIG_R = SIGN(HASH_R) */ ++ .hash_type = V1_HASH_NONE, }, + + /* STATE_AGGR_R1: + * SMF_PSK_AUTH: HDR*, HASH_I --> done +@@ -442,24 +508,39 @@ + SMF_OUTPUT_ENCRYPTED | SMF_RELEASE_PENDING_P2 | + SMF_RETRANSMIT_ON_DUPLICATE, + P(HASH), P(VID) | P(NATD_RFC), +- EVENT_SA_REPLACE, aggr_inI2 }, ++ EVENT_SA_REPLACE, ++ FM(aggr_inI2), ++ /* calls oakley_id_and_auth() which calls main_mode_hash() */ ++ /* RFC 2409: 5. Exchanges & 5.2 Phase 1 Authenticated With Public Key Encryption ++ HASH_I = prf(SKEYID, g^xi | g^xr | CKY-I | CKY-R | SAi_b | IDii_b ) */ ++ .hash_type = V1_HASH_NONE, }, + + { STATE_AGGR_R1, STATE_AGGR_R2, + SMF_DS_AUTH | SMF_FIRST_ENCRYPTED_INPUT | + SMF_OUTPUT_ENCRYPTED | SMF_RELEASE_PENDING_P2 | + SMF_RETRANSMIT_ON_DUPLICATE, + P(SIG), P(VID) | P(NATD_RFC), +- EVENT_SA_REPLACE, aggr_inI2 }, ++ EVENT_SA_REPLACE, ++ FM(aggr_inI2), ++ /* calls oakley_id_and_auth() which calls main_mode_hash() */ ++ /* RFC 2409: 5. Exchanges & 5.1 IKE Phase 1 Authenticated With Signatures ++ HASH_I = prf(SKEYID, g^xi | g^xr | CKY-I | CKY-R | SAi_b | IDii_b ) ++ SIG_I = SIGN(HASH_I) */ ++ .hash_type = V1_HASH_NONE, }, + + /* STATE_AGGR_I2: can only get here due to packet loss */ + { STATE_AGGR_I2, STATE_UNDEFINED, + SMF_ALL_AUTH | SMF_INITIATOR | SMF_RETRANSMIT_ON_DUPLICATE, +- LEMPTY, LEMPTY, EVENT_NULL, unexpected }, ++ LEMPTY, LEMPTY, EVENT_NULL, ++ FM(unexpected), ++ .hash_type = V1_HASH_NONE, }, + + /* STATE_AGGR_R2: can only get here due to packet loss */ + { STATE_AGGR_R2, STATE_UNDEFINED, + SMF_ALL_AUTH, +- LEMPTY, LEMPTY, EVENT_NULL, unexpected }, ++ LEMPTY, LEMPTY, EVENT_NULL, ++ FM(unexpected), ++ .hash_type = V1_HASH_NONE, }, + + /***** Phase 2 Quick Mode *****/ + +@@ -478,7 +559,11 @@ + { STATE_QUICK_R0, STATE_QUICK_R1, + SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_REPLY, + P(HASH) | P(SA) | P(NONCE), /* P(SA) | */ P(KE) | P(ID) | P(NATOA_RFC), +- EVENT_RETRANSMIT, quick_inI1_outR1 }, ++ EVENT_RETRANSMIT, ++ FM(quick_inI1_outR1), ++ /* RFC 2409: 5.5 Phase 2 - Quick Mode: ++ HASH(1) = prf(SKEYID_a, M-ID | ) */ ++ .hash_type = V1_HASH_1, }, + + /* STATE_QUICK_I1: + * HDR*, HASH(2), SA, Nr [, KE ] [, IDci, IDcr ] --> +@@ -489,7 +574,11 @@ + { STATE_QUICK_I1, STATE_QUICK_I2, + SMF_ALL_AUTH | SMF_INITIATOR | SMF_ENCRYPTED | SMF_REPLY, + P(HASH) | P(SA) | P(NONCE), /* P(SA) | */ P(KE) | P(ID) | P(NATOA_RFC), +- EVENT_SA_REPLACE, quick_inR1_outI2 }, ++ EVENT_SA_REPLACE, ++ FM(quick_inR1_outI2), ++ /* RFC 2409: 5.5 Phase 2 - Quick Mode: ++ HASH(2) = prf(SKEYID_a, M-ID | Ni_b | ) */ ++ .hash_type = V1_HASH_2, }, + + /* STATE_QUICK_R1: HDR*, HASH(3) --> done + * Installs outbound IPsec SAs, routing, etc. +@@ -497,20 +586,28 @@ + { STATE_QUICK_R1, STATE_QUICK_R2, + SMF_ALL_AUTH | SMF_ENCRYPTED, + P(HASH), LEMPTY, +- EVENT_SA_REPLACE, quick_inI2 }, ++ EVENT_SA_REPLACE, ++ FM(quick_inI2), ++ /* RFC 2409: 5.5 Phase 2 - Quick Mode: ++ HASH(3) = prf(SKEYID_a, 0 | M-ID | Ni_b | Nr_b) */ ++ .hash_type = V1_HASH_3, }, + + /* STATE_QUICK_I2: can only happen due to lost packet */ + { STATE_QUICK_I2, STATE_UNDEFINED, + SMF_ALL_AUTH | SMF_INITIATOR | SMF_ENCRYPTED | + SMF_RETRANSMIT_ON_DUPLICATE, + LEMPTY, LEMPTY, +- EVENT_NULL, unexpected }, ++ EVENT_NULL, ++ FM(unexpected), ++ .hash_type = V1_HASH_NONE, }, + + /* STATE_QUICK_R2: can only happen due to lost packet */ + { STATE_QUICK_R2, STATE_UNDEFINED, + SMF_ALL_AUTH | SMF_ENCRYPTED, + LEMPTY, LEMPTY, +- EVENT_NULL, unexpected }, ++ EVENT_NULL, ++ FM(unexpected), ++ .hash_type = V1_HASH_NONE, }, + + /***** informational messages *****/ + +@@ -522,7 +619,9 @@ + { STATE_INFO, STATE_UNDEFINED, + SMF_ALL_AUTH, + LEMPTY, LEMPTY, +- EVENT_NULL, informational }, ++ EVENT_NULL, ++ FM(informational), ++ .hash_type = V1_HASH_NONE, }, + + /* Informational Exchange (RFC 2408 4.8): + * HDR* N/D +@@ -531,29 +630,41 @@ + { STATE_INFO_PROTECTED, STATE_UNDEFINED, + SMF_ALL_AUTH | SMF_ENCRYPTED, + P(HASH), LEMPTY, +- EVENT_NULL, informational }, ++ EVENT_NULL, ++ FM(informational), ++ /* RFC 2409: 5.7 ISAKMP Informational Exchanges: ++ HASH(1) = prf(SKEYID_a, M-ID | N/D) */ ++ .hash_type = V1_HASH_1, }, + + { STATE_XAUTH_R0, STATE_XAUTH_R1, + SMF_ALL_AUTH | SMF_ENCRYPTED, + P(MCFG_ATTR) | P(HASH), P(VID), +- EVENT_NULL, xauth_inR0 }, /* Re-transmit may be done by previous state */ ++ EVENT_NULL, ++ FM(xauth_inR0), ++ /* RFC ????: */ ++ .hash_type = V1_HASH_1, }, /* Re-transmit may be done by previous state */ + + { STATE_XAUTH_R1, STATE_MAIN_R3, + SMF_ALL_AUTH | SMF_ENCRYPTED, + P(MCFG_ATTR) | P(HASH), P(VID), +- EVENT_SA_REPLACE, xauth_inR1 }, ++ EVENT_SA_REPLACE, ++ FM(xauth_inR1), ++ /* RFC ????: */ ++ .hash_type = V1_HASH_1, }, + + #if 0 + /* for situation where there is XAUTH + ModeCFG */ + { STATE_XAUTH_R2, STATE_XAUTH_R3, + SMF_ALL_AUTH | SMF_ENCRYPTED, + P(MCFG_ATTR) | P(HASH), P(VID), +- EVENT_SA_REPLACE, xauth_inR2 }, ++ EVENT_SA_REPLACE, ++ FM(xauth_inR2), }, + + { STATE_XAUTH_R3, STATE_MAIN_R3, + SMF_ALL_AUTH | SMF_ENCRYPTED, + P(MCFG_ATTR) | P(HASH), P(VID), +- EVENT_SA_REPLACE, xauth_inR3 }, ++ EVENT_SA_REPLACE, ++ FM(xauth_inR3), }, + #endif + + /* MODE_CFG_x: +@@ -568,37 +679,57 @@ + { STATE_MODE_CFG_R0, STATE_MODE_CFG_R1, + SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_REPLY, + P(MCFG_ATTR) | P(HASH), P(VID), +- EVENT_SA_REPLACE, modecfg_inR0 }, ++ EVENT_SA_REPLACE, ++ FM(modecfg_inR0), ++ /* RFC ????: */ ++ .hash_type = V1_HASH_1, }, + + { STATE_MODE_CFG_R1, STATE_MODE_CFG_R2, + SMF_ALL_AUTH | SMF_ENCRYPTED, + P(MCFG_ATTR) | P(HASH), P(VID), +- EVENT_SA_REPLACE, modecfg_inR1 }, ++ EVENT_SA_REPLACE, ++ FM(modecfg_inR1), ++ /* RFC ????: */ ++ .hash_type = V1_HASH_1, }, + + { STATE_MODE_CFG_R2, STATE_UNDEFINED, + SMF_ALL_AUTH | SMF_ENCRYPTED, + LEMPTY, LEMPTY, +- EVENT_NULL, unexpected }, ++ EVENT_NULL, ++ FM(unexpected), ++ .hash_type = V1_HASH_NONE, }, + + { STATE_MODE_CFG_I1, STATE_MAIN_I4, + SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_RELEASE_PENDING_P2, + P(MCFG_ATTR) | P(HASH), P(VID), +- EVENT_SA_REPLACE, modecfg_inR1 }, ++ EVENT_SA_REPLACE, ++ FM(modecfg_inR1), ++ /* RFC ????: */ ++ .hash_type = V1_HASH_1, }, + + { STATE_XAUTH_I0, STATE_XAUTH_I1, + SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_REPLY | SMF_RELEASE_PENDING_P2, + P(MCFG_ATTR) | P(HASH), P(VID), +- EVENT_RETRANSMIT, xauth_inI0 }, ++ EVENT_RETRANSMIT, ++ FM(xauth_inI0), ++ /* RFC ????: */ ++ .hash_type = V1_HASH_1, }, + + { STATE_XAUTH_I1, STATE_MAIN_I4, + SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_REPLY | SMF_RELEASE_PENDING_P2, + P(MCFG_ATTR) | P(HASH), P(VID), +- EVENT_RETRANSMIT, xauth_inI1 }, ++ EVENT_RETRANSMIT, ++ FM(xauth_inI1), ++ /* RFC ????: */ ++ .hash_type = V1_HASH_1, }, + + { STATE_IKEv1_ROOF, STATE_IKEv1_ROOF, + LEMPTY, + LEMPTY, LEMPTY, +- EVENT_NULL, NULL }, ++ EVENT_NULL, NULL, ++ .hash_type = V1_HASH_NONE, }, ++ ++#undef FM + #undef P + }; + +@@ -748,6 +879,11 @@ + DBGF(DBG_TMI, "processing IKEv1 state transition %s -> %s", + from->fs_short_name, to->fs_short_name); + ++ if (t->message == NULL) { ++ PEXPECT_LOG("transition %s -> %s missing .message", ++ from->fs_short_name, to->fs_short_name); ++ } ++ + /* + * Point .fs_v1_transitions at to the first entry in + * v1_state_microcode_table for that state. All other +@@ -786,10 +922,32 @@ + * always true of a state? + */ + if ((t->flags & from->fs_flags) != from->fs_flags) { +- DBGF(DBG_BASE, "transition %s -> %s missing flags 0x%"PRIxLSET, +- from->fs_short_name, to->fs_short_name, from->fs_flags); ++ DBGF(DBG_BASE, "transition %s -> %s (%s) missing flags 0x%"PRIxLSET, ++ from->fs_short_name, to->fs_short_name, ++ t->message, from->fs_flags); + } + from->fs_flags |= t->flags & SMF_RETRANSMIT_ON_DUPLICATE; ++ ++ if (!(t->flags & SMF_FIRST_ENCRYPTED_INPUT) && ++ (t->flags & SMF_INPUT_ENCRYPTED) && ++ t->processor != unexpected) { ++ /* ++ * The first encrypted message carries ++ * authentication information so isn't ++ * applicable. Other encrypted messages ++ * require integrity via the HASH payload. ++ */ ++ if (!(t->req_payloads & LELEM(ISAKMP_NEXT_HASH))) { ++ PEXPECT_LOG("transition %s -> %s (%s) missing HASH payload", ++ from->fs_short_name, to->fs_short_name, ++ t->message); ++ } ++ if (t->hash_type == V1_HASH_NONE) { ++ PEXPECT_LOG("transition %s -> %s (%s) missing HASH protection", ++ from->fs_short_name, to->fs_short_name, ++ t->message); ++ } ++ } + } + + /* +@@ -2252,30 +2410,9 @@ + } + } + +- if (md->hdr.isa_xchg == ISAKMP_XCHG_INFO && +- md->hdr.isa_np == ISAKMP_NEXT_HASH) { +- pb_stream *const hash_pbs = &(md)->chain[ISAKMP_NEXT_HASH]->pbs; +- u_char hash_val[MAX_DIGEST_LEN]; +- size_t hash_len = quick_mode_hash12(hash_val, hash_pbs->roof, +- md->message_pbs.roof, +- st, &md->hdr.isa_msgid, FALSE); +- if (pbs_left(hash_pbs) != hash_len) { +- loglog(RC_LOG_SERIOUS, +- "received 'informational' message HASH(1) data is the wrong length (received %zu bytes but expected %zu)", +- pbs_left(hash_pbs), hash_len); +- return; +- } +- if (!memeq(hash_pbs->cur, hash_val, hash_len)) { +- if (DBGP(DBG_CRYPT)) { +- DBG_dump("received 'informational':", +- hash_pbs->cur, pbs_left(hash_pbs)); +- } +- loglog(RC_LOG_SERIOUS, +- "received 'informational' message HASH(1) data does not match computed value"); +- return; +- } else { +- dbg("received 'informational' message HASH(1) data ok"); +- } ++ if (!check_v1_HASH(smc->hash_type, smc->message, st, md)) { ++ /*SEND_NOTIFICATION(INVALID_HASH_INFORMATION);*/ ++ return; + } + + /* more sanity checking: enforce most ordering constraints */ +diff -Naur libreswan-3.29-orig/programs/pluto/ikev1_hash.c libreswan-3.29/programs/pluto/ikev1_hash.c +--- libreswan-3.29-orig/programs/pluto/ikev1_hash.c 1969-12-31 19:00:00.000000000 -0500 ++++ libreswan-3.29/programs/pluto/ikev1_hash.c 2019-06-11 19:24:00.543181473 -0400 +@@ -0,0 +1,158 @@ ++/* IKEv1 HASH payload wierdness, for Libreswan ++ * ++ * Copyright (C) 2019 Andrew Cagney ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See . ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ * ++ */ ++ ++#include "ikev1_hash.h" ++ ++#include "state.h" ++#include "crypt_prf.h" ++#include "ike_alg.h" ++#include "lswlog.h" ++#include "demux.h" ++#include "impair.h" ++ ++bool emit_v1_HASH(enum v1_hash_type hash_type, const char *what, ++ enum exchange_impairment exchange, ++ struct state *st, struct v1_hash_fixup *fixup, ++ pb_stream *rbody) ++{ ++ zero(fixup); ++ fixup->what = what; ++ fixup->hash_type = hash_type; ++ fixup->impair = (impair_v1_hash_exchange == exchange ++ ? impair_v1_hash_payload : SEND_NORMAL); ++ if (fixup->impair == SEND_OMIT) { ++ libreswan_log("IMPAIR: omitting HASH payload for %s", what); ++ return true; ++ } ++ pb_stream hash_pbs; ++ if (!ikev1_out_generic(0, &isakmp_hash_desc, rbody, &hash_pbs)) { ++ return false; ++ } ++ if (fixup->impair == SEND_EMPTY) { ++ libreswan_log("IMPAIR: sending HASH payload with no data for %s", what); ++ } else { ++ /* reserve space for HASH data */ ++ fixup->hash_data = chunk(hash_pbs.cur, st->st_oakley.ta_prf->prf_output_size); ++ if (!out_zero(fixup->hash_data.len, &hash_pbs, "HASH DATA")) ++ return false; ++ } ++ close_output_pbs(&hash_pbs); ++ /* save start of rest of message for later */ ++ fixup->body = rbody->cur; ++ return true; ++} ++ ++void fixup_v1_HASH(struct state *st, const struct v1_hash_fixup *fixup, ++ msgid_t msgid, const uint8_t *roof) ++{ ++ if (fixup->impair >= SEND_ROOF) { ++ libreswan_log("IMPAIR: setting HASH payload bytes to %02x", ++ fixup->impair - SEND_ROOF); ++ /* chunk_fill()? */ ++ memset(fixup->hash_data.ptr, fixup->impair - SEND_ROOF, ++ fixup->hash_data.len); ++ return; ++ } else if (fixup->impair != SEND_NORMAL) { ++ /* already logged above? */ ++ return; ++ } ++ struct crypt_prf *hash = ++ crypt_prf_init_symkey("HASH(1)", st->st_oakley.ta_prf, ++ "SKEYID_a", st->st_skeyid_a_nss); ++ /* msgid */ ++ passert(sizeof(msgid_t) == sizeof(uint32_t)); ++ msgid_t raw_msgid = htonl(msgid); ++ switch (fixup->hash_type) { ++ case V1_HASH_1: ++ /* HASH(1) = prf(SKEYID_a, M-ID | payload ) */ ++ crypt_prf_update_bytes(hash, "M-ID", &raw_msgid, sizeof(raw_msgid)); ++ crypt_prf_update_bytes(hash, "payload", ++ fixup->body, roof - fixup->body); ++ break; ++ case V1_HASH_2: ++ /* HASH(2) = prf(SKEYID_a, M-ID | Ni_b | payload ) */ ++ crypt_prf_update_bytes(hash, "M-ID", &raw_msgid, sizeof(raw_msgid)); ++ crypt_prf_update_chunk(hash, "Ni_b", st->st_ni); ++ crypt_prf_update_bytes(hash, "payload", ++ fixup->body, roof - fixup->body); ++ break; ++ case V1_HASH_3: ++ /* HASH(3) = prf(SKEYID_a, 0 | M-ID | Ni_b | Nr_b) */ ++ crypt_prf_update_byte(hash, "0", 0); ++ crypt_prf_update_bytes(hash, "M-ID", &raw_msgid, sizeof(raw_msgid)); ++ crypt_prf_update_chunk(hash, "Ni_b", st->st_ni); ++ crypt_prf_update_chunk(hash, "Nr_b", st->st_nr); ++ break; ++ default: ++ bad_case(fixup->hash_type); ++ } ++ /* stuff result into hash_data */ ++ passert(fixup->hash_data.len == st->st_oakley.ta_prf->prf_output_size); ++ crypt_prf_final_bytes(&hash, fixup->hash_data.ptr, fixup->hash_data.len); ++ if (DBGP(DBG_BASE)) { ++ DBG_log("%s HASH(%u):", fixup->what, fixup->hash_type); ++ DBG_dump_chunk(NULL, fixup->hash_data); ++ } ++} ++ ++bool check_v1_HASH(enum v1_hash_type type, const char *what, ++ struct state *st, struct msg_digest *md) ++{ ++ if (type == V1_HASH_NONE) { ++ dbg("message '%s' HASH payload not checked early", what); ++ return true; ++ } ++ if (impair_v1_hash_check) { ++ libreswan_log("IMPAIR: skipping check of '%s' HASH payload", what); ++ return true; ++ } ++ if (md->hdr.isa_np != ISAKMP_NEXT_HASH) { ++ loglog(RC_LOG_SERIOUS, "received '%s' message is missing a HASH(%u) payload", ++ what, type); ++ return false; ++ } ++ pb_stream *hash_pbs = &md->chain[ISAKMP_NEXT_HASH]->pbs; ++ chunk_t received_hash = same_in_pbs_left_as_chunk(hash_pbs); ++ if (received_hash.len != st->st_oakley.ta_prf->prf_output_size) { ++ loglog(RC_LOG_SERIOUS, ++ "received '%s' message HASH(%u) data is the wrong length (received %zd bytes but expected %zd)", ++ what, type, received_hash.len, st->st_oakley.ta_prf->prf_output_size); ++ return false; ++ } ++ /* compute the expected hash */ ++ uint8_t hash_val[MAX_DIGEST_LEN]; ++ passert(sizeof(hash_val) >= st->st_oakley.ta_prf->prf_output_size); ++ struct v1_hash_fixup expected = { ++ .hash_data = chunk(hash_val, st->st_oakley.ta_prf->prf_output_size), ++ .body = received_hash.ptr + received_hash.len, ++ .what = what, ++ .hash_type = type, ++ }; ++ fixup_v1_HASH(st, &expected, md->hdr.isa_msgid, md->message_pbs.roof); ++ /* does it match? */ ++ if (!chunk_eq(received_hash, expected.hash_data)) { ++ if (DBGP(DBG_BASE)) { ++ DBG_log("received %s HASH_DATA:", what); ++ DBG_dump_chunk(NULL, received_hash); ++ } ++ loglog(RC_LOG_SERIOUS, ++ "received '%s' message HASH(%u) data does not match computed value", ++ what, type); ++ return false; ++ } ++ dbg("received '%s' message HASH(%u) data ok", what, type); ++ return true; ++} +diff -Naur libreswan-3.29-orig/programs/pluto/ikev1_hash.h libreswan-3.29/programs/pluto/ikev1_hash.h +--- libreswan-3.29-orig/programs/pluto/ikev1_hash.h 1969-12-31 19:00:00.000000000 -0500 ++++ libreswan-3.29/programs/pluto/ikev1_hash.h 2019-06-11 19:24:00.543181473 -0400 +@@ -0,0 +1,77 @@ ++/* IKEv1 HASH payload wierdness, for Libreswan ++ * ++ * Copyright (C) 2019 Andrew Cagney ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See . ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ * ++ */ ++ ++#ifndef IKEV1_HASH_H ++#define IKEV1_HASH_H ++ ++#include ++#include ++ ++#include "chunk.h" ++#include "defs.h" /* for msgid_t */ ++#include "packet.h" /* for pb_stream */ ++#include "impair.h" ++ ++struct state; ++struct msg_digest; ++ ++/* ++ * RFC 2409: 5.5 Phase 2 - Quick Mode ++ * ++ * HASH(1) = prf(SKEYID_a, M-ID | SA | Ni [ | KE ] [ | IDci | IDcr ) ++ * aka HASH(1) = prf(SKEYID_a, M-ID | payload ) ++ * ++ * HASH(2) = prf(SKEYID_a, M-ID | Ni_b | SA | Nr [ | KE ] [ | IDci | IDcr ) ++ * aka HASH(2) = prf(SKEYID_a, M-ID | Ni_b | payload ) ++ * ++ * HASH(3) = prf(SKEYID_a, 0 | M-ID | Ni_b | Nr_b) ++ */ ++ ++enum v1_hash_type { ++ V1_HASH_NONE, ++ V1_HASH_1 = 1, ++ V1_HASH_2 = 2, ++ V1_HASH_3 = 3, ++}; ++ ++/* ++ * Emit (saving where it is) and fixup (a previously saved) v1 HASH ++ * payload. ++ */ ++ ++struct v1_hash_fixup { ++ chunk_t hash_data; ++ const uint8_t *body; ++ msgid_t msgid; ++ const char *what; ++ enum send_impairment impair; ++ enum v1_hash_type hash_type; ++}; ++ ++bool emit_v1_HASH(enum v1_hash_type type, const char *what, ++ enum exchange_impairment exchange, struct state *st, ++ struct v1_hash_fixup *hash_fixup, pb_stream *out_pbs); ++ ++void fixup_v1_HASH(struct state *st, const struct v1_hash_fixup *data, ++ msgid_t msgid, const uint8_t *roof); ++ ++/* ++ * Check the IKEv1 HASH payload. ++ */ ++bool check_v1_HASH(enum v1_hash_type type, const char *what, ++ struct state *st, struct msg_digest *md); ++ ++#endif +diff -Naur libreswan-3.29-orig/programs/pluto/ikev1_main.c libreswan-3.29/programs/pluto/ikev1_main.c +--- libreswan-3.29-orig/programs/pluto/ikev1_main.c 2019-06-10 10:22:04.000000000 -0400 ++++ libreswan-3.29/programs/pluto/ikev1_main.c 2019-06-11 19:23:55.362124010 -0400 +@@ -65,6 +65,7 @@ + #include "fetch.h" + #include "asn1.h" + #include "pending.h" ++#include "ikev1_hash.h" + + #include "crypto.h" + #include "secrets.h" +@@ -1547,6 +1548,10 @@ + "received Hash Payload does not match computed value"); + /* XXX Could send notification back */ + r = STF_FAIL + INVALID_HASH_INFORMATION; ++ } else { ++ dbg("received '%s' message HASH_%s data ok", ++ aggrmode ? "Aggr" : "Main", ++ initiator ? "R" : "I" /*reverse*/); + } + break; + } +@@ -1555,6 +1560,11 @@ + { + r = RSA_check_signature(st, hash_val, hash_len, + &md->chain[ISAKMP_NEXT_SIG]->pbs, 0 /* for ikev2 only*/); ++ if (r != STF_OK) { ++ dbg("received '%s' message SIG_%s data did not match computed value", ++ aggrmode ? "Aggr" : "Main", ++ initiator ? "R" : "I" /*reverse*/); ++ } + break; + } + /* These are the only IKEv1 AUTH methods we support */ +@@ -1862,14 +1872,11 @@ + } + + stf_status send_isakmp_notification(struct state *st, +- uint16_t type, const void *data, +- size_t len) ++ uint16_t type, const void *data, ++ size_t len) + { + msgid_t msgid; + pb_stream rbody; +- u_char +- *r_hashval, /* where in reply to jam hash value */ +- *r_hash_start; /* start of what is to be hashed */ + + msgid = generate_msgid(st); + +@@ -1879,7 +1886,6 @@ + /* HDR* */ + { + struct isakmp_hdr hdr = { +- .isa_np = ISAKMP_NEXT_HASH, + .isa_version = ISAKMP_MAJOR_VERSION << ISA_MAJ_SHIFT | + ISAKMP_MINOR_VERSION, + .isa_xchg = ISAKMP_XCHG_INFO, +@@ -1891,8 +1897,13 @@ + if (!out_struct(&hdr, &isakmp_hdr_desc, &reply_stream, &rbody)) + return STF_INTERNAL_ERROR; + } +- /* HASH -- create and note space to be filled later */ +- START_HASH_PAYLOAD(rbody, ISAKMP_NEXT_N); ++ ++ struct v1_hash_fixup hash_fixup; ++ if (!emit_v1_HASH(V1_HASH_1, "notification", ++ NOTIFICATION_EXCHANGE, ++ st, &hash_fixup, &rbody)) { ++ return STF_INTERNAL_ERROR; ++ } + + /* NOTIFY */ + { +@@ -1919,23 +1930,8 @@ + close_output_pbs(¬ify_pbs); + } + ++ fixup_v1_HASH(st, &hash_fixup, msgid, rbody.cur); + +- { +- /* finish computing HASH */ +- struct hmac_ctx ctx; +- +- hmac_init(&ctx, st->st_oakley.ta_prf, st->st_skeyid_a_nss); +- passert(sizeof(msgid_t) == sizeof(uint32_t)); +- msgid_t raw_msgid = htonl(msgid); +- hmac_update(&ctx, (const void *)&raw_msgid, sizeof(raw_msgid)); +- hmac_update(&ctx, r_hash_start, rbody.cur - r_hash_start); +- hmac_final(r_hashval, &ctx); +- +- DBG(DBG_CRYPT, { +- DBG_log("HASH computed:"); +- DBG_dump("", r_hashval, ctx.hmac_digest_len); +- }); +- } + /* + * save old IV (this prevents from copying a whole new state object + * for NOTIFICATION / DELETE messages we don't need to maintain a state +@@ -1984,13 +1980,9 @@ + pb_stream pbs; + + pb_stream r_hdr_pbs; +- u_char *r_hashval, *r_hash_start; + static monotime_t last_malformed = MONOTIME_EPOCH; + monotime_t n = mononow(); + +- r_hashval = NULL; +- r_hash_start = NULL; +- + switch (type) { + case PAYLOAD_MALFORMED: + /* only send one per second. */ +@@ -2065,7 +2057,6 @@ + struct isakmp_hdr hdr = { + .isa_version = ISAKMP_MAJOR_VERSION << ISA_MAJ_SHIFT | + ISAKMP_MINOR_VERSION, +- .isa_np = encst ? ISAKMP_NEXT_HASH : ISAKMP_NEXT_N, + .isa_xchg = ISAKMP_XCHG_INFO, + .isa_msgid = msgid, + .isa_flags = encst ? ISAKMP_FLAGS_v1_ENCRYPTION : 0, +@@ -2078,15 +2069,14 @@ + } + + /* HASH -- value to be filled later */ +- if (encst) { +- pb_stream hash_pbs; +- passert(ikev1_out_generic(ISAKMP_NEXT_N, &isakmp_hash_desc, &r_hdr_pbs, +- &hash_pbs)); +- r_hashval = hash_pbs.cur; /* remember where to plant value */ +- passert(out_zero(encst->st_oakley.ta_prf->prf_output_size, +- &hash_pbs, "HASH(1)")); +- close_output_pbs(&hash_pbs); +- r_hash_start = r_hdr_pbs.cur; /* hash from after HASH(1) */ ++ struct v1_hash_fixup hash_fixup; ++ if (encst != NULL) { ++ if (!emit_v1_HASH(V1_HASH_1, "send notification", ++ NOTIFICATION_EXCHANGE, ++ encst, &hash_fixup, &r_hdr_pbs)) { ++ /* return STF_INTERNAL_ERROR; */ ++ return; ++ } + } + + /* Notification Payload */ +@@ -2111,21 +2101,8 @@ + } + + /* calculate hash value and patch into Hash Payload */ +- if (encst) { +- struct hmac_ctx ctx; +- +- hmac_init(&ctx, encst->st_oakley.ta_prf, +- encst->st_skeyid_a_nss); +- passert(sizeof(msgid_t) == sizeof(uint32_t)); +- msgid_t raw_msgid = htonl(msgid); +- hmac_update(&ctx, (const void *)&raw_msgid, sizeof(raw_msgid)); +- hmac_update(&ctx, r_hash_start, r_hdr_pbs.cur - r_hash_start); +- hmac_final(r_hashval, &ctx); +- +- DBG(DBG_CRYPT, { +- DBG_log("HASH(1) computed:"); +- DBG_dump("", r_hashval, ctx.hmac_digest_len); +- }); ++ if (encst != NULL) { ++ fixup_v1_HASH(encst, &hash_fixup, msgid, r_hdr_pbs.cur); + } + + if (encst != NULL) { +@@ -2242,9 +2219,6 @@ + struct state *p1st; + ip_said said[EM_MAXRELSPIS]; + ip_said *ns = said; +- u_char +- *r_hashval, /* where in reply to jam hash value */ +- *r_hash_start; /* start of what is to be hashed */ + bool isakmp_sa = FALSE; + + /* If there are IPsec SA's related to this state struct... */ +@@ -2288,7 +2262,6 @@ + struct isakmp_hdr hdr = { + .isa_version = ISAKMP_MAJOR_VERSION << ISA_MAJ_SHIFT | + ISAKMP_MINOR_VERSION, +- .isa_np = ISAKMP_NEXT_HASH, + .isa_xchg = ISAKMP_XCHG_INFO, + .isa_msgid = msgid, + .isa_flags = ISAKMP_FLAGS_v1_ENCRYPTION, +@@ -2300,16 +2273,10 @@ + } + + /* HASH -- value to be filled later */ +- { +- pb_stream hash_pbs; +- +- passert(ikev1_out_generic(ISAKMP_NEXT_D, &isakmp_hash_desc, &r_hdr_pbs, +- &hash_pbs)); +- r_hashval = hash_pbs.cur; /* remember where to plant value */ +- passert(out_zero(p1st->st_oakley.ta_prf->prf_output_size, +- &hash_pbs, "HASH(1)")); +- close_output_pbs(&hash_pbs); +- r_hash_start = r_hdr_pbs.cur; /* hash from after HASH(1) */ ++ struct v1_hash_fixup hash_fixup; ++ if (!emit_v1_HASH(V1_HASH_1, "send delete", DELETE_EXCHANGE, ++ p1st, &hash_fixup, &r_hdr_pbs)) { ++ return /* STF_INTERNAL_ERROR */; + } + + /* Delete Payloads */ +@@ -2375,22 +2342,7 @@ + } + + /* calculate hash value and patch into Hash Payload */ +- { +- struct hmac_ctx ctx; +- +- hmac_init(&ctx, p1st->st_oakley.ta_prf, +- p1st->st_skeyid_a_nss); +- passert(sizeof(msgid_t) == sizeof(uint32_t)); +- msgid_t raw_msgid = htonl(msgid); +- hmac_update(&ctx, (const void *)&raw_msgid, sizeof(raw_msgid)); +- hmac_update(&ctx, r_hash_start, r_hdr_pbs.cur - r_hash_start); +- hmac_final(r_hashval, &ctx); +- +- DBG(DBG_CRYPT, { +- DBG_log("HASH(1) computed:"); +- DBG_dump("", r_hashval, ctx.hmac_digest_len); +- }); +- } ++ fixup_v1_HASH(p1st, &hash_fixup, msgid, r_hdr_pbs.cur); + + /* + * Do a dance to avoid needing a new state object. +diff -Naur libreswan-3.29-orig/programs/pluto/ikev1_quick.c libreswan-3.29/programs/pluto/ikev1_quick.c +--- libreswan-3.29-orig/programs/pluto/ikev1_quick.c 2019-06-10 10:22:04.000000000 -0400 ++++ libreswan-3.29/programs/pluto/ikev1_quick.c 2019-06-11 19:28:00.687844878 -0400 +@@ -81,6 +81,7 @@ + #include "pluto_x509.h" + #include "ip_address.h" + #include "af_info.h" ++#include "ikev1_hash.h" + + #include + +@@ -660,69 +661,6 @@ + return !bad_proposal; + } + +-/* Compute HASH(1), HASH(2) of Quick Mode. +- * HASH(1) is part of Quick I1 message. +- * HASH(2) is part of Quick R1 message. +- * Used by: quick_outI1, quick_inI1_outR1 (twice), quick_inR1_outI2 +- * (see RFC 2409 "IKE" 5.5, pg. 18 or draft-ietf-ipsec-ike-01.txt 6.2 pg 25) +- */ +-size_t quick_mode_hash12(u_char *dest, const u_char *start, +- const u_char *roof, +- const struct state *st, const msgid_t *msgid, +- bool hash2) +-{ +- struct hmac_ctx ctx; +- +-#if 0 /* if desperate to debug hashing */ +-# define hmac_update(ctx, ptr, len) { \ +- DBG_dump("hash input", (ptr), (len)); \ +- (hmac_update)((ctx), (ptr), (len)); \ +-} +- DBG_dump("hash key", st->st_skeyid_a.ptr, st->st_skeyid_a.len); +-#endif +- hmac_init(&ctx, st->st_oakley.ta_prf, st->st_skeyid_a_nss); +- passert(sizeof(msgid_t) == sizeof(uint32_t)); +- msgid_t raw_msgid = htonl(*msgid); +- hmac_update(&ctx, (const void *)&raw_msgid, sizeof(raw_msgid)); +- if (hash2) +- hmac_update_chunk(&ctx, st->st_ni); /* include Ni_b in the hash */ +- hmac_update(&ctx, start, roof - start); +- hmac_final(dest, &ctx); +- +- DBG(DBG_CRYPT, { +- DBG_log("HASH(%d) computed:", hash2 + 1); +- DBG_dump("", dest, ctx.hmac_digest_len); +- }); +- return ctx.hmac_digest_len; +- +-# undef hmac_update +-} +- +-/* Compute HASH(3) in Quick Mode (part of Quick I2 message). +- * Used by: quick_inR1_outI2, quick_inI2 +- * See RFC2409 "The Internet Key Exchange (IKE)" 5.5. +- * NOTE: this hash (unlike HASH(1) and HASH(2)) ONLY covers the +- * Message ID and Nonces. This is a mistake. +- */ +-static size_t quick_mode_hash3(u_char *dest, struct state *st) +-{ +- struct hmac_ctx ctx; +- +- hmac_init(&ctx, st->st_oakley.ta_prf, st->st_skeyid_a_nss); +- hmac_update(&ctx, (const u_char *)"\0", 1); +- passert(sizeof(msgid_t) == sizeof(uint32_t)); +- msgid_t raw_msgid = htonl(st->st_msgid); +- hmac_update(&ctx, (const void*)&raw_msgid, sizeof(raw_msgid)); +- hmac_update_chunk(&ctx, st->st_ni); +- hmac_update_chunk(&ctx, st->st_nr); +- hmac_final(dest, &ctx); +- if (DBGP(DBG_CRYPT)) { +- DBG_dump("HASH(3) computed:", dest, +- ctx.hmac_digest_len); +- } +- return ctx.hmac_digest_len; +-} +- + /* Compute Phase 2 IV. + * Uses Phase 1 IV from st_iv; puts result in st_new_iv. + */ +@@ -879,9 +817,6 @@ + struct state *isakmp_sa = state_with_serialno(st->st_clonedfrom); + struct connection *c = st->st_connection; + pb_stream rbody; +- u_char /* set by START_HASH_PAYLOAD: */ +- *r_hashval, /* where in reply to jam hash value */ +- *r_hash_start; /* start of what is to be hashed */ + bool has_client = c->spd.this.has_client || c->spd.that.has_client || + c->spd.this.protocol != 0 || c->spd.that.protocol != 0 || + c->spd.this.port != 0 || c->spd.that.port != 0; +@@ -915,7 +850,6 @@ + struct isakmp_hdr hdr = { + .isa_version = ISAKMP_MAJOR_VERSION << ISA_MAJ_SHIFT | + ISAKMP_MINOR_VERSION, +- .isa_np = ISAKMP_NEXT_HASH, + .isa_xchg = ISAKMP_XCHG_QUICK, + .isa_msgid = st->st_msgid, + .isa_flags = ISAKMP_FLAGS_v1_ENCRYPTION, +@@ -930,7 +864,11 @@ + } + + /* HASH(1) -- create and note space to be filled later */ +- START_HASH_PAYLOAD(rbody, ISAKMP_NEXT_SA); ++ struct v1_hash_fixup hash_fixup; ++ if (!emit_v1_HASH(V1_HASH_1, "outI1", QUICK_EXCHANGE, ++ st, &hash_fixup, &rbody)) { ++ return STF_INTERNAL_ERROR; ++ } + + /* SA out */ + +@@ -1010,8 +948,7 @@ + } + + /* finish computing HASH(1), inserting it in output */ +- (void) quick_mode_hash12(r_hashval, r_hash_start, rbody.cur, +- st, &st->st_msgid, FALSE); ++ fixup_v1_HASH(st, &hash_fixup, st->st_msgid, rbody.cur); + + /* encrypt message, except for fixed part of header */ + +@@ -1098,13 +1035,6 @@ + struct payload_digest *const id_pd = md->chain[ISAKMP_NEXT_ID]; + struct verify_oppo_bundle b; + +- /* HASH(1) in */ +- CHECK_QUICK_HASH(md, +- quick_mode_hash12(hash_val, hash_pbs->roof, +- md->message_pbs.roof, +- p1st, &md->hdr.isa_msgid, FALSE), +- "HASH(1)", "Quick I1"); +- + /* [ IDci, IDcr ] in + * We do this now (probably out of physical order) because + * we wish to select the correct connection before we consult +@@ -1577,9 +1507,6 @@ + struct state *st = md->st; + struct payload_digest *const id_pd = md->chain[ISAKMP_NEXT_ID]; + struct payload_digest *const sapd = md->chain[ISAKMP_NEXT_SA]; +- u_char /* set by START_HASH_PAYLOAD: */ +- *r_hashval, /* where in reply to jam hash value */ +- *r_hash_start; /* from where to start hashing */ + + /* Start the output packet. + * +@@ -1594,12 +1521,15 @@ + + /* HDR* out */ + pb_stream rbody; +- ikev1_init_out_pbs_echo_hdr(md, TRUE, ISAKMP_NEXT_HASH, ++ ikev1_init_out_pbs_echo_hdr(md, TRUE, 0, + &reply_stream, reply_buffer, sizeof(reply_buffer), + &rbody); + +- /* HASH(2) out -- first pass */ +- START_HASH_PAYLOAD(rbody, ISAKMP_NEXT_SA); ++ struct v1_hash_fixup hash_fixup; ++ if (!emit_v1_HASH(V1_HASH_2, "quick inR1 outI2", ++ QUICK_EXCHANGE, st, &hash_fixup, &rbody)) { ++ return STF_INTERNAL_ERROR; ++ } + + passert(st->st_connection != NULL); + +@@ -1720,8 +1650,7 @@ + } + + /* Compute reply HASH(2) and insert in output */ +- (void)quick_mode_hash12(r_hashval, r_hash_start, rbody.cur, +- st, &st->st_msgid, TRUE); ++ fixup_v1_HASH(st, &hash_fixup, st->st_msgid, rbody.cur); + + /* Derive new keying material */ + compute_keymats(st); +@@ -1758,13 +1687,6 @@ + + stf_status quick_inR1_outI2(struct state *st, struct msg_digest *md) + { +- /* HASH(2) in */ +- CHECK_QUICK_HASH(md, +- quick_mode_hash12(hash_val, hash_pbs->roof, +- md->message_pbs.roof, +- st, &st->st_msgid, TRUE), +- "HASH(2)", "Quick R1"); +- + /* SA in */ + { + struct payload_digest *const sa_pd = md->chain[ISAKMP_NEXT_SA]; +@@ -1812,7 +1734,7 @@ + struct connection *c = st->st_connection; + + pb_stream rbody; +- ikev1_init_out_pbs_echo_hdr(md, TRUE, ISAKMP_NEXT_HASH, ++ ikev1_init_out_pbs_echo_hdr(md, TRUE, 0, + &reply_stream, reply_buffer, sizeof(reply_buffer), + &rbody); + +@@ -1907,7 +1829,7 @@ + + /* HASH(3) out -- sometimes, we add more content */ + { +- u_char *r_hashval; /* set by START_HASH_PAYLOAD */ ++ struct v1_hash_fixup hash_fixup; + + #ifdef IMPAIR_UNALIGNED_I2_MSG + { +@@ -1945,12 +1867,13 @@ + } + } + #else +- START_HASH_PAYLOAD_NO_R_HASH_START(rbody, +- ISAKMP_NEXT_NONE); ++ if (!emit_v1_HASH(V1_HASH_3, "quick_inR1_outI2", ++ QUICK_EXCHANGE, st, &hash_fixup, &rbody)) { ++ return STF_INTERNAL_ERROR; ++ } + #endif + +- +- (void)quick_mode_hash3(r_hashval, st); ++ fixup_v1_HASH(st, &hash_fixup, st->st_msgid, NULL); + } + + /* Derive new keying material */ +@@ -1986,12 +1909,8 @@ + * (see RFC 2409 "IKE" 5.5) + * Installs outbound IPsec SAs, routing, etc. + */ +-stf_status quick_inI2(struct state *st, struct msg_digest *md) ++stf_status quick_inI2(struct state *st, struct msg_digest *md UNUSED) + { +- /* HASH(3) in */ +- CHECK_QUICK_HASH(md, quick_mode_hash3(hash_val, st), +- "HASH(3)", "Quick I2"); +- + /* Tell the kernel to establish the outbound and routing part of the new SA + * (the previous state established inbound) + * (unless the commit bit is set -- which we don't support). +diff -Naur libreswan-3.29-orig/programs/pluto/ikev1_xauth.c libreswan-3.29/programs/pluto/ikev1_xauth.c +--- libreswan-3.29-orig/programs/pluto/ikev1_xauth.c 2019-06-10 10:22:04.000000000 -0400 ++++ libreswan-3.29/programs/pluto/ikev1_xauth.c 2019-06-11 19:28:00.688844889 -0400 +@@ -78,6 +78,8 @@ + #include "send.h" /* for send without recording */ + #include "ikev1_send.h" + #include "af_info.h" ++#include "ikev1_hash.h" ++#include "impair.h" + + /* forward declarations */ + static stf_status xauth_client_ackstatus(struct state *st, +@@ -198,25 +200,19 @@ + * @param st State structure + * @return size_t Length of the HASH + */ +-static size_t xauth_mode_cfg_hash(u_char *dest, +- const u_char *start, +- const u_char *roof, +- const struct state *st) +-{ +- struct hmac_ctx ctx; +- +- hmac_init(&ctx, st->st_oakley.ta_prf, st->st_skeyid_a_nss); +- passert(sizeof(msgid_t) == sizeof(uint32_t)); +- msgid_t raw_msgid = htonl(st->st_msgid_phase15); +- hmac_update(&ctx, (const void *)&raw_msgid, sizeof(raw_msgid)); +- hmac_update(&ctx, start, roof - start); +- hmac_final(dest, &ctx); +- +- DBG(DBG_CRYPT|DBG_XAUTH, { +- DBG_log("XAUTH: HASH computed:"); +- DBG_dump("", dest, ctx.hmac_digest_len); +- }); +- return ctx.hmac_digest_len; ++ ++static bool emit_xauth_hash(const char *what, struct state *st, ++ struct v1_hash_fixup *hash_fixup, pb_stream *out) ++{ ++ return emit_v1_HASH(V1_HASH_1, what, XAUTH_EXCHANGE, ++ st, hash_fixup, out); ++} ++ ++static void fixup_xauth_hash(struct state *st, ++ struct v1_hash_fixup *hash_fixup, ++ const uint8_t *roof) ++{ ++ fixup_v1_HASH(st, hash_fixup, st->st_msgid_phase15, roof); + } + + /** +@@ -383,23 +379,10 @@ + bool use_modecfg_addr_as_client_addr, + uint16_t ap_id) + { +- unsigned char *r_hash_start, *r_hashval; +- +- /* START_HASH_PAYLOAD(rbody, ISAKMP_NEXT_MCFG_ATTR); */ +- +- { +- pb_stream hash_pbs; +- +- if (!ikev1_out_generic(ISAKMP_NEXT_MCFG_ATTR, &isakmp_hash_desc, rbody, &hash_pbs)) +- return STF_INTERNAL_ERROR; +- +- r_hashval = hash_pbs.cur; /* remember where to plant value */ +- if (!out_zero(st->st_oakley.ta_prf->prf_output_size, +- &hash_pbs, "HASH")) +- return STF_INTERNAL_ERROR; +- +- close_output_pbs(&hash_pbs); +- r_hash_start = rbody->cur; /* hash from after HASH payload */ ++ struct v1_hash_fixup hash_fixup; ++ if (!emit_xauth_hash("XAUTH: mode config response", ++ st, &hash_fixup, rbody)) { ++ return STF_INTERNAL_ERROR; + } + + /* ATTR out */ +@@ -497,7 +480,7 @@ + return STF_INTERNAL_ERROR; + } + +- xauth_mode_cfg_hash(r_hashval, r_hash_start, rbody->cur, st); ++ fixup_xauth_hash(st, &hash_fixup, rbody->cur); + + if (!ikev1_close_message(rbody, st) || + !ikev1_encrypt_message(rbody, st)) +@@ -523,7 +506,6 @@ + /* HDR out */ + { + struct isakmp_hdr hdr = { +- .isa_np = ISAKMP_NEXT_HASH, + .isa_version = ISAKMP_MAJOR_VERSION << ISA_MAJ_SHIFT | + ISAKMP_MINOR_VERSION, + .isa_xchg = ISAKMP_XCHG_MODE_CFG, +@@ -604,7 +586,6 @@ + pb_stream reply; + pb_stream rbody; + unsigned char buf[256]; +- u_char *r_hash_start, *r_hashval; + const enum state_kind p_state = st->st_state; + + /* set up reply */ +@@ -620,7 +601,6 @@ + /* HDR out */ + { + struct isakmp_hdr hdr = { +- .isa_np = ISAKMP_NEXT_HASH, + .isa_version = ISAKMP_MAJOR_VERSION << ISA_MAJ_SHIFT | + ISAKMP_MINOR_VERSION, + .isa_xchg = ISAKMP_XCHG_MODE_CFG, +@@ -638,7 +618,11 @@ + return STF_INTERNAL_ERROR; + } + +- START_HASH_PAYLOAD(rbody, ISAKMP_NEXT_MCFG_ATTR); ++ struct v1_hash_fixup hash_fixup; ++ if (!emit_xauth_hash("XAUTH: send request", ++ st, &hash_fixup, &rbody)) { ++ return STF_INTERNAL_ERROR; ++ } + + /* ATTR out */ + { +@@ -668,7 +652,7 @@ + return STF_INTERNAL_ERROR; + } + +- xauth_mode_cfg_hash(r_hashval, r_hash_start, rbody.cur, st); ++ fixup_xauth_hash(st, &hash_fixup, rbody.cur); + + if (!ikev1_close_message(&rbody, st)) + return STF_INTERNAL_ERROR; +@@ -719,7 +703,6 @@ + pb_stream reply; + pb_stream rbody; + unsigned char buf[256]; +- u_char *r_hash_start, *r_hashval; + + /* set up reply */ + init_out_pbs(&reply, buf, sizeof(buf), "xauth_buf"); +@@ -733,7 +716,6 @@ + /* HDR out */ + { + struct isakmp_hdr hdr = { +- .isa_np = ISAKMP_NEXT_HASH, + .isa_version = ISAKMP_MAJOR_VERSION << ISA_MAJ_SHIFT | + ISAKMP_MINOR_VERSION, + .isa_xchg = ISAKMP_XCHG_MODE_CFG, +@@ -752,7 +734,11 @@ + return STF_INTERNAL_ERROR; + } + +- START_HASH_PAYLOAD(rbody, ISAKMP_NEXT_MCFG_ATTR); ++ struct v1_hash_fixup hash_fixup; ++ if (!emit_xauth_hash("XAUTH: mode config request", ++ st, &hash_fixup, &rbody)) { ++ return STF_INTERNAL_ERROR; ++ } + + /* ATTR out */ + { +@@ -785,7 +771,7 @@ + return STF_INTERNAL_ERROR; + } + +- xauth_mode_cfg_hash(r_hashval, r_hash_start, rbody.cur, st); ++ fixup_xauth_hash(st, &hash_fixup, rbody.cur); + + if (!ikev1_close_message(&rbody, st)) + return STF_INTERNAL_ERROR; +@@ -821,7 +807,6 @@ + pb_stream reply; + pb_stream rbody; + unsigned char buf[256]; +- u_char *r_hash_start, *r_hashval; + + /* set up reply */ + init_out_pbs(&reply, buf, sizeof(buf), "xauth_buf"); +@@ -832,7 +817,6 @@ + /* HDR out */ + { + struct isakmp_hdr hdr = { +- .isa_np = ISAKMP_NEXT_HASH, + .isa_version = ISAKMP_MAJOR_VERSION << ISA_MAJ_SHIFT | + ISAKMP_MINOR_VERSION, + .isa_xchg = ISAKMP_XCHG_MODE_CFG, +@@ -850,7 +834,10 @@ + return STF_INTERNAL_ERROR; + } + +- START_HASH_PAYLOAD(rbody, ISAKMP_NEXT_MCFG_ATTR); ++ struct v1_hash_fixup hash_fixup; ++ if (!emit_xauth_hash("XAUTH: status", st, &hash_fixup, &rbody)) { ++ return STF_INTERNAL_ERROR; ++ } + + /* ATTR out */ + { +@@ -873,7 +860,7 @@ + return STF_INTERNAL_ERROR; + } + +- xauth_mode_cfg_hash(r_hashval, r_hash_start, rbody.cur, st); ++ fixup_xauth_hash(st, &hash_fixup, rbody.cur); + + if (!ikev1_close_message(&rbody, st)) + return STF_INTERNAL_ERROR; +@@ -1280,12 +1267,6 @@ + bool gotname = FALSE, + gotpassword = FALSE; + +- CHECK_QUICK_HASH(md, +- xauth_mode_cfg_hash(hash_val, hash_pbs->roof, +- md->message_pbs.roof, +- st), +- "XAUTH-HASH", "XAUTH R0"); +- + setchunk(name, unknown, sizeof(unknown) - 1); /* to make diagnostics easier */ + + /* XXX This needs checking with the proper RFC's - ISAKMP_CFG_ACK got added for Cisco interop */ +@@ -1469,11 +1450,6 @@ + DBG(DBG_CONTROLMORE, DBG_log("arrived in modecfg_inR0")); + + st->st_msgid_phase15 = md->hdr.isa_msgid; +- CHECK_QUICK_HASH(md, +- xauth_mode_cfg_hash(hash_val, +- hash_pbs->roof, +- md->message_pbs.roof, st), +- "MODECFG-HASH", "MODE R0"); + + switch (ma->isama_type) { + default: +@@ -1559,12 +1535,6 @@ + DBG(DBG_CONTROL, DBG_log("modecfg_inI2")); + + st->st_msgid_phase15 = md->hdr.isa_msgid; +- CHECK_QUICK_HASH(md, +- xauth_mode_cfg_hash(hash_val, +- hash_pbs->roof, +- md->message_pbs.roof, +- st), +- "MODECFG-HASH", "MODE R1"); + + /* CHECK that SET has been received. */ + +@@ -1690,11 +1660,6 @@ + DBG(DBG_CONTROL, DBG_log("modecfg_inR1: received mode cfg reply")); + + st->st_msgid_phase15 = md->hdr.isa_msgid; +- CHECK_QUICK_HASH(md, +- xauth_mode_cfg_hash(hash_val, hash_pbs->roof, +- md->message_pbs.roof, +- st), +- "MODECFG-HASH", "MODE R1"); + + switch (ma->isama_type) { + default: +@@ -1978,26 +1943,12 @@ + pb_stream *rbody, + uint16_t ap_id) + { +- unsigned char *r_hash_start, *r_hashval; + char xauth_username[MAX_XAUTH_USERNAME_LEN]; + struct connection *c = st->st_connection; + +- /* START_HASH_PAYLOAD(rbody, ISAKMP_NEXT_MCFG_ATTR); */ +- +- { +- pb_stream hash_pbs; +- int np = ISAKMP_NEXT_MCFG_ATTR; +- +- if (!ikev1_out_generic(np, &isakmp_hash_desc, rbody, &hash_pbs)) +- return STF_INTERNAL_ERROR; +- +- r_hashval = hash_pbs.cur; /* remember where to plant value */ +- if (!out_zero(st->st_oakley.ta_prf->prf_output_size, +- &hash_pbs, "HASH")) +- return STF_INTERNAL_ERROR; +- +- close_output_pbs(&hash_pbs); +- r_hash_start = (rbody)->cur; /* hash from after HASH payload */ ++ struct v1_hash_fixup hash_fixup; ++ if (!emit_xauth_hash("XAUTH: client response", st, &hash_fixup, rbody)) { ++ return STF_INTERNAL_ERROR; + } + + /* MCFG_ATTR out */ +@@ -2201,7 +2152,7 @@ + libreswan_log("XAUTH: Answering XAUTH challenge with user='%s'", + st->st_xauth_username); + +- xauth_mode_cfg_hash(r_hashval, r_hash_start, rbody->cur, st); ++ fixup_xauth_hash(st, &hash_fixup, rbody->cur); + + if (!ikev1_close_message(rbody, st) || + !ikev1_encrypt_message(rbody, st)) +@@ -2252,10 +2203,6 @@ + } + + st->st_msgid_phase15 = md->hdr.isa_msgid; +- CHECK_QUICK_HASH(md, xauth_mode_cfg_hash(hash_val, +- hash_pbs->roof, +- md->message_pbs.roof, st), +- "MODECFG-HASH", "XAUTH I0"); + + switch (ma->isama_type) { + default: +@@ -2446,24 +2393,9 @@ + pb_stream *rbody, + uint16_t ap_id) + { +- unsigned char *r_hash_start, *r_hashval; +- +- /* START_HASH_PAYLOAD(rbody, ISAKMP_NEXT_MCFG_ATTR); */ +- +- { +- pb_stream hash_pbs; +- int np = ISAKMP_NEXT_MCFG_ATTR; +- +- if (!ikev1_out_generic(np, &isakmp_hash_desc, rbody, &hash_pbs)) +- return STF_INTERNAL_ERROR; +- +- r_hashval = hash_pbs.cur; /* remember where to plant value */ +- if (!out_zero(st->st_oakley.ta_prf->prf_output_size, +- &hash_pbs, "HASH")) +- return STF_INTERNAL_ERROR; +- +- close_output_pbs(&hash_pbs); +- r_hash_start = (rbody)->cur; /* hash from after HASH payload */ ++ struct v1_hash_fixup hash_fixup; ++ if (!emit_xauth_hash("XAUTH: ack status", st, &hash_fixup, rbody)) { ++ return STF_INTERNAL_ERROR; + } + + /* ATTR out */ +@@ -2486,7 +2418,7 @@ + return STF_INTERNAL_ERROR; + } + +- xauth_mode_cfg_hash(r_hashval, r_hash_start, rbody->cur, st); ++ fixup_xauth_hash(st, &hash_fixup, rbody->cur); + + if (!ikev1_close_message(rbody, st) || + !ikev1_encrypt_message(rbody, st)) +@@ -2525,11 +2457,6 @@ + DBG(DBG_CONTROLMORE, DBG_log("Continuing with xauth_inI1")); + + st->st_msgid_phase15 = md->hdr.isa_msgid; +- CHECK_QUICK_HASH(md, +- xauth_mode_cfg_hash(hash_val, +- hash_pbs->roof, +- md->message_pbs.roof, st), +- "MODECFG-HASH", "XAUTH I1"); + + switch (ma->isama_type) { + default: +diff -Naur libreswan-3.29-orig/programs/pluto/ipsec_doi.h libreswan-3.29/programs/pluto/ipsec_doi.h +--- libreswan-3.29-orig/programs/pluto/ipsec_doi.h 2019-06-10 10:22:04.000000000 -0400 ++++ libreswan-3.29/programs/pluto/ipsec_doi.h 2019-06-11 19:28:00.688844889 -0400 +@@ -65,67 +65,6 @@ + const struct oakley_group_desc *gr, + struct payload_digest *ke_pd); + +-/* START_HASH_PAYLOAD_NO_HASH_START +- * +- * Emit a to-be-filled-in hash payload, noting the field start (r_hashval) +- * and the start of the part of the message to be hashed (r_hash_start). +- * This macro is magic. +- * - it can cause the caller to return +- * - it references variables local to the caller (r_hashval, st) +- */ +-#define START_HASH_PAYLOAD_NO_R_HASH_START(rbody, np) { \ +- pb_stream hash_pbs; \ +- if (!ikev1_out_generic(np, &isakmp_hash_desc, &(rbody), &hash_pbs)) \ +- return STF_INTERNAL_ERROR; \ +- r_hashval = hash_pbs.cur; /* remember where to plant value */ \ +- if (!out_zero(st->st_oakley.ta_prf->prf_output_size, \ +- &hash_pbs, "HASH")) \ +- return STF_INTERNAL_ERROR; \ +- close_output_pbs(&hash_pbs); \ +-} +- +-/* START_HASH_PAYLOAD +- * +- * Emit a to-be-filled-in hash payload, noting the field start (r_hashval) +- * and the start of the part of the message to be hashed (r_hash_start). +- * This macro is magic. +- * - it can cause the caller to return +- * - it references variables local to the caller (r_hashval, r_hash_start, st) +- */ +-#define START_HASH_PAYLOAD(rbody, np) { \ +- START_HASH_PAYLOAD_NO_R_HASH_START(rbody, np); \ +- r_hash_start = (rbody).cur; /* hash from after HASH payload */ \ +-} +- +-/* CHECK_QUICK_HASH +- * +- * This macro is magic -- it cannot be expressed as a function. +- * - it causes the caller to return! +- * - it declares local variables and expects the "do_hash" argument +- * expression to reference them (hash_val, hash_pbs) +- */ +-#define CHECK_QUICK_HASH(md, do_hash, hash_name, msg_name) { \ +- pb_stream *const hash_pbs = &(md)->chain[ISAKMP_NEXT_HASH]->pbs; \ +- u_char hash_val[MAX_DIGEST_LEN]; \ +- size_t hash_len = (do_hash); \ +- if (pbs_left(hash_pbs) != hash_len || \ +- !memeq(hash_pbs->cur, hash_val, hash_len)) { \ +- if (DBGP(DBG_CRYPT)) { \ +- DBG_dump("received " hash_name ":", \ +- hash_pbs->cur, pbs_left(hash_pbs)); \ +- } \ +- loglog(RC_LOG_SERIOUS, \ +- "received " hash_name " does not match computed value in " msg_name); \ +- /* XXX Could send notification back */ \ +- return STF_FAIL + INVALID_HASH_INFORMATION; \ +- } \ +- } +- +-size_t quick_mode_hash12(u_char *dest, const u_char *start, +- const u_char *roof, +- const struct state *st, const msgid_t *msgid, +- bool hash2); +- + extern stf_status send_isakmp_notification(struct state *st, + uint16_t type, const void *data, + size_t len); +diff -Naur libreswan-3.29-orig/programs/pluto/Makefile libreswan-3.29/programs/pluto/Makefile +--- libreswan-3.29-orig/programs/pluto/Makefile 2019-06-10 10:22:04.000000000 -0400 ++++ libreswan-3.29/programs/pluto/Makefile 2019-06-11 19:23:19.841729230 -0400 +@@ -215,6 +215,7 @@ + OBJS += ikev2_ipseckey.o + endif + OBJS += ikev1.o ikev1_main.o ikev1_quick.o ikev1_dpd.o ikev1_spdb_struct.o ikev1_msgid.o ++OBJS += ikev1_hash.o + OBJS += ikev2.o ikev2_parent.o ikev2_child.o ikev2_spdb_struct.o + OBJS += ikev2_ecdsa.o ikev2_rsa.o ikev2_psk.o ikev2_ppk.o ikev2_crypto.o + OBJS += ikev2_redirect.o diff --git a/SPECS/libreswan.spec b/SPECS/libreswan.spec new file mode 100644 index 0000000..4419183 --- /dev/null +++ b/SPECS/libreswan.spec @@ -0,0 +1,469 @@ +%global _hardened_build 1 +# These are rpm macros and are 0 or 1 +%global with_efence 0 +%global with_development 0 +%global with_cavstests 1 +# Libreswan config options +%global libreswan_config \\\ + FINALLIBEXECDIR=%{_libexecdir}/ipsec \\\ + FINALMANDIR=%{_mandir} \\\ + FIPSPRODUCTCHECK=%{_sysconfdir}/system-fips \\\ + INC_RCDEFAULT=%{_initrddir} \\\ + INC_USRLOCAL=%{_prefix} \\\ + INITSYSTEM=systemd \\\ + NSS_HAS_IPSEC_PROFILE=true \\\ + USE_DNSSEC=true \\\ + USE_FIPSCHECK=true \\\ + USE_LABELED_IPSEC=true \\\ + USE_LDAP=true \\\ + USE_LIBCAP_NG=true \\\ + USE_LIBCURL=true \\\ + USE_LINUX_AUDIT=true \\\ + USE_NM=true \\\ + USE_SECCOMP=true \\\ + USE_XAUTHPAM=true \\\ + USE_KLIPS=false \\\ + USE_NSS_PRF=true \\\ + USE_PRF_AES_XCBC=true \\\ +%{nil} + +#global prever rc1 + +Name: libreswan +Summary: IPsec implementation with IKEv1 and IKEv2 keying protocols +# version is generated in the release script +Version: 3.29 +Release: %{?prever:0.}6%{?prever:.%{prever}}%{?dist} +License: GPLv2 +Url: https://libreswan.org/ +Source0: https://download.libreswan.org/%{?prever:with_development/}%{name}-%{version}%{?prever}.tar.gz +%if 0%{with_cavstests} +Source1: https://download.libreswan.org/cavs/ikev1_dsa.fax.bz2 +Source2: https://download.libreswan.org/cavs/ikev1_psk.fax.bz2 +Source3: https://download.libreswan.org/cavs/ikev2.fax.bz2 +%endif + +Patch1: libreswan-3.28-maintain-different-v1v2-split.patch +Patch2: libreswan-3.29-CVE-2019-10155-testing.patch +Patch3: libreswan-3.29-1723957-audit.patch +Patch4: libreswan-3.25-1724200-halfopen-shunt.patch +Patch5: libreswan-3.29-1699318-show.patch +Patch6: libreswan-3.29-1714331-nss-kdf.patch + +Group: System Environment/Daemons +BuildRequires: bison flex pkgconfig +BuildRequires: systemd systemd-units systemd-devel +Requires(post): coreutils bash systemd +Requires(preun): systemd +Requires(postun): systemd + +BuildRequires: pkgconfig hostname +# minimum version for support for rhbz#1651314 +BuildRequires: nss-tools nss-devel >= 3.44.0-8 +Requires: nss >= 3.44.0-8 +BuildRequires: nspr-devel +BuildRequires: pam-devel +BuildRequires: libevent-devel +BuildRequires: unbound-devel >= 1.6.0-6 ldns-devel +BuildRequires: libseccomp-devel +BuildRequires: libselinux-devel +BuildRequires: fipscheck-devel +Requires: fipscheck%{_isa} +Buildrequires: audit-libs-devel + +BuildRequires: libcap-ng-devel +BuildRequires: openldap-devel curl-devel +%if 0%{with_efence} +BuildRequires: ElectricFence +%endif +BuildRequires: xmlto + +Requires: nss-tools, nss-softokn +Requires: iproute >= 2.6.8 +Requires: unbound-libs >= 1.6.6 + +%description +Libreswan is a free implementation of IKE/IPsec for Linux. IPsec is +the Internet Protocol Security and uses strong cryptography to provide +both authentication and encryption services. These services allow you +to build secure tunnels through untrusted networks. Everything passing +through the untrusted net is encrypted by the ipsec gateway machine and +decrypted by the gateway at the other end of the tunnel. The resulting +tunnel is a virtual private network or VPN. + +This package contains the daemons and userland tools for setting up +Libreswan. + +Libreswan also supports IKEv2 (RFC7296) and Secure Labeling + +Libreswan is based on Openswan-2.6.38 which in turn is based on FreeS/WAN-2.04 + +%prep +%setup -q -n libreswan-%{version}%{?prever} +%patch1 -p1 +%patch2 -p1 +%patch3 -p1 +%patch4 -p1 +%patch5 -p1 +%patch6 -p1 + +pathfix.py -i %{__python3} -pn programs/verify/verify.in programs/show/show.in \ + testing/cert_verify/usage_test testing/pluto/ikev1-01-fuzzer/cve-2015-3204.py \ + testing/pluto/ikev2-15-fuzzer/send_bad_packets.py testing/x509/dist_certs.py \ + programs/_unbound-hook/_unbound-hook.in + +# replace unsupported KLIPS README +echo "KLIPS is not supported with RHEL8" > README.KLIPS + +# linking to freebl is not needed +sed -i "s/-lfreebl //" mk/config.mk + +# enable crypto-policies support +sed -i "s:#[ ]*include \(.*\)\(/crypto-policies/back-ends/libreswan.config\)$:include \1\2:" programs/configs/ipsec.conf.in + +%build +%if 0%{with_efence} +%global efence "-lefence" +%endif + +#796683: -fno-strict-aliasing +make %{?_smp_mflags} \ +%if 0%{with_development} + USERCOMPILE="-g -DGCC_LINT %(echo %{optflags} | sed -e s/-O[0-9]*/ /) %{?efence} -fPIE -pie -fno-strict-aliasing -Wformat-nonliteral -Wformat-security" \ +%else + USERCOMPILE="-g -DGCC_LINT %{optflags} %{?efence} -fPIE -pie -fno-strict-aliasing -Wformat-nonliteral -Wformat-security" \ +%endif + USERLINK="-g -pie -Wl,-z,relro,-z,now %{?efence}" \ + %{libreswan_config} \ + programs +FS=$(pwd) + +# Add generation of HMAC checksums of the final stripped binaries +%define __spec_install_post \ + %{?__debug_package:%{__debug_install_post}} \ + %{__arch_install_post} \ + %{__os_install_post} \ + fipshmac -d %{buildroot}%{_libdir}/fipscheck %{buildroot}%{_libexecdir}/ipsec/pluto \ +%{nil} + +%install +make \ + DESTDIR=%{buildroot} \ + %{libreswan_config} \ + install +FS=$(pwd) +rm -rf %{buildroot}/usr/share/doc/libreswan + +install -d -m 0755 %{buildroot}%{_rundir}/pluto +# used when setting --perpeerlog without --perpeerlogbase +install -d -m 0700 %{buildroot}%{_localstatedir}/log/pluto/peer +install -d %{buildroot}%{_sbindir} + +install -d %{buildroot}%{_sysconfdir}/sysctl.d +install -m 0644 packaging/fedora/libreswan-sysctl.conf \ + %{buildroot}%{_sysconfdir}/sysctl.d/50-libreswan.conf + +mkdir -p %{buildroot}%{_libdir}/fipscheck + +echo "include %{_sysconfdir}/ipsec.d/*.secrets" \ + > %{buildroot}%{_sysconfdir}/ipsec.secrets +rm -fr %{buildroot}%{_sysconfdir}/rc.d/rc* +# remove testing binaries +rm -fr %{buildroot}%{_libexecdir}/ipsec/*check + +%if 0%{with_cavstests} +%check +# There is an elaborate upstream testing infrastructure which we do not +# run here - it takes hours and uses kvm +# We only run the CAVS tests. +cp %{SOURCE1} %{SOURCE2} %{SOURCE3} . +bunzip2 *.fax.bz2 + +: starting CAVS test for IKEv2 +%{buildroot}%{_libexecdir}/ipsec/cavp -v2 ikev2.fax | \ + diff -u ikev2.fax - > /dev/null +: starting CAVS test for IKEv1 RSASIG +%{buildroot}%{_libexecdir}/ipsec/cavp -v1dsa ikev1_dsa.fax | \ + diff -u ikev1_dsa.fax - > /dev/null +: starting CAVS test for IKEv1 PSK +%{buildroot}%{_libexecdir}/ipsec/cavp -v1psk ikev1_psk.fax | \ + diff -u ikev1_psk.fax - > /dev/null +: CAVS tests passed + +# Some of these tests will show ERROR for negative testing - it will exit on real errors +%{buildroot}%{_libexecdir}/ipsec/algparse -tp || { echo prooposal test failed; exit 1; } +%{buildroot}%{_libexecdir}/ipsec/algparse -ta || { echo algorithm test failed; exit 1; } +: Algorithm parser tests passed + +# self test for pluto daemon - this also shows which algorithms it allows in FIPS mode +tmpdir=$(mktemp -d /tmp/libreswan-XXXXX) +certutil -N -d sql:$tmpdir --empty-password +%{buildroot}%{_libexecdir}/ipsec/pluto --selftest --nssdir $tmpdir --rundir $tmpdir +: pluto self-test passed - verify FIPS algorithms allowed is still compliant with NIST + +%endif + +%post +%systemd_post ipsec.service + +%preun +%systemd_preun ipsec.service + +%postun +%systemd_postun_with_restart ipsec.service + +%files +%doc CHANGES COPYING CREDITS README* LICENSE +%doc docs/*.* docs/examples +%attr(0644,root,root) %config(noreplace) %{_sysconfdir}/ipsec.conf +%attr(0600,root,root) %config(noreplace) %{_sysconfdir}/ipsec.secrets +%attr(0700,root,root) %dir %{_sysconfdir}/ipsec.d +%attr(0700,root,root) %dir %{_sysconfdir}/ipsec.d/policies +%attr(0644,root,root) %config(noreplace) %{_sysconfdir}/ipsec.d/policies/* +%attr(0644,root,root) %config(noreplace) %{_sysconfdir}/sysctl.d/50-libreswan.conf +%attr(0700,root,root) %dir %{_localstatedir}/log/pluto +%attr(0700,root,root) %dir %{_localstatedir}/log/pluto/peer +%attr(0755,root,root) %dir %{_rundir}/pluto +%attr(0644,root,root) %{_tmpfilesdir}/libreswan.conf +%attr(0644,root,root) %{_unitdir}/ipsec.service +%attr(0644,root,root) %config(noreplace) %{_sysconfdir}/pam.d/pluto +%{_sbindir}/ipsec +%{_libexecdir}/ipsec +%attr(0644,root,root) %doc %{_mandir}/*/* +%{_libdir}/fipscheck/pluto.hmac + +%changelog +* Tue Aug 13 2019 Paul Wouters - 3.29-6 +- Resolves: rhbz#1714331 support NSS based IKE KDF's [require updated nss for rhbz 1738689, memleak fix] + +* Thu Aug 08 2019 Paul Wouters - 3.29-5 +- Resolves: rhbz#1714331 support NSS based IKE KDF's so libreswan does not need FIPS certification + +* Thu Aug 01 2019 Paul Wouters - 3.29-4 +- Resolves: rhbz#1699318 'ipsec show' has python3 invalid syntax + +* Thu Jul 04 2019 Paul Wouters - 3.29-3 +- Resolves: rhbz#1725205 XFRM policy for OE/32 peer is deleted when shunts for previous half-open state expire + +* Thu Jun 27 2019 Paul Wouters - 3.29-2 +- Resolves: rhbz#1723957 libreswan is missing linux audit calls for failed IKE SAs and failed IPsec SAs required for Common Criteria + +* Mon Jun 10 2019 Paul Wouters - 3.29-1 +- Resolves: rhbz#1712555 libreswan rebase to 3.29 + +* Tue May 28 2019 Paul Wouters - 3.28-2 +- Resolves: rhbz#1713734: barf: shell syntax error in barf diagnostic tool + +* Tue May 21 2019 Paul Wouters - 3.28-1 +- Resolves: rhbz#1712555 libreswan rebase to 3.28 +- Resolves: rhbz#1683706 Libreswan shows incorrect error messages +- Resolves: rhbz#1706180 Remove last usage of old (unused) PF_KEY API +- Resolves: rhbz#1677045 Opportunistic IPsec instances of /32 groups or auto=start that receive delete won't restart +- Resolves: rhbz#1686990 IKEv1 traffic interruption when responder deletes SAs 60 seconds before EVENT_SA_REPLACE +- Resolves: rhbz#1608353 /usr/sbin/ipsec part of the libreswan packages still invokes commands that were deprecated a decade ago +- Resolves: rhbz#1699318 'ipsec show' has python3 invalid syntax +- Resolves: rhbz#1679394 libreswan using NSS IPsec profiles regresses when critical flags are set causing validation failure + +* Thu Feb 21 2019 Paul Wouters - 3.27-9 +- Resolves: rhbz#1648776 limit connections to be ikev1only or ikev2only and make ikev2only the default [man page update] + +* Fri Feb 15 2019 Paul Wouters - 3.27-8 +- Resolves: rhbz#1664101 system wide crypto policies causing IKE_INIT packet fragmentation + +* Tue Feb 05 2019 Paul Wouters - 3.27-7 +- Resolves: rhbz#1671793 proessing ISAKMP_NEXT_D with additional payloads causes dangling pointer to deleted state + +* Fri Feb 01 2019 Paul Wouters - 3.27-6 +- Resolves: rhbz#1668342 SELinux prevents libreswan from using some outbound ports causing DNS resolution failures at connection at load time + +* Thu Jan 10 2019 Paul Wouters - 3.27-5 +- Resolves: rhbz#1664522 libreswan 3.25 in FIPS mode is incorrectly rejecting X.509 public keys that are >= 3072 bits + +* Mon Dec 10 2018 Paul Wouters - 3.27-4 +- Resolves: rhbz#1657846 libreswan no longer needs to provide openswan in rhel8 +- Resolves: rhbz#1643388 libreswan: Unable to verify certificate with non-empty Extended Key Usage which does not include serverAuth or clientAuth +- Resolves: rhbz#1657854 remove userland support for deprecated KLIPS IPsec stack support + +* Sun Dec 09 2018 Paul Wouters - 3.27-3 +- Resolves: rhbz#1648776 limit connections to be ikev1only or ikev2only and make ikev2only the default + +* Thu Nov 08 2018 Paul Wouters - 3.27-2 +- Resolves: rhbz#1645137 Libreswan segfaults when it loads configuration file with more then 5 connections + +* Mon Oct 08 2018 Paul Wouters - 3.27-1 +- Resolves: rhbz#1566574 Rebase to libreswan 3.27 + +* Mon Sep 17 2018 Paul Wouters - 3.26-1 +- Resolves: rhbz#1566574 Rebase to libreswan 3.26 +- Resolves: rhbz#1527037 libreswan IPSEC implementation: should follow the policies of system-wide crypto policy +- Resolves: rhbz#1375779 [IKEv2 Conformance] Test IKEv2.EN.R.1.1.6.7: Sending INVALID_KE_PAYLOAD failed +- Resolves: rhbz#1085758 [TAHI][IKEv2] IKEv2.EN.I.1.2.1.1: Can't observe CREATE_CHILD_SA request for rekey +- Resolves: rhbz#1053048 [TAHI][IKEv2] IKEv2.EN.I.1.2.4.1-7: libreswan doesn't sent CREATE_CHILD_SA after IKE_SA Lifetime timeout + +* Mon Aug 13 2018 Paul Wouters - 3.25-4 +- Resolves: rhbz#1590823 libreswan: Use Python 3 in RHEL 8 + +* Wed Aug 01 2018 Charalampos Stratakis - 3.25-3.1 +- Rebuild for platform-python + +* Mon Jul 09 2018 Paul Wouters - 3.25-3 +- Cleanup shebangs for python3 +- Use the same options via macro for make programs and make install +- Remove old ifdefs +- Sync up patches to new upstream version +- Add Requires: for unbound-libs >= 1.6.6 +- Enable crypto-policies support +- Make rundir world readable for easier permission granting for socket + +* Tue Jun 26 2018 Charalampos Stratakis - 3.23-2.2 +- Make python shebangs point to python3 + +* Fri Jun 22 2018 Troy Dawson - 3.23-2.1 +- Fix python shebangs (#1580773) + +* Mon Feb 19 2018 Paul Wouters - 3.23-2 +- Support crypto-policies package +- Pull in some patches from upstream and IANA registry updates +- gcc7 format-truncate fixes and workarounds + +* Wed Feb 07 2018 Fedora Release Engineering - 3.23-1.1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild + +* Thu Jan 25 2018 Paul Wouters - 3.23-1 +- Updated to 3.23 - support for MOBIKE, PPK, CMAC, nic offload and performance improvements + +* Sat Jan 20 2018 Björn Esser - 3.22-1.1 +- Rebuilt for switch to libxcrypt + +* Mon Oct 23 2017 Paul Wouters - 3.22-1 +- Updated to 3.22 - many bugfixes, and unbound ipsecmod support + +* Wed Aug 9 2017 Paul Wouters - 3.21-1 +- Updated to 3.21 + +* Thu Aug 03 2017 Fedora Release Engineering - 3.20-1.2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild + +* Wed Jul 26 2017 Fedora Release Engineering - 3.20-1.1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild + +* Tue Mar 14 2017 Paul Wouters - 3.20-1 +- Updated to 3.20 + +* Fri Mar 03 2017 Paul Wouters - 3.20-0.1.dr4 +- Update to 3.20dr4 to test mozbz#1336487 export CERT_CompareAVA + +* Fri Feb 10 2017 Fedora Release Engineering - 3.19-1.1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild + +* Fri Feb 03 2017 Paul Wouters - 3.19-2 +- Resolves: rhbz#1392191 libreswan: crash when OSX client connects +- Improved uniqueid and session replacing support +- Test Buffer warning fix on size_t +- Re-introduce --configdir for backwards compatibility + +* Sun Jan 15 2017 Paul Wouters - 3.19-1 +- Updated to 3.19 (see download.libreswan.org/CHANGES) + +* Mon Dec 19 2016 Miro Hrončok - 3.18-1.1 +- Rebuild for Python 3.6 + +* Fri Jul 29 2016 Paul Wouters - 3.18-1 +- Updated to 3.18 for CVE-2016-5391 rhbz#1361164 and VTI support +- Remove support for /etc/sysconfig/pluto (use native systemd instead) + +* Thu May 05 2016 Paul Wouters - 3.17-2 +- Resolves: rhbz#1324956 prelink is gone, /etc/prelink.conf.d/* is no longer used + +* Thu Apr 07 2016 Paul Wouters - 3.17-1 +- Updated to 3.17 for CVE-2016-3071 +- Disable LIBCAP_NG as it prevents unbound-control from working properly +- Temporarilly disable WERROR due to a few minor known issues + +* Thu Feb 04 2016 Fedora Release Engineering - 3.16-1.1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild + +* Fri Dec 18 2015 Paul Wouters - 3.16-1 +- Updated to 3.16 (see https://download.libreswan.org/CHANGES) + +* Tue Aug 11 2015 Paul Wouters - 3.15-1 +- Updated to 3.15 (see http://download.libreswan.org/CHANGES) +- Resolves: rhbz#CVE-2015-3240 IKE daemon restart when receiving a bad DH gx +- NSS database creation moved from spec file to service file +- Run CAVS tests on package build +- Added BuildRequire systemd-units and xmlto +- Bumped minimum required nss to 3.16.1 +- Install tmpfiles +- Install sysctl file +- Update doc files to include + +* Mon Jul 13 2015 Paul Wouters - 3.13-2 +- Resolves: rhbz#1238967 Switch libreswan to use python3 + +* Wed Jun 17 2015 Fedora Release Engineering - 3.13-1.1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild + +* Mon Jun 01 2015 Paul Wouters - 3.13-1 +- Updated to 3.13 for CVE-2015-3204 + +* Fri Nov 07 2014 Paul Wouters - 3.12-1 +- Updated to 3.12 Various IKEv2 fixes + +* Wed Oct 22 2014 Paul Wouters - 3.11-1 +- Updated to 3.11 (many fixes, including startup fixes) +- Resolves: rhbz#1144941 libreswan 3.10 upgrade breaks old ipsec.secrets configs +- Resolves: rhbz#1147072 ikev1 aggr mode connection fails after libreswan upgrade +- Resolves: rhbz#1144831 Libreswan appears to start with systemd before all the NICs are up and running + +* Tue Sep 09 2014 Paul Wouters - 3.10-3 +- Fix some coverity issues, auto=route on bootup and snprintf on 32bit machines + +* Mon Sep 01 2014 Paul Wouters - 3.10-1 +- Updated to 3.10, major bugfix release, new xauth status options + +* Sun Aug 17 2014 Fedora Release Engineering - 3.9-1.1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild + +* Thu Jul 10 2014 Paul Wouters - 3.9-1 +- Updated to 3.9. IKEv2 enhancements, ESP/IKE algo enhancements +- Mark libreswan-fips.conf as config file +- attr modifier for man pages no longer needed +- BUGS file no longer exists upstream + +* Sat Jun 07 2014 Fedora Release Engineering - 3.8-1.1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild + +* Sat Jan 18 2014 Paul Wouters - 3.8-1 +- Updated to 3.8, fixes rhbz#CVE-2013-6467 (rhbz#1054102) + +* Wed Dec 11 2013 Paul Wouters - 3.7-1 +- Updated to 3.7, fixes CVE-2013-4564 +- Fixes creating a bogus NSS db on startup (rhbz#1005410) + +* Thu Oct 31 2013 Paul Wouters - 3.6-1 +- Updated to 3.6 (IKEv2, MODECFG, Cisco interop fixes) +- Generate empty NSS db if none exists + +* Mon Aug 19 2013 Paul Wouters - 3.5-3 +- Add a Provides: for openswan-doc + +* Sat Aug 03 2013 Fedora Release Engineering - 3.5-1.1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_20_Mass_Rebuild + +* Mon Jul 15 2013 Paul Wouters - 3.5-2 +- Added interop patch for (some?) Cisco VPN clients sending 16 zero + bytes of extraneous IKE data +- Removed fipscheck_version + +* Sat Jul 13 2013 Paul Wouters - 3.5-1 +- Updated to 3.5 + +* Thu Jun 06 2013 Paul Wouters - 3.4-1 +- Updated to 3.4, which only contains style changes to kernel coding style +- IN MEMORIAM: June 3rd, 2013 Hugh Daniel + +* Mon May 13 2013 Paul Wouters - 3.3-1 +- Updated to 3.3, which resolves CVE-2013-2052 + +* Sat Apr 13 2013 Paul Wouters - 3.2-1 +- Initial package for Fedora