libreswan/SOURCES/libreswan-3.29-CVE-2019-10155-testing.patch
2021-09-09 20:51:31 +00:00

1831 lines
57 KiB
Diff

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 <cagney@gnu.org>
+ * 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 -> <number> */
};
+/*
+ * 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 <cagney@gnu.org>
* Copyright (C) 2019-2019 Paul Wouters <pwouters@redhat.com>
@@ -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 | <rest>) */
+ .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 | <rest>) */
+ .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 <https://www.gnu.org/licenses/gpl2.txt>.
+ *
+ * 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 <https://www.gnu.org/licenses/gpl2.txt>.
+ *
+ * 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 <stdint.h>
+#include <stdbool.h>
+
+#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(&notify_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 <blapit.h>
@@ -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