diff -Naur libreswan-3.27-orig/include/alg_byname.h libreswan-3.27/include/alg_byname.h
--- libreswan-3.27-orig/include/alg_byname.h 2018-10-07 22:52:09.000000000 -0400
+++ libreswan-3.27/include/alg_byname.h 2019-02-15 16:32:28.971835267 -0500
@@ -30,26 +30,26 @@
* messages better align with the input files.
*/
-bool alg_byname_ok(const struct proposal_parser *parser,
+bool alg_byname_ok(struct proposal_parser *parser,
const struct ike_alg *alg, shunk_t print_name);
/*
* Helper functions to implement most of the lookup.
*/
-const struct ike_alg *encrypt_alg_byname(const struct proposal_parser *parser,
+const struct ike_alg *encrypt_alg_byname(struct proposal_parser *parser,
shunk_t name, size_t key_bit_length,
shunk_t print_name);
-const struct ike_alg *prf_alg_byname(const struct proposal_parser *parser,
+const struct ike_alg *prf_alg_byname(struct proposal_parser *parser,
shunk_t name, size_t key_bit_length,
shunk_t print_name);
-const struct ike_alg *integ_alg_byname(const struct proposal_parser *parser,
+const struct ike_alg *integ_alg_byname(struct proposal_parser *parser,
shunk_t name, size_t key_bit_length,
shunk_t print_name);
-const struct ike_alg *dh_alg_byname(const struct proposal_parser *parser,
+const struct ike_alg *dh_alg_byname(struct proposal_parser *parser,
shunk_t name, size_t key_bit_length,
shunk_t print_name);
diff -Naur libreswan-3.27-orig/include/alg_info.h libreswan-3.27/include/alg_info.h
--- libreswan-3.27-orig/include/alg_info.h 2018-10-07 22:52:09.000000000 -0400
+++ libreswan-3.27/include/alg_info.h 1969-12-31 19:00:00.000000000 -0500
@@ -1,245 +0,0 @@
-/* Algorithm info parsing and creation functions
- *
- * Author: JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>
- * Copyright (C) 2007 Michael Richardson <mcr@xelerance.com>
- * Copyright (C) 2012-2013 Paul Wouters <paul@libreswan.org>
- * Copyright (C) 2013 D. Hugh Redelmeier <hugh@mimosa.com>
- * Copyright (C) 2013 Paul Wouters <pwouters@redhat.com>
- * Copyright (C) 2015-2017 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 ALG_INFO_H
-#define ALG_INFO_H
-
-#include "lswcdefs.h"
-#include "constants.h"
-#include "ike_alg.h"
-#include "shunk.h"
-
-struct alg_info;
-struct proposal_protocol;
-struct proposal_info;
-struct proposal_policy;
-struct proposal_parser;
-
-typedef const struct ike_alg *(alg_byname_fn)(const struct proposal_parser *parser,
- shunk_t name, size_t key_bit_length,
- shunk_t print_name);
-
-/*
- * Parameters to tune the parser.
- */
-
-struct proposal_policy {
- bool ikev1;
- bool ikev2;
- bool pfs; /* For CHILD SA, use DH from IKE SA */
- /*
- * According to current policy, is the algorithm ok
- * (supported)? If it isn't return FALSE.
- *
- * For instance, an IKE algorithm requires in-process support;
- * while an ESP/AH algorithm requires kernel support.
- */
- bool (*alg_is_ok)(const struct ike_alg *alg);
- /*
- * Print a warning. Signature needs to match libreswan_log.
- */
- int (*warning)(const char *fmt, ...) PRINTF_LIKE(1);
-};
-
-/*
- * Defaults to fill in.
- */
-
-struct proposal_defaults {
- const struct ike_alg **dh;
- const struct ike_alg **prf;
- const struct ike_alg **integ;
- const struct ike_alg **encrypt;
-};
-
-/*
- * Parameters to set the parser's basic behaviour - ESP/AH/IKE.
- */
-
-struct proposal_protocol {
- const char *name;
- enum ike_alg_key ikev1_alg_id;
-
- /*
- * Lists of defaults.
- */
- const struct proposal_defaults *ikev1_defaults;
- const struct proposal_defaults *ikev2_defaults;
-
- /*
- * Is the proposal OK?
- *
- * This is the final check, if this succeeds then the proposal
- * is added.
- */
- bool (*proposal_ok)(const struct proposal_parser *parser,
- const struct proposal_info *proposal);
-
- /*
- * XXX: Is the proto-id needed? Parser should be protocol
- * agnostic.
- */
- unsigned protoid;
-
- /*
- * This lookup functions must set err and return null if NAME
- * isn't valid.
- */
- alg_byname_fn *encrypt_alg_byname;
- alg_byname_fn *prf_alg_byname;
- alg_byname_fn *integ_alg_byname;
- alg_byname_fn *dh_alg_byname;
-};
-
-/*
- * Everything combined.
- */
-struct proposal_parser {
- const struct proposal_protocol *protocol;
- const struct proposal_param *param;
- const struct proposal_policy *policy;
- char *err_buf;
- size_t err_buf_len;
-};
-
-/*
- * A proposal as decoded by the parser.
- */
-
-struct proposal_info {
- /*
- * The encryption algorithm and key length.
- *
- * Because struct encrypt_desc still specifies multiple key
- * lengths, ENCKEYLEN is still required.
- */
- const struct encrypt_desc *encrypt;
- size_t enckeylen; /* keylength for ESP transform (bits) */
- /*
- * The integrity and PRF algorithms.
- */
- const struct prf_desc *prf;
- const struct integ_desc *integ;
- /*
- * PFS/DH negotiation.
- */
- const struct oakley_group_desc *dh;
- /*
- * Which protocol is this proposal intended for?
- */
- const struct proposal_protocol *protocol;
-};
-
-/* common prefix of struct alg_info_esp and struct alg_info_ike */
-struct alg_info {
- int alg_info_cnt;
- int ref_cnt;
- struct proposal_info proposals[128];
-};
-
-struct alg_info_esp {
- struct alg_info ai; /* common prefix */
-};
-
-struct alg_info_ike {
- struct alg_info ai; /* common prefix */
-};
-
-extern void alg_info_free(struct alg_info *alg_info);
-extern void alg_info_addref(struct alg_info *alg_info);
-extern void alg_info_delref(struct alg_info *alg_info);
-
-extern struct alg_info_ike *alg_info_ike_create_from_str(const struct proposal_policy *policy,
- const char *alg_str,
- char *err_buf, size_t err_buf_len);
-
-extern struct alg_info_esp *alg_info_esp_create_from_str(const struct proposal_policy *policy,
- const char *alg_str,
- char *err_buf, size_t err_buf_len);
-
-extern struct alg_info_esp *alg_info_ah_create_from_str(const struct proposal_policy *policy,
- const char *alg_str,
- char *err_buf, size_t err_buf_len);
-
-size_t lswlog_proposal_info(struct lswlog *log, const struct proposal_info *proposal);
-size_t lswlog_alg_info(struct lswlog *log, const struct alg_info *alg_info);
-
-/*
- * Iterate through the elements of an ESP or IKE table.
- *
- * Use __typeof__ instead of const to get around ALG_INFO some times
- * being const and sometimes not.
- *
- * XXX: yes, they are the same!
- */
-
-#define FOR_EACH_PROPOSAL_INFO(ALG_INFO, PROPOSAL_INFO) \
- for (__typeof__((ALG_INFO)->proposals[0]) *(PROPOSAL_INFO) = (ALG_INFO)->proposals; \
- (PROPOSAL_INFO) < (ALG_INFO)->proposals + (ALG_INFO)->alg_info_cnt; \
- (PROPOSAL_INFO)++)
-
-#define FOR_EACH_ESP_INFO(ALG_INFO, ESP_INFO) \
- FOR_EACH_PROPOSAL_INFO(&((ALG_INFO)->ai), ESP_INFO)
-
-#define FOR_EACH_IKE_INFO(ALG_INFO, IKE_INFO) \
- FOR_EACH_PROPOSAL_INFO(&((ALG_INFO)->ai), IKE_INFO)
-
-/*
- * Error indicated by err_buf[0] != '\0'.
- *
- * POLICY should be used to guard algorithm supported checks. For
- * instance: if POLICY=IKEV1, then IKEv1 support is required (IKEv2 is
- * don't care); and if POLICY=IKEV1|IKEV2, then both IKEv1 and IKEv2
- * support is required.
- *
- * Parsing with POLICY=IKEV1, but then proposing the result using
- * IKEv2 is a program error. The IKEv2 should complain loudly and,
- * we hope, not crash.
- *
- * Parsing with POLICY='0' is allowed. It will accept the algorithms
- * unconditionally (spi.c seems to need this).
- */
-
-struct proposal_parser proposal_parser(const struct proposal_policy *policy,
- const struct proposal_protocol *protocol,
- char *err_buf, size_t err_buf_len);
-
-bool alg_info_parse_str(const struct proposal_parser *parser,
- struct alg_info *alg_info,
- shunk_t alg_str);
-
-/*
- * Check that encrypt==AEAD and/or integ==none don't contradict.
- */
-bool proposal_aead_none_ok(const struct proposal_parser *parser,
- const struct proposal_info *proposal);
-
-bool alg_info_pfs_vs_dh_check(const struct proposal_parser *parser,
- struct alg_info_esp *aie);
-
-#if 0
-/* return true if it really is an error (when impaired return false) */
-bool proposal_error(const struct proposal_parser *parser,
- const char *message, ...) PRINTF_LIKE(2);
-#endif
-
-bool impair_proposal_errors(const struct proposal_parser *parser);
-
-#endif /* ALG_INFO_H */
diff -Naur libreswan-3.27-orig/include/ike_alg.h libreswan-3.27/include/ike_alg.h
--- libreswan-3.27-orig/include/ike_alg.h 2018-10-07 22:52:09.000000000 -0400
+++ libreswan-3.27/include/ike_alg.h 2019-02-15 16:32:28.972835277 -0500
@@ -252,7 +252,7 @@
* Easier to just require that this contain everything then
* poke around in multiple places.
*/
- const char *names[5];
+ const char *names[6];
/*
* See above.
*
diff -Naur libreswan-3.27-orig/include/lswlog.h libreswan-3.27/include/lswlog.h
--- libreswan-3.27-orig/include/lswlog.h 2018-10-07 22:52:09.000000000 -0400
+++ libreswan-3.27/include/lswlog.h 2019-02-15 16:32:28.973835286 -0500
@@ -577,7 +577,7 @@
#define PEXPECT_LOG(FMT, ...) \
libreswan_pexpect_log(__func__, \
PASSERT_BASENAME, __LINE__, \
- FMT, __VA_ARGS__)
+ FMT,##__VA_ARGS__)
/*
diff -Naur libreswan-3.27-orig/include/names_constant.h libreswan-3.27/include/names_constant.h
--- libreswan-3.27-orig/include/names_constant.h 2018-10-07 22:52:09.000000000 -0400
+++ libreswan-3.27/include/names_constant.h 2019-02-15 16:32:28.973835286 -0500
@@ -41,6 +41,8 @@
extern enum_names auth_alg_names;
extern enum_names oakley_lifetime_names;
+extern enum_names ike_version_names;
+extern enum_names ike_version_liveness_names;
extern enum_names version_names;
extern enum_names doi_names;
extern enum_names ikev1_payload_names;
diff -Naur libreswan-3.27-orig/include/pluto_constants.h libreswan-3.27/include/pluto_constants.h
--- libreswan-3.27-orig/include/pluto_constants.h 2019-02-15 16:31:43.034408076 -0500
+++ libreswan-3.27/include/pluto_constants.h 2019-02-15 16:32:28.974835295 -0500
@@ -28,6 +28,12 @@
# define DEFAULT_DNSSEC_ROOTKEY_FILE "<unused>"
# endif
+enum ike_version {
+ IKEv1 = 1,
+ IKEv2 = 2,
+#define IKE_VERSION_ROOF 3
+};
+
/*
* IETF has no recommendations
* FIPS SP800-77 sayas IKE max is 24h, IPsec max is 8h
diff -Naur libreswan-3.27-orig/include/proposals.h libreswan-3.27/include/proposals.h
--- libreswan-3.27-orig/include/proposals.h 1969-12-31 19:00:00.000000000 -0500
+++ libreswan-3.27/include/proposals.h 2019-02-15 16:32:28.975835304 -0500
@@ -0,0 +1,264 @@
+/* Proposals, for libreswan
+ *
+ * Author: JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>
+ * Copyright (C) 2007 Michael Richardson <mcr@xelerance.com>
+ * Copyright (C) 2012-2013 Paul Wouters <paul@libreswan.org>
+ * Copyright (C) 2013 D. Hugh Redelmeier <hugh@mimosa.com>
+ * Copyright (C) 2013 Paul Wouters <pwouters@redhat.com>
+ * Copyright (C) 2015-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 PROPOSALS_H
+#define PROPOSALS_H
+
+#include "lswcdefs.h"
+#include "constants.h"
+#include "ike_alg.h"
+#include "shunk.h"
+
+struct alg_info;
+struct proposal_protocol;
+struct proposal;
+struct proposals;
+struct proposal_policy;
+struct proposal_parser;
+
+/*
+ * XXX: needs to be merged with IKE_ALG_TYPE.
+ */
+enum proposal_algorithm {
+ PROPOSAL_encrypt,
+ PROPOSAL_prf,
+ PROPOSAL_integ,
+ PROPOSAL_dh,
+ PROPOSAL_ALGORITHM_ROOF,
+};
+
+/*
+ * Everything combined.
+ */
+struct proposal_parser {
+ const struct proposal_protocol *protocol;
+ const struct proposal_param *param;
+ const struct proposal_policy *policy;
+ /* need to eliminate hardwired size */
+ char error[200];
+};
+
+/*
+ * Parameters to tune the parser.
+ */
+
+struct proposal_policy {
+ enum ike_version version;
+ unsigned parser_version;
+ bool pfs; /* For CHILD SA, use DH from IKE SA */
+ bool check_pfs_vs_dh;
+ /*
+ * According to current policy, is the algorithm ok
+ * (supported)? If it isn't return FALSE.
+ *
+ * For instance, an IKE algorithm requires in-process support;
+ * while an ESP/AH algorithm requires kernel support.
+ */
+ bool (*alg_is_ok)(const struct ike_alg *alg);
+ /*
+ * Print a warning. Signature needs to match libreswan_log.
+ */
+ int (*warning)(const char *fmt, ...) PRINTF_LIKE(1);
+};
+
+/*
+ * Defaults the parser uses to fill things in.
+ */
+
+struct proposal_defaults {
+ const struct ike_alg **dh;
+ const struct ike_alg **prf;
+ const struct ike_alg **integ;
+ const struct ike_alg **encrypt;
+};
+
+/*
+ * The protocol - ESP/AH/IKE - the parser is processing.
+ */
+
+typedef const struct ike_alg *(alg_byname_fn)(struct proposal_parser *parser,
+ shunk_t name, size_t key_bit_length,
+ shunk_t print_name);
+
+struct proposal_protocol {
+ const char *name;
+ enum ike_alg_key ikev1_alg_id;
+
+ /*
+ * Lists of defaults for each IKE version.
+ */
+ const struct proposal_defaults *defaults[IKE_VERSION_ROOF];
+
+ /*
+ * Is the proposal OK?
+ *
+ * This is the final check, if this succeeds then the proposal
+ * is added.
+ */
+ bool (*proposal_ok)(struct proposal_parser *parser,
+ const struct proposal *proposal);
+
+ /*
+ * XXX: Is the proto-id needed? Parser should be protocol
+ * agnostic.
+ */
+ unsigned protoid;
+
+ /*
+ * This lookup functions must set err and return null if NAME
+ * isn't valid.
+ */
+ alg_byname_fn *encrypt_alg_byname;
+ alg_byname_fn *prf_alg_byname;
+ alg_byname_fn *integ_alg_byname;
+ alg_byname_fn *dh_alg_byname;
+};
+
+/*
+ * A proposal as decoded by the parser.
+ */
+
+struct algorithm {
+ const struct ike_alg *desc;
+ /*
+ * Because struct encrypt_desc still specifies multiple key
+ * lengths, ENCKEYLEN is still required.
+ */
+ int enckeylen; /* only one! */
+ struct algorithm *next;
+};
+
+/* return counts of encrypt=aead and integ=none */
+bool proposal_encrypt_aead(const struct proposal *proposal);
+bool proposal_encrypt_norm(const struct proposal *proposal);
+bool proposal_integ_none(const struct proposal *proposal);
+
+unsigned nr_proposals(struct proposals *proposals);
+
+extern void proposals_addref(struct proposals **proposals);
+extern void proposals_delref(struct proposals **proposals);
+
+extern struct proposal *alloc_proposal(struct proposal_parser *parser);
+extern void free_proposal(struct proposal **proposal);
+
+void free_algorithms(struct proposal *proposal, enum proposal_algorithm algorithm);
+void append_proposal(struct proposals *proposals, struct proposal **proposal);
+void append_algorithm(struct proposal_parser *parser,
+ struct proposal *proposal, enum proposal_algorithm algorithm,
+ const struct ike_alg *alg, int enckeylen);
+
+struct proposal_parser *alloc_proposal_parser(const struct proposal_policy *policy,
+ const struct proposal_protocol *protocol);
+void free_proposal_parser(struct proposal_parser **parser);
+struct proposal_parser *ike_proposal_parser(const struct proposal_policy *policy);
+struct proposal_parser *esp_proposal_parser(const struct proposal_policy *policy);
+struct proposal_parser *ah_proposal_parser(const struct proposal_policy *policy);
+
+/*
+ * XXX: useful?
+ */
+struct ike_proposals {
+ struct proposals *p;
+};
+
+struct child_proposals {
+ struct proposals *p;
+};
+
+void fmt_proposal(struct lswlog *log,
+ const struct proposal *proposal);
+void fmt_proposals(struct lswlog *log, const struct proposals *proposals);
+
+/*
+ * Iterate through all the proposals and the proposal's algorithms.
+ *
+ * Use __typeof__ instead of const to get around ALG_INFO some times
+ * being const and sometimes not.
+ */
+
+struct proposal *next_proposal(const struct proposals *proposals,
+ struct proposal *last_proposal);
+
+#define FOR_EACH_PROPOSAL(PROPOSALS, PROPOSAL) \
+ for (struct proposal *PROPOSAL = next_proposal(PROPOSALS, NULL); \
+ PROPOSAL != NULL; \
+ PROPOSAL = next_proposal(PROPOSALS, PROPOSAL))
+
+struct algorithm *next_algorithm(const struct proposal *proposal,
+ enum proposal_algorithm algorithm,
+ struct algorithm *last);
+
+#define FOR_EACH_ALGORITHM(PROPOSAL, TYPE, ALGORITHM) \
+ for (struct algorithm *ALGORITHM = next_algorithm(PROPOSAL, PROPOSAL_##TYPE, NULL); \
+ ALGORITHM != NULL; ALGORITHM = next_algorithm(PROPOSAL, PROPOSAL_##TYPE, ALGORITHM))
+
+/*
+ * Error indicated by err_buf[0] != '\0'.
+ *
+ * POLICY should be used to guard algorithm supported checks. For
+ * instance: if POLICY=IKEV1, then IKEv1 support is required (IKEv2 is
+ * don't care); and if POLICY=IKEV1|IKEV2, then both IKEv1 and IKEv2
+ * support is required.
+ *
+ * Parsing with POLICY=IKEV1, but then proposing the result using
+ * IKEv2 is a program error. The IKEv2 should complain loudly and,
+ * we hope, not crash.
+ *
+ * Parsing with POLICY='0' is allowed. It will accept the algorithms
+ * unconditionally (spi.c seems to need this).
+ */
+
+struct proposals *proposals_from_str(struct proposal_parser *parser,
+ const char *str);
+
+bool v1_proposals_parse_str(struct proposal_parser *parser,
+ struct proposals *proposals,
+ shunk_t alg_str);
+bool v2_proposals_parse_str(struct proposal_parser *parser,
+ struct proposals *proposals,
+ shunk_t alg_str);
+
+/*
+ * Check that encrypt==AEAD and/or integ==none don't contradict.
+ */
+bool proposal_aead_none_ok(struct proposal_parser *parser,
+ const struct proposal *proposal);
+
+void proposal_error(struct proposal_parser *parser,
+ const char *message, ...) PRINTF_LIKE(2);
+
+bool impair_proposal_errors(struct proposal_parser *parser);
+
+/*
+ * Convert a generic proposal back into something the IKEv1 code can
+ * digest.
+ */
+struct v1_proposal {
+ int enckeylen;
+ const struct encrypt_desc *encrypt;
+ const struct prf_desc *prf;
+ const struct integ_desc *integ;
+ const struct oakley_group_desc *dh;
+ const struct proposal_protocol *protocol;
+};
+
+struct v1_proposal v1_proposal(const struct proposal *proposal);
+
+#endif /* PROPOSALS_H */
diff -Naur libreswan-3.27-orig/include/shunk.h libreswan-3.27/include/shunk.h
--- libreswan-3.27-orig/include/shunk.h 2018-10-07 22:52:09.000000000 -0400
+++ libreswan-3.27/include/shunk.h 2019-02-15 16:32:28.975835304 -0500
@@ -1,7 +1,6 @@
-/*
- * string fragments, for libreswan
+/* constant string (octet) fragments, for libreswan
*
- * Copyright (C) 2018 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
@@ -21,8 +20,15 @@
#include <stddef.h> /* size_t */
/*
- * shunk_t is a rip of of chunk_t, but with a character pointer. It
- * is intended for string slicing.
+ * Think of shunk_t and shunk_t as opposite solutions to the same
+ * problem - carving up streams of octets:
+ *
+ * shunk_t's buffer is constant making it good for manipulating static
+ * constant data (such as "a string"), chunk_t's is not.
+ *
+ * shunk_t's buffer is of type 'char' (which may or may not be signed)
+ * making it easier to manipulate strings, chunk_t's is uint8_t making
+ * it easier to manipulate raw bytes.
*/
struct shunk {
@@ -32,21 +38,49 @@
typedef struct shunk shunk_t;
-extern const shunk_t empty_shunk;
+/*
+ * Just like for strings, an empty or zero length shunk such as
+ * {.ptr="",.len = 0} should not be confused with the NULL shunk
+ * (i.e., {.ptr=NULL,.len=0}).
+ *
+ * Use 'null_shunk' in initialisers. The only exception is static
+ * initializers - which will get a compiler error - and NULL_SHUNK can
+ * be used.
+ */
+
+#define NULL_SHUNK { .ptr = NULL, .len = 0, }
+extern const shunk_t null_shunk;
shunk_t shunk1(const char *ptr); /* strlen() implied */
shunk_t shunk2(const char *ptr, int len);
/*
- * shunk version of strsep() (which is like strtok())
+ * A shunk version of strsep() (which is like strtok()) - split INPUT
+ * in two using a character from the DELIM set.
+ *
+ * If INPUT contains a character from the DELIM set, return the
+ * characters before the DELIM character as the next TOKEN, and set
+ * INPUT to the sub-string following the DELIM character.
+ *
+ * If INPUT contains no character from the DELIM set, return INPUT as
+ * the next TOKEN (possibly empty), and set INPUT to the null_shunk.
+ *
+ * If INPUT is the null_shunk, return the null_shunk as the next
+ * TOKEN, string remains unchanged (still the null_shunk).
+ *
+ * One way to implement a simple parser is to use TOKEN.ptr==NULL as
+ * an end-of-input indicator:
*
- * Split SHUNK in two using the DELIM set. Return a shunk of the
- * characters up to but not including DELIM (or the entire string if
- * DELIM isn't found. Update SHUNK to be one past DELIM.
+ * shunk_t token = shunk_strsep(&input, ",");
+ * while (token.ptr != NULL) {
+ * ... process token ...
+ * token = shunk_strsep(&input, ",");
+ * }
*
- * XXX: should this return the DELIM?
+ * XXX: Provided INPUT.ptr is non-NULL, INPUT.ptr[-1] is the DELIM
+ * character; should this be made an explict parameter.
*/
-shunk_t shunk_strsep(shunk_t *shunk, const char *delim);
+shunk_t shunk_strsep(shunk_t *input, const char *delim);
/*
* shunk version of string compare functions (or at least libreswan's
diff -Naur libreswan-3.27-orig/lib/libswan/ah_info.c libreswan-3.27/lib/libswan/ah_info.c
--- libreswan-3.27-orig/lib/libswan/ah_info.c 2018-10-07 22:52:09.000000000 -0400
+++ libreswan-3.27/lib/libswan/ah_info.c 2019-02-15 16:50:12.776728076 -0500
@@ -22,50 +22,71 @@
#include "lswalloc.h"
#include "lswlog.h"
-#include "alg_info.h"
+#include "proposals.h"
#include "alg_byname.h"
#include "lswfips.h"
#include "ike_alg.h"
#include "ike_alg_integ.h"
-static bool ah_proposal_ok(const struct proposal_parser *parser,
- const struct proposal_info *proposal)
+static bool ah_proposal_ok(struct proposal_parser *parser,
+ const struct proposal *proposal)
{
- impaired_passert(PROPOSAL_PARSER, proposal->encrypt == NULL);
- impaired_passert(PROPOSAL_PARSER, proposal->prf == NULL);
- impaired_passert(PROPOSAL_PARSER, proposal->integ != NULL);
+ impaired_passert(PROPOSAL_PARSER,
+ next_algorithm(proposal, PROPOSAL_encrypt, NULL) == NULL);
+ impaired_passert(PROPOSAL_PARSER,
+ next_algorithm(proposal, PROPOSAL_prf, NULL) == NULL);
+ impaired_passert(PROPOSAL_PARSER,
+ next_algorithm(proposal, PROPOSAL_integ, NULL) != NULL);
/* ah=null is invalid */
- if (!IMPAIR(ALLOW_NULL_NONE) &&
- proposal->integ == &ike_alg_integ_none) {
- snprintf(parser->err_buf, parser->err_buf_len,
- "AH cannot have 'none' as the integrity algorithm");
- if (!impair_proposal_errors(parser)) {
- return false;
+ if (!IMPAIR(ALLOW_NULL_NONE)) {
+ FOR_EACH_ALGORITHM(proposal, integ, alg) {
+ /* passerts */
+ const struct integ_desc *integ = integ_desc(alg->desc);
+ if (integ == &ike_alg_integ_none) {
+ proposal_error(parser, "AH cannot have 'none' as the integrity algorithm");
+ if (!impair_proposal_errors(parser)) {
+ return false;
+ }
+ }
}
}
return true;
}
-static const struct ike_alg *default_ah_integ[] = {
+static const struct ike_alg *default_v1_ah_integ[] = {
#ifdef USE_SHA1
&ike_alg_integ_sha1.common,
#endif
NULL,
};
-const struct proposal_defaults ah_defaults = {
- .integ = default_ah_integ,
+static const struct ike_alg *default_v2_ah_integ[] = {
+#ifdef USE_SHA2
+ &ike_alg_integ_sha2_512.common,
+ &ike_alg_integ_sha2_256.common,
+#endif
+ NULL,
+};
+
+const struct proposal_defaults v1_ah_defaults = {
+ .integ = default_v1_ah_integ,
+};
+
+const struct proposal_defaults v2_ah_defaults = {
+ .integ = default_v2_ah_integ,
};
const struct proposal_protocol ah_proposal_protocol = {
.name = "AH",
.ikev1_alg_id = IKEv1_ESP_ID,
.protoid = PROTO_IPSEC_AH,
- .ikev1_defaults = &ah_defaults,
- .ikev2_defaults = &ah_defaults,
+ .defaults = {
+ [IKEv1] = &v1_ah_defaults,
+ [IKEv2] = &v2_ah_defaults,
+ },
.proposal_ok = ah_proposal_ok,
.integ_alg_byname = integ_alg_byname,
.dh_alg_byname = dh_alg_byname,
@@ -77,7 +98,7 @@
* parser configuration - encryption isn't allowed.
*
* ??? the only difference between
- * alg_info_ah_create_from_str and alg_info_esp_create_from_str
+ * ah_proposals_create_from_str and alg_info_esp_create_from_str
* is in the second argument to proposal_parser.
*
* XXX: On the other hand, since "struct ike_info" and "struct
@@ -87,33 +108,7 @@
/* This function is tested in testing/algparse/algparse.c */
-struct alg_info_esp *alg_info_ah_create_from_str(const struct proposal_policy *policy,
- const char *alg_str,
- char *err_buf, size_t err_buf_len)
+struct proposal_parser *ah_proposal_parser(const struct proposal_policy *policy)
{
- shunk_t string = shunk1(alg_str);
- const struct proposal_parser parser = proposal_parser(policy,
- &ah_proposal_protocol,
- err_buf, err_buf_len);
-
- /*
- * alg_info storage should be sized dynamically
- * but this may require two passes to know
- * transform count in advance.
- */
- struct alg_info_esp *alg_info_ah = alloc_thing(struct alg_info_esp, "alg_info_ah");
-
- if (!alg_info_parse_str(&parser, &alg_info_ah->ai, string)) {
- passert(err_buf[0] != '\0');
- alg_info_free(&alg_info_ah->ai);
- return NULL;
- }
-
- if (!alg_info_pfs_vs_dh_check(&parser, alg_info_ah)) {
- passert(err_buf[0] != '\0');
- alg_info_free(&alg_info_ah->ai);
- return NULL;
- }
-
- return alg_info_ah;
+ return alloc_proposal_parser(policy, &ah_proposal_protocol);
}
diff -Naur libreswan-3.27-orig/lib/libswan/alg_byname.c libreswan-3.27/lib/libswan/alg_byname.c
--- libreswan-3.27-orig/lib/libswan/alg_byname.c 2018-10-07 22:52:09.000000000 -0400
+++ libreswan-3.27/lib/libswan/alg_byname.c 2019-02-15 16:32:28.976835314 -0500
@@ -17,11 +17,11 @@
#include <stdlib.h>
#include "lswlog.h"
-#include "alg_info.h"
+#include "proposals.h"
#include "alg_byname.h"
#include "ike_alg.h"
-bool alg_byname_ok(const struct proposal_parser *parser,
+bool alg_byname_ok(struct proposal_parser *parser,
const struct ike_alg *alg, shunk_t print_name)
{
const struct proposal_protocol *protocol = parser->protocol;
@@ -30,19 +30,27 @@
* If the connection is IKEv1|IKEv2 then this code will
* exclude anything not supported by both protocols.
*/
- if (policy->ikev1 && alg->id[protocol->ikev1_alg_id] < 0) {
- snprintf(parser->err_buf, parser->err_buf_len,
- "%s %s algorithm '"PRI_SHUNK"' is not supported by IKEv1",
- protocol->name, ike_alg_type_name(alg->algo_type),
- PRI_shunk(print_name));
- return false;
- }
- if (policy->ikev2 && alg->id[IKEv2_ALG_ID] < 0) {
- snprintf(parser->err_buf, parser->err_buf_len,
- "%s %s algorithm '"PRI_SHUNK"' is not supported by IKEv2",
- protocol->name, ike_alg_type_name(alg->algo_type),
- PRI_shunk(print_name));
- return false;
+ switch (policy->version) {
+ case IKEv1:
+ /* IKEv1 has different IDs for ESP/IKE/AH */
+ if (alg->id[protocol->ikev1_alg_id] < 0) {
+ proposal_error(parser, "%s %s algorithm '"PRI_SHUNK"' is not supported by IKEv1",
+ protocol->name, ike_alg_type_name(alg->algo_type),
+ PRI_shunk(print_name));
+ return false;
+ }
+ break;
+ case IKEv2:
+ if (alg->id[IKEv2_ALG_ID] < 0) {
+ proposal_error(parser, "%s %s algorithm '"PRI_SHUNK"' is not supported by IKEv2",
+ protocol->name, ike_alg_type_name(alg->algo_type),
+ PRI_shunk(print_name));
+ return false;
+ }
+ break;
+ default:
+ /* ignore */
+ break;
}
/*
* According to parser policy, is the algorithm "implemented"?
@@ -54,10 +62,9 @@
*/
passert(policy->alg_is_ok != NULL);
if (!policy->alg_is_ok(alg)) {
- snprintf(parser->err_buf, parser->err_buf_len,
- "%s %s algorithm '"PRI_SHUNK"' is not supported",
- protocol->name, ike_alg_type_name(alg->algo_type),
- PRI_shunk(print_name));
+ proposal_error(parser, "%s %s algorithm '"PRI_SHUNK"' is not supported",
+ protocol->name, ike_alg_type_name(alg->algo_type),
+ PRI_shunk(print_name));
return false;
}
/*
@@ -69,16 +76,15 @@
* Since it likely involves a lookup, it is left until last.
*/
if (!ike_alg_is_valid(alg)) {
- snprintf(parser->err_buf, parser->err_buf_len,
- "%s %s algorithm '"PRI_SHUNK"' is not valid",
- protocol->name, ike_alg_type_name(alg->algo_type),
- PRI_shunk(print_name));
+ proposal_error(parser, "%s %s algorithm '"PRI_SHUNK"' is not valid",
+ protocol->name, ike_alg_type_name(alg->algo_type),
+ PRI_shunk(print_name));
return false;
}
return true;
}
-static const struct ike_alg *alg_byname(const struct proposal_parser *parser,
+static const struct ike_alg *alg_byname(struct proposal_parser *parser,
const struct ike_alg_type *type,
shunk_t name, shunk_t print_name)
{
@@ -91,15 +97,14 @@
*/
if (ike_alg_enum_match(type, protocol->ikev1_alg_id, name) >= 0 ||
ike_alg_enum_match(type, IKEv2_ALG_ID, name) >= 0) {
- snprintf(parser->err_buf, parser->err_buf_len,
- "%s %s algorithm '"PRI_SHUNK"' is not supported",
- protocol->name, ike_alg_type_name(type),
- PRI_shunk(print_name));
+ proposal_error(parser, "%s %s algorithm '"PRI_SHUNK"' is not supported",
+ protocol->name, ike_alg_type_name(type),
+ PRI_shunk(print_name));
+
} else {
- snprintf(parser->err_buf, parser->err_buf_len,
- "%s %s algorithm '"PRI_SHUNK"' is not recognized",
- protocol->name, ike_alg_type_name(type),
- PRI_shunk(print_name));
+ proposal_error(parser, "%s %s algorithm '"PRI_SHUNK"' is not recognized",
+ protocol->name, ike_alg_type_name(type),
+ PRI_shunk(print_name));
}
return NULL;
}
@@ -108,14 +113,14 @@
* Does it pass muster?
*/
if (!alg_byname_ok(parser, alg, print_name)) {
- passert(parser->err_buf[0] != '\0');
+ passert(parser->error[0] != '\0');
return NULL;
}
return alg;
}
-const struct ike_alg *encrypt_alg_byname(const struct proposal_parser *parser,
+const struct ike_alg *encrypt_alg_byname(struct proposal_parser *parser,
shunk_t name, size_t key_bit_length,
shunk_t print_name)
{
@@ -127,10 +132,9 @@
const struct encrypt_desc *encrypt = encrypt_desc(alg);
if (!IMPAIR(SEND_KEY_SIZE_CHECK) && key_bit_length > 0) {
if (encrypt->keylen_omitted) {
- snprintf(parser->err_buf, parser->err_buf_len,
- "%s does not take variable key lengths",
- enum_short_name(&ikev2_trans_type_encr_names,
- encrypt->common.id[IKEv2_ALG_ID]));
+ proposal_error(parser, "%s does not take variable key lengths",
+ enum_short_name(&ikev2_trans_type_encr_names,
+ encrypt->common.id[IKEv2_ALG_ID]));
if (!impair_proposal_errors(parser)) {
return NULL;
}
@@ -141,8 +145,7 @@
* should instead generate a real list from
* encrypt.
*/
- snprintf(parser->err_buf, parser->err_buf_len,
- "wrong encryption key length - key size must be 128 (default), 192 or 256");
+ proposal_error(parser, "wrong encryption key length - key size must be 128 (default), 192 or 256");
if (!impair_proposal_errors(parser)) {
return NULL;
}
@@ -151,21 +154,21 @@
return alg;
}
-const struct ike_alg *prf_alg_byname(const struct proposal_parser *parser,
+const struct ike_alg *prf_alg_byname(struct proposal_parser *parser,
shunk_t name, size_t key_bit_length UNUSED,
shunk_t print_name)
{
return alg_byname(parser, IKE_ALG_PRF, name, print_name);
}
-const struct ike_alg *integ_alg_byname(const struct proposal_parser *parser,
+const struct ike_alg *integ_alg_byname(struct proposal_parser *parser,
shunk_t name, size_t key_bit_length UNUSED,
shunk_t print_name)
{
return alg_byname(parser, IKE_ALG_INTEG, name, print_name);
}
-const struct ike_alg *dh_alg_byname(const struct proposal_parser *parser,
+const struct ike_alg *dh_alg_byname(struct proposal_parser *parser,
shunk_t name, size_t key_bit_length UNUSED,
shunk_t print_name)
{
diff -Naur libreswan-3.27-orig/lib/libswan/alg_info.c libreswan-3.27/lib/libswan/alg_info.c
--- libreswan-3.27-orig/lib/libswan/alg_info.c 2018-10-07 22:52:09.000000000 -0400
+++ libreswan-3.27/lib/libswan/alg_info.c 1969-12-31 19:00:00.000000000 -0500
@@ -1,884 +0,0 @@
-/*
- * Algorithm info parsing and creation functions
- * Author: JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>
- *
- * Copyright (C) 2012 Paul Wouters <paul@libreswan.org>
- * Copyright (C) 2015-2018 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 <stdio.h>
-#include <string.h>
-#include <limits.h>
-
-#include "lswlog.h"
-#include "lswalloc.h"
-#include "constants.h"
-#include "alg_info.h"
-#include "ike_alg.h"
-#include "ike_alg_integ.h"
-#include "ike_alg_dh.h"
-#include "alg_byname.h"
-
-/*
- * Add the proposal defaults for the specific algorithm.
- */
-
-typedef struct proposal_info merge_alg_default_t(struct proposal_info proposal,
- const struct ike_alg *default_alg);
-
-static struct proposal_info merge_dh_default(struct proposal_info proposal,
- const struct ike_alg *default_alg)
-{
- proposal.dh = oakley_group_desc(default_alg);
- return proposal;
-}
-
-static struct proposal_info merge_encrypt_default(struct proposal_info proposal,
- const struct ike_alg *default_alg)
-{
- proposal.encrypt = encrypt_desc(default_alg);
- return proposal;
-}
-
-static struct proposal_info merge_prf_default(struct proposal_info proposal,
- const struct ike_alg *default_alg)
-{
- proposal.prf = prf_desc(default_alg);
- return proposal;
-}
-
-static struct proposal_info merge_integ_default(struct proposal_info proposal,
- const struct ike_alg *default_alg)
-{
- proposal.integ = integ_desc(default_alg);
- return proposal;
-}
-
-static bool add_proposal_defaults(const struct proposal_parser *parser,
- const struct proposal_defaults *defaults,
- struct alg_info *alg_info,
- const struct proposal_info *proposal);
-
-static bool add_alg_defaults(const struct proposal_parser *parser,
- const struct proposal_defaults *defaults,
- struct alg_info *alg_info,
- const struct proposal_info *proposal,
- const struct ike_alg_type *type,
- const struct ike_alg **default_algs,
- merge_alg_default_t *merge_alg_default)
-{
- /*
- * Use VALID_ALG to add the valid algorithms into VALID_ALGS.
- */
- for (const struct ike_alg **default_alg = default_algs;
- *default_alg; default_alg++) {
- const struct ike_alg *alg = *default_alg;
- if (!alg_byname_ok(parser, alg,
- shunk1(alg->name))) {
- DBG(DBG_PROPOSAL_PARSER,
- DBG_log("skipping default %s",
- parser->err_buf));
- parser->err_buf[0] = '\0';
- continue;
- }
- /* add it */
- DBG(DBG_PROPOSAL_PARSER,
- DBG_log("adding default %s %s",
- ike_alg_type_name(type),
- alg->name));
- struct proposal_info merged_proposal = merge_alg_default(*proposal,
- *default_alg);
- if (!add_proposal_defaults(parser, defaults,
- alg_info, &merged_proposal)) {
- passert(parser->err_buf[0] != '\0');
- return false;
- }
- }
- return true;
-}
-
-/*
- * Validate the proposal and, suppressing duplicates, add it to the
- * proposal list.
- */
-
-static bool add_proposal(const struct proposal_parser *parser,
- struct alg_info *alg_info,
- const struct proposal_info *proposal)
-{
- /* duplicate? */
- FOR_EACH_PROPOSAL_INFO(alg_info, existing_proposal) {
- /*
- * key length 0 is like a wild-card (it actually means
- * propose default and strongest key lengths) so if
- * either is zero just treat it as a match.
- */
- if (existing_proposal->encrypt == proposal->encrypt &&
- existing_proposal->prf == proposal->prf &&
- existing_proposal->integ == proposal->integ &&
- existing_proposal->dh == proposal->dh &&
- (existing_proposal->enckeylen == proposal->enckeylen ||
- existing_proposal->enckeylen == 0 ||
- proposal->enckeylen == 0)) {
- if (IMPAIR(PROPOSAL_PARSER)) {
- libreswan_log("IMPAIR: including duplicate %s proposal encrypt=%s enckeylen=%zu prf=%s integ=%s dh=%s",
- proposal->protocol->name,
- proposal->encrypt != NULL ? proposal->encrypt->common.name : "n/a",
- proposal->enckeylen,
- proposal->prf != NULL ? proposal->prf->common.name : "n/a",
- proposal->integ != NULL ? proposal->integ->common.name : "n/a",
- proposal->dh != NULL ? proposal->dh->common.name : "n/a");
- } else {
- DBG(DBG_CRYPT,
- DBG_log("discarding duplicate %s proposal encrypt=%s enckeylen=%zu prf=%s integ=%s dh=%s",
- proposal->protocol->name,
- proposal->encrypt != NULL ? proposal->encrypt->common.name : "n/a",
- proposal->enckeylen,
- proposal->prf != NULL ? proposal->prf->common.name : "n/a",
- proposal->integ != NULL ? proposal->integ->common.name : "n/a",
- proposal->dh != NULL ? proposal->dh->common.name : "n/a"));
- return true;
- }
- }
- }
-
- /* Overflow? */
- if ((unsigned)alg_info->alg_info_cnt >= elemsof(alg_info->proposals)) {
- snprintf(parser->err_buf, parser->err_buf_len,
- "more than %zu %s algorithms specified",
- elemsof(alg_info->proposals),
- proposal->protocol->name);
- /* drop it like a rock */
- return false;
- }
-
- /* back end? */
- if (!proposal->protocol->proposal_ok(parser, proposal)) {
- return false;
- }
-
- alg_info->proposals[alg_info->alg_info_cnt++] = *proposal;
- return true;
-}
-
-/*
- * For all the algorithms, when an algorithm is missing (NULL), and
- * there are defaults, add them.
- */
-
-static bool add_proposal_defaults(const struct proposal_parser *parser,
- const struct proposal_defaults *defaults,
- struct alg_info *alg_info,
- const struct proposal_info *proposal)
-{
- /*
- * Note that the order in which things are recursively added -
- * MODP, ENCR, PRF/HASH - affects test results. It determines
- * things like the order of proposals.
- */
- if (proposal->dh == NULL &&
- defaults != NULL && defaults->dh != NULL) {
- return add_alg_defaults(parser, defaults,
- alg_info, proposal,
- &ike_alg_dh, defaults->dh,
- merge_dh_default);
- } else if (proposal->encrypt == NULL &&
- defaults != NULL && defaults->encrypt != NULL) {
- return add_alg_defaults(parser, defaults,
- alg_info, proposal,
- &ike_alg_encrypt, defaults->encrypt,
- merge_encrypt_default);
- } else if (proposal->prf == NULL &&
- defaults != NULL && defaults->prf != NULL) {
- return add_alg_defaults(parser, defaults,
- alg_info, proposal,
- &ike_alg_prf, defaults->prf,
- merge_prf_default);
- } else if (proposal->integ == NULL &&
- proposal->encrypt != NULL &&
- encrypt_desc_is_aead(proposal->encrypt)) {
- /*
- * Since AEAD, integrity is always 'none'.
- */
- struct proposal_info merged_proposal = *proposal;
- merged_proposal.integ = &ike_alg_integ_none;
- return add_proposal_defaults(parser, defaults,
- alg_info, &merged_proposal);
- } else if (proposal->integ == NULL &&
- defaults != NULL && defaults->integ != NULL) {
- return add_alg_defaults(parser, defaults,
- alg_info, proposal,
- &ike_alg_integ, defaults->integ,
- merge_integ_default);
- } else if (proposal->integ == NULL &&
- proposal->prf != NULL &&
- proposal->encrypt != NULL &&
- !encrypt_desc_is_aead(proposal->encrypt)) {
- /*
- * Since non-AEAD, use an integrity algorithm that is
- * implemented using the PRF.
- */
- struct proposal_info merged_proposal = *proposal;
- for (const struct integ_desc **algp = next_integ_desc(NULL);
- algp != NULL; algp = next_integ_desc(algp)) {
- const struct integ_desc *alg = *algp;
- if (alg->prf == proposal->prf) {
- merged_proposal.integ = alg;
- break;
- }
- }
- if (merged_proposal.integ == NULL) {
- snprintf(parser->err_buf, parser->err_buf_len,
- "%s integrity derived from PRF '%s' is not supported",
- proposal->protocol->name,
- proposal->prf->common.name);
- return false;
- }
- return add_proposal_defaults(parser, defaults,
- alg_info, &merged_proposal);
- } else {
- return add_proposal(parser, alg_info, proposal);
- }
-}
-
-static bool merge_default_proposals(const struct proposal_parser *parser,
- struct alg_info *alg_info,
- const struct proposal_info *proposal)
-{
- /*
- * If there's a hint of IKEv1 being enabled then prefer its
- * larger set of defaults.
- *
- * This should increase the odds of both ends interoperating.
- *
- * For instance, the IKEv2 defaults were preferred and one end
- * has ikev2=never then, in aggressive mode, things don't
- * work.
- */
- const struct proposal_defaults *defaults = (parser->policy->ikev1
- ? proposal->protocol->ikev1_defaults
- : proposal->protocol->ikev2_defaults);
- return add_proposal_defaults(parser, defaults,
- alg_info, proposal);
-}
-
-static const struct ike_alg *lookup_byname(const struct proposal_parser *parser,
- alg_byname_fn *alg_byname,
- shunk_t name,
- size_t key_bit_length,
- shunk_t print_name,
- const char *what)
-{
- if (name.len > 0) {
- if (alg_byname != NULL) {
- const struct ike_alg *alg = alg_byname(parser, name, key_bit_length,
- print_name);
- if (alg == NULL) {
- DBG(DBG_PROPOSAL_PARSER,
- DBG_log("%s_byname('"PRI_SHUNK"') failed: %s",
- what, PRI_shunk(name),
- parser->err_buf));
- passert(parser->err_buf[0] != '\0');
- return NULL;
- }
- DBG(DBG_PROPOSAL_PARSER,
- DBG_log("%s_byname('"PRI_SHUNK"') returned '%s'",
- what, PRI_shunk(name), alg->name));
- return alg;
- } else {
- DBG(DBG_PROPOSAL_PARSER,
- DBG_log("ignoring %s '"PRI_SHUNK"'",
- what, PRI_shunk(name)));
- return NULL;
- }
- }
- return NULL;
-}
-
-static int parse_eklen(char *err_buf, size_t err_buf_len,
- shunk_t buf)
-{
- /* convert -<eklen> if present */
- char *end = NULL;
- long eklen = strtol(buf.ptr, &end, 10);
- if (buf.ptr + buf.len != end) {
- snprintf(err_buf, err_buf_len,
- "encryption key length '"PRI_SHUNK"' contains a non-numeric character",
- PRI_shunk(buf));
- return 0;
- }
- if (eklen >= INT_MAX) {
- snprintf(err_buf, err_buf_len,
- "encryption key length '"PRI_SHUNK"' WAY too big",
- PRI_shunk(buf));
- return 0;
- }
- if (eklen == 0) {
- snprintf(err_buf, err_buf_len,
- "encryption key length is zero");
- return 0;
- }
- return eklen;
-}
-
-/*
- * Try to parse any of <ealg>-<ekeylen>, <ealg>_<ekeylen>,
- * <ealg><ekeylen>, or <ealg>. Strings like aes_gcm_16 and
- * aes_gcm_16_256 end up in alg[0], while strings like aes_gcm_16-256
- * end up in alg[0]-alg[1].
- */
-
-struct token {
- char sep;
- shunk_t alg;
-};
-
-static bool parse_encrypt(const struct proposal_parser *parser,
- struct token **tokens,
- struct proposal_info *proposal)
-{
- shunk_t ealg = (*tokens)[0].alg;
- shunk_t eklen = (*tokens)[1].alg;
- if (eklen.len > 0 && isdigit(eklen.ptr[0])) {
- /* assume <ealg>-<eklen> */
- int enckeylen = parse_eklen(parser->err_buf,
- parser->err_buf_len,
- eklen);
- if (enckeylen <= 0) {
- passert(parser->err_buf[0] != '\0');
- return false;
- }
- /* print <alg>-<len> */
- shunk_t print_name = shunk2(ealg.ptr, eklen.ptr + eklen.len - ealg.ptr);
- proposal->enckeylen = enckeylen;
- proposal->encrypt =
- encrypt_desc(lookup_byname(parser,
- encrypt_alg_byname,
- ealg, proposal->enckeylen,
- print_name, "encryption"));
- /* Was <ealg>-<eklen> rejected? */
- if (parser->err_buf[0] != '\0') {
- return false;
- }
- *tokens += 2; /* consume both tokens */
- return true;
- }
- /* try <ealg> */
- shunk_t print_name = ealg;
- proposal->encrypt =
- encrypt_desc(lookup_byname(parser,
- encrypt_alg_byname,
- ealg, proposal->enckeylen,
- print_name, "encryption"));
- if (parser->err_buf[0] != '\0') {
- /*
- * Could it be <ealg><eklen> or <ealg>_<eklen>? Work
- * backwards skipping any digits.
- */
- shunk_t end = shunk2(ealg.ptr + ealg.len, 0);
- while (end.ptr > ealg.ptr && isdigit(end.ptr[-1])) {
- end.ptr--;
- end.len++;
- }
- if (end.len == 0) {
- /*
- * no trailing <eklen> and <ealg> was rejected
- */
- passert(parser->err_buf[0] != '\0');
- return false;
- }
- /* try to convert */
- int enckeylen = parse_eklen(parser->err_buf, parser->err_buf_len, end);
- if (enckeylen <= 0) {
- passert(parser->err_buf[0] != '\0');
- return false;
- }
- proposal->enckeylen = enckeylen;
- /*
- * trim <eklen> from <ealg>; and then trim any
- * trailing '_'
- */
- ealg.len = end.ptr - ealg.ptr;
- if (end.ptr > ealg.ptr && end.ptr[-1] == '_') {
- ealg.len -= 1;
- }
- /* try again */
- parser->err_buf[0] = '\0';
- proposal->encrypt =
- encrypt_desc(lookup_byname(parser,
- encrypt_alg_byname,
- ealg, proposal->enckeylen,
- print_name, "encryption"));
- if (parser->err_buf[0] != '\0') {
- return false;
- }
- }
- *tokens += 1; /* consume one token */
- return true;
-}
-
-static bool parser_alg_info_add(const struct proposal_parser *parser,
- struct token *tokens, struct proposal_info proposal,
- struct alg_info *alg_info)
-{
- LSWDBGP(DBG_PROPOSAL_PARSER, buf) {
- lswlogs(buf, "algs:");
- for (struct token *token = tokens; token->alg.ptr != NULL; token++) {
- lswlogf(buf, " algs[%tu] = '"PRI_SHUNK"'",
- token - tokens, PRI_shunk(token->alg));
- }
- }
-
- bool lookup_encrypt = parser->protocol->encrypt_alg_byname != NULL;
- if (!lookup_encrypt && IMPAIR(PROPOSAL_PARSER)) {
- /* Force lookup, will discard any error. */
- lookup_encrypt = true;
- }
- if (lookup_encrypt && tokens->alg.ptr != NULL && tokens->sep != ';') {
- if (!parse_encrypt(parser, &tokens, &proposal)) {
- if (IMPAIR(PROPOSAL_PARSER)) {
- /* ignore the lookup and stumble on */
- parser->err_buf[0] = '\0';
- } else {
- passert(parser->err_buf[0] != '\0');
- return false;
- }
- }
- }
-
- bool lookup_prf = parser->protocol->prf_alg_byname != NULL;
- if (!lookup_prf && IMPAIR(PROPOSAL_PARSER)) {
- /*
- * Force PRF lookup when the folloing token looks like
- * an INTEG algorithm (i.e., its lookup succeeds).
- * Otherwise something like ah=sha1 gets parsed as
- * ah=[encr]-sha1-[integ]-[dh].
- */
- shunk_t prf = tokens[0].alg;
- shunk_t integ = tokens[1].alg;
- if (prf.ptr != NULL && integ.ptr != NULL) {
- lookup_prf = (lookup_byname(parser, integ_alg_byname,
- integ, 0, integ, "integrity")
- != NULL);
- parser->err_buf[0] = '\0';
- }
- }
- if (lookup_prf && tokens->alg.ptr != NULL && tokens->sep != ';') {
- shunk_t prf = tokens[0].alg;
- proposal.prf = prf_desc(lookup_byname(parser,
- prf_alg_byname,
- prf, 0, prf, "PRF"));
- if (parser->err_buf[0] != '\0') {
- return false;
- }
- tokens += 1; /* consume one arg */
- }
-
- bool lookup_integ = parser->protocol->integ_alg_byname != NULL;
- if (!lookup_integ && IMPAIR(PROPOSAL_PARSER)) {
- /* force things */
- lookup_integ = true;
- }
- if (lookup_integ && tokens->alg.ptr != NULL && tokens->sep != ';') {
- shunk_t integ = tokens[0].alg;
- proposal.integ = integ_desc(lookup_byname(parser,
- integ_alg_byname,
- integ, 0, integ, "integrity"));
- if (parser->err_buf[0] != '\0') {
- if (tokens[1].alg.ptr != NULL) {
- /*
- * This alg should have been
- * integrity, since the next would be
- * DH; error applies.
- */
- passert(parser->err_buf[0] != '\0');
- return false;
- }
- if (tokens[1].alg.ptr == NULL &&
- parser->protocol->prf_alg_byname == NULL) {
- /*
- * Only one arg, integrity is prefered
- * to DH (and no PRF); error applies.
- */
- passert(parser->err_buf[0] != '\0');
- return false;
- }
- /* let DH try */
- parser->err_buf[0] = '\0';
- } else {
- tokens += 1; /* consume one arg */
- }
- }
-
- bool lookup_dh = parser->protocol->dh_alg_byname || IMPAIR(PROPOSAL_PARSER);
- if (lookup_dh && tokens->alg.ptr != NULL) {
- shunk_t dh = tokens[0].alg;
- proposal.dh = oakley_group_desc(lookup_byname(parser,
- dh_alg_byname,
- dh, 0,
- dh, "DH"));
- if (parser->err_buf[0] != '\0') {
- return false;
- }
- tokens += 1; /* consume one arg */
- }
-
- if (tokens->alg.ptr != NULL) {
- snprintf(parser->err_buf, parser->err_buf_len,
- "'"PRI_SHUNK"' unexpected",
- PRI_shunk(tokens[0].alg));
- return false;
- }
-
- if (IMPAIR(PROPOSAL_PARSER)) {
- return add_proposal(parser, alg_info, &proposal);
- } else {
- return merge_default_proposals(parser, alg_info, &proposal);
- }
-}
-
-
-bool alg_info_parse_str(const struct proposal_parser *parser,
- struct alg_info *alg_info,
- shunk_t alg_str)
-{
- DBG(DBG_PROPOSAL_PARSER,
- DBG_log("parsing '"PRI_SHUNK"' for %s",
- PRI_shunk(alg_str), parser->protocol->name));
-
- /* use default if no string */
- if (alg_str.ptr == NULL) {
- const struct proposal_info proposal = {
- .protocol = parser->protocol,
- };
- return merge_default_proposals(parser, alg_info, &proposal);
- }
-
- if (alg_str.len == 0) {
- /* XXX: hack to keep testsuite happy */
- snprintf(parser->err_buf, parser->err_buf_len,
- "String ended with invalid char, just after \"\"");
- return false;
- }
-
- shunk_t prop_ptr = alg_str;
- do {
- /* find the next proposal */
- shunk_t prop = shunk_strsep(&prop_ptr, ",");
- /* parse it */
- struct token tokens[8];
- zero(&tokens);
- struct token *token = tokens;
- char last_sep = '\0';
- shunk_t alg_ptr = prop;
- do {
- if (token + 1 >= tokens+elemsof(tokens)) {
- /* space for NULL? */
- snprintf(parser->err_buf, parser->err_buf_len,
- "proposal too long");
- return false;
- }
- /* find the next alg */
- shunk_t alg = shunk_strsep(&alg_ptr, "-;,");
- *token++ = (struct token) {
- .alg = alg,
- .sep = last_sep,
- };
- last_sep = alg.ptr[alg.len]; /* save separator */
- } while (alg_ptr.len > 0);
- struct proposal_info proposal = {
- .protocol = parser->protocol,
- };
- if (!parser_alg_info_add(parser, tokens, proposal,
- alg_info)) {
- passert(parser->err_buf[0] != '\0');
- return false;
- }
- } while (prop_ptr.len > 0);
- return true;
-}
-
-struct proposal_parser proposal_parser(const struct proposal_policy *policy,
- const struct proposal_protocol *protocol,
- char *err_buf, size_t err_buf_len)
-{
- const struct proposal_parser parser = {
- .policy = policy,
- .protocol = protocol,
- .err_buf = err_buf,
- .err_buf_len = err_buf_len,
- };
- err_buf[0] = '\0';
- return parser;
-}
-
-bool proposal_aead_none_ok(const struct proposal_parser *parser,
- const struct proposal_info *proposal)
-{
- if (IMPAIR(ALLOW_NULL_NONE)) {
- return true;
- }
-
- if (proposal->encrypt != NULL &&
- encrypt_desc_is_aead(proposal->encrypt) &&
- proposal->integ != NULL &&
- proposal->integ != &ike_alg_integ_none) {
- /*
- * For instance, esp=aes_gcm-sha1" is invalid.
- */
- snprintf(parser->err_buf, parser->err_buf_len,
- "AEAD %s encryption algorithm '%s' must have 'none' as the integrity algorithm",
- proposal->protocol->name,
- proposal->encrypt->common.name);
- return false;
- }
-
- if (proposal->encrypt != NULL &&
- !encrypt_desc_is_aead(proposal->encrypt) &&
- proposal->integ != NULL &&
- proposal->integ == &ike_alg_integ_none) {
- /*
- * For instance, esp=aes_cbc-none" is invalid.
- */
- snprintf(parser->err_buf, parser->err_buf_len,
- "non-AEAD %s encryption algorithm '%s' cannot have 'none' as the integrity algorithm",
- proposal->protocol->name,
- proposal->encrypt->common.name);
- return false;
- }
-
- return true;
-}
-
-/*
- * alg_info struct can be shared by several connections instances,
- * handle free() with ref_cnts.
- *
- * Use alg_info_free() if the value returned by *_parse_str() is found
- * to be (semantically) bogus.
- */
-
-void alg_info_free(struct alg_info *alg_info)
-{
- passert(alg_info);
- passert(alg_info->ref_cnt == 0);
- pfree(alg_info);
-}
-
-void alg_info_addref(struct alg_info *alg_info)
-{
- alg_info->ref_cnt++;
-}
-
-void alg_info_delref(struct alg_info *alg_info)
-{
- passert(alg_info->ref_cnt != 0);
- alg_info->ref_cnt--;
- if (alg_info->ref_cnt == 0)
- alg_info_free(alg_info);
-}
-
-size_t lswlog_proposal_info(struct lswlog *log,
- const struct proposal_info *proposal)
-{
- size_t size = 0;
- const char *sep = "";
-
- if (proposal->encrypt != NULL) {
- size += lswlogs(log, sep); sep = "-";
- size += lswlogs(log, proposal->encrypt->common.fqn);
- if (proposal->enckeylen != 0) {
- size += lswlogf(log, "_%zd", proposal->enckeylen);
- }
- } else if (IMPAIR(PROPOSAL_PARSER)) {
- size += lswlogs(log, sep); sep = "-";
- size += lswlogs(log, "[ENCRYPT]");
- }
-
- if (proposal->prf != NULL) {
- size += lswlogs(log, sep); sep = "-";
- size += lswlogs(log, proposal->prf->common.fqn);
- } else if (IMPAIR(PROPOSAL_PARSER)) {
- size += lswlogs(log, sep); sep = "-";
- size += lswlogs(log, "[PRF]");
- }
-
- if (proposal->integ != NULL && proposal->prf == NULL) {
- size += lswlogs(log, sep); sep = "-";
- size += lswlogs(log, proposal->integ->common.fqn);
- } else if (!(proposal->integ == &ike_alg_integ_none &&
- encrypt_desc_is_aead(proposal->encrypt)) &&
- proposal->integ != NULL && proposal->integ->prf != proposal->prf) {
- size += lswlogs(log, sep); sep = "-";
- size += lswlogs(log, proposal->integ->common.fqn);
- } else if (IMPAIR(PROPOSAL_PARSER)) {
- size += lswlogs(log, sep); sep = "-";
- if (proposal->integ != NULL) {
- size += lswlogs(log, proposal->integ->common.fqn);
- } else {
- size += lswlogs(log, "[INTEG]");
- }
- }
-
- if (proposal->dh != NULL) {
- size += lswlogs(log, sep); sep = "-"; /* sep not subsequently used */
- size += lswlogs(log, proposal->dh->common.fqn);
- } else if (IMPAIR(PROPOSAL_PARSER)) {
- size += lswlogs(log, sep); sep = "-"; /* sep not subsequently used */
- size += lswlogs(log, "[DH]");
- }
-
- return size;
-}
-
-size_t lswlog_alg_info(struct lswlog *log, const struct alg_info *alg_info)
-{
- size_t size = 0;
- const char *sep = "";
- FOR_EACH_PROPOSAL_INFO(alg_info, proposal) {
- size += lswlogs(log, sep);
- size += lswlog_proposal_info(log, proposal);
- sep = ", ";
- }
- return size;
-}
-
-/*
- * When PFS=no ignore any DH algorithms, and when PFS=yes reject
- * mixing implict and explicit DH.
- */
-bool alg_info_pfs_vs_dh_check(const struct proposal_parser *parser,
- struct alg_info_esp *aie)
-{
- if (aie->ai.alg_info_cnt <= 0) {
- /* let caller deal with no proposals. */
- return true;
- }
-
- /* scrape the proposals for dh algorithms */
- struct proposal_info *first_null = NULL;
- struct proposal_info *first_dh = NULL;
- struct proposal_info *second_dh = NULL;
- struct proposal_info *first_none = NULL;
- FOR_EACH_ESP_INFO(aie, alg) {
- if (alg->dh == NULL) {
- if (first_null == NULL) {
- first_null = alg;
- }
- } else if (alg->dh == &ike_alg_dh_none) {
- if (first_none == NULL) {
- first_none = alg;
- }
- } else if (first_dh == NULL) {
- first_dh = alg;
- } else if (second_dh == NULL && first_dh->dh != alg->dh) {
- second_dh = alg;
- }
- }
-
- if (first_dh == NULL && first_none == NULL) {
- /* no DH is always ok */
- return true;
- }
-
- /*
- * Try to generate very specific errors first. For instance,
- * given PFS=no esp=aes,aes;dh21, an error stating that dh21
- * is not valid because of PFS is more helpful than an error
- * saying that all or no proposals need PFS.
- */
-
- /*
- * Since PFS=NO overrides any DH, don't silently ignore it.
- * Check this early so that a conflict with PFS=no code gets
- * reported before anything else.
- */
- if (!parser->policy->pfs && (first_dh != NULL || first_none != NULL)) {
- FOR_EACH_ESP_INFO(aie, alg) {
- if (alg->dh == &ike_alg_dh_none) {
- parser->policy->warning("ignoring redundant %s DH algorithm NONE as PFS policy is disabled",
- parser->protocol->name);
- } else if (alg->dh != NULL) {
- parser->policy->warning("ignoring %s DH algorithm %s as PFS policy is disabled",
- parser->protocol->name,
- alg->dh->common.fqn);
- }
- alg->dh = NULL;
- }
- return true;
- }
-
- /*
- * Since at least one proposal included DH, all proposals
- * should. A proposal without DH is an error.
- *
- * (The converse, no proposals including DH was handled right
- * at the start).
- */
- if (first_null != NULL) {
- /* DH was specified */
- snprintf(parser->err_buf, parser->err_buf_len,
- "either all or no %s proposals should specify DH",
- parser->protocol->name);
- if (!impair_proposal_errors(parser)) {
- return false;
- }
- }
-
- /*
- * IKEv1 only allows one DH algorithm.
- */
- if (parser->policy->ikev1) {
- if (first_dh != NULL && second_dh != NULL) {
- snprintf(parser->err_buf, parser->err_buf_len,
- "more than one IKEv1 %s DH algorithm (%s, %s) is not allowed in quick mode",
- parser->protocol->name,
- first_dh->dh->common.fqn,
- second_dh->dh->common.fqn);
- if (!impair_proposal_errors(parser)) {
- return false;
- }
- }
- }
-
- /*
- * IKEv2, only implements one DH algorithm.
- */
- if (parser->policy->ikev2) {
- if (first_dh != NULL && second_dh != NULL) {
- snprintf(parser->err_buf, parser->err_buf_len,
- "more than one IKEv2 %s DH algorithm (%s, %s) requires unimplemented CHILD_SA INVALID_KE",
- parser->protocol->name,
- first_dh->dh->common.fqn,
- second_dh->dh->common.fqn);
- if (!impair_proposal_errors(parser)) {
- return false;
- }
- }
- }
-
- return true;
-}
-
-bool impair_proposal_errors(const struct proposal_parser *parser)
-{
- pexpect(parser->err_buf[0] != '\0');
- if (IMPAIR(PROPOSAL_PARSER)) {
- libreswan_log("IMPAIR: ignoring proposal error: %s",
- parser->err_buf);
- parser->err_buf[0] = '\0';
- return true;
- } else {
- return false;
- }
-}
diff -Naur libreswan-3.27-orig/lib/libswan/esp_info.c libreswan-3.27/lib/libswan/esp_info.c
--- libreswan-3.27-orig/lib/libswan/esp_info.c 2018-10-07 22:52:09.000000000 -0400
+++ libreswan-3.27/lib/libswan/esp_info.c 2019-02-15 16:50:12.776728076 -0500
@@ -22,7 +22,7 @@
#include "lswalloc.h"
#include "lswlog.h"
-#include "alg_info.h"
+#include "proposals.h"
#include "alg_byname.h"
#include "lswfips.h"
@@ -33,8 +33,8 @@
/*
* Add ESP alg info _with_ logic (policy):
*/
-static bool esp_proposal_ok(const struct proposal_parser *parser,
- const struct proposal_info *proposal)
+static bool esp_proposal_ok(struct proposal_parser *parser,
+ const struct proposal *proposal)
{
if (!proposal_aead_none_ok(parser, proposal)) {
if (!impair_proposal_errors(parser)) {
@@ -42,12 +42,19 @@
}
}
- impaired_passert(PROPOSAL_PARSER, proposal->encrypt != NULL);
- impaired_passert(PROPOSAL_PARSER, proposal->prf == NULL);
- impaired_passert(PROPOSAL_PARSER, proposal->integ != NULL);
+ impaired_passert(PROPOSAL_PARSER,
+ next_algorithm(proposal, PROPOSAL_encrypt, NULL) != NULL);
+ impaired_passert(PROPOSAL_PARSER,
+ next_algorithm(proposal, PROPOSAL_prf, NULL) == NULL);
+ impaired_passert(PROPOSAL_PARSER,
+ next_algorithm(proposal, PROPOSAL_integ, NULL) != NULL);
return true;
}
+/*
+ * since esp= must have an encryption algorithm this is normally
+ * ignored.
+ */
static const struct ike_alg *default_esp_encrypt[] = {
#ifdef USE_AES
&ike_alg_encrypt_aes_cbc.common,
@@ -55,24 +62,39 @@
NULL,
};
-static const struct ike_alg *default_esp_integ[] = {
+static const struct ike_alg *default_v1_esp_integ[] = {
#ifdef USE_SHA1
&ike_alg_integ_sha1.common,
#endif
NULL,
};
-static const struct proposal_defaults esp_defaults = {
+static const struct ike_alg *default_v2_esp_integ[] = {
+#ifdef USE_SHA2
+ &ike_alg_integ_sha2_512.common,
+ &ike_alg_integ_sha2_256.common,
+#endif
+ NULL,
+};
+
+static const struct proposal_defaults v1_esp_defaults = {
.encrypt = default_esp_encrypt,
- .integ = default_esp_integ,
+ .integ = default_v1_esp_integ,
+};
+
+static const struct proposal_defaults v2_esp_defaults = {
+ .encrypt = default_esp_encrypt,
+ .integ = default_v2_esp_integ,
};
static const struct proposal_protocol esp_proposal_protocol = {
.name = "ESP",
.ikev1_alg_id = IKEv1_ESP_ID,
.protoid = PROTO_IPSEC_ESP,
- .ikev1_defaults = &esp_defaults,
- .ikev2_defaults = &esp_defaults,
+ .defaults = {
+ [IKEv1] = &v1_esp_defaults,
+ [IKEv2] = &v2_esp_defaults,
+ },
.proposal_ok = esp_proposal_ok,
.encrypt_alg_byname = encrypt_alg_byname,
.integ_alg_byname = integ_alg_byname,
@@ -81,7 +103,7 @@
/*
* ??? the only difference between
- * alg_info_ah_create_from_str and alg_info_esp_create_from_str
+ * alg_info_ah_create_from_str and esp_proposals_create_from_str
* is in the second argument to proposal_parser.
*
* XXX: On the other hand, since "struct ike_info" and "struct
@@ -91,33 +113,7 @@
/* This function is tested in testing/algparse/algparse.c */
-struct alg_info_esp *alg_info_esp_create_from_str(const struct proposal_policy *policy,
- const char *alg_str,
- char *err_buf, size_t err_buf_len)
+struct proposal_parser *esp_proposal_parser(const struct proposal_policy *policy)
{
- shunk_t string = shunk1(alg_str);
- const struct proposal_parser parser = proposal_parser(policy,
- &esp_proposal_protocol,
- err_buf, err_buf_len);
-
- /*
- * alg_info storage should be sized dynamically
- * but this may require two passes to know
- * transform count in advance.
- */
- struct alg_info_esp *alg_info_esp = alloc_thing(struct alg_info_esp,
- "alg_info_esp");
- if (!alg_info_parse_str(&parser, &alg_info_esp->ai, string)) {
- passert(err_buf[0] != '\0');
- alg_info_free(&alg_info_esp->ai);
- return NULL;
- }
-
- if (!alg_info_pfs_vs_dh_check(&parser, alg_info_esp)) {
- passert(err_buf[0] != '\0');
- alg_info_free(&alg_info_esp->ai);
- return NULL;
- }
-
- return alg_info_esp;
+ return alloc_proposal_parser(policy, &esp_proposal_protocol);
}
diff -Naur libreswan-3.27-orig/lib/libswan/ike_alg.c libreswan-3.27/lib/libswan/ike_alg.c
--- libreswan-3.27-orig/lib/libswan/ike_alg.c 2018-10-07 22:52:09.000000000 -0400
+++ libreswan-3.27/lib/libswan/ike_alg.c 2019-02-15 16:32:28.978835332 -0500
@@ -37,7 +37,7 @@
#include "ike_alg.h"
#include "ike_alg_integ.h"
#include "ike_alg_encrypt.h"
-#include "alg_info.h"
+#include "proposals.h"
#include "ike_alg_prf.h"
#include "ike_alg_prf_hmac_ops.h"
#include "ike_alg_prf_nss_ops.h"
@@ -589,7 +589,7 @@
static bool integ_desc_is_ike(const struct ike_alg *alg)
{
const struct integ_desc *integ = integ_desc(alg);
- return integ->prf != NULL;
+ return integ->prf != NULL || integ == &ike_alg_integ_none;
}
static struct algorithm_table integ_algorithms = ALGORITHM_TABLE(integ_descriptors);
diff -Naur libreswan-3.27-orig/lib/libswan/ike_alg_dh.c libreswan-3.27/lib/libswan/ike_alg_dh.c
--- libreswan-3.27-orig/lib/libswan/ike_alg_dh.c 2018-10-07 22:52:09.000000000 -0400
+++ libreswan-3.27/lib/libswan/ike_alg_dh.c 2019-02-15 16:32:28.979835342 -0500
@@ -186,7 +186,7 @@
.algo_type = IKE_ALG_DH,
.name = "DH19",
.fqn = "DH19",
- .names = { "dh19", "ecp_256", },
+ .names = { "dh19", "ecp_256", "ecp256" },
.id = {
[IKEv1_OAKLEY_ID] = OAKLEY_GROUP_ECP_256,
[IKEv1_ESP_ID] = -1,
@@ -205,7 +205,7 @@
.algo_type = IKE_ALG_DH,
.name = "DH20",
.fqn = "DH20",
- .names = { "dh20", "ecp_384", },
+ .names = { "dh20", "ecp_384", "ecp384" },
.id = {
[IKEv1_OAKLEY_ID] = OAKLEY_GROUP_ECP_384,
[IKEv1_ESP_ID] = -1,
@@ -224,7 +224,7 @@
.algo_type = IKE_ALG_DH,
.name = "DH21",
.fqn = "DH21",
- .names = { "dh21", "ecp_521", },
+ .names = { "dh21", "ecp_521", "ecp521" },
.id = {
[IKEv1_OAKLEY_ID] = OAKLEY_GROUP_ECP_521,
[IKEv1_ESP_ID] = -1,
diff -Naur libreswan-3.27-orig/lib/libswan/ike_alg_sha2.c libreswan-3.27/lib/libswan/ike_alg_sha2.c
--- libreswan-3.27-orig/lib/libswan/ike_alg_sha2.c 2018-10-07 22:52:09.000000000 -0400
+++ libreswan-3.27/lib/libswan/ike_alg_sha2.c 2019-02-15 16:32:28.979835342 -0500
@@ -79,7 +79,7 @@
.common = {
.name = "sha2_256",
.fqn = "HMAC_SHA2_256_128",
- .names = { "sha2", "sha256", "sha2_256", "hmac_sha2_256", "hmac_sha2_256_128", },
+ .names = { "sha2", "sha256", "sha2_256", "sha2_256_128", "hmac_sha2_256", "hmac_sha2_256_128", },
.algo_type = IKE_ALG_INTEG,
.id = {
[IKEv1_OAKLEY_ID] = OAKLEY_SHA2_256,
@@ -206,7 +206,7 @@
.common = {
.name = "sha2_384",
.fqn = "HMAC_SHA2_384_192",
- .names = { "sha384", "sha2_384", "hmac_sha2_384", "hmac_sha2_384_192", },
+ .names = { "sha384", "sha2_384", "sha2_384_192", "hmac_sha2_384", "hmac_sha2_384_192", },
.algo_type = IKE_ALG_INTEG,
.id = {
[IKEv1_OAKLEY_ID] = OAKLEY_SHA2_384,
@@ -308,7 +308,7 @@
.common = {
.name = "sha2_512",
.fqn = "HMAC_SHA2_512_256",
- .names = { "sha512", "sha2_512", "hmac_sha2_512", "hmac_sha2_512_256", },
+ .names = { "sha512", "sha2_512", "sha2_512_256", "hmac_sha2_512", "hmac_sha2_512_256", },
.algo_type = IKE_ALG_INTEG,
.id = {
[IKEv1_OAKLEY_ID] = OAKLEY_SHA2_512,
diff -Naur libreswan-3.27-orig/lib/libswan/ike_info.c libreswan-3.27/lib/libswan/ike_info.c
--- libreswan-3.27-orig/lib/libswan/ike_info.c 2018-10-07 22:52:09.000000000 -0400
+++ libreswan-3.27/lib/libswan/ike_info.c 2019-02-15 16:50:12.777728085 -0500
@@ -27,10 +27,10 @@
#include "ike_alg_integ.h"
#include "ike_alg_prf.h"
#include "ike_alg_dh.h"
-#include "alg_info.h"
+#include "proposals.h"
-static bool ike_proposal_ok(const struct proposal_parser *parser,
- const struct proposal_info *proposal)
+static bool ike_proposal_ok(struct proposal_parser *parser,
+ const struct proposal *proposal)
{
if (!proposal_aead_none_ok(parser, proposal)) {
if (!impair_proposal_errors(parser)) {
@@ -42,27 +42,42 @@
* Check that the ALG_INFO spec is implemented.
*/
- impaired_passert(PROPOSAL_PARSER, proposal->encrypt != NULL);
- passert(proposal->encrypt == NULL || ike_alg_is_ike(&(proposal->encrypt->common)));
- passert(IMPAIR(PROPOSAL_PARSER) || proposal->enckeylen == 0 ||
- encrypt_has_key_bit_length(proposal->encrypt,
- proposal->enckeylen));
-
- impaired_passert(PROPOSAL_PARSER, proposal->prf != NULL);
- passert(proposal->prf == NULL || ike_alg_is_ike(&(proposal->prf->common)));
-
- impaired_passert(PROPOSAL_PARSER, proposal->integ != NULL);
- passert(proposal->integ == &ike_alg_integ_none ||
- proposal->integ == NULL ||
- ike_alg_is_ike(&proposal->integ->common));
-
- impaired_passert(PROPOSAL_PARSER, proposal->dh != NULL);
- passert(proposal->dh == NULL || ike_alg_is_ike(&(proposal->dh->common)));
- if (proposal->dh == &ike_alg_dh_none) {
- snprintf(parser->err_buf, parser->err_buf_len,
- "IKE DH algorithm 'none' not permitted");
- if (!impair_proposal_errors(parser)) {
- return false;
+ impaired_passert(PROPOSAL_PARSER,
+ next_algorithm(proposal, PROPOSAL_encrypt, NULL) != NULL);
+ FOR_EACH_ALGORITHM(proposal, encrypt, alg) {
+ const struct encrypt_desc *encrypt = encrypt_desc(alg->desc);
+ passert(ike_alg_is_ike(&encrypt->common));
+ passert(IMPAIR(PROPOSAL_PARSER) ||
+ alg->enckeylen == 0 ||
+ encrypt_has_key_bit_length(encrypt,
+ alg->enckeylen));
+ }
+
+ impaired_passert(PROPOSAL_PARSER,
+ next_algorithm(proposal, PROPOSAL_prf, NULL) != NULL);
+ FOR_EACH_ALGORITHM(proposal, prf, alg) {
+ const struct prf_desc *prf = prf_desc(alg->desc);
+ passert(ike_alg_is_ike(&prf->common));
+ }
+
+ impaired_passert(PROPOSAL_PARSER,
+ next_algorithm(proposal, PROPOSAL_integ, NULL) != NULL);
+ FOR_EACH_ALGORITHM(proposal, integ, alg) {
+ const struct integ_desc *integ = integ_desc(alg->desc);
+ passert(integ == &ike_alg_integ_none ||
+ ike_alg_is_ike(&integ->common));
+ }
+
+ impaired_passert(PROPOSAL_PARSER,
+ next_algorithm(proposal, PROPOSAL_dh, NULL) != NULL);
+ FOR_EACH_ALGORITHM(proposal, dh, alg) {
+ const struct oakley_group_desc *dh = dh_desc(alg->desc);
+ passert(ike_alg_is_ike(&dh->common));
+ if (dh == &ike_alg_dh_none) {
+ proposal_error(parser, "IKE DH algorithm 'none' not permitted");
+ if (!impair_proposal_errors(parser)) {
+ return false;
+ }
}
}
@@ -84,9 +99,20 @@
};
static const struct ike_alg *default_ikev2_groups[] = {
&oakley_group_modp2048.common,
+ &oakley_group_modp3072.common,
+ &oakley_group_modp4096.common,
+ &oakley_group_modp8192.common,
+ &oakley_group_dh19.common,
+ &oakley_group_dh20.common,
+ &oakley_group_dh21.common,
+ &oakley_group_dh31.common,
NULL,
};
+/*
+ * since ike= must have an encryption algorithm this is normally
+ * ignored.
+ */
static const struct ike_alg *default_ike_ealgs[] = {
#ifdef USE_AES
&ike_alg_encrypt_aes_cbc.common,
@@ -97,7 +123,7 @@
NULL,
};
-static const struct ike_alg *default_ike_aalgs[] = {
+static const struct ike_alg *default_v1_ike_prfs[] = {
#ifdef USE_SHA2
&ike_alg_prf_sha2_256.common,
&ike_alg_prf_sha2_512.common,
@@ -108,24 +134,34 @@
NULL,
};
+static const struct ike_alg *default_v2_ike_prfs[] = {
+#ifdef USE_SHA2
+ &ike_alg_prf_sha2_512.common,
+ &ike_alg_prf_sha2_256.common,
+#endif
+ NULL,
+};
+
const struct proposal_defaults ikev1_ike_defaults = {
.dh = default_ikev1_groups,
.encrypt = default_ike_ealgs,
- .prf = default_ike_aalgs,
+ .prf = default_v1_ike_prfs,
};
const struct proposal_defaults ikev2_ike_defaults = {
.dh = default_ikev2_groups,
.encrypt = default_ike_ealgs,
- .prf = default_ike_aalgs,
+ .prf = default_v2_ike_prfs,
};
const struct proposal_protocol ike_proposal_protocol = {
.name = "IKE",
.ikev1_alg_id = IKEv1_OAKLEY_ID,
.protoid = PROTO_ISAKMP,
- .ikev1_defaults = &ikev1_ike_defaults,
- .ikev2_defaults = &ikev2_ike_defaults,
+ .defaults = {
+ [IKEv1] = &ikev1_ike_defaults,
+ [IKEv2] = &ikev2_ike_defaults,
+ },
.proposal_ok = ike_proposal_ok,
.encrypt_alg_byname = encrypt_alg_byname,
.prf_alg_byname = prf_alg_byname,
@@ -133,25 +169,7 @@
.dh_alg_byname = dh_alg_byname,
};
-struct alg_info_ike *alg_info_ike_create_from_str(const struct proposal_policy *policy,
- const char *alg_str,
- char *err_buf, size_t err_buf_len)
+struct proposal_parser *ike_proposal_parser(const struct proposal_policy *policy)
{
- /*
- * alg_info storage should be sized dynamically
- * but this may require two passes to know
- * transform count in advance.
- */
- struct alg_info_ike *alg_info_ike = alloc_thing(struct alg_info_ike, "alg_info_ike");
- const struct proposal_parser parser = proposal_parser(policy,
- &ike_proposal_protocol,
- err_buf, err_buf_len);
-
- if (!alg_info_parse_str(&parser, &alg_info_ike->ai, shunk1(alg_str))) {
- passert(err_buf[0] != '\0');
- alg_info_free(&alg_info_ike->ai);
- return NULL;
- }
-
- return alg_info_ike;
+ return alloc_proposal_parser(policy, &ike_proposal_protocol);
}
diff -Naur libreswan-3.27-orig/lib/libswan/Makefile libreswan-3.27/lib/libswan/Makefile
--- libreswan-3.27-orig/lib/libswan/Makefile 2019-02-15 16:31:43.029408030 -0500
+++ libreswan-3.27/lib/libswan/Makefile 2019-02-15 16:32:28.981835360 -0500
@@ -74,7 +74,12 @@
OBJS += satot.o
OBJS += ultot.o
-OBJS += alg_info.o esp_info.o ike_info.o ah_info.o
+OBJS += proposals.o
+OBJS += v1_proposals.o
+OBJS += v2_proposals.o
+OBJS += esp_info.o
+OBJS += ah_info.o
+OBJS += ike_info.o
OBJS += ckaid.o
diff -Naur libreswan-3.27-orig/lib/libswan/proposals.c libreswan-3.27/lib/libswan/proposals.c
--- libreswan-3.27-orig/lib/libswan/proposals.c 1969-12-31 19:00:00.000000000 -0500
+++ libreswan-3.27/lib/libswan/proposals.c 2019-02-15 16:46:01.378390204 -0500
@@ -0,0 +1,573 @@
+/*
+ * Algorithm info parsing and creation functions
+ * Author: JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>
+ *
+ * Copyright (C) 2012 Paul Wouters <paul@libreswan.org>
+ * Copyright (C) 2015-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 <stdio.h>
+#include <string.h>
+#include <limits.h>
+
+#include "lswlog.h"
+#include "lswalloc.h"
+#include "constants.h"
+#include "proposals.h"
+#include "ike_alg.h"
+#include "ike_alg_integ.h"
+#include "ike_alg_dh.h"
+#include "alg_byname.h"
+
+struct proposal {
+ /*
+ * The algorithm entries.
+ */
+ struct algorithm *algorithms[PROPOSAL_ALGORITHM_ROOF];
+ /*
+ * Which protocol is this proposal intended for?
+ */
+ const struct proposal_protocol *protocol;
+ struct proposal *next;
+};
+
+struct proposals {
+ int ref_cnt;
+ struct proposal *proposals;
+};
+
+struct proposal_parser *alloc_proposal_parser(const struct proposal_policy *policy,
+ const struct proposal_protocol *protocol)
+{
+ struct proposal_parser *parser = alloc_thing(struct proposal_parser, "parser");
+ parser->policy = policy;
+ parser->protocol = protocol;
+ parser->error[0] = '\0';
+ return parser;
+}
+
+void free_proposal_parser(struct proposal_parser **parser)
+{
+ pfree(*parser);
+ *parser = NULL;
+}
+
+bool proposal_encrypt_aead(const struct proposal *proposal)
+{
+ if (proposal->algorithms[PROPOSAL_encrypt] == NULL) {
+ return false;
+ }
+ FOR_EACH_ALGORITHM(proposal, encrypt, alg) {
+ const struct encrypt_desc *encrypt = encrypt_desc(alg->desc);
+ if (!encrypt_desc_is_aead(encrypt)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool proposal_encrypt_norm(const struct proposal *proposal)
+{
+ if (proposal->algorithms[PROPOSAL_encrypt] == NULL) {
+ return false;
+ }
+ FOR_EACH_ALGORITHM(proposal, encrypt, alg) {
+ const struct encrypt_desc *encrypt = encrypt_desc(alg->desc);
+ if (encrypt_desc_is_aead(encrypt)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool proposal_integ_none(const struct proposal *proposal)
+{
+ /* interpret NULL as NONE */
+ FOR_EACH_ALGORITHM(proposal, integ, alg) {
+ const struct integ_desc *integ = integ_desc(alg->desc);
+ if (integ != &ike_alg_integ_none) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool proposal_aead_none_ok(struct proposal_parser *parser,
+ const struct proposal *proposal)
+{
+ if (IMPAIR(ALLOW_NULL_NONE)) {
+ return true;
+ }
+
+ if (proposal->algorithms[PROPOSAL_encrypt] == NULL) {
+ return true;
+ }
+
+ /* are any and all encrypt algorithms AEAD? */
+ bool aead = proposal_encrypt_aead(proposal);
+ bool norm = proposal_encrypt_norm(proposal);
+
+ if (!aead && !norm) {
+ proposal_error(parser, "AEAD and non-AEAD %s encryption algorithm can not be combined",
+ proposal->protocol->name);
+ return false;
+ }
+
+ /* are any and all integ algorithms NONE? */
+ bool none = proposal_integ_none(proposal);
+
+ if (aead && !none) {
+ const struct ike_alg *encrypt = proposal->algorithms[PROPOSAL_encrypt]->desc;
+ /*
+ * At least one of the integrity algorithms wasn't
+ * NONE. For instance, esp=aes_gcm-sha1" is invalid.
+ */
+ proposal_error(parser, "AEAD %s encryption algorithm '%s' must have 'none' as the integrity algorithm",
+ proposal->protocol->name,
+ encrypt->name);
+ return false;
+ }
+
+ if (norm && none) {
+ const struct ike_alg *encrypt = proposal->algorithms[PROPOSAL_encrypt]->desc;
+ /*
+ * Not AEAD and either there was no integrity
+ * algorithm (implying NONE) or at least one integrity
+ * algorithm was NONE. For instance,
+ * esp=aes_cbc-none" is invalid.
+ */
+ proposal_error(parser, "non-AEAD %s encryption algorithm '%s' cannot have 'none' as the integrity algorithm",
+ proposal->protocol->name,
+ encrypt->name);
+ return false;
+ }
+
+ return true;
+}
+
+
+/*
+ * proposals struct can be shared by several connections instances,
+ * handle free() with ref_cnts.
+ */
+
+void proposals_addref(struct proposals **proposals)
+{
+ if ((*proposals) != NULL) {
+ (*proposals)->ref_cnt++;
+ }
+}
+
+void proposals_delref(struct proposals **proposals)
+{
+ if ((*proposals) != NULL) {
+ if ((*proposals)->ref_cnt == 0) {
+ free_proposal(&(*proposals)->proposals);
+ pfree((*proposals));
+ } else {
+ (*proposals)->ref_cnt--;
+ }
+ *proposals = NULL;
+ }
+}
+struct proposal *next_proposal(const struct proposals *proposals,
+ struct proposal *last)
+{
+ if (last == NULL) {
+ return proposals->proposals;
+ } else {
+ return last->next;
+ }
+}
+
+unsigned nr_proposals(struct proposals *proposals)
+{
+ unsigned nr = 0;
+ FOR_EACH_PROPOSAL(proposals, proposal) {
+ nr++;
+ }
+ return nr;
+}
+
+void append_proposal(struct proposals *proposals, struct proposal **proposal)
+{
+ struct proposal **end = &proposals->proposals;
+ /* check for duplicates */
+ while ((*end) != NULL) {
+ bool same = true;
+ for (enum proposal_algorithm pa = 0;
+ same && pa < PROPOSAL_ALGORITHM_ROOF; pa++) {
+ struct algorithm *old = (*end)->algorithms[pa];
+ struct algorithm *new = (*proposal)->algorithms[pa];
+ while (same) {
+ if (new == NULL && old == NULL) {
+ break;
+ }
+ if (new == NULL || old == NULL) {
+ same = false;
+ break;
+ }
+ if (new->desc != old->desc) {
+ same = false;
+ break;
+ }
+ /*
+ * If list already contains encryption
+ * with ENCKEYLEN=0 then new is a
+ * duplicate as 0 generates all keys.
+ * Ignore reverse vis aes128,aes.
+ */
+ if (old->desc->algo_type == IKE_ALG_ENCRYPT &&
+ (old->enckeylen != 0 &&
+ new->enckeylen != old->enckeylen)) {
+ same = false;
+ break;
+ }
+ new = new->next;
+ old = old->next;
+ }
+ }
+ if (same) {
+ /* parser->policy->warning("discarding duplicate proposal"); */
+ free_proposal(proposal);
+ return;
+ }
+ end = &(*end)->next;
+ }
+ *end = *proposal;
+ *proposal = NULL;
+}
+
+struct v1_proposal v1_proposal(const struct proposal *proposal)
+{
+ struct v1_proposal v1 = {
+ .protocol = proposal->protocol,
+#define D(ALG) .ALG = proposal->algorithms[PROPOSAL_##ALG] != NULL ? ALG##_desc(proposal->algorithms[PROPOSAL_##ALG]->desc) : NULL
+ D(encrypt),
+ D(prf),
+ D(integ),
+ D(dh),
+#undef D
+ };
+ v1.enckeylen = proposal->algorithms[PROPOSAL_encrypt] != NULL ? proposal->algorithms[PROPOSAL_encrypt]->enckeylen : 0;
+
+ return v1;
+}
+
+struct algorithm *next_algorithm(const struct proposal *proposal,
+ enum proposal_algorithm algorithm,
+ struct algorithm *last)
+{
+ if (last == NULL) {
+ /*
+ * Hack, there should there a way to index algorithm
+ * types; however the old enum proved very dangerous.
+ */
+ passert(algorithm < elemsof(proposal->algorithms));
+ return proposal->algorithms[algorithm];
+ } else {
+ return last->next;
+ }
+}
+
+void free_algorithms(struct proposal *proposal,
+ enum proposal_algorithm algorithm)
+{
+ passert(algorithm < elemsof(proposal->algorithms));
+ struct algorithm *alg = proposal->algorithms[algorithm];
+ while (alg != NULL) {
+ struct algorithm *del = alg;
+ alg = alg->next;
+ pfree(del);
+ }
+ proposal->algorithms[algorithm] = NULL;
+}
+
+struct proposal *alloc_proposal(struct proposal_parser *parser)
+{
+ struct proposal *proposal = alloc_thing(struct proposal, "proposal");
+ proposal->protocol = parser->protocol;
+ return proposal;
+}
+
+void free_proposal(struct proposal **proposals)
+{
+ struct proposal *proposal = *proposals;
+ while (proposal != NULL) {
+ struct proposal *del = proposal;
+ proposal = proposal->next;
+ for (enum proposal_algorithm algorithm = 0;
+ algorithm < PROPOSAL_ALGORITHM_ROOF;
+ algorithm++) {
+ free_algorithms(del, algorithm);
+ }
+ pfree(del);
+ }
+ *proposals = NULL;
+}
+
+void append_algorithm(struct proposal_parser *parser,
+ struct proposal *proposal,
+ enum proposal_algorithm algorithm,
+ const struct ike_alg *alg,
+ int enckeylen)
+{
+ passert(algorithm < elemsof(proposal->algorithms));
+ struct algorithm **end = &proposal->algorithms[algorithm];
+ /* find end, and check for duplicates */
+ while ((*end) != NULL) {
+ /*
+ * enckeylen=0 acts as a wildcard
+ */
+ if (alg == (*end)->desc &&
+ (alg->algo_type != IKE_ALG_ENCRYPT ||
+ ((*end)->enckeylen == 0 ||
+ enckeylen == (*end)->enckeylen))) {
+ parser->policy->warning("discarding duplicate algorithm '%s'",
+ alg->name);
+ return;
+ }
+ end = &(*end)->next;
+ }
+ struct algorithm new_algorithm = {
+ .desc = alg,
+ .enckeylen = enckeylen,
+ };
+ *end = clone_thing(new_algorithm, "alg");
+}
+
+void fmt_proposal(struct lswlog *log,
+ const struct proposal *proposal)
+{
+ const char *ps = "";
+
+ const char *as = "";
+
+ as = ps;
+ FOR_EACH_ALGORITHM(proposal, encrypt, alg) {
+ const struct encrypt_desc *encrypt = encrypt_desc(alg->desc);
+ lswlogs(log, as); ps = "-"; as = "+";
+ lswlogs(log, encrypt->common.fqn);
+ if (alg->enckeylen != 0) {
+ lswlogf(log, "_%d", alg->enckeylen);
+ }
+ }
+
+ as = ps;
+ FOR_EACH_ALGORITHM(proposal, prf, alg) {
+ const struct prf_desc *prf = prf_desc(alg->desc);
+ lswlogs(log, as); ps = "-"; as = "+";
+ lswlogs(log, prf->common.fqn);
+ }
+
+ as = ps;
+ if ((proposal->algorithms[PROPOSAL_prf] == NULL &&
+ proposal->algorithms[PROPOSAL_integ] != NULL) ||
+ (IMPAIR(PROPOSAL_PARSER) &&
+ proposal->algorithms[PROPOSAL_integ] != NULL)) {
+ FOR_EACH_ALGORITHM(proposal, integ, alg) {
+ const struct integ_desc *integ = integ_desc(alg->desc);
+ lswlogs(log, as); ps = "-"; as = "+";
+ lswlogs(log, integ->common.fqn);
+ }
+ }
+
+ as = ps;
+ FOR_EACH_ALGORITHM(proposal, dh, alg) {
+ const struct oakley_group_desc *dh = dh_desc(alg->desc);
+ lswlogs(log, as); ps = "-"; as = "+";
+ lswlogs(log, dh->common.fqn);
+ }
+}
+
+void fmt_proposals(struct lswlog *log, const struct proposals *proposals)
+{
+ const char *sep = "";
+ FOR_EACH_PROPOSAL(proposals, proposal) {
+ lswlogs(log, sep);
+ fmt_proposal(log, proposal);
+ sep = ", ";
+ }
+}
+
+/*
+ * When PFS=no ignore any DH algorithms, and when PFS=yes reject
+ * mixing implict and explicit DH.
+ */
+static bool proposals_pfs_vs_dh_check(struct proposal_parser *parser,
+ struct proposals *proposals)
+{
+ /* scrape the proposals for dh algorithms */
+ const struct proposal *first_null = NULL;
+ const struct proposal *first_none = NULL;
+ const struct ike_alg *first_dh = NULL;
+ const struct ike_alg *second_dh = NULL;
+ FOR_EACH_PROPOSAL(proposals, proposal) {
+ if (proposal->algorithms[PROPOSAL_dh] == NULL) {
+ if (first_null == NULL) {
+ first_null = proposal;
+ }
+ } else if (proposal->algorithms[PROPOSAL_dh]->desc == &ike_alg_dh_none.common) {
+ if (first_none == NULL) {
+ first_none = proposal;
+ }
+ } else if (first_dh == NULL) {
+ first_dh = proposal->algorithms[PROPOSAL_dh]->desc;
+ } else if (second_dh == NULL &&
+ first_dh != proposal->algorithms[PROPOSAL_dh]->desc) {
+ second_dh = proposal->algorithms[PROPOSAL_dh]->desc;
+ }
+ }
+
+ if (first_dh == NULL && first_none == NULL) {
+ /* no DH is always ok */
+ return true;
+ }
+
+ /*
+ * Try to generate very specific errors first. For instance,
+ * given PFS=no esp=aes,aes;dh21, an error stating that dh21
+ * is not valid because of PFS is more helpful than an error
+ * saying that all or no proposals need PFS.
+ */
+
+ /*
+ * Since PFS=NO overrides any DH, don't silently ignore it.
+ * Check this early so that a conflict with PFS=no code gets
+ * reported before anything else.
+ */
+ if (!parser->policy->pfs && (first_dh != NULL || first_none != NULL)) {
+ FOR_EACH_PROPOSAL(proposals, proposal) {
+ const struct ike_alg *dh = NULL;
+ if (proposal->algorithms[PROPOSAL_dh] != NULL) {
+ dh = proposal->algorithms[PROPOSAL_dh]->desc;
+ }
+ if (dh == &ike_alg_dh_none.common) {
+ parser->policy->warning("ignoring redundant %s DH algorithm NONE as PFS policy is disabled",
+ parser->protocol->name);
+ } else if (dh != NULL) {
+ parser->policy->warning("ignoring %s DH algorithm %s as PFS policy is disabled",
+ parser->protocol->name,
+ dh->fqn);
+ }
+ free_algorithms(proposal, PROPOSAL_dh);
+ }
+ return true;
+ }
+
+ /*
+ * Since at least one proposal included DH, all proposals
+ * should. A proposal without DH is an error.
+ *
+ * (The converse, no proposals including DH was handled right
+ * at the start).
+ */
+ if (first_null != NULL) {
+ /* DH was specified */
+ proposal_error(parser, "either all or no %s proposals should specify DH",
+ parser->protocol->name);
+ if (!impair_proposal_errors(parser)) {
+ return false;
+ }
+ }
+
+ switch (parser->policy->version) {
+
+ case IKEv1:
+ /*
+ * IKEv1 only allows one DH algorithm.
+ */
+ if (first_dh != NULL && second_dh != NULL) {
+ proposal_error(parser, "more than one IKEv1 %s DH algorithm (%s, %s) is not allowed in quick mode",
+ parser->protocol->name,
+ first_dh->fqn,
+ second_dh->fqn);
+ if (!impair_proposal_errors(parser)) {
+ return false;
+ }
+ }
+ break;
+
+ case IKEv2:
+ /*
+ * IKEv2, only implements one DH algorithm.
+ */
+ if (first_dh != NULL && second_dh != NULL) {
+ proposal_error(parser, "more than one IKEv2 %s DH algorithm (%s, %s) requires unimplemented CHILD_SA INVALID_KE",
+ parser->protocol->name,
+ first_dh->fqn,
+ second_dh->fqn);
+ if (!impair_proposal_errors(parser)) {
+ return false;
+ }
+ }
+ break;
+
+ default:
+ /* ignore */
+ break;
+ }
+
+ return true;
+}
+
+void proposal_error(struct proposal_parser *parser, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ vsnprintf(parser->error, sizeof(parser->error), fmt, ap);
+ va_end(ap);
+}
+
+bool impair_proposal_errors(struct proposal_parser *parser)
+{
+ pexpect(parser->error[0] != '\0');
+ if (IMPAIR(PROPOSAL_PARSER)) {
+ libreswan_log("IMPAIR: ignoring proposal error: %s",
+ parser->error);
+ parser->error[0] = '\0';
+ return true;
+ } else {
+ return false;
+ }
+}
+
+struct proposals *proposals_from_str(struct proposal_parser *parser,
+ const char *str)
+{
+ struct proposals *proposals = alloc_thing(struct proposals, "proposals");
+ unsigned parser_version = parser->policy->parser_version;
+ if (parser_version == 0) {
+ parser_version = parser->policy->version;
+ }
+ bool ok;
+ switch (parser_version) {
+ case 2: ok = v2_proposals_parse_str(parser, proposals, shunk1(str)); break;
+ default: ok = v1_proposals_parse_str(parser, proposals, shunk1(str)); break;
+ }
+ if (!ok) {
+ proposals_delref(&proposals);
+ return NULL;
+ }
+ if (proposals->proposals == NULL) {
+ proposals_delref(&proposals);
+ return NULL;
+ }
+ if (parser->policy->check_pfs_vs_dh &&
+ !proposals_pfs_vs_dh_check(parser, proposals)) {
+ pexpect(parser->error[0] != '\0');
+ proposals_delref(&proposals);
+ return NULL;
+ }
+ return proposals;
+}
diff -Naur libreswan-3.27-orig/lib/libswan/shunk.c libreswan-3.27/lib/libswan/shunk.c
--- libreswan-3.27-orig/lib/libswan/shunk.c 2018-10-07 22:52:09.000000000 -0400
+++ libreswan-3.27/lib/libswan/shunk.c 2019-02-15 16:32:28.982835370 -0500
@@ -1,6 +1,6 @@
-/* string fragments, for libreswan
+/* Constant string (octet) fragments, for libreswan
*
- * Copyright (C) 2018 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
@@ -20,12 +20,17 @@
#include "shunk.h"
-const shunk_t empty_shunk;
+/*
+ * Don't mistake a NULL_SHUNK for an empty shunk - just like for
+ * strings they are different.
+ */
+
+const shunk_t null_shunk = NULL_SHUNK;
shunk_t shunk1(const char *ptr)
{
if (ptr == NULL) {
- return empty_shunk;
+ return null_shunk;
} else {
return shunk2(ptr, strlen(ptr));
}
@@ -34,28 +39,37 @@
shunk_t shunk2(const char *ptr, int len)
{
/*
- * Since a zero length string and a NULL string pointer are
- * considered to be different, don't convert the former into
- * an empty_chunk.
+ * Since a zero length string is not the same as a NULL
+ * string, don't try to be smart and convert the former into
+ * the latter.
*/
return (shunk_t) { .ptr = ptr, .len = len, };
}
-shunk_t shunk_strsep(shunk_t *shunk, const char *delim)
+shunk_t shunk_strsep(shunk_t *input, const char *delim)
{
- shunk_t token = shunk2(shunk->ptr, 0);
- while (shunk->len > 0) {
- if (strchr(delim, *shunk->ptr) != NULL) {
+ /*
+ * If INPUT is NULL, the loop is skipped and NULL is
+ * returned.
+ */
+ shunk_t token = shunk2(input->ptr, 0);
+ while (input->len > 0) {
+ if (strchr(delim, *input->ptr) != NULL) {
/* discard delim */
- shunk->ptr++;
- shunk->len--;
+ input->ptr++;
+ input->len--;
return token;
}
/* advance, transfering the char */
token.len++;
- shunk->ptr++;
- shunk->len--;
+ input->ptr++;
+ input->len--;
}
+ /*
+ * Flag this as the last token by setting INPUT to NULL; next
+ * call will return the NULL shunk.
+ */
+ *input = null_shunk;
return token;
}
diff -Naur libreswan-3.27-orig/lib/libswan/v1_proposals.c libreswan-3.27/lib/libswan/v1_proposals.c
--- libreswan-3.27-orig/lib/libswan/v1_proposals.c 1969-12-31 19:00:00.000000000 -0500
+++ libreswan-3.27/lib/libswan/v1_proposals.c 2019-02-15 16:47:22.485144451 -0500
@@ -0,0 +1,578 @@
+/* V1 algorithm proposal parsing, for libreswan
+ *
+ * Copyright (C) 2012 Paul Wouters <paul@libreswan.org>
+ * Copyright (C) 2015-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 <stdio.h>
+#include <string.h>
+#include <limits.h>
+
+#include "lswlog.h"
+#include "lswalloc.h"
+#include "constants.h"
+#include "proposals.h"
+#include "ike_alg.h"
+#include "ike_alg_integ.h"
+#include "ike_alg_dh.h"
+#include "alg_byname.h"
+
+/*
+ * Add the proposal defaults for the specific algorithm.
+ */
+
+typedef struct v1_proposal merge_alg_default_t(struct v1_proposal proposal,
+ const struct ike_alg *default_alg);
+
+static struct v1_proposal merge_dh_default(struct v1_proposal proposal,
+ const struct ike_alg *default_alg)
+{
+ proposal.dh = oakley_group_desc(default_alg);
+ return proposal;
+}
+
+static struct v1_proposal merge_encrypt_default(struct v1_proposal proposal,
+ const struct ike_alg *default_alg)
+{
+ proposal.encrypt = encrypt_desc(default_alg);
+ return proposal;
+}
+
+static struct v1_proposal merge_prf_default(struct v1_proposal proposal,
+ const struct ike_alg *default_alg)
+{
+ proposal.prf = prf_desc(default_alg);
+ return proposal;
+}
+
+static struct v1_proposal merge_integ_default(struct v1_proposal proposal,
+ const struct ike_alg *default_alg)
+{
+ proposal.integ = integ_desc(default_alg);
+ return proposal;
+}
+
+static bool add_proposal_defaults(struct proposal_parser *parser,
+ const struct proposal_defaults *defaults,
+ struct proposals *proposals,
+ const struct v1_proposal *proposal);
+
+static bool add_alg_defaults(struct proposal_parser *parser,
+ const struct proposal_defaults *defaults,
+ struct proposals *proposals,
+ const struct v1_proposal *proposal,
+ const struct ike_alg_type *type,
+ const struct ike_alg **default_algs,
+ merge_alg_default_t *merge_alg_default)
+{
+ /*
+ * Use VALID_ALG to add the valid algorithms into VALID_ALGS.
+ */
+ for (const struct ike_alg **default_alg = default_algs;
+ *default_alg; default_alg++) {
+ const struct ike_alg *alg = *default_alg;
+ if (!alg_byname_ok(parser, alg,
+ shunk1(alg->name))) {
+ DBG(DBG_PROPOSAL_PARSER,
+ DBG_log("skipping default %s",
+ parser->error));
+ parser->error[0] = '\0';
+ continue;
+ }
+ /* add it */
+ DBG(DBG_PROPOSAL_PARSER,
+ DBG_log("adding default %s %s",
+ ike_alg_type_name(type),
+ alg->name));
+ struct v1_proposal merged_proposal = merge_alg_default(*proposal,
+ *default_alg);
+ if (!add_proposal_defaults(parser, defaults,
+ proposals, &merged_proposal)) {
+ passert(parser->error[0] != '\0');
+ return false;
+ }
+ }
+ return true;
+}
+
+/*
+ * Validate the proposal and, suppressing duplicates, add it to the
+ * proposal list.
+ */
+
+static bool add_proposal(struct proposal_parser *parser,
+ struct proposals *proposals,
+ const struct v1_proposal *proposal)
+{
+ struct proposal *new = alloc_proposal(parser);
+ if (proposal->encrypt != NULL) {
+ append_algorithm(parser, new, PROPOSAL_encrypt,
+ &proposal->encrypt->common,
+ proposal->enckeylen);
+ }
+#define A(NAME) \
+ if (proposal->NAME != NULL) { \
+ append_algorithm(parser, new, PROPOSAL_##NAME, \
+ &proposal->NAME->common, 0); \
+ }
+ A(prf);
+ A(integ);
+ A(dh);
+#undef A
+ /* back end? */
+ if (!proposal->protocol->proposal_ok(parser, new)) {
+ free_proposal(&new);
+ return false;
+ }
+ append_proposal(proposals, &new);
+ return true;
+}
+
+/*
+ * For all the algorithms, when an algorithm is missing (NULL), and
+ * there are defaults, add them.
+ */
+
+static bool add_proposal_defaults(struct proposal_parser *parser,
+ const struct proposal_defaults *defaults,
+ struct proposals *proposals,
+ const struct v1_proposal *proposal)
+{
+ /*
+ * Note that the order in which things are recursively added -
+ * MODP, ENCR, PRF/HASH - affects test results. It determines
+ * things like the order of proposals.
+ */
+ if (proposal->dh == NULL &&
+ defaults != NULL && defaults->dh != NULL) {
+ return add_alg_defaults(parser, defaults,
+ proposals, proposal,
+ &ike_alg_dh, defaults->dh,
+ merge_dh_default);
+ } else if (proposal->encrypt == NULL &&
+ defaults != NULL && defaults->encrypt != NULL) {
+ return add_alg_defaults(parser, defaults,
+ proposals, proposal,
+ &ike_alg_encrypt, defaults->encrypt,
+ merge_encrypt_default);
+ } else if (proposal->prf == NULL &&
+ defaults != NULL && defaults->prf != NULL) {
+ return add_alg_defaults(parser, defaults,
+ proposals, proposal,
+ &ike_alg_prf, defaults->prf,
+ merge_prf_default);
+ } else if (proposal->integ == NULL &&
+ proposal->encrypt != NULL &&
+ encrypt_desc_is_aead(proposal->encrypt)) {
+ /*
+ * Since AEAD, integrity is always 'none'.
+ */
+ struct v1_proposal merged_proposal = *proposal;
+ merged_proposal.integ = &ike_alg_integ_none;
+ return add_proposal_defaults(parser, defaults,
+ proposals, &merged_proposal);
+ } else if (proposal->integ == NULL &&
+ defaults != NULL && defaults->integ != NULL) {
+ return add_alg_defaults(parser, defaults,
+ proposals, proposal,
+ &ike_alg_integ, defaults->integ,
+ merge_integ_default);
+ } else if (proposal->integ == NULL &&
+ proposal->prf != NULL &&
+ proposal->encrypt != NULL &&
+ !encrypt_desc_is_aead(proposal->encrypt)) {
+ /*
+ * Since non-AEAD, use an integrity algorithm that is
+ * implemented using the PRF.
+ */
+ struct v1_proposal merged_proposal = *proposal;
+ for (const struct integ_desc **algp = next_integ_desc(NULL);
+ algp != NULL; algp = next_integ_desc(algp)) {
+ const struct integ_desc *alg = *algp;
+ if (alg->prf == proposal->prf) {
+ merged_proposal.integ = alg;
+ break;
+ }
+ }
+ if (merged_proposal.integ == NULL) {
+ proposal_error(parser, "%s integrity derived from PRF '%s' is not supported",
+ proposal->protocol->name,
+ proposal->prf->common.name);
+ return false;
+ }
+ return add_proposal_defaults(parser, defaults,
+ proposals, &merged_proposal);
+ } else {
+ return add_proposal(parser, proposals, proposal);
+ }
+}
+
+static bool merge_default_proposals(struct proposal_parser *parser,
+ struct proposals *proposals,
+ const struct v1_proposal *proposal)
+{
+ /*
+ * If there's a hint of IKEv1 being enabled then prefer its
+ * larger set of defaults.
+ *
+ * This should increase the odds of both ends interoperating.
+ *
+ * For instance, the IKEv2 defaults were preferred and one end
+ * has ikev2=never then, in aggressive mode, things don't
+ * work.
+ */
+ passert(parser->policy->version < elemsof(proposal->protocol->defaults));
+ const struct proposal_defaults *defaults =
+ proposal->protocol->defaults[parser->policy->version];
+ return add_proposal_defaults(parser, defaults,
+ proposals, proposal);
+}
+
+static const struct ike_alg *lookup_byname(struct proposal_parser *parser,
+ alg_byname_fn *alg_byname,
+ shunk_t name,
+ size_t key_bit_length,
+ shunk_t print_name,
+ const char *what)
+{
+ if (name.len > 0) {
+ if (alg_byname != NULL) {
+ const struct ike_alg *alg = alg_byname(parser, name, key_bit_length,
+ print_name);
+ if (alg == NULL) {
+ DBG(DBG_PROPOSAL_PARSER,
+ DBG_log("%s_byname('"PRI_SHUNK"') failed: %s",
+ what, PRI_shunk(name),
+ parser->error));
+ passert(parser->error[0] != '\0');
+ return NULL;
+ }
+ DBG(DBG_PROPOSAL_PARSER,
+ DBG_log("%s_byname('"PRI_SHUNK"') returned '%s'",
+ what, PRI_shunk(name), alg->name));
+ return alg;
+ } else {
+ DBG(DBG_PROPOSAL_PARSER,
+ DBG_log("ignoring %s '"PRI_SHUNK"'",
+ what, PRI_shunk(name)));
+ return NULL;
+ }
+ }
+ return NULL;
+}
+
+static int parse_eklen(struct proposal_parser *parser, shunk_t buf)
+{
+ /* convert -<eklen> if present */
+ char *end = NULL;
+ long eklen = strtol(buf.ptr, &end, 10);
+ if (buf.ptr + buf.len != end) {
+ proposal_error(parser, "encryption key length '"PRI_SHUNK"' contains a non-numeric character",
+ PRI_shunk(buf));
+ return 0;
+ }
+ if (eklen >= INT_MAX) {
+ proposal_error(parser, "encryption key length '"PRI_SHUNK"' WAY too big",
+ PRI_shunk(buf));
+ return 0;
+ }
+ if (eklen == 0) {
+ proposal_error(parser, "encryption key length is zero");
+ return 0;
+ }
+ return eklen;
+}
+
+/*
+ * Try to parse any of <ealg>-<ekeylen>, <ealg>_<ekeylen>,
+ * <ealg><ekeylen>, or <ealg>. Strings like aes_gcm_16 and
+ * aes_gcm_16_256 end up in alg[0], while strings like aes_gcm_16-256
+ * end up in alg[0]-alg[1].
+ */
+
+struct token {
+ char sep;
+ shunk_t alg;
+};
+
+static bool parse_encrypt(struct proposal_parser *parser,
+ struct token **tokens,
+ struct v1_proposal *proposal)
+{
+ shunk_t ealg = (*tokens)[0].alg;
+ shunk_t eklen = (*tokens)[1].alg;
+ if (eklen.len > 0 && isdigit(eklen.ptr[0])) {
+ /* assume <ealg>-<eklen> */
+ int enckeylen = parse_eklen(parser, eklen);
+ if (enckeylen <= 0) {
+ passert(parser->error[0] != '\0');
+ return false;
+ }
+ /* print <alg>-<len> */
+ shunk_t print_name = shunk2(ealg.ptr, eklen.ptr + eklen.len - ealg.ptr);
+ proposal->enckeylen = enckeylen;
+ proposal->encrypt =
+ encrypt_desc(lookup_byname(parser,
+ encrypt_alg_byname,
+ ealg, proposal->enckeylen,
+ print_name, "encryption"));
+ /* Was <ealg>-<eklen> rejected? */
+ if (parser->error[0] != '\0') {
+ return false;
+ }
+ *tokens += 2; /* consume both tokens */
+ return true;
+ }
+ /* try <ealg> */
+ shunk_t print_name = ealg;
+ proposal->encrypt =
+ encrypt_desc(lookup_byname(parser,
+ encrypt_alg_byname,
+ ealg, proposal->enckeylen,
+ print_name, "encryption"));
+ if (parser->error[0] != '\0') {
+ /*
+ * Could it be <ealg><eklen> or <ealg>_<eklen>? Work
+ * backwards skipping any digits.
+ */
+ shunk_t end = shunk2(ealg.ptr + ealg.len, 0);
+ while (end.ptr > ealg.ptr && isdigit(end.ptr[-1])) {
+ end.ptr--;
+ end.len++;
+ }
+ if (end.len == 0) {
+ /*
+ * no trailing <eklen> and <ealg> was rejected
+ */
+ passert(parser->error[0] != '\0');
+ return false;
+ }
+ /* try to convert */
+ int enckeylen = parse_eklen(parser, end);
+ if (enckeylen <= 0) {
+ passert(parser->error[0] != '\0');
+ return false;
+ }
+ proposal->enckeylen = enckeylen;
+ /*
+ * trim <eklen> from <ealg>; and then trim any
+ * trailing '_'
+ */
+ ealg.len = end.ptr - ealg.ptr;
+ if (end.ptr > ealg.ptr && end.ptr[-1] == '_') {
+ ealg.len -= 1;
+ }
+ /* try again */
+ parser->error[0] = '\0';
+ proposal->encrypt =
+ encrypt_desc(lookup_byname(parser,
+ encrypt_alg_byname,
+ ealg, proposal->enckeylen,
+ print_name, "encryption"));
+ if (parser->error[0] != '\0') {
+ return false;
+ }
+ }
+ *tokens += 1; /* consume one token */
+ return true;
+}
+
+static bool parser_proposals_add(struct proposal_parser *parser,
+ struct token *tokens, struct v1_proposal proposal,
+ struct proposals *proposals)
+{
+ LSWDBGP(DBG_PROPOSAL_PARSER, buf) {
+ lswlogs(buf, "algs:");
+ for (struct token *token = tokens; token->alg.ptr != NULL; token++) {
+ lswlogf(buf, " algs[%tu] = '"PRI_SHUNK"'",
+ token - tokens, PRI_shunk(token->alg));
+ }
+ }
+
+ bool lookup_encrypt = parser->protocol->encrypt_alg_byname != NULL;
+ if (!lookup_encrypt && IMPAIR(PROPOSAL_PARSER)) {
+ /* Force lookup, will discard any error. */
+ lookup_encrypt = true;
+ }
+ if (lookup_encrypt && tokens->alg.ptr != NULL && tokens->sep != ';') {
+ if (!parse_encrypt(parser, &tokens, &proposal)) {
+ if (IMPAIR(PROPOSAL_PARSER)) {
+ /* ignore the lookup and stumble on */
+ parser->error[0] = '\0';
+ } else {
+ passert(parser->error[0] != '\0');
+ return false;
+ }
+ }
+ }
+
+ bool lookup_prf = parser->protocol->prf_alg_byname != NULL;
+ if (!lookup_prf && IMPAIR(PROPOSAL_PARSER)) {
+ /*
+ * When impaired, only force PRF lookup when the the
+ * token after this one is a valid INTEG algorithm.
+ * Otherwise something like ah=sha1 gets parsed as
+ * ah=[encr]-sha1-[integ]-[dh] instead of
+ * ah=[encr]-[prf]-sha1-[dh].
+ */
+ shunk_t prf = tokens[0].alg;
+ shunk_t integ = tokens[1].alg;
+ if (prf.ptr != NULL && integ.ptr != NULL) {
+ lookup_prf = (lookup_byname(parser, integ_alg_byname,
+ integ, 0, integ, "integrity")
+ != NULL);
+ parser->error[0] = '\0';
+ }
+ }
+ if (lookup_prf && tokens->alg.ptr != NULL && tokens->sep != ';') {
+ shunk_t prf = tokens[0].alg;
+ proposal.prf = prf_desc(lookup_byname(parser,
+ prf_alg_byname,
+ prf, 0, prf, "PRF"));
+ if (parser->error[0] != '\0') {
+ return false;
+ }
+ tokens += 1; /* consume one arg */
+ }
+
+ /*
+ * By default, don't allow IKE's [...]-<prf>-<integ>-[....].
+ * Instead fill in integrity using the above PRF.
+ *
+ * XXX: The parser and output isn't consistent in that for ESP
+ * it parses <encry>-<integ> but for IKE it parses
+ * <encr>-<prf>. This seems to lead to confusion when
+ * printing proposals - ike=aes_gcm-sha1 gets mis-read as as
+ * using sha1 as integrity. ike-aes_gcm-none-sha1 would
+ * clarify this but that makes for a fun parse.
+ */
+ bool lookup_integ = (parser->protocol->prf_alg_byname == NULL &&
+ parser->protocol->integ_alg_byname != NULL);
+ if (!lookup_integ && IMPAIR(PROPOSAL_PARSER)) {
+ /* force things */
+ lookup_integ = true;
+ }
+ if (lookup_integ && tokens->alg.ptr != NULL && tokens->sep != ';') {
+ shunk_t integ = tokens[0].alg;
+ proposal.integ = integ_desc(lookup_byname(parser,
+ integ_alg_byname,
+ integ, 0, integ, "integrity"));
+ if (parser->error[0] != '\0') {
+ if (tokens[1].alg.ptr != NULL) {
+ /*
+ * This alg should have been
+ * integrity, since the next would be
+ * DH; error applies.
+ */
+ passert(parser->error[0] != '\0');
+ return false;
+ }
+ if (tokens[1].alg.ptr == NULL &&
+ parser->protocol->prf_alg_byname == NULL) {
+ /*
+ * Only one arg, integrity is prefered
+ * to DH (and no PRF); error applies.
+ */
+ passert(parser->error[0] != '\0');
+ return false;
+ }
+ /* let DH try */
+ parser->error[0] = '\0';
+ } else {
+ tokens += 1; /* consume one arg */
+ }
+ }
+
+ bool lookup_dh = parser->protocol->dh_alg_byname || IMPAIR(PROPOSAL_PARSER);
+ if (lookup_dh && tokens->alg.ptr != NULL) {
+ shunk_t dh = tokens[0].alg;
+ proposal.dh = oakley_group_desc(lookup_byname(parser,
+ dh_alg_byname,
+ dh, 0,
+ dh, "DH"));
+ if (parser->error[0] != '\0') {
+ return false;
+ }
+ tokens += 1; /* consume one arg */
+ }
+
+ if (tokens->alg.ptr != NULL) {
+ proposal_error(parser, "'"PRI_SHUNK"' unexpected",
+ PRI_shunk(tokens[0].alg));
+ return false;
+ }
+
+ if (IMPAIR(PROPOSAL_PARSER)) {
+ return add_proposal(parser, proposals, &proposal);
+ } else {
+ return merge_default_proposals(parser, proposals, &proposal);
+ }
+}
+
+bool v1_proposals_parse_str(struct proposal_parser *parser,
+ struct proposals *proposals,
+ shunk_t alg_str)
+{
+ DBG(DBG_PROPOSAL_PARSER,
+ DBG_log("parsing '"PRI_SHUNK"' for %s",
+ PRI_shunk(alg_str), parser->protocol->name));
+
+ /* use default if no string */
+ if (alg_str.ptr == NULL) {
+ const struct v1_proposal proposal = {
+ .protocol = parser->protocol,
+ };
+ return merge_default_proposals(parser, proposals, &proposal);
+ }
+
+ if (alg_str.len == 0) {
+ /* XXX: hack to keep testsuite happy */
+ proposal_error(parser, "String ended with invalid char, just after \"\"");
+ return false;
+ }
+
+ shunk_t prop_ptr = alg_str;
+ do {
+ /* find the next proposal */
+ shunk_t prop = shunk_strsep(&prop_ptr, ",");
+ /* parse it */
+ struct token tokens[8];
+ zero(&tokens);
+ struct token *token = tokens;
+ char last_sep = '\0';
+ shunk_t alg_ptr = prop;
+ do {
+ if (token + 1 >= tokens+elemsof(tokens)) {
+ /* space for NULL? */
+ proposal_error(parser, "proposal too long");
+ return false;
+ }
+ /* find the next alg */
+ shunk_t alg = shunk_strsep(&alg_ptr, "-;,");
+ *token++ = (struct token) {
+ .alg = alg,
+ .sep = last_sep,
+ };
+ last_sep = alg.ptr[alg.len]; /* save separator */
+ } while (alg_ptr.len > 0);
+ struct v1_proposal proposal = {
+ .protocol = parser->protocol,
+ };
+ if (!parser_proposals_add(parser, tokens, proposal,
+ proposals)) {
+ passert(parser->error[0] != '\0');
+ return false;
+ }
+ } while (prop_ptr.len > 0);
+ return true;
+}
diff -Naur libreswan-3.27-orig/lib/libswan/v2_proposals.c libreswan-3.27/lib/libswan/v2_proposals.c
--- libreswan-3.27-orig/lib/libswan/v2_proposals.c 1969-12-31 19:00:00.000000000 -0500
+++ libreswan-3.27/lib/libswan/v2_proposals.c 2019-02-15 16:49:23.278267768 -0500
@@ -0,0 +1,398 @@
+/* V2 algorithm proposal parsing, 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 <stdio.h>
+#include <string.h>
+#include <limits.h>
+
+#include "lswlog.h"
+#include "lswalloc.h"
+#include "constants.h"
+#include "proposals.h"
+#include "ike_alg.h"
+#include "ike_alg_integ.h"
+#include "ike_alg_dh.h"
+#include "alg_byname.h"
+
+/*
+ * For all the algorithms, when an algorithm is missing (NULL), and
+ * there are defaults, add them.
+ */
+
+static void merge_algorithms(struct proposal_parser *parser,
+ struct proposal *proposal,
+ enum proposal_algorithm algorithm,
+ const struct ike_alg **defaults)
+{
+ if (defaults == NULL) {
+ return;
+ }
+ if (next_algorithm(proposal, algorithm, NULL) != NULL) {
+ return;
+ }
+ for (const struct ike_alg **alg = defaults; (*alg) != NULL; alg++) {
+ append_algorithm(parser, proposal, algorithm, *alg, 0);
+ }
+}
+
+static bool merge_defaults(struct proposal_parser *parser,
+ struct proposal *proposal)
+{
+ pexpect(parser->policy->version < elemsof(parser->protocol->defaults));
+ const struct proposal_defaults *defaults =
+ parser->protocol->defaults[parser->policy->version];
+ merge_algorithms(parser, proposal, PROPOSAL_encrypt, defaults->encrypt);
+ merge_algorithms(parser, proposal, PROPOSAL_prf, defaults->prf);
+ if (next_algorithm(proposal, PROPOSAL_integ, NULL) == NULL) {
+ if (proposal_encrypt_aead(proposal)) {
+ /*
+ * Since AEAD, integrity is always 'none'.
+ */
+ append_algorithm(parser, proposal, PROPOSAL_integ,
+ &ike_alg_integ_none.common, 0);
+ } else if (defaults->integ != NULL) {
+ /*
+ * Merge in the defaults.
+ */
+ merge_algorithms(parser, proposal, PROPOSAL_integ,
+ defaults->integ);
+ } else if (next_algorithm(proposal, PROPOSAL_prf, NULL) != NULL &&
+ proposal_encrypt_norm(proposal)) {
+ /*
+ * Since non-AEAD, use integrity algorithms
+ * that are implemented using the PRFs.
+ */
+ FOR_EACH_ALGORITHM(proposal, prf, prf) {
+ const struct integ_desc *integ = NULL;
+ for (const struct integ_desc **integp = next_integ_desc(NULL);
+ integp != NULL; integp = next_integ_desc(integp)) {
+ if ((*integp)->prf != NULL &&
+ &(*integp)->prf->common == prf->desc) {
+ integ = *integp;
+ break;
+ }
+ }
+ if (integ == NULL) {
+ proposal_error(parser, "%s integrity derived from PRF '%s' is not supported",
+ parser->protocol->name,
+ prf->desc->name);
+ return false;
+ }
+ append_algorithm(parser, proposal, PROPOSAL_integ,
+ &integ->common, 0);
+ }
+ }
+ }
+ merge_algorithms(parser, proposal, PROPOSAL_dh, defaults->dh);
+ return true;
+}
+
+static bool parse_alg(struct proposal_parser *parser,
+ struct proposal *proposal,
+ enum proposal_algorithm algorithm,
+ alg_byname_fn *alg_byname,
+ shunk_t token, int enckeylen, shunk_t print,
+ const char *what)
+{
+ if (alg_byname == NULL) {
+ /* n/a */
+ return false;
+ }
+ if (token.len == 0) {
+ /* will error at end */
+ return false;
+ }
+ const struct ike_alg *alg = alg_byname(parser, token, enckeylen, print);
+ if (alg == NULL) {
+ if (DBGP(DBG_PROPOSAL_PARSER)) {
+ DBG_log("%s_byname('"PRI_SHUNK"') failed: %s",
+ what, PRI_shunk(token),
+ parser->error);
+ }
+ pexpect(parser->error[0] != '\0');
+ return false;
+ }
+ DBGF(DBG_PROPOSAL_PARSER, "adding %s algorithm %s[_%d]",
+ what, alg->name, enckeylen);
+ append_algorithm(parser, proposal, algorithm, alg, enckeylen);
+ return true;
+}
+
+/*
+ * tokenize <input> into <delim><alg><input>
+ */
+
+struct token {
+ char delim;
+ shunk_t alg;
+ shunk_t input;
+};
+
+static void next(struct token *token)
+{
+ if (token->delim == '\0') {
+ /* first call, set delim to something bogus */
+ token->delim = ' ';
+ } else {
+ token->delim = token->input.ptr != NULL ? token->input.ptr[-1] : ' ';
+ }
+ token->alg = shunk_strsep(&token->input, "-;+");
+ if (DBGP(DBG_PROPOSAL_PARSER)) {
+ if (token->alg.ptr == NULL) {
+ DBG_log("delim: n/a alg: end-of-input");
+ } else {
+ DBG_log("delim: '%c' alg: '"PRI_SHUNK"'",
+ token->delim, PRI_shunk(token->alg));
+ }
+ }
+}
+
+/*
+ * Try to parse any of <ealg>-<ekeylen>, <ealg>_<ekeylen>,
+ * <ealg><ekeylen>, or <ealg> using some look-ahead.
+ */
+
+static int parse_eklen(struct proposal_parser *parser, shunk_t buf)
+{
+ /* convert -<eklen> if present */
+ char *end = NULL;
+ long eklen = strtol(buf.ptr, &end, 10);
+ if (buf.ptr + buf.len != end) {
+ proposal_error(parser, "encryption key length '"PRI_SHUNK"' contains a non-numeric character",
+ PRI_shunk(buf));
+ return 0;
+ }
+ if (eklen >= INT_MAX) {
+ proposal_error(parser, "encryption key length '"PRI_SHUNK"' WAY too big",
+ PRI_shunk(buf));
+ return 0;
+ }
+ if (eklen == 0) {
+ proposal_error(parser, "encryption key length is zero");
+ return 0;
+ }
+ return eklen;
+}
+
+static bool parse_encrypt(struct proposal_parser *parser,
+ struct proposal *proposal, struct token *token)
+{
+ alg_byname_fn *alg_byname = parser->protocol->encrypt_alg_byname;
+ if (alg_byname == NULL) {
+ return false;
+ }
+ if (token->alg.len == 0) {
+ return false;
+ }
+ shunk_t ealg = token->alg;
+ /* try <ealg=token>-<eklen=lookahead> using look-ahead? */
+ struct token lookahead = *token;
+ next(&lookahead);
+ if (lookahead.delim == '-' &&
+ lookahead.alg.len > 0 &&
+ isdigit(lookahead.alg.ptr[0])) {
+ shunk_t eklen = lookahead.alg;
+ /* assume <ealg>-<eklen> */
+ int enckeylen = parse_eklen(parser, eklen);
+ if (enckeylen <= 0) {
+ pexpect(parser->error[0] != '\0');
+ return false;
+ }
+ /* print "<ealg>-<eklen>" in errors */
+ shunk_t print_name = shunk2(ealg.ptr, eklen.ptr + eklen.len - ealg.ptr);
+ if (!parse_alg(parser, proposal, PROPOSAL_encrypt, alg_byname,
+ ealg, enckeylen, print_name, "encrypt")) {
+ return false;
+ }
+ *token = lookahead;
+ return true;
+ }
+ /* try <ealg> (no key len) */
+ shunk_t print_name = token->alg;
+ if (!parse_alg(parser, proposal, PROPOSAL_encrypt, alg_byname,
+ ealg, 0, print_name, "encrypt")) {
+ /*
+ * Could it be <ealg><eklen> or <ealg>_<eklen>? Work
+ * backwards skipping any digits.
+ */
+ shunk_t end = shunk2(ealg.ptr + ealg.len, 0);
+ while (end.ptr > ealg.ptr && isdigit(end.ptr[-1])) {
+ end.ptr--;
+ end.len++;
+ }
+ if (end.len == 0) {
+ /*
+ * no trailing <eklen> and <ealg> was rejected
+ */
+ pexpect(parser->error[0] != '\0');
+ return false;
+ }
+ /* try to convert */
+ int enckeylen = parse_eklen(parser, end);
+ if (enckeylen <= 0) {
+ pexpect(parser->error[0] != '\0');
+ return false;
+ }
+ /*
+ * trim <eklen> from <ealg>; and then trim any
+ * trailing '_'
+ */
+ ealg.len = end.ptr - ealg.ptr;
+ if (end.ptr > ealg.ptr && end.ptr[-1] == '_') {
+ ealg.len -= 1;
+ }
+ /* try again */
+ if (!parse_alg(parser, proposal, PROPOSAL_encrypt, alg_byname,
+ ealg, enckeylen, print_name, "encrypt")) {
+ return false;
+ }
+ }
+ return true;
+}
+
+static bool parse_proposal(struct proposal_parser *parser,
+ struct proposals *proposals UNUSED, shunk_t input)
+{
+ if (DBGP(DBG_PROPOSAL_PARSER)) {
+ DBG_log("proposal: '"PRI_SHUNK"'", PRI_shunk(input));
+ }
+
+ char error[sizeof(parser->error)] = "";
+ struct proposal *proposal = alloc_proposal(parser);
+
+ struct token token = {
+ .input = input,
+ };
+ next(&token);
+ /*
+ * Encryption is not optional.
+ */
+ bool lookup_encrypt = parser->protocol->encrypt_alg_byname != NULL;
+ if (lookup_encrypt) {
+ if (!parse_encrypt(parser, proposal, &token)) {
+ free_proposal(&proposal);
+ return false;
+ }
+ error[0] = parser->error[0] = '\0';
+ next(&token);
+ while (token.delim == '+' &&
+ parse_encrypt(parser, proposal, &token)) {
+ error[0] = parser->error[0] = '\0';
+ next(&token);
+ }
+ }
+#define PARSE_ALG(STOP, ALG) \
+ if (error[0] == '\0' && parser->error[0] != '\0') { \
+ strcpy(error, parser->error); \
+ DBGF(DBG_PROPOSAL_PARSER, "saved first error: %s", error); \
+ } \
+ if (token.delim != STOP && \
+ parse_alg(parser, proposal, PROPOSAL_##ALG, \
+ parser->protocol->ALG##_alg_byname, \
+ token.alg, 0, token.alg, #ALG)) { \
+ error[0] = parser->error[0] = '\0'; \
+ next(&token); \
+ while (token.delim == '+' && \
+ parse_alg(parser, proposal, PROPOSAL_##ALG, \
+ parser->protocol->ALG##_alg_byname, \
+ token.alg, 0, token.alg, #ALG)) { \
+ error[0] = parser->error[0] = '\0'; \
+ next(&token); \
+ } \
+ }
+ PARSE_ALG(';', prf);
+ /*
+ * By default, don't allow ike=...-<prf>-<integ>-... but do
+ * allow esp=...-<integ>. In the case of IKE, when integrity
+ * is required, it is filled in using the PRF.
+ *
+ * XXX: The parser and output isn't consistent in that for ESP
+ * it parses <encry>-<integ> but for IKE it parses
+ * <encr>-<prf>. This seems to lead to confusion when
+ * printing proposals - ike=aes_gcm-sha1 gets mis-read as as
+ * using sha1 as integrity. ike-aes_gcm-none-sha1 would
+ * clarify this but that makes for a fun parse.
+ */
+ if (parser->protocol->prf_alg_byname == NULL ||
+ IMPAIR(PROPOSAL_PARSER)) {
+ PARSE_ALG(';', integ);
+ }
+ PARSE_ALG('\0', dh);
+ if (error[0] != '\0') {
+ DBGF(DBG_PROPOSAL_PARSER, "return first error: %s", error);
+ free_proposal(&proposal);
+ strcpy(parser->error, error);
+ return false;
+ }
+ if (parser->error[0] != '\0') {
+ DBGF(DBG_PROPOSAL_PARSER, "return last error: %s", parser->error);
+ free_proposal(&proposal);
+ return false;
+ }
+ if (token.alg.ptr != NULL) {
+ proposal_error(parser, "'"PRI_SHUNK"' unexpected",
+ PRI_shunk(token.alg));
+ free_proposal(&proposal);
+ return false;
+ }
+ if (!IMPAIR(PROPOSAL_PARSER) &&
+ !merge_defaults(parser, proposal)) {
+ free_proposal(&proposal);
+ return false;
+ }
+ /* back end? */
+ if (!parser->protocol->proposal_ok(parser, proposal)) {
+ free_proposal(&proposal);
+ return false;
+ }
+ append_proposal(proposals, &proposal);
+ return true;
+}
+
+bool v2_proposals_parse_str(struct proposal_parser *parser,
+ struct proposals *proposals,
+ shunk_t input)
+{
+ DBG(DBG_PROPOSAL_PARSER,
+ DBG_log("parsing '"PRI_SHUNK"' for %s",
+ PRI_shunk(input), parser->protocol->name));
+
+ /* use default if no string */
+ if (input.ptr == NULL) {
+ struct proposal *proposal = alloc_proposal(parser);
+ if (!merge_defaults(parser, proposal)) {
+ free_proposal(&proposal);
+ return false;
+ }
+ append_proposal(proposals, &proposal);
+ return true;
+ }
+
+ if (input.len == 0) {
+ /* XXX: hack to keep testsuite happy */
+ proposal_error(parser, "String ended with invalid char, just after \"\"");
+ return false;
+ }
+
+ do {
+ /* find the next proposal */
+ shunk_t proposal = shunk_strsep(&input, ",");
+ if (!parse_proposal(parser, proposals, proposal)) {
+ pexpect(parser->error[0] != '\0');
+ return false;
+ }
+ } while (input.len > 0);
+ return true;
+}
diff -Naur libreswan-3.27-orig/programs/algparse/algparse.c libreswan-3.27/programs/algparse/algparse.c
--- libreswan-3.27-orig/programs/algparse/algparse.c 2018-10-07 22:52:09.000000000 -0400
+++ libreswan-3.27/programs/algparse/algparse.c 2019-02-15 16:49:23.278267768 -0500
@@ -9,15 +9,15 @@
#include "lswconf.h"
#include "ike_alg.h"
-#include "alg_info.h"
+#include "proposals.h"
static bool test_proposals = false;
static bool test_algs = false;
static bool verbose = false;
static bool debug = false;
static bool impair = false;
-static bool ikev1 = false;
-static bool ikev2 = false;
+static enum ike_version ike_version = IKEv2;
+static unsigned parser_version = 0;
static bool fips = false;
static bool pfs = false;
static int failures = 0;
@@ -25,23 +25,23 @@
enum status { PASSED = 0, FAILED = 1, ERROR = 126, };
enum expect { FAIL = false, PASS = true, COUNT, };
-#define CHECK(TYPE,PARSE,OK) { \
+#define CHECK(CHECK,PARSE,OK) { \
struct proposal_policy policy = { \
- .ikev1 = ikev1, \
- .ikev2 = ikev2, \
+ .version = ike_version, \
+ .parser_version = parser_version, \
.alg_is_ok = OK, \
.pfs = pfs, \
.warning = warning, \
+ .check_pfs_vs_dh = CHECK, \
}; \
printf("algparse "); \
if (fips) { \
printf("-fips "); \
} \
- if (ikev1) { \
- printf("-v1 "); \
- } \
- if (ikev2) { \
- printf("-v2 "); \
+ switch (ike_version) { \
+ case IKEv1: printf("-v1 "); break; \
+ case IKEv2: printf("-v2 "); break; \
+ default: break; \
} \
if (pfs) { \
printf("-pfs "); \
@@ -52,21 +52,19 @@
printf("'%s=%s'\n", #PARSE, algstr); \
} \
fflush(NULL); \
- char err_buf[512] = ""; /* ??? big enough? */ \
- struct alg_info_##TYPE *e = \
- alg_info_##PARSE##_create_from_str(&policy, \
- algstr, \
- err_buf, \
- sizeof(err_buf)); \
- if (e != NULL) { \
- passert(err_buf[0] == '\0'); \
- FOR_EACH_PROPOSAL_INFO(&e->ai, proposal) { \
+ struct proposal_parser *parser = \
+ PARSE##_proposal_parser(&policy); \
+ struct proposals *proposals = \
+ proposals_from_str(parser, algstr); \
+ if (proposals != NULL) { \
+ pexpect(parser->error[0] == '\0'); \
+ FOR_EACH_PROPOSAL(proposals, proposal) { \
LSWLOG_FILE(stdout, log) { \
lswlogf(log, "\t"); \
- lswlog_proposal_info(log, proposal); \
+ fmt_proposal(log, proposal); \
} \
} \
- alg_info_free(&e->ai); \
+ proposals_delref(&proposals); \
if (expected == FAIL) { \
failures++; \
fprintf(stderr, \
@@ -76,8 +74,8 @@
algstr == NULL ? "" : algstr); \
} \
} else { \
- passert(err_buf[0]); \
- printf("\tERROR: %s\n", err_buf); \
+ pexpect(parser->error[0]); \
+ printf("\tERROR: %s\n", parser->error); \
if (expected == PASS) { \
failures++; \
fprintf(stderr, \
@@ -89,6 +87,7 @@
failures++; \
} \
} \
+ free_proposal_parser(&parser); \
fflush(NULL); \
}
@@ -122,17 +121,17 @@
static void esp(enum expect expected, const char *algstr)
{
- CHECK(esp, esp, kernel_alg_is_ok);
+ CHECK(true, esp, kernel_alg_is_ok);
}
static void ah(enum expect expected, const char *algstr)
{
- CHECK(esp, ah, kernel_alg_is_ok);
+ CHECK(true, ah, kernel_alg_is_ok);
}
static void ike(enum expect expected, const char *algstr)
{
- CHECK(ike, ike, ike_alg_is_ike);
+ CHECK(false, ike, ike_alg_is_ike);
}
typedef void (protocol_t)(enum expect expected, const char *);
@@ -203,8 +202,8 @@
esp(!fips, "3des-sha1;modp1024");
esp(!fips, "3des-sha1;modp1536");
esp(true, "3des-sha1;modp2048");
- esp(!ikev1, "3des-sha1;dh21");
- esp(!ikev1, "3des-sha1;ecp_521");
+ esp(ike_version == IKEv2, "3des-sha1;dh21");
+ esp(ike_version == IKEv2, "3des-sha1;ecp_521");
esp(false, "3des-sha1;dh23");
esp(false, "3des-sha1;dh24");
esp(true, "3des-sha1");
@@ -218,7 +217,7 @@
esp(true, "aes-sha384");
esp(true, "aes-sha512");
esp(true, "aes128-sha1");
- esp(true, "aes128-aes_xcbc");
+ esp(!fips, "aes128-aes_xcbc");
esp(true, "aes192-sha1");
esp(true, "aes256-sha1");
esp(true, "aes256-sha");
@@ -300,18 +299,18 @@
esp(!fips, "twofish");
esp(!fips, "camellia_cbc_256-hmac_sha2_512_256;modp8192"); /* long */
- esp(!fips, "null_auth_aes_gmac_256-null;modp8192"); /* long */
+ esp(true, "null_auth_aes_gmac_256-null;modp8192"); /* long */
esp(true, "3des-sha1;modp8192"); /* allow ';' when unambigious */
esp(true, "3des-sha1-modp8192"); /* allow '-' when unambigious */
esp(!pfs, "aes-sha1,3des-sha1;modp8192");
esp(true, "aes-sha1-modp8192,3des-sha1-modp8192"); /* silly */
esp(true, "aes-sha1-modp8192,aes-sha1-modp8192,aes-sha1-modp8192"); /* suppress duplicates */
- esp(!ikev1, "aes;none");
- esp(!ikev1 && !pfs, "aes;none,aes");
- esp(!ikev1, "aes;none,aes;modp2048");
- esp(!ikev1, "aes-sha1-none");
- esp(!ikev1, "aes-sha1;none");
+ esp(ike_version == IKEv2, "aes;none");
+ esp(ike_version == IKEv2 && !pfs, "aes;none,aes");
+ esp(ike_version == IKEv2, "aes;none,aes;modp2048");
+ esp(ike_version == IKEv2, "aes-sha1-none");
+ esp(ike_version == IKEv2, "aes-sha1;none");
/*
* should this be supported - for now man page says not
@@ -374,9 +373,9 @@
ah(true, "sha2_256");
ah(true, "sha2_384");
ah(true, "sha2_512");
- ah(true, "aes_xcbc");
- ah(!ikev1, "sha2-none");
- ah(!ikev1, "sha2;none");
+ ah(!fips, "aes_xcbc");
+ ah(ike_version == IKEv2, "sha2-none");
+ ah(ike_version == IKEv2, "sha2;none");
ah(true, "sha1-modp8192,sha1-modp8192,sha1-modp8192"); /* suppress duplicates */
ah(impair, "aes-sha1");
ah(false, "vanityhash1");
@@ -400,12 +399,15 @@
ike(true, "3des;dh21");
ike(true, "3des-sha1;dh21");
ike(true, "3des-sha1-ecp_521");
- ike(!ikev1, "aes_gcm");
+ ike(ike_version == IKEv2, "aes_gcm");
ike(true, "aes-sha1-modp8192,aes-sha1-modp8192,aes-sha1-modp8192"); /* suppress duplicates */
ike(false, "aes;none");
ike(false, "id2"); /* should be rejected; idXXX removed */
ike(false, "3des-id2"); /* should be rejected; idXXX removed */
ike(false, "aes_ccm"); /* ESP/AH only */
+ ike(impair, "aes_gcm-sha1-none-modp2048");
+ ike(impair, "aes_gcm+aes_gcm-sha1-none-modp2048");
+ ike(false, "aes+aes_gcm"); /* mixing AEAD and NORM encryption */
}
static void usage(void)
@@ -432,9 +434,8 @@
"\n"
"Additional options:\n"
"\n"
- " -v1 | -ikev1: require IKEv1 support\n"
- " -v2 | -ikev2: require IKEv2 support\n"
- " default: require either IKEv1 or IKEv2 support\n"
+ " -v2 | -ikev2: configure for IKEv2 (default)\n"
+ " -v1 | -ikev1: configure for IKEv1\n"
" -pfs | -pfs=yes | -pfs=no: specify PFS (perfect forward privicy)\n"
" default: no\n"
" -fips | -fips=yes | -fips=no: force NSS's FIPS mode\n"
@@ -446,6 +447,8 @@
" -v --verbose: be more verbose\n"
" -d --debug: enable debug logging\n"
" -i --impair: disable all algorithm parser checks\n"
+ " -p1: simple parser\n"
+ " -p2: complex parser\n"
"\n"
"Examples:\n"
"\n"
@@ -483,10 +486,14 @@
test_proposals = true;
} else if (streq(arg, "ta")) {
test_algs = true;
+ } else if (streq(arg, "p1")) {
+ parser_version = 1;
+ } else if (streq(arg, "p2")) {
+ parser_version = 2;
} else if (streq(arg, "v1") || streq(arg, "ikev1")) {
- ikev1 = true;
+ ike_version = IKEv1;
} else if (streq(arg, "v2") || streq(arg, "ikev2")) {
- ikev2 = true;
+ ike_version = IKEv2;
} else if (streq(arg, "pfs") || streq(arg, "pfs=yes") || streq(arg, "pfs=on")) {
pfs = true;
} else if (streq(arg, "pfs=no") || streq(arg, "pfs=off")) {
diff -Naur libreswan-3.27-orig/programs/pluto/connections.c libreswan-3.27/programs/pluto/connections.c
--- libreswan-3.27-orig/programs/pluto/connections.c 2019-02-15 16:31:43.031408048 -0500
+++ libreswan-3.27/programs/pluto/connections.c 2019-02-15 16:32:28.986835407 -0500
@@ -69,7 +69,7 @@
#include "peerlog.h"
#include "keys.h"
#include "whack.h"
-#include "alg_info.h"
+#include "proposals.h"
#include "spdb.h"
#include "ike_alg.h"
#include "kernel_alg.h"
@@ -352,17 +352,13 @@
sr = next_sr;
}
- if (c->alg_info_ike != NULL) {
- alg_info_delref(&c->alg_info_ike->ai);
- c->alg_info_ike = NULL;
- }
- free_ikev2_proposals(&c->ike_proposals);
+ proposals_delref(&c->ike_proposals.p);
+ proposals_delref(&c->child_proposals.p);
- if (c->alg_info_esp != NULL) {
- alg_info_delref(&c->alg_info_esp->ai);
- c->alg_info_esp = NULL;
- }
- free_ikev2_proposals(&c->esp_or_ah_proposals);
+ free_ikev2_proposals(&c->v2_ike_proposals);
+ free_ikev2_proposals(&c->v2_ike_auth_child_proposals);
+ free_ikev2_proposals(&c->v2_create_child_proposals);
+ c->v2_create_child_proposals_default_dh = NULL; /* static pointer */
pfree(c);
}
@@ -807,11 +803,8 @@
}
/* increment references to algo's, if any */
- if (c->alg_info_ike != NULL)
- alg_info_addref(&c->alg_info_ike->ai);
-
- if (c->alg_info_esp != NULL)
- alg_info_addref(&c->alg_info_esp->ai);
+ proposals_addref(&c->ike_proposals.p);
+ proposals_addref(&c->child_proposals.p);
if (c->pool != NULL)
reference_addresspool(c);
@@ -1496,8 +1489,6 @@
c->connalias = wm->connalias;
c->dnshostname = wm->dnshostname;
c->policy = wm->policy;
- c->alg_info_ike = NULL;
- c->alg_info_esp = NULL;
c->sighash_policy = wm->sighash_policy;
if (NEVER_NEGOTIATE(c->policy)) {
@@ -1556,49 +1547,35 @@
/* IKE cipher suites */
if (!LIN(POLICY_AUTH_NEVER, wm->policy) && wm->ike != NULL) {
- char err_buf[256] = ""; /* ??? big enough? */
const struct proposal_policy proposal_policy = {
- .ikev1 = LIN(POLICY_IKEV1_ALLOW, wm->policy),
- /*
- * logic needs to match pick_initiator()
- *
- * XXX: Once pluto is changed to IKEv1 XOR
- * IKEv2 it should be possible to move this
- * magic into pluto proper and instead pass a
- * simple boolean.
- */
- .ikev2 = LIN(POLICY_IKEV2_PROPOSE | POLICY_IKEV2_ALLOW, wm->policy),
+ /* * logic needs to match pick_initiator() */
+ .version = LIN(POLICY_IKEV2_ALLOW, wm->policy) ? IKEv2 : IKEv1,
.alg_is_ok = ike_alg_is_ike,
.pfs = LIN(POLICY_PFS, wm->policy),
+ .check_pfs_vs_dh = false,
.warning = libreswan_log,
};
- c->alg_info_ike = alg_info_ike_create_from_str(&proposal_policy, wm->ike,
- err_buf, sizeof(err_buf));
+ struct proposal_parser *parser = ike_proposal_parser(&proposal_policy);
+ c->ike_proposals.p = proposals_from_str(parser, wm->ike);
- if (c->alg_info_ike == NULL) {
- pexpect(err_buf[0]); /* something */
+ if (c->ike_proposals.p == NULL) {
+ pexpect(parser->error[0]); /* something */
loglog(RC_FATAL, "Failed to add connection \"%s\": ike string error: %s",
- wm->name, err_buf);
+ wm->name, parser->error);
+ free_proposal_parser(&parser);
pfree(c);
return;
}
+ free_proposal_parser(&parser);
- /* from here on, error returns should alg_info_free(&c->alg_info_ike->ai); */
+ /* from here on, error returns should alg_info_free(&c->ike_proposals->ai); */
LSWDBGP(DBG_CRYPT | DBG_CONTROL, buf) {
lswlogs(buf, "ike (phase1) algorithm values: ");
- lswlog_alg_info(buf, &c->alg_info_ike->ai);
+ fmt_proposals(buf, c->ike_proposals.p);
};
- if (c->alg_info_ike->ai.alg_info_cnt == 0) {
- loglog(RC_FATAL,
- "Failed to add connection \"%s\": got 0 transforms for ike=\"%s\"",
- wm->name, wm->ike);
- alg_info_free(&c->alg_info_ike->ai);
- pfree(c);
- return;
- }
}
/* ESP or AH cipher suites (but not both) */
@@ -1607,10 +1584,7 @@
DBG(DBG_CONTROL,
DBG_log("from whack: got --esp=%s", wm->esp));
- char err_buf[256] = ""; /* ??? big enough? */
-
const struct proposal_policy proposal_policy = {
- .ikev1 = LIN(POLICY_IKEV1_ALLOW, wm->policy),
/*
* logic needs to match pick_initiator()
*
@@ -1619,11 +1593,16 @@
* magic into pluto proper and instead pass a
* simple boolean.
*/
- .ikev2 = LIN(POLICY_IKEV2_PROPOSE | POLICY_IKEV2_ALLOW, wm->policy),
+ .version = LIN(POLICY_IKEV2_ALLOW, wm->policy) ? IKEv2 : IKEv1,
.alg_is_ok = kernel_alg_is_ok,
.pfs = LIN(POLICY_PFS, wm->policy),
+ .check_pfs_vs_dh = true,
.warning = libreswan_log,
};
+ struct proposal_parser *(*fn)(const struct proposal_policy *policy) =
+ (c->policy & POLICY_ENCRYPT ? esp_proposal_parser :
+ ah_proposal_parser);
+ struct proposal_parser *parser = fn(&proposal_policy);
/*
* We checked above that exactly one of
@@ -1632,42 +1611,22 @@
* function is called (and those functions are
* almost identical).
*/
- c->alg_info_esp =
- /* function: */
- (c->policy & POLICY_ENCRYPT ?
- alg_info_esp_create_from_str :
- alg_info_ah_create_from_str)
- /* arguments: */
- (&proposal_policy,
- wm->esp, err_buf, sizeof(err_buf));
-
- if (c->alg_info_esp == NULL) {
+ c->child_proposals.p = proposals_from_str(parser, wm->esp);
+ if (c->child_proposals.p == NULL) {
loglog(RC_FATAL,
"Failed to add connection \"%s\", esp=\"%s\" is invalid: %s",
- wm->name, wm->esp, err_buf);
- if (c->alg_info_ike != NULL)
- alg_info_free(&c->alg_info_ike->ai);
+ wm->name, wm->esp, parser->error);
+ free_proposal_parser(&parser);
pfree(c);
return;
}
+ free_proposal_parser(&parser);
- /* from here on, error returns should alg_info_free(&c->alg_info_esp->ai); */
-
- if (c->alg_info_esp->ai.alg_info_cnt == 0) {
- loglog(RC_FATAL,
- "Failed to add connection \"%s\", esp=\"%s\" contained 0 valid transforms",
- wm->name, wm->esp);
- if (c->alg_info_ike != NULL)
- alg_info_free(&c->alg_info_ike->ai);
- if (c->alg_info_esp != NULL) \
- alg_info_free(&c->alg_info_esp->ai);
- pfree(c);
- return;
- }
+ /* from here on, error returns should alg_info_free(&c->child_proposals->ai); */
LSWDBGP(DBG_CONTROL, buf) {
lswlogs(buf, "ESP/AH string values: ");
- lswlog_alg_info(buf, &c->alg_info_esp->ai);
+ fmt_proposals(buf, c->child_proposals.p);
};
}
diff -Naur libreswan-3.27-orig/programs/pluto/connections.h libreswan-3.27/programs/pluto/connections.h
--- libreswan-3.27-orig/programs/pluto/connections.h 2018-10-07 22:52:09.000000000 -0400
+++ libreswan-3.27/programs/pluto/connections.h 2019-02-15 16:32:28.986835407 -0500
@@ -29,6 +29,7 @@
#define CONNECTIONS_H
#include "fd.h"
+#include "proposals.h"
/* There are two kinds of connections:
* - ISAKMP connections, between hosts (for IKE communication)
@@ -318,8 +319,8 @@
/* if multiple policies, next one to apply */
struct connection *policy_next;
- struct alg_info_esp *alg_info_esp; /* ??? OK for AH too? */
- struct alg_info_ike *alg_info_ike;
+ struct ike_proposals ike_proposals;
+ struct child_proposals child_proposals;
/*
* The ALG_INFO converted to IKEv2 format.
@@ -327,9 +328,23 @@
* Since they are allocated on-demand so there's no need to
* worry about copying them when a connection object gets
* cloned.
+ *
+ * For a child SA, two different proposals are used:
+ *
+ * - during the IKE_AUTH exchange a proposal stripped of any
+ * DH (it uses keying material from the IKE SA's SKSEED).
+ *
+ * - during a CREATE_CHILD_SA exchange, a mash up of the
+ * proposal and the IKE SA's DH algorithm. Since the IKE
+ * SA's DH can change, it too is saved so a rebuild can be
+ * triggered.
+ *
+ * XXX: has to be a better way?
*/
- struct ikev2_proposals *ike_proposals;
- struct ikev2_proposals *esp_or_ah_proposals;
+ struct ikev2_proposals *v2_ike_proposals;
+ struct ikev2_proposals *v2_ike_auth_child_proposals;
+ struct ikev2_proposals *v2_create_child_proposals;
+ const struct oakley_group_desc *v2_create_child_proposals_default_dh;
/* host_pair linkage */
struct host_pair *host_pair;
diff -Naur libreswan-3.27-orig/programs/pluto/crypto.c libreswan-3.27/programs/pluto/crypto.c
--- libreswan-3.27-orig/programs/pluto/crypto.c 2018-10-07 22:52:09.000000000 -0400
+++ libreswan-3.27/programs/pluto/crypto.c 2019-02-15 16:32:28.987835416 -0500
@@ -33,11 +33,12 @@
#include "state.h"
#include "log.h"
#include "crypto.h"
-#include "alg_info.h"
+#include "proposals.h"
#include "ike_alg.h"
#include "test_buffer.h"
#include "connections.h"
+#include "ike_alg_integ.h"
#include "kernel_alg.h"
/*
@@ -47,7 +48,7 @@
*/
void ike_alg_show_connection(const struct connection *c, const char *instance)
{
- if (c->alg_info_ike != NULL) {
+ if (c->ike_proposals.p != NULL) {
/*
* List the algorithms as found in alg_info_ike and as
* will be fed into the proposal code.
@@ -79,30 +80,46 @@
LSWLOG_WHACK(RC_COMMENT, buf) {
lswlogf(buf, "\"%s\"%s: IKE algorithms: ",
c->name, instance);
- lswlog_alg_info(buf, &c->alg_info_ike->ai);
+ fmt_proposals(buf, c->ike_proposals.p);
}
}
const struct state *st = state_with_serialno(c->newest_isakmp_sa);
if (st != NULL) {
- /*
- * Convert the crypt-suite into 'struct proposal_info'
- * so that the parser's print-alg code can be used.
- */
- const struct proposal_info p = {
- .encrypt = st->st_oakley.ta_encrypt,
- .enckeylen = st->st_oakley.enckeylen,
- .prf = st->st_oakley.ta_prf,
- .integ = st->st_oakley.ta_integ,
- .dh = st->st_oakley.ta_dh,
- };
- const char *v = st->st_ikev2 ? "IKEv2" : "IKE";
LSWLOG_WHACK(RC_COMMENT, buf) {
lswlogf(buf,
"\"%s\"%s: %s algorithm newest: ",
- c->name, instance, v);
- lswlog_proposal_info(buf, &p);
+ c->name, instance,
+ "IKE");
+ const struct trans_attrs *ta = &st->st_oakley;
+ const char *sep = "";
+ if (ta->ta_encrypt != NULL) {
+ lswlogs(buf, sep); sep = "-";
+ lswlogs(buf, ta->ta_encrypt->common.fqn);
+ if (ta->enckeylen != 0) {
+ lswlogf(buf, "_%d", ta->enckeylen);
+ }
+ }
+ if (ta->ta_prf != NULL) {
+ lswlogs(buf, sep); sep = "-";
+ lswlogs(buf, ta->ta_prf->common.fqn);
+ }
+ /* XXX: should just print everything */
+ if (ta->ta_integ != NULL) {
+ if ((ta->ta_prf == NULL) ||
+ (encrypt_desc_is_aead(ta->ta_encrypt) &&
+ ta->ta_integ != &ike_alg_integ_none) ||
+ (!encrypt_desc_is_aead(ta->ta_encrypt) &&
+ ta->ta_integ->prf != ta->ta_prf)) {
+ lswlogs(buf, sep); sep = "-";
+ lswlogs(buf, ta->ta_integ->common.fqn);
+ }
+ }
+ if (ta->ta_dh != NULL) {
+ lswlogs(buf, sep); sep = "-";
+ lswlogs(buf, ta->ta_dh->common.fqn);
+ }
}
}
}
diff -Naur libreswan-3.27-orig/programs/pluto/db_ops.c libreswan-3.27/programs/pluto/db_ops.c
--- libreswan-3.27-orig/programs/pluto/db_ops.c 2018-10-07 22:52:09.000000000 -0400
+++ libreswan-3.27/programs/pluto/db_ops.c 2019-02-15 16:32:28.987835416 -0500
@@ -62,6 +62,7 @@
#include "defs.h"
#include "state.h"
#include "packet.h"
+#include "proposals.h"
#include "spdb.h"
#include "db_ops.h"
#include "log.h"
diff -Naur libreswan-3.27-orig/programs/pluto/hmac.c libreswan-3.27/programs/pluto/hmac.c
--- libreswan-3.27-orig/programs/pluto/hmac.c 2018-10-07 22:52:09.000000000 -0400
+++ libreswan-3.27/programs/pluto/hmac.c 2019-02-15 16:32:28.988835425 -0500
@@ -27,7 +27,7 @@
#include "constants.h"
#include "defs.h"
#include "crypto.h"
-#include "alg_info.h"
+#include "proposals.h"
#include "ike_alg.h"
#include <nss.h>
diff -Naur libreswan-3.27-orig/programs/pluto/hostpair.c libreswan-3.27/programs/pluto/hostpair.c
--- libreswan-3.27-orig/programs/pluto/hostpair.c 2018-10-07 22:52:09.000000000 -0400
+++ libreswan-3.27/programs/pluto/hostpair.c 2019-02-15 16:32:28.988835425 -0500
@@ -57,7 +57,7 @@
#include "log.h"
#include "keys.h"
#include "whack.h"
-#include "alg_info.h"
+#include "proposals.h"
#include "spdb.h"
#include "ike_alg.h"
#include "kernel_alg.h"
diff -Naur libreswan-3.27-orig/programs/pluto/ikev1_aggr.c libreswan-3.27/programs/pluto/ikev1_aggr.c
--- libreswan-3.27-orig/programs/pluto/ikev1_aggr.c 2018-10-07 22:52:09.000000000 -0400
+++ libreswan-3.27/programs/pluto/ikev1_aggr.c 2019-02-15 16:32:28.989835435 -0500
@@ -24,7 +24,7 @@
#include "constants.h" /* for dup_any()!?! ... */
#include "lswlog.h"
-#include "alg_info.h"
+#include "proposals.h"
#include "defs.h"
#include "state.h"
diff -Naur libreswan-3.27-orig/programs/pluto/ikev1.h libreswan-3.27/programs/pluto/ikev1.h
--- libreswan-3.27-orig/programs/pluto/ikev1.h 2018-10-07 22:52:09.000000000 -0400
+++ libreswan-3.27/programs/pluto/ikev1.h 2019-02-15 16:32:28.989835435 -0500
@@ -6,11 +6,14 @@
#include "packet.h" /* for pb_stream */
#include "fd.h"
+struct child_proposals;
+struct ike_proposals;
+
/* ikev1.c */
extern void init_ikev1(void);
-const struct oakley_group_desc *ikev1_quick_pfs(struct alg_info_esp *aie);
+const struct oakley_group_desc *ikev1_quick_pfs(const struct child_proposals proposals);
void ikev1_init_out_pbs_echo_hdr(struct msg_digest *md, bool enc, uint8_t np,
pb_stream *output_stream, uint8_t *output_buffer,
diff -Naur libreswan-3.27-orig/programs/pluto/ikev1_quick.c libreswan-3.27/programs/pluto/ikev1_quick.c
--- libreswan-3.27-orig/programs/pluto/ikev1_quick.c 2018-10-07 22:52:09.000000000 -0400
+++ libreswan-3.27/programs/pluto/ikev1_quick.c 2019-02-15 16:32:28.990835444 -0500
@@ -79,20 +79,22 @@
#include "virtual.h" /* needs connections.h */
#include "ikev1_dpd.h"
#include "pluto_x509.h"
-#include "alg_info.h"
+#include "proposals.h"
#include "ip_address.h"
#include <blapit.h>
-const struct oakley_group_desc *ikev1_quick_pfs(struct alg_info_esp *aie)
+const struct oakley_group_desc *ikev1_quick_pfs(const struct child_proposals proposals)
{
- if (aie == NULL) {
+ if (proposals.p == NULL) {
return NULL;
}
- if (aie->ai.alg_info_cnt == 0) {
+ struct proposal *proposal = next_proposal(proposals.p, NULL);
+ struct algorithm *dh = next_algorithm(proposal, PROPOSAL_dh, NULL);
+ if (dh == NULL) {
return NULL;
}
- return aie->ai.proposals[0].dh;
+ return dh_desc(dh->desc);
}
/* accept_PFS_KE
@@ -816,7 +818,7 @@
* use that group.
* if not, fallback to old use-same-as-P1 behaviour
*/
- st->st_pfs_group = ikev1_quick_pfs(c->alg_info_esp);
+ st->st_pfs_group = ikev1_quick_pfs(c->child_proposals);
/* otherwise, use the same group as during Phase 1:
* since no negotiation is possible, we pick one that is
* very likely supported.
@@ -832,8 +834,8 @@
}
lswlogf(buf, " {using isakmp#%lu msgid:%08" PRIx32 " proposal=",
isakmp_sa->st_serialno, st->st_msgid);
- if (st->st_connection->alg_info_esp != NULL) {
- lswlog_alg_info(buf, &st->st_connection->alg_info_esp->ai);
+ if (st->st_connection->child_proposals.p != NULL) {
+ fmt_proposals(buf, st->st_connection->child_proposals.p);
} else {
lswlogf(buf, "defaults");
}
diff -Naur libreswan-3.27-orig/programs/pluto/ikev1_spdb_struct.c libreswan-3.27/programs/pluto/ikev1_spdb_struct.c
--- libreswan-3.27-orig/programs/pluto/ikev1_spdb_struct.c 2018-10-07 22:52:09.000000000 -0400
+++ libreswan-3.27/programs/pluto/ikev1_spdb_struct.c 2019-02-15 16:32:28.991835453 -0500
@@ -47,7 +47,7 @@
#include "crypto.h"
#include "ikev1.h"
-#include "alg_info.h"
+#include "proposals.h"
#include "kernel_alg.h"
#include "ike_alg.h"
#include "ike_alg_encrypt.h"
@@ -305,17 +305,18 @@
return false;
}
- if (c->alg_info_esp== NULL) {
+ if (c->child_proposals.p == NULL) {
DBGF(DBG_CONTROL, "ESP IPsec Transform verified unconditionally; no alg_info to check against");
return true;
}
- FOR_EACH_ESP_INFO(c->alg_info_esp, esp_info) {
- if (esp_info->encrypt == ta->ta_encrypt &&
- (esp_info->enckeylen == 0 ||
- ta->enckeylen == 0 ||
- esp_info->enckeylen == ta->enckeylen) &&
- esp_info->integ == ta->ta_integ) {
+ FOR_EACH_PROPOSAL(c->child_proposals.p, proposal) {
+ struct v1_proposal algs = v1_proposal(proposal);
+ if (algs.encrypt == ta->ta_encrypt &&
+ (algs.enckeylen == 0 ||
+ ta->enckeylen == 0 ||
+ algs.enckeylen == ta->enckeylen) &&
+ algs.integ == ta->ta_integ) {
DBG(DBG_CONTROL,
DBG_log("ESP IPsec Transform verified; matches alg_info entry"));
return true;
@@ -351,14 +352,15 @@
ta->ta_dh->common.fqn);
return false;
}
- if (c->alg_info_esp == NULL) {
+ if (c->child_proposals.p == NULL) {
DBG(DBG_CONTROL,
DBG_log("AH IPsec Transform verified unconditionally; no alg_info to check against"));
return true;
}
- FOR_EACH_ESP_INFO(c->alg_info_esp, esp_info) { /* really AH */
- if (esp_info->integ == ta->ta_integ) {
+ FOR_EACH_PROPOSAL(c->child_proposals.p, proposal) { /* really AH */
+ struct v1_proposal algs = v1_proposal(proposal);
+ if (algs.integ == ta->ta_integ) {
DBG(DBG_CONTROL,
DBG_log("ESP IPsec Transform verified; matches alg_info entry"));
return true;
@@ -401,12 +403,12 @@
* Aggr-Mode - Max transforms == 2 - Multiple
* transforms, 1 DH group
*/
- revised_sadb = oakley_alg_makedb(st->st_connection->alg_info_ike,
+ revised_sadb = oakley_alg_makedb(st->st_connection->ike_proposals,
auth_method,
aggressive_mode);
} else {
revised_sadb = kernel_alg_makedb(st->st_connection->policy,
- st->st_connection->alg_info_esp,
+ st->st_connection->child_proposals,
TRUE);
/* add IPcomp proposal if policy asks for it */
@@ -984,7 +986,7 @@
}
static bool ikev1_verify_ike(const struct trans_attrs *ta,
- struct alg_info_ike *alg_info_ike)
+ struct ike_proposals ike_proposals)
{
if (ta->ta_encrypt == NULL) {
loglog(RC_LOG_SERIOUS,
@@ -1005,7 +1007,7 @@
loglog(RC_LOG_SERIOUS, "OAKLEY proposal refused: missing DH");
return false;
}
- if (alg_info_ike == NULL) {
+ if (ike_proposals.p == NULL) {
DBG(DBG_CONTROL,
DBG_log("OAKLEY proposal verified unconditionally; no alg_info to check against"));
return true;
@@ -1016,14 +1018,14 @@
* if specified in "esp" string
*/
bool ealg_insecure = (ta->enckeylen < 128);
-
- FOR_EACH_IKE_INFO(alg_info_ike, ike_info) {
- if (ike_info->encrypt == ta->ta_encrypt &&
- (ike_info->enckeylen == 0 ||
+ FOR_EACH_PROPOSAL(ike_proposals.p, proposal) {
+ struct v1_proposal algs = v1_proposal(proposal);
+ if (algs.encrypt == ta->ta_encrypt &&
+ (algs.enckeylen == 0 ||
ta->enckeylen == 0 ||
- ike_info->enckeylen == ta->enckeylen) &&
- ike_info->prf == ta->ta_prf &&
- ike_info->dh == ta->ta_dh) {
+ algs.enckeylen == ta->enckeylen) &&
+ algs.prf == ta->ta_prf &&
+ algs.dh == ta->ta_dh) {
if (ealg_insecure) {
loglog(RC_LOG_SERIOUS,
"You should NOT use insecure/broken IKE algorithms (%s)!",
@@ -1522,7 +1524,7 @@
}
/*
* check if this keylen is compatible
- * with specified alg_info_ike.
+ * with specified ike_proposals.
*/
if (!encrypt_has_key_bit_length(ta.ta_encrypt, val)) {
ugh = "peer proposed key_len not valid for encrypt algo setup specified";
@@ -1584,9 +1586,9 @@
}
/*
- * ML: at last check for allowed transforms in alg_info_ike
+ * ML: at last check for allowed transforms in ike_proposals
*/
- if (!ikev1_verify_ike(&ta, c->alg_info_ike)) {
+ if (!ikev1_verify_ike(&ta, c->ike_proposals)) {
/*
* already logged; UGH acts as a skip
* rest of checks flag
@@ -1715,7 +1717,7 @@
const struct connection *c = st->st_connection;
/*
- * Construct the proposals by combining ALG_INFO_IKE with the
+ * Construct the proposals by combining IKE_PROPOSALS with the
* AUTH (proof of identity) extracted from the aggressive mode
* SADB. As if by magic, attrs[2] is always the
* authentication method.
@@ -1733,7 +1735,7 @@
* Max transforms == 2 - Multiple transforms, 1 DH
* group
*/
- revised_sadb = oakley_alg_makedb(c->alg_info_ike,
+ revised_sadb = oakley_alg_makedb(c->ike_proposals,
auth_method, TRUE);
}
diff -Naur libreswan-3.27-orig/programs/pluto/ikev2.c libreswan-3.27/programs/pluto/ikev2.c
--- libreswan-3.27-orig/programs/pluto/ikev2.c 2018-10-07 22:52:09.000000000 -0400
+++ libreswan-3.27/programs/pluto/ikev2.c 2019-02-15 16:32:28.993835472 -0500
@@ -68,7 +68,7 @@
#include "vendor.h"
#include "ip_address.h"
#include "ikev2_send.h"
-#include "alg_info.h" /* for ike_info / esp_info */
+#include "proposals.h" /* for ike_info / esp_info */
#include "ietf_constants.h"
diff -Naur libreswan-3.27-orig/programs/pluto/ikev2_crypto.c libreswan-3.27/programs/pluto/ikev2_crypto.c
--- libreswan-3.27-orig/programs/pluto/ikev2_crypto.c 2018-10-07 22:52:09.000000000 -0400
+++ libreswan-3.27/programs/pluto/ikev2_crypto.c 2019-02-15 16:32:28.993835472 -0500
@@ -52,7 +52,7 @@
#include "ikev2.h"
#include "ikev2_prf.h"
#include "ike_alg.h"
-#include "alg_info.h"
+#include "proposals.h"
#include "kernel_alg.h"
#include "crypt_symkey.h"
#include "ikev2_prf.h"
diff -Naur libreswan-3.27-orig/programs/pluto/ikev2.h libreswan-3.27/programs/pluto/ikev2.h
--- libreswan-3.27-orig/programs/pluto/ikev2.h 2018-10-07 22:52:09.000000000 -0400
+++ libreswan-3.27/programs/pluto/ikev2.h 2019-02-15 16:32:28.994835481 -0500
@@ -97,11 +97,27 @@
void free_ikev2_proposal(struct ikev2_proposal **proposal);
void free_ikev2_proposals(struct ikev2_proposals **proposals);
-void ikev2_need_ike_proposals(struct connection *c, const char *why);
+/*
+ * On-demand, generate proposals for either the IKE SA or the CHILD
+ * SA.
+ *
+ * For CHILD SAs, two different proposal suites are used: during the
+ * IKE_AUTH exchange a stripped down proposal that excludes DH; and
+ * during the CREATE_CHILD_SA exchange DH a mashed up proposal that
+ * can include the IKE SA's latest DH.
+ *
+ * This is done on-demand as, only at the point where the IKE or CHILD
+ * SA is being instantiated, is it clear what proposals are needed.
+ * For instance, when a CHILD SA shares an existing IKE SA, the CHILD
+ * won't need IKE proposals but will need the IKE SA's DH.
+ *
+ * XXX: Should the CREATE CHILD SA proposals be stored in the state?
+ */
-void ikev2_need_esp_or_ah_proposals(struct connection *c,
- const char *why,
- const struct oakley_group_desc *default_dh);
+struct ikev2_proposals *get_v2_ike_proposals(struct connection *c, const char *why);
+struct ikev2_proposals *get_v2_ike_auth_child_proposals(struct connection *c, const char *why);
+struct ikev2_proposals *get_v2_create_child_proposals(struct connection *c, const char *why,
+ const struct oakley_group_desc *default_dh);
bool ikev2_emit_sa_proposal(pb_stream *pbs,
const struct ikev2_proposal *proposal,
diff -Naur libreswan-3.27-orig/programs/pluto/ikev2_parent.c libreswan-3.27/programs/pluto/ikev2_parent.c
--- libreswan-3.27-orig/programs/pluto/ikev2_parent.c 2018-10-07 22:52:09.000000000 -0400
+++ libreswan-3.27/programs/pluto/ikev2_parent.c 2019-02-15 16:32:28.996835500 -0500
@@ -67,7 +67,7 @@
#include "pending.h"
#include "kernel.h"
#include "nat_traversal.h"
-#include "alg_info.h" /* for ike_info / esp_info */
+#include "proposals.h" /* for ike_info / esp_info */
#include "key.h" /* for SECKEY_DestroyPublicKey */
#include "vendor.h"
#include "crypt_hash.h"
@@ -848,8 +848,9 @@
* Initialize st->st_oakley, including the group number.
* Grab the DH group from the first configured proposal and build KE.
*/
- ikev2_need_ike_proposals(c, "IKE SA initiator selecting KE");
- st->st_oakley.ta_dh = ikev2_proposals_first_dh(c->ike_proposals);
+ struct ikev2_proposals *ike_proposals =
+ get_v2_ike_proposals(c, "IKE SA initiator selecting KE");
+ st->st_oakley.ta_dh = ikev2_proposals_first_dh(ike_proposals);
if (st->st_oakley.ta_dh == NULL) {
libreswan_log("proposals do not contain a valid DH");
delete_state(st); /* pops state? */
@@ -991,7 +992,8 @@
}
/* SA out */
{
- ikev2_need_ike_proposals(c, "IKE SA initiator emitting local proposals");
+ struct ikev2_proposals *ike_proposals =
+ get_v2_ike_proposals(c, "IKE SA initiator emitting local proposals");
/*
* Since this is an initial IKE exchange, the SPI is
* emitted as is part of the packet header and not the
@@ -999,7 +1001,7 @@
*/
u_char *sa_start = rbody.cur;
bool ret = ikev2_emit_sa_proposals(&rbody,
- c->ike_proposals,
+ ike_proposals,
(chunk_t*)NULL);
if (!ret) {
libreswan_log("outsa fail");
@@ -1328,7 +1330,8 @@
}
/* Get the proposals ready. */
- ikev2_need_ike_proposals(c, "IKE SA responder matching remote proposals");
+ struct ikev2_proposals *ike_proposals =
+ get_v2_ike_proposals(c, "IKE SA responder matching remote proposals");
/*
* Select the proposal.
@@ -1342,7 +1345,7 @@
/*expect_accepted*/ FALSE,
LIN(POLICY_OPPORTUNISTIC, c->policy),
&accepted_ike_proposal,
- c->ike_proposals);
+ ike_proposals);
if (ret != STF_OK)
return ret;
@@ -1812,9 +1815,10 @@
pstats(invalidke_recv_s, sg.sg_group);
pstats(invalidke_recv_u, st->st_oakley.ta_dh->group);
- ikev2_need_ike_proposals(c, "IKE SA initiator validating remote's suggested KE");
+ struct ikev2_proposals *ike_proposals =
+ get_v2_ike_proposals(c, "IKE SA initiator validating remote's suggested KE");
- if (ikev2_proposals_include_modp(c->ike_proposals, sg.sg_group)) {
+ if (ikev2_proposals_include_modp(ike_proposals, sg.sg_group)) {
DBG(DBG_CONTROLMORE, DBG_log("Suggested modp group is acceptable"));
/*
* Since there must be a group object
@@ -2081,7 +2085,9 @@
/* SA body in and out */
struct payload_digest *const sa_pd =
md->chain[ISAKMP_NEXT_v2SA];
- ikev2_need_ike_proposals(c, "IKE SA initiator accepting remote proposal");
+ struct ikev2_proposals *ike_proposals =
+ get_v2_ike_proposals(c, "IKE SA initiator accepting remote proposal");
+
stf_status ret = ikev2_process_sa_payload("IKE initiator (accepting)",
&sa_pd->pbs,
@@ -2090,7 +2096,7 @@
/*expect_accepted*/ TRUE,
LIN(POLICY_OPPORTUNISTIC, c->policy),
&st->st_accepted_ike_proposal,
- c->ike_proposals);
+ ike_proposals);
if (ret != STF_OK) {
DBG(DBG_CONTROLMORE, DBG_log("ikev2_parse_parent_sa_body() failed in ikev2_parent_inR1outI2()"));
return ret;
@@ -3564,17 +3570,13 @@
sizeof(proto_info->our_spi));
/*
- * UNSET_GROUP means strip DH from the proposal. A
- * CHILD_SA established during an AUTH exchange does
+ * A CHILD_SA established during an AUTH exchange does
* not propose DH - the IKE SA's SKEYSEED is always
* used.
*/
- free_ikev2_proposals(&cc->esp_or_ah_proposals);
- ikev2_need_esp_or_ah_proposals(cc,
- "IKE SA initiator emitting ESP/AH proposals",
- &unset_group);
-
- if (!ikev2_emit_sa_proposals(&e_pbs_cipher, cc->esp_or_ah_proposals,
+ struct ikev2_proposals *child_proposals =
+ get_v2_ike_auth_child_proposals(cc, "IKE SA initiator emitting ESP/AH proposals");
+ if (!ikev2_emit_sa_proposals(&e_pbs_cipher, child_proposals,
&local_spi))
return STF_INTERNAL_ERROR;
@@ -4374,31 +4376,25 @@
stf_status ret;
char *what;
- const struct oakley_group_desc *default_dh;
+ struct ikev2_proposals *child_proposals;
if (isa_xchg == ISAKMP_v2_CREATE_CHILD_SA) {
if (st->st_state == STATE_V2_CREATE_I) {
what = "ESP/AH initiator accepting remote proposal";
} else {
what = "ESP/AH responder matching remote proposals";
}
- default_dh = (c->policy & POLICY_PFS) != LEMPTY
+ const struct oakley_group_desc *default_dh = (c->policy & POLICY_PFS) != LEMPTY
? ike->sa.st_oakley.ta_dh
: &ike_alg_dh_none;
+ child_proposals = get_v2_create_child_proposals(c, what, default_dh);
} else if (expect_accepted) {
- what = "IKE SA initiator accepting remote ESP/AH proposal";
- default_dh = &unset_group; /* no DH */
+ what = "IKE_AUTH initiator accepting remote ESP/AH proposal";
+ child_proposals = get_v2_ike_auth_child_proposals(c, what);
} else {
- what = "IKE SA responder matching remote ESP/AH proposals";
- default_dh = &unset_group; /* no DH */
- }
-
- if (!expect_accepted) {
- /* preparing to initiate or parse a request flush old ones */
- free_ikev2_proposals(&c->esp_or_ah_proposals);
+ what = "IKE_AUTH responder matching remote ESP/AH proposals";
+ child_proposals = get_v2_ike_auth_child_proposals(c, what);
}
- ikev2_need_esp_or_ah_proposals(c, what, default_dh);
-
ret = ikev2_process_sa_payload(what,
&sa_pd->pbs,
/*expect_ike*/ FALSE,
@@ -4406,7 +4402,7 @@
expect_accepted,
LIN(POLICY_OPPORTUNISTIC, c->policy),
&st->st_accepted_esp_or_ah_proposal,
- c->esp_or_ah_proposals);
+ child_proposals);
if (ret != STF_OK) {
LSWLOG_RC(RC_LOG_SERIOUS, buf) {
@@ -5217,8 +5213,8 @@
chunk_t local_spi;
setchunk(local_spi, (uint8_t*)&proto_info->our_spi,
sizeof(proto_info->our_spi));
-
- if (!ikev2_emit_sa_proposals(outpbs, cc->esp_or_ah_proposals,
+ passert(cc->v2_create_child_proposals != NULL);
+ if (!ikev2_emit_sa_proposals(outpbs, cc->v2_create_child_proposals,
&local_spi))
return STF_INTERNAL_ERROR;
@@ -5312,12 +5308,11 @@
sizeof(st->st_icookie));
local_nonce = st->st_ni;
- /* ??? why do we need to free the previous proposals? */
- free_ikev2_proposals(&c->ike_proposals);
- ikev2_need_ike_proposals(c, "IKE SA initiating rekey");
+ struct ikev2_proposals *ike_proposals =
+ get_v2_ike_proposals(c, "IKE SA initiating rekey");
/* send v2 IKE SAs*/
- if (!ikev2_emit_sa_proposals(outpbs, c->ike_proposals, &local_spi)) {
+ if (!ikev2_emit_sa_proposals(outpbs, ike_proposals, &local_spi)) {
libreswan_log("outsa fail");
DBG(DBG_CONTROL, DBG_log("problem emitting connection ike proposals in CREATE_CHILD_SA"));
return STF_INTERNAL_ERROR;
@@ -5379,7 +5374,8 @@
struct payload_digest *const sa_pd = md->chain[ISAKMP_NEXT_v2SA];
/* Get the proposals ready. */
- ikev2_need_ike_proposals(c, "IKE SA accept response to rekey");
+ struct ikev2_proposals *ike_proposals =
+ get_v2_ike_proposals(c, "IKE SA accept response to rekey");
stf_status ret = ikev2_process_sa_payload("IKE initiator (accepting)",
&sa_pd->pbs,
@@ -5388,7 +5384,7 @@
/*expect_accepted*/ TRUE,
LIN(POLICY_OPPORTUNISTIC, c->policy),
&st->st_accepted_ike_proposal,
- c->ike_proposals);
+ ike_proposals);
if (ret != STF_OK) {
DBG(DBG_CONTROLMORE, DBG_log("failed to accept IKE SA, REKEY, response, in process_ike_rekey_sa_pl_response"));
return ret;
@@ -5424,7 +5420,8 @@
struct payload_digest *const sa_pd = md->chain[ISAKMP_NEXT_v2SA];
/* Get the proposals ready. */
- ikev2_need_ike_proposals(c, "IKE SA responding to rekey");
+ struct ikev2_proposals *ike_proposals =
+ get_v2_ike_proposals(c, "IKE SA responding to rekey");
struct ikev2_proposal *accepted_ike_proposal = NULL;
stf_status ret = ikev2_process_sa_payload("IKE Rekey responder child",
@@ -5434,7 +5431,7 @@
/*expect_accepted*/ FALSE,
LIN(POLICY_OPPORTUNISTIC, c->policy),
&accepted_ike_proposal,
- c->ike_proposals);
+ ike_proposals);
if (ret != STF_OK)
return ret;
@@ -6677,21 +6674,17 @@
if (sa_type == IPSEC_SA) {
const struct state *rst = state_with_serialno(p->replacing);
- /*
- * Because the proposal generated during AUTH won't contain DH,
- * always force the proposal to be re-generated here. Not the
- * most efficient, fix probably means moving the proposals to
- * the state object.
- */
- free_ikev2_proposals(&c->esp_or_ah_proposals);
const struct oakley_group_desc *default_dh =
c->policy & POLICY_PFS ? ike->sa.st_oakley.ta_dh : NULL;
- ikev2_need_esp_or_ah_proposals(c,
- "ESP/AH initiator emitting proposals",
- default_dh);
+ struct ikev2_proposals *child_proposals =
+ get_v2_create_child_proposals(c,
+ "ESP/AH initiator emitting proposals",
+ default_dh);
+ /* see ikev2_child_add_ipsec_payloads */
+ passert(c->v2_create_child_proposals != NULL);
- st->st_pfs_group = ikev2_proposals_first_dh(c->esp_or_ah_proposals);
+ st->st_pfs_group = ikev2_proposals_first_dh(child_proposals);
DBG(DBG_CONTROLMORE, {
const char *pfsgroupname = st->st_pfs_group == NULL ?
diff -Naur libreswan-3.27-orig/programs/pluto/ikev2_spdb_struct.c libreswan-3.27/programs/pluto/ikev2_spdb_struct.c
--- libreswan-3.27-orig/programs/pluto/ikev2_spdb_struct.c 2018-10-07 22:52:09.000000000 -0400
+++ libreswan-3.27/programs/pluto/ikev2_spdb_struct.c 2019-02-15 16:32:28.998835518 -0500
@@ -51,7 +51,7 @@
#include "crypto.h"
-#include "alg_info.h"
+#include "proposals.h"
#include "kernel_alg.h"
#include "ike_alg.h"
#include "ike_alg_integ.h"
@@ -264,7 +264,7 @@
*
* PROPNUM is an int.
*/
-#define FOR_EACH_PROPOSAL(PROPNUM, PROPOSAL, PROPOSALS) \
+#define FOR_EACH_V2_PROPOSAL(PROPNUM, PROPOSAL, PROPOSALS) \
for ((PROPNUM) = 1, \
(PROPOSAL) = &(PROPOSALS)->proposal[(PROPNUM)]; \
(PROPNUM) < (PROPOSALS)->roof; \
@@ -276,7 +276,7 @@
*
* PROPNUM, BASE, BOUND are all ints.
*/
-#define FOR_EACH_PROPOSAL_IN_RANGE(PROPNUM, PROPOSAL, PROPOSALS, BASE, BOUND) \
+#define FOR_EACH_V2_PROPOSAL_IN_RANGE(PROPNUM, PROPOSAL, PROPOSALS, BASE, BOUND) \
for ((PROPNUM) = ((BASE) > 0 ? (BASE) : 1), \
(PROPOSAL) = &(PROPOSALS)->proposal[(PROPNUM)]; \
(PROPNUM) < (BOUND) && (PROPNUM) < (PROPOSALS)->roof; \
@@ -395,7 +395,7 @@
const char *proposal_sep = "";
int propnum;
const struct ikev2_proposal *proposal;
- FOR_EACH_PROPOSAL(propnum, proposal, proposals) {
+ FOR_EACH_V2_PROPOSAL(propnum, proposal, proposals) {
lswlogs(buf, proposal_sep);
proposal_sep = " ";
print_proposal(buf, propnum, proposal);
@@ -443,8 +443,8 @@
{
int local_propnum;
const struct ikev2_proposal *local_proposal;
- FOR_EACH_PROPOSAL_IN_RANGE(local_propnum, local_proposal, local_proposals,
- local_propnum_base, local_propnum_bound) {
+ FOR_EACH_V2_PROPOSAL_IN_RANGE(local_propnum, local_proposal, local_proposals,
+ local_propnum_base, local_propnum_bound) {
struct ikev2_proposal_match *matching_local_proposal = &matching_local_proposals[local_propnum];
/* clear matched */
matching_local_proposal->matched_transform_types = LEMPTY;
@@ -579,8 +579,8 @@
*/
int local_propnum;
struct ikev2_proposal *local_proposal;
- FOR_EACH_PROPOSAL_IN_RANGE(local_propnum, local_proposal, local_proposals,
- local_propnum_base, local_propnum_bound) {
+ FOR_EACH_V2_PROPOSAL_IN_RANGE(local_propnum, local_proposal, local_proposals,
+ local_propnum_base, local_propnum_bound) {
if (local_proposal->protoid == remote_protoid) {
/*
* Search the proposal for transforms of this
@@ -680,8 +680,8 @@
int local_propnum;
struct ikev2_proposal *local_proposal;
- FOR_EACH_PROPOSAL_IN_RANGE(local_propnum, local_proposal, local_proposals,
- local_propnum_base, local_propnum_bound) {
+ FOR_EACH_V2_PROPOSAL_IN_RANGE(local_propnum, local_proposal, local_proposals,
+ local_propnum_base, local_propnum_bound) {
struct ikev2_proposal_match *matching_local_proposal = &matching_local_proposals[local_propnum];
LSWDBGP(DBG_CONTROLMORE, log) {
lswlogf(log, "comparing remote proposal %u containing ",
@@ -834,7 +834,7 @@
{
int local_propnum;
struct ikev2_proposal *local_proposal;
- FOR_EACH_PROPOSAL(local_propnum, local_proposal, local_proposals) {
+ FOR_EACH_V2_PROPOSAL(local_propnum, local_proposal, local_proposals) {
struct ikev2_proposal_match *matching_local_proposal = &matching_local_proposals[local_propnum];
enum ikev2_trans_type type;
struct ikev2_transforms *local_transforms;
@@ -1156,7 +1156,7 @@
*
* Must be freed by this function.
*/
- stf_status status;
+ stf_status status = STF_FAIL; /* initialized just to silence gcc -Og */
LSWBUF(remote_print_buf) {
int matching_local_propnum = ikev2_process_proposals(sa_payload,
expect_ike, expect_spi,
@@ -1448,7 +1448,7 @@
int propnum;
const struct ikev2_proposal *proposal;
- FOR_EACH_PROPOSAL(propnum, proposal, proposals) {
+ FOR_EACH_V2_PROPOSAL(propnum, proposal, proposals) {
if (!emit_proposal(&sa_pbs, proposal, propnum, local_spi,
(propnum < proposals->roof - 1
? v2_PROPOSAL_NON_LAST
@@ -1804,9 +1804,9 @@
return TRUE;
}
-static struct ikev2_proposal *ikev2_proposal_from_proposal_info(const struct proposal_info *info,
+static struct ikev2_proposal *ikev2_proposal_from_proposal_info(const struct proposal *proposal,
enum ikev2_sec_proto_id protoid,
- struct ikev2_proposals *proposals,
+ struct ikev2_proposals *v2_proposals,
const struct oakley_group_desc *default_dh)
{
/*
@@ -1814,19 +1814,19 @@
* contain partially constructed stuff from an earlier
* iteration).
*/
- struct ikev2_proposal *proposal = &proposals->proposal[proposals->roof];
- *proposal = (struct ikev2_proposal) {
+ struct ikev2_proposal *v2_proposal = &v2_proposals->proposal[v2_proposals->roof];
+ *v2_proposal = (struct ikev2_proposal) {
.protoid = protoid,
- .propnum = proposals->roof,
+ .propnum = v2_proposals->roof,
};
/*
* Encryption.
*/
- const struct encrypt_desc *encrypt = info->encrypt;
- if (encrypt != NULL) {
- if (!append_encrypt_transform(proposal, encrypt,
- info->enckeylen)) {
+ FOR_EACH_ALGORITHM(proposal, encrypt, alg) {
+ const struct encrypt_desc *encrypt = encrypt_desc(alg->desc);
+ if (!append_encrypt_transform(v2_proposal, encrypt,
+ alg->enckeylen)) {
return NULL;
}
}
@@ -1834,22 +1834,22 @@
/*
* PRF.
*/
- const struct prf_desc *prf = info->prf;
- if (prf != NULL) {
- append_transform(proposal, IKEv2_TRANS_TYPE_PRF,
+ FOR_EACH_ALGORITHM(proposal, prf, alg) {
+ const struct prf_desc *prf = prf_desc(alg->desc);
+ append_transform(v2_proposal, IKEv2_TRANS_TYPE_PRF,
prf->common.id[IKEv2_ALG_ID], 0);
}
/*
* Integrity.
*/
- const struct integ_desc *integ = info->integ;
- if (integ != NULL) {
+ FOR_EACH_ALGORITHM(proposal, integ, alg) {
+ const struct integ_desc *integ = integ_desc(alg->desc);
/*
* While INTEG=NONE is included in the proposal it
* omitted when emitted.
*/
- append_transform(proposal, IKEv2_TRANS_TYPE_INTEG,
+ append_transform(v2_proposal, IKEv2_TRANS_TYPE_INTEG,
integ->common.id[IKEv2_ALG_ID], 0);
}
@@ -1860,20 +1860,25 @@
* happens during the AUTH exchange). Otherwise use either
* the proposed or default DH.
*/
- const struct oakley_group_desc *dh =
- default_dh == &unset_group ? &ike_alg_dh_none
- : info->dh != NULL ? info->dh
- : default_dh;
- if (dh != NULL) {
- /*
- * WHILE DH=NONE is included in the proposal it is
- * omitted when emitted.
- */
- append_transform(proposal, IKEv2_TRANS_TYPE_DH,
- dh->common.id[IKEv2_ALG_ID], 0);
+ if (default_dh == &unset_group) {
+ append_transform(v2_proposal, IKEv2_TRANS_TYPE_DH,
+ ike_alg_dh_none.common.id[IKEv2_ALG_ID], 0);
+ } else if (next_algorithm(proposal, PROPOSAL_dh, NULL) != NULL) {
+ FOR_EACH_ALGORITHM(proposal, dh, alg) {
+ const struct oakley_group_desc *dh = dh_desc(alg->desc);
+ /*
+ * WHILE DH=NONE is included in the proposal it is
+ * omitted when emitted.
+ */
+ append_transform(v2_proposal, IKEv2_TRANS_TYPE_DH,
+ dh->common.id[IKEv2_ALG_ID], 0);
+ }
+ } else if (default_dh != NULL) {
+ append_transform(v2_proposal, IKEv2_TRANS_TYPE_DH,
+ default_dh->common.id[IKEv2_ALG_ID], 0);
}
- return proposal;
+ return v2_proposal;
}
/*
@@ -1993,67 +1998,73 @@
};
/*
- * Ensure c->ike_proposals is filled in. If not, build it.
- *
- * ??? if c->ike_proposals was set for v1 we won't change it.
+ * On-demand compute and return the IKE proposals for the connection.
*
- * WARNING: alg_info_ike is IKEv1
+ * If the default alg_info_ike includes unknown algorithms those get
+ * dropped, which can lead to no proposals.
*
- * If alg_info_ike includes unknown algorithms those get dropped,
- * which can lead to no proposals.
- * c->ike_proposals will not be NULL (see passert).
+ * Never returns NULL (see passert).
*/
-void ikev2_need_ike_proposals(struct connection *c, const char *why) {
- if (c->ike_proposals != NULL) {
- DBGF(DBG_CONTROL, "already constructed local IKE proposals for connection %s (%s)",
- c->name, why);
- return;
+struct ikev2_proposals *get_v2_ike_proposals(struct connection *c, const char *why)
+{
+ if (c->v2_ike_proposals != NULL) {
+ LSWDBGP(DBG_CONTROL, buf) {
+ lswlogf(buf, "using existing local IKE proposals for connection %s (%s): ",
+ c->name, why);
+ print_proposals(buf, c->v2_ike_proposals);
+ }
+ return c->v2_ike_proposals;
}
const char *notes;
- if (c->alg_info_ike == NULL) {
+ if (c->ike_proposals.p == NULL) {
DBGF(DBG_CONTROL, "selecting default constructed local IKE proposals for connection %s (%s)",
c->name, why);
- c->ike_proposals = &default_ikev2_ike_proposals;
+ c->v2_ike_proposals = &default_ikev2_ike_proposals;
notes = " (default)";
} else {
DBGF(DBG_CONTROL, "constructing local IKE proposals for %s (%s)",
c->name, why);
- struct ikev2_proposals *proposals = alloc_thing(struct ikev2_proposals, "proposals");
- int proposals_roof = c->alg_info_ike->ai.alg_info_cnt + 1;
- proposals->proposal = alloc_things(struct ikev2_proposal, proposals_roof, "propsal");
- proposals->on_heap = TRUE;
- proposals->roof = 1;
+ struct ikev2_proposals *v2_proposals = alloc_thing(struct ikev2_proposals,
+ "proposals");
+ /* +1 as proposal[0] is empty */
+ int v2_proposals_roof = nr_proposals(c->ike_proposals.p) + 1;
+ v2_proposals->proposal = alloc_things(struct ikev2_proposal,
+ v2_proposals_roof, "propsal");
+ v2_proposals->on_heap = TRUE;
+ v2_proposals->roof = 1;
- FOR_EACH_IKE_INFO(c->alg_info_ike, ike_info) {
+ FOR_EACH_PROPOSAL(c->ike_proposals.p, ike_info) {
LSWDBGP(DBG_CONTROL, buf) {
lswlogs(buf, "converting ike_info ");
- lswlog_proposal_info(buf, ike_info);
+ fmt_proposal(buf, ike_info);
lswlogs(buf, " to ikev2 ...");
}
- passert(proposals->roof < proposals_roof);
- struct ikev2_proposal *proposal =
- ikev2_proposal_from_proposal_info(ike_info, IKEv2_SEC_PROTO_IKE,
- proposals, NULL);
- if (proposal != NULL) {
+ passert(v2_proposals->roof < v2_proposals_roof);
+ struct ikev2_proposal *v2_proposal =
+ ikev2_proposal_from_proposal_info(ike_info,
+ IKEv2_SEC_PROTO_IKE,
+ v2_proposals, NULL);
+ if (v2_proposal != NULL) {
DBG(DBG_CONTROL,
- DBG_log_ikev2_proposal("... ", proposal));
- proposals->roof++;
+ DBG_log_ikev2_proposal("... ", v2_proposal));
+ v2_proposals->roof++;
}
}
- c->ike_proposals = proposals;
+ c->v2_ike_proposals = v2_proposals;
notes = "";
}
- LSWLOG(buf) {
+ LSWLOG_CONNECTION(c, buf) {
lswlogf(buf, "constructed local IKE proposals for %s (%s): ",
c->name, why);
- print_proposals(buf, c->ike_proposals);
+ print_proposals(buf, c->v2_ike_proposals);
lswlogs(buf, notes);
}
- passert(c->ike_proposals != NULL);
+ passert(c->v2_ike_proposals != NULL);
+ return c->v2_ike_proposals;
}
static struct ikev2_proposal default_ikev2_esp_proposal_missing_esn[] = {
@@ -2143,19 +2154,23 @@
}
}
-void ikev2_need_esp_or_ah_proposals(struct connection *c,
- const char *why,
- const struct oakley_group_desc *default_dh)
+static struct ikev2_proposals *get_v2_child_proposals(struct ikev2_proposals **child_proposals,
+ struct connection *c,
+ const char *why,
+ const struct oakley_group_desc *default_dh)
{
- if (c->esp_or_ah_proposals != NULL) {
- DBGF(DBG_CONTROL, "already constructed local ESP/AH proposals for %s (%s)",
- c->name, why);
- return;
+ if (*child_proposals != NULL) {
+ LSWDBGP(DBG_CONTROL, buf) {
+ lswlogf(buf, "using existing local ESP/AH proposals for %s (%s): ",
+ c->name, why);
+ print_proposals(buf, *child_proposals);
+ }
+ return *child_proposals;
}
const char *notes;
- if (c->alg_info_esp == NULL) {
- DBGF(DBG_CONTROL, "selecting default construvted local ESP/AH proposals for %s (%s)",
+ if (c->child_proposals.p == NULL) {
+ DBGF(DBG_CONTROL, "selecting default local ESP/AH proposals for %s (%s)",
c->name, why);
lset_t esp_ah = c->policy & (POLICY_ENCRYPT | POLICY_AUTHENTICATE);
struct ikev2_proposals *default_proposals_missing_esn;
@@ -2186,38 +2201,38 @@
/*
* Clone the default proposal and add the missing ESN.
*/
- struct ikev2_proposals *proposals = alloc_thing(struct ikev2_proposals,
- "cloned ESP/AH proposals");
- proposals->on_heap = TRUE;
- proposals->roof = default_proposals_missing_esn->roof;
+ struct ikev2_proposals *v2_proposals = alloc_thing(struct ikev2_proposals,
+ "cloned ESP/AH proposals");
+ v2_proposals->on_heap = TRUE;
+ v2_proposals->roof = default_proposals_missing_esn->roof;
if (add_empty_msdh_duplicates) {
/* add space for duplicates, minus the empty first proposal */
- proposals->roof += default_proposals_missing_esn->roof - 1;
+ v2_proposals->roof += default_proposals_missing_esn->roof - 1;
}
- proposals->proposal = alloc_things(struct ikev2_proposal, proposals->roof,
- "ESP/AH proposals");
- memcpy(proposals->proposal, default_proposals_missing_esn->proposal,
- sizeof(proposals->proposal[0]) * default_proposals_missing_esn->roof);
+ v2_proposals->proposal = alloc_things(struct ikev2_proposal, v2_proposals->roof,
+ "ESP/AH proposals");
+ memcpy(v2_proposals->proposal, default_proposals_missing_esn->proposal,
+ sizeof(v2_proposals->proposal[0]) * default_proposals_missing_esn->roof);
if (add_empty_msdh_duplicates) {
/*
* Append duplicates but discarding
* proposal[0] which is filler.
*/
- memcpy(proposals->proposal + default_proposals_missing_esn->roof,
+ memcpy(v2_proposals->proposal + default_proposals_missing_esn->roof,
default_proposals_missing_esn->proposal + 1, /* skip "0" */
- sizeof(proposals->proposal[0]) * (default_proposals_missing_esn->roof - 1));
+ sizeof(v2_proposals->proposal[0]) * (default_proposals_missing_esn->roof - 1));
}
int propnum;
- struct ikev2_proposal *proposal;
- FOR_EACH_PROPOSAL(propnum, proposal, proposals) {
- add_esn_transforms(proposal, c->policy);
+ struct ikev2_proposal *v2_proposal;
+ FOR_EACH_V2_PROPOSAL(propnum, v2_proposal, v2_proposals) {
+ add_esn_transforms(v2_proposal, c->policy);
}
if (default_dh != NULL && default_dh != &unset_group) {
DBGF(DBG_CONTROL, "adding dh %s to default proposals",
default_dh->common.name);
- FOR_EACH_PROPOSAL(propnum, proposal, proposals) {
- append_transform(proposal,
+ FOR_EACH_V2_PROPOSAL(propnum, v2_proposal, v2_proposals) {
+ append_transform(v2_proposal,
IKEv2_TRANS_TYPE_DH,
default_dh->group, 0);
if (propnum >= default_proposals_missing_esn->roof)
@@ -2225,7 +2240,7 @@
break;
}
}
- c->esp_or_ah_proposals = proposals;
+ *child_proposals = v2_proposals;
notes = " (default)";
} else {
LSWDBGP(DBG_CONTROL, buf) {
@@ -2250,17 +2265,18 @@
bool add_empty_msdh_duplicates = (c->policy & POLICY_MSDH_DOWNGRADE) &&
default_dh != &unset_group;
- struct ikev2_proposals *proposals = alloc_thing(struct ikev2_proposals,
- "ESP/AH proposals");
- int proposals_roof = c->alg_info_esp->ai.alg_info_cnt + 1;
+ struct ikev2_proposals *v2_proposals = alloc_thing(struct ikev2_proposals,
+ "ESP/AH proposals");
+ /* proposal[0] is empty so +1 */
+ int v2_proposals_roof = nr_proposals(c->child_proposals.p) + 1;
if (add_empty_msdh_duplicates) {
- /* make space for everything duplicated */
- proposals_roof += c->alg_info_esp->ai.alg_info_cnt;
+ /* make space for everything duplicated; note +1 above */
+ v2_proposals_roof = v2_proposals_roof * 2 - 1;
}
- proposals->proposal = alloc_things(struct ikev2_proposal, proposals_roof,
- "ESP/AH proposal");
- proposals->on_heap = TRUE;
- proposals->roof = 1;
+ v2_proposals->proposal = alloc_things(struct ikev2_proposal, v2_proposals_roof,
+ "ESP/AH proposal");
+ v2_proposals->on_heap = TRUE;
+ v2_proposals->roof = 1;
enum ikev2_sec_proto_id protoid;
switch (c->policy & (POLICY_ENCRYPT | POLICY_AUTHENTICATE)) {
@@ -2275,10 +2291,10 @@
}
for (int dup = 0; dup < (add_empty_msdh_duplicates ? 2 : 1); dup++) {
- FOR_EACH_ESP_INFO(c->alg_info_esp, esp_info) {
+ FOR_EACH_PROPOSAL(c->child_proposals.p, esp_info) {
LSWDBGP(DBG_CONTROL, log) {
lswlogf(log, "converting proposal ");
- lswlog_proposal_info(log, esp_info);
+ fmt_proposal(log, esp_info);
lswlogf(log, " to ikev2 ...");
}
@@ -2286,37 +2302,94 @@
* Get the next proposal with the
* basics filled in.
*/
- passert(proposals->roof < proposals_roof);
- if (dup && default_dh == NULL && esp_info->dh == NULL) {
+ passert(v2_proposals->roof < v2_proposals_roof);
+ if (dup && default_dh == NULL &&
+ next_algorithm(esp_info, PROPOSAL_dh, NULL) == NULL) {
/*
* First pass didn't include DH.
*/
continue;
}
- struct ikev2_proposal *proposal =
- ikev2_proposal_from_proposal_info(esp_info, protoid,
- proposals,
+ struct ikev2_proposal *v2_proposal =
+ ikev2_proposal_from_proposal_info(esp_info,
+ protoid,
+ v2_proposals,
dup ? &unset_group : default_dh);
- if (proposal != NULL) {
- add_esn_transforms(proposal, c->policy);
+ if (v2_proposal != NULL) {
+ add_esn_transforms(v2_proposal, c->policy);
DBG(DBG_CONTROL,
- DBG_log_ikev2_proposal("... ", proposal));
- proposals->roof++;
+ DBG_log_ikev2_proposal("... ", v2_proposal));
+ v2_proposals->roof++;
}
}
}
- c->esp_or_ah_proposals = proposals;
+ *child_proposals = v2_proposals;
notes = "";
}
- LSWLOG(buf) {
+ LSWLOG_CONNECTION(c, buf) {
lswlogf(buf, "constructed local ESP/AH proposals for %s (%s): ",
c->name, why);
- print_proposals(buf, c->esp_or_ah_proposals);
+ print_proposals(buf, *child_proposals);
lswlogs(buf, notes);
}
- passert(c->esp_or_ah_proposals != NULL);
+ passert(*child_proposals != NULL);
+ return *child_proposals;
+}
+
+/*
+ * If needed, generate the proposals for a CHILD SA being created
+ * during the IKE_AUTH exchange.
+ *
+ * Since a CHILD_SA established during an IKE_AUTH exchange does not
+ * propose DH (keying material is taken from the IKE SA's SKEYSEED),
+ * DH is stripped from the proposals.
+ *
+ * Since only things that affect this proposal suite are the
+ * connection's .policy bits and the contents .child_proposals, and
+ * modifiying those triggers the creation of a new connection (true?),
+ * the connection can be cached.
+ */
+
+struct ikev2_proposals *get_v2_ike_auth_child_proposals(struct connection *c, const char *why)
+{
+ /* UNSET_GROUP means strip DH from the proposal. */
+ return get_v2_child_proposals(&c->v2_ike_auth_child_proposals, c,
+ why, &unset_group);
+}
+
+/*
+ * If needed, generate the proposals for a CHILD SA being created (or
+ * re-keyed) during a CREATE_CHILD_SA exchange.
+ *
+ * If the proposals do not include DH, and PFS is enabled, then the
+ * DEFAULT_DH (DH used by the IKE SA) is added to all proposals.
+ *
+ * XXX:
+ *
+ * This means that the CHILD SA's proposal suite will change depending
+ * on what DH is negotiated by the IKE SA! Hence the need to save the
+ * DEFAULT_DH and check for change. It should probably be storing the
+ * proposal in the state.
+ *
+ * Horrible.
+ */
+struct ikev2_proposals *get_v2_create_child_proposals(struct connection *c, const char *why,
+ const struct oakley_group_desc *default_dh)
+{
+ if (c->v2_create_child_proposals_default_dh != default_dh) {
+ const char *old_fqn = (c->v2_create_child_proposals_default_dh != NULL
+ ? c->v2_create_child_proposals_default_dh->common.fqn
+ : "no-PFS");
+ const char *new_fqn = default_dh != NULL ? default_dh->common.fqn : "no-PFS";
+ DBGF(DBG_CONTROL, "create child proposal's DH changed from %s to %s, flushing",
+ old_fqn, new_fqn);
+ free_ikev2_proposals(&c->v2_create_child_proposals);
+ c->v2_create_child_proposals_default_dh = default_dh;
+ }
+ return get_v2_child_proposals(&c->v2_create_child_proposals, c, why,
+ c->v2_create_child_proposals_default_dh);
}
struct ipsec_proto_info *ikev2_child_sa_proto_info(struct state *st, lset_t policy)
@@ -2358,7 +2431,7 @@
{
int propnum;
const struct ikev2_proposal *proposal;
- FOR_EACH_PROPOSAL(propnum, proposal, proposals) {
+ FOR_EACH_V2_PROPOSAL(propnum, proposal, proposals) {
const struct ikev2_transforms *transforms = &proposal->transforms[IKEv2_TRANS_TYPE_DH];
int t;
for (t = 0; t < transforms->transform[t].valid; t++) {
@@ -2393,7 +2466,7 @@
{
int propnum;
const struct ikev2_proposal *proposal;
- FOR_EACH_PROPOSAL(propnum, proposal, proposals) {
+ FOR_EACH_V2_PROPOSAL(propnum, proposal, proposals) {
const struct ikev2_transforms *transforms = &proposal->transforms[IKEv2_TRANS_TYPE_DH];
const struct ikev2_transform *transform;
FOR_EACH_TRANSFORM(transform, transforms) {
diff -Naur libreswan-3.27-orig/programs/pluto/initiate.c libreswan-3.27/programs/pluto/initiate.c
--- libreswan-3.27-orig/programs/pluto/initiate.c 2018-10-07 22:52:09.000000000 -0400
+++ libreswan-3.27/programs/pluto/initiate.c 2019-02-15 16:32:28.999835528 -0500
@@ -63,7 +63,7 @@
#include "log.h"
#include "keys.h"
#include "whack.h"
-#include "alg_info.h"
+#include "proposals.h"
#include "spdb.h"
#include "ike_alg.h"
#include "kernel_alg.h"
@@ -287,15 +287,12 @@
/* We will only request an IPsec SA if policy isn't empty
* (ignoring Main Mode items).
* This is a fudge, but not yet important.
- * If we are to proceed asynchronously, whackfd will be NULL_FD.
*/
if (c->policy & (POLICY_ENCRYPT | POLICY_AUTHENTICATE)) {
- struct alg_info_esp *alg = c->alg_info_esp;
- struct db_sa *phase2_sa = kernel_alg_makedb(
- c->policy, alg, TRUE);
-
- if (alg != NULL && phase2_sa == NULL) {
+ struct db_sa *phase2_sa =
+ kernel_alg_makedb(c->policy, c->child_proposals, TRUE);
+ if (c->child_proposals.p != NULL && phase2_sa == NULL) {
whack_log(RC_LOG_SERIOUS,
"cannot initiate: no acceptable kernel algorithms loaded");
reset_cur_connection();
diff -Naur libreswan-3.27-orig/programs/pluto/kernel_bsdkame.c libreswan-3.27/programs/pluto/kernel_bsdkame.c
--- libreswan-3.27-orig/programs/pluto/kernel_bsdkame.c 2018-10-07 22:52:09.000000000 -0400
+++ libreswan-3.27/programs/pluto/kernel_bsdkame.c 2019-02-15 16:32:28.999835528 -0500
@@ -47,7 +47,6 @@
#include "whack.h" /* for RC_LOG_SERIOUS */
#include "packet.h" /* for pb_stream in nat_traversal.h */
#include "nat_traversal.h"
-#include "alg_info.h"
#include "kernel_alg.h"
#include "kernel_sadb.h"
diff -Naur libreswan-3.27-orig/programs/pluto/kernel.c libreswan-3.27/programs/pluto/kernel.c
--- libreswan-3.27-orig/programs/pluto/kernel.c 2018-10-07 22:52:09.000000000 -0400
+++ libreswan-3.27/programs/pluto/kernel.c 2019-02-15 16:32:29.000835537 -0500
@@ -1176,7 +1176,6 @@
}
}
-#include "alg_info.h"
#include "kernel_alg.h"
void set_text_said(char *text_said, const ip_address *dst,
diff -Naur libreswan-3.27-orig/programs/pluto/kernel_klips.c libreswan-3.27/programs/pluto/kernel_klips.c
--- libreswan-3.27-orig/programs/pluto/kernel_klips.c 2018-10-07 22:52:09.000000000 -0400
+++ libreswan-3.27/programs/pluto/kernel_klips.c 2019-02-15 16:32:29.000835537 -0500
@@ -48,7 +48,6 @@
#include "nat_traversal.h"
#include "server.h"
-#include "alg_info.h"
#include "kernel_alg.h"
#include "ip_address.h"
diff -Naur libreswan-3.27-orig/programs/pluto/kernel_mast.c libreswan-3.27/programs/pluto/kernel_mast.c
--- libreswan-3.27-orig/programs/pluto/kernel_mast.c 2018-10-07 22:52:09.000000000 -0400
+++ libreswan-3.27/programs/pluto/kernel_mast.c 2019-02-15 16:32:29.001835546 -0500
@@ -48,7 +48,6 @@
#include "nat_traversal.h"
#include "server.h"
-#include "alg_info.h"
#include "kernel_alg.h"
static int next_free_mast_device = -1;
diff -Naur libreswan-3.27-orig/programs/pluto/kernel_pfkey.c libreswan-3.27/programs/pluto/kernel_pfkey.c
--- libreswan-3.27-orig/programs/pluto/kernel_pfkey.c 2018-10-07 22:52:09.000000000 -0400
+++ libreswan-3.27/programs/pluto/kernel_pfkey.c 2019-02-15 16:32:29.001835546 -0500
@@ -63,7 +63,6 @@
#include "nat_traversal.h"
#include "lsw_select.h"
-#include "alg_info.h"
#include "kernel_alg.h"
#include "ip_address.h"
diff -Naur libreswan-3.27-orig/programs/pluto/plutoalg.c libreswan-3.27/programs/pluto/plutoalg.c
--- libreswan-3.27-orig/programs/pluto/plutoalg.c 2018-10-07 22:52:09.000000000 -0400
+++ libreswan-3.27/programs/pluto/plutoalg.c 2019-02-15 16:32:29.002835556 -0500
@@ -34,7 +34,7 @@
#include "connections.h"
#include "state.h"
#include "kernel_alg.h"
-#include "alg_info.h"
+#include "proposals.h"
#include "ike_alg.h"
#include "ike_alg_integ.h"
#include "ike_alg_encrypt.h"
@@ -47,15 +47,16 @@
#include "ikev1.h" /* for ikev1_quick_dh() */
static bool kernel_alg_db_add(struct db_context *db_ctx,
- const struct proposal_info *esp_info,
+ const struct proposal *proposal,
lset_t policy, bool logit)
{
int ealg_i = SADB_EALG_NONE;
+ struct v1_proposal algs = v1_proposal(proposal);
if (policy & POLICY_ENCRYPT) {
- ealg_i = esp_info->encrypt->common.id[IKEv1_ESP_ID];
+ ealg_i = algs.encrypt->common.id[IKEv1_ESP_ID];
/* already checked by the parser? */
- if (!kernel_alg_encrypt_ok(esp_info->encrypt)) {
+ if (!kernel_alg_encrypt_ok(algs.encrypt)) {
if (logit) {
loglog(RC_LOG_SERIOUS,
"requested kernel enc ealg_id=%d not present",
@@ -68,10 +69,10 @@
}
}
- int aalg_i = esp_info->integ->integ_ikev1_ah_transform;
+ int aalg_i = algs.integ->integ_ikev1_ah_transform;
/* already checked by the parser? */
- if (!kernel_alg_integ_ok(esp_info->integ)) {
+ if (!kernel_alg_integ_ok(algs.integ)) {
DBG_log("kernel_alg_db_add() kernel auth aalg_id=%d not present",
aalg_i);
return FALSE;
@@ -82,32 +83,32 @@
db_trans_add(db_ctx, ealg_i);
/* add ESP auth attr (if present) */
- if (esp_info->integ != &ike_alg_integ_none) {
+ if (algs.integ != &ike_alg_integ_none) {
db_attr_add_values(db_ctx,
AUTH_ALGORITHM,
- esp_info->integ->common.id[IKEv1_ESP_ID]);
+ algs.integ->common.id[IKEv1_ESP_ID]);
}
/* add keylength if specified in esp= string */
- if (esp_info->enckeylen != 0) {
- db_attr_add_values(db_ctx,
- KEY_LENGTH,
- esp_info->enckeylen);
+ if (algs.enckeylen != 0) {
+ db_attr_add_values(db_ctx,
+ KEY_LENGTH,
+ algs.enckeylen);
} else {
/* no key length - if required add default here and add another max entry */
- int def_ks = (esp_info->encrypt->keylen_omitted ? 0
- : esp_info->encrypt->keydeflen);
+ int def_ks = (algs.encrypt->keylen_omitted ? 0
+ : algs.encrypt->keydeflen);
if (def_ks != 0) {
db_attr_add_values(db_ctx, KEY_LENGTH, def_ks);
/* add this trans again with max key size */
- int max_ks = encrypt_max_key_bit_length(esp_info->encrypt);
+ int max_ks = encrypt_max_key_bit_length(algs.encrypt);
if (def_ks != max_ks) {
db_trans_add(db_ctx, ealg_i);
- if (esp_info->integ != &ike_alg_integ_none) {
+ if (algs.integ != &ike_alg_integ_none) {
db_attr_add_values(db_ctx,
AUTH_ALGORITHM,
- esp_info->integ->common.id[IKEv1_ESP_ID]);
+ algs.integ->common.id[IKEv1_ESP_ID]);
}
db_attr_add_values(db_ctx,
KEY_LENGTH,
@@ -120,8 +121,8 @@
db_trans_add(db_ctx, aalg_i);
/* add ESP auth attr */
- db_attr_add_values(db_ctx,
- AUTH_ALGORITHM, esp_info->integ->common.id[IKEv1_ESP_ID]);
+ db_attr_add_values(db_ctx, AUTH_ALGORITHM,
+ algs.integ->common.id[IKEv1_ESP_ID]);
}
return TRUE;
@@ -135,7 +136,7 @@
* for now this function does free() previous returned
* malloced pointer (this quirk allows easier spdb.c change)
*/
-static struct db_context *kernel_alg_db_new(struct alg_info_esp *alg_info,
+static struct db_context *kernel_alg_db_new(struct child_proposals proposals,
lset_t policy, bool logit)
{
unsigned int trans_cnt = 0;
@@ -157,25 +158,24 @@
/*
* Loop: for each element (struct esp_info) of
- * alg_info, if kernel support is present then
+ * proposals, if kernel support is present then
* build the transform (and attrs)
*
- * if NULL alg_info, propose everything ...
+ * if NULL proposals, propose everything ...
*/
bool success = TRUE;
- if (alg_info != NULL) {
- FOR_EACH_ESP_INFO(alg_info, proposal) {
+ if (proposals.p != NULL) {
+ FOR_EACH_PROPOSAL(proposals.p, proposal) {
LSWDBGP(DBG_CONTROL | DBG_EMITTING, buf) {
lswlogs(buf, "adding proposal: ");
- lswlog_proposal_info(buf, proposal);
+ fmt_proposal(buf, proposal);
}
- if (!kernel_alg_db_add(ctx_new, proposal,
- policy, logit))
+ if (!kernel_alg_db_add(ctx_new, proposal, policy, logit))
success = FALSE; /* ??? should we break? */
}
} else {
- PEXPECT_LOG("%s", "alg_info should be non-NULL");
+ PEXPECT_LOG("%s", "proposals should be non-NULL");
}
if (!success) {
@@ -268,7 +268,7 @@
* If this is NULL and PFS is required then callers fall back to using
* the parent's DH algorithm.
*/
- const struct oakley_group_desc *dh = ikev1_quick_pfs(c->alg_info_esp);
+ const struct oakley_group_desc *dh = ikev1_quick_pfs(c->child_proposals);
if (dh != NULL) {
pfsbuf = dh->common.fqn;
} else {
@@ -278,7 +278,7 @@
pfsbuf = "<N/A>";
}
- if (c->alg_info_esp != NULL) {
+ if (c->child_proposals.p != NULL) {
LSWLOG_WHACK(RC_COMMENT, buf) {
/*
* If DH (PFS) was specified in the esp= or
@@ -299,7 +299,7 @@
*/
lswlogf(buf, "\"%s\"%s: %s algorithms: ",
c->name, instance, satype);
- lswlog_alg_info(buf, &c->alg_info_esp->ai);
+ fmt_proposals(buf, c->child_proposals.p);
}
}
@@ -326,10 +326,11 @@
}
}
-struct db_sa *kernel_alg_makedb(lset_t policy, struct alg_info_esp *ei,
+struct db_sa *kernel_alg_makedb(lset_t policy,
+ struct child_proposals proposals,
bool logit)
{
- if (ei == NULL) {
+ if (proposals.p == NULL) {
struct db_sa *sadb;
lset_t pm = POLICY_ENCRYPT | POLICY_AUTHENTICATE;
@@ -344,7 +345,7 @@
return sadb;
}
- struct db_context *dbnew = kernel_alg_db_new(ei, policy, logit);
+ struct db_context *dbnew = kernel_alg_db_new(proposals, policy, logit);
if (dbnew == NULL) {
libreswan_log("failed to translate esp_info to proposal, returning empty");
diff -Naur libreswan-3.27-orig/programs/pluto/spdb.c libreswan-3.27/programs/pluto/spdb.c
--- libreswan-3.27-orig/programs/pluto/spdb.c 2018-10-07 22:52:09.000000000 -0400
+++ libreswan-3.27/programs/pluto/spdb.c 2019-02-15 16:32:29.002835556 -0500
@@ -51,7 +51,6 @@
#include "crypto.h"
-#include "alg_info.h"
#include "kernel_alg.h"
#include "ike_alg.h"
#include "db_ops.h"
diff -Naur libreswan-3.27-orig/programs/pluto/spdb.h libreswan-3.27/programs/pluto/spdb.h
--- libreswan-3.27-orig/programs/pluto/spdb.h 2018-10-07 22:52:09.000000000 -0400
+++ libreswan-3.27/programs/pluto/spdb.h 2019-02-15 16:32:29.002835556 -0500
@@ -171,12 +171,12 @@
struct alg_info_ike;
struct alg_info_esp;
-extern struct db_sa *oakley_alg_makedb(struct alg_info_ike *ai,
+extern struct db_sa *oakley_alg_makedb(const struct ike_proposals proposals,
enum ikev1_auth_method auth_method,
bool single_dh);
extern struct db_sa *kernel_alg_makedb(lset_t policy,
- struct alg_info_esp *ei,
+ const struct child_proposals proposals,
bool logit);
#endif /* _SPDB_H_ */
diff -Naur libreswan-3.27-orig/programs/pluto/spdb_struct.c libreswan-3.27/programs/pluto/spdb_struct.c
--- libreswan-3.27-orig/programs/pluto/spdb_struct.c 2018-10-07 22:52:09.000000000 -0400
+++ libreswan-3.27/programs/pluto/spdb_struct.c 2019-02-15 16:32:29.003835565 -0500
@@ -45,7 +45,6 @@
#include "crypto.h"
-#include "alg_info.h"
#include "kernel_alg.h"
#include "ike_alg.h"
#include "db_ops.h"
@@ -82,30 +81,31 @@
* one DH group.
*/
-static struct db_sa *oakley_alg_mergedb(struct alg_info_ike *ai,
+static struct db_sa *oakley_alg_mergedb(struct ike_proposals ike_proposals,
enum ikev1_auth_method auth_method,
bool single_dh);
-static struct alg_info_ike *ikev1_default_ike_info(void)
+static struct ike_proposals ikev1_default_ike_info(void)
{
static const struct proposal_policy policy = {
- .ikev1 = TRUE,
+ .version = IKEv1,
+ .check_pfs_vs_dh = false,
.alg_is_ok = ike_alg_is_ike,
.warning = libreswan_log,
};
- char err[100];
- struct alg_info_ike *defaults =
- alg_info_ike_create_from_str(&policy, NULL,
- err, sizeof(err));
- if (defaults == NULL) {
- PEXPECT_LOG("Invalid IKEv1 default algorithms: %s", err);
+ struct proposal_parser *parser = ike_proposal_parser(&policy);
+ struct ike_proposals defaults = { .p = proposals_from_str(parser, NULL), };
+ if (defaults.p == NULL) {
+ PEXPECT_LOG("Invalid IKEv1 default algorithms: %s",
+ parser->error);
}
+ free_proposal_parser(&parser);
return defaults;
}
-struct db_sa *oakley_alg_makedb(struct alg_info_ike *ai,
+struct db_sa *oakley_alg_makedb(const struct ike_proposals ike_proposals,
enum ikev1_auth_method auth_method,
bool single_dh)
{
@@ -114,26 +114,25 @@
* standard defaults.
*/
- if (ai == NULL) {
+ if (ike_proposals.p == NULL) {
DBG(DBG_CONTROL, DBG_log(
"no specific IKE algorithms specified - using defaults"));
- struct alg_info_ike *default_info
- = ikev1_default_ike_info();
+ struct ike_proposals default_info = ikev1_default_ike_info();
struct db_sa *new_db = oakley_alg_mergedb(default_info,
auth_method,
single_dh);
- pfree(default_info);
+ proposals_delref(&default_info.p);
return new_db;
} else {
- return oakley_alg_mergedb(ai, auth_method, single_dh);
+ return oakley_alg_mergedb(ike_proposals, auth_method, single_dh);
}
}
-struct db_sa *oakley_alg_mergedb(struct alg_info_ike *ai,
+struct db_sa *oakley_alg_mergedb(struct ike_proposals ike_proposals,
enum ikev1_auth_method auth_method,
bool single_dh)
{
- passert(ai != NULL);
+ passert(ike_proposals.p != NULL);
struct db_sa *gsp = NULL;
@@ -150,26 +149,28 @@
* when creating each item, we will use the first transform
* from the base item as the template.
*/
- FOR_EACH_IKE_INFO(ai, ike_info) {
+ FOR_EACH_PROPOSAL(ike_proposals.p, proposal) {
struct db_sa *emp_sp;
- passert(ike_info->encrypt);
- passert(ike_info->prf);
- passert(ike_info->dh);
-
- unsigned ealg = ike_info->encrypt->common.ikev1_oakley_id;
- unsigned halg = ike_info->prf->common.ikev1_oakley_id;
- unsigned modp = ike_info->dh->group;
- unsigned eklen = ike_info->enckeylen;
+ struct v1_proposal algs = v1_proposal(proposal);
+
+ passert(algs.encrypt != NULL);
+ passert(algs.prf != NULL);
+ passert(algs.dh != NULL);
+
+ unsigned ealg = algs.encrypt->common.ikev1_oakley_id;
+ unsigned halg = algs.prf->common.ikev1_oakley_id;
+ unsigned modp = algs.dh->group;
+ unsigned eklen = algs.enckeylen;
DBG(DBG_CONTROL,
DBG_log("oakley_alg_makedb() processing ealg=%s=%u halg=%s=%u modp=%s=%u eklen=%u",
- ike_info->encrypt->common.name, ealg,
- ike_info->prf->common.name, halg,
- ike_info->dh->common.name, modp,
+ algs.encrypt->common.name, ealg,
+ algs.prf->common.name, halg,
+ algs.dh->common.name, modp,
eklen));
- const struct encrypt_desc *enc_desc = ike_info->encrypt;
+ const struct encrypt_desc *enc_desc = algs.encrypt;
if (eklen != 0 && !encrypt_has_key_bit_length(enc_desc, eklen)) {
PEXPECT_LOG("IKEv1 proposal with ENCRYPT%s (specified) keylen:%d, not valid, should have been dropped",
enc_desc->common.name,
@@ -251,7 +252,7 @@
* a different DH group, we try to deal with this.
*/
if (single_dh && transcnt > 0 &&
- ike_info->dh->group != last_modp) {
+ algs.dh->group != last_modp) {
if (
#ifdef USE_DH2
last_modp == OAKLEY_GROUP_MODP1024 ||
@@ -269,13 +270,13 @@
}
loglog(RC_LOG_SERIOUS,
- "transform (%s,%s,%s keylen %zd) ignored.",
+ "transform (%s,%s,%s keylen %d) ignored.",
enum_name(&oakley_enc_names,
- ike_info->encrypt->common.ikev1_oakley_id),
+ algs.encrypt->common.ikev1_oakley_id),
enum_name(&oakley_hash_names,
- ike_info->prf->common.ikev1_oakley_id),
- ike_info->dh->common.name,
- ike_info->enckeylen);
+ algs.prf->common.ikev1_oakley_id),
+ algs.dh->common.name,
+ algs.enckeylen);
free_sa(&emp_sp);
} else {
/*
@@ -303,9 +304,9 @@
* Exclude 3des et.al. which do not include
* default key lengths in the proposal.
*/
- if (ike_info->enckeylen == 0 &&
- !ike_info->encrypt->keylen_omitted) {
- const struct encrypt_desc *enc_desc = ike_info->encrypt;
+ if (algs.enckeylen == 0 &&
+ !algs.encrypt->keylen_omitted) {
+ const struct encrypt_desc *enc_desc = algs.encrypt;
int def_ks = enc_desc->keydeflen;
passert(def_ks); /* ike=null not supported */
int max_ks = encrypt_max_key_bit_length(enc_desc);
@@ -375,7 +376,7 @@
emp_sp = NULL;
}
}
- last_modp = ike_info->dh->group;
+ last_modp = algs.dh->group;
}
transcnt++;
diff -Naur libreswan-3.27-orig/programs/pluto/terminate.c libreswan-3.27/programs/pluto/terminate.c
--- libreswan-3.27-orig/programs/pluto/terminate.c 2018-10-07 22:52:09.000000000 -0400
+++ libreswan-3.27/programs/pluto/terminate.c 2019-02-15 16:32:29.003835565 -0500
@@ -53,7 +53,6 @@
#include "log.h"
#include "keys.h"
#include "whack.h"
-#include "alg_info.h"
#include "spdb.h"
#include "ike_alg.h"
#include "kernel_alg.h"
diff -Naur libreswan-3.27-orig/programs/spi/spi.c libreswan-3.27/programs/spi/spi.c
--- libreswan-3.27-orig/programs/spi/spi.c 2018-10-07 22:52:09.000000000 -0400
+++ libreswan-3.27/programs/spi/spi.c 2019-02-15 16:32:29.003835565 -0500
@@ -61,7 +61,6 @@
#include "lswlog.h"
#include "lswtool.h"
-#include "alg_info.h"
#include "kernel_alg.h"
#include "kernel_sadb.h"
#include "pfkey_help.h"
diff -Naur libreswan-3.27-orig/testing/pluto/algparse-01/algparse.v1.pfs.txt libreswan-3.27/testing/pluto/algparse-01/algparse.v1.pfs.txt
--- libreswan-3.27-orig/testing/pluto/algparse-01/algparse.v1.pfs.txt 2018-10-07 22:52:09.000000000 -0400
+++ libreswan-3.27/testing/pluto/algparse-01/algparse.v1.pfs.txt 2019-02-15 16:46:01.379390213 -0500
@@ -386,3 +386,9 @@
ERROR: IKE PRF algorithm 'id2' is not recognized
algparse -v1 -pfs 'ike=aes_ccm'
ERROR: IKE encryption algorithm 'aes_ccm' is not supported by IKEv1
+algparse -v1 -pfs 'ike=aes_gcm-sha1-none-modp2048'
+ ERROR: IKE encryption algorithm 'aes_gcm' is not supported by IKEv1
+algparse -v1 -pfs 'ike=aes_gcm+aes_gcm-sha1-none-modp2048'
+ ERROR: IKE encryption algorithm 'aes_gcm+aes_gcm' is not recognized
+algparse -v1 -pfs 'ike=aes+aes_gcm'
+ ERROR: IKE encryption algorithm 'aes+aes_gcm' is not recognized
diff -Naur libreswan-3.27-orig/testing/pluto/algparse-01/algparse.v1.txt libreswan-3.27/testing/pluto/algparse-01/algparse.v1.txt
--- libreswan-3.27-orig/testing/pluto/algparse-01/algparse.v1.txt 2018-10-07 22:52:09.000000000 -0400
+++ libreswan-3.27/testing/pluto/algparse-01/algparse.v1.txt 2019-02-15 16:46:01.379390213 -0500
@@ -418,3 +418,9 @@
ERROR: IKE PRF algorithm 'id2' is not recognized
algparse -v1 'ike=aes_ccm'
ERROR: IKE encryption algorithm 'aes_ccm' is not supported by IKEv1
+algparse -v1 'ike=aes_gcm-sha1-none-modp2048'
+ ERROR: IKE encryption algorithm 'aes_gcm' is not supported by IKEv1
+algparse -v1 'ike=aes_gcm+aes_gcm-sha1-none-modp2048'
+ ERROR: IKE encryption algorithm 'aes_gcm+aes_gcm' is not recognized
+algparse -v1 'ike=aes+aes_gcm'
+ ERROR: IKE encryption algorithm 'aes+aes_gcm' is not recognized
diff -Naur libreswan-3.27-orig/testing/pluto/algparse-01/algparse.v2.pfs.txt libreswan-3.27/testing/pluto/algparse-01/algparse.v2.pfs.txt
--- libreswan-3.27-orig/testing/pluto/algparse-01/algparse.v2.pfs.txt 2018-10-07 22:52:09.000000000 -0400
+++ libreswan-3.27/testing/pluto/algparse-01/algparse.v2.pfs.txt 2019-02-15 16:50:12.777728085 -0500
@@ -1,11 +1,11 @@
algparse -v2 -pfs 'esp'
- AES_CBC-HMAC_SHA1_96
+ AES_CBC-HMAC_SHA2_512_256+HMAC_SHA2_256_128
algparse -v2 -pfs 'esp='
ERROR: String ended with invalid char, just after ""
algparse -v2 -pfs 'esp=aes'
- AES_CBC-HMAC_SHA1_96
+ AES_CBC-HMAC_SHA2_512_256+HMAC_SHA2_256_128
algparse -v2 -pfs 'esp=aes;modp2048'
- AES_CBC-HMAC_SHA1_96-MODP2048
+ AES_CBC-HMAC_SHA2_512_256+HMAC_SHA2_256_128-MODP2048
algparse -v2 -pfs 'esp=aes-sha1'
AES_CBC-HMAC_SHA1_96
algparse -v2 -pfs 'esp=aes-sha1'
@@ -13,7 +13,7 @@
algparse -v2 -pfs 'esp=aes-sha1-modp2048'
AES_CBC-HMAC_SHA1_96-MODP2048
algparse -v2 -pfs 'esp=aes-128'
- AES_CBC_128-HMAC_SHA1_96
+ AES_CBC_128-HMAC_SHA2_512_256+HMAC_SHA2_256_128
algparse -v2 -pfs 'esp=aes-128-sha1'
AES_CBC_128-HMAC_SHA1_96
algparse -v2 -pfs 'esp=aes-128-sha1'
@@ -41,7 +41,7 @@
algparse -v2 -pfs 'esp=null-sha1'
NULL-HMAC_SHA1_96
algparse -v2 -pfs 'esp=aes_cbc'
- AES_CBC-HMAC_SHA1_96
+ AES_CBC-HMAC_SHA2_512_256+HMAC_SHA2_256_128
algparse -v2 -pfs 'esp=aes-sha'
AES_CBC-HMAC_SHA1_96
algparse -v2 -pfs 'esp=aes-sha1'
@@ -73,13 +73,13 @@
algparse -v2 -pfs 'esp=aes256-sha2_512'
AES_CBC_256-HMAC_SHA2_512_256
algparse -v2 -pfs 'esp=camellia'
- CAMELLIA_CBC-HMAC_SHA1_96
+ CAMELLIA_CBC-HMAC_SHA2_512_256+HMAC_SHA2_256_128
algparse -v2 -pfs 'esp=camellia128'
- CAMELLIA_CBC_128-HMAC_SHA1_96
+ CAMELLIA_CBC_128-HMAC_SHA2_512_256+HMAC_SHA2_256_128
algparse -v2 -pfs 'esp=camellia192'
- CAMELLIA_CBC_192-HMAC_SHA1_96
+ CAMELLIA_CBC_192-HMAC_SHA2_512_256+HMAC_SHA2_256_128
algparse -v2 -pfs 'esp=camellia256'
- CAMELLIA_CBC_256-HMAC_SHA1_96
+ CAMELLIA_CBC_256-HMAC_SHA2_512_256+HMAC_SHA2_256_128
algparse -v2 -pfs 'esp=aes_ccm'
AES_CCM_16-NONE
algparse -v2 -pfs 'esp=aes_ccm_a-128-null'
@@ -181,19 +181,19 @@
algparse -v2 -pfs 'esp=aes_gcm_16_256-null'
AES_GCM_16_256-NONE
algparse -v2 -pfs 'esp=aes_ctr'
- AES_CTR-HMAC_SHA1_96
+ AES_CTR-HMAC_SHA2_512_256+HMAC_SHA2_256_128
algparse -v2 -pfs 'esp=aesctr'
- AES_CTR-HMAC_SHA1_96
+ AES_CTR-HMAC_SHA2_512_256+HMAC_SHA2_256_128
algparse -v2 -pfs 'esp=aes_ctr128'
- AES_CTR_128-HMAC_SHA1_96
+ AES_CTR_128-HMAC_SHA2_512_256+HMAC_SHA2_256_128
algparse -v2 -pfs 'esp=aes_ctr192'
- AES_CTR_192-HMAC_SHA1_96
+ AES_CTR_192-HMAC_SHA2_512_256+HMAC_SHA2_256_128
algparse -v2 -pfs 'esp=aes_ctr256'
- AES_CTR_256-HMAC_SHA1_96
+ AES_CTR_256-HMAC_SHA2_512_256+HMAC_SHA2_256_128
algparse -v2 -pfs 'esp=serpent'
- SERPENT_CBC-HMAC_SHA1_96
+ SERPENT_CBC-HMAC_SHA2_512_256+HMAC_SHA2_256_128
algparse -v2 -pfs 'esp=twofish'
- TWOFISH_CBC-HMAC_SHA1_96
+ TWOFISH_CBC-HMAC_SHA2_512_256+HMAC_SHA2_256_128
algparse -v2 -pfs 'esp=camellia_cbc_256-hmac_sha2_512_256;modp8192'
CAMELLIA_CBC_256-HMAC_SHA2_512_256-MODP8192
algparse -v2 -pfs 'esp=null_auth_aes_gmac_256-null;modp8192'
@@ -210,12 +210,12 @@
algparse -v2 -pfs 'esp=aes-sha1-modp8192,aes-sha1-modp8192,aes-sha1-modp8192'
AES_CBC-HMAC_SHA1_96-MODP8192
algparse -v2 -pfs 'esp=aes;none'
- AES_CBC-HMAC_SHA1_96-NONE
+ AES_CBC-HMAC_SHA2_512_256+HMAC_SHA2_256_128-NONE
algparse -v2 -pfs 'esp=aes;none,aes'
ERROR: either all or no ESP proposals should specify DH
algparse -v2 -pfs 'esp=aes;none,aes;modp2048'
- AES_CBC-HMAC_SHA1_96-NONE
- AES_CBC-HMAC_SHA1_96-MODP2048
+ AES_CBC-HMAC_SHA2_512_256+HMAC_SHA2_256_128-NONE
+ AES_CBC-HMAC_SHA2_512_256+HMAC_SHA2_256_128-MODP2048
algparse -v2 -pfs 'esp=aes-sha1-none'
AES_CBC-HMAC_SHA1_96-NONE
algparse -v2 -pfs 'esp=aes-sha1;none'
@@ -293,7 +293,7 @@
algparse -v2 -pfs 'esp=3des-sha1-modp8192,3des-sha2-modp2048'
ERROR: more than one IKEv2 ESP DH algorithm (MODP8192, MODP2048) requires unimplemented CHILD_SA INVALID_KE
algparse -v2 -pfs 'ah'
- HMAC_SHA1_96
+ HMAC_SHA2_512_256+HMAC_SHA2_256_128
algparse -v2 -pfs 'ah='
ERROR: String ended with invalid char, just after ""
algparse -v2 -pfs 'ah=md5'
@@ -345,32 +345,23 @@
algparse -v2 -pfs 'ah=ripemd'
ERROR: AH integrity algorithm 'ripemd' is not recognized
algparse -v2 -pfs 'ike'
- AES_CBC-HMAC_SHA2_256-MODP2048
- AES_CBC-HMAC_SHA2_512-MODP2048
- AES_CBC-HMAC_SHA1-MODP2048
- 3DES_CBC-HMAC_SHA2_256-MODP2048
- 3DES_CBC-HMAC_SHA2_512-MODP2048
- 3DES_CBC-HMAC_SHA1-MODP2048
+ AES_CBC+3DES_CBC-HMAC_SHA2_512+HMAC_SHA2_256-MODP2048+MODP3072+MODP4096+MODP8192+DH19+DH20+DH21+DH31
algparse -v2 -pfs 'ike='
ERROR: String ended with invalid char, just after ""
algparse -v2 -pfs 'ike=3des-sha1'
- 3DES_CBC-HMAC_SHA1-MODP2048
+ 3DES_CBC-HMAC_SHA1-MODP2048+MODP3072+MODP4096+MODP8192+DH19+DH20+DH21+DH31
algparse -v2 -pfs 'ike=3des-sha1'
- 3DES_CBC-HMAC_SHA1-MODP2048
+ 3DES_CBC-HMAC_SHA1-MODP2048+MODP3072+MODP4096+MODP8192+DH19+DH20+DH21+DH31
algparse -v2 -pfs 'ike=3des-sha1;modp1536'
3DES_CBC-HMAC_SHA1-MODP1536
algparse -v2 -pfs 'ike=3des;dh21'
- 3DES_CBC-HMAC_SHA2_256-DH21
- 3DES_CBC-HMAC_SHA2_512-DH21
- 3DES_CBC-HMAC_SHA1-DH21
+ 3DES_CBC-HMAC_SHA2_512+HMAC_SHA2_256-DH21
algparse -v2 -pfs 'ike=3des-sha1;dh21'
3DES_CBC-HMAC_SHA1-DH21
algparse -v2 -pfs 'ike=3des-sha1-ecp_521'
3DES_CBC-HMAC_SHA1-DH21
algparse -v2 -pfs 'ike=aes_gcm'
- AES_GCM_16-HMAC_SHA2_256-MODP2048
- AES_GCM_16-HMAC_SHA2_512-MODP2048
- AES_GCM_16-HMAC_SHA1-MODP2048
+ AES_GCM_16-HMAC_SHA2_512+HMAC_SHA2_256-MODP2048+MODP3072+MODP4096+MODP8192+DH19+DH20+DH21+DH31
algparse -v2 -pfs 'ike=aes-sha1-modp8192,aes-sha1-modp8192,aes-sha1-modp8192'
AES_CBC-HMAC_SHA1-MODP8192
algparse -v2 -pfs 'ike=aes;none'
@@ -381,3 +372,10 @@
ERROR: IKE PRF algorithm 'id2' is not recognized
algparse -v2 -pfs 'ike=aes_ccm'
ERROR: IKE encryption algorithm 'aes_ccm' is not supported
+algparse -v2 -pfs 'ike=aes_gcm-sha1-none-modp2048'
+ ERROR: 'modp2048' unexpected
+algparse -v2 -pfs 'ike=aes_gcm+aes_gcm-sha1-none-modp2048'
+ WARNING: discarding duplicate algorithm 'aes_gcm_16'
+ ERROR: 'modp2048' unexpected
+algparse -v2 -pfs 'ike=aes+aes_gcm'
+ ERROR: AEAD and non-AEAD IKE encryption algorithm can not be combined
diff -Naur libreswan-3.27-orig/testing/pluto/algparse-01/algparse.v2.txt libreswan-3.27/testing/pluto/algparse-01/algparse.v2.txt
--- libreswan-3.27-orig/testing/pluto/algparse-01/algparse.v2.txt 2018-10-07 22:52:09.000000000 -0400
+++ libreswan-3.27/testing/pluto/algparse-01/algparse.v2.txt 2019-02-15 16:50:12.778728094 -0500
@@ -1,12 +1,12 @@
algparse -v2 'esp'
- AES_CBC-HMAC_SHA1_96
+ AES_CBC-HMAC_SHA2_512_256+HMAC_SHA2_256_128
algparse -v2 'esp='
ERROR: String ended with invalid char, just after ""
algparse -v2 'esp=aes'
- AES_CBC-HMAC_SHA1_96
+ AES_CBC-HMAC_SHA2_512_256+HMAC_SHA2_256_128
algparse -v2 'esp=aes;modp2048'
WARNING: ignoring ESP DH algorithm MODP2048 as PFS policy is disabled
- AES_CBC-HMAC_SHA1_96
+ AES_CBC-HMAC_SHA2_512_256+HMAC_SHA2_256_128
algparse -v2 'esp=aes-sha1'
AES_CBC-HMAC_SHA1_96
algparse -v2 'esp=aes-sha1'
@@ -15,7 +15,7 @@
WARNING: ignoring ESP DH algorithm MODP2048 as PFS policy is disabled
AES_CBC-HMAC_SHA1_96
algparse -v2 'esp=aes-128'
- AES_CBC_128-HMAC_SHA1_96
+ AES_CBC_128-HMAC_SHA2_512_256+HMAC_SHA2_256_128
algparse -v2 'esp=aes-128-sha1'
AES_CBC_128-HMAC_SHA1_96
algparse -v2 'esp=aes-128-sha1'
@@ -49,7 +49,7 @@
algparse -v2 'esp=null-sha1'
NULL-HMAC_SHA1_96
algparse -v2 'esp=aes_cbc'
- AES_CBC-HMAC_SHA1_96
+ AES_CBC-HMAC_SHA2_512_256+HMAC_SHA2_256_128
algparse -v2 'esp=aes-sha'
AES_CBC-HMAC_SHA1_96
algparse -v2 'esp=aes-sha1'
@@ -81,13 +81,13 @@
algparse -v2 'esp=aes256-sha2_512'
AES_CBC_256-HMAC_SHA2_512_256
algparse -v2 'esp=camellia'
- CAMELLIA_CBC-HMAC_SHA1_96
+ CAMELLIA_CBC-HMAC_SHA2_512_256+HMAC_SHA2_256_128
algparse -v2 'esp=camellia128'
- CAMELLIA_CBC_128-HMAC_SHA1_96
+ CAMELLIA_CBC_128-HMAC_SHA2_512_256+HMAC_SHA2_256_128
algparse -v2 'esp=camellia192'
- CAMELLIA_CBC_192-HMAC_SHA1_96
+ CAMELLIA_CBC_192-HMAC_SHA2_512_256+HMAC_SHA2_256_128
algparse -v2 'esp=camellia256'
- CAMELLIA_CBC_256-HMAC_SHA1_96
+ CAMELLIA_CBC_256-HMAC_SHA2_512_256+HMAC_SHA2_256_128
algparse -v2 'esp=aes_ccm'
AES_CCM_16-NONE
algparse -v2 'esp=aes_ccm_a-128-null'
@@ -189,19 +189,19 @@
algparse -v2 'esp=aes_gcm_16_256-null'
AES_GCM_16_256-NONE
algparse -v2 'esp=aes_ctr'
- AES_CTR-HMAC_SHA1_96
+ AES_CTR-HMAC_SHA2_512_256+HMAC_SHA2_256_128
algparse -v2 'esp=aesctr'
- AES_CTR-HMAC_SHA1_96
+ AES_CTR-HMAC_SHA2_512_256+HMAC_SHA2_256_128
algparse -v2 'esp=aes_ctr128'
- AES_CTR_128-HMAC_SHA1_96
+ AES_CTR_128-HMAC_SHA2_512_256+HMAC_SHA2_256_128
algparse -v2 'esp=aes_ctr192'
- AES_CTR_192-HMAC_SHA1_96
+ AES_CTR_192-HMAC_SHA2_512_256+HMAC_SHA2_256_128
algparse -v2 'esp=aes_ctr256'
- AES_CTR_256-HMAC_SHA1_96
+ AES_CTR_256-HMAC_SHA2_512_256+HMAC_SHA2_256_128
algparse -v2 'esp=serpent'
- SERPENT_CBC-HMAC_SHA1_96
+ SERPENT_CBC-HMAC_SHA2_512_256+HMAC_SHA2_256_128
algparse -v2 'esp=twofish'
- TWOFISH_CBC-HMAC_SHA1_96
+ TWOFISH_CBC-HMAC_SHA2_512_256+HMAC_SHA2_256_128
algparse -v2 'esp=camellia_cbc_256-hmac_sha2_512_256;modp8192'
WARNING: ignoring ESP DH algorithm MODP8192 as PFS policy is disabled
CAMELLIA_CBC_256-HMAC_SHA2_512_256
@@ -228,16 +228,16 @@
AES_CBC-HMAC_SHA1_96
algparse -v2 'esp=aes;none'
WARNING: ignoring redundant ESP DH algorithm NONE as PFS policy is disabled
- AES_CBC-HMAC_SHA1_96
+ AES_CBC-HMAC_SHA2_512_256+HMAC_SHA2_256_128
algparse -v2 'esp=aes;none,aes'
WARNING: ignoring redundant ESP DH algorithm NONE as PFS policy is disabled
- AES_CBC-HMAC_SHA1_96
- AES_CBC-HMAC_SHA1_96
+ AES_CBC-HMAC_SHA2_512_256+HMAC_SHA2_256_128
+ AES_CBC-HMAC_SHA2_512_256+HMAC_SHA2_256_128
algparse -v2 'esp=aes;none,aes;modp2048'
WARNING: ignoring redundant ESP DH algorithm NONE as PFS policy is disabled
WARNING: ignoring ESP DH algorithm MODP2048 as PFS policy is disabled
- AES_CBC-HMAC_SHA1_96
- AES_CBC-HMAC_SHA1_96
+ AES_CBC-HMAC_SHA2_512_256+HMAC_SHA2_256_128
+ AES_CBC-HMAC_SHA2_512_256+HMAC_SHA2_256_128
algparse -v2 'esp=aes-sha1-none'
WARNING: ignoring redundant ESP DH algorithm NONE as PFS policy is disabled
AES_CBC-HMAC_SHA1_96
@@ -332,7 +332,7 @@
3DES_CBC-HMAC_SHA1_96
3DES_CBC-HMAC_SHA2_256_128
algparse -v2 'ah'
- HMAC_SHA1_96
+ HMAC_SHA2_512_256+HMAC_SHA2_256_128
algparse -v2 'ah='
ERROR: String ended with invalid char, just after ""
algparse -v2 'ah=md5'
@@ -388,32 +388,23 @@
algparse -v2 'ah=ripemd'
ERROR: AH integrity algorithm 'ripemd' is not recognized
algparse -v2 'ike'
- AES_CBC-HMAC_SHA2_256-MODP2048
- AES_CBC-HMAC_SHA2_512-MODP2048
- AES_CBC-HMAC_SHA1-MODP2048
- 3DES_CBC-HMAC_SHA2_256-MODP2048
- 3DES_CBC-HMAC_SHA2_512-MODP2048
- 3DES_CBC-HMAC_SHA1-MODP2048
+ AES_CBC+3DES_CBC-HMAC_SHA2_512+HMAC_SHA2_256-MODP2048+MODP3072+MODP4096+MODP8192+DH19+DH20+DH21+DH31
algparse -v2 'ike='
ERROR: String ended with invalid char, just after ""
algparse -v2 'ike=3des-sha1'
- 3DES_CBC-HMAC_SHA1-MODP2048
+ 3DES_CBC-HMAC_SHA1-MODP2048+MODP3072+MODP4096+MODP8192+DH19+DH20+DH21+DH31
algparse -v2 'ike=3des-sha1'
- 3DES_CBC-HMAC_SHA1-MODP2048
+ 3DES_CBC-HMAC_SHA1-MODP2048+MODP3072+MODP4096+MODP8192+DH19+DH20+DH21+DH31
algparse -v2 'ike=3des-sha1;modp1536'
3DES_CBC-HMAC_SHA1-MODP1536
algparse -v2 'ike=3des;dh21'
- 3DES_CBC-HMAC_SHA2_256-DH21
- 3DES_CBC-HMAC_SHA2_512-DH21
- 3DES_CBC-HMAC_SHA1-DH21
+ 3DES_CBC-HMAC_SHA2_512+HMAC_SHA2_256-DH21
algparse -v2 'ike=3des-sha1;dh21'
3DES_CBC-HMAC_SHA1-DH21
algparse -v2 'ike=3des-sha1-ecp_521'
3DES_CBC-HMAC_SHA1-DH21
algparse -v2 'ike=aes_gcm'
- AES_GCM_16-HMAC_SHA2_256-MODP2048
- AES_GCM_16-HMAC_SHA2_512-MODP2048
- AES_GCM_16-HMAC_SHA1-MODP2048
+ AES_GCM_16-HMAC_SHA2_512+HMAC_SHA2_256-MODP2048+MODP3072+MODP4096+MODP8192+DH19+DH20+DH21+DH31
algparse -v2 'ike=aes-sha1-modp8192,aes-sha1-modp8192,aes-sha1-modp8192'
AES_CBC-HMAC_SHA1-MODP8192
algparse -v2 'ike=aes;none'
@@ -424,3 +415,10 @@
ERROR: IKE PRF algorithm 'id2' is not recognized
algparse -v2 'ike=aes_ccm'
ERROR: IKE encryption algorithm 'aes_ccm' is not supported
+algparse -v2 'ike=aes_gcm-sha1-none-modp2048'
+ ERROR: 'modp2048' unexpected
+algparse -v2 'ike=aes_gcm+aes_gcm-sha1-none-modp2048'
+ WARNING: discarding duplicate algorithm 'aes_gcm_16'
+ ERROR: 'modp2048' unexpected
+algparse -v2 'ike=aes+aes_gcm'
+ ERROR: AEAD and non-AEAD IKE encryption algorithm can not be combined
diff -Naur libreswan-3.27-orig/testing/pluto/algparse-01/algparse.v.txt libreswan-3.27/testing/pluto/algparse-01/algparse.v.txt
--- libreswan-3.27-orig/testing/pluto/algparse-01/algparse.v.txt 2018-10-07 22:52:09.000000000 -0400
+++ libreswan-3.27/testing/pluto/algparse-01/algparse.v.txt 2019-02-15 16:32:29.004835574 -0500
@@ -13,7 +13,7 @@
algparse: SERPENT_CBC IKEv1: IKE ESP IKEv2: IKE ESP {256,192,*128} serpent
algparse: TWOFISH_CBC IKEv1: IKE ESP IKEv2: IKE ESP {256,192,*128} twofish
algparse: TWOFISH_SSH IKEv1: IKE IKEv2: IKE ESP {256,192,*128} twofish_cbc_ssh
-algparse: NULL_AUTH_AES_GMAC IKEv1: ESP IKEv2: ESP {256,192,*128} aes_gmac
+algparse: NULL_AUTH_AES_GMAC IKEv1: ESP IKEv2: ESP FIPS {256,192,*128} aes_gmac
algparse: NULL IKEv1: ESP IKEv2: ESP []
algparse: CHACHA20_POLY1305 IKEv1: IKEv2: IKE ESP [*256] chacha20poly1305
algparse: Hash algorithms:
@@ -28,17 +28,17 @@
algparse: HMAC_SHA2_256 IKEv1: IKE IKEv2: IKE FIPS sha2, sha256, sha2_256
algparse: HMAC_SHA2_384 IKEv1: IKE IKEv2: IKE FIPS sha384, sha2_384
algparse: HMAC_SHA2_512 IKEv1: IKE IKEv2: IKE FIPS sha512, sha2_512
-algparse: AES_XCBC IKEv1: IKEv2: IKE FIPS aes128_xcbc
+algparse: AES_XCBC IKEv1: IKEv2: IKE aes128_xcbc
algparse: Integrity algorithms:
algparse: HMAC_MD5_96 IKEv1: IKE ESP AH IKEv2: IKE ESP AH md5, hmac_md5
algparse: HMAC_SHA1_96 IKEv1: IKE ESP AH IKEv2: IKE ESP AH FIPS sha, sha1, sha1_96, hmac_sha1
-algparse: HMAC_SHA2_512_256 IKEv1: IKE ESP AH IKEv2: IKE ESP AH FIPS sha512, sha2_512, hmac_sha2_512
-algparse: HMAC_SHA2_384_192 IKEv1: IKE ESP AH IKEv2: IKE ESP AH FIPS sha384, sha2_384, hmac_sha2_384
-algparse: HMAC_SHA2_256_128 IKEv1: IKE ESP AH IKEv2: IKE ESP AH FIPS sha2, sha256, sha2_256, hmac_sha2_256
+algparse: HMAC_SHA2_512_256 IKEv1: IKE ESP AH IKEv2: IKE ESP AH FIPS sha512, sha2_512, sha2_512_256, hmac_sha2_512
+algparse: HMAC_SHA2_384_192 IKEv1: IKE ESP AH IKEv2: IKE ESP AH FIPS sha384, sha2_384, sha2_384_192, hmac_sha2_384
+algparse: HMAC_SHA2_256_128 IKEv1: IKE ESP AH IKEv2: IKE ESP AH FIPS sha2, sha256, sha2_256, sha2_256_128, hmac_sha2_256
algparse: HMAC_SHA2_256_TRUNCBUG IKEv1: ESP AH IKEv2: AH
-algparse: AES_XCBC_96 IKEv1: ESP AH IKEv2: IKE ESP AH FIPS aes_xcbc, aes128_xcbc, aes128_xcbc_96
+algparse: AES_XCBC_96 IKEv1: ESP AH IKEv2: IKE ESP AH aes_xcbc, aes128_xcbc, aes128_xcbc_96
algparse: AES_CMAC_96 IKEv1: ESP AH IKEv2: ESP AH FIPS aes_cmac
-algparse: NONE IKEv1: ESP IKEv2: ESP FIPS null
+algparse: NONE IKEv1: ESP IKEv2: IKE ESP FIPS null
algparse: DH algorithms:
algparse: NONE IKEv1: IKEv2: IKE ESP AH FIPS null, dh0
algparse: MODP1024 IKEv1: IKE ESP AH IKEv2: IKE ESP AH dh2
@@ -48,8 +48,8 @@
algparse: MODP4096 IKEv1: IKE ESP AH IKEv2: IKE ESP AH FIPS dh16
algparse: MODP6144 IKEv1: IKE ESP AH IKEv2: IKE ESP AH FIPS dh17
algparse: MODP8192 IKEv1: IKE ESP AH IKEv2: IKE ESP AH FIPS dh18
-algparse: DH19 IKEv1: IKE IKEv2: IKE ESP AH FIPS ecp_256
-algparse: DH20 IKEv1: IKE IKEv2: IKE ESP AH FIPS ecp_384
-algparse: DH21 IKEv1: IKE IKEv2: IKE ESP AH FIPS ecp_521
+algparse: DH19 IKEv1: IKE IKEv2: IKE ESP AH FIPS ecp_256, ecp256
+algparse: DH20 IKEv1: IKE IKEv2: IKE ESP AH FIPS ecp_384, ecp384
+algparse: DH21 IKEv1: IKE IKEv2: IKE ESP AH FIPS ecp_521, ecp521
algparse: DH31 IKEv1: IKE IKEv2: IKE ESP AH curve25519
algparse: leak detective found no leaks
diff -Naur libreswan-3.27-orig/testing/pluto/algparse-01/west.conf libreswan-3.27/testing/pluto/algparse-01/west.conf
--- libreswan-3.27-orig/testing/pluto/algparse-01/west.conf 2018-10-07 22:52:09.000000000 -0400
+++ libreswan-3.27/testing/pluto/algparse-01/west.conf 2019-02-15 16:32:29.004835574 -0500
@@ -10,4 +10,7 @@
protostack=netkey
plutodebug=all
+conn %default
+ ikev2=no
+
include /testing/baseconfigs/all/etc/ipsec.d/ipsec.conf.common
diff -Naur libreswan-3.27-orig/testing/pluto/algparse-01/west.console.txt libreswan-3.27/testing/pluto/algparse-01/west.console.txt
--- libreswan-3.27-orig/testing/pluto/algparse-01/west.console.txt 2018-10-07 22:52:09.000000000 -0400
+++ libreswan-3.27/testing/pluto/algparse-01/west.console.txt 2019-02-15 16:32:29.005835584 -0500
@@ -5,8 +5,6 @@
../bin/algparse.sh PATH/libexec/ipsec/algparse algparse*.txt
PATH/libexec/ipsec/algparse -v1 -pfs -t # algparse.v1.pfs.txt
PATH/libexec/ipsec/algparse -v1 -t # algparse.v1.txt
-PATH/libexec/ipsec/algparse -v1 -v2 -pfs -t # algparse.v1.v2.pfs.txt
-PATH/libexec/ipsec/algparse -v1 -v2 -t # algparse.v1.v2.txt
PATH/libexec/ipsec/algparse -v2 -pfs -t # algparse.v2.pfs.txt
PATH/libexec/ipsec/algparse -v2 -t # algparse.v2.txt
PATH/libexec/ipsec/algparse -v # algparse.v.txt
@@ -48,7 +46,7 @@
SERPENT_CBC IKEv1: IKE ESP IKEv2: IKE ESP {256,192,*128} serpent
TWOFISH_CBC IKEv1: IKE ESP IKEv2: IKE ESP {256,192,*128} twofish
TWOFISH_SSH IKEv1: IKE IKEv2: IKE ESP {256,192,*128} twofish_cbc_ssh
- NULL_AUTH_AES_GMAC IKEv1: ESP IKEv2: ESP {256,192,*128} aes_gmac
+ NULL_AUTH_AES_GMAC IKEv1: ESP IKEv2: ESP FIPS {256,192,*128} aes_gmac
NULL IKEv1: ESP IKEv2: ESP []
CHACHA20_POLY1305 IKEv1: IKEv2: IKE ESP [*256] chacha20poly1305
Hash algorithms:
@@ -63,7 +61,7 @@
HMAC_SHA2_256 IKEv1: IKE IKEv2: IKE FIPS sha2, sha256, sha2_256
HMAC_SHA2_384 IKEv1: IKE IKEv2: IKE FIPS sha384, sha2_384
HMAC_SHA2_512 IKEv1: IKE IKEv2: IKE FIPS sha512, sha2_512
- AES_XCBC IKEv1: IKEv2: IKE FIPS aes128_xcbc
+ AES_XCBC IKEv1: IKEv2: IKE aes128_xcbc
Integrity algorithms:
HMAC_MD5_96 IKEv1: IKE ESP AH IKEv2: IKE ESP AH md5, hmac_md5
HMAC_SHA1_96 IKEv1: IKE ESP AH IKEv2: IKE ESP AH FIPS sha, sha1, sha1_96, hmac_sha1
@@ -71,7 +69,7 @@
HMAC_SHA2_384_192 IKEv1: IKE ESP AH IKEv2: IKE ESP AH FIPS sha384, sha2_384, hmac_sha2_384
HMAC_SHA2_256_128 IKEv1: IKE ESP AH IKEv2: IKE ESP AH FIPS sha2, sha256, sha2_256, hmac_sha2_256
HMAC_SHA2_256_TRUNCBUG IKEv1: ESP AH IKEv2: AH
- AES_XCBC_96 IKEv1: ESP AH IKEv2: IKE ESP AH FIPS aes_xcbc, aes128_xcbc, aes128_xcbc_96
+ AES_XCBC_96 IKEv1: ESP AH IKEv2: IKE ESP AH aes_xcbc, aes128_xcbc, aes128_xcbc_96
AES_CMAC_96 IKEv1: ESP AH IKEv2: ESP AH FIPS aes_cmac
NONE IKEv1: ESP IKEv2: ESP FIPS null
DH algorithms:
diff -Naur libreswan-3.27-orig/testing/pluto/algparse-02-fips/algparse.v1.pfs.txt libreswan-3.27/testing/pluto/algparse-02-fips/algparse.v1.pfs.txt
--- libreswan-3.27-orig/testing/pluto/algparse-02-fips/algparse.v1.pfs.txt 2018-10-07 22:52:09.000000000 -0400
+++ libreswan-3.27/testing/pluto/algparse-02-fips/algparse.v1.pfs.txt 2019-02-15 16:46:01.380390223 -0500
@@ -57,7 +57,7 @@
algparse -fips -v1 -pfs 'esp=aes128-sha1'
AES_CBC_128-HMAC_SHA1_96
algparse -fips -v1 -pfs 'esp=aes128-aes_xcbc'
- AES_CBC_128-AES_XCBC_96
+ ERROR: ESP integrity algorithm 'aes_xcbc' is not supported
algparse -fips -v1 -pfs 'esp=aes192-sha1'
AES_CBC_192-HMAC_SHA1_96
algparse -fips -v1 -pfs 'esp=aes256-sha1'
@@ -197,7 +197,7 @@
algparse -fips -v1 -pfs 'esp=camellia_cbc_256-hmac_sha2_512_256;modp8192'
ERROR: ESP encryption algorithm 'camellia_cbc_256' is not supported
algparse -fips -v1 -pfs 'esp=null_auth_aes_gmac_256-null;modp8192'
- ERROR: ESP encryption algorithm 'null_auth_aes_gmac_256' is not supported
+ NULL_AUTH_AES_GMAC_256-NONE-MODP8192
algparse -fips -v1 -pfs 'esp=3des-sha1;modp8192'
3DES_CBC-HMAC_SHA1_96-MODP8192
algparse -fips -v1 -pfs 'esp=3des-sha1-modp8192'
@@ -318,7 +318,7 @@
algparse -fips -v1 -pfs 'ah=sha2_512'
HMAC_SHA2_512_256
algparse -fips -v1 -pfs 'ah=aes_xcbc'
- AES_XCBC_96
+ ERROR: AH integrity algorithm 'aes_xcbc' is not supported
algparse -fips -v1 -pfs 'ah=sha2-none'
ERROR: AH DH algorithm 'none' is not supported by IKEv1
algparse -fips -v1 -pfs 'ah=sha2;none'
@@ -378,3 +378,9 @@
ERROR: IKE PRF algorithm 'id2' is not recognized
algparse -fips -v1 -pfs 'ike=aes_ccm'
ERROR: IKE encryption algorithm 'aes_ccm' is not supported by IKEv1
+algparse -fips -v1 -pfs 'ike=aes_gcm-sha1-none-modp2048'
+ ERROR: IKE encryption algorithm 'aes_gcm' is not supported by IKEv1
+algparse -fips -v1 -pfs 'ike=aes_gcm+aes_gcm-sha1-none-modp2048'
+ ERROR: IKE encryption algorithm 'aes_gcm+aes_gcm' is not recognized
+algparse -fips -v1 -pfs 'ike=aes+aes_gcm'
+ ERROR: IKE encryption algorithm 'aes+aes_gcm' is not recognized
diff -Naur libreswan-3.27-orig/testing/pluto/algparse-02-fips/algparse.v1.txt libreswan-3.27/testing/pluto/algparse-02-fips/algparse.v1.txt
--- libreswan-3.27-orig/testing/pluto/algparse-02-fips/algparse.v1.txt 2018-10-07 22:52:09.000000000 -0400
+++ libreswan-3.27/testing/pluto/algparse-02-fips/algparse.v1.txt 2019-02-15 16:46:01.380390223 -0500
@@ -61,7 +61,7 @@
algparse -fips -v1 'esp=aes128-sha1'
AES_CBC_128-HMAC_SHA1_96
algparse -fips -v1 'esp=aes128-aes_xcbc'
- AES_CBC_128-AES_XCBC_96
+ ERROR: ESP integrity algorithm 'aes_xcbc' is not supported
algparse -fips -v1 'esp=aes192-sha1'
AES_CBC_192-HMAC_SHA1_96
algparse -fips -v1 'esp=aes256-sha1'
@@ -201,7 +201,8 @@
algparse -fips -v1 'esp=camellia_cbc_256-hmac_sha2_512_256;modp8192'
ERROR: ESP encryption algorithm 'camellia_cbc_256' is not supported
algparse -fips -v1 'esp=null_auth_aes_gmac_256-null;modp8192'
- ERROR: ESP encryption algorithm 'null_auth_aes_gmac_256' is not supported
+ WARNING: ignoring ESP DH algorithm MODP8192 as PFS policy is disabled
+ NULL_AUTH_AES_GMAC_256-NONE
algparse -fips -v1 'esp=3des-sha1;modp8192'
WARNING: ignoring ESP DH algorithm MODP8192 as PFS policy is disabled
3DES_CBC-HMAC_SHA1_96
@@ -345,7 +346,7 @@
algparse -fips -v1 'ah=sha2_512'
HMAC_SHA2_512_256
algparse -fips -v1 'ah=aes_xcbc'
- AES_XCBC_96
+ ERROR: AH integrity algorithm 'aes_xcbc' is not supported
algparse -fips -v1 'ah=sha2-none'
ERROR: AH DH algorithm 'none' is not supported by IKEv1
algparse -fips -v1 'ah=sha2;none'
@@ -406,3 +407,9 @@
ERROR: IKE PRF algorithm 'id2' is not recognized
algparse -fips -v1 'ike=aes_ccm'
ERROR: IKE encryption algorithm 'aes_ccm' is not supported by IKEv1
+algparse -fips -v1 'ike=aes_gcm-sha1-none-modp2048'
+ ERROR: IKE encryption algorithm 'aes_gcm' is not supported by IKEv1
+algparse -fips -v1 'ike=aes_gcm+aes_gcm-sha1-none-modp2048'
+ ERROR: IKE encryption algorithm 'aes_gcm+aes_gcm' is not recognized
+algparse -fips -v1 'ike=aes+aes_gcm'
+ ERROR: IKE encryption algorithm 'aes+aes_gcm' is not recognized
diff -Naur libreswan-3.27-orig/testing/pluto/algparse-02-fips/algparse.v2.pfs.txt libreswan-3.27/testing/pluto/algparse-02-fips/algparse.v2.pfs.txt
--- libreswan-3.27-orig/testing/pluto/algparse-02-fips/algparse.v2.pfs.txt 2018-10-07 22:52:09.000000000 -0400
+++ libreswan-3.27/testing/pluto/algparse-02-fips/algparse.v2.pfs.txt 2019-02-15 16:50:12.778728094 -0500
@@ -1,11 +1,11 @@
algparse -fips -v2 -pfs 'esp'
- AES_CBC-HMAC_SHA1_96
+ AES_CBC-HMAC_SHA2_512_256+HMAC_SHA2_256_128
algparse -fips -v2 -pfs 'esp='
ERROR: String ended with invalid char, just after ""
algparse -fips -v2 -pfs 'esp=aes'
- AES_CBC-HMAC_SHA1_96
+ AES_CBC-HMAC_SHA2_512_256+HMAC_SHA2_256_128
algparse -fips -v2 -pfs 'esp=aes;modp2048'
- AES_CBC-HMAC_SHA1_96-MODP2048
+ AES_CBC-HMAC_SHA2_512_256+HMAC_SHA2_256_128-MODP2048
algparse -fips -v2 -pfs 'esp=aes-sha1'
AES_CBC-HMAC_SHA1_96
algparse -fips -v2 -pfs 'esp=aes-sha1'
@@ -13,7 +13,7 @@
algparse -fips -v2 -pfs 'esp=aes-sha1-modp2048'
AES_CBC-HMAC_SHA1_96-MODP2048
algparse -fips -v2 -pfs 'esp=aes-128'
- AES_CBC_128-HMAC_SHA1_96
+ AES_CBC_128-HMAC_SHA2_512_256+HMAC_SHA2_256_128
algparse -fips -v2 -pfs 'esp=aes-128-sha1'
AES_CBC_128-HMAC_SHA1_96
algparse -fips -v2 -pfs 'esp=aes-128-sha1'
@@ -41,7 +41,7 @@
algparse -fips -v2 -pfs 'esp=null-sha1'
ERROR: ESP encryption algorithm 'null' is not supported
algparse -fips -v2 -pfs 'esp=aes_cbc'
- AES_CBC-HMAC_SHA1_96
+ AES_CBC-HMAC_SHA2_512_256+HMAC_SHA2_256_128
algparse -fips -v2 -pfs 'esp=aes-sha'
AES_CBC-HMAC_SHA1_96
algparse -fips -v2 -pfs 'esp=aes-sha1'
@@ -57,7 +57,7 @@
algparse -fips -v2 -pfs 'esp=aes128-sha1'
AES_CBC_128-HMAC_SHA1_96
algparse -fips -v2 -pfs 'esp=aes128-aes_xcbc'
- AES_CBC_128-AES_XCBC_96
+ ERROR: ESP integrity algorithm 'aes_xcbc' is not supported
algparse -fips -v2 -pfs 'esp=aes192-sha1'
AES_CBC_192-HMAC_SHA1_96
algparse -fips -v2 -pfs 'esp=aes256-sha1'
@@ -181,15 +181,15 @@
algparse -fips -v2 -pfs 'esp=aes_gcm_16_256-null'
AES_GCM_16_256-NONE
algparse -fips -v2 -pfs 'esp=aes_ctr'
- AES_CTR-HMAC_SHA1_96
+ AES_CTR-HMAC_SHA2_512_256+HMAC_SHA2_256_128
algparse -fips -v2 -pfs 'esp=aesctr'
- AES_CTR-HMAC_SHA1_96
+ AES_CTR-HMAC_SHA2_512_256+HMAC_SHA2_256_128
algparse -fips -v2 -pfs 'esp=aes_ctr128'
- AES_CTR_128-HMAC_SHA1_96
+ AES_CTR_128-HMAC_SHA2_512_256+HMAC_SHA2_256_128
algparse -fips -v2 -pfs 'esp=aes_ctr192'
- AES_CTR_192-HMAC_SHA1_96
+ AES_CTR_192-HMAC_SHA2_512_256+HMAC_SHA2_256_128
algparse -fips -v2 -pfs 'esp=aes_ctr256'
- AES_CTR_256-HMAC_SHA1_96
+ AES_CTR_256-HMAC_SHA2_512_256+HMAC_SHA2_256_128
algparse -fips -v2 -pfs 'esp=serpent'
ERROR: ESP encryption algorithm 'serpent' is not supported
algparse -fips -v2 -pfs 'esp=twofish'
@@ -197,7 +197,7 @@
algparse -fips -v2 -pfs 'esp=camellia_cbc_256-hmac_sha2_512_256;modp8192'
ERROR: ESP encryption algorithm 'camellia_cbc_256' is not supported
algparse -fips -v2 -pfs 'esp=null_auth_aes_gmac_256-null;modp8192'
- ERROR: ESP encryption algorithm 'null_auth_aes_gmac_256' is not supported
+ NULL_AUTH_AES_GMAC_256-NONE-MODP8192
algparse -fips -v2 -pfs 'esp=3des-sha1;modp8192'
3DES_CBC-HMAC_SHA1_96-MODP8192
algparse -fips -v2 -pfs 'esp=3des-sha1-modp8192'
@@ -210,12 +210,12 @@
algparse -fips -v2 -pfs 'esp=aes-sha1-modp8192,aes-sha1-modp8192,aes-sha1-modp8192'
AES_CBC-HMAC_SHA1_96-MODP8192
algparse -fips -v2 -pfs 'esp=aes;none'
- AES_CBC-HMAC_SHA1_96-NONE
+ AES_CBC-HMAC_SHA2_512_256+HMAC_SHA2_256_128-NONE
algparse -fips -v2 -pfs 'esp=aes;none,aes'
ERROR: either all or no ESP proposals should specify DH
algparse -fips -v2 -pfs 'esp=aes;none,aes;modp2048'
- AES_CBC-HMAC_SHA1_96-NONE
- AES_CBC-HMAC_SHA1_96-MODP2048
+ AES_CBC-HMAC_SHA2_512_256+HMAC_SHA2_256_128-NONE
+ AES_CBC-HMAC_SHA2_512_256+HMAC_SHA2_256_128-MODP2048
algparse -fips -v2 -pfs 'esp=aes-sha1-none'
AES_CBC-HMAC_SHA1_96-NONE
algparse -fips -v2 -pfs 'esp=aes-sha1;none'
@@ -293,7 +293,7 @@
algparse -fips -v2 -pfs 'esp=3des-sha1-modp8192,3des-sha2-modp2048'
ERROR: more than one IKEv2 ESP DH algorithm (MODP8192, MODP2048) requires unimplemented CHILD_SA INVALID_KE
algparse -fips -v2 -pfs 'ah'
- HMAC_SHA1_96
+ HMAC_SHA2_512_256+HMAC_SHA2_256_128
algparse -fips -v2 -pfs 'ah='
ERROR: String ended with invalid char, just after ""
algparse -fips -v2 -pfs 'ah=md5'
@@ -319,7 +319,7 @@
algparse -fips -v2 -pfs 'ah=sha2_512'
HMAC_SHA2_512_256
algparse -fips -v2 -pfs 'ah=aes_xcbc'
- AES_XCBC_96
+ ERROR: AH integrity algorithm 'aes_xcbc' is not supported
algparse -fips -v2 -pfs 'ah=sha2-none'
HMAC_SHA2_256_128-NONE
algparse -fips -v2 -pfs 'ah=sha2;none'
@@ -345,32 +345,23 @@
algparse -fips -v2 -pfs 'ah=ripemd'
ERROR: AH integrity algorithm 'ripemd' is not recognized
algparse -fips -v2 -pfs 'ike'
- AES_CBC-HMAC_SHA2_256-MODP2048
- AES_CBC-HMAC_SHA2_512-MODP2048
- AES_CBC-HMAC_SHA1-MODP2048
- 3DES_CBC-HMAC_SHA2_256-MODP2048
- 3DES_CBC-HMAC_SHA2_512-MODP2048
- 3DES_CBC-HMAC_SHA1-MODP2048
+ AES_CBC+3DES_CBC-HMAC_SHA2_512+HMAC_SHA2_256-MODP2048+MODP3072+MODP4096+MODP8192+DH19+DH20+DH21+DH31
algparse -fips -v2 -pfs 'ike='
ERROR: String ended with invalid char, just after ""
algparse -fips -v2 -pfs 'ike=3des-sha1'
- 3DES_CBC-HMAC_SHA1-MODP2048
+ 3DES_CBC-HMAC_SHA1-MODP2048+MODP3072+MODP4096+MODP8192+DH19+DH20+DH21+DH31
algparse -fips -v2 -pfs 'ike=3des-sha1'
- 3DES_CBC-HMAC_SHA1-MODP2048
+ 3DES_CBC-HMAC_SHA1-MODP2048+MODP3072+MODP4096+MODP8192+DH19+DH20+DH21+DH31
algparse -fips -v2 -pfs 'ike=3des-sha1;modp1536'
ERROR: IKE DH algorithm 'modp1536' is not supported
algparse -fips -v2 -pfs 'ike=3des;dh21'
- 3DES_CBC-HMAC_SHA2_256-DH21
- 3DES_CBC-HMAC_SHA2_512-DH21
- 3DES_CBC-HMAC_SHA1-DH21
+ 3DES_CBC-HMAC_SHA2_512+HMAC_SHA2_256-DH21
algparse -fips -v2 -pfs 'ike=3des-sha1;dh21'
3DES_CBC-HMAC_SHA1-DH21
algparse -fips -v2 -pfs 'ike=3des-sha1-ecp_521'
3DES_CBC-HMAC_SHA1-DH21
algparse -fips -v2 -pfs 'ike=aes_gcm'
- AES_GCM_16-HMAC_SHA2_256-MODP2048
- AES_GCM_16-HMAC_SHA2_512-MODP2048
- AES_GCM_16-HMAC_SHA1-MODP2048
+ AES_GCM_16-HMAC_SHA2_512+HMAC_SHA2_256-MODP2048+MODP3072+MODP4096+MODP8192+DH19+DH20+DH21+DH31
algparse -fips -v2 -pfs 'ike=aes-sha1-modp8192,aes-sha1-modp8192,aes-sha1-modp8192'
AES_CBC-HMAC_SHA1-MODP8192
algparse -fips -v2 -pfs 'ike=aes;none'
@@ -381,3 +372,10 @@
ERROR: IKE PRF algorithm 'id2' is not recognized
algparse -fips -v2 -pfs 'ike=aes_ccm'
ERROR: IKE encryption algorithm 'aes_ccm' is not supported
+algparse -fips -v2 -pfs 'ike=aes_gcm-sha1-none-modp2048'
+ ERROR: 'modp2048' unexpected
+algparse -fips -v2 -pfs 'ike=aes_gcm+aes_gcm-sha1-none-modp2048'
+ WARNING: discarding duplicate algorithm 'aes_gcm_16'
+ ERROR: 'modp2048' unexpected
+algparse -fips -v2 -pfs 'ike=aes+aes_gcm'
+ ERROR: AEAD and non-AEAD IKE encryption algorithm can not be combined
diff -Naur libreswan-3.27-orig/testing/pluto/algparse-02-fips/algparse.v2.txt libreswan-3.27/testing/pluto/algparse-02-fips/algparse.v2.txt
--- libreswan-3.27-orig/testing/pluto/algparse-02-fips/algparse.v2.txt 2018-10-07 22:52:09.000000000 -0400
+++ libreswan-3.27/testing/pluto/algparse-02-fips/algparse.v2.txt 2019-02-15 16:50:12.778728094 -0500
@@ -1,12 +1,12 @@
algparse -fips -v2 'esp'
- AES_CBC-HMAC_SHA1_96
+ AES_CBC-HMAC_SHA2_512_256+HMAC_SHA2_256_128
algparse -fips -v2 'esp='
ERROR: String ended with invalid char, just after ""
algparse -fips -v2 'esp=aes'
- AES_CBC-HMAC_SHA1_96
+ AES_CBC-HMAC_SHA2_512_256+HMAC_SHA2_256_128
algparse -fips -v2 'esp=aes;modp2048'
WARNING: ignoring ESP DH algorithm MODP2048 as PFS policy is disabled
- AES_CBC-HMAC_SHA1_96
+ AES_CBC-HMAC_SHA2_512_256+HMAC_SHA2_256_128
algparse -fips -v2 'esp=aes-sha1'
AES_CBC-HMAC_SHA1_96
algparse -fips -v2 'esp=aes-sha1'
@@ -15,7 +15,7 @@
WARNING: ignoring ESP DH algorithm MODP2048 as PFS policy is disabled
AES_CBC-HMAC_SHA1_96
algparse -fips -v2 'esp=aes-128'
- AES_CBC_128-HMAC_SHA1_96
+ AES_CBC_128-HMAC_SHA2_512_256+HMAC_SHA2_256_128
algparse -fips -v2 'esp=aes-128-sha1'
AES_CBC_128-HMAC_SHA1_96
algparse -fips -v2 'esp=aes-128-sha1'
@@ -47,7 +47,7 @@
algparse -fips -v2 'esp=null-sha1'
ERROR: ESP encryption algorithm 'null' is not supported
algparse -fips -v2 'esp=aes_cbc'
- AES_CBC-HMAC_SHA1_96
+ AES_CBC-HMAC_SHA2_512_256+HMAC_SHA2_256_128
algparse -fips -v2 'esp=aes-sha'
AES_CBC-HMAC_SHA1_96
algparse -fips -v2 'esp=aes-sha1'
@@ -63,7 +63,7 @@
algparse -fips -v2 'esp=aes128-sha1'
AES_CBC_128-HMAC_SHA1_96
algparse -fips -v2 'esp=aes128-aes_xcbc'
- AES_CBC_128-AES_XCBC_96
+ ERROR: ESP integrity algorithm 'aes_xcbc' is not supported
algparse -fips -v2 'esp=aes192-sha1'
AES_CBC_192-HMAC_SHA1_96
algparse -fips -v2 'esp=aes256-sha1'
@@ -187,15 +187,15 @@
algparse -fips -v2 'esp=aes_gcm_16_256-null'
AES_GCM_16_256-NONE
algparse -fips -v2 'esp=aes_ctr'
- AES_CTR-HMAC_SHA1_96
+ AES_CTR-HMAC_SHA2_512_256+HMAC_SHA2_256_128
algparse -fips -v2 'esp=aesctr'
- AES_CTR-HMAC_SHA1_96
+ AES_CTR-HMAC_SHA2_512_256+HMAC_SHA2_256_128
algparse -fips -v2 'esp=aes_ctr128'
- AES_CTR_128-HMAC_SHA1_96
+ AES_CTR_128-HMAC_SHA2_512_256+HMAC_SHA2_256_128
algparse -fips -v2 'esp=aes_ctr192'
- AES_CTR_192-HMAC_SHA1_96
+ AES_CTR_192-HMAC_SHA2_512_256+HMAC_SHA2_256_128
algparse -fips -v2 'esp=aes_ctr256'
- AES_CTR_256-HMAC_SHA1_96
+ AES_CTR_256-HMAC_SHA2_512_256+HMAC_SHA2_256_128
algparse -fips -v2 'esp=serpent'
ERROR: ESP encryption algorithm 'serpent' is not supported
algparse -fips -v2 'esp=twofish'
@@ -203,7 +203,8 @@
algparse -fips -v2 'esp=camellia_cbc_256-hmac_sha2_512_256;modp8192'
ERROR: ESP encryption algorithm 'camellia_cbc_256' is not supported
algparse -fips -v2 'esp=null_auth_aes_gmac_256-null;modp8192'
- ERROR: ESP encryption algorithm 'null_auth_aes_gmac_256' is not supported
+ WARNING: ignoring ESP DH algorithm MODP8192 as PFS policy is disabled
+ NULL_AUTH_AES_GMAC_256-NONE
algparse -fips -v2 'esp=3des-sha1;modp8192'
WARNING: ignoring ESP DH algorithm MODP8192 as PFS policy is disabled
3DES_CBC-HMAC_SHA1_96
@@ -224,16 +225,16 @@
AES_CBC-HMAC_SHA1_96
algparse -fips -v2 'esp=aes;none'
WARNING: ignoring redundant ESP DH algorithm NONE as PFS policy is disabled
- AES_CBC-HMAC_SHA1_96
+ AES_CBC-HMAC_SHA2_512_256+HMAC_SHA2_256_128
algparse -fips -v2 'esp=aes;none,aes'
WARNING: ignoring redundant ESP DH algorithm NONE as PFS policy is disabled
- AES_CBC-HMAC_SHA1_96
- AES_CBC-HMAC_SHA1_96
+ AES_CBC-HMAC_SHA2_512_256+HMAC_SHA2_256_128
+ AES_CBC-HMAC_SHA2_512_256+HMAC_SHA2_256_128
algparse -fips -v2 'esp=aes;none,aes;modp2048'
WARNING: ignoring redundant ESP DH algorithm NONE as PFS policy is disabled
WARNING: ignoring ESP DH algorithm MODP2048 as PFS policy is disabled
- AES_CBC-HMAC_SHA1_96
- AES_CBC-HMAC_SHA1_96
+ AES_CBC-HMAC_SHA2_512_256+HMAC_SHA2_256_128
+ AES_CBC-HMAC_SHA2_512_256+HMAC_SHA2_256_128
algparse -fips -v2 'esp=aes-sha1-none'
WARNING: ignoring redundant ESP DH algorithm NONE as PFS policy is disabled
AES_CBC-HMAC_SHA1_96
@@ -328,7 +329,7 @@
3DES_CBC-HMAC_SHA1_96
3DES_CBC-HMAC_SHA2_256_128
algparse -fips -v2 'ah'
- HMAC_SHA1_96
+ HMAC_SHA2_512_256+HMAC_SHA2_256_128
algparse -fips -v2 'ah='
ERROR: String ended with invalid char, just after ""
algparse -fips -v2 'ah=md5'
@@ -355,7 +356,7 @@
algparse -fips -v2 'ah=sha2_512'
HMAC_SHA2_512_256
algparse -fips -v2 'ah=aes_xcbc'
- AES_XCBC_96
+ ERROR: AH integrity algorithm 'aes_xcbc' is not supported
algparse -fips -v2 'ah=sha2-none'
WARNING: ignoring redundant AH DH algorithm NONE as PFS policy is disabled
HMAC_SHA2_256_128
@@ -384,32 +385,23 @@
algparse -fips -v2 'ah=ripemd'
ERROR: AH integrity algorithm 'ripemd' is not recognized
algparse -fips -v2 'ike'
- AES_CBC-HMAC_SHA2_256-MODP2048
- AES_CBC-HMAC_SHA2_512-MODP2048
- AES_CBC-HMAC_SHA1-MODP2048
- 3DES_CBC-HMAC_SHA2_256-MODP2048
- 3DES_CBC-HMAC_SHA2_512-MODP2048
- 3DES_CBC-HMAC_SHA1-MODP2048
+ AES_CBC+3DES_CBC-HMAC_SHA2_512+HMAC_SHA2_256-MODP2048+MODP3072+MODP4096+MODP8192+DH19+DH20+DH21+DH31
algparse -fips -v2 'ike='
ERROR: String ended with invalid char, just after ""
algparse -fips -v2 'ike=3des-sha1'
- 3DES_CBC-HMAC_SHA1-MODP2048
+ 3DES_CBC-HMAC_SHA1-MODP2048+MODP3072+MODP4096+MODP8192+DH19+DH20+DH21+DH31
algparse -fips -v2 'ike=3des-sha1'
- 3DES_CBC-HMAC_SHA1-MODP2048
+ 3DES_CBC-HMAC_SHA1-MODP2048+MODP3072+MODP4096+MODP8192+DH19+DH20+DH21+DH31
algparse -fips -v2 'ike=3des-sha1;modp1536'
ERROR: IKE DH algorithm 'modp1536' is not supported
algparse -fips -v2 'ike=3des;dh21'
- 3DES_CBC-HMAC_SHA2_256-DH21
- 3DES_CBC-HMAC_SHA2_512-DH21
- 3DES_CBC-HMAC_SHA1-DH21
+ 3DES_CBC-HMAC_SHA2_512+HMAC_SHA2_256-DH21
algparse -fips -v2 'ike=3des-sha1;dh21'
3DES_CBC-HMAC_SHA1-DH21
algparse -fips -v2 'ike=3des-sha1-ecp_521'
3DES_CBC-HMAC_SHA1-DH21
algparse -fips -v2 'ike=aes_gcm'
- AES_GCM_16-HMAC_SHA2_256-MODP2048
- AES_GCM_16-HMAC_SHA2_512-MODP2048
- AES_GCM_16-HMAC_SHA1-MODP2048
+ AES_GCM_16-HMAC_SHA2_512+HMAC_SHA2_256-MODP2048+MODP3072+MODP4096+MODP8192+DH19+DH20+DH21+DH31
algparse -fips -v2 'ike=aes-sha1-modp8192,aes-sha1-modp8192,aes-sha1-modp8192'
AES_CBC-HMAC_SHA1-MODP8192
algparse -fips -v2 'ike=aes;none'
@@ -420,3 +412,10 @@
ERROR: IKE PRF algorithm 'id2' is not recognized
algparse -fips -v2 'ike=aes_ccm'
ERROR: IKE encryption algorithm 'aes_ccm' is not supported
+algparse -fips -v2 'ike=aes_gcm-sha1-none-modp2048'
+ ERROR: 'modp2048' unexpected
+algparse -fips -v2 'ike=aes_gcm+aes_gcm-sha1-none-modp2048'
+ WARNING: discarding duplicate algorithm 'aes_gcm_16'
+ ERROR: 'modp2048' unexpected
+algparse -fips -v2 'ike=aes+aes_gcm'
+ ERROR: AEAD and non-AEAD IKE encryption algorithm can not be combined
diff -Naur libreswan-3.27-orig/testing/pluto/algparse-02-fips/algparse.v.txt libreswan-3.27/testing/pluto/algparse-02-fips/algparse.v.txt
--- libreswan-3.27-orig/testing/pluto/algparse-02-fips/algparse.v.txt 2018-10-07 22:52:09.000000000 -0400
+++ libreswan-3.27/testing/pluto/algparse-02-fips/algparse.v.txt 2019-02-15 16:32:29.006835593 -0500
@@ -3,13 +3,14 @@
algparse: Encryption algorithm SERPENT_CBC disabled; not FIPS compliant
algparse: Encryption algorithm TWOFISH_CBC disabled; not FIPS compliant
algparse: Encryption algorithm TWOFISH_SSH disabled; not FIPS compliant
-algparse: Encryption algorithm NULL_AUTH_AES_GMAC disabled; not FIPS compliant
algparse: Encryption algorithm NULL disabled; not FIPS compliant
algparse: Encryption algorithm CHACHA20_POLY1305 disabled; not FIPS compliant
algparse: Hash algorithm MD5 disabled; not FIPS compliant
algparse: PRF algorithm HMAC_MD5 disabled; not FIPS compliant
+algparse: PRF algorithm AES_XCBC disabled; not FIPS compliant
algparse: Integrity algorithm HMAC_MD5_96 disabled; not FIPS compliant
algparse: Integrity algorithm HMAC_SHA2_256_TRUNCBUG disabled; not FIPS compliant
+algparse: Integrity algorithm AES_XCBC_96 disabled; not FIPS compliant
algparse: DH algorithm MODP1024 disabled; not FIPS compliant
algparse: DH algorithm MODP1536 disabled; not FIPS compliant
algparse: DH algorithm DH31 disabled; not FIPS compliant
@@ -23,6 +24,7 @@
algparse: AES_GCM_8 IKEv1: ESP IKEv2: IKE ESP FIPS {256,192,*128} aes_gcm_a
algparse: AES_CTR IKEv1: IKE ESP IKEv2: IKE ESP FIPS {256,192,*128} aesctr
algparse: AES_CBC IKEv1: IKE ESP IKEv2: IKE ESP FIPS {256,192,*128} aes
+algparse: NULL_AUTH_AES_GMAC IKEv1: ESP IKEv2: ESP FIPS {256,192,*128} aes_gmac
algparse: FIPS Hash algorithms:
algparse: SHA1 IKEv1: IKE IKEv2: FIPS sha
algparse: SHA2_256 IKEv1: IKE IKEv2: FIPS sha2, sha256
@@ -33,15 +35,13 @@
algparse: HMAC_SHA2_256 IKEv1: IKE IKEv2: IKE FIPS sha2, sha256, sha2_256
algparse: HMAC_SHA2_384 IKEv1: IKE IKEv2: IKE FIPS sha384, sha2_384
algparse: HMAC_SHA2_512 IKEv1: IKE IKEv2: IKE FIPS sha512, sha2_512
-algparse: AES_XCBC IKEv1: IKEv2: IKE FIPS aes128_xcbc
algparse: FIPS Integrity algorithms:
algparse: HMAC_SHA1_96 IKEv1: IKE ESP AH IKEv2: IKE ESP AH FIPS sha, sha1, sha1_96, hmac_sha1
-algparse: HMAC_SHA2_512_256 IKEv1: IKE ESP AH IKEv2: IKE ESP AH FIPS sha512, sha2_512, hmac_sha2_512
-algparse: HMAC_SHA2_384_192 IKEv1: IKE ESP AH IKEv2: IKE ESP AH FIPS sha384, sha2_384, hmac_sha2_384
-algparse: HMAC_SHA2_256_128 IKEv1: IKE ESP AH IKEv2: IKE ESP AH FIPS sha2, sha256, sha2_256, hmac_sha2_256
-algparse: AES_XCBC_96 IKEv1: ESP AH IKEv2: IKE ESP AH FIPS aes_xcbc, aes128_xcbc, aes128_xcbc_96
+algparse: HMAC_SHA2_512_256 IKEv1: IKE ESP AH IKEv2: IKE ESP AH FIPS sha512, sha2_512, sha2_512_256, hmac_sha2_512
+algparse: HMAC_SHA2_384_192 IKEv1: IKE ESP AH IKEv2: IKE ESP AH FIPS sha384, sha2_384, sha2_384_192, hmac_sha2_384
+algparse: HMAC_SHA2_256_128 IKEv1: IKE ESP AH IKEv2: IKE ESP AH FIPS sha2, sha256, sha2_256, sha2_256_128, hmac_sha2_256
algparse: AES_CMAC_96 IKEv1: ESP AH IKEv2: ESP AH FIPS aes_cmac
-algparse: NONE IKEv1: ESP IKEv2: ESP FIPS null
+algparse: NONE IKEv1: ESP IKEv2: IKE ESP FIPS null
algparse: FIPS DH algorithms:
algparse: NONE IKEv1: IKEv2: IKE ESP AH FIPS null, dh0
algparse: MODP2048 IKEv1: IKE ESP AH IKEv2: IKE ESP AH FIPS dh14
@@ -49,7 +49,7 @@
algparse: MODP4096 IKEv1: IKE ESP AH IKEv2: IKE ESP AH FIPS dh16
algparse: MODP6144 IKEv1: IKE ESP AH IKEv2: IKE ESP AH FIPS dh17
algparse: MODP8192 IKEv1: IKE ESP AH IKEv2: IKE ESP AH FIPS dh18
-algparse: DH19 IKEv1: IKE IKEv2: IKE ESP AH FIPS ecp_256
-algparse: DH20 IKEv1: IKE IKEv2: IKE ESP AH FIPS ecp_384
-algparse: DH21 IKEv1: IKE IKEv2: IKE ESP AH FIPS ecp_521
+algparse: DH19 IKEv1: IKE IKEv2: IKE ESP AH FIPS ecp_256, ecp256
+algparse: DH20 IKEv1: IKE IKEv2: IKE ESP AH FIPS ecp_384, ecp384
+algparse: DH21 IKEv1: IKE IKEv2: IKE ESP AH FIPS ecp_521, ecp521
algparse: leak detective found no leaks
diff -Naur libreswan-3.27-orig/testing/pluto/algparse-02-fips/west.conf libreswan-3.27/testing/pluto/algparse-02-fips/west.conf
--- libreswan-3.27-orig/testing/pluto/algparse-02-fips/west.conf 2018-10-07 22:52:09.000000000 -0400
+++ libreswan-3.27/testing/pluto/algparse-02-fips/west.conf 2019-02-15 16:32:29.006835593 -0500
@@ -10,4 +10,7 @@
protostack=netkey
plutodebug=all
+conn %default
+ ikev2=no
+
include /testing/baseconfigs/all/etc/ipsec.d/ipsec.conf.common
diff -Naur libreswan-3.27-orig/testing/pluto/algparse-02-fips/west.console.txt libreswan-3.27/testing/pluto/algparse-02-fips/west.console.txt
--- libreswan-3.27-orig/testing/pluto/algparse-02-fips/west.console.txt 2018-10-07 22:52:09.000000000 -0400
+++ libreswan-3.27/testing/pluto/algparse-02-fips/west.console.txt 2019-02-15 16:32:29.006835593 -0500
@@ -7,8 +7,6 @@
../bin/algparse.sh PATH/libexec/ipsec/algparse algparse*.txt
PATH/libexec/ipsec/algparse -v1 -pfs -t # algparse.v1.pfs.txt
PATH/libexec/ipsec/algparse -v1 -t # algparse.v1.txt
-PATH/libexec/ipsec/algparse -v1 -v2 -pfs -t # algparse.v1.v2.pfs.txt
-PATH/libexec/ipsec/algparse -v1 -v2 -t # algparse.v1.v2.txt
PATH/libexec/ipsec/algparse -v2 -pfs -t # algparse.v2.pfs.txt
PATH/libexec/ipsec/algparse -v2 -t # algparse.v2.txt
PATH/libexec/ipsec/algparse -v # algparse.v.txt
@@ -50,6 +48,7 @@
AES_GCM_8 IKEv1: ESP IKEv2: IKE ESP FIPS {256,192,*128} aes_gcm_a
AES_CTR IKEv1: IKE ESP IKEv2: IKE ESP FIPS {256,192,*128} aesctr
AES_CBC IKEv1: IKE ESP IKEv2: IKE ESP FIPS {256,192,*128} aes
+ NULL_AUTH_AES_GMAC IKEv1: ESP IKEv2: ESP FIPS {256,192,*128} aes_gmac
FIPS Hash algorithms:
SHA1 IKEv1: IKE IKEv2: FIPS sha
SHA2_256 IKEv1: IKE IKEv2: FIPS sha2, sha256
@@ -60,13 +59,11 @@
HMAC_SHA2_256 IKEv1: IKE IKEv2: IKE FIPS sha2, sha256, sha2_256
HMAC_SHA2_384 IKEv1: IKE IKEv2: IKE FIPS sha384, sha2_384
HMAC_SHA2_512 IKEv1: IKE IKEv2: IKE FIPS sha512, sha2_512
- AES_XCBC IKEv1: IKEv2: IKE FIPS aes128_xcbc
FIPS Integrity algorithms:
HMAC_SHA1_96 IKEv1: IKE ESP AH IKEv2: IKE ESP AH FIPS sha, sha1, sha1_96, hmac_sha1
HMAC_SHA2_512_256 IKEv1: IKE ESP AH IKEv2: IKE ESP AH FIPS sha512, sha2_512, hmac_sha2_512
HMAC_SHA2_384_192 IKEv1: IKE ESP AH IKEv2: IKE ESP AH FIPS sha384, sha2_384, hmac_sha2_384
HMAC_SHA2_256_128 IKEv1: IKE ESP AH IKEv2: IKE ESP AH FIPS sha2, sha256, sha2_256, hmac_sha2_256
- AES_XCBC_96 IKEv1: ESP AH IKEv2: IKE ESP AH FIPS aes_xcbc, aes128_xcbc, aes128_xcbc_96
AES_CMAC_96 IKEv1: ESP AH IKEv2: ESP AH FIPS aes_cmac
NONE IKEv1: ESP IKEv2: ESP FIPS null
FIPS DH algorithms: