From f352430f829afdaad274ef3f6469ebe6afadcd24 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Thu, 1 Aug 2019 17:28:20 -0400 Subject: [PATCH] import libreswan-3.29-1.el8 --- .gitignore | 4 + .libreswan.metadata | 4 + ...n-3.28-maintain-different-v1v2-split.patch | 68 + ...ibreswan-3.29-CVE-2019-10155-testing.patch | 1830 +++++++++++++++++ SPECS/libreswan.spec | 444 ++++ 5 files changed, 2350 insertions(+) create mode 100644 .gitignore create mode 100644 .libreswan.metadata create mode 100644 SOURCES/libreswan-3.28-maintain-different-v1v2-split.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.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-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..d98bb76 --- /dev/null +++ b/SPECS/libreswan.spec @@ -0,0 +1,444 @@ +%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 \\\ +%{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.}1%{?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 + +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.39.0-1.4 +Requires: nss >= 3.39.0-1.4 +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} +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 + +%patch1 -p1 +%patch2 -p1 + +%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 +* 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