diff --git a/.gitignore b/.gitignore index c47bf85..9f1434e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ SOURCES/ikev1_dsa.fax.bz2 SOURCES/ikev1_psk.fax.bz2 SOURCES/ikev2.fax.bz2 -SOURCES/libreswan-3.12.tar.gz +SOURCES/libreswan-3.15.tar.gz diff --git a/.libreswan.metadata b/.libreswan.metadata index 3e211e5..992bed3 100644 --- a/.libreswan.metadata +++ b/.libreswan.metadata @@ -1,4 +1,4 @@ b35cd50b8bc0a08b9c07713bf19c72d53bfe66bb SOURCES/ikev1_dsa.fax.bz2 861d97bf488f9e296cad8c43ab72f111a5b1a848 SOURCES/ikev1_psk.fax.bz2 fcaf77f3deae3d8e99cdb3b1f8abea63167a0633 SOURCES/ikev2.fax.bz2 -bca50e25b044df1b9fc4b732be38b28c25216674 SOURCES/libreswan-3.12.tar.gz +f2f7f4c0e6ffc979d3cc3b301dc56b49a9dcc2f3 SOURCES/libreswan-3.15.tar.gz diff --git a/SOURCES/libreswan-3.12-1052811.patch b/SOURCES/libreswan-3.12-1052811.patch deleted file mode 100644 index 8634e1f..0000000 --- a/SOURCES/libreswan-3.12-1052811.patch +++ /dev/null @@ -1,35 +0,0 @@ -diff --git a/programs/pluto/ikev2_child.c b/programs/pluto/ikev2_child.c -index 1a49b53..a5e8724 100644 ---- a/programs/pluto/ikev2_child.c -+++ b/programs/pluto/ikev2_child.c -@@ -1006,10 +1006,11 @@ stf_status ikev2_child_sa_respond(struct msg_digest *md, - - /* start of SA out */ - { -- struct isakmp_sa r_sa = sa_pd->payload.sa; -+ struct isakmp_sa r_sa; - stf_status ret; - pb_stream r_sa_pbs; - -+ zero(&r_sa); - r_sa.isasa_np = isa_xchg == ISAKMP_v2_CREATE_CHILD_SA ? - ISAKMP_NEXT_v2Nr : ISAKMP_NEXT_v2TSi; - -diff --git a/programs/pluto/ikev2_parent.c b/programs/pluto/ikev2_parent.c -index 739518f..3ef8c53 100644 ---- a/programs/pluto/ikev2_parent.c -+++ b/programs/pluto/ikev2_parent.c -@@ -924,10 +924,12 @@ static stf_status ikev2_parent_inI1outR1_tail( - - /* start of SA out */ - { -- struct isakmp_sa r_sa = sa_pd->payload.sa; -+ struct isakmp_sa r_sa; - stf_status ret; - pb_stream r_sa_pbs; - -+ zero(&r_sa); -+ - if (!DBGP(IMPAIR_SEND_IKEv2_KE)) { - /* normal case */ - r_sa.isasa_np = ISAKMP_NEXT_v2KE; diff --git a/SOURCES/libreswan-3.12-1074018-audit.patch b/SOURCES/libreswan-3.12-1074018-audit.patch deleted file mode 100644 index 9f4ed33..0000000 --- a/SOURCES/libreswan-3.12-1074018-audit.patch +++ /dev/null @@ -1,527 +0,0 @@ -diff -Naurw libreswan-3.12-orig/include/pluto_constants.h libreswan-3.12/include/pluto_constants.h ---- libreswan-3.12-orig/include/pluto_constants.h 2014-11-06 22:52:50.000000000 -0500 -+++ libreswan-3.12/include/pluto_constants.h 2015-01-20 16:30:04.725000000 -0500 -@@ -460,10 +460,6 @@ - - /* Only relevant to IKEv2 */ - --#define IS_PARENT_SA_ESTABLISHED(s) ((s) == STATE_PARENT_I2 || \ -- (s) == STATE_PARENT_R1 || \ -- (s) == STATE_IKESA_DEL) -- - #define IS_V2_INITIATOR(s) ((s) == STATE_PARENT_I1 || \ - (s) == STATE_PARENT_I2 || \ - (s) == STATE_PARENT_I3) -@@ -472,7 +468,7 @@ - - #define IS_V2_ESTABLISHED(s) ((s) == STATE_PARENT_R2 || (s) == STATE_PARENT_I3) - --#define IS_IKE_SA_ESTABLISHED(s) (IS_ISAKMP_SA_ESTABLISHED(s) || IS_PARENT_SA_ESTABLISHED(s)) -+#define IS_IKE_SA_ESTABLISHED(st) (IS_ISAKMP_SA_ESTABLISHED(st->st_state) || IS_PARENT_SA_ESTABLISHED(st)) - - /* - * ??? Issue here is that our child SA appears as a -@@ -480,9 +476,12 @@ - * So we fall back to checking if it is cloned, and therefore really a child. - */ - #define IS_CHILD_SA_ESTABLISHED(st) \ -- (((st->st_state == STATE_PARENT_I3 || st->st_state == STATE_PARENT_R2) && \ -- IS_CHILD_SA(st)) || \ -- st->st_state == STATE_CHILDSA_DEL) -+ ((st->st_state == STATE_PARENT_I3 || st->st_state == STATE_PARENT_R2) && \ -+ IS_CHILD_SA(st)) -+ -+#define IS_PARENT_SA_ESTABLISHED(st) \ -+ ((st->st_state == STATE_PARENT_I3 || st->st_state == STATE_PARENT_R2) \ -+ && !IS_CHILD_SA(st)) - - #define IS_CHILD_SA(st) ((st)->st_clonedfrom != SOS_NOBODY) - -diff -Naurw libreswan-3.12-orig/programs/pluto/ikev1_aggr.c libreswan-3.12/programs/pluto/ikev1_aggr.c ---- libreswan-3.12-orig/programs/pluto/ikev1_aggr.c 2014-11-06 22:52:50.000000000 -0500 -+++ libreswan-3.12/programs/pluto/ikev1_aggr.c 2015-01-20 16:30:04.725000000 -0500 -@@ -924,7 +924,10 @@ - * payloads etc. will not lose our IV - */ - set_ph1_iv_from_new(st); -- -+ DBG(DBG_CONTROL, DBG_log("phase 1 complete")); -+#ifdef USE_LINUX_AUDIT -+ linux_audit_conn(st, LAK_PARENT_START); -+#endif - return STF_OK; - } - -@@ -1040,9 +1043,10 @@ - * payloads etc. will not lose our IV - */ - set_ph1_iv_from_new(st); -- - DBG(DBG_CONTROL, DBG_log("phase 1 complete")); -- -+#ifdef USE_LINUX_AUDIT -+ linux_audit_conn(st, LAK_PARENT_START); -+#endif - return STF_OK; - } - -diff -Naurw libreswan-3.12-orig/programs/pluto/ikev1_main.c libreswan-3.12/programs/pluto/ikev1_main.c ---- libreswan-3.12-orig/programs/pluto/ikev1_main.c 2014-11-06 22:52:50.000000000 -0500 -+++ libreswan-3.12/programs/pluto/ikev1_main.c 2015-01-20 16:30:04.726000000 -0500 -@@ -2201,6 +2201,10 @@ - } - - ISAKMP_SA_established(st->st_connection, st->st_serialno); -+#ifdef USE_LINUX_AUDIT -+ linux_audit_conn(st, LAK_PARENT_START); -+#endif -+ - - return STF_OK; - } -@@ -2270,6 +2274,9 @@ - } - - ISAKMP_SA_established(st->st_connection, st->st_serialno); -+#ifdef USE_LINUX_AUDIT -+ linux_audit_conn(st, LAK_PARENT_START); -+#endif - - passert((st->st_policy & POLICY_PFS) == 0 || - st->st_pfs_group != NULL); -diff -Naurw libreswan-3.12-orig/programs/pluto/ikev2.c libreswan-3.12/programs/pluto/ikev2.c ---- libreswan-3.12-orig/programs/pluto/ikev2.c 2014-11-06 22:52:50.000000000 -0500 -+++ libreswan-3.12/programs/pluto/ikev2.c 2015-01-20 16:30:04.727000000 -0500 -@@ -1069,7 +1069,7 @@ - sizeof(sadetails)); - /* log our success */ - w = RC_SUCCESS; -- } else if (IS_PARENT_SA_ESTABLISHED(st->st_state)) { -+ } else if (st->st_state == STATE_PARENT_I2 || st->st_state == STATE_PARENT_R1) { - fmt_isakmp_sa_established(st, sadetails, - sizeof(sadetails)); - } -diff -Naurw libreswan-3.12-orig/programs/pluto/ikev2_parent.c libreswan-3.12/programs/pluto/ikev2_parent.c ---- libreswan-3.12-orig/programs/pluto/ikev2_parent.c 2015-01-20 16:25:53.561000000 -0500 -+++ libreswan-3.12/programs/pluto/ikev2_parent.c 2015-01-20 16:30:04.727000000 -0500 -@@ -2155,6 +2155,10 @@ - change_state(st, STATE_PARENT_R2); - c->newest_isakmp_sa = st->st_serialno; - -+#ifdef USE_LINUX_AUDIT -+ linux_audit_conn(st, LAK_PARENT_START); -+#endif -+ - delete_event(st); - { - enum event_type x = EVENT_SA_REPLACE; -@@ -2505,6 +2509,10 @@ - - /* authentication good */ - -+#ifdef USE_LINUX_AUDIT -+ linux_audit_conn(st, LAK_PARENT_START); -+#endif -+ - /* TODO: see if there are any notifications */ - - /* See if there is a child SA available */ -diff -Naurw libreswan-3.12-orig/programs/pluto/kernel.c libreswan-3.12/programs/pluto/kernel.c ---- libreswan-3.12-orig/programs/pluto/kernel.c 2014-11-06 22:52:50.000000000 -0500 -+++ libreswan-3.12/programs/pluto/kernel.c 2015-01-20 16:30:04.728000000 -0500 -@@ -2942,6 +2942,10 @@ - } - } - -+#ifdef USE_LINUX_AUDIT -+ linux_audit_conn(st, LAK_CHILD_START); -+#endif -+ - return TRUE; - } - -@@ -2949,9 +2953,13 @@ - * we may not succeed, but we bull ahead anyway because - * we cannot do anything better by recognizing failure - */ --void delete_ipsec_sa(struct state *st USED_BY_KLIPS, -- bool inbound_only USED_BY_KLIPS) -+void delete_ipsec_sa(struct state *st, bool inbound_only) - { -+#ifdef USE_LINUX_AUDIT -+ /* XXX in IKEv2 we get a spurious call with a parent st :( */ -+ if (IS_CHILD_SA(st)) -+ linux_audit_conn(st, LAK_CHILD_DESTROY); -+#endif - switch (kern_interface) { - case USE_MASTKLIPS: - case USE_KLIPS: -diff -Naurw libreswan-3.12-orig/programs/pluto/log.c libreswan-3.12/programs/pluto/log.c ---- libreswan-3.12-orig/programs/pluto/log.c 2014-11-06 22:52:50.000000000 -0500 -+++ libreswan-3.12/programs/pluto/log.c 2015-01-20 16:33:30.903000000 -0500 -@@ -62,6 +62,11 @@ - /* for show_virtual_private: */ - #include "virtual.h" /* needs connections.h */ - -+#ifdef USE_LINUX_AUDIT -+# include -+# include "crypto.h" /* for oakley_group_desc */ -+#endif -+ - #ifndef NO_DB_OPS_STATS - #define NO_DB_CONTEXT - #include "db_ops.h" -@@ -76,8 +81,9 @@ - log_to_stderr = TRUE, /* should log go to stderr? */ - log_to_syslog = TRUE, /* should log go to syslog? */ - log_to_perpeer = FALSE, /* should log go to per-IP file? */ -- log_with_timestamp = FALSE; /* some people want timestamps, but we -+ log_with_timestamp = FALSE, /* some people want timestamps, but we - * don't want those in our test output */ -+ log_to_audit = FALSE; /* audit log messages for kernel */ - - bool - logged_txt_warning = FALSE; /* should we complain about finding KEY? */ -@@ -921,7 +927,7 @@ - if (IS_IKE_SA(st)) { - if (lc->tunnel < tun_phase1) - lc->tunnel = tun_phase1; -- if (IS_IKE_SA_ESTABLISHED(st->st_state)) { -+ if (IS_IKE_SA_ESTABLISHED(st)) { - if (lc->tunnel < tun_phase1up) - lc->tunnel = tun_phase1up; - lc->phase1 = p1_up; -@@ -1087,3 +1093,188 @@ - DBG(DBG_CONTROLMORE, - DBG_log("log_state for connection %s completed", conn->name)); - } -+ -+#ifdef USE_LINUX_AUDIT -+void linux_audit_init() -+{ -+ libreswan_log("Linux audit support [enabled]"); -+ /* test and log if audit is enabled on the system */ -+ int audit_fd; -+ audit_fd = audit_open(); -+ if (audit_fd < 0) { -+ if (errno == EINVAL || errno == EPROTONOSUPPORT || -+ errno == EAFNOSUPPORT) { -+ loglog(RC_LOG_SERIOUS, -+ "Warning: kernel has no audit support"); -+ } else { -+ loglog(RC_LOG_SERIOUS, -+ "FATAL: audit_open() failed : %s", -+ strerror(errno)); -+ exit_pluto(7); -+ } -+ } else { -+ log_to_audit = TRUE; -+ } -+ close(audit_fd); -+ libreswan_log("Linux audit activated"); -+} -+ -+void linux_audit(const int type, const char *message, const char *addr, -+ const int result) -+{ -+ -+ int audit_fd, rc; -+ -+ if (!log_to_audit) -+ return; -+ -+ audit_fd = audit_open(); -+ if (audit_fd < 0) { -+ loglog(RC_LOG_SERIOUS, -+ "FATAL (SOON): audit_open() failed : %s", -+ strerror(errno)); -+ exit_pluto(7); -+ } -+ -+ /* -+ * audit_log_user_message() - log a general user message -+ * -+ * audit_fd - The fd returned by audit_open -+ * type - type of message, ex: AUDIT_USYS_CONFIG, AUDIT_USER_LOGIN -+ * message - the message text being sent -+ * hostname - the hostname if known, NULL if unknown -+ * addr - The network address of the user, NULL if unknown -+ * tty - The tty of the user, if NULL will attempt to figure out -+ * result - 1 is "success" and 0 is "failed" -+ * -+ * We log the remoteid instead of hostname -+ */ -+ -+ rc = audit_log_user_message(audit_fd, type, message, NULL, addr, NULL, result); -+ close(audit_fd); -+ if (rc < 0) { -+ loglog(RC_LOG_SERIOUS, -+ "FATAL: audit log failed: %s", -+ strerror(errno)); -+ exit_pluto(7); -+ } -+} -+ -+/* -+ * any admin/network strings but go through audit_encode_nv_string() -+ */ -+void linux_audit_conn(const struct state *st, enum linux_audit_kind op) -+{ -+ char raddr[ADDRTOT_BUF]; -+ char laddr[ADDRTOT_BUF]; -+ char audit_str[AUDIT_LOG_SIZE]; -+ char cipher_str[AUDIT_LOG_SIZE]; -+ char spi_str[AUDIT_LOG_SIZE]; -+ struct connection *const c = st->st_connection; -+ bool initiator = FALSE; -+ char head[IDTOA_BUF]; -+ char integname[IDTOA_BUF]; -+ char prfname[IDTOA_BUF]; -+ struct esb_buf esb; -+ /* we need to free() this */ -+ char *conn_encode = audit_encode_nv_string("conn-name",c->name,0); -+ -+ zero(&cipher_str); -+ zero(&spi_str); -+ -+ switch(op) { -+ case LAK_PARENT_START: -+ case LAK_PARENT_DESTROY: -+ initiator = IS_V2_INITIATOR(st->st_state) || IS_PHASE1_INIT(st->st_state); -+ snprintf(head, sizeof(head), "op=%s direction=%s %s connstate=%ld ike-version=%s auth=%s", -+ op == LAK_PARENT_START ? "start" : "destroy", -+ initiator ? "initiator" : "responder", -+ conn_encode, -+ st->st_serialno, -+ st->st_ikev2 ? "2.0" : "1", -+ st->st_ikev2 ? ((c->policy & POLICY_PSK) ? "PRESHARED_KEY" : "RSA_SIG") : -+ strip_prefix(enum_show(&oakley_auth_names, -+ st->st_oakley.auth), "OAKLEY_")); -+ -+ snprintf(prfname, sizeof(prfname), "%s", -+ st->st_oakley.prf_hasher->common.officname); -+ -+ if (st->st_oakley.integ_hasher != NULL) { -+ snprintf(integname, sizeof(integname), "%s_%zu", -+ st->st_oakley.integ_hasher->common.officname, -+ st->st_oakley.integ_hasher->hash_integ_len * -+ BITS_PER_BYTE); -+ } else { -+ if (!st->st_ikev2) { -+ /* ikev1 takes integ from prf, ecept of cause gcm */ -+ /* but we dont support gcm in ikev1 for now */ -+ snprintf(integname, sizeof(integname), prfname); -+ } else { -+ snprintf(integname, sizeof(integname), "none"); -+ } -+ } -+ -+ snprintf(cipher_str, sizeof(cipher_str), -+ "cipher=%s ksize=%d integ=%s prf=%s pfs=%s", -+ st->st_oakley.encrypter->common.officname, -+ st->st_oakley.enckeylen, -+ integname, prfname, -+ strip_prefix(enum_name(&oakley_group_names, st->st_oakley.group->group), "OAKLEY_GROUP_")); -+ break; -+ -+ case LAK_CHILD_START: -+ case LAK_CHILD_DESTROY: -+ snprintf(head, sizeof(head), "op=%s %s connstate=%ld, satype=%s samode=%s", -+ op == LAK_CHILD_START ? "start" : "destroy", -+ conn_encode, -+ st->st_serialno, -+ st->st_esp.present ? "ipsec-esp" : (st->st_ah.present ? "ipsec-ah" : "ipsec-policy"), -+ c->policy & POLICY_TUNNEL ? "tunnel" : "transport"); -+ -+ snprintf(cipher_str, sizeof(cipher_str), -+ "cipher=%s ksize=%d integ=%s", -+ st->st_esp.present ? -+ strip_prefix(enum_showb(&esp_transformid_names, -+ st->st_esp.attrs.transattrs.encrypt, &esb), "ESP_") : -+ "none", -+ st->st_esp.present ? -+ st->st_esp.attrs.transattrs.enckeylen : -+ 0, -+ strip_prefix(enum_show(&auth_alg_names, -+ st->st_esp.attrs.transattrs.integ_hash), -+ "AUTH_ALGORITHM_")); -+ -+ snprintf(spi_str, sizeof(spi_str), -+ "in-spi=%lu(0x%08lx) out-spi=%lu(0x%08lx) in-ipcomp=%lu(0x%08lx) out-ipcomp=%lu(0x%08lx)", -+ st->st_esp.present ? (unsigned long)ntohl(st->st_esp.attrs.spi) : -+ (unsigned long)ntohl(st->st_ah.attrs.spi), -+ st->st_esp.present ? (unsigned long)ntohl(st->st_esp.attrs.spi) : -+ (unsigned long)ntohl(st->st_ah.attrs.spi), -+ st->st_esp.present ? (unsigned long)ntohl(st->st_esp.our_spi) : -+ (unsigned long)ntohl(st->st_ah.our_spi), -+ st->st_esp.present ? (unsigned long)ntohl(st->st_esp.our_spi) : -+ (unsigned long)ntohl(st->st_ah.our_spi), -+ st->st_ipcomp.present ? (unsigned long)ntohl(st->st_ipcomp.attrs.spi) : (unsigned long)0, -+ st->st_ipcomp.present ? (unsigned long)ntohl(st->st_ipcomp.attrs.spi) : (unsigned long)0, -+ st->st_ipcomp.present ? (unsigned long)ntohl(st->st_ipcomp.our_spi) : (unsigned long)0, -+ st->st_ipcomp.present ? (unsigned long)ntohl(st->st_ipcomp.our_spi) : (unsigned long)0); -+ break; -+ default: -+ bad_case(op); -+ } -+ free(conn_encode); /* allocated by audit_encode_nv_string() */ -+ -+ addrtot(&c->spd.this.host_addr, 0, laddr, sizeof(laddr)); -+ addrtot(&c->spd.that.host_addr, 0, raddr, sizeof(raddr)); -+ -+ snprintf(audit_str, sizeof(audit_str), "%s %s %s laddr=%s", -+ head, -+ cipher_str, -+ spi_str, -+ laddr); -+ -+ linux_audit( (op == LAK_CHILD_START || op == LAK_CHILD_DESTROY) ? -+ AUDIT_CRYPTO_IPSEC_SA : AUDIT_CRYPTO_IKE_SA, -+ audit_str, raddr, AUDIT_RESULT_OK); -+} -+#endif -diff -Naurw libreswan-3.12-orig/programs/pluto/log.h libreswan-3.12/programs/pluto/log.h ---- libreswan-3.12-orig/programs/pluto/log.h 2014-11-06 22:52:50.000000000 -0500 -+++ libreswan-3.12/programs/pluto/log.h 2015-01-20 16:30:04.729000000 -0500 -@@ -34,6 +34,7 @@ - log_to_stderr, /* should log go to stderr? */ - log_to_syslog, /* should log go to syslog? */ - log_to_perpeer, /* should log go to per-IP file? */ -+ log_to_audit, /* audit logs for kernel/auditd */ - log_with_timestamp; /* prefix timestamp */ - - extern char *base_perpeer_logdir; -@@ -137,6 +138,31 @@ - extern void show_setup_plutomain(void); - extern void show_setup_natt(void); - -+#ifdef USE_LINUX_AUDIT -+#include -+#define AUDIT_LOG_SIZE 256 -+/* should really be in libaudit.h */ -+#define AUDIT_RESULT_FAIL 0 -+#define AUDIT_RESULT_OK 1 -+#ifndef AUDIT_CRYPTO_IKE_SA -+# define AUDIT_CRYPTO_IKE_SA 2408 -+#endif -+#ifndef AUDIT_CRYPTO_IPSEC_SA -+# define AUDIT_CRYPTO_IPSEC_SA 2409 -+#endif -+ -+enum linux_audit_kind { -+ LAK_PARENT_START, -+ LAK_CHILD_START, -+ LAK_PARENT_DESTROY, -+ LAK_CHILD_DESTROY -+}; -+extern void linux_audit_init(); -+extern void linux_audit(const int type, const char *message, -+ const char *addr, const int result); -+extern void linux_audit_conn(const struct state *st, enum linux_audit_kind); -+#endif -+ - /* - * some events are to be logged only occasionally. - */ -diff -Naurw libreswan-3.12-orig/programs/pluto/pluto_constants.c libreswan-3.12/programs/pluto/pluto_constants.c ---- libreswan-3.12-orig/programs/pluto/pluto_constants.c 2014-11-06 22:52:50.000000000 -0500 -+++ libreswan-3.12/programs/pluto/pluto_constants.c 2015-01-20 16:30:04.729000000 -0500 -@@ -149,6 +149,9 @@ - "STATE_PARENT_I3", - "STATE_PARENT_R1", - "STATE_PARENT_R2", -+ "STATE_IKESA_DEL", -+ "STATE_CHILDSA_DEL", -+ - "STATE_IKEv2_ROOF" - }; - -diff -Naurw libreswan-3.12-orig/programs/pluto/plutomain.c libreswan-3.12/programs/pluto/plutomain.c ---- libreswan-3.12-orig/programs/pluto/plutomain.c 2014-11-06 22:52:50.000000000 -0500 -+++ libreswan-3.12/programs/pluto/plutomain.c 2015-01-20 16:30:04.729000000 -0500 -@@ -99,10 +99,6 @@ - # include "security_selinux.h" - #endif - --#ifdef USE_LINUX_AUDIT --# include --#endif -- - static const char *pluto_name; /* name (path) we were invoked with */ - - static const char *ctlbase = "/var/run/pluto"; -@@ -1220,32 +1216,7 @@ - #endif - - #ifdef USE_LINUX_AUDIT -- libreswan_log("Linux audit support [enabled]"); -- /* test and log if audit is enabled on the system */ -- int audit_fd, rc; -- audit_fd = audit_open(); -- if (audit_fd < 0) { -- if (errno == EINVAL || errno == EPROTONOSUPPORT || -- errno == EAFNOSUPPORT) { -- loglog(RC_LOG_SERIOUS, -- "Warning: kernel has no audit support"); -- } else { -- loglog(RC_LOG_SERIOUS, -- "FATAL (SOON): audit_open() failed : %s", -- strerror(errno)); -- /* temp disabled exit_pluto(10); */ -- } -- } -- rc = audit_log_acct_message(audit_fd, AUDIT_USER_START, NULL, -- "starting pluto daemon", NULL, -1, NULL, -- NULL, NULL, 1); -- close(audit_fd); -- if (rc < 0) { -- loglog(RC_LOG_SERIOUS, -- "FATAL: audit_log_acct_message failed: %s", -- strerror(errno)); -- exit_pluto(10); -- } -+ linux_audit_init(); - #else - libreswan_log("Linux audit support [disabled]"); - #endif -@@ -1382,7 +1353,6 @@ - #ifdef HAVE_LABELED_IPSEC - init_avc(); - #endif -- - daily_log_event(); - call_server(); - return -1; /* Shouldn't ever reach this */ -@@ -1432,7 +1402,6 @@ - /* report memory leaks now, after all free_* calls */ - if(leak_detective) - report_leaks(); -- - close_log(); /* close the logfiles */ - exit(status); /* exit, with our error code */ - } -diff -Naurw libreswan-3.12-orig/programs/pluto/state.c libreswan-3.12/programs/pluto/state.c ---- libreswan-3.12-orig/programs/pluto/state.c 2014-11-06 22:52:50.000000000 -0500 -+++ libreswan-3.12/programs/pluto/state.c 2015-01-20 16:30:04.730000000 -0500 -@@ -356,6 +356,12 @@ - - DBG(DBG_CONTROL, DBG_log("deleting state #%lu", st->st_serialno)); - -+#ifdef USE_LINUX_AUDIT -+ /* only log parent state deletes, we log children in ipsec_delete_sa() */ -+ if (IS_IKE_SA_ESTABLISHED(st) || st->st_state == STATE_IKESA_DEL) -+ linux_audit_conn(st, LAK_PARENT_DESTROY); -+#endif -+ - if (IS_IPSEC_SA_ESTABLISHED(st->st_state)) { - /* Note that a state/SA can have more then one of ESP/AH/IPCOMP */ - if (st->st_esp.present) { -@@ -471,7 +477,7 @@ - * ??? we ought to tell peer to delete IPSEC SAs - */ - if (IS_IPSEC_SA_ESTABLISHED(st->st_state) || -- IS_CHILD_SA_ESTABLISHED(st)) -+ (IS_CHILD_SA_ESTABLISHED(st) || st->st_state == STATE_CHILDSA_DEL)) - delete_ipsec_sa(st, FALSE); - else if (IS_ONLY_INBOUND_IPSEC_SA_ESTABLISHED(st->st_state)) - delete_ipsec_sa(st, TRUE); diff --git a/SOURCES/libreswan-3.12-1105171-manpage.patch b/SOURCES/libreswan-3.12-1105171-manpage.patch deleted file mode 100644 index a13c8db..0000000 --- a/SOURCES/libreswan-3.12-1105171-manpage.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff -Naur libreswan-3.12-orig/programs/configs/d.ipsec.conf/ike.xml libreswan-3.12/programs/configs/d.ipsec.conf/ike.xml ---- libreswan-3.12-orig/programs/configs/d.ipsec.conf/ike.xml 2014-11-06 22:52:50.000000000 -0500 -+++ libreswan-3.12/programs/configs/d.ipsec.conf/ike.xml 2014-12-03 09:40:41.917495865 -0500 -@@ -16,8 +16,7 @@ - ike=aes, - ike=aes128-md5;modp2048, - ike=aes128-sha1;dh22, --ike=3des-md5;modp1024,aes-sha1;modp1536 or --ike=modp1536. -+ike=3des-md5;modp1024,aes-sha1;modp1536. - The options must be suitable as a value of - ipsec_spi8's - option. The default is to use IKE, and to allow all combinations of: diff --git a/SOURCES/libreswan-3.12-1131503-invalid-ke.patch b/SOURCES/libreswan-3.12-1131503-invalid-ke.patch deleted file mode 100644 index a6ca14b..0000000 --- a/SOURCES/libreswan-3.12-1131503-invalid-ke.patch +++ /dev/null @@ -1,592 +0,0 @@ -diff -Naur libreswan-3.12-orig/include/packet.h libreswan-3.12/include/packet.h ---- libreswan-3.12-orig/include/packet.h 2014-11-06 22:52:50.000000000 -0500 -+++ libreswan-3.12/include/packet.h 2014-12-23 21:28:05.703817443 -0500 -@@ -943,4 +943,10 @@ - struct ikev2_cp_attribute v2cp_attribute; - }; - -+struct suggested_group { -+ u_int16_t /*oakley_group_t*/ sg_group; -+}; -+ -+extern struct_desc suggested_group_desc; -+ - #endif /* _PACKET_H */ -diff -Naur libreswan-3.12-orig/programs/pluto/ikev2.c libreswan-3.12/programs/pluto/ikev2.c ---- libreswan-3.12-orig/programs/pluto/ikev2.c 2014-12-23 21:17:09.810251869 -0500 -+++ libreswan-3.12/programs/pluto/ikev2.c 2014-12-23 21:24:07.883811100 -0500 -@@ -65,6 +65,12 @@ - - #include "pluto_crypt.h" /* just for log_crypto_workers() */ - -+#include "alg_info.h" /* for ALG_INFO_IKE_FOREACH */ -+ -+#include "ietf_constants.h" -+ -+#include "plutoalg.h" /* for default_ike_groups */ -+ - /* Note: same definition appears in programs/pluto/ikev2_parent.c */ - #define SEND_V2_NOTIFICATION(t) { \ - if (st != NULL) \ -@@ -895,6 +901,17 @@ - } - } - -+void send_v2_notification_invalid_ke(struct state *st) -+{ -+ const u_int16_t gr = htons(first_modp_from_propset( -+ st->st_connection->alg_info_ike)); /* oakley_group_t */ -+ chunk_t nd = {(unsigned char *)&gr, sizeof(gr) }; -+ -+ /* RFC 5996, Section 2.6 recommends using 0 responder SPI */ -+ send_v2_notification(st, v2N_INVALID_KE_PAYLOAD, NULL, -+ st->st_icookie, NULL, &nd); -+} -+ - void send_v2_notification_from_state(struct state *st, - v2_notification_t type, - chunk_t *data) -@@ -1319,15 +1336,28 @@ - /* - * Only send a notify is this packet was a request, - * not if it was a reply. -- * ??? is this a reasonable choice? - */ -- if (!(md->hdr.isa_flags & ISAKMP_FLAGS_v2_MSG_R)) -- /* -- * ??? if this can be sent as part of an -- * existing exchange, rather than a new -- * Informational Exchange, should it not be? -- */ -- SEND_V2_NOTIFICATION(md->note); -+ if (!(md->hdr.isa_flags & ISAKMP_FLAGS_v2_MSG_R)) { -+ DBG(DBG_CONTROL, DBG_log("sending a notification reply")); -+ /* Check if this is an IKE_INIT reply w INVALID_KE */ -+ if (md->hdr.isa_xchg == ISAKMP_v2_SA_INIT && -+ md->note == (notification_t)v2N_INVALID_KE_PAYLOAD) { -+ DBG(DBG_CONTROL, DBG_log("sending IKE_INIT with INVALID_KE")); -+ send_v2_notification_invalid_ke(md->st); -+ } else { -+ /* -+ * ??? if this can be sent as part of an -+ * existing exchange, rather than a new -+ * Informational Exchange, should it not be? -+ * -+ * Paul: The macro expands to -+ * send_v2_notification_from_state() and if -+ * st != NULL then calls send_v2_notification -+ * which hardcodes ISAKMP_v2_SA_INIT -+ */ -+ SEND_V2_NOTIFICATION(md->note); -+ } -+ } - } - - DBG(DBG_CONTROL, -@@ -1362,3 +1392,56 @@ - clonereplacechunk(*dest, nonce_pbs->cur, len, "nonce"); - return v2N_NOTHING_WRONG; - } -+ -+ -+bool modp_in_propset(oakley_group_t received, struct alg_info_ike *ai_list) -+{ -+ -+ if (lookup_group(received) == NULL) { -+ DBG(DBG_CONTROL, DBG_log( -+ "Received DH group %d not supported", received)); -+ return FALSE; -+ } -+ -+ if (ai_list != NULL) { -+ struct ike_info *ike_info; -+ int cnt; -+ -+ ALG_INFO_IKE_FOREACH(ai_list, ike_info, cnt) { -+ if (received == ike_info->ike_modp) -+ return TRUE; -+ } -+ DBG(DBG_CONTROL, DBG_log( -+ "received DH group %d not in our proposal set", received)); -+ return FALSE; -+ } else { -+ unsigned int cnt; -+ -+ DBG(DBG_CONTROL,DBG_log("check our default proposal for receievd DH group")); -+ for (cnt = 0; cnt < elemsof(default_ike_groups); cnt++) { -+ if (received == default_ike_groups[cnt]) -+ return TRUE; -+ } -+ DBG(DBG_CONTROL,DBG_log("received DH group not in our default proposal")); -+ return FALSE; -+ } -+} -+ -+oakley_group_t first_modp_from_propset(struct alg_info_ike *ai_list) -+{ -+ struct ike_info *ike_info; -+ int cnt; -+ -+ if (ai_list == NULL) -+ return default_ike_groups[0]; -+ -+ ALG_INFO_IKE_FOREACH(ai_list, ike_info, cnt) { -+ if (ike_info->ike_modp != OAKLEY_GROUP_invalid) { -+ /* confirm we support it */ -+ if (lookup_group(ike_info->ike_modp) != NULL) -+ return ike_info->ike_modp; -+ } -+ } -+ /* no valid groups, again pick first from default list */ -+ return default_ike_groups[0]; -+} -diff -Naur libreswan-3.12-orig/programs/pluto/ikev2.h libreswan-3.12/programs/pluto/ikev2.h ---- libreswan-3.12-orig/programs/pluto/ikev2.h 2014-11-06 22:52:50.000000000 -0500 -+++ libreswan-3.12/programs/pluto/ikev2.h 2014-12-23 21:24:36.251527561 -0500 -@@ -206,3 +206,7 @@ - stf_status ikev2_send_cp(struct connection *c, enum next_payload_types_ikev2 np, - pb_stream *outpbs); - bool ikev2_parse_cp_r_body(struct payload_digest *cp_pd, struct state *st); -+ -+void send_v2_notification_invalid_ke(struct state *st); -+bool modp_in_propset(oakley_group_t received, struct alg_info_ike *ai_list); -+oakley_group_t first_modp_from_propset(struct alg_info_ike *ai_list); -diff -Naur libreswan-3.12-orig/programs/pluto/ikev2_parent.c libreswan-3.12/programs/pluto/ikev2_parent.c ---- libreswan-3.12-orig/programs/pluto/ikev2_parent.c 2014-12-23 21:17:09.811251894 -0500 -+++ libreswan-3.12/programs/pluto/ikev2_parent.c 2014-12-23 21:24:40.046623408 -0500 -@@ -61,6 +61,11 @@ - #include "pending.h" - #include "kernel.h" - #include "nat_traversal.h" -+#include "alg_info.h" /* for ALG_INFO_IKE_FOREACH */ -+ -+#include "nss3/key.h" /* for SECKEY_DestroyPublicKey */ -+ -+#include "ietf_constants.h" - - /* Note: same definition appears in programs/pluto/ikev2.c */ - #define SEND_V2_NOTIFICATION(t) { \ -@@ -92,6 +97,8 @@ - static stf_status ikev2_child_inIoutR_tail(struct qke_continuation *qke, - struct pluto_crypto_req *r); - -+static stf_status crypto_helper_build_ke(struct state *st); -+ - /* - * This code assumes that the encrypted part of an IKE message starts - * with an Initialization Vector (IV) of enc_blocksize of random octets. -@@ -108,6 +115,27 @@ - return out_raw(ivbuf, ivsize, pbs, "IV"); - } - -+static stf_status crypto_helper_build_ke(struct state *st) -+{ -+ struct ke_continuation *ke = alloc_thing( -+ struct ke_continuation, -+ "ikev2_outI1 KE"); -+ stf_status e; -+ -+ /* ??? fake an md since we aren't based on one */ -+ ke->ke_md = alloc_md(); -+ ke->ke_md->from_state = STATE_IKEv2_BASE; -+ ke->ke_md->svm = &ikev2_parent_firststate_microcode; -+ ke->ke_md->st = st; -+ set_suspended(st, ke->ke_md); -+ -+ pcrc_init(&ke->ke_pcrc, ikev2_parent_outI1_continue); -+ e = build_ke_and_nonce(&ke->ke_pcrc, st, st->st_oakley.group, -+ pcim_stranger_crypto); -+ -+ return e; -+} -+ - /* - * - *************************************************************** -@@ -179,9 +207,9 @@ - * number needs to be initialized. - */ - { -+ - oakley_group_t groupnum = OAKLEY_GROUP_invalid; - struct db_sa *sadb; -- unsigned int pc_cnt; - - /* inscrutable dance of the sadbs */ - sadb = &oakley_sadb[sadb_index(policy, c)]; -@@ -196,77 +224,23 @@ - sadb = sa_v2_convert(sadb); - st->st_sadb = sadb; - -- /* look at all the proposals for the first group specified */ -- -- for (pc_cnt = 0; -- pc_cnt < sadb->prop_disj_cnt && -- groupnum == 0; -- pc_cnt++) -- { -- /* look at all the proposals in this disjunction */ -- struct db_v2_prop *vp = &sadb->prop_disj[pc_cnt]; -- unsigned int pr_cnt; -- -- for (pr_cnt = 0; -- pr_cnt < vp->prop_cnt && groupnum == OAKLEY_GROUP_invalid; -- pr_cnt++) -- { -- struct db_v2_prop_conj *vpc = &vp->props[pr_cnt]; -- unsigned int ts_cnt; -- -- for (ts_cnt = 0; -- ts_cnt < vpc->trans_cnt && groupnum == OAKLEY_GROUP_invalid; -- ts_cnt++) -- { -- struct db_v2_trans *tr = -- &vpc->trans[ts_cnt]; -+ /* Grab the DH group from the first configured proposal to build KE */ -+ groupnum = first_modp_from_propset(c->alg_info_ike); - -- /* ??? why would tr be NULL? */ -- if (tr != NULL && -- tr->transform_type -- == IKEv2_TRANS_TYPE_DH) -- { -- groupnum = tr->transid; -- } -- } -- } -+ if (groupnum == OAKLEY_GROUP_invalid) { -+ libreswan_log("No valid MODP group found in configuration, defaulting to first default"); -+ groupnum = default_ike_groups[0]; - } -- if (groupnum == OAKLEY_GROUP_invalid) -- groupnum = OAKLEY_GROUP_MODP2048; - st->st_oakley.group = lookup_group(groupnum); /* NULL if unknown */ -+ passert(st->st_oakley.group != NULL); - st->st_oakley.groupnum = groupnum; - } -+ - /* now we need to go calculate the nonce, and the KE */ - { -- struct ke_continuation *ke = alloc_thing( -- struct ke_continuation, -- "ikev2_outI1 KE"); -- stf_status e; -- -- /* ??? fake an md since we aren't based on one */ -- ke->ke_md = alloc_md(); -- ke->ke_md->from_state = STATE_IKEv2_BASE; -- ke->ke_md->svm = &ikev2_parent_firststate_microcode; -- ke->ke_md->st = st; -- set_suspended(st, ke->ke_md); -- -- /* -- * ??? how would st->st_sec_in_use? -- * This routine creates *st itself so how would this field -- * be already filled-in. -- */ -- pexpect(!st->st_sec_in_use); -- if (!st->st_sec_in_use) { -- pcrc_init(&ke->ke_pcrc, ikev2_parent_outI1_continue); -- e = build_ke_and_nonce(&ke->ke_pcrc, st, st->st_oakley.group, -- importance); -- } else { -- ke->ke_pcrc.pcrc_serialno = st->st_serialno; /* transitional */ -- e = ikev2_parent_outI1_tail(ke, NULL); -- } -+ stf_status e = crypto_helper_build_ke(st); - - reset_globals(); -- - return e; - } - } -@@ -607,7 +582,7 @@ - /* we received dcookie we send earlier verify it */ - if (md->chain[ISAKMP_NEXT_v2N]->payload.v2n.isan_spisize != 0) { - DBG(DBG_CONTROLMORE, DBG_log( -- "DOS cookie contains non-zero length SPI - message dropped" -+ "DOS cookie contains non-zero length SPI - message discarded" - )); - return STF_IGNORE; - } -@@ -767,26 +742,15 @@ - md->from_state = STATE_IKEv2_BASE; - } - -- -- /* -- * We have to agree to the DH group before we actually know who -- * we are talking to. If we support the group, we use it. -- * -- * It is really too hard here to go through all the possible policies -- * that might permit this group. If we think we are being DOS'ed -- * then we should demand a cookie. -- */ - { - struct ikev2_ke *ke = &md->chain[ISAKMP_NEXT_v2KE]->payload.v2ke; - - st->st_oakley.group = lookup_group(ke->isak_group); -- if (st->st_oakley.group == NULL) { -- ipstr_buf b; - -- libreswan_log( -- "rejecting I1 from %s:%u, invalid DH group=%u", -- ipstr(&md->sender, &b), md->sender_port, -- ke->isak_group); -+ if (!modp_in_propset(ke->isak_group,c->alg_info_ike)){ -+ DBG(DBG_CONTROL, DBG_log("need to send INVALID_KE for modp %d and suggest %d", -+ ke->isak_group, -+ first_modp_from_propset(c->alg_info_ike))); - return STF_FAIL + v2N_INVALID_KE_PAYLOAD; - } - } -@@ -966,16 +930,18 @@ - * RFC 5996 1.3 says that we should return - * our desired group number when rejecting sender's. - */ -- u_int16_t group_number = htons( -- st->st_oakley.group->group); -- chunk_t dc = { (unsigned char *)&group_number, -- sizeof(group_number) }; -+ u_int16_t gn = htons(st->st_oakley.group->group); -+ chunk_t dc = { (unsigned char *)&gn, sizeof(gn) }; - -+ DBG(DBG_CONTROL, DBG_log("INVALID_KEY_INFORMATION:, sending invalid_ke back with %s", -+ strip_prefix(enum_show(&oakley_group_names, -+ st->st_oakley.group->group), -+ "OAKLEY_GROUP_"))); - send_v2_notification_from_state(st, - v2N_INVALID_KE_PAYLOAD, &dc); -- delete_state(st); -+ delete_state(st); /* nothing to do or remember */ - md->st = NULL; -- return STF_FAIL; /* don't send second notification */ -+ return STF_FAIL; - } - default: - /* hope v1 and v2 notifications correspond! */ -@@ -1076,9 +1042,19 @@ - struct payload_digest *ntfy; - - for (ntfy = md->chain[ISAKMP_NEXT_v2N]; ntfy != NULL; ntfy = ntfy->next) { -+ if (ntfy->payload.v2n.isan_spisize != 0) { -+ DBG(DBG_CONTROLMORE, DBG_log( -+ "Notify payload for IKE must have zero length SPI - message dropped" -+ )); -+ return STF_IGNORE; -+ } - switch (ntfy->payload.v2n.isan_type) { - case v2N_COOKIE: - { -+ /* careful of DDOS, only log with debugging on */ -+ -+ -+ - /* - * Responder replied with N(COOKIE) for DOS avoidance. - * See rfc5996bis-04 2.6. -@@ -1086,19 +1062,22 @@ - * Our state should not advance. Instead - * we should send our I1 packet with the same cookie. - */ -- u_int8_t spisize; - const pb_stream *dc_pbs; - - if (ntfy != md->chain[ISAKMP_NEXT_v2N] || ntfy->next != NULL) { -- libreswan_log("v2N_COOKIE must be only notification in packet"); -- return STF_FAIL + v2N_INVALID_SYNTAX; -+ DBG(DBG_CONTROL, DBG_log("non-v2N_COOKIE notify payload(s) ignored ")); -+ } -+ DBG(DBG_CONTROL, DBG_log("Received anti-DDOS COOKIE -resending I1 with cookie payload")); -+ if (ntfy->payload.v2n.isan_spisize != 0) { -+ DBG(DBG_CONTROLMORE, DBG_log( -+ "DOS cookie notify for IKE must have zero length SPI - message dropped" -+ )); -+ return STF_IGNORE; - } -- libreswan_log("Received anti-DDOS COOKIE -resending I1 with cookie payload"); -- spisize = ntfy->payload.v2n.isan_spisize; - dc_pbs = &ntfy->pbs; - clonetochunk(st->st_dcookie, -- dc_pbs->cur + spisize, -- pbs_left(dc_pbs) - spisize, -+ dc_pbs->cur, -+ pbs_left(dc_pbs), - "saved received dcookie"); - - DBG(DBG_CONTROLMORE, -@@ -1115,12 +1094,48 @@ - - return ikev2_parent_outI1_common(md, st); - } -+ - case v2N_INVALID_KE_PAYLOAD: -+ { -+ /* careful of DDOS, only log with debugging on */ -+ struct suggested_group sg; -+ -+ /* we treat this as a "retransmit" event to rate limit these */ -+ if (st->st_retransmit >= MAXIMUM_RETRANSMISSIONS) { -+ DBG(DBG_CONTROLMORE, DBG_log("ignoring received INVALID_KE packets - received too many (DoS?)")); -+ return STF_IGNORE; -+ } -+ st->st_retransmit++; -+ -+ if (!in_struct(&sg, &suggested_group_desc, -+ &ntfy->pbs, NULL)) -+ return STF_IGNORE; -+ -+ if (modp_in_propset(sg.sg_group, -+ st->st_connection->alg_info_ike)) { -+ -+ DBG(DBG_CONTROLMORE, DBG_log("Suggested modp group is acceptable")); -+ st->st_oakley.groupnum = sg.sg_group; -+ st->st_oakley.group = lookup_group(sg.sg_group); -+ libreswan_log("Received unauthenticated INVALID_KE with suggested group %s; resending with updated modp group", -+ strip_prefix(enum_show(&oakley_group_names, -+ sg.sg_group), "OAKLEY_GROUP_")); -+ clear_dh_from_state(st); /* wipe our mismatched KE */ -+ /* get a new KE */ -+ return crypto_helper_build_ke(st); -+ } else { -+ libreswan_log("Ignoring received unauthenticated INVALID_KE with unacceptable DH group suggestion %s", -+ strip_prefix(enum_show(&oakley_group_names, -+ sg.sg_group), "OAKLEY_GROUP_")); -+ return STF_IGNORE; -+ } -+ } -+ - case v2N_NO_PROPOSAL_CHOSEN: - default: - /* -- * ??? At least INVALID_KE_PAYLOAD and NO_PROPOSAL_CHOSEN -- * are legal and should keep us in this state. -+ * ??? At least NO_PROPOSAL_CHOSEN -+ * is legal and should keep us in this state. - * The responder SPI ought to have been 0 (but might not be). - * See rfc5996bis-04 2.6. - */ -@@ -2856,7 +2871,8 @@ - - zero(&hdr); - hdr.isa_version = build_ikev2_version(); -- memcpy(hdr.isa_rcookie, rcookie, COOKIE_SIZE); -+ if (rcookie != NULL) /* some responses are with zero rSPI */ -+ memcpy(hdr.isa_rcookie, rcookie, COOKIE_SIZE); - memcpy(hdr.isa_icookie, icookie, COOKIE_SIZE); - hdr.isa_xchg = ISAKMP_v2_SA_INIT; - hdr.isa_np = ISAKMP_NEXT_v2N; -@@ -4046,3 +4062,4 @@ - << ISA_MAJ_SHIFT) | (IKEv2_MINOR_VERSION + - (DBGP(IMPAIR_MINOR_VERSION_BUMP) ? 1 : 0)); - } -+ -diff -Naur libreswan-3.12-orig/programs/pluto/ikev2_spdb_struct.c libreswan-3.12/programs/pluto/ikev2_spdb_struct.c ---- libreswan-3.12-orig/programs/pluto/ikev2_spdb_struct.c 2014-12-23 21:17:09.797251541 -0500 -+++ libreswan-3.12/programs/pluto/ikev2_spdb_struct.c 2014-12-23 21:24:43.006698168 -0500 -@@ -427,6 +427,7 @@ - struct db_v2_prop_conj *pc; - struct db_v2_prop *pr; - -+ DBG(DBG_CONTROL, DBG_log("sa_v2_convert() called - known to be done repeatedly")); - if (f == NULL) - return NULL; - -diff -Naur libreswan-3.12-orig/programs/pluto/packet.c libreswan-3.12/programs/pluto/packet.c ---- libreswan-3.12-orig/programs/pluto/packet.c 2014-11-06 22:52:50.000000000 -0500 -+++ libreswan-3.12/programs/pluto/packet.c 2014-12-23 21:29:21.210724396 -0500 -@@ -1251,6 +1251,17 @@ - &ikev2_cp_desc, /* 57 ISAKMP_NEXT_v2CP */ - }; - -+static field_desc suggested_group_fields[] = { -+ { ft_enum, 16 / BITS_PER_BYTE, "suggested DH Group", &oakley_group_names }, -+ { ft_end, 0, NULL, NULL } -+}; -+ -+struct_desc suggested_group_desc = { -+ "Suggested Group", -+ suggested_group_fields, -+ sizeof(struct suggested_group) -+}; -+ - const struct_desc *payload_desc(unsigned p) - { - return p < elemsof(payload_descs) ? payload_descs[p] : NULL; -diff -Naur libreswan-3.12-orig/programs/pluto/plutoalg.c libreswan-3.12/programs/pluto/plutoalg.c ---- libreswan-3.12-orig/programs/pluto/plutoalg.c 2014-11-06 22:52:50.000000000 -0500 -+++ libreswan-3.12/programs/pluto/plutoalg.c 2014-12-23 21:25:11.876427304 -0500 -@@ -178,9 +178,9 @@ - * Proposals will be built by looping over default_ike_groups array and - * merging alg_info (ike_info) contents - */ --static const int default_ike_groups[] = { DEFAULT_OAKLEY_GROUPS }; - static const int default_ike_ealgs[] = { DEFAULT_OAKLEY_EALGS }; - static const int default_ike_aalgs[] = { DEFAULT_OAKLEY_AALGS }; -+/* default_ike_groups now non-static and moved to plutoalg.h */ - - /* - * Add IKE alg info _with_ logic (policy): -diff -Naur libreswan-3.12-orig/programs/pluto/plutoalg.h libreswan-3.12/programs/pluto/plutoalg.h ---- libreswan-3.12-orig/programs/pluto/plutoalg.h 2014-11-06 22:52:50.000000000 -0500 -+++ libreswan-3.12/programs/pluto/plutoalg.h 2014-12-23 21:25:15.906529088 -0500 -@@ -17,3 +17,5 @@ - const struct alg_info_esp *alg_info); - - extern bool ikev1_verify_ah(int aalg, const struct alg_info_esp *alg_info); -+ -+static const oakley_group_t default_ike_groups[] = { DEFAULT_OAKLEY_GROUPS }; /* used for invalid_ke */ -diff -Naur libreswan-3.12-orig/programs/pluto/spdb.h libreswan-3.12/programs/pluto/spdb.h ---- libreswan-3.12-orig/programs/pluto/spdb.h 2014-11-06 22:52:50.000000000 -0500 -+++ libreswan-3.12/programs/pluto/spdb.h 2014-12-23 21:25:18.996607131 -0500 -@@ -196,9 +196,9 @@ - extern struct db_sa *sa_merge_proposals(struct db_sa *a, struct db_sa *b); - - /* in spdb_print.c - normally never used in pluto */ --extern void sa_print(struct db_sa *f); -+extern void sa_log(struct db_sa *f); - --extern void sa_v2_print(struct db_sa *f); -+extern void sa_v2_log(struct db_sa *f); - - /* IKEv1 <-> IKEv2 things */ - extern struct db_sa *sa_v2_convert(struct db_sa *f); -diff -Naur libreswan-3.12-orig/programs/pluto/state.c libreswan-3.12/programs/pluto/state.c ---- libreswan-3.12-orig/programs/pluto/state.c 2014-12-23 21:17:09.818252071 -0500 -+++ libreswan-3.12/programs/pluto/state.c 2014-12-23 21:25:22.092685326 -0500 -@@ -512,10 +512,7 @@ - free_sa(st->st_sadb); - st->st_sadb = NULL; - -- if (st->st_sec_in_use) { -- SECKEY_DestroyPublicKey(st->st_pubk_nss); -- SECKEY_DestroyPrivateKey(st->st_sec_nss); -- } -+ clear_dh_from_state(st); - - freeanychunk(st->st_firstpacket_me); - freeanychunk(st->st_firstpacket_him); -@@ -1883,3 +1880,13 @@ - } - return FALSE; - } -+ -+void clear_dh_from_state(struct state *st) -+{ -+ /* when responding with INVALID_DH, we didn't do the work yet */ -+ if (st->st_sec_in_use) { -+ SECKEY_DestroyPublicKey(st->st_pubk_nss); -+ SECKEY_DestroyPrivateKey(st->st_sec_nss); -+ st->st_sec_in_use = FALSE; -+ } -+} -diff -Naur libreswan-3.12-orig/programs/pluto/state.h libreswan-3.12/programs/pluto/state.h ---- libreswan-3.12-orig/programs/pluto/state.h 2014-11-06 22:52:50.000000000 -0500 -+++ libreswan-3.12/programs/pluto/state.h 2014-12-23 21:25:28.450845908 -0500 -@@ -540,5 +540,6 @@ - } while (0) - - extern bool state_busy(const struct state *st); -+extern void clear_dh_from_state(struct state *st); - - #endif /* _STATE_H */ diff --git a/SOURCES/libreswan-3.12-1134297-aes_ctr.patch b/SOURCES/libreswan-3.12-1134297-aes_ctr.patch deleted file mode 100644 index 0a5f163..0000000 --- a/SOURCES/libreswan-3.12-1134297-aes_ctr.patch +++ /dev/null @@ -1,2061 +0,0 @@ -diff -Naur libreswan-3.12-orig/lib/libswan/constants.c libreswan-3.12/lib/libswan/constants.c ---- libreswan-3.12-orig/lib/libswan/constants.c 2014-11-06 22:52:50.000000000 -0500 -+++ libreswan-3.12/lib/libswan/constants.c 2014-12-30 22:36:06.812000000 -0500 -@@ -1161,12 +1161,12 @@ - "OAKLEY_3DES_CBC", - "OAKLEY_CAST_CBC", - "OAKLEY_AES_CBC", -- "DISABLED-OAKLEY_CAMELLIA_CBC", /* 8 */ -+ "OAKLEY_CAMELLIA_CBC", /* 8 */ - "UNUSED_9", - "UNUSED_10", - "UNUSED_11", - "UNUSED_12", -- "DISABLED-OAKLEY_AES_CTR", /* stolen from IKEv2 */ -+ "OAKLEY_AES_CTR", /* stolen from IKEv2 */ - "OAKLEY_AES_CCM_A", - "OAKLEY_AES_CCM_B", - "OAKLEY_AES_CCM_16", -diff -Naur libreswan-3.12-orig/programs/pluto/cbc_test_vectors.c libreswan-3.12/programs/pluto/cbc_test_vectors.c ---- libreswan-3.12-orig/programs/pluto/cbc_test_vectors.c 1969-12-31 19:00:00.000000000 -0500 -+++ libreswan-3.12/programs/pluto/cbc_test_vectors.c 2014-12-30 22:36:06.813000000 -0500 -@@ -0,0 +1,217 @@ -+/* -*- mode: c; c-file-style: linux; -*- */ -+ -+#include -+#include -+ -+#include "constants.h" -+#include "lswalloc.h" -+#include "lswlog.h" -+ -+#include "ike_alg.h" -+#include "test_buffer.h" -+#include "cbc_test_vectors.h" -+ -+#include "nss.h" -+#include "pk11pub.h" -+ -+struct cbc_test_vector { -+ const char *description; -+ /* mumble something about algorithm setting here. */ -+ const char *key; -+ const char *iv; -+ const char *plaintext; -+ const char *ciphertext; -+}; -+ -+/* -+ * Ref: http://tools.ietf.org/html/rfc3602: Test Vectors -+ */ -+const struct cbc_test_vector aes_cbc_test_vectors[] = { -+ { -+ .description = "Case #1: Encrypting 16 bytes (1 block) using AES-CBC with 128-bit key", -+ .key = "0x06a9214036b8a15b512e03d534120006", -+ .iv = "0x3dafba429d9eb430b422da802c9fac41", -+ .plaintext = "Single block msg", -+ .ciphertext = "0xe353779c1079aeb82708942dbe77181a" -+ }, -+ { -+ .description = "Case #2: Encrypting 32 bytes (2 blocks) using AES-CBC with 128-bit key", -+ .key = "0xc286696d887c9aa0611bbb3e2025a45a", -+ .iv = "0x562e17996d093d28ddb3ba695a2e6f58", -+ .plaintext = -+ "0x000102030405060708090a0b0c0d0e0f" -+ "101112131415161718191a1b1c1d1e1f", -+ .ciphertext = -+ "0xd296cd94c2cccf8a3a863028b5e1dc0a" -+ "7586602d253cfff91b8266bea6d61ab1" -+ }, -+ { -+ .description = "Case #3: Encrypting 48 bytes (3 blocks) using AES-CBC with 128-bit key", -+ .key = "0x6c3ea0477630ce21a2ce334aa746c2cd", -+ .iv = "0xc782dc4c098c66cbd9cd27d825682c81", -+ .plaintext = "This is a 48-byte message (exactly 3 AES blocks)", -+ .ciphertext = -+ "0xd0a02b3836451753d493665d33f0e886" -+ "2dea54cdb293abc7506939276772f8d5" -+ "021c19216bad525c8579695d83ba2684" -+ }, -+ { -+ .description = "Case #4: Encrypting 64 bytes (4 blocks) using AES-CBC with 128-bit key", -+ .key = "0x56e47a38c5598974bc46903dba290349", -+ .iv = "0x8ce82eefbea0da3c44699ed7db51b7d9", -+ .plaintext = -+ "0xa0a1a2a3a4a5a6a7a8a9aaabacadaeaf" -+ "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf" -+ "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf" -+ "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf", -+ .ciphertext = -+ "0xc30e32ffedc0774e6aff6af0869f71aa" -+ "0f3af07a9a31a9c684db207eb0ef8e4e" -+ "35907aa632c3ffdf868bb7b29d3d46ad" -+ "83ce9f9a102ee99d49a53e87f4c3da55" -+ }, -+ { -+ .description = NULL, -+ } -+}; -+ -+/* -+ * https://tools.ietf.org/html/rfc4312 -+ * https://info.isl.ntt.co.jp/crypt/index.html -+ * https://info.isl.ntt.co.jp/crypt/eng/camellia/dl/cryptrec/t_camellia.txt -+ */ -+const struct cbc_test_vector camellia_cbc_test_vectors[] = { -+ { -+ .description = "Camellia: 16 bytes with 128-bit key #1", -+ .key = "0x" "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", -+ .iv = "0x" "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", -+ .plaintext = "0x" "80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", -+ .ciphertext = "0x" "07 92 3A 39 EB 0A 81 7D 1C 4D 87 BD B8 2D 1F 1C" -+ }, -+ { -+ .description = "Camellia: 16 bytes with 128-bit key #2", -+ .key = "0x" "00 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF", -+ .iv = "0x" "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", -+ .plaintext = "0x" "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 ", -+ .ciphertext = "0x" "14 4D 2B 0F 50 0C 27 B7 EC 2C D1 2D 91 59 6F 37" -+ }, -+ { -+ .description = "Camellia: 16 bytes with 256-bit key #1", -+ .key = "0x" "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", -+ .iv = "0x" "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", -+ .plaintext = "0x" "80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", -+ .ciphertext = "0x" "B0 C6 B8 8A EA 51 8A B0 9E 84 72 48 E9 1B 1B 9D" -+ }, -+ { -+ .description = "Camellia: 16 bytes with 256-bit key #2", -+ .key = "0x" "00 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF FF EE DD CC BB AA 99 88 77 66 55 44 33 22 11 00", -+ .iv = "0x" "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", -+ .plaintext = "0x" "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01", -+ .ciphertext = "0x" "CC 39 FF EE 18 56 D3 EB 61 02 5E 93 21 9B 65 23 " -+ }, -+ { -+ .description = NULL, -+ } -+}; -+ -+static int test_cbc_op(const struct encrypt_desc *encrypt_desc, -+ const char *description, int encrypt, -+ PK11SymKey *sym_key, const char *encoded_iv, -+ const char *input_name, const char *input, -+ const char *output_name, const char *output) -+{ -+ const char *op = encrypt ? "encrypt" : "decrypt"; -+ int ok = 1; -+ chunk_t iv = decode_to_chunk("IV: ", encoded_iv); -+ -+ /* -+ * If encrypting, the new iv is in the output, if decrypting, -+ * the new iv is the input. The expected IV is found in the -+ * last few bytes. -+ */ -+ chunk_t expected_iv = -+ decode_to_chunk("new IV: ", encrypt ? output : input); -+ chunk_t tmp = decode_to_chunk(input_name, input); -+ chunk_t expected = decode_to_chunk(output_name, output); -+ -+ /* do_crypt modifies the data and IV in place. */ -+ encrypt_desc->do_crypt(tmp.ptr, tmp.len, -+ sym_key, iv.ptr, encrypt); -+ -+ if (!compare_chunks(op, expected, tmp)) { -+ DBG(DBG_CRYPT, DBG_log("test_cbc_op: %s: %s: output does not match", description, op)); -+ ok = 0; -+ } -+ if (!compare_chunk("updated CBC IV", iv, -+ expected_iv.ptr + expected_iv.len - iv.len)) { -+ DBG(DBG_CRYPT, DBG_log("test_cbc_op: %s: %s: IV does not match", description, op)); -+ ok = 0; -+ } -+ -+ freeanychunk(iv); -+ freeanychunk(expected_iv); -+ freeanychunk(tmp); -+ freeanychunk(expected); -+ -+ return ok; -+} -+ -+/* -+ * https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/nss_sample_code/NSS_Sample_Code_sample2 -+ * https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/NSS_Tech_Notes/nss_tech_note5 -+ */ -+ -+static int test_cbc_vector(CK_MECHANISM_TYPE cipher_mechanism, -+ const struct encrypt_desc *encrypt_desc, -+ const struct cbc_test_vector *test) -+{ -+ int ok = 1; -+ DBG(DBG_CRYPT, DBG_log("test_cbc_vector: %s", test->description)); -+ -+ PK11SymKey *sym_key = decode_to_key(cipher_mechanism, test->key); -+ if (!test_cbc_op(encrypt_desc, test->description, 1, -+ sym_key, test->iv, -+ "plaintext: ", test->plaintext, -+ "ciphertext: ", test->ciphertext)) { -+ ok = 0; -+ } -+ if (!test_cbc_op(encrypt_desc, test->description, 0, -+ sym_key, test->iv, -+ "cipertext: ", test->ciphertext, -+ "plaintext: ", test->plaintext)) { -+ ok = 0; -+ } -+ -+ /* Clean up. */ -+ PK11_FreeSymKey(sym_key); -+ -+ DBG(DBG_CRYPT, DBG_log("test_ctr_vector: %s %s", -+ test->description, ok ? "passed" : "failed")); -+ return ok; -+} -+ -+static int test_cbc_vectors(CK_MECHANISM_TYPE cipher_mechanism, -+ const struct encrypt_desc *encrypt_desc, -+ const struct cbc_test_vector *tests) -+{ -+ int ok = 1; -+ const struct cbc_test_vector *test; -+ for (test = tests; test->description != NULL; test++) { -+ if (!test_cbc_vector(cipher_mechanism, encrypt_desc, test)) { -+ ok = 0; -+ } -+ } -+ return ok; -+} -+ -+int test_aes_cbc(const struct encrypt_desc *encrypt_desc) -+{ -+ return test_cbc_vectors(CKM_AES_CBC, encrypt_desc, -+ aes_cbc_test_vectors); -+} -+ -+int test_camellia_cbc(const struct encrypt_desc *encrypt_desc) -+{ -+ return test_cbc_vectors(CKM_CAMELLIA_CBC, encrypt_desc, -+ camellia_cbc_test_vectors); -+} -diff -Naur libreswan-3.12-orig/programs/pluto/cbc_test_vectors.h libreswan-3.12/programs/pluto/cbc_test_vectors.h ---- libreswan-3.12-orig/programs/pluto/cbc_test_vectors.h 1969-12-31 19:00:00.000000000 -0500 -+++ libreswan-3.12/programs/pluto/cbc_test_vectors.h 2014-12-30 22:36:06.813000000 -0500 -@@ -0,0 +1,2 @@ -+int test_camellia_cbc(const struct encrypt_desc *encrypt_desc); -+int test_aes_cbc(const struct encrypt_desc *encrypt_desc); -diff -Naur libreswan-3.12-orig/programs/pluto/crypt_dh.c libreswan-3.12/programs/pluto/crypt_dh.c ---- libreswan-3.12-orig/programs/pluto/crypt_dh.c 2014-11-06 22:52:50.000000000 -0500 -+++ libreswan-3.12/programs/pluto/crypt_dh.c 2014-12-30 22:36:06.814000000 -0500 -@@ -105,10 +105,10 @@ - case OAKLEY_CAMELLIA_CBC: - mechanism = CKM_CAMELLIA_CBC; - break; --#ifdef NOT_YET - case OAKLEY_AES_CTR: - mechanism = CKM_AES_CTR; - break; -+#ifdef NOT_YET - case OAKLEY_AES_CCM_8: - case OAKLEY_AES_CCM_12: - case OAKLEY_AES_CCM_16: -@@ -1075,7 +1075,7 @@ - /* okay, so now calculate IV */ - calc_skeyids_iv(&dhq, - shared, -- dhq.keysize, -+ dhq.key_size, - &skeyid, - &skeyid_d, - &skeyid_a, -@@ -1127,6 +1127,49 @@ - skr->shared = calc_dh_shared(g, ltsecret, group, pubk); - } - -+static chunk_t chunk_from_symkey(const char *name, PK11SymKey *source_key, -+ size_t next_bit, size_t byte_size) -+{ -+ if (byte_size == 0) { -+ DBG(DBG_CRYPT, DBG_log("chunk_from_symkey: %s: zero size", name)); -+ return empty_chunk; -+ } -+ CK_EXTRACT_PARAMS bs = next_bit; -+ SECItem param = { .data = (unsigned char*)&bs, .len = sizeof(bs) }; -+ PK11SymKey *sym_key = PK11_DeriveWithFlags(source_key, -+ CKM_EXTRACT_KEY_FROM_KEY, -+ ¶m, -+ CKM_VENDOR_DEFINED, -+ CKA_FLAGS_ONLY, byte_size, 0); -+ if (sym_key == NULL) { -+ loglog(RC_LOG_SERIOUS, "NSS: PK11_DeriveWithFlags failed while generating %s", name); -+ return empty_chunk; -+ } -+ SECStatus s = PK11_ExtractKeyValue(sym_key); -+ if (s != SECSuccess) { -+ loglog(RC_LOG_SERIOUS, "NSS: PK11_ExtractKeyValue failed while generating %s", name); -+ return empty_chunk; -+ } -+ /* Internal structure address, do not free. */ -+ SECItem *data = PK11_GetKeyData(sym_key); -+ if (data == NULL) { -+ loglog(RC_LOG_SERIOUS, "NSS: PK11_GetKeyData failed while generating %s", name); -+ return empty_chunk; -+ } -+ DBG(DBG_CRYPT, -+ DBG_log("chunk_from_symkey: %s: extracted len %d bytes at %p", -+ name, data->len, data->data)); -+ if (data->len != byte_size) { -+ loglog(RC_LOG_SERIOUS, "NSS: PK11_GetKeyData returned wrong number of bytes while generating %s", name); -+ return empty_chunk; -+ } -+ chunk_t chunk; -+ clonetochunk(chunk, data->data, data->len, name); -+ DBG(DBG_CRYPT, DBG_dump_chunk(name, chunk)); -+ PK11_FreeSymKey(sym_key); -+ return chunk; -+} -+ - /* - * IKEv2 - RFC4306 2.14 SKEYSEED - calculation. - */ -@@ -1134,7 +1177,8 @@ - /* MUST BE THREAD-SAFE */ - static void calc_skeyseed_v2(struct pcr_skeyid_q *skq, - PK11SymKey *shared, -- const size_t keysize, -+ const size_t key_size, -+ const size_t salt_size, - PK11SymKey **skeyseed_out, - PK11SymKey **SK_d_out, - PK11SymKey **SK_ai_out, -@@ -1142,7 +1186,9 @@ - PK11SymKey **SK_ei_out, - PK11SymKey **SK_er_out, - PK11SymKey **SK_pi_out, -- PK11SymKey **SK_pr_out -+ PK11SymKey **SK_pr_out, -+ chunk_t *initiator_salt_out, -+ chunk_t *responder_salt_out - ) - { - struct v2prf_stuff vpss; -@@ -1164,6 +1210,8 @@ - *SK_er_k, - *SK_pi_k, - *SK_pr_k; -+ chunk_t initiator_salt; -+ chunk_t responder_salt; - - zero(&vpss); - -@@ -1174,10 +1222,10 @@ - setchunk_from_wire(vpss.spir, skq, &skq->rcookie); - - DBG(DBG_CONTROLMORE, -- DBG_log("calculating skeyseed using prf=%s integ=%s cipherkey=%lu", -+ DBG_log("calculating skeyseed using prf=%s integ=%s cipherkey-size=%zu salt-size=%zu", - enum_name(&ikev2_trans_type_prf_names, skq->prf_hash), - enum_name(&ikev2_trans_type_integ_names, skq->integ_hash), -- (long unsigned)keysize)); -+ key_size, salt_size)); - - const struct hash_desc *hasher = (struct hash_desc *) - ikev2_alg_find(IKE_ALG_HASH, skq->prf_hash); -@@ -1200,22 +1248,22 @@ - /* now we have to generate the keys for everything */ - { - /* need to know how many bits to generate */ -- /* SK_d needs PRF hasher key bits */ -- /* SK_p needs PRF hasher*2 key bits */ -- /* SK_e needs keysize*2 key bits */ -- /* SK_a needs hash's key bits size */ -+ /* SK_d needs PRF hasher key bytes */ -+ /* SK_p needs PRF hasher*2 key bytes */ -+ /* SK_e needs key_size*2 key bytes */ -+ /* ..._salt needs salt_size*2 bytes */ -+ /* SK_a needs hash's key size */ - const struct hash_desc *integ_hasher = - (struct hash_desc *)ikev2_alg_find(IKE_ALG_INTEG, - skq->integ_hash); - int skd_bytes = hasher->hash_key_size; - int skp_bytes = hasher->hash_key_size; - int ska_bytes = integ_hasher->hash_key_size; -- int ske_bytes = keysize; - - vpss.counter[0] = 0x01; - vpss.t.len = 0; - total_keysize = skd_bytes + -- (2 * (ska_bytes + ske_bytes + skp_bytes)); -+ (2 * (ska_bytes + key_size + salt_size + skp_bytes)); - - DBG(DBG_CRYPT, { - DBG_log("PRF+ input"); -@@ -1223,8 +1271,8 @@ - DBG_dump_chunk("Nr", vpss.nr); - DBG_dump_chunk("SPIi", vpss.spii); - DBG_dump_chunk("SPIr", vpss.spir); -- DBG_log("Total keysize needed %d", -- (int)total_keysize); -+ DBG_log("Total keysize needed %zd", -+ total_keysize); - }); - - PK11SymKey *finalkey = NULL; -@@ -1417,52 +1465,62 @@ - DBG_log("NSS ikev2: finished computing key material for IKEv2 SA")); - - CK_EXTRACT_PARAMS bs = 0; -+ size_t next_bit = 0; - -- SK_d_k = pk11_extract_derive_wrapper_lsw(finalkey, bs, -+ SK_d_k = pk11_extract_derive_wrapper_lsw(finalkey, next_bit, - CKM_CONCATENATE_BASE_AND_DATA, CKA_DERIVE, - skd_bytes); -+ next_bit += skd_bytes * BITS_PER_BYTE; - -- bs = skd_bytes * BITS_PER_BYTE; -- SK_ai_k = pk11_extract_derive_wrapper_lsw(finalkey, bs, -+ SK_ai_k = pk11_extract_derive_wrapper_lsw(finalkey, next_bit, - CKM_CONCATENATE_BASE_AND_DATA, CKA_DERIVE, - ska_bytes); -+ next_bit += ska_bytes * BITS_PER_BYTE; - -- bs = (skd_bytes + ska_bytes) * BITS_PER_BYTE; -- SK_ar_k = pk11_extract_derive_wrapper_lsw(finalkey, bs, -+ SK_ar_k = pk11_extract_derive_wrapper_lsw(finalkey, next_bit, - CKM_CONCATENATE_BASE_AND_DATA, CKA_DERIVE, - ska_bytes); -+ next_bit += ska_bytes * BITS_PER_BYTE; - -- bs = (skd_bytes + (2 * ska_bytes)) * BITS_PER_BYTE; -+ bs = next_bit; - param1.data = (unsigned char*)&bs; - param1.len = sizeof(bs); - SK_ei_k = PK11_DeriveWithFlags(finalkey, - CKM_EXTRACT_KEY_FROM_KEY, - ¶m1, - nss_encryption_mech(encrypter), -- CKA_FLAGS_ONLY, ske_bytes, -+ CKA_FLAGS_ONLY, key_size, - CKF_ENCRYPT | CKF_DECRYPT); -+ next_bit += key_size * BITS_PER_BYTE; - -- bs = (skd_bytes + (2 * ska_bytes) + ske_bytes) * BITS_PER_BYTE; -+ initiator_salt = chunk_from_symkey("initiator salt", finalkey, -+ next_bit, salt_size); -+ next_bit += salt_size * BITS_PER_BYTE; -+ -+ bs = next_bit; - param1.data = (unsigned char*)&bs; - param1.len = sizeof(bs); - SK_er_k = PK11_DeriveWithFlags(finalkey, - CKM_EXTRACT_KEY_FROM_KEY, - ¶m1, -- nss_encryption_mech( -- encrypter), CKA_FLAGS_ONLY, ske_bytes, CKF_ENCRYPT | -- CKF_DECRYPT); -- -- bs = (skd_bytes + (2 * ska_bytes) + (2 * ske_bytes)) -- * BITS_PER_BYTE; -- SK_pi_k = pk11_extract_derive_wrapper_lsw(finalkey, bs, -+ nss_encryption_mech(encrypter), -+ CKA_FLAGS_ONLY, key_size, -+ CKF_ENCRYPT | CKF_DECRYPT); -+ next_bit += key_size * BITS_PER_BYTE; -+ -+ responder_salt = chunk_from_symkey("responder salt", finalkey, -+ next_bit, salt_size); -+ next_bit += salt_size * BITS_PER_BYTE; -+ -+ SK_pi_k = pk11_extract_derive_wrapper_lsw(finalkey, next_bit, - CKM_CONCATENATE_BASE_AND_DATA, CKA_DERIVE, - skp_bytes); -+ next_bit += skp_bytes * BITS_PER_BYTE; - -- bs = (skd_bytes + (2 * ska_bytes) + (2 * ske_bytes) + skp_bytes) -- * BITS_PER_BYTE; -- SK_pr_k = pk11_extract_derive_wrapper_lsw(finalkey, bs, -+ SK_pr_k = pk11_extract_derive_wrapper_lsw(finalkey, next_bit, - CKM_CONCATENATE_BASE_AND_DATA, CKA_DERIVE, - skp_bytes); -+ next_bit += skp_bytes * BITS_PER_BYTE; - - DBG(DBG_CRYPT, - DBG_log("NSS ikev2: finished computing individual keys for IKEv2 SA")); -@@ -1476,14 +1534,18 @@ - *SK_er_out = SK_er_k; - *SK_pi_out = SK_pi_k; - *SK_pr_out = SK_pr_k; -+ *initiator_salt_out = initiator_salt; -+ *responder_salt_out = responder_salt; - - freeanychunk(hmac_opad); - freeanychunk(hmac_ipad); - freeanychunk(hmac_pad_prf); - } - DBG(DBG_CRYPT, -- DBG_log("calc_skeyseed_v2 pointers: shared %p, skeyseed %p, SK_d %p, SK_ai %p, SK_ar %p, SK_ei %p, SK_er %p, SK_pi %p, SK_pr %p", -- shared, skeyseed_k, SK_d_k, SK_ai_k, SK_ar_k, SK_ei_k, SK_er_k, SK_pi_k, SK_pr_k)); -+ DBG_log("calc_skeyseed_v2 pointers: shared %p, skeyseed %p, SK_d %p, SK_ai %p, SK_ar %p, SK_ei %p, SK_er %p, SK_pi %p, SK_pr %p", -+ shared, skeyseed_k, SK_d_k, SK_ai_k, SK_ar_k, SK_ei_k, SK_er_k, SK_pi_k, SK_pr_k); -+ DBG_dump_chunk("calc_skeyseed_v2 initiator salt", initiator_salt); -+ DBG_dump_chunk("calc_skeyseed_v2 responder salt", responder_salt)); - } - - /* MUST BE THREAD-SAFE */ -@@ -1504,6 +1566,8 @@ - *SK_er, - *SK_pi, - *SK_pr; -+ chunk_t initiator_salt; -+ chunk_t responder_salt; - SECKEYPublicKey *pubk; - - /* copy the request, since the reply will re-use the memory of the r->pcr_d.dhq */ -@@ -1527,10 +1591,11 @@ - - shared = calc_dh_shared(g, ltsecret, group, pubk); - -- /* okay, so now calculate IV */ -+ /* okay, so now all the shared key material */ - calc_skeyseed_v2(&dhq, /* input */ - shared, /* input */ -- dhq.keysize, /* input */ -+ dhq.key_size, /* input */ -+ dhq.salt_size, /* input */ - - &skeyseed, /* output */ - &SK_d, /* output */ -@@ -1539,7 +1604,9 @@ - &SK_ei, /* output */ - &SK_er, /* output */ - &SK_pi, /* output */ -- &SK_pr); /* output */ -+ &SK_pr, /* output */ -+ &initiator_salt, /* output */ -+ &responder_salt); /* output */ - - skr->shared = shared; - skr->skeyseed = skeyseed; -@@ -1550,4 +1617,6 @@ - skr->skeyid_er = SK_er; - skr->skeyid_pi = SK_pi; - skr->skeyid_pr = SK_pr; -+ skr->skey_initiator_salt = initiator_salt; -+ skr->skey_responder_salt = responder_salt; - } -diff -Naur libreswan-3.12-orig/programs/pluto/crypto.c libreswan-3.12/programs/pluto/crypto.c ---- libreswan-3.12-orig/programs/pluto/crypto.c 2014-12-30 22:34:14.339000000 -0500 -+++ libreswan-3.12/programs/pluto/crypto.c 2014-12-30 22:36:06.815000000 -0500 -@@ -77,7 +77,8 @@ - .algo_next = NULL, }, - .enc_ctxsize = sizeof(des_key_schedule) * 3, - .enc_blocksize = DES_CBC_BLOCK_SIZE, -- .ivsize = DES_CBC_BLOCK_SIZE, -+ .pad_to_blocksize = TRUE, -+ .wire_iv_size = DES_CBC_BLOCK_SIZE, - .keydeflen = DES_CBC_BLOCK_SIZE * 3 * BITS_PER_BYTE, - .keyminlen = DES_CBC_BLOCK_SIZE * 3 * BITS_PER_BYTE, - .keymaxlen = DES_CBC_BLOCK_SIZE * 3 * BITS_PER_BYTE, -diff -Naur libreswan-3.12-orig/programs/pluto/crypt_start_dh.c libreswan-3.12/programs/pluto/crypt_start_dh.c ---- libreswan-3.12-orig/programs/pluto/crypt_start_dh.c 2014-11-06 22:52:50.000000000 -0500 -+++ libreswan-3.12/programs/pluto/crypt_start_dh.c 2014-12-30 22:36:06.814000000 -0500 -@@ -76,7 +76,8 @@ - dhq->prf_hash = st->st_oakley.prf_hash; - dhq->oakley_group = oakley_group2; - dhq->role = role; -- dhq->keysize = st->st_oakley.enckeylen / BITS_PER_BYTE; -+ dhq->key_size = st->st_oakley.enckeylen / BITS_PER_BYTE; -+ dhq->salt_size = st->st_oakley.encrypter->salt_size; - - passert(r.pcr_d.dhq.oakley_group != OAKLEY_GROUP_invalid); - DBG(DBG_CONTROL | DBG_CRYPT, -@@ -148,7 +149,8 @@ - dhq->prf_hash = st->st_oakley.prf_hash; - dhq->oakley_group = oakley_group2; - dhq->role = role; -- dhq->keysize = st->st_oakley.enckeylen / BITS_PER_BYTE; -+ dhq->key_size = st->st_oakley.enckeylen / BITS_PER_BYTE; -+ dhq->salt_size = st->st_oakley.encrypter->salt_size; - - if (pss != NULL) - WIRE_CLONE_CHUNK(*dhq, pss, *pss); -@@ -222,7 +224,8 @@ - dhq->integ_hash = st->st_oakley.integ_hash; - dhq->oakley_group = st->st_oakley.groupnum; - dhq->role = role; -- dhq->keysize = st->st_oakley.enckeylen / BITS_PER_BYTE; -+ dhq->key_size = st->st_oakley.enckeylen / BITS_PER_BYTE; -+ dhq->salt_size = st->st_oakley.encrypter->salt_size; - - passert(r.pcr_d.dhq.oakley_group != OAKLEY_GROUP_invalid); - -@@ -270,6 +273,8 @@ - st->st_skey_pr_nss = dhv2->skeyid_pr; - st->st_skey_ei_nss = dhv2->skeyid_ei; - st->st_skey_er_nss = dhv2->skeyid_er; -+ st->st_skey_initiator_salt = dhv2->skey_initiator_salt; -+ st->st_skey_responder_salt = dhv2->skey_responder_salt; - - st->hidden_variables.st_skeyid_calculated = TRUE; - } -diff -Naur libreswan-3.12-orig/programs/pluto/ctr_test_vectors.c libreswan-3.12/programs/pluto/ctr_test_vectors.c ---- libreswan-3.12-orig/programs/pluto/ctr_test_vectors.c 1969-12-31 19:00:00.000000000 -0500 -+++ libreswan-3.12/programs/pluto/ctr_test_vectors.c 2014-12-30 22:36:06.815000000 -0500 -@@ -0,0 +1,229 @@ -+/* -*- mode: c; c-file-style: linux; -*- */ -+ -+#include -+#include -+#include "constants.h" -+#include "lswalloc.h" -+#include "lswlog.h" -+ -+#include "ike_alg.h" -+#include "test_buffer.h" -+#include "ctr_test_vectors.h" -+ -+#include "nss.h" -+#include "pk11pub.h" -+ -+struct ctr_test_vector { -+ // CK_MECHANISM_TYPE cipher_mechanism; -+ // struct encrypt_desc *encrypt_desc; -+ const char *description; -+ const char *key; -+ const char *cb; -+ const char *plaintext; -+ const char *ciphertext; -+ const char *output_cb; -+}; -+ -+/* -+ * Ref: https://tools.ietf.org/html/rfc3686 Test Vectors -+ */ -+const struct ctr_test_vector aes_ctr_test_vectors[] = { -+ { -+ .description = "Test Vector #1: Encrypting 16 octets using AES-CTR with 128-bit key", -+ .key = "0x AE 68 52 F8 12 10 67 CC 4B F7 A5 76 55 77 F3 9E", -+ .plaintext = "0x 53 69 6E 67 6C 65 20 62 6C 6F 63 6B 20 6D 73 67", -+ .cb = "0x 00 00 00 30 00 00 00 00 00 00 00 00 00 00 00 01", -+ .ciphertext = "0x E4 09 5D 4F B7 A7 B3 79 2D 61 75 A3 26 13 11 B8", -+ .output_cb = "0x 00 00 00 30 00 00 00 00 00 00 00 00 00 00 00 02", -+ }, -+ { -+ .description = "Test Vector #2: Encrypting 32 octets using AES-CTR with 128-bit key", -+ .key = "0x 7E 24 06 78 17 FA E0 D7 43 D6 CE 1F 32 53 91 63", -+ .plaintext = "0x" -+ "00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F" -+ "10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F", -+ .cb = "0x 00 6C B6 DB C0 54 3B 59 DA 48 D9 0B 00 00 00 01", -+ .ciphertext = "0x" -+ "51 04 A1 06 16 8A 72 D9 79 0D 41 EE 8E DA D3 88" -+ "EB 2E 1E FC 46 DA 57 C8 FC E6 30 DF 91 41 BE 28", -+ .output_cb = "0x 00 6C B6 DB C0 54 3B 59 DA 48 D9 0B 00 00 00 03", -+ }, -+ { -+ .description = "Test Vector #3: Encrypting 36 octets using AES-CTR with 128-bit key", -+ .key = "0x 76 91 BE 03 5E 50 20 A8 AC 6E 61 85 29 F9 A0 DC", -+ .plaintext = "0x" -+ "00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F" -+ "10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F" -+ "20 21 22 23", -+ .cb = "0x 00 E0 01 7B 27 77 7F 3F 4A 17 86 F0 00 00 00 01", -+ .ciphertext = "0x" -+ "C1 CF 48 A8 9F 2F FD D9 CF 46 52 E9 EF DB 72 D7" -+ "45 40 A4 2B DE 6D 78 36 D5 9A 5C EA AE F3 10 53" -+ "25 B2 07 2F", -+ .output_cb = "0x 00 E0 01 7B 27 77 7F 3F 4A 17 86 F0 00 00 00 04", -+ }, -+ { -+ .description = "Test Vector #4: Encrypting 16 octets using AES-CTR with 192-bit key", -+ .key = "0x" -+ "16 AF 5B 14 5F C9 F5 79 C1 75 F9 3E 3B FB 0E ED" -+ "86 3D 06 CC FD B7 85 15", -+ .plaintext = "0x 53 69 6E 67 6C 65 20 62 6C 6F 63 6B 20 6D 73 67", -+ .cb = "0x 00 00 00 48 36 73 3C 14 7D 6D 93 CB 00 00 00 01", -+ .ciphertext = "0x 4B 55 38 4F E2 59 C9 C8 4E 79 35 A0 03 CB E9 28", -+ .output_cb = "0x 00 00 00 48 36 73 3C 14 7D 6D 93 CB 00 00 00 02", -+ }, -+ { -+ .description = "Test Vector #5: Encrypting 32 octets using AES-CTR with 192-bit key", -+ .key = "0x" -+ "7C 5C B2 40 1B 3D C3 3C 19 E7 34 08 19 E0 F6 9C" -+ "67 8C 3D B8 E6 F6 A9 1A", -+ .plaintext = "0x" -+ "00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F" -+ "10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F", -+ .cb = "0x 00 96 B0 3B 02 0C 6E AD C2 CB 50 0D 00 00 00 01", -+ .ciphertext = "0x" -+ "45 32 43 FC 60 9B 23 32 7E DF AA FA 71 31 CD 9F" -+ "84 90 70 1C 5A D4 A7 9C FC 1F E0 FF 42 F4 FB 00", -+ .output_cb = "0x 00 96 B0 3B 02 0C 6E AD C2 CB 50 0D 00 00 00 03", -+ }, -+ { -+ .description = "Test Vector #6: Encrypting 36 octets using AES-CTR with 192-bit key", -+ .key = "0x" -+ "02 BF 39 1E E8 EC B1 59 B9 59 61 7B 09 65 27 9B" -+ "F5 9B 60 A7 86 D3 E0 FE", -+ .plaintext = "0x" -+ "00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F" -+ "10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F" -+ "20 21 22 23", -+ .cb = "0x 00 07 BD FD 5C BD 60 27 8D CC 09 12 00 00 00 01", -+ .ciphertext = "0x" -+ "96 89 3F C5 5E 5C 72 2F 54 0B 7D D1 DD F7 E7 58" -+ "D2 88 BC 95 C6 91 65 88 45 36 C8 11 66 2F 21 88" -+ "AB EE 09 35", -+ .output_cb = "0x 00 07 BD FD 5C BD 60 27 8D CC 09 12 00 00 00 04", -+ }, -+ { -+ .description = "Test Vector #7: Encrypting 16 octets using AES-CTR with 256-bit key", -+ .key = "0x" -+ "77 6B EF F2 85 1D B0 6F 4C 8A 05 42 C8 69 6F 6C" -+ "6A 81 AF 1E EC 96 B4 D3 7F C1 D6 89 E6 C1 C1 04", -+ .plaintext = "0x 53 69 6E 67 6C 65 20 62 6C 6F 63 6B 20 6D 73 67", -+ .cb = "0x 00 00 00 60 DB 56 72 C9 7A A8 F0 B2 00 00 00 01", -+ .ciphertext = "0x 14 5A D0 1D BF 82 4E C7 56 08 63 DC 71 E3 E0 C0", -+ .output_cb = "0x 00 00 00 60 DB 56 72 C9 7A A8 F0 B2 00 00 00 02", -+ }, -+ { -+ .description = "Test Vector #8: Encrypting 32 octets using AES-CTR with 256-bit key", -+ .key = "0x" -+ "F6 D6 6D 6B D5 2D 59 BB 07 96 36 58 79 EF F8 86" -+ "C6 6D D5 1A 5B 6A 99 74 4B 50 59 0C 87 A2 38 84", -+ .plaintext = "0x" -+ "00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F" -+ "10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F", -+ .cb = "0x 00 FA AC 24 C1 58 5E F1 5A 43 D8 75 00 00 00 01", -+ .ciphertext = "0x" -+ "F0 5E 23 1B 38 94 61 2C 49 EE 00 0B 80 4E B2 A9" -+ "B8 30 6B 50 8F 83 9D 6A 55 30 83 1D 93 44 AF 1C", -+ .output_cb = "0x 00 FA AC 24 C1 58 5E F1 5A 43 D8 75 00 00 00 03", -+ }, -+ { -+ .description = "Test Vector #9: Encrypting 36 octets using AES-CTR with 256-bit key", -+ .key = "0x" -+ "FF 7A 61 7C E6 91 48 E4 F1 72 6E 2F 43 58 1D E2" -+ "AA 62 D9 F8 05 53 2E DF F1 EE D6 87 FB 54 15 3D", -+ .plaintext = "0x" -+ "00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F" -+ "10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F" -+ "20 21 22 23", -+ .cb = "0x 00 1C C5 B7 51 A5 1D 70 A1 C1 11 48 00 00 00 01", -+ .ciphertext = "0x" -+ "EB 6C 52 82 1D 0B BB F7 CE 75 94 46 2A CA 4F AA" -+ "B4 07 DF 86 65 69 FD 07 F4 8C C0 B5 83 D6 07 1F" -+ "1E C0 E6 B8", -+ .output_cb = "0x 00 1C C5 B7 51 A5 1D 70 A1 C1 11 48 00 00 00 04", -+ }, -+ { -+ .description = NULL, -+ } -+}; -+ -+static int test_ctr_op(const struct encrypt_desc *encrypt_desc, -+ const char *description, int encrypt, -+ PK11SymKey *sym_key, -+ const char *encoded_cb, const char *output_cb, -+ const char *input_name, const char *input, -+ const char *output_name, const char *output) -+{ -+ const char *op = encrypt ? "encrypt" : "decrypt"; -+ -+ int ok = 1; -+ chunk_t cb = decode_to_chunk("input counter-block: ", encoded_cb); -+ chunk_t tmp = decode_to_chunk(input_name, input); -+ chunk_t expected_output = decode_to_chunk(output_name, output); -+ chunk_t expected_cb = decode_to_chunk("expected counter-block: ", output_cb); -+ -+ /* do_crypt modifies the data and IV in place. */ -+ encrypt_desc->do_crypt(tmp.ptr, tmp.len, -+ sym_key, cb.ptr, encrypt); -+ if (!compare_chunks(op, expected_output, tmp)) { -+ DBG(DBG_CRYPT, DBG_log("test_ctr_op: %s: %s: output does not match", description, op)); -+ ok = 0; -+ } -+ if (!compare_chunks("counter-block", expected_cb, cb)) { -+ DBG(DBG_CRYPT, DBG_log("test_ctr_op: %s: %s: counter-block does not match", description, op)); -+ ok = 0; -+ } -+ -+ freeanychunk(cb); -+ freeanychunk(expected_cb); -+ freeanychunk(tmp); -+ freeanychunk(expected_output); -+ -+ return ok; -+} -+ -+static int test_ctr_vector(CK_MECHANISM_TYPE cipher_mechanism, -+ const struct encrypt_desc *encrypt_desc, -+ const struct ctr_test_vector *test) -+{ -+ DBG(DBG_CRYPT, DBG_log("test_ctr_vector: %s", test->description)); -+ int ok = 1; -+ -+ PK11SymKey *sym_key = decode_to_key(cipher_mechanism, test->key); -+ if (!test_ctr_op(encrypt_desc, test->description, 1, sym_key, -+ test->cb, test->output_cb, -+ "Plaintext", test->plaintext, -+ "Ciphertext", test->ciphertext)) { -+ ok = 0; -+ } -+ if (!test_ctr_op(encrypt_desc, test->description, 0, sym_key, -+ test->cb, test->output_cb, -+ "Ciphertext", test->ciphertext, -+ "Plaintext", test->plaintext)) { -+ ok = 0; -+ } -+ -+ PK11_FreeSymKey(sym_key); -+ DBG(DBG_CRYPT, DBG_log("test_ctr_vector: %s %s", -+ test->description, ok ? "passed" : "failed")); -+ return ok; -+} -+ -+static int test_ctr_vectors(CK_MECHANISM_TYPE cipher_mechanism, -+ const struct encrypt_desc *encrypt_desc, -+ const struct ctr_test_vector *tests) -+{ -+ int ok = 1; -+ const struct ctr_test_vector *test; -+ for (test = tests; test->description != NULL; test++) { -+ if (!test_ctr_vector(cipher_mechanism, encrypt_desc, test)) { -+ ok = 0; -+ } -+ } -+ return ok; -+} -+ -+int test_aes_ctr(struct encrypt_desc *encrypt_desc) -+{ -+ return test_ctr_vectors(CKM_AES_CTR, encrypt_desc, aes_ctr_test_vectors); -+} -diff -Naur libreswan-3.12-orig/programs/pluto/ctr_test_vectors.h libreswan-3.12/programs/pluto/ctr_test_vectors.h ---- libreswan-3.12-orig/programs/pluto/ctr_test_vectors.h 1969-12-31 19:00:00.000000000 -0500 -+++ libreswan-3.12/programs/pluto/ctr_test_vectors.h 2014-12-30 22:36:06.815000000 -0500 -@@ -0,0 +1,2 @@ -+int test_aes_ctr(struct encrypt_desc *encrypt_desc); -+ -diff -Naur libreswan-3.12-orig/programs/pluto/ike_alg_aes.c libreswan-3.12/programs/pluto/ike_alg_aes.c ---- libreswan-3.12-orig/programs/pluto/ike_alg_aes.c 2014-11-06 22:52:50.000000000 -0500 -+++ libreswan-3.12/programs/pluto/ike_alg_aes.c 2014-12-30 22:36:06.816000000 -0500 -@@ -36,6 +36,9 @@ - #include - #include "lswconf.h" - #include "lswlog.h" -+#include "ike_alg_nss_cbc.h" -+#include "ctr_test_vectors.h" -+#include "cbc_test_vectors.h" - - static void aes_xcbc_init_thunk(union hash_ctx *ctx) - { -@@ -52,83 +55,9 @@ - aes_xcbc_final(hash, &ctx->ctx_aes_xcbc); - } - --static void do_aes_cbc(u_int8_t *buf, size_t buf_len, PK11SymKey *symkey, -- u_int8_t *iv, bool enc) --{ -- -- u_int8_t iv_bak[AES_CBC_BLOCK_SIZE]; -- u_int8_t *new_iv = NULL; /* logic will avoid copy to NULL */ -- u_int8_t *tmp_buf; -- -- CK_MECHANISM_TYPE ciphermech; -- SECItem ivitem; -- SECItem *secparam; -- PK11Context *enccontext; -- SECStatus rv; -- int outlen; -- -- DBG(DBG_CRYPT, DBG_log("NSS do_aes_cbc: enter")); -- ciphermech = CKM_AES_CBC; /* libreswan provides padding */ -- -- if (symkey == NULL) { -- loglog(RC_LOG_SERIOUS, -- "do_aes_cbc: NSS derived enc key in NULL"); -- abort(); -- } -- -- ivitem.type = siBuffer; -- ivitem.data = iv; -- ivitem.len = AES_CBC_BLOCK_SIZE; -- -- secparam = PK11_ParamFromIV(ciphermech, &ivitem); -- if (secparam == NULL) { -- loglog(RC_LOG_SERIOUS, -- "do_aes_cbc: Failure to set up PKCS11 param (err %d)", -- PR_GetError()); -- abort(); -- } -- -- outlen = 0; -- tmp_buf = PR_Malloc((PRUint32)buf_len); -- -- if (!enc) { -- new_iv = iv_bak; -- memcpy(new_iv, -- (char*) buf + buf_len - AES_CBC_BLOCK_SIZE, -- AES_CBC_BLOCK_SIZE); -- } -- -- enccontext = PK11_CreateContextBySymKey(ciphermech, -- enc ? CKA_ENCRYPT : CKA_DECRYPT, symkey, -- secparam); -- if (enccontext == NULL) { -- loglog(RC_LOG_SERIOUS, -- "do_aes_cbc: PKCS11 context creation failure (err %d)", -- PR_GetError()); -- abort(); -- } -- -- rv = PK11_CipherOp(enccontext, tmp_buf, &outlen, buf_len, buf, -- buf_len); -- if (rv != SECSuccess) { -- loglog(RC_LOG_SERIOUS, -- "do_aes_cbc: PKCS11 operation failure (err %d)", -- PR_GetError()); -- abort(); -- } -- PK11_DestroyContext(enccontext, PR_TRUE); -- memcpy(buf, tmp_buf, buf_len); - -- if (enc) -- new_iv = (u_int8_t*) buf + buf_len - AES_CBC_BLOCK_SIZE; -- -- memcpy(iv, new_iv, AES_CBC_BLOCK_SIZE); -- PR_Free(tmp_buf); -- -- if (secparam != NULL) -- SECITEM_FreeItem(secparam, PR_TRUE); -- DBG(DBG_CRYPT, DBG_log("NSS do_aes_cbc: exit")); --} -+static void do_aes_cbc(u_int8_t *buf, size_t buf_len, PK11SymKey *symkey, -+ u_int8_t *iv, bool enc); - - struct encrypt_desc algo_aes_cbc = - { -@@ -142,17 +71,90 @@ - }, - .enc_ctxsize = sizeof(aes_context), - .enc_blocksize = AES_CBC_BLOCK_SIZE, -- .ivsize = AES_CBC_BLOCK_SIZE, -+ .pad_to_blocksize = TRUE, -+ .wire_iv_size = AES_CBC_BLOCK_SIZE, - .keyminlen = AES_KEY_MIN_LEN, - .keydeflen = AES_KEY_DEF_LEN, - .keymaxlen = AES_KEY_MAX_LEN, - .do_crypt = do_aes_cbc, - }; - --static void do_aes_ctr(u_int8_t *buf UNUSED, size_t buf_len UNUSED, PK11SymKey *symkey UNUSED, -- u_int8_t *nonce_iv UNUSED, bool enc UNUSED) -+static void do_aes_cbc(u_int8_t *buf, size_t buf_len, PK11SymKey *symkey, -+ u_int8_t *iv, bool enc) -+{ -+ ike_alg_nss_cbc(CKM_AES_CBC, &algo_aes_cbc, -+ buf, buf_len, symkey, iv, enc); -+} -+ -+static void do_aes_ctr(u_int8_t *buf, size_t buf_len, PK11SymKey *sym_key, -+ u_int8_t *counter_block, bool encrypt) - { -- DBG(DBG_CRYPT, DBG_log("NSS do_aes_ctr: stubb only")); -+ DBG(DBG_CRYPT, DBG_log("do_aes_ctr: enter")); -+ -+ if (sym_key == NULL) { -+ loglog(RC_LOG_SERIOUS, "do_aes_ctr: NSS derived enc key in NULL"); -+ exit_pluto(10); -+ } -+ -+ CK_AES_CTR_PARAMS counter_param; -+ counter_param.ulCounterBits = sizeof(u_int32_t) * 8;/* Per RFC 3686 */ -+ memcpy(counter_param.cb, counter_block, sizeof(counter_param.cb)); -+ SECItem param; -+ param.type = siBuffer; -+ param.data = (void*)&counter_param; -+ param.len = sizeof(counter_param); -+ -+ /* Output buffer for transformed data. */ -+ u_int8_t *out_buf = PR_Malloc((PRUint32)buf_len); -+ unsigned int out_len = 0; -+ -+ if (encrypt) { -+ SECStatus rv = PK11_Encrypt(sym_key, CKM_AES_CTR, ¶m, -+ out_buf, &out_len, buf_len, -+ buf, buf_len); -+ if (rv != SECSuccess) { -+ loglog(RC_LOG_SERIOUS, -+ "do_aes_ctr: PK11_Encrypt failure (err %d)", PR_GetError()); -+ exit_pluto(10); -+ } -+ } else { -+ SECStatus rv = PK11_Decrypt(sym_key, CKM_AES_CTR, ¶m, -+ out_buf, &out_len, buf_len, -+ buf, buf_len); -+ if (rv != SECSuccess) { -+ loglog(RC_LOG_SERIOUS, -+ "do_aes_ctr: PK11_Decrypt failure (err %d)", PR_GetError()); -+ exit_pluto(10); -+ } -+ } -+ -+ memcpy(buf, out_buf, buf_len); -+ PR_Free(out_buf); -+ -+ /* -+ * Finally update the counter located at the end of the -+ * counter_block. It is incremented by 1 for every full or -+ * partial block encoded/decoded. -+ * -+ * There's a portability assumption here that the IV buffer is -+ * at least sizeof(u_int32_t) (4-byte) aligned. -+ */ -+ u_int32_t *counter = (u_int32_t*)(counter_block + AES_BLOCK_SIZE -+ - sizeof(u_int32_t)); -+ u_int32_t old_counter = ntohl(*counter); -+ size_t increment = (buf_len + AES_BLOCK_SIZE - 1) / AES_BLOCK_SIZE; -+ u_int32_t new_counter = old_counter + increment; -+ DBG(DBG_CRYPT, DBG_log("do_aes_ctr: counter-block updated from 0x%lx to 0x%lx for %zd bytes", -+ (unsigned long)old_counter, (unsigned long)new_counter, buf_len)); -+ if (new_counter < old_counter) { -+ /* Wrap ... */ -+ loglog(RC_LOG_SERIOUS, -+ "do_aes_ctr: counter wrapped"); -+ /* what next??? */ -+ } -+ *counter = htonl(new_counter); -+ -+ DBG(DBG_CRYPT, DBG_log("do_aes_ctr: exit")); - } - - struct encrypt_desc algo_aes_ctr = -@@ -167,7 +169,9 @@ - }, - .enc_ctxsize = sizeof(aes_context), - .enc_blocksize = AES_BLOCK_SIZE, -- .ivsize = 8, -+ .pad_to_blocksize = FALSE, -+ .wire_iv_size = 8, -+ .salt_size = 4, - .keyminlen = AES_KEY_MIN_LEN, - .keydeflen = AES_KEY_DEF_LEN, - .keymaxlen = AES_KEY_MAX_LEN, -@@ -210,8 +214,15 @@ - - void ike_alg_aes_init(void) - { -+ if (!test_aes_cbc(&algo_aes_cbc)) { -+ loglog(RC_LOG_SERIOUS, "CKM_AES_CBC: test failure"); -+ } - if (ike_alg_register_enc(&algo_aes_cbc) != 1) - loglog(RC_LOG_SERIOUS, "Warning: failed to register algo_aes_cbc for IKE"); -+ -+ if (!test_aes_ctr(&algo_aes_ctr)) { -+ loglog(RC_LOG_SERIOUS, "CKM_AES_CTR: test failure"); -+ } - if (ike_alg_register_enc(&algo_aes_ctr) != 1) - loglog(RC_LOG_SERIOUS, "Warning: failed to register algo_aes_ctr for IKE"); - -diff -Naur libreswan-3.12-orig/programs/pluto/ike_alg_camellia.c libreswan-3.12/programs/pluto/ike_alg_camellia.c ---- libreswan-3.12-orig/programs/pluto/ike_alg_camellia.c 2014-11-06 22:52:50.000000000 -0500 -+++ libreswan-3.12/programs/pluto/ike_alg_camellia.c 2014-12-30 22:36:06.816000000 -0500 -@@ -33,83 +33,11 @@ - #include "lswconf.h" - #include "lswlog.h" - --static void do_camellia_cbc(u_int8_t *buf, size_t buf_len, PK11SymKey *symkey, -- u_int8_t *iv, bool enc) --{ -+#include "ike_alg_nss_cbc.h" -+#include "cbc_test_vectors.h" - -- u_int8_t iv_bak[CAMELLIA_BLOCK_SIZE]; -- u_int8_t *new_iv = NULL; /* logic will avoid copy to NULL */ -- u_int8_t *tmp_buf; -- -- CK_MECHANISM_TYPE ciphermech; -- SECItem ivitem; -- SECItem *secparam; -- PK11Context *enccontext; -- SECStatus rv; -- int outlen; -- -- DBG(DBG_CRYPT, DBG_log("NSS do_camellia_cbc: enter")); -- ciphermech = CKM_CAMELLIA_CBC; /*libreswan provides padding*/ -- -- if (symkey == NULL) { -- loglog(RC_LOG_SERIOUS, -- "do_camellia_cbc: NSS derived enc key in NULL"); -- abort(); -- } -- -- ivitem.type = siBuffer; -- ivitem.data = iv; -- ivitem.len = CAMELLIA_BLOCK_SIZE; -- -- secparam = PK11_ParamFromIV(ciphermech, &ivitem); -- if (secparam == NULL) { -- loglog(RC_LOG_SERIOUS, -- "do_camellia_cbc: Failure to set up PKCS11 param (err %d)", -- PR_GetError()); -- abort(); -- } -- -- outlen = 0; -- tmp_buf = PR_Malloc((PRUint32)buf_len); -- -- if (!enc) { -- new_iv = iv_bak; -- memcpy(new_iv, -- (char*) buf + buf_len - CAMELLIA_BLOCK_SIZE, -- CAMELLIA_BLOCK_SIZE); -- } -- -- enccontext = PK11_CreateContextBySymKey(ciphermech, -- enc ? CKA_ENCRYPT : CKA_DECRYPT, symkey, -- secparam); -- if (enccontext == NULL) { -- loglog(RC_LOG_SERIOUS, -- "do_camellia_cbc: PKCS11 context creation failure (err %d)", -- PR_GetError()); -- abort(); -- } -- -- rv = PK11_CipherOp(enccontext, tmp_buf, &outlen, buf_len, buf, -- buf_len); -- if (rv != SECSuccess) { -- loglog(RC_LOG_SERIOUS, -- "do_camellia_cbc: PKCS11 operation failure (err %d)", -- PR_GetError()); -- abort(); -- } -- PK11_DestroyContext(enccontext, PR_TRUE); -- memcpy(buf, tmp_buf, buf_len); -- -- if (enc) -- new_iv = (u_int8_t*) buf + buf_len - CAMELLIA_BLOCK_SIZE; -- -- memcpy(iv, new_iv, CAMELLIA_BLOCK_SIZE); -- PR_Free(tmp_buf); -- -- if (secparam != NULL) -- SECITEM_FreeItem(secparam, PR_TRUE); -- DBG(DBG_CRYPT, DBG_log("NSS do_camellia_cbc: exit")); --} -+static void do_camellia_cbc(u_int8_t *buf, size_t buf_len, PK11SymKey *symkey, -+ u_int8_t *iv, bool enc); - - struct encrypt_desc algo_camellia_cbc = - { -@@ -123,13 +51,21 @@ - }, - .enc_ctxsize = sizeof(camellia_context), - .enc_blocksize = CAMELLIA_BLOCK_SIZE, -- .ivsize = CAMELLIA_BLOCK_SIZE, -+ .pad_to_blocksize = TRUE, -+ .wire_iv_size = CAMELLIA_BLOCK_SIZE, - .keyminlen = CAMELLIA_KEY_MIN_LEN, - .keydeflen = CAMELLIA_KEY_DEF_LEN, - .keymaxlen = CAMELLIA_KEY_MAX_LEN, - .do_crypt = do_camellia_cbc, - }; - -+static void do_camellia_cbc(u_int8_t *buf, size_t buf_len, PK11SymKey *symkey, -+ u_int8_t *iv, bool enc) -+{ -+ ike_alg_nss_cbc(CKM_CAMELLIA_CBC, &algo_camellia_cbc, -+ buf, buf_len, symkey, iv, enc); -+} -+ - static void do_camellia_ctr(u_int8_t *buf UNUSED, size_t buf_len UNUSED, PK11SymKey *symkey UNUSED, - u_int8_t *nonce_iv UNUSED, bool enc UNUSED) - { -@@ -148,7 +84,8 @@ - }, - .enc_ctxsize = sizeof(camellia_context), - .enc_blocksize = CAMELLIA_BLOCK_SIZE, -- .ivsize = 8, -+ .pad_to_blocksize = FALSE, -+ .wire_iv_size = CAMELLIA_BLOCK_SIZE, - .keyminlen = CAMELLIA_KEY_MIN_LEN, - .keydeflen = CAMELLIA_KEY_DEF_LEN, - .keymaxlen = CAMELLIA_KEY_MAX_LEN, -@@ -157,8 +94,11 @@ - - void ike_alg_camellia_init(void) - { -+ test_camellia_cbc(&algo_camellia_cbc); - if (ike_alg_register_enc(&algo_camellia_cbc) != 1) - loglog(RC_LOG_SERIOUS, "Warning: failed to register algo_camellia_cbc for IKE"); -+ -+ // test_camellia_ctr(&algo_camellia_ctr); - if (ike_alg_register_enc(&algo_camellia_ctr) != 1) - loglog(RC_LOG_SERIOUS, "Warning: failed to register algo_camellia_ctr for IKE"); - } -diff -Naur libreswan-3.12-orig/programs/pluto/ike_alg.h libreswan-3.12/programs/pluto/ike_alg.h ---- libreswan-3.12-orig/programs/pluto/ike_alg.h 2014-11-06 22:52:50.000000000 -0500 -+++ libreswan-3.12/programs/pluto/ike_alg.h 2014-12-30 22:36:06.816000000 -0500 -@@ -22,7 +22,30 @@ - struct ike_alg common; /* MUST BE FIRST */ - size_t enc_ctxsize; - size_t enc_blocksize; -- size_t ivsize; -+ /* -+ * Does this algorithm require padding to the above -+ * ENC_BLOCKSIZE bytes? -+ * -+ * This shouldn't be confused with the need to pad things to -+ * 4-bytes (ESP) or not at all (IKE). -+ */ -+ bool pad_to_blocksize; -+ /* -+ * Number of additional bytes that should be extracted from -+ * the initial shared-secret. -+ * -+ * CTR calls this nonce; CCM calls it salt. -+ */ -+ size_t salt_size; -+ /* -+ * The IV sent across the wire; this is random material. -+ * -+ * The WIRE-IV which will be sent across the wire in public. -+ * The SALT, WIRE-IV, and who-knows what else are concatenated -+ * to form a ENC_BLOCKSIZE-byte starting-variable (aka IV). -+ */ -+ size_t wire_iv_size; -+ - unsigned keydeflen; - unsigned keymaxlen; - unsigned keyminlen; -diff -Naur libreswan-3.12-orig/programs/pluto/ike_alg_nss_cbc.c libreswan-3.12/programs/pluto/ike_alg_nss_cbc.c ---- libreswan-3.12-orig/programs/pluto/ike_alg_nss_cbc.c 1969-12-31 19:00:00.000000000 -0500 -+++ libreswan-3.12/programs/pluto/ike_alg_nss_cbc.c 2014-12-30 22:36:06.817000000 -0500 -@@ -0,0 +1,96 @@ -+#include -+#include -+ -+#include -+ -+#include "defs.h" -+#include "lswlog.h" -+#include "prmem.h" -+#include "prerror.h" -+ -+#include "constants.h" -+#include "ike_alg.h" -+#include "ike_alg_nss_cbc.h" -+ -+void ike_alg_nss_cbc(CK_MECHANISM_TYPE ciphermech, const struct encrypt_desc *alg, -+ u_int8_t *in_buf, size_t in_buf_len, PK11SymKey *symkey, -+ u_int8_t *iv, bool enc) -+{ -+ DBG(DBG_CRYPT, DBG_log("NSS ike_alg_nss_cbc: %s - enter", alg->common.name)); -+ -+ if (symkey == NULL) { -+ loglog(RC_LOG_SERIOUS, -+ "ike_alg_nss_cbc: %s - NSS derived enc key in NULL", -+ alg->common.name); -+ exit_pluto(10); -+ } -+ -+ SECItem ivitem; -+ ivitem.type = siBuffer; -+ ivitem.data = iv; -+ ivitem.len = alg->enc_blocksize; -+ SECItem *secparam = PK11_ParamFromIV(ciphermech, &ivitem); -+ if (secparam == NULL) { -+ loglog(RC_LOG_SERIOUS, -+ "ike_alg_nss_cbc: %s - Failure to set up PKCS11 param (err %d)", -+ alg->common.name, PR_GetError()); -+ exit_pluto(10); -+ } -+ -+ PK11Context *enccontext; -+ enccontext = PK11_CreateContextBySymKey(ciphermech, -+ enc ? CKA_ENCRYPT : CKA_DECRYPT, -+ symkey, secparam); -+ if (enccontext == NULL) { -+ loglog(RC_LOG_SERIOUS, -+ "ike_alg_nss_cbc: %s - PKCS11 context creation failure (err %d)", -+ alg->common.name, PR_GetError()); -+ exit_pluto(10); -+ } -+ -+ -+ /* Output buffer for transformed data. */ -+ u_int8_t *out_buf = PR_Malloc((PRUint32)in_buf_len); -+ int out_buf_len = 0; -+ -+ SECStatus rv = PK11_CipherOp(enccontext, out_buf, &out_buf_len, in_buf_len, -+ in_buf, in_buf_len); -+ if (rv != SECSuccess) { -+ loglog(RC_LOG_SERIOUS, -+ "ike_alg_nss_cbc: %s - PKCS11 operation failure (err %d)", -+ alg->common.name, PR_GetError()); -+ exit_pluto(10); -+ } -+ -+ PK11_DestroyContext(enccontext, PR_TRUE); -+ -+ /* -+ * Update the IV ready for the next call to this function. -+ */ -+ u_int8_t *new_iv; -+ if (enc) { -+ /* -+ * The IV for the next encryption call is the last -+ * block of encrypted output data. -+ */ -+ new_iv = out_buf + out_buf_len - alg->enc_blocksize; -+ } else { -+ /* -+ * The IV for the next decryption call is the last -+ * block of the encrypted input data. -+ */ -+ new_iv = in_buf + in_buf_len - alg->enc_blocksize; -+ } -+ memcpy(iv, new_iv, alg->enc_blocksize); -+ -+ /* -+ * Finally, copy the transformed data back to the buffer. Do -+ * this after extracting the IV. -+ */ -+ memcpy(in_buf, out_buf, in_buf_len); -+ PR_Free(out_buf); -+ -+ if (secparam != NULL) -+ SECITEM_FreeItem(secparam, PR_TRUE); -+ DBG(DBG_CRYPT, DBG_log("NSS ike_alg_nss_cbc: %s - exit", alg->common.name)); -+} -diff -Naur libreswan-3.12-orig/programs/pluto/ike_alg_nss_cbc.h libreswan-3.12/programs/pluto/ike_alg_nss_cbc.h ---- libreswan-3.12-orig/programs/pluto/ike_alg_nss_cbc.h 1969-12-31 19:00:00.000000000 -0500 -+++ libreswan-3.12/programs/pluto/ike_alg_nss_cbc.h 2014-12-30 22:36:06.817000000 -0500 -@@ -0,0 +1,4 @@ -+extern void ike_alg_nss_cbc(CK_MECHANISM_TYPE ciphermech, const struct encrypt_desc *algo, -+ u_int8_t *buf, size_t buf_len, PK11SymKey *symkey, -+ u_int8_t *iv, bool enc); -+ -diff -Naur libreswan-3.12-orig/programs/pluto/ike_alg_serpent.c libreswan-3.12/programs/pluto/ike_alg_serpent.c ---- libreswan-3.12-orig/programs/pluto/ike_alg_serpent.c 2014-11-06 22:52:50.000000000 -0500 -+++ libreswan-3.12/programs/pluto/ike_alg_serpent.c 2014-12-30 22:36:06.817000000 -0500 -@@ -84,7 +84,8 @@ - }, - .enc_ctxsize = sizeof(struct serpent_context), - .enc_blocksize = SERPENT_CBC_BLOCK_SIZE, -- .ivsize = SERPENT_CBC_BLOCK_SIZE, -+ .pad_to_blocksize = TRUE, -+ .wire_iv_size = SERPENT_CBC_BLOCK_SIZE, - .keyminlen = SERPENT_KEY_MIN_LEN, - .keydeflen = SERPENT_KEY_DEF_LEN, - .keymaxlen = SERPENT_KEY_MAX_LEN, -diff -Naur libreswan-3.12-orig/programs/pluto/ike_alg_twofish.c libreswan-3.12/programs/pluto/ike_alg_twofish.c ---- libreswan-3.12-orig/programs/pluto/ike_alg_twofish.c 2014-11-06 22:52:50.000000000 -0500 -+++ libreswan-3.12/programs/pluto/ike_alg_twofish.c 2014-12-30 22:36:06.817000000 -0500 -@@ -88,7 +88,8 @@ - }, - .enc_ctxsize = sizeof(twofish_context), - .enc_blocksize = TWOFISH_CBC_BLOCK_SIZE, -- .ivsize = TWOFISH_CBC_BLOCK_SIZE, -+ .pad_to_blocksize = TRUE, -+ .wire_iv_size = TWOFISH_CBC_BLOCK_SIZE, - .keydeflen = TWOFISH_KEY_MIN_LEN, - .keyminlen = TWOFISH_KEY_DEF_LEN, - .keymaxlen = TWOFISH_KEY_MAX_LEN, -@@ -107,7 +108,8 @@ - }, - .enc_ctxsize = sizeof(twofish_context), - .enc_blocksize = TWOFISH_CBC_BLOCK_SIZE, -- .ivsize = TWOFISH_CBC_BLOCK_SIZE, -+ .pad_to_blocksize = TRUE, -+ .wire_iv_size = TWOFISH_CBC_BLOCK_SIZE, - .keydeflen = TWOFISH_KEY_MIN_LEN, - .keyminlen = TWOFISH_KEY_DEF_LEN, - .keymaxlen = TWOFISH_KEY_MAX_LEN, -diff -Naur libreswan-3.12-orig/programs/pluto/ikev2_parent.c libreswan-3.12/programs/pluto/ikev2_parent.c ---- libreswan-3.12-orig/programs/pluto/ikev2_parent.c 2014-12-30 22:34:14.352000000 -0500 -+++ libreswan-3.12/programs/pluto/ikev2_parent.c 2014-12-30 22:36:06.819000000 -0500 -@@ -105,14 +105,14 @@ - * The IV will subsequently be discarded after decryption. - * This is true of Cipher Block Chaining mode (CBC). - */ --static bool emit_iv(const struct state *st, pb_stream *pbs) -+static bool emit_wire_iv(const struct state *st, pb_stream *pbs) - { -- size_t ivsize = st->st_oakley.encrypter->ivsize; -+ size_t wire_iv_size = st->st_oakley.encrypter->wire_iv_size; - unsigned char ivbuf[MAX_CBC_BLOCK_SIZE]; - -- passert(ivsize <= MAX_CBC_BLOCK_SIZE); -- get_rnd_bytes(ivbuf, ivsize); -- return out_raw(ivbuf, ivsize, pbs, "IV"); -+ passert(wire_iv_size <= MAX_CBC_BLOCK_SIZE); -+ get_rnd_bytes(ivbuf, wire_iv_size); -+ return out_raw(ivbuf, wire_iv_size, pbs, "IV"); - } - - static stf_status crypto_helper_build_ke(struct state *st) -@@ -1279,11 +1279,49 @@ - } - - /* -- * Pad message for CBC-mode encryption. Should not be called for CTR or CCM/GCM -- * Octets are added to make the message a multiple of the cipher block size. -- * At least one octet is added and at most blocksize are added. -- * The first is 0, and each subsequent octet is one larger. -- * Thus the last octet contains one less than the number of octets added. -+ * Form the encryption IV (a.k.a. starting variable) from the salt -+ * (a.k.a. nonce) wire-iv and a counter set to 1. -+ * -+ * note: no iv is longer than MAX_CBC_BLOCK_SIZE -+ */ -+static void construct_enc_iv(const char *name, -+ u_char enc_iv[], -+ u_char *wire_iv, chunk_t salt, -+ const struct encrypt_desc *encrypter) -+{ -+ DBG(DBG_CRYPT, DBG_log("construct_enc_iv: %s: salt-size=%zd wire-IV-size=%zd block-size %zd", -+ name, encrypter->salt_size, encrypter->wire_iv_size, -+ encrypter->enc_blocksize)); -+ passert(salt.len == encrypter->salt_size); -+ passert(encrypter->enc_blocksize <= MAX_CBC_BLOCK_SIZE); -+ passert(encrypter->enc_blocksize >= encrypter->salt_size + encrypter->wire_iv_size); -+ size_t counter_size = encrypter->enc_blocksize - encrypter->salt_size - encrypter->wire_iv_size; -+ DBG(DBG_CRYPT, DBG_log("construct_enc_iv: %s: computed counter-size=%zd", -+ name, counter_size)); -+ -+ memcpy(enc_iv, salt.ptr, salt.len); -+ memcpy(enc_iv + salt.len, wire_iv, encrypter->wire_iv_size); -+ if (counter_size > 0) { -+ memset(enc_iv + encrypter->enc_blocksize - counter_size, 0, -+ counter_size - 1); -+ enc_iv[encrypter->enc_blocksize - 1] = 1; -+ } -+ DBG(DBG_CRYPT, DBG_dump(name, enc_iv, encrypter->enc_blocksize)); -+} -+ -+/* -+ * Append optional "padding" and reguired "padding-length" byte. -+ * -+ * Some encryption modes, namely CBC, require things to be padded to -+ * the encryption block-size. While others, such as CTR, do not. -+ * Either way a "padding-length" byte is always appended. -+ * -+ * This code starts by appending a 0 pad-octet, and each subsequent -+ * octet is one larger. Thus the last octet always contains one less -+ * than the number of octets added i.e., the padding-length. -+ * -+ * Adding to the confusion, ESP requires a minimum of 4-byte alignment -+ * and IKE is free to use the ESP code for padding - we don't. - */ - static bool ikev2_padup_pre_encrypt(struct state *st, - pb_stream *e_pbs_cipher) MUST_USE_RESULT; -@@ -1300,10 +1338,21 @@ - size_t blocksize = pst->st_oakley.encrypter->enc_blocksize; - char b[MAX_CBC_BLOCK_SIZE]; - unsigned int i; -- size_t padding = pad_up(pbs_offset(e_pbs_cipher), blocksize); - -- if (padding == 0) -- padding = blocksize; -+ size_t padding; -+ if (pst->st_oakley.encrypter->pad_to_blocksize) { -+ padding = pad_up(pbs_offset(e_pbs_cipher), blocksize); -+ if (padding == 0) { -+ padding = blocksize; -+ } -+ DBG(DBG_CRYPT, -+ DBG_log("ikev2_padup_pre_encrypt: adding %zd bytes of padding (last is padding-length)", -+ padding)); -+ } else { -+ padding = 1; -+ DBG(DBG_CRYPT, -+ DBG_log("ikev2_padup_pre_encrypt: adding %zd byte padding-length", padding)); -+ } - - for (i = 0; i < padding; i++) - b[i] = i; -@@ -1336,7 +1385,7 @@ - static stf_status ikev2_encrypt_msg(struct state *st, - enum phase1_role role, - unsigned char *authstart, -- unsigned char *iv, -+ unsigned char *wire_iv, - unsigned char *encstart, - unsigned char *authloc, - pb_stream *e_pbs UNUSED, -@@ -1348,32 +1397,35 @@ - if (IS_CHILD_SA(st)) - pst = state_with_serialno(st->st_clonedfrom); - -+ chunk_t salt; - if (role == O_INITIATOR) { - cipherkey = pst->st_skey_ei_nss; - authkey = pst->st_skey_ai_nss; -+ salt = pst->st_skey_initiator_salt; - } else { - cipherkey = pst->st_skey_er_nss; - authkey = pst->st_skey_ar_nss; -+ salt = pst->st_skey_responder_salt; - } - - /* encrypt the block */ - { -- size_t ivsize = pst->st_oakley.encrypter->ivsize; - /* note: no iv is longer than MAX_CBC_BLOCK_SIZE */ -- unsigned char savediv[MAX_CBC_BLOCK_SIZE]; -+ unsigned char enc_iv[MAX_CBC_BLOCK_SIZE]; -+ construct_enc_iv("encryption IV/starting-variable", enc_iv, -+ wire_iv, salt, -+ pst->st_oakley.encrypter); -+ - unsigned int cipherlen = e_pbs_cipher->cur - encstart; - -- passert(ivsize <= MAX_CBC_BLOCK_SIZE); - DBG(DBG_CRYPT, - DBG_dump("data before encryption:", encstart, cipherlen)); - -- memcpy(savediv, iv, ivsize); -- - /* now, encrypt */ - (st->st_oakley.encrypter->do_crypt)(encstart, - cipherlen, - cipherkey, -- savediv, TRUE); -+ enc_iv, TRUE); - - DBG(DBG_CRYPT, - DBG_dump("data after encryption:", encstart, cipherlen)); -@@ -1411,9 +1463,11 @@ - * Calls ikev2_process_payloads to decode the payloads within. - * - * This code assumes that the encrypted part of an IKE message starts -- * with an Initialization Vector (IV) of ivsize of random octets. -+ * with an Initialization Vector (IV) of WIRE_IV_SIZE random octets. - * We will discard the IV after decryption. -- * This is true of Cipher Block Chaining mode (CBC). -+ * -+ * The (optional) salt, wire-iv, and (optional) 1 are combined to form -+ * the actual starting-variable (a.k.a. IV). - */ - static - stf_status ikev2_decrypt_msg(struct msg_digest *md, -@@ -1424,10 +1478,11 @@ - state_with_serialno(st->st_clonedfrom) : st; - pb_stream *e_pbs = &md->chain[ISAKMP_NEXT_v2E]->pbs; - unsigned char *authstart = md->packet_pbs.start; -- unsigned char *iv = e_pbs->cur; /* start of IV, right after header */ -+ u_char *wire_iv = e_pbs->cur; /* start of wire-IV, right after header */ -+ const size_t wire_iv_size = pst->st_oakley.encrypter->wire_iv_size; - size_t integ_len = pst->st_oakley.integ_hasher->hash_integ_len; -- size_t enc_blocksize = pst->st_oakley.encrypter->enc_blocksize; -- size_t ivsize = pst->st_oakley.encrypter->ivsize; -+ const size_t enc_blocksize = pst->st_oakley.encrypter->enc_blocksize; -+ const bool pad_to_blocksize = pst->st_oakley.encrypter->pad_to_blocksize; - unsigned char *roof= e_pbs->roof; - PK11SymKey *cipherkey, *authkey; - -@@ -1447,23 +1502,26 @@ - /* - * check to see if length is plausible. Need room for: - * - IV (at start) -- * - at least one byte for padding (just before integrity digest) -+ * - the padding-length byte - * - truncated integrity digest (at end) - */ -- if (roof - iv < (ptrdiff_t)(ivsize + 1 + integ_len)) { -+ if (roof - wire_iv < (ptrdiff_t)(wire_iv_size + 1 + integ_len)) { - libreswan_log("encrypted payload impossibly short (%td)", -- roof - iv); -+ roof - wire_iv); - return STF_FAIL; - } - - roof -= integ_len; /* strip truncated digest */ - -+ chunk_t salt; - if (role == O_INITIATOR) { - cipherkey = pst->st_skey_er_nss; - authkey = pst->st_skey_ar_nss; -+ salt = pst->st_skey_responder_salt; - } else { - cipherkey = pst->st_skey_ei_nss; - authkey = pst->st_skey_ai_nss; -+ salt = pst->st_skey_initiator_salt; - } - - /* -@@ -1499,35 +1557,34 @@ - - /* decrypt */ - { -- /* -- * The first [ivsize] octet chunk is the IV. -- * The encrypted data follows. -- * The last byte of encrypted data is one less than -- * the number of padding octets. -- */ -- unsigned char *encstart = iv + ivsize; -+ u_char *encstart = wire_iv + wire_iv_size; - size_t enclen = roof - encstart; -- unsigned char padlen; -+ /* note: no iv is longer than MAX_CBC_BLOCK_SIZE */ -+ unsigned char enc_iv[MAX_CBC_BLOCK_SIZE]; -+ construct_enc_iv("decription IV/starting-variable", enc_iv, -+ wire_iv, salt, -+ pst->st_oakley.encrypter); - - DBG(DBG_CRYPT, - DBG_dump("data before decryption:", encstart, enclen)); - -- if (enclen % enc_blocksize != 0) { -- libreswan_log("cyphertext length (%zu) not a multiple of blocksize (%zu)", -- enclen, enc_blocksize); -- return STF_FAIL; -+ if (pad_to_blocksize) { -+ if (enclen % enc_blocksize != 0) { -+ libreswan_log("cyphertext length (%zu) not a multiple of blocksize (%zu)", -+ enclen, enc_blocksize); -+ return STF_FAIL; -+ } - } - - /* now, decrypt */ - (pst->st_oakley.encrypter->do_crypt)(encstart, - enclen, - cipherkey, -- iv, FALSE); -- -- padlen = encstart[enclen - 1] + 1; -+ enc_iv, FALSE); - -+ u_char padlen = encstart[enclen - 1] + 1; - if (padlen > enc_blocksize || padlen > enclen) { -- libreswan_log("invalid last pad octet: 0x%2x", padlen - 1); -+ libreswan_log("invalid padding-length octet: 0x%2x", padlen - 1); - return STF_FAIL; - } - -@@ -1754,7 +1811,7 @@ - - /* insert IV */ - iv = e_pbs.cur; -- if (!emit_iv(st, &e_pbs)) -+ if (!emit_wire_iv(st, &e_pbs)) - return STF_INTERNAL_ERROR; - - /* note where cleartext starts */ -@@ -1888,8 +1945,6 @@ - } - - /* -- * TODO WARNING: padding must not be done for CTR mode -- * - * need to extend the packet so that we will know how big it is - * since the length is under the integrity check - */ -@@ -2226,7 +2281,7 @@ - - /* insert IV */ - iv = e_pbs.cur; -- if (!emit_iv(st, &e_pbs)) -+ if (!emit_wire_iv(st, &e_pbs)) - return STF_INTERNAL_ERROR; - - /* note where cleartext starts */ -@@ -3147,7 +3202,7 @@ - - /* IV */ - iv = e_pbs.cur; -- if (!emit_iv(st, &e_pbs)) -+ if (!emit_wire_iv(st, &e_pbs)) - return STF_INTERNAL_ERROR; - - /* note where cleartext starts */ -@@ -3352,7 +3407,7 @@ - - /* insert IV */ - iv = e_pbs.cur; -- if (!emit_iv(st, &e_pbs)) -+ if (!emit_wire_iv(st, &e_pbs)) - return STF_INTERNAL_ERROR; - - /* note where cleartext starts in output */ -@@ -3767,7 +3822,7 @@ - - /* IV */ - iv = e_pbs.cur; -- if (!emit_iv(st, &e_pbs)) -+ if (!emit_wire_iv(st, &e_pbs)) - return STF_INTERNAL_ERROR; - - /* note where cleartext starts */ -@@ -3889,7 +3944,7 @@ - - /* insert IV */ - iv = e_pbs.cur; -- if (!emit_iv(st, &e_pbs)) -+ if (!emit_wire_iv(st, &e_pbs)) - return FALSE; - - /* note where cleartext starts */ -diff -Naur libreswan-3.12-orig/programs/pluto/kernel_netlink.c libreswan-3.12/programs/pluto/kernel_netlink.c ---- libreswan-3.12-orig/programs/pluto/kernel_netlink.c 2014-11-06 22:52:50.000000000 -0500 -+++ libreswan-3.12/programs/pluto/kernel_netlink.c 2014-12-30 22:36:06.819000000 -0500 -@@ -246,7 +246,8 @@ - .algo_next = NULL, - }, - .enc_blocksize = AES_BLOCK_SIZE, -- .ivsize = 8, -+ .wire_iv_size = 8, -+ .pad_to_blocksize = FALSE, - /* Only 128, 192 and 256 are supported (24 bits KEYMAT for salt not included) */ - .keyminlen = AEAD_AES_KEY_MIN_LEN, - .keydeflen = AEAD_AES_KEY_DEF_LEN, -@@ -263,7 +264,8 @@ - .algo_next = NULL, - }, - .enc_blocksize = AES_BLOCK_SIZE, -- .ivsize = 8, -+ .wire_iv_size = 8, -+ .pad_to_blocksize = FALSE, - /* Only 128, 192 and 256 are supported (24 bits KEYMAT for salt not included) */ - .keyminlen = AEAD_AES_KEY_MIN_LEN, - .keydeflen = AEAD_AES_KEY_DEF_LEN, -@@ -280,7 +282,8 @@ - .algo_next = NULL, - }, - .enc_blocksize = AES_BLOCK_SIZE, -- .ivsize = 8, -+ .wire_iv_size = 8, -+ .pad_to_blocksize = FALSE, - /* Only 128, 192 and 256 are supported (24 bits KEYMAT for salt not included) */ - .keyminlen = AEAD_AES_KEY_MIN_LEN, - .keydeflen = AEAD_AES_KEY_DEF_LEN, -@@ -297,7 +300,8 @@ - .algo_next = NULL, - }, - .enc_blocksize = AES_BLOCK_SIZE, -- .ivsize = 8, -+ .wire_iv_size = 8, -+ .pad_to_blocksize = FALSE, - /* Only 128, 192 and 256 are supported (32 bits KEYMAT for salt not included) */ - .keyminlen = AEAD_AES_KEY_MIN_LEN, - .keydeflen = AEAD_AES_KEY_DEF_LEN, -@@ -314,7 +318,8 @@ - .algo_next = NULL, - }, - .enc_blocksize = AES_BLOCK_SIZE, -- .ivsize = 8, -+ .wire_iv_size = 8, -+ .pad_to_blocksize = FALSE, - /* Only 128, 192 and 256 are supported (32 bits KEYMAT for salt not included) */ - .keyminlen = AEAD_AES_KEY_MIN_LEN, - .keydeflen = AEAD_AES_KEY_DEF_LEN, -@@ -331,7 +336,8 @@ - .algo_next = NULL, - }, - .enc_blocksize = AES_BLOCK_SIZE, -- .ivsize = 8, -+ .wire_iv_size = 8, -+ .pad_to_blocksize = FALSE, - /* Only 128, 192 and 256 are supported (32 bits KEYMAT for salt not included) */ - .keyminlen = AEAD_AES_KEY_MIN_LEN, - .keydeflen = AEAD_AES_KEY_DEF_LEN, -diff -Naur libreswan-3.12-orig/programs/pluto/Makefile libreswan-3.12/programs/pluto/Makefile ---- libreswan-3.12-orig/programs/pluto/Makefile 2014-11-06 22:52:50.000000000 -0500 -+++ libreswan-3.12/programs/pluto/Makefile 2014-12-30 22:36:06.813000000 -0500 -@@ -108,6 +108,10 @@ - pluto.8 ipsec_whack.8 ipsec.secrets.5 .cvsignore - - DISTSRC = \ -+ ike_alg_nss_cbc.h ike_alg_nss_cbc.c \ -+ cbc_test_vectors.h cbc_test_vectors.c \ -+ ctr_test_vectors.h ctr_test_vectors.c \ -+ test_buffer.h test_buffer.c \ - connections.c initiate.c terminate.c connections.h \ - pending.c pending.h \ - foodgroups.c foodgroups.h \ -@@ -160,6 +164,10 @@ - DIST = $(DISTMISC) $(DISTSRC) - - OBJSPLUTO = connections.o initiate.o terminate.o -+OBJSPLUTO += ike_alg_nss_cbc.o -+OBJSPLUTO += cbc_test_vectors.o -+OBJSPLUTO += ctr_test_vectors.o -+OBJSPLUTO += test_buffer.o - OBJSPLUTO += pending.o cookie.o crypto.o defs.o - OBJSPLUTO += foodgroups.o log.o state.o plutomain.o plutoalg.o server.o - OBJSPLUTO += timer.o hmac.o hostpair.o -diff -Naur libreswan-3.12-orig/programs/pluto/pluto_crypt.h libreswan-3.12/programs/pluto/pluto_crypt.h ---- libreswan-3.12-orig/programs/pluto/pluto_crypt.h 2014-11-06 22:52:50.000000000 -0500 -+++ libreswan-3.12/programs/pluto/pluto_crypt.h 2014-12-30 22:36:06.820000000 -0500 -@@ -171,7 +171,8 @@ - oakley_hash_t integ_hash; - oakley_hash_t prf_hash; - enum phase1_role role; -- size_t keysize; /* of encryptor */ -+ size_t key_size; /* of encryptor, in bytes */ -+ size_t salt_size; /* ov IV salt, in bytes */ - wire_chunk_t gi; - wire_chunk_t gr; - wire_chunk_t pss; -@@ -211,6 +212,8 @@ - PK11SymKey *skeyid_er; - PK11SymKey *skeyid_pi; - PK11SymKey *skeyid_pr; -+ chunk_t skey_initiator_salt; -+ chunk_t skey_responder_salt; - }; - - struct pluto_crypto_req { -diff -Naur libreswan-3.12-orig/programs/pluto/plutomain.c libreswan-3.12/programs/pluto/plutomain.c ---- libreswan-3.12-orig/programs/pluto/plutomain.c 2014-12-30 22:34:14.347000000 -0500 -+++ libreswan-3.12/programs/pluto/plutomain.c 2014-12-30 22:36:06.820000000 -0500 -@@ -82,6 +82,9 @@ - - #include "nat_traversal.h" - -+#include "cbc_test_vectors.h" -+#include "ctr_test_vectors.h" -+ - #ifndef IPSECDIR - #define IPSECDIR "/etc/ipsec.d" - #endif -@@ -523,8 +526,32 @@ - exit(0); - } - -+ -+#if 0 -+/* -+ * XXX: Can't use this call to get encrypt_desc struct encrypt_desc -+ */ -+extern struct encrypt_desc algo_aes_cbc; -+extern struct encrypt_desc algo_camellia_cbc; -+extern struct encrypt_desc algo_aes_ctr; -+#endif -+ - int main(int argc, char **argv) - { -+#if 0 -+ NSS_NoDB_Init("."); -+ if (!test_aes_cbc(&algo_aes_cbc)) { -+ printf("aes-cbc failed\n"); -+ } -+ if (!test_camellia_cbc(&algo_camellia_cbc)) { -+ printf("camellia-cbc failed\n"); -+ } -+ if (!test_aes_ctr(&algo_aes_ctr)) { -+ printf("aes-ctr failed\n"); -+ } -+ exit(0); -+#endif -+ - int lockfd; - - /* -diff -Naur libreswan-3.12-orig/programs/pluto/state.c libreswan-3.12/programs/pluto/state.c ---- libreswan-3.12-orig/programs/pluto/state.c 2014-12-30 22:34:14.354000000 -0500 -+++ libreswan-3.12/programs/pluto/state.c 2014-12-30 22:36:06.821000000 -0500 -@@ -542,6 +542,8 @@ - free_any_nss_symkey(st->st_skey_pr_nss); - free_any_nss_symkey(st->st_enc_key_nss); - # undef free_any_nss_symkey -+ freeanychunk(st->st_skey_initiator_salt); -+ freeanychunk(st->st_skey_responder_salt); - - # define wipe_any(p, l) { \ - if ((p) != NULL) { \ -@@ -876,6 +878,18 @@ - clone_nss_symkey_field(st_skey_pr_nss); - clone_nss_symkey_field(st_enc_key_nss); - # undef clone_nss_symkey_field -+# define clone_any_chunk(field) { \ -+ if (st->field.ptr == NULL) { \ -+ nst->field.ptr = NULL; \ -+ nst->field.len = 0; \ -+ } else { \ -+ clonetochunk(nst->field, st->field.ptr, st->field.len, \ -+ #field " in duplicate state"); \ -+ } \ -+ } -+ clone_any_chunk(st_skey_initiator_salt); -+ clone_any_chunk(st_skey_responder_salt); -+# undef clone_any_chunk - - /* v2 duplication of state */ - # define clone_chunk(ch, name) \ -diff -Naur libreswan-3.12-orig/programs/pluto/state.h libreswan-3.12/programs/pluto/state.h ---- libreswan-3.12-orig/programs/pluto/state.h 2014-12-30 22:34:14.354000000 -0500 -+++ libreswan-3.12/programs/pluto/state.h 2014-12-30 22:36:06.821000000 -0500 -@@ -395,6 +395,8 @@ - PK11SymKey *st_skey_er_nss; /* KM for ISAKMP encryption */ - PK11SymKey *st_skey_pi_nss; /* KM for ISAKMP encryption */ - PK11SymKey *st_skey_pr_nss; /* KM for ISAKMP encryption */ -+ chunk_t st_skey_initiator_salt; -+ chunk_t st_skey_responder_salt; - - /* connection included in AUTH */ - struct traffic_selector st_ts_this; -diff -Naur libreswan-3.12-orig/programs/pluto/test_buffer.c libreswan-3.12/programs/pluto/test_buffer.c ---- libreswan-3.12-orig/programs/pluto/test_buffer.c 1969-12-31 19:00:00.000000000 -0500 -+++ libreswan-3.12/programs/pluto/test_buffer.c 2014-12-30 22:36:06.821000000 -0500 -@@ -0,0 +1,143 @@ -+#include -+ -+#include "defs.h" -+#include "constants.h" -+#include "lswalloc.h" -+#include "lswlog.h" -+ -+#include "nss.h" -+#include "pk11pub.h" -+ -+#include "test_buffer.h" -+ -+static chunk_t zalloc_chunk(size_t length, const char *name) -+{ -+ chunk_t chunk; -+ chunk.len = length; -+ chunk.ptr = alloc_bytes(length, name); -+ memset(chunk.ptr, 0, chunk.len); -+ return chunk; -+} -+ -+/* -+ * Given a hex encode string, decode it into a chunk. -+ * -+ * If this function fails, crash and burn. Its been fed static data -+ * so should never ever have a problem. -+ */ -+static chunk_t decode_hex_to_chunk(const char *original, const char *string) -+{ -+ /* The decoded buffer can't be bigger than the encoded string. */ -+ chunk_t chunk = zalloc_chunk(strlen(string), original); -+ chunk.len = 0; -+ const char *pos = string; -+ while (*pos != '\0') { -+ /* skip leading/trailing space */ -+ while (*pos == ' ') { -+ pos++; -+ } -+ if (*pos == '\0') { -+ break; -+ } -+ /* Expecting , at least *pos is valid. */ -+ char buf[3]; -+ int i = 0; -+ do { -+ buf[i++] = *pos++; -+ } while (*pos != ' ' && *pos != '\0' && i < 2); -+ buf[i] = '\0'; -+ if (i != 2) { -+ loglog(RC_INTERNALERR, -+ "decode_hex_to_chunk: hex buffer \"%s\" contains unexpected space or NUL at \"%s\"\n", string, pos); -+ exit_pluto(1); -+ } -+ char *end; -+ chunk.ptr[chunk.len] = strtoul(buf, &end, 16); -+ if (end - buf != 2) { -+ loglog(RC_INTERNALERR, -+ "decode_hex_to_chunk: hex buffer \"%s\" invalid hex character at \"%s\"\n", string, pos); -+ exit_pluto(1); -+ } -+ chunk.len++; -+ } -+ return chunk; -+} -+ -+/* -+ * Given an ASCII string, convert it onto a buffer of bytes. If the -+ * buffer is prefixed by 0x assume the contents are hex (with spaces) -+ * and decode it; otherwise it is assumed that the ascii (minus the -+ * NUL) should be copied. -+ */ -+chunk_t decode_to_chunk(const char *prefix, const char *original) -+{ -+ DBG(DBG_CRYPT, DBG_log("decode_to_chunk: %s: input \"%s\"", -+ prefix, original)); -+ chunk_t chunk; -+ if (startswith(original, "0x")) { -+ chunk = decode_hex_to_chunk(original, original + strlen("0x")); -+ } else { -+ chunk = zalloc_chunk(strlen(original), original); -+ memcpy(chunk.ptr, original, chunk.len); -+ } -+ DBG(DBG_CRYPT, DBG_dump_chunk("decode_to_chunk: output: ", chunk)); -+ return chunk; -+} -+ -+int compare_chunk(const char *prefix, -+ chunk_t expected, -+ u_char *actual) -+{ -+ size_t i; -+ for (i = 0; i < expected.len; i++) { -+ u_char l = expected.ptr[i]; -+ u_char r = actual[i]; -+ if (l != r) { -+ /* Caller should issue the real log message. */ -+ DBG(DBG_CRYPT, DBG_log("compare_chunk: %s: bytes at %zd differ, expected %02x found %02x", -+ prefix, i, l, r)); -+ return 0; -+ } -+ } -+ DBG(DBG_CRYPT, DBG_log("compare_chunk: %s: ok", prefix)); -+ return 1; -+} -+ -+int compare_chunks(const char *prefix, -+ chunk_t expected, -+ chunk_t actual) -+{ -+ if (expected.len != actual.len) { -+ DBG(DBG_CRYPT, -+ DBG_log("compare_chunks: %s: expected length %zd but got %zd", -+ prefix, expected.len, actual.len)); -+ return 0; -+ } -+ return compare_chunk(prefix, expected, actual.ptr); -+} -+ -+/* -+ * Turn the raw key into a SECItem and then SymKey. -+ * -+ * Since slots are referenced counted and ImportSymKey adds a -+ * reference, immediate freeing of the local slot is possible. -+ * -+ * ImportSymKey makes a copy of the key chunk so that can also be -+ * released. -+ */ -+PK11SymKey *decode_to_key(CK_MECHANISM_TYPE cipher_mechanism, -+ const char *encoded_key) -+{ -+ PK11SlotInfo *slot = PK11_GetBestSlot(cipher_mechanism, NULL); -+ chunk_t raw_key = decode_to_chunk("Key: ", encoded_key); -+ SECItem key_item; -+ key_item.type = siBuffer; -+ key_item.data = raw_key.ptr; /* ptr to an array of key bytes */ -+ key_item.len = raw_key.len; /* length of the array of key bytes */ -+ PK11SymKey *sym_key = PK11_ImportSymKey(slot, cipher_mechanism, -+ PK11_OriginUnwrap, -+ CKA_ENCRYPT, &key_item, NULL); -+ freeanychunk(raw_key); -+ PK11_FreeSlot(slot); -+ return sym_key; -+} -diff -Naur libreswan-3.12-orig/programs/pluto/test_buffer.h libreswan-3.12/programs/pluto/test_buffer.h ---- libreswan-3.12-orig/programs/pluto/test_buffer.h 1969-12-31 19:00:00.000000000 -0500 -+++ libreswan-3.12/programs/pluto/test_buffer.h 2014-12-30 22:36:06.822000000 -0500 -@@ -0,0 +1,9 @@ -+ -+chunk_t decode_to_chunk(const char *prefix, const char *string); -+int compare_chunks(const char *prefix, -+ chunk_t expected, -+ chunk_t actual); -+int compare_chunk(const char *prefix, -+ chunk_t expected, -+ u_char *actual); -+PK11SymKey *decode_to_key(CK_MECHANISM_TYPE cipher_mechanism, const char *string); diff --git a/SOURCES/libreswan-3.12-1144120-camellia-ikev2.patch b/SOURCES/libreswan-3.12-1144120-camellia-ikev2.patch deleted file mode 100644 index d1f55ba..0000000 --- a/SOURCES/libreswan-3.12-1144120-camellia-ikev2.patch +++ /dev/null @@ -1,127 +0,0 @@ -diff -Naur libreswan-3.12-orig/include/ietf_constants.h libreswan-3.12/include/ietf_constants.h ---- libreswan-3.12-orig/include/ietf_constants.h 2014-11-06 22:52:50.000000000 -0500 -+++ libreswan-3.12/include/ietf_constants.h 2014-12-03 20:32:48.588715740 -0500 -@@ -825,6 +825,9 @@ - IKEv2_ENCR_INVALID = 65536, - }; - -+#define IKEv2_ENCR_CAMELLIA_CBC_ikev1 IKEv2_RESERVED_IEEE_P1619_XTS_AES -+ -+ - enum ikev2_trans_type_prf { - IKEv2_PRF_HMAC_MD5 = 1, /* RFC2104 */ - IKEv2_PRF_HMAC_SHA1 = 2, /* RFC2104 */ -diff -Naur libreswan-3.12-orig/lib/libswan/kernel_alg.c libreswan-3.12/lib/libswan/kernel_alg.c ---- libreswan-3.12-orig/lib/libswan/kernel_alg.c 2014-11-06 22:52:50.000000000 -0500 -+++ libreswan-3.12/lib/libswan/kernel_alg.c 2014-12-03 20:32:48.590715792 -0500 -@@ -193,6 +193,11 @@ - /* - * test #1: encrypt algo must be present - */ -+ -+ /* fixup broken IANA registry */ -+ if (alg_id == ESP_CAMELLIA) -+ alg_id = ESP_CAMELLIAv1; -+ - if (!ESP_EALG_PRESENT(alg_id)) { - DBG(DBG_KERNEL, - DBG_log("check_kernel_encrypt_alg(%d,%d): alg not present in system", -@@ -476,6 +481,10 @@ - int sadb_aalg, sadb_ealg; - static struct esp_info ei_buf; /* static ??? fixme */ - -+ /* fixup broken IANA registry */ -+ if (transid == ESP_CAMELLIA) -+ transid = ESP_CAMELLIAv1; -+ - DBG(DBG_PARSING, - DBG_log("kernel_alg_esp_info(): transid=%d, keylen=%d,auth=%d, ", - transid, keylen, auth)); -diff -Naur libreswan-3.12-orig/programs/pluto/crypto.c libreswan-3.12/programs/pluto/crypto.c ---- libreswan-3.12-orig/programs/pluto/crypto.c 2014-11-06 22:52:50.000000000 -0500 -+++ libreswan-3.12/programs/pluto/crypto.c 2014-12-03 20:32:48.591715818 -0500 -@@ -376,6 +376,7 @@ - case IKEv2_ENCR_AES_GCM_8: - case IKEv2_ENCR_AES_GCM_12: - case IKEv2_ENCR_AES_GCM_16: -+ case IKEv2_ENCR_CAMELLIA_CBC_ikev1: /* IANA ikev1/ipsec-v3 fixup */ - case IKEv2_ENCR_CAMELLIA_CBC: - case IKEv2_ENCR_NULL_AUTH_AES_GMAC: - return AES_KEY_DEF_LEN; -diff -Naur libreswan-3.12-orig/programs/pluto/ike_alg.c libreswan-3.12/programs/pluto/ike_alg.c ---- libreswan-3.12-orig/programs/pluto/ike_alg.c 2014-11-06 22:52:50.000000000 -0500 -+++ libreswan-3.12/programs/pluto/ike_alg.c 2014-12-03 20:32:48.592715843 -0500 -@@ -189,9 +189,18 @@ - enum ikev2_trans_type_encr algo_v2id) - { - struct ike_alg *e = ike_alg_base[algo_type]; -+ int search_algo_v2id = algo_v2id; -+ -+ /* -+ * these types are mixed up, so go along with it :( -+ * IKEv2_ENCR_CAMELLIA_CBC_ikev1 == ESP_CAMELLIAv1 -+ * IKEv2_ENCR_CAMELLIA_CBC == ESP_CAMELLIA -+ */ -+ if (algo_type == IKE_ALG_ENCRYPT && algo_v2id == IKEv2_ENCR_CAMELLIA_CBC_ikev1) -+ search_algo_v2id = IKEv2_ENCR_CAMELLIA_CBC; - - for (; e != NULL; e = e->algo_next) { -- if (e->algo_v2id == algo_v2id) -+ if (e->algo_v2id == search_algo_v2id) - break; - } - return e; -diff -Naur libreswan-3.12-orig/programs/pluto/ikev2_spdb_struct.c libreswan-3.12/programs/pluto/ikev2_spdb_struct.c ---- libreswan-3.12-orig/programs/pluto/ikev2_spdb_struct.c 2014-11-06 22:52:50.000000000 -0500 -+++ libreswan-3.12/programs/pluto/ikev2_spdb_struct.c 2014-12-03 20:32:48.594715892 -0500 -@@ -466,8 +466,13 @@ - unsigned int attr_cnt; - - dtfone->protoid = dp->protoid; -- if (!f->parentSA) -+ -+ if (!f->parentSA) { - dtfone->encr_transid = tr->transid; -+ /* IANA ikev1 / ipsec-v3 fixup */ -+ if (dtfone->encr_transid == IKEv2_ENCR_CAMELLIA_CBC_ikev1) -+ dtfone->encr_transid = IKEv2_ENCR_CAMELLIA_CBC; -+ } - - for (attr_cnt = 0; attr_cnt < tr->attr_cnt; - attr_cnt++) { -@@ -527,10 +532,12 @@ - break; - - case ENCAPSULATION_MODE: -- /* XXX */ - break; - - default: -+ libreswan_log( -+ "sa_v2_convert(): Ignored unknown IPsec transform attribute type: %d", -+ attr->type.ipsec); - break; - } - } -@@ -1881,10 +1888,10 @@ - case IKEv2_ENCR_CAMELLIA_CCM_A: - case IKEv2_ENCR_CAMELLIA_CCM_B: - case IKEv2_ENCR_CAMELLIA_CCM_C: -- /* no IKE struct encrypt_desc yet */ -- /* fall through */ -+ /* no IKE struct encrypt_desc yet, fall through */ - case IKEv2_ENCR_AES_CBC: - case IKEv2_ENCR_CAMELLIA_CBC: -+ case IKEv2_ENCR_CAMELLIA_CBC_ikev1: /* IANA ikev1/ipsec-v3 fixup */ - /* these all have mandatory key length attributes */ - if (ta.enckeylen == 0) { - loglog(RC_LOG_SERIOUS, "Missing mandatory KEY_LENGTH attribute - refusing proposal"); -@@ -1892,7 +1899,7 @@ - } - break; - default: -- loglog(RC_LOG_SERIOUS, "Did not find valid ESP encrypter - refusing proposal"); -+ loglog(RC_LOG_SERIOUS, "Did not find valid ESP encrypter for %d - refusing proposal", ta.encrypt); - pexpect(ta.encrypt == IKEv2_ENCR_NULL); /* fire photon torpedo! */ - return STF_FAIL + v2N_NO_PROPOSAL_CHOSEN; - } diff --git a/SOURCES/libreswan-3.12-1162770-gcm-man.patch b/SOURCES/libreswan-3.12-1162770-gcm-man.patch deleted file mode 100644 index 881cc6d..0000000 --- a/SOURCES/libreswan-3.12-1162770-gcm-man.patch +++ /dev/null @@ -1,25 +0,0 @@ -diff --git a/programs/configs/d.ipsec.conf/phase2alg.xml b/programs/configs/d.ipsec.conf/phase2alg.xml -index df5353b..560b3d4 100644 ---- a/programs/configs/d.ipsec.conf/phase2alg.xml -+++ b/programs/configs/d.ipsec.conf/phase2alg.xml -@@ -16,11 +16,15 @@ instance, "3des-md5" or "aes256-sha1;modp2048" or "aes-sha1,aes-md5". - The format for AH is AUTH followed by an optional PFSgroup. For - instance, "md5" or "sha1;modp1536". - --AES-GCM and AES-CCM use the syntax like --"phase2alg=aes_ccm_c-256-null". The only supported key sizes are 128, --192 and 256. The subscript (_a, _b and _c) stand for the ICV versions --(8,12,16). It is recommended to migrate to the _c versions, as support --for smaller ICV's will be removed in the future. -+AES-GCM and AES-CCM use a syntax like -+"phase2alg=aes_ccm-null or phase2alg=aes_gcm-null". The -+only supported key sizes are 128, 192 and 256, which are specified similarly -+to plain aes, i.e. "phase2alg=aes_gcm256". A subscript (_a or _b or _c) -+can be used to refer to the different ICV versions (8,12,16). The default -+when not using a subscript is the 16 bute ICV, so phase2alg=aes_gcm_c256-null) -+is the same as phase2alg=aes_gcm256-null. -+It is recommended to migrate to the _c versions (without specifying _c), -+as support for smaller ICV's might be removed in the future. - Note that openswan and versions of libreswan up to 3.6 require - adding the salt size to the key size. Therefor, to interop with an older - version of openswan or libreswan, use: "phase2alg=aes_ccm_c-280-null". For diff --git a/SOURCES/libreswan-3.12-1170018-netlink-label.patch b/SOURCES/libreswan-3.12-1170018-netlink-label.patch deleted file mode 100644 index 2b11cae..0000000 --- a/SOURCES/libreswan-3.12-1170018-netlink-label.patch +++ /dev/null @@ -1,124 +0,0 @@ -diff -Naur libreswan-3.12-orig/programs/pluto/kernel_netlink.c libreswan-3.12/programs/pluto/kernel_netlink.c ---- libreswan-3.12-orig/programs/pluto/kernel_netlink.c 2015-02-26 22:02:15.641000000 -0600 -+++ libreswan-3.12/programs/pluto/kernel_netlink.c 2015-02-26 22:04:29.990000000 -0600 -@@ -426,7 +426,7 @@ - struct { - struct nlmsghdr n; - struct nlmsgerr e; -- char data[1024]; -+ char data[MAX_NETLINK_DATA_SIZE]; - } rsp; - size_t len; - ssize_t r; -@@ -547,7 +547,7 @@ - struct { - struct nlmsghdr n; - struct nlmsgerr e; -- char data[1024]; -+ char data[MAX_NETLINK_DATA_SIZE]; - } rsp; - int error; - -@@ -610,7 +610,7 @@ - struct xfrm_userpolicy_info p; - struct xfrm_userpolicy_id id; - } u; -- char data[1024]; -+ char data[MAX_NETLINK_DATA_SIZE]; - } req; - int shift; - int dir; -@@ -907,7 +907,7 @@ - struct { - struct nlmsghdr n; - struct xfrm_usersa_info p; -- char data[1024]; -+ char data[MAX_NETLINK_DATA_SIZE]; - } req; - struct rtattr *attr; - const struct aead_alg *aead; -@@ -1233,7 +1233,7 @@ - struct { - struct nlmsghdr n; - struct xfrm_usersa_id id; -- char data[1024]; -+ char data[MAX_NETLINK_DATA_SIZE]; - } req; - - zero(&req); -@@ -1513,7 +1513,7 @@ - struct { - struct nlmsghdr n; - struct xfrm_userpolicy_info pol; -- char data[1024]; -+ char data[MAX_NETLINK_DATA_SIZE]; - } rsp; - - if (n->nlmsg_len < NLMSG_LENGTH(sizeof(*upe))) { -@@ -1569,7 +1569,7 @@ - { - struct { - struct nlmsghdr n; -- char data[1024]; -+ char data[MAX_NETLINK_DATA_SIZE]; - } rsp; - ssize_t r; - struct sockaddr_nl addr; -@@ -1650,7 +1650,7 @@ - struct nlmsgerr e; - struct xfrm_usersa_info sa; - } u; -- char data[1024]; -+ char data[MAX_NETLINK_DATA_SIZE]; - } rsp; - static bool get_cpi_bug = FALSE; /* sticky after failure */ - -@@ -2235,7 +2235,7 @@ - struct { - struct nlmsghdr n; - struct xfrm_usersa_info info; -- char data[1024]; -+ char data[MAX_NETLINK_DATA_SIZE]; - } rsp; - - zero(&req); -diff -Naur libreswan-3.12-orig/programs/pluto/kernel_netlink.h libreswan-3.12/programs/pluto/kernel_netlink.h ---- libreswan-3.12-orig/programs/pluto/kernel_netlink.h 2014-11-06 21:52:50.000000000 -0600 -+++ libreswan-3.12/programs/pluto/kernel_netlink.h 2015-02-26 22:02:44.521000000 -0600 -@@ -15,4 +15,13 @@ - - #if defined(linux) && defined(NETKEY_SUPPORT) - extern const struct kernel_ops netkey_kernel_ops; -+/* -+ * The socket buffer is used to queue netlink messages between sender and -+ * receiver. The size of these buffers specifies the maximum size you will be -+ * able to write() to a netlink socket, i.e. it will indirectly define the -+ * maximum message size. The default is 32KiB. For now we picked a somewhat -+ * arbitrary maximum of 8192 for the data portion to accomdate large selinux -+ * IPsec labels (see rhbz#1154784) -+ */ -+#define MAX_NETLINK_DATA_SIZE 8192 - #endif -diff -Naur libreswan-3.12-orig/programs/pluto/state.h libreswan-3.12/programs/pluto/state.h ---- libreswan-3.12-orig/programs/pluto/state.h 2015-02-26 22:02:15.658000000 -0600 -+++ libreswan-3.12/programs/pluto/state.h 2015-02-26 22:02:44.521000000 -0600 -@@ -195,10 +195,16 @@ - }; - - #ifdef HAVE_LABELED_IPSEC --/* security label length should not exceed 256 in most cases, -- * (discussed with kernel and selinux people). -+/* -+ * While security label length usually does not exceed 256, -+ * there have been requests (rhbz#1154784) for using larger -+ * labels. The maximum label size is PAGE_SIZE (4096 on a -+ * x86_64, but 64kb on ppc64). However, this label has to fit -+ * inside a netlink message whose maximum size is 32KiB. -+ * For now we picked the somewhat arbitrary size of 4096. - */ --#define MAX_SECCTX_LEN 257 /* including '\0'*/ -+#define MAX_SECCTX_LEN 4096 /* including '\0'*/ -+ - struct xfrm_user_sec_ctx_ike { - u_int16_t len; - u_int16_t exttype; diff --git a/SOURCES/libreswan-3.12-1182224-bsi-random.patch b/SOURCES/libreswan-3.12-1182224-bsi-random.patch deleted file mode 100644 index 7810a7b..0000000 --- a/SOURCES/libreswan-3.12-1182224-bsi-random.patch +++ /dev/null @@ -1,571 +0,0 @@ -diff -Naur libreswan-3.12-orig/include/ipsecconf/keywords.h libreswan-3.12/include/ipsecconf/keywords.h ---- libreswan-3.12-orig/include/ipsecconf/keywords.h 2015-02-26 21:24:52.037000000 -0600 -+++ libreswan-3.12/include/ipsecconf/keywords.h 2015-02-26 21:25:39.297000000 -0600 -@@ -83,6 +83,7 @@ - KBF_STRICTCRLPOLICY, - KBF_SEND_CA, - KBF_NATIKEPORT, -+ KBF_SEEDBITS, - KBF_KEEPALIVE, - KBF_PLUTORESTARTONCRASH, - KBF_CRLCHECKINTERVAL, -diff -Naur libreswan-3.12-orig/lib/libipsecconf/confread.c libreswan-3.12/lib/libipsecconf/confread.c ---- libreswan-3.12-orig/lib/libipsecconf/confread.c 2015-02-26 21:24:52.038000000 -0600 -+++ libreswan-3.12/lib/libipsecconf/confread.c 2015-02-26 21:25:39.297000000 -0600 -@@ -98,6 +98,10 @@ - - cfg->setup.options[KBF_KEEPALIVE] = 0; /* config setup */ - cfg->setup.options[KBF_NATIKEPORT] = NAT_IKE_UDP_PORT; -+ -+ /* Don't inflict BSI requirements on everyone */ -+ cfg->setup.options[KBF_SEEDBITS] = 0; -+ - #ifdef HAVE_LABELED_IPSEC - cfg->setup.options[KBF_SECCTX] = SECCTX; - #endif -diff -Naur libreswan-3.12-orig/lib/libipsecconf/keywords.c libreswan-3.12/lib/libipsecconf/keywords.c ---- libreswan-3.12-orig/lib/libipsecconf/keywords.c 2015-02-26 21:24:52.038000000 -0600 -+++ libreswan-3.12/lib/libipsecconf/keywords.c 2015-02-26 21:25:39.298000000 -0600 -@@ -369,6 +369,7 @@ - { "virtual-private", kv_config, kt_string, KSF_VIRTUALPRIVATE, NOT_ENUM }, - { "nat_ikeport", kv_config | kv_alias, kt_number, KBF_NATIKEPORT, NOT_ENUM }, /* obsolete _ */ - { "nat-ikeport", kv_config, kt_number, KBF_NATIKEPORT, NOT_ENUM }, -+ { "seedbits", kv_config, kt_number, KBF_SEEDBITS, NOT_ENUM }, - { "keep_alive", kv_config | kv_alias, kt_number, KBF_KEEPALIVE, NOT_ENUM }, /* obsolete _ */ - { "keep-alive", kv_config, kt_number, KBF_KEEPALIVE, NOT_ENUM }, - { "nat_traversal", kv_config, kt_obsolete_quiet, KBF_WARNIGNORE, NOT_ENUM }, -diff -Naur libreswan-3.12-orig/programs/configs/d.ipsec.conf/order.txt libreswan-3.12/programs/configs/d.ipsec.conf/order.txt ---- libreswan-3.12-orig/programs/configs/d.ipsec.conf/order.txt 2015-02-26 21:24:52.040000000 -0600 -+++ libreswan-3.12/programs/configs/d.ipsec.conf/order.txt 2015-02-26 21:25:39.298000000 -0600 -@@ -89,6 +89,7 @@ - d.ipsec.conf/myvendorid.xml - d.ipsec.conf/oe.xml - d.ipsec.conf/nhelpers.xml -+d.ipsec.conf/seedbits.xml - d.ipsec.conf/secctx-attr-value.xml - d.ipsec.conf/plutofork.xml - d.ipsec.conf/crlcheckinterval.xml -diff -Naur libreswan-3.12-orig/programs/configs/d.ipsec.conf/seedbits.xml libreswan-3.12/programs/configs/d.ipsec.conf/seedbits.xml ---- libreswan-3.12-orig/programs/configs/d.ipsec.conf/seedbits.xml 1969-12-31 18:00:00.000000000 -0600 -+++ libreswan-3.12/programs/configs/d.ipsec.conf/seedbits.xml 2015-02-26 21:25:39.299000000 -0600 -@@ -0,0 +1,15 @@ -+ -+ seedbits -+ -+ -+Pluto uses the NSS crypto library as its random source. Some government -+Three Letter Agencies require that pluto reads additional bits from /dev/random -+and feed these into the NSS RNG before drawing random from the NSS library, -+despite the NSS library itself already seeding its internal state. This -+process can block pluto for an extended time during startup, depending on -+the entropy of the system. Therefor, the default is to not perform this -+redundant seeding. If specifying a value, it is recommended to specify at -+least 460 bits (for FIPS) or 440 bits (for BSI). -+ -+ -+ -diff -Naur libreswan-3.12-orig/programs/pluto/pluto.8 libreswan-3.12/programs/pluto/pluto.8 ---- libreswan-3.12-orig/programs/pluto/pluto.8 2014-11-06 21:52:50.000000000 -0600 -+++ libreswan-3.12/programs/pluto/pluto.8 2015-02-26 21:25:39.299000000 -0600 -@@ -2,12 +2,12 @@ - .\" Title: IPSEC_PLUTO - .\" Author: Paul Wouters - .\" Generator: DocBook XSL Stylesheets v1.78.1 --.\" Date: 10/22/2014 -+.\" Date: 01/14/2015 - .\" Manual: Executable programs - .\" Source: libreswan - .\" Language: English - .\" --.TH "IPSEC_PLUTO" "8" "10/22/2014" "libreswan" "Executable programs" -+.TH "IPSEC_PLUTO" "8" "01/14/2015" "libreswan" "Executable programs" - .\" ----------------------------------------------------------------- - .\" * Define some portability stuff - .\" ----------------------------------------------------------------- -@@ -31,7 +31,7 @@ - pluto \- ipsec whack : IPsec IKE keying daemon and control interface - .SH "SYNOPSIS" - .HP \w'\fBipsec\fR\ 'u --\fBipsec\fR \fIpluto\fR [\-\-help] [\-\-version] [\-\-leak\-detective] [\-\-config\ \fIfilename\fR] [\-\-vendorid\ \fIVID\fR] [\-\-nofork] [\-\-stderrlog] [\-\-\-\-plutostderrlogtime] [\-\-logfile\ \fIfilename\fR] [\-\-use\-klips] [\-\-use\-mast] [\-\-use\-netkey] [\-\-use\-nostack] [\-\-uniqueids] [\-\-virtual\-private\ \fInetwork_list\fR] [\-\-keep\-alive\ \fIdelay_sec\fR] [\-\-force\-busy] [\-\-nocrsend] [\-\-strictcrlpolicy] [\-\-crlcheckinterval] [\-\-interface\ \fIinterfacename\fR] [\-\-listen\ \fIipaddr\fR] [\-\-ikeport\ \fIportnumber\fR] [\-\-natikeport\ \fIportnumber\fR] [\-\-ctlbase\ \fIpath\fR] [\-\-secretsfile\ \fIsecrets\-file\fR] [\-\-adns\ \fIpathname\fR] [\-\-nhelpers\ \fInumber\fR] [\-\-perpeerlog] [\-\-perpeerlogbase\ \fIdirname\fR] [\-\-ipsecdir\ \fIdirname\fR] [\-\-coredir\ \fIdirname\fR] [\-\-statsbin\ \fIfilename\fR] [\-\-secctx\-attr\-value\ \fInumber\fR] -+\fBipsec\fR \fIpluto\fR [\-\-help] [\-\-version] [\-\-leak\-detective] [\-\-config\ \fIfilename\fR] [\-\-vendorid\ \fIVID\fR] [\-\-nofork] [\-\-stderrlog] [\-\-\-\-plutostderrlogtime] [\-\-logfile\ \fIfilename\fR] [\-\-use\-klips] [\-\-use\-mast] [\-\-use\-netkey] [\-\-use\-nostack] [\-\-uniqueids] [\-\-virtual\-private\ \fInetwork_list\fR] [\-\-keep\-alive\ \fIdelay_sec\fR] [\-\-force\-busy] [\-\-nocrsend] [\-\-strictcrlpolicy] [\-\-crlcheckinterval] [\-\-interface\ \fIinterfacename\fR] [\-\-listen\ \fIipaddr\fR] [\-\-ikeport\ \fIportnumber\fR] [\-\-natikeport\ \fIportnumber\fR] [\-\-ctlbase\ \fIpath\fR] [\-\-secretsfile\ \fIsecrets\-file\fR] [\-\-adns\ \fIpathname\fR] [\-\-nhelpers\ \fInumber\fR] [\-\-seedbits\ \fInumbits\fR] [\-\-perpeerlog] [\-\-perpeerlogbase\ \fIdirname\fR] [\-\-ipsecdir\ \fIdirname\fR] [\-\-coredir\ \fIdirname\fR] [\-\-statsbin\ \fIfilename\fR] [\-\-secctx\-attr\-value\ \fInumber\fR] - .HP \w'\fBipsec\fR\ 'u - \fBipsec\fR \fIwhack\fR [\-\-help] [\-\-version] - .HP \w'\fBipsec\fR\ 'u -@@ -317,6 +317,10 @@ - \fI\-1\fR - tells pluto to perform the above calculation\&. Any other value forces the number to that amount\&. - .PP -+Pluto uses the NSS crypto library as its random source\&. Some government Three Letter Agency requires that pluto reads 440 bits from /dev/random and feed this into the NSS RNG before drawing random from the NSS library, despite the NSS library itself already seeding its internal state\&. As this process can block pluto for an extended time, the default is to not perform this redundant seeding\&. The -+\fB\-\-seedbits\fR -+option can be used to specify the number of bits that will be pulled from /dev/random and seeded into the NSS RNG\&. This can also be accomplished by specifying seedbits in the "config setup" section of ipsec\&.conf\&. This option should not be used by most people\&. -+.PP - \fBpluto\fR - attempts to create a lockfile with the name - /var/run/pluto/pluto\&.pid\&. If the lockfile cannot be created, -diff -Naur libreswan-3.12-orig/programs/pluto/pluto.8.xml libreswan-3.12/programs/pluto/pluto.8.xml ---- libreswan-3.12-orig/programs/pluto/pluto.8.xml 2014-11-06 21:52:50.000000000 -0600 -+++ libreswan-3.12/programs/pluto/pluto.8.xml 2015-02-26 21:25:39.300000000 -0600 -@@ -57,6 +57,7 @@ - --secretsfile secrets-file - --adns pathname - --nhelpers number -+ --seedbits numbits - --perpeerlog - --perpeerlogbase dirname - --ipsecdir dirname -@@ -984,6 +985,18 @@ - -1 tells pluto to perform the above - calculation. Any other value forces the number to that amount. - -+ Pluto uses the NSS crypto library as its random source. Some -+ government Three Letter Agency requires that pluto reads 440 bits -+ from /dev/random and feed this into the NSS RNG before drawing -+ random from the NSS library, despite the NSS library itself -+ already seeding its internal state. As this process can block -+ pluto for an extended time, the default is to not perform this -+ redundant seeding. The --seedbits -+ option can be used to specify the number of bits that will be -+ pulled from /dev/random and seeded into the NSS RNG. This can -+ also be accomplished by specifying seedbits in the "config setup" -+ section of ipsec.conf. This option should not be used by most people. -+ - pluto attempts to create a lockfile - with the name /var/run/pluto/pluto.pid. If the - lockfile cannot be created, pluto exits - -diff -Naur libreswan-3.12-orig/programs/pluto/plutomain.c libreswan-3.12/programs/pluto/plutomain.c ---- libreswan-3.12-orig/programs/pluto/plutomain.c 2015-02-26 21:24:52.012000000 -0600 -+++ libreswan-3.12/programs/pluto/plutomain.c 2015-02-26 21:25:39.301000000 -0600 -@@ -111,6 +111,7 @@ - /* pulled from main for show_setup_plutomain() */ - static const struct lsw_conf_options *oco; - static char *coredir; -+static int pluto_nss_seedbits; - static int nhelpers = -1; - - libreswan_passert_fail_t libreswan_passert_fail = passert_fail; -@@ -314,6 +315,49 @@ - *target = strdup(value); - } - -+/* -+ * This function MUST NOT be used for anything else! -+ * It is used to seed the NSS PRNG based on --seedbits pluto argument -+ * or the seedbits= * config setup option in ipsec.conf. -+ * Everything else that needs random MUST use get_rnd_bytes() -+ * This function MUST NOT be changed to use /dev/urandom. -+ */ -+static void get_bsi_random(size_t nbytes, unsigned char *buf) -+{ -+ size_t ndone; -+ int dev; -+ ssize_t got; -+ const char *device = "/dev/random"; -+ -+ dev = open(device, 0); -+ if (dev < 0) { -+ loglog(RC_LOG_SERIOUS, "could not open %s (%s)\n", -+ device, strerror(errno)); -+ exit_pluto(6); -+ } -+ -+ ndone = 0; -+ DBG(DBG_CONTROL,DBG_log("need %d bits random for extra seeding of the NSS PRNG", -+ (int) nbytes * BITS_PER_BYTE)); -+ -+ while (ndone < nbytes) { -+ got = read(dev, buf + ndone, nbytes - ndone); -+ if (got < 0) { -+ loglog(RC_LOG_SERIOUS,"read error on %s (%s)\n", -+ device, strerror(errno)); -+ exit_pluto(6); -+ } -+ if (got == 0) { -+ loglog(RC_LOG_SERIOUS,"EOF on %s!?!\n", device); -+ exit_pluto(6); -+ } -+ ndone += got; -+ } -+ close(dev); -+ DBG(DBG_CONTROL,DBG_log("read %ld bytes from /dev/random for NSS PRNG", -+ nbytes)); -+} -+ - static void pluto_init_nss(char *confddir) - { - SECStatus nss_init_status; -@@ -328,6 +372,23 @@ - libreswan_log("NSS Initialized"); - PK11_SetPasswordFunc(getNSSPassword); - } -+ -+ /* -+ * This exists purely to make the BSI happy. -+ * We do not infliect this on other users -+ */ -+ if (pluto_nss_seedbits != 0) { -+ SECStatus rv; -+ int seedbytes = BYTES_FOR_BITS(pluto_nss_seedbits); -+ unsigned char *buf = alloc_bytes(seedbytes,"TLA seedmix"); -+ -+ get_bsi_random(seedbytes, buf); /* much TLA, very blocking */ -+ rv = PK11_RandomUpdate(buf, seedbytes); -+ libreswan_log("seeded %d bytes into the NSS PRNG", seedbytes); -+ passert(rv == SECSuccess); -+ zero(&buf); -+ pfree(buf); -+ } - } - - /* by default the CRL policy is lenient */ -@@ -417,6 +478,7 @@ - { "virtual_private\0_", required_argument, NULL, '6' }, /* _ */ - { "virtual-private\0", required_argument, NULL, '6' }, - { "nhelpers\0", required_argument, NULL, 'j' }, -+ { "seedbits\0", required_argument, NULL, 'c' }, - #ifdef HAVE_LABELED_IPSEC - { "secctx_attr_value\0_", required_argument, NULL, 'w' }, /* _ */ - { "secctx-attr-value\0", required_argument, NULL, 'w' }, -@@ -692,6 +754,14 @@ - nhelpers = u; - } - continue; -+ case 'c': /* --seedbits */ -+ pluto_nss_seedbits = atoi(optarg); -+ if (pluto_nss_seedbits == 0) { -+ printf("pluto: seedbits must be an integer > 0"); -+ /* not exit_pluto because we are not initialized yet */ -+ exit(6); -+ } -+ continue; - - #ifdef HAVE_LABELED_IPSEC - case 'w': /* --secctx-attr-value */ -@@ -969,6 +1039,7 @@ - } - } - -+ pluto_nss_seedbits = cfg->setup.options[KBF_SEEDBITS]; - pluto_nat_port = - cfg->setup.options[KBF_NATIKEPORT]; - keep_alive = cfg->setup.options[KBF_KEEPALIVE]; -@@ -1473,3 +1544,4 @@ - whack_log(RC_COMMENT, "secctx-attr-value="); - #endif - } -+ -diff -Naur libreswan-3.12-orig/programs/rsasigkey/Makefile libreswan-3.12/programs/rsasigkey/Makefile ---- libreswan-3.12-orig/programs/rsasigkey/Makefile 2014-11-06 21:52:50.000000000 -0600 -+++ libreswan-3.12/programs/rsasigkey/Makefile 2015-02-26 21:25:39.301000000 -0600 -@@ -16,7 +16,7 @@ - include ${LIBRESWANSRCDIR}/Makefile.inc - - PROGRAM=rsasigkey --LIBS=${LIBRESWANLIB} -lgmp -+LIBS=${LSWLOGLIB} ${LIBRESWANLIB} -lgmp - LIBS+=${NSSLIBS} - - ifeq ($(USE_FIPSCHECK),true) -diff -Naur libreswan-3.12-orig/programs/rsasigkey/rsasigkey.8 libreswan-3.12/programs/rsasigkey/rsasigkey.8 ---- libreswan-3.12-orig/programs/rsasigkey/rsasigkey.8 2014-11-06 21:52:50.000000000 -0600 -+++ libreswan-3.12/programs/rsasigkey/rsasigkey.8 2015-02-26 21:25:39.302000000 -0600 -@@ -2,12 +2,12 @@ - .\" Title: IPSEC_RSASIGKEY - .\" Author: Paul Wouters - .\" Generator: DocBook XSL Stylesheets v1.78.1 --.\" Date: 09/06/2013 -+.\" Date: 01/14/2015 - .\" Manual: Executable programs - .\" Source: libreswan - .\" Language: English - .\" --.TH "IPSEC_RSASIGKEY" "8" "09/06/2013" "libreswan" "Executable programs" -+.TH "IPSEC_RSASIGKEY" "8" "01/14/2015" "libreswan" "Executable programs" - .\" ----------------------------------------------------------------- - .\" * Define some portability stuff - .\" ----------------------------------------------------------------- -@@ -31,9 +31,7 @@ - ipsec_rsasigkey \- generate RSA signature key - .SH "SYNOPSIS" - .HP \w'\fBipsec\fR\ 'u --\fBipsec\fR \fIrsasigkey\fR [\-\-verbose] [\-\-random\ \fIfilename\fR] [\-\-configdir\ \fInssdbdir\fR] [\-\-password\ \fInsspassword\fR] [\-\-hostname\ \fIhostname\fR] [nbits] --.HP \w'\fBipsec\fR\ 'u --\fBipsec\fR \fIrsasigkey\fR [\-\-verbose] [\-\-configdir\ \fInssdbdir\fR] [\-\-password\ \fInsspassword\fR] [\-\-hostname\ \fIhostname\fR] -+\fBipsec\fR \fIrsasigkey\fR [\-\-verbose] [\-\-random\ \fIdevice\fR] [\-\-seed\ \fInumbits\fR] [\-\-configdir\ \fInssdbdir\fR] [\-\-password\ \fInsspassword\fR] [\-\-hostname\ \fIhostname\fR] [nbits] - .SH "DESCRIPTION" - .PP - \fIRsasigkey\fR -@@ -50,7 +48,8 @@ - .PP - The - \fB\-\-verbose\fR --option makes\fIrsasigkey\fR -+option makes -+\fIrsasigkey\fR - give a running commentary on standard error\&. By default, it works in silence until it is ready to generate output\&. - .PP - The -@@ -58,9 +57,15 @@ - option specifies a source for random bits used to seed the crypto library\*(Aqs RNG\&. The default is - /dev/random - (see --\fBrandom\fR(4))\&. FreeS/WAN and Openswan without NSS support used this option to specify the random source used to directly create keys\&. Libreswan only uses it to seed the crypto libraries RNG\&. Under Linux with hardware random support, special devices might show up as -+\fBrandom\fR(4))\&. FreeS/WAN and Openswan without NSS support use this option to specify the random source used to directly create keys\&. Libreswan only uses it to seed the NSS crypto libraries RNG\&. Under Linux with hardware random support, special devices might show up as - /dev/*rng* --devices\&. However, these should never be access directly using this option, as hardware failures could lead to extremely non\-random values (streams of zeroes have been observed in the wild) -+devices\&. However, these should never be accessed directly using this option, as hardware failures could lead to extremely non\-random values (streams of zeroes have been observed in the wild) -+.PP -+The -+\fB\-\-seedbits\fR -+option specifies how many seed bits are pulled from the random device to seed the NSS PRNG\&. The default of 480bit comes from FIPS requirements\&. Seed bits are rounded up to a multiple of 8\&. -+.PP -+The use of a different random device or a reduction of seedbits from the default value is prevented when the system is running in FIPS mode\&. - .PP - The - \fB\-\-configdir\fR -@@ -69,7 +74,8 @@ - .PP - The - \fB\-\-password\fR --option specifies the nss cryptographic module authentication password if the NSS module has been configured to require it\&. A password is required by hardware tokens and also by the internal softotken module when configured to run in FIPS mode\&. -+option specifies the nss cryptographic module authentication password if the NSS module has been configured to require it\&. A password is required by hardware tokens and also by the internal software token module when configured to run in FIPS mode\&. If the argument is -+\fIconfigdir\fR/nsspassword, the password comes from that file; otherwise argument is the password\&. - .PP - The - \fB\-\-hostname\fR -@@ -140,7 +146,7 @@ - \fBCoefficient\fR - line gives the Chinese Remainder Theorem coefficient, which is the inverse of - \fIq\fR, mod --\fIp\fR\&. These additional numbers (which must all be kept as secret as the private exponent) are precomputed aids to rapid signature generation\&. When NSS is used, these values are not available outside the NSS security database (softtoken or hardware token) and are instead filled in with the CKA_ID\&. -+\fIp\fR\&. These additional numbers (which must all be kept as secret as the private exponent) are precomputed aids to rapid signature generation\&. When NSS is used, these values are not available outside the NSS security database (software token or hardware token) and are instead filled in with the CKA_ID\&. - .PP - No attempt is made to break long lines\&. - .PP -diff -Naur libreswan-3.12-orig/programs/rsasigkey/rsasigkey.8.xml libreswan-3.12/programs/rsasigkey/rsasigkey.8.xml ---- libreswan-3.12-orig/programs/rsasigkey/rsasigkey.8.xml 2014-11-06 21:52:50.000000000 -0600 -+++ libreswan-3.12/programs/rsasigkey/rsasigkey.8.xml 2015-02-26 21:25:39.302000000 -0600 -@@ -23,20 +23,13 @@ - ipsec - rsasigkey - --verbose -- --random filename -+ --random device -+ --seed numbits - --configdir nssdbdir - --password nsspassword - --hostname hostname - nbits - -- -- ipsec -- rsasigkey -- --verbose -- --configdir nssdbdir -- --password nsspassword -- --hostname hostname -- - - - -@@ -61,14 +54,22 @@ - source for random bits used to seed the crypto library's - RNG. The default is /dev/random (see - random4). --FreeS/WAN and Openswan without NSS support used this option to specify -+FreeS/WAN and Openswan without NSS support use this option to specify - the random source used to directly create keys. Libreswan only uses --it to seed the crypto libraries RNG. Under Linux with hardware random -+it to seed the NSS crypto libraries RNG. Under Linux with hardware random - support, special devices might show up as /dev/*rng* --devices. However, these should never be access directly using this option, -+devices. However, these should never be accessed directly using this option, - as hardware failures could lead to extremely non-random values (streams - of zeroes have been observed in the wild) - -+The option specifies how many seed bits are pulled from -+the random device to seed the NSS PRNG. The default of 480bit comes from FIPS requirements. -+Seed bits are rounded up to a multiple of 8. -+ -+ -+The use of a different random device or a reduction of seedbits from the default value is -+prevented when the system is running in FIPS mode. -+ - The option specifies the nss configuration directory to use. - This is the directory where the NSS certificate, key and security modules databases reside. The - default value is /etc/ipsec.d. -diff -Naur libreswan-3.12-orig/programs/rsasigkey/rsasigkey.c libreswan-3.12/programs/rsasigkey/rsasigkey.c ---- libreswan-3.12-orig/programs/rsasigkey/rsasigkey.c 2014-11-06 21:52:50.000000000 -0600 -+++ libreswan-3.12/programs/rsasigkey/rsasigkey.c 2015-02-26 21:25:39.303000000 -0600 -@@ -4,7 +4,7 @@ - * Copyright (C) 2003-2008 Michael C Richardson - * Copyright (C) 2003-2009 Paul Wouters - * Copyright (C) 2009 Avesh Agarwal -- * Copyright (C) 2012-2013 Paul Wouters -+ * Copyright (C) 2012-2015 Paul Wouters - * - * 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 -@@ -64,26 +64,22 @@ - #define MIN_KEYBIT 2192 - - #ifndef DEVICE --/* To the openwrt people: Do not change /dev/random to /dev/urandom. The -- * /dev/random device is ONLY used for generating long term keys, which -- * should NEVER be done with /dev/urandom. If people use X.509, PSK or -- * even raw RSA keys generated on other systems, changing this will have -- * 0 effect. It's better to fail or bail out of generating a key, then -- * generate a bad one. -- */ - # define DEVICE "/dev/random" - #endif - #ifndef MAXBITS - # define MAXBITS 20000 - #endif - -+#define DEFAULT_SEED_BITS 60 /* 480 bits of random seed */ -+ - #define E 3 /* standard public exponent */ - /* #define F4 65537 */ /* possible future public exponent, Fermat's 4th number */ - - #define NSSDIR "/etc/ipsec.d" - -+char *progname; - char usage[] = -- "rsasigkey [--verbose] [--random ] [--configdir ] [--password ] [--hostname host] []"; -+ "rsasigkey [--verbose] [--random ] [--configdir ] [--password ] [--hostname host] [--seedbits bits] []"; - struct option opts[] = { - { "rounds", 1, NULL, 'p', }, /* obsoleted */ - { "noopt", 0, NULL, 'n', }, /* obsoleted */ -@@ -96,6 +92,7 @@ - { "configdir", 1, NULL, 'c' }, - { "configdir2", 1, NULL, 'd' }, /* nss tools use -d */ - { "password", 1, NULL, 'P' }, -+ { "seedbits", 1, NULL, 's' }, - { 0, 0, NULL, 0, } - }; - int verbose = 0; /* narrate the action? */ -@@ -106,14 +103,13 @@ - char me[] = "ipsec rsasigkey"; /* for messages */ - - /* forwards */ --void rsasigkey(int nbits, char *configdir, char *password); -+void rsasigkey(int nbits, int seedbits, char *configdir, char *password); - void getrandom(size_t nbytes, unsigned char *buf); - static const unsigned char *bundle(int e, mpz_t n, size_t *sizep); - static const char *conv(const unsigned char *bits, size_t nbytes, int format); - static const char *hexout(mpz_t var); - void report(char *msg); - --#define RAND_BUF_SIZE 60 - - /* getModulus - returns modulus of the RSA public key */ - static SECItem *getModulus(SECKEYPublicKey *pk) -@@ -163,15 +159,17 @@ - } - - /* UpdateRNG - Updates NSS's PRNG with user generated entropy. */ --static void UpdateNSS_RNG(void) -+static void UpdateNSS_RNG(int seedbits) - { - SECStatus rv; -- unsigned char buf[RAND_BUF_SIZE]; -+ int seedbytes = BYTES_FOR_BITS(seedbits); -+ unsigned char *buf = alloc_bytes(seedbytes,"TLA seedmix"); - -- getrandom(RAND_BUF_SIZE, buf); -- rv = PK11_RandomUpdate(buf, sizeof buf); -+ getrandom(seedbytes, buf); -+ rv = PK11_RandomUpdate(buf, seedbytes); - assert(rv == SECSuccess); - zero(&buf); -+ pfree(buf); - } - - /* Returns the password passed in in the text file. -@@ -303,6 +301,7 @@ - { - int opt; - int nbits = 0; -+ int seedbits = DEFAULT_SEED_BITS; - char *configdir = NULL; /* where the NSS databases reside */ - char *password = NULL; /* password for token authentication */ - -@@ -344,6 +343,16 @@ - case 'P': /* token authentication password */ - password = optarg; - break; -+ case 's': /* seed bits */ -+ seedbits = atoi(optarg); -+ if (PK11_IsFIPS()) { -+ if (seedbits < DEFAULT_SEED_BITS) { -+ fprintf(stderr, "%s: FIPS mode does not allow < %d seed bits\n", -+ me, DEFAULT_SEED_BITS); -+ exit(1); -+ } -+ } -+ break; - case '?': - default: - printf("Usage:\t%s\n", usage); -@@ -393,7 +402,7 @@ - exit(1); - } - -- rsasigkey(nbits, configdir, password); -+ rsasigkey(nbits, seedbits, configdir, password); - exit(0); - } - -@@ -405,7 +414,7 @@ - * real speed advantages. - * See also: https://www.imperialviolet.org/2012/03/16/rsae.html - */ --void rsasigkey(int nbits, char *configdir, char *password) -+void rsasigkey(int nbits, int seedbits, char *configdir, char *password) - { - SECStatus rv; - PK11RSAGenParams rsaparams = { nbits, (long) E }; -@@ -483,7 +492,7 @@ - #endif /* 0 */ - - /* Do some random-number initialization. */ -- UpdateNSS_RNG(); -+ UpdateNSS_RNG(seedbits); - /* Log in to the token */ - if (password) { - rv = PK11_Authenticate(slot, PR_FALSE, &pwdata); -@@ -553,9 +562,7 @@ - /* - - getrandom - get some random bytes from /dev/random (or wherever) - */ --void getrandom(nbytes, buf) --size_t nbytes; --unsigned char *buf; /* known to be big enough */ -+void getrandom(size_t nbytes, unsigned char *buf) - { - size_t ndone; - int dev; -@@ -570,8 +577,8 @@ - - ndone = 0; - if (verbose) { -- fprintf(stderr, "getting %d random bytes from %s...\n", -- (int) nbytes, -+ fprintf(stderr, "getting %d random seed bytes for NSS from %s...\n", -+ (int) nbytes * BITS_PER_BYTE, - device); - } - while (ndone < nbytes) { -@@ -683,3 +690,12 @@ - - fprintf(stderr, "%s\n", msg); - } -+/* exit_tool() is needed if the library was compiled with DEBUG, even if we are not. -+ * The odd-looking parens are to prevent macro expansion: -+ * lswlog.h without DEBUG define a macro exit_tool(). -+ */ -+void (exit_tool)(int x) -+{ -+ exit(x); -+} -+ diff --git a/SOURCES/libreswan-3.12-1203794-fipstest.patch b/SOURCES/libreswan-3.12-1203794-fipstest.patch deleted file mode 100644 index dc6a248..0000000 --- a/SOURCES/libreswan-3.12-1203794-fipstest.patch +++ /dev/null @@ -1,57 +0,0 @@ -diff -Naur libreswan-3.12-orig/programs/pluto/ike_alg_aes.c libreswan-3.12/programs/pluto/ike_alg_aes.c ---- libreswan-3.12-orig/programs/pluto/ike_alg_aes.c 2015-04-12 16:52:11.748913102 -0400 -+++ libreswan-3.12/programs/pluto/ike_alg_aes.c 2015-04-12 20:19:08.330821771 -0400 -@@ -410,20 +410,24 @@ - - void ike_alg_aes_init(void) - { -- if (!test_aes_cbc(&algo_aes_cbc)) { -+ bool fips = libreswan_fipsmode(); -+ if (!fips && !test_aes_cbc(&algo_aes_cbc)) { - loglog(RC_LOG_SERIOUS, "CKM_AES_CBC: test failure"); -+ exit_pluto(6); - } - if (ike_alg_register_enc(&algo_aes_cbc) != 1) - loglog(RC_LOG_SERIOUS, "Warning: failed to register algo_aes_cbc for IKE"); - -- if (!test_aes_ctr(&algo_aes_ctr)) { -+ if (!fips && !test_aes_ctr(&algo_aes_ctr)) { - loglog(RC_LOG_SERIOUS, "CKM_AES_CTR: test failure"); -+ exit_pluto(6); - } - if (ike_alg_register_enc(&algo_aes_ctr) != 1) - loglog(RC_LOG_SERIOUS, "Warning: failed to register algo_aes_ctr for IKE"); - -- if (!test_aes_gcm()) { -+ if (!fips && !test_aes_gcm()) { - loglog(RC_LOG_SERIOUS, "CKM_AES_GCM: test failure"); -+ exit_pluto(6); - } - if (ike_alg_register_enc(&algo_aes_gcm_8) != 1) - loglog(RC_LOG_SERIOUS, "Warning: failed to register algo_aes_gcm_8 for IKE"); -diff -Naur libreswan-3.12-orig/programs/pluto/ike_alg_camellia.c libreswan-3.12/programs/pluto/ike_alg_camellia.c ---- libreswan-3.12-orig/programs/pluto/ike_alg_camellia.c 2015-04-12 16:52:11.705911919 -0400 -+++ libreswan-3.12/programs/pluto/ike_alg_camellia.c 2015-04-12 17:41:22.863365586 -0400 -@@ -94,11 +94,20 @@ - - void ike_alg_camellia_init(void) - { -- test_camellia_cbc(&algo_camellia_cbc); -+#ifdef FIPS_CHECK -+ bool fips = libreswan_fipsmode(); -+#else -+ bool fips = FALSE; -+#endif -+ -+ if (!fips && !test_camellia_cbc(&algo_camellia_cbc)) { -+ loglog(RC_LOG_SERIOUS, "CKM_CAMELLIA_CBC: test failure"); -+ exit_pluto(6); -+ } -+ - if (ike_alg_register_enc(&algo_camellia_cbc) != 1) - loglog(RC_LOG_SERIOUS, "Warning: failed to register algo_camellia_cbc for IKE"); - -- // test_camellia_ctr(&algo_camellia_ctr); - if (ike_alg_register_enc(&algo_camellia_ctr) != 1) - loglog(RC_LOG_SERIOUS, "Warning: failed to register algo_camellia_ctr for IKE"); - } diff --git a/SOURCES/libreswan-3.12-1207689-blacklist.patch b/SOURCES/libreswan-3.12-1207689-blacklist.patch deleted file mode 100644 index 2ed01e5..0000000 --- a/SOURCES/libreswan-3.12-1207689-blacklist.patch +++ /dev/null @@ -1,160 +0,0 @@ -diff -Naur libreswan-3.12-orig/Makefile.inc libreswan-3.12/Makefile.inc ---- libreswan-3.12-orig/Makefile.inc 2014-11-06 22:52:50.000000000 -0500 -+++ libreswan-3.12/Makefile.inc 2015-04-28 23:18:45.781649956 -0400 -@@ -176,7 +176,10 @@ - OSMOD_DESTDIR?=net/ipsec - - # What command to use to load the modules. openwrt does not have modprobe --MODPROBE?=modprobe -q -+# Using -b enables blacklisting - this is needed for some known bad -+# versions of crypto acceleration modules. -+MODPROBEBIN?=modprobe -+MODPROBEARGS?=-q -b - - ### misc installation stuff - -@@ -521,7 +524,8 @@ - -e "s:@IPSEC_EXECDIR@:$(FINALLIBEXECDIR):g" \ - -e "s:@IPSEC_VARDIR@:$(FINALVARDIR):g" \ - -e "s:@IPSEC_SBINDIR@:$(FINALSBINDIR):g" \ -- -e "s:@MODPROBE@:$(MODPROBE):g" \ -+ -e "s:@MODPROBEBIN@:$(MODPROBEBIN):g" \ -+ -e "s:@MODPROBEARGS@:$(MODPROBEARGS):g" \ - -e "s:@USE_DEFAULT_CONNS@:$(USE_DEFAULT_CONNS):g" \ - - # For KVM testing setup -diff -Naur libreswan-3.12-orig/programs/_stackmanager/_stackmanager.in libreswan-3.12/programs/_stackmanager/_stackmanager.in ---- libreswan-3.12-orig/programs/_stackmanager/_stackmanager.in 2014-11-06 22:52:50.000000000 -0500 -+++ libreswan-3.12/programs/_stackmanager/_stackmanager.in 2015-04-28 23:16:25.709947026 -0400 -@@ -2,7 +2,7 @@ - # STACK startup script - # Copyright (C) 2007 Ken Bantoft - # Copyright (C) 2007-2008 Paul Wouters --# Copyright (C) 2008-2014 Tuomo Soini -+# Copyright (C) 2008-2015 Tuomo Soini - # Copyright (C) 2012-2014 Paul Wouters - # - # This program is free software; you can redistribute it and/or modify it -@@ -24,6 +24,7 @@ - export PATH - - test ${IPSEC_INIT_SCRIPT_DEBUG} && set -v -x -+MODPROBE="@MODPROBEBIN@ @MODPROBEARGS@" - - kamepfkey=/proc/net/pfkey - ipsecpfkey=/proc/net/ipsec/version -@@ -119,11 +120,11 @@ - xfrm4_mode_beet esp4 esp6 ah4 ah6 af_key ip_vti - do - # echo -n "${mod} " >&2 -- @MODPROBE@ ${mod} 2>/dev/null -+ ${MODPROBE} ${mod} 2>/dev/null - done - - # xfrm_user is the old name for xfrm4_tunnel - backwards compatibility -- @MODPROBE@ xfrm_user 2>/dev/null -+ ${MODPROBE} xfrm_user 2>/dev/null - - fi - # Required for Labeled IPsec -@@ -184,19 +185,19 @@ - cryptomodules() { - # load hardware random and crypto related modules. - # some changed names over time -- @MODPROBE@ hw_random 2>/dev/null -- @MODPROBE@ hwrng 2>/dev/null -- @MODPROBE@ virtio-rng 2>/dev/null -- @MODPROBE@ amd-rng 2>/dev/null -- @MODPROBE@ intel-rng 2>/dev/null -- @MODPROBE@ geode-rng 2>/dev/null -- @MODPROBE@ timeriomem-rng 2>/dev/null -- @MODPROBE@ tpm-rng 2>/dev/null -+ ${MODPROBE} hw_random 2>/dev/null -+ ${MODPROBE} hwrng 2>/dev/null -+ ${MODPROBE} virtio-rng 2>/dev/null -+ ${MODPROBE} amd-rng 2>/dev/null -+ ${MODPROBE} intel-rng 2>/dev/null -+ ${MODPROBE} geode-rng 2>/dev/null -+ ${MODPROBE} timeriomem-rng 2>/dev/null -+ ${MODPROBE} tpm-rng 2>/dev/null - - # load any OCF and CryptoAPI modules we might need for acceleration - # (OCF works for NETKEY and KLIPS/MAST) - # OCF cryptosoft is for kernel acceleration (ESP/AH) -- @MODPROBE@ cryptosoft 2>/dev/null -+ ${MODPROBE} cryptosoft 2>/dev/null - # We skip cryptodev.ko because we no longer support /dev/crypto offloading - # (the overhead of cryptodev is not worth it even on embedded platforms) - -@@ -219,9 +220,9 @@ - # padlock must load before aes module - though does not exist on newer - # kernels - # padlock-aes must load before padlock-sha for some reason -- @MODPROBE@ padlock 2>/dev/null -- @MODPROBE@ padlock-aes 2>/dev/null -- @MODPROBE@ padlock-sha 2>/dev/null -+ ${MODPROBE} padlock 2>/dev/null -+ ${MODPROBE} padlock-aes 2>/dev/null -+ ${MODPROBE} padlock-sha 2>/dev/null - # load the most common ciphers/algo's - # aes-x86_64 has higher priority in via crypto api - # kernel directory does not match uname -m on x86_64 :( -@@ -234,7 +235,7 @@ - do - module=$(basename ${module} | sed "s/\.ko$//") - # echo -n "${module} " >&2 -- @MODPROBE@ ${module} 2>/dev/null -+ ${MODPROBE} ${module} 2>/dev/null - done - } - -@@ -264,10 +265,10 @@ - ;; - esac - # modprobe does not like specifying .o or .ko, but insmod needs it -- if [ "$(basename @MODPROBE@)" = "modprobe" ]; then -- @MODPROBE@ ipsec -+ if [ "$(basename "@MODPROBEBIN@")" = "modprobe" ]; then -+ ${MODPROBE} ipsec - else -- @MODPROBE@ ${modulename} -+ ${MODPROBE} ${modulename} - fi - - if [ ! -f ${ipsecpfkey} ]; then -@@ -418,7 +419,12 @@ - exit 4 - fi - --stack="$(ipsec addconn --config ${IPSEC_CONF} --liststack)" -+if [ "$2" = "--netkey" ]; then -+ # manual override for use in docker -+ stack=netkey -+else -+ stack="$(ipsec addconn --config ${IPSEC_CONF} --liststack)" -+fi - - case ${stack} in - netkey|klips|mast|none) -@@ -435,15 +441,18 @@ - - case ${action} in - stop) -- # We don't unload NETKEY/XFRM on stop - only when we detect a stack change. -+ # We don't unload NETKEY/XFRM on stop - only when we detect a stack -+ # change. - if [ -f ${ipsecpfkey} ]; then - ipsec eroute --clear -- # this clears all IP addresses on ipsecX interfaces by unloading the module -+ # this clears all IP addresses on ipsecX interfaces by -+ # unloading the module - stopklips - elif [ -f ${kamepfkey} ]; then - ip xfrm state flush - ip xfrm policy flush -- # module unloading skipped on purpose - can hang for a long time or fail -+ # module unloading skipped on purpose - can hang for a long -+ # time or fail - fi - ;; - start) diff --git a/SOURCES/libreswan-3.12-1212121-cavs.patch b/SOURCES/libreswan-3.12-1212121-cavs.patch deleted file mode 100644 index f1f7743..0000000 --- a/SOURCES/libreswan-3.12-1212121-cavs.patch +++ /dev/null @@ -1,5368 +0,0 @@ -diff -Naur libreswan-3.12-orig/programs/pluto/cavp.c libreswan-3.12/programs/pluto/cavp.c ---- libreswan-3.12-orig/programs/pluto/cavp.c 1969-12-31 19:00:00.000000000 -0500 -+++ libreswan-3.12/programs/pluto/cavp.c 2015-05-06 11:45:32.912301324 -0400 -@@ -0,0 +1,305 @@ -+/* -+ * Parse CAVP test vectors, for libreswan -+ * -+ * Copyright (C) 2015 Andrew Cagney -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * for more details. -+ */ -+ -+#include -+/* #include */ -+#include -+#include -+ -+#include "constants.h" -+#include "lswalloc.h" -+#include "ike_alg.h" -+#include "crypto.h" -+#include "crypt_symkey.h" -+#include "test_buffer.h" -+ -+#include "cavp.h" -+#include "cavp_print.h" -+#include "cavp_ikev1.h" -+#include "cavp_ikev2.h" -+ -+struct cavp *cavps[] = { -+ &cavp_ikev1_sig, -+ &cavp_ikev1_psk, -+ &cavp_ikev2, -+ NULL -+}; -+ -+#define BUF_SIZE 4096 -+ -+static struct cavp_entry *lookup_entry(struct cavp_entry *entries, const char *key) -+{ -+ struct cavp_entry *entry; -+ for (entry = entries; entry->op != NULL; entry++) { -+ if (strcmp(entry->key, key) == 0) { -+ return entry; -+ } -+ } -+ return NULL; -+} -+ -+enum what { INITIAL, BLANK, CONFIG, DATA, RUN, FINAL } state = INITIAL; -+ -+static void error_state(enum what state, enum what what) -+{ -+ fprintf(stderr, "bad state %d what %d\n", state, what); -+ exit(1); -+} -+ -+static struct cavp *cavp; -+ -+static void next_state(enum what what) -+{ -+ switch (state) { -+ case INITIAL: -+ switch (what) { -+ case CONFIG: -+ state = CONFIG; -+ break; -+ case BLANK: -+ break; -+ default: -+ error_state(state, what); -+ } -+ break; -+ case CONFIG: -+ switch (what) { -+ case CONFIG: -+ break; -+ case BLANK: -+ cavp->print_config(); -+ state = DATA; -+ break; -+ default: -+ error_state(state, what); -+ } -+ break; -+ case DATA: -+ switch (what) { -+ case DATA: -+ break; -+ case BLANK: -+ cavp->run(); -+ state = RUN; -+ break; -+ default: -+ error_state(state, what); -+ } -+ break; -+ case RUN: -+ switch (what) { -+ case CONFIG: -+ state = CONFIG; -+ break; -+ case DATA: -+ state = DATA; -+ break; -+ case BLANK: -+ break; -+ default: -+ error_state(state, what); -+ } -+ break; -+ default: -+ error_state(state, what); -+ break; -+ } -+} -+ -+struct hash_desc *hasher; -+char hasher_name[BUF_SIZE]; -+ -+void hash(struct cavp_entry *entry, -+ const char *value UNUSED) -+{ -+ strcpy(hasher_name, entry->key); -+ hasher = ike_alg_get_hasher(entry->value); -+ if (hasher == NULL) { -+ fprintf(stderr, "hasher %s not found\n", entry->key); -+ } -+} -+ -+void chunk(struct cavp_entry *entry, -+ const char *value) -+{ -+ freeanychunk(*(entry->chunk)); -+ *(entry->chunk) = decode_hex_to_chunk(entry->key, value); -+} -+ -+void symkey(struct cavp_entry *entry, -+ const char *value) -+{ -+ free_any_symkey(__func__, entry->symkey); -+ chunk_t chunk = decode_hex_to_chunk(entry->key, value); -+ *(entry->symkey) = chunk_to_key(CKM_DH_PKCS_DERIVE, chunk); -+ freeanychunk(chunk); -+} -+ -+void number(struct cavp_entry *entry, -+ const char *value) -+{ -+ *(entry->number) = atoi(value); -+} -+ -+void ignore(struct cavp_entry *entry UNUSED, -+ const char *value UNUSED) -+{ -+} -+ -+static void cavp_parser() -+{ -+ char line[BUF_SIZE]; -+ while (TRUE) { -+ if (fgets(line, sizeof(line), stdin) == NULL) { -+ int error = ferror(stdin); -+ if (error) { -+ fprintf(stderr, "Unexpected error: %s\n", -+ strerror(error)); -+ exit(1); -+ } -+ break; -+ } -+ /* trim trailing cr/nl. */ -+ int last = strlen(line) - 1; -+ while (last >= 0 && strchr("\r\n", line[last]) != NULL) { -+ last--; -+ } -+ line[last + 1] = '\0'; -+ /* break the line up */ -+ char *lparen = strchr(line, '['); -+ char *eq = strchr(line, '='); -+ char *rparen = strchr(line, ']'); -+ if (line[0] == '\0') { -+ next_state(BLANK); -+ /* blank */ -+ print_line(line); -+ } else if (line[0] == '#') { -+ /* # .... comment */ -+ if (cavp == NULL) { -+ struct cavp **cavpp; -+ for (cavpp = cavps; *cavpp != NULL; cavpp++) { -+ if (strstr(line, (*cavpp)->description) != NULL) { -+ cavp = *cavpp; -+ fprintf(stderr, "\ntest: %s (guess)\n\n", cavp->description); -+ break; -+ } -+ } -+ } -+ print_line(line); -+ } else if (lparen != NULL && rparen != NULL) { -+ next_state(CONFIG); -+ /* "[" [ " = " ] "]" */ -+ *rparen = '\0'; -+ char *key = lparen + 1; -+ char *value; -+ if (eq == NULL) { -+ value = NULL; -+ } else { -+ value = eq + 2; -+ *(eq - 1) = '\0'; -+ } -+ struct cavp_entry *entry = lookup_entry(cavp->config, key); -+ if (entry == NULL) { -+ fprintf(stderr, "unknown config entry: ['%s' = '%s']\n", key, value); -+ exit(1); -+ } -+ entry->op(entry, value); -+ } else if (eq != NULL) { -+ next_state(DATA); -+ *(eq - 1) = '\0'; -+ char *key = line; -+ char *value = eq + 2; -+ struct cavp_entry *entry = lookup_entry(cavp->data, key); -+ if (entry == NULL) { -+ fprintf(stderr, "unknown data entry: '%s' = '%s'\n", key, value); -+ exit(1); -+ } -+ entry->op(entry, value); -+ } else { -+ fprintf(stderr, "bad line: '%s'\n", line); -+ } -+ } -+} -+ -+static void usage() -+{ -+ fprintf(stderr, "Usage: cavp [ -OPTION ] |-\n"); -+ struct cavp **cavpp; -+ for (cavpp = cavps; *cavpp != NULL; cavpp++) { -+ fprintf(stderr, "\t-%s\t%s\n", (*cavpp)->alias, (*cavpp)->description); -+ } -+} -+ -+int main(int argc, char *argv[]) -+{ -+ if (argc <= 1) { -+ usage(); -+ exit(1); -+ } -+ char **argp = argv + 1; -+ -+ /* a -XXX option? */ -+ if ((*argp)[0] == '-' && (*argp)[1] != '\0') { -+ struct cavp **cavpp; -+ for (cavpp = cavps; *cavpp != NULL; cavpp++) { -+ if (strcmp(argv[1]+1, (*cavpp)->alias) == 0) { -+ cavp = *cavpp; -+ fprintf(stderr, "test: %s\n", cavp->description); -+ break; -+ } -+ } -+ if (cavp == NULL) { -+ fprintf(stderr, "Unknown test %s\n", argv[1]); -+ usage(); -+ exit(1); -+ } -+ argp++; -+ } else { -+ fprintf(stderr, "Guessing test type ...\n"); -+ } -+ -+ if (*argp == NULL) { -+ fprintf(stderr, "missing test file\n"); -+ usage(); -+ exit(1); -+ } -+ if (strcmp(*argp, "-") == 0) { -+ fprintf(stderr, "Reading from stdin\n"); -+ } else { -+ fprintf(stderr, "reading from %s\n", *argp); -+ if (freopen(*argp, "r", stdin) == NULL) { -+ perror("freopen"); -+ exit(1); -+ } -+ } -+ argp++; -+ -+ if (*argp != NULL) { -+ fprintf(stderr, "unexpected %s", *argp); -+ usage(); -+ exit(1); -+ } -+ -+ setbuf(stdout, NULL); -+ -+ NSS_NoDB_Init("."); -+ init_crypto(); -+ -+ cavp_parser(); -+ -+ NSS_Shutdown(); -+ return 0; -+} -diff -Naur libreswan-3.12-orig/programs/pluto/cavp.h libreswan-3.12/programs/pluto/cavp.h ---- libreswan-3.12-orig/programs/pluto/cavp.h 1969-12-31 19:00:00.000000000 -0500 -+++ libreswan-3.12/programs/pluto/cavp.h 2015-05-06 11:45:32.912301324 -0400 -@@ -0,0 +1,45 @@ -+/* -+ * Parse CAVP test vectors, for libreswan -+ * -+ * Copyright (C) 2015 Andrew Cagney -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * for more details. -+ */ -+ -+struct hash_desc; -+ -+struct cavp_entry { -+ const char *key; -+ void (*op)(struct cavp_entry *key, const char *value); -+ chunk_t *chunk; -+ PK11SymKey **symkey; -+ int *number; -+ struct hash_desc **hasher; -+ int value; -+}; -+ -+struct cavp { -+ const char *alias; -+ const char *description; -+ void (*print_config)(void); -+ void (*run)(void); -+ struct cavp_entry *config; -+ struct cavp_entry *data; -+}; -+ -+extern struct hash_desc *hasher; -+extern char hasher_name[]; -+void hash(struct cavp_entry *entry, const char *value); -+ -+void ignore(struct cavp_entry *entry, const char *value); -+void chunk(struct cavp_entry *entry, const char *value); -+void symkey(struct cavp_entry *entry, const char *value); -+void number(struct cavp_entry *entry, const char *value); -diff -Naur libreswan-3.12-orig/programs/pluto/cavp_ikev1.c libreswan-3.12/programs/pluto/cavp_ikev1.c ---- libreswan-3.12-orig/programs/pluto/cavp_ikev1.c 1969-12-31 19:00:00.000000000 -0500 -+++ libreswan-3.12/programs/pluto/cavp_ikev1.c 2015-05-06 11:45:32.913301336 -0400 -@@ -0,0 +1,174 @@ -+/* -+ * Parse IKEv1 CAVP test functions, for libreswan -+ * -+ * Copyright (C) 2015 Andrew Cagney -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * for more details. -+ */ -+ -+#include -+ -+#include "lswalloc.h" -+#include "ike_alg.h" -+ -+#include "ikev1_prf.h" -+#include "crypt_symkey.h" -+ -+#include "cavp.h" -+#include "cavp_print.h" -+#include "cavp_ikev1.h" -+ -+static int ni_length; -+static int nr_length; -+static int psk_length; -+static int g_xy_length; -+ -+static struct cavp_entry config_entries[] = { -+ { .key = "SHA-1", .op = hash, .value = OAKLEY_SHA1, }, -+ { .key = "SHA-224", .op = hash, .value = 0, }, -+ { .key = "SHA-256", .op = hash, .value = OAKLEY_SHA2_256, }, -+ { .key = "SHA-384", .op = hash, .value = OAKLEY_SHA2_384, }, -+ { .key = "SHA-512", .op = hash, .value = OAKLEY_SHA2_512, }, -+ { .key = "Ni length", .op = number, .number = &ni_length }, -+ { .key = "Nr length", .op = number, .number = &nr_length }, -+ { .key = "pre-shared-key length", .op = number, .number = &psk_length }, -+ { .key = "g^xy length", .op = number, .number = &g_xy_length }, -+ { .key = NULL } -+}; -+ -+static int count; -+static chunk_t psk; -+static chunk_t ni; -+static chunk_t nr; -+static chunk_t cky_i; -+static chunk_t cky_r; -+static PK11SymKey *g_xy; -+ -+static struct cavp_entry data_entries[] = { -+ { .key = "COUNT", .op = number, .number = &count }, -+ { .key = "g^xy", .op = symkey, .symkey = &g_xy }, -+ { .key = "Ni", .op = chunk, .chunk = &ni }, -+ { .key = "Nr", .op = chunk, .chunk = &nr }, -+ { .key = "CKY_I", .op = chunk, .chunk = &cky_i }, -+ { .key = "CKY_R", .op = chunk, .chunk = &cky_r }, -+ { .key = "pre-shared-key", .op = chunk, .chunk = &psk }, -+ { .key = "SKEYID", .op = ignore }, -+ { .key = "SKEYID_d", .op = ignore }, -+ { .key = "SKEYID_a", .op = ignore }, -+ { .key = "SKEYID_e", .op = ignore }, -+ { .key = "SKEYID_", .op = ignore }, -+ { .op = NULL } -+}; -+ -+static void ikev1_skeyid_alphabet(PK11SymKey *skeyid) -+{ -+ PK11SymKey *skeyid_d = -+ ikev1_skeyid_d(hasher, skeyid, -+ g_xy, cky_i, cky_r); -+ print_symkey("SKEYID_d", skeyid_d, 0); -+ -+ PK11SymKey *skeyid_a = -+ ikev1_skeyid_a(hasher, skeyid, skeyid_d, -+ g_xy, cky_i, cky_r); -+ print_symkey("SKEYID_a", skeyid_a, 0); -+ -+ PK11SymKey *skeyid_e = -+ ikev1_skeyid_e(hasher, skeyid, skeyid_a, -+ g_xy, cky_i, cky_r); -+ print_symkey("SKEYID_e", skeyid_e, 0); -+ -+ free_any_symkey("skeyid_d", &skeyid_d); -+ free_any_symkey("skeyid_e", &skeyid_e); -+ free_any_symkey("skeyid_a", &skeyid_a); -+} -+ -+static void print_sig_config() -+{ -+ config_number("g^xy length", g_xy_length); -+ config_key(hasher_name); -+ config_number("Ni length", ni_length); -+ config_number("Nr length", nr_length); -+} -+ -+static void run_sig(void) -+{ -+ print_number("COUNT", count); -+ print_chunk("CKY_I", cky_i, 0); -+ print_chunk("CKY_R", cky_r, 0); -+ print_chunk("Ni", ni, 0); -+ print_chunk("Nr", nr, 0); -+ print_symkey("g^xy", g_xy, 0); -+ -+ if (hasher == NULL) { -+ print_line(hasher_name); -+ return; -+ } -+ -+ PK11SymKey *skeyid = -+ ikev1_signature_skeyid(hasher, -+ ni, nr, -+ g_xy); -+ print_symkey("SKEYID", skeyid, 0); -+ ikev1_skeyid_alphabet(skeyid); -+ free_any_symkey("skeyid", &skeyid); -+} -+ -+struct cavp cavp_ikev1_sig = { -+ .alias = "v1sig", -+ .description = "IKE v1 Digital Signature Authentication", -+ .print_config = print_sig_config, -+ .run = run_sig, -+ .config = config_entries, -+ .data = data_entries, -+}; -+ -+static void print_psk_config(void) -+{ -+ config_number("g^xy length", g_xy_length); -+ config_key(hasher_name); -+ config_number("Ni length", ni_length); -+ config_number("Nr length", nr_length); -+ config_number("pre-shared-key length", psk_length); -+} -+ -+static void run_psk(void) -+{ -+ print_number("COUNT", count); -+ print_chunk("CKY_I", cky_i, 0); -+ print_chunk("CKY_R", cky_r, 0); -+ print_chunk("Ni", ni, 0); -+ print_chunk("Nr", nr, 0); -+ print_symkey("g^xy", g_xy, 0); -+ print_chunk("pre-shared-key", psk, 0); -+ -+ if (hasher == NULL) { -+ print_line(hasher_name); -+ return; -+ } -+ -+ PK11SymKey *skeyid = -+ ikev1_pre_shared_key_skeyid(hasher, -+ psk, -+ ni, nr, -+ g_xy); -+ print_symkey("SKEYID", skeyid, 0); -+ ikev1_skeyid_alphabet(skeyid); -+ free_any_symkey("skeyid", &skeyid); -+} -+ -+struct cavp cavp_ikev1_psk = { -+ .alias = "v1psk", -+ .description = "IKE v1 Pre-shared Key Authentication", -+ .print_config = print_psk_config, -+ .run = run_psk, -+ .config = config_entries, -+ .data = data_entries, -+}; -diff -Naur libreswan-3.12-orig/programs/pluto/cavp_ikev1.h libreswan-3.12/programs/pluto/cavp_ikev1.h ---- libreswan-3.12-orig/programs/pluto/cavp_ikev1.h 1969-12-31 19:00:00.000000000 -0500 -+++ libreswan-3.12/programs/pluto/cavp_ikev1.h 2015-05-06 11:45:32.913301336 -0400 -@@ -0,0 +1,18 @@ -+/* -+ * Parse IKEv1 CAVP test functions, for libreswan -+ * -+ * Copyright (C) 2015 Andrew Cagney -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * for more details. -+ */ -+ -+struct cavp cavp_ikev1_sig; -+struct cavp cavp_ikev1_psk; -diff -Naur libreswan-3.12-orig/programs/pluto/cavp_ikev2.c libreswan-3.12/programs/pluto/cavp_ikev2.c ---- libreswan-3.12-orig/programs/pluto/cavp_ikev2.c 1969-12-31 19:00:00.000000000 -0500 -+++ libreswan-3.12/programs/pluto/cavp_ikev2.c 2015-05-06 11:45:32.913301336 -0400 -@@ -0,0 +1,141 @@ -+/* -+ * Parse IKEv1 CAVP test functions, for libreswan -+ * -+ * Copyright (C) 2015 Andrew Cagney -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * for more details. -+ */ -+ -+#include -+ -+#include "lswalloc.h" -+#include "ike_alg.h" -+ -+#include "crypt_symkey.h" -+#include "ikev2_prf.h" -+ -+#include "cavp.h" -+#include "cavp_print.h" -+#include "cavp_ikev2.h" -+ -+static int g_ir_length; -+static int ni_length; -+static int nr_length; -+static int dkm_length; -+static int child_sa_dkm_length; -+ -+static struct cavp_entry config_entries[] = { -+ { .key = "g^ir length", .op = number, .number = &g_ir_length }, -+ { .key = "SHA-1", .op = hash, .value = OAKLEY_SHA1, }, -+ { .key = "SHA-224", .op = hash, .value = 0, }, -+ { .key = "SHA-256", .op = hash, .value = OAKLEY_SHA2_256, }, -+ { .key = "SHA-384", .op = hash, .value = OAKLEY_SHA2_384, }, -+ { .key = "SHA-512", .op = hash, .value = OAKLEY_SHA2_512, }, -+ { .key = "Ni length", .op = number, .number = &ni_length }, -+ { .key = "Nr length", .op = number, .number = &nr_length }, -+ { .key = "DKM length", .op = number, .number = &dkm_length }, -+ { .key = "Child SA DKM length", .op = number, .number = &child_sa_dkm_length }, -+ { .key = NULL } -+}; -+ -+static void ikev2_config() -+{ -+ config_number("g^ir length", g_ir_length); -+ config_key(hasher_name); -+ config_number("Ni length",ni_length); -+ config_number("Nr length",nr_length); -+ config_number("DKM length",dkm_length); -+ config_number("Child SA DKM length",child_sa_dkm_length); -+} -+ -+static int count; -+static chunk_t ni; -+static chunk_t nr; -+static PK11SymKey *g_ir; -+static PK11SymKey *g_ir_new; -+static chunk_t spi_i; -+static chunk_t spi_r; -+ -+static struct cavp_entry data_entries[] = { -+ { .key = "COUNT", .op = number, .number = &count }, -+ { .key = "g^ir", .op = symkey, .symkey = &g_ir }, -+ { .key = "g^ir (new)", .op = symkey, .symkey = &g_ir_new }, -+ { .key = "Ni", .op = chunk, .chunk = &ni }, -+ { .key = "Nr", .op = chunk, .chunk = &nr }, -+ { .key = "SPIi", .op = chunk, .chunk = &spi_i }, -+ { .key = "SPIr", .op = chunk, .chunk = &spi_r }, -+ { .key = "SKEYSEED", .op = ignore }, -+ { .key = "DKM", .op = ignore }, -+ { .key = "DKM(Child SA)", .op = ignore }, -+ { .key = "DKM(Child SA D-H)", .op = ignore }, -+ { .key = "SKEYSEED(Rekey)", .op = ignore }, -+ { .op = NULL } -+}; -+ -+static void run_ikev2(void) -+{ -+ print_number("COUNT", count); -+ print_chunk("Ni", ni, 0); -+ print_chunk("Nr", nr, 0); -+ print_symkey("g^ir", g_ir, 0); -+ print_symkey("g^ir (new)", g_ir_new, 0); -+ print_chunk("SPIi", spi_i, 0); -+ print_chunk("SPIr", spi_r, 0); -+ -+ if (hasher == NULL) { -+ print_line(hasher_name); -+ return; -+ } -+ -+ /* SKEYSEED = prf(Ni | Nr, g^ir) */ -+ PK11SymKey *skeyseed = -+ ikev2_ike_sa_skeyseed(hasher, ni, nr, g_ir); -+ print_symkey("SKEYSEED", skeyseed, 0); -+ -+ /* prf+(SKEYSEED, Ni | Nr | SPIi | SPIr) */ -+ PK11SymKey *dkm = -+ ikev2_ike_sa_keymat(hasher, skeyseed, -+ ni, nr, spi_i, spi_r, dkm_length / 8); -+ print_symkey("DKM", dkm, dkm_length / 8); -+ -+ /* prf+(SK_d, Ni | Nr) */ -+ PK11SymKey *SK_d = key_from_symkey_bytes(dkm, 0, hasher->hash_digest_len); -+ PK11SymKey *child_sa_dkm = -+ ikev2_child_sa_keymat(hasher, SK_d, NULL, ni, nr, child_sa_dkm_length / 8); -+ print_symkey("DKM(Child SA)", child_sa_dkm, child_sa_dkm_length / 8); -+ -+ /* prf+(SK_d, g^ir (new) | Ni | Nr) */ -+ PK11SymKey *child_sa_dkm_dh = -+ ikev2_child_sa_keymat(hasher, SK_d, g_ir_new, ni, nr, -+ child_sa_dkm_length / 8); -+ print_symkey("DKM(Child SA D-H)", child_sa_dkm_dh, child_sa_dkm_length / 8); -+ -+ /* prf(SK_d (old), g^ir (new) | Ni | Nr) */ -+ PK11SymKey *skeyseed_rekey = -+ ikev2_ike_sa_rekey_skeyseed(hasher, SK_d, g_ir_new, ni, nr); -+ print_symkey("SKEYSEED(Rekey)", skeyseed_rekey, 0); -+ -+ free_any_symkey("skeyseed", &skeyseed); -+ free_any_symkey("dkm", &dkm); -+ free_any_symkey("SK_d", &SK_d); -+ free_any_symkey("child_sa_dkm", &child_sa_dkm); -+ free_any_symkey("child_sa_dkm_dh", &child_sa_dkm_dh); -+ free_any_symkey("skeyseed_rekey", &skeyseed_rekey); -+} -+ -+struct cavp cavp_ikev2 = { -+ .alias = "v2", -+ .description = "IKE v2", -+ .print_config = ikev2_config, -+ .run = run_ikev2, -+ .config = config_entries, -+ .data = data_entries, -+}; -diff -Naur libreswan-3.12-orig/programs/pluto/cavp_ikev2.h libreswan-3.12/programs/pluto/cavp_ikev2.h ---- libreswan-3.12-orig/programs/pluto/cavp_ikev2.h 1969-12-31 19:00:00.000000000 -0500 -+++ libreswan-3.12/programs/pluto/cavp_ikev2.h 2015-05-06 11:45:32.914301347 -0400 -@@ -0,0 +1,17 @@ -+/* -+ * Parse IKEv1 CAVP test functions, for libreswan -+ * -+ * Copyright (C) 2015 Andrew Cagney -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * for more details. -+ */ -+ -+struct cavp cavp_ikev2; -diff -Naur libreswan-3.12-orig/programs/pluto/cavp_print.c libreswan-3.12/programs/pluto/cavp_print.c ---- libreswan-3.12-orig/programs/pluto/cavp_print.c 1969-12-31 19:00:00.000000000 -0500 -+++ libreswan-3.12/programs/pluto/cavp_print.c 2015-05-06 11:45:32.914301347 -0400 -@@ -0,0 +1,73 @@ -+/* -+ * Parse CAVP test vectors, for libreswan -+ * -+ * Copyright (C) 2015 Andrew Cagney -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * for more details. -+ */ -+ -+#include -+#include -+ -+#include "constants.h" -+#include "lswalloc.h" -+#include "crypt_symkey.h" -+#include "cavp_print.h" -+ -+/* -+ * The test vectors are CR-LF terminated, mimic this. -+ */ -+static const char crlf[] = "\r\n"; -+ -+void config_key(const char *key) -+{ -+ fputs("[", stdout); -+ fputs(key, stdout); -+ fputs("]", stdout); -+ fputs(crlf, stdout); -+} -+ -+void config_number(const char *key, int number) -+{ -+ printf("[%s = %d]%s", key, number, crlf); -+} -+ -+void print_chunk(const char *prefix, chunk_t chunk, size_t binlen) -+{ -+ printf("%s = ", prefix); -+ size_t len = binlen == 0 ? chunk.len -+ : binlen < chunk.len ? binlen -+ : chunk.len; -+ -+ size_t i = 0; -+ for (i = 0; i < len; i++) { -+ printf("%02x", chunk.ptr[i]); -+ } -+ printf("%s", crlf); -+} -+ -+void print_symkey(const char *prefix, PK11SymKey *key, size_t binlen) -+{ -+ chunk_t chunk = chunk_from_symkey(prefix, key); -+ print_chunk(prefix, chunk, binlen); -+ freeanychunk(chunk); -+} -+ -+void print_number(const char *prefix, int number) -+{ -+ printf("%s = %d%s", prefix, number, crlf); -+} -+ -+void print_line(const char *line) -+{ -+ fputs(line, stdout); -+ fputs(crlf, stdout); -+} -diff -Naur libreswan-3.12-orig/programs/pluto/cavp_print.h libreswan-3.12/programs/pluto/cavp_print.h ---- libreswan-3.12-orig/programs/pluto/cavp_print.h 1969-12-31 19:00:00.000000000 -0500 -+++ libreswan-3.12/programs/pluto/cavp_print.h 2015-05-06 11:45:32.914301347 -0400 -@@ -0,0 +1,23 @@ -+/* -+ * Parse CAVP test vectors, for libreswan -+ * -+ * Copyright (C) 2015 Andrew Cagney -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * for more details. -+ */ -+ -+void config_number(const char *prefix, int number); -+void config_key(const char *key); -+ -+void print_chunk(const char *prefix, chunk_t chunk, size_t binlen); -+void print_symkey(const char *prefix, PK11SymKey *key, size_t binlen); -+void print_number(const char *prefix, int number); -+void print_line(const char *line); -diff -Naur libreswan-3.12-orig/programs/pluto/cavp_stubs.c libreswan-3.12/programs/pluto/cavp_stubs.c ---- libreswan-3.12-orig/programs/pluto/cavp_stubs.c 1969-12-31 19:00:00.000000000 -0500 -+++ libreswan-3.12/programs/pluto/cavp_stubs.c 2015-05-06 11:45:32.915301359 -0400 -@@ -0,0 +1,21 @@ -+#include -+ -+#include "constants.h" -+#include "libreswan/passert.h" -+ -+/* -+ * Crud to get main to link. -+ */ -+libreswan_passert_fail_t libreswan_passert_fail; -+enum kernel_interface kern_interface; -+extern void exit_pluto(int status); -+void exit_pluto(int status UNUSED) { } -+extern void show_setup_plutomain(); -+void show_setup_plutomain() { } -+extern char *pluto_listen; -+char *pluto_listen = NULL; -+u_int16_t secctx_attr_type = 0; -+u_int16_t secctx_attr_value = 0; -+bool force_busy = FALSE; -+bool strict_crl_policy = FALSE; -+deltatime_t crl_check_interval = { 0 }; -diff -Naur libreswan-3.12-orig/programs/pluto/cbc_test_vectors.c libreswan-3.12/programs/pluto/cbc_test_vectors.c ---- libreswan-3.12-orig/programs/pluto/cbc_test_vectors.c 2015-05-06 11:44:21.562466284 -0400 -+++ libreswan-3.12/programs/pluto/cbc_test_vectors.c 2015-05-06 11:45:32.915301359 -0400 -@@ -13,6 +13,7 @@ - - #include "nss.h" - #include "pk11pub.h" -+#include "crypt_symkey.h" - - struct cbc_test_vector { - const char *description; -@@ -183,7 +184,7 @@ - } - - /* Clean up. */ -- PK11_FreeSymKey(sym_key); -+ free_any_symkey("sym_key", &sym_key); - - DBG(DBG_CRYPT, DBG_log("test_ctr_vector: %s %s", - test->description, ok ? "passed" : "failed")); -diff -Naur libreswan-3.12-orig/programs/pluto/crypt_dh.c libreswan-3.12/programs/pluto/crypt_dh.c ---- libreswan-3.12-orig/programs/pluto/crypt_dh.c 2015-05-06 11:44:21.583466531 -0400 -+++ libreswan-3.12/programs/pluto/crypt_dh.c 2015-05-06 11:45:32.917301382 -0400 -@@ -57,90 +57,20 @@ - #include "id.h" - #include "secrets.h" - #include "keys.h" --#include "ikev2_prfplus.h" -+#include "crypt_dh.h" -+#include "crypt_symkey.h" - - #include - #include - #include - #include "lswconf.h" - --/* #define PK11_Derive(base, mechanism, param, target, operation, keysize) \ -- * PK11_Derive_lsw(base, mechanism, param, target, operation, keysize) -- */ -- --/* MUST BE THREAD-SAFE */ --static PK11SymKey *pk11_extract_derive_wrapper_lsw(PK11SymKey *base, -- CK_EXTRACT_PARAMS bs, -- CK_MECHANISM_TYPE target, -- CK_ATTRIBUTE_TYPE operation, -- int keySize) --{ -- SECItem param; -- -- param.data = (unsigned char*)&bs; -- param.len = sizeof(bs); -- -- return PK11_Derive_lsw(base, CKM_EXTRACT_KEY_FROM_KEY, ¶m, target, -- operation, keySize); --} -- --static CK_MECHANISM_TYPE nss_encryption_mech( -- const struct encrypt_desc *encrypter) --{ -- /* the best wey have for "undefined" */ -- CK_MECHANISM_TYPE mechanism = CKM_VENDOR_DEFINED; -- -- switch (encrypter->common.algo_id) { -- case OAKLEY_3DES_CBC: -- mechanism = CKM_DES3_CBC; -- break; --#ifdef NOT_YET -- case OAKLEY_CAST_CBC: -- mechanism = CKM_CAST5_CBC: -- break; --#endif -- case OAKLEY_AES_CBC: -- mechanism = CKM_AES_CBC; -- break; -- case OAKLEY_CAMELLIA_CBC: -- mechanism = CKM_CAMELLIA_CBC; -- break; -- case OAKLEY_AES_CTR: -- mechanism = CKM_AES_CTR; -- break; --#ifdef NOT_YET -- case OAKLEY_AES_CCM_8: -- case OAKLEY_AES_CCM_12: -- case OAKLEY_AES_CCM_16: -- mechanism = CKM_AES_CCM; -- break; --#endif -- case OAKLEY_AES_GCM_8: -- case OAKLEY_AES_GCM_12: -- case OAKLEY_AES_GCM_16: -- mechanism = CKM_AES_GCM; -- break; --#ifdef NOT_YET -- case OAKLEY_TWOFISH_CBC: -- mechanism = CKM_TWOFISH_CBC; -- break; --#endif -- default: -- loglog(RC_LOG_SERIOUS, -- "NSS: Unsupported encryption mechanism for %s", -- strip_prefix(enum_name(&oakley_enc_names, -- encrypter->common.algo_id), "OAKLEY_")); -- break; -- } -- return mechanism; --} -- - /** Compute DH shared secret from our local secret and the peer's public value. - * We make the leap that the length should be that of the group - * (see quoted passage at start of ACCEPT_KE). - */ - /* MUST BE THREAD-SAFE */ --static PK11SymKey *calc_dh_shared(const chunk_t g, /* converted to SECItem */ -+PK11SymKey *calc_dh_shared(const chunk_t g, /* converted to SECItem */ - /*const*/ SECKEYPrivateKey *privk, /* NSS doesn't do const */ - const struct oakley_group_desc *group, - const SECKEYPublicKey *local_pubk) -@@ -214,7 +144,7 @@ - CKM_CONCATENATE_DATA_AND_BASE, - CKA_DERIVE, 0); - passert(newdhshared != NULL); -- PK11_FreeSymKey(dhshared); -+ free_any_symkey("dhshared", &dhshared); - dhshared = newdhshared; - freeanychunk(zeros); - } else { -@@ -240,862 +170,6 @@ - return dhshared; - } - --/* SKEYID for preshared keys. -- * See draft-ietf-ipsec-ike-01.txt 4.1 -- */ -- --static PK11SymKey *skeyid_preshared(const chunk_t pss, -- const chunk_t ni, -- const chunk_t nr, -- PK11SymKey *shared, -- const struct hash_desc *hasher) --{ -- struct hmac_ctx ctx; -- -- passert(hasher != NULL); -- -- chunk_t nir; -- unsigned int k; -- CK_MECHANISM_TYPE mechanism; -- u_char buf1[HMAC_BUFSIZE * 2], buf2[HMAC_BUFSIZE * 2]; -- chunk_t buf1_chunk, buf2_chunk; -- PK11SymKey *skeyid; -- -- DBG(DBG_CRYPT, { -- DBG_log("NSS: skeyid inputs (pss+NI+NR+shared-secret) hasher: %s", -- hasher->common.name); -- DBG_log("shared-secret (pointer in chunk_t): %p", shared); -- DBG_dump_chunk("ni: ", ni); -- DBG_dump_chunk("nr: ", nr); -- }); -- -- /* We need to hmac_init with the concatenation of Ni_b and Nr_b, -- * so we have to build a temporary concatentation. -- */ -- -- nir.len = ni.len + nr.len; -- nir.ptr = alloc_bytes(nir.len, "Ni + Nr in skeyid_preshared"); -- memcpy(nir.ptr, ni.ptr, ni.len); -- memcpy(nir.ptr + ni.len, nr.ptr, nr.len); -- -- zero(&buf1); -- -- if (pss.len <= hasher->hash_block_size) { -- memcpy(buf1, pss.ptr, pss.len); -- } else { -- hasher->hash_init(&ctx.hash_ctx); -- hasher->hash_update(&ctx.hash_ctx, pss.ptr, pss.len); -- hasher->hash_final(buf1, &ctx.hash_ctx); -- } -- -- memcpy(buf2, buf1, hasher->hash_block_size); -- -- for (k = 0; k < hasher->hash_block_size; k++) { -- buf1[k] ^= HMAC_IPAD; -- buf2[k] ^= HMAC_OPAD; -- } -- -- /* pfree(nir.ptr); */ -- -- mechanism = nss_key_derivation_mech(hasher); -- buf1_chunk.ptr = buf1; -- buf1_chunk.len = hasher->hash_block_size; -- -- buf2_chunk.ptr = buf2; -- buf2_chunk.len = hasher->hash_block_size; -- -- PK11SymKey *tkey4 = pk11_derive_wrapper_lsw(shared, -- CKM_CONCATENATE_DATA_AND_BASE, buf1_chunk, CKM_EXTRACT_KEY_FROM_KEY, CKA_DERIVE, -- 0); -- /* nss_symkey_log(tkey4, "pss+ipad+shared"); */ -- -- CK_EXTRACT_PARAMS bs = 0; -- PK11SymKey *tkey5 = pk11_extract_derive_wrapper_lsw(tkey4, bs, -- CKM_CONCATENATE_BASE_AND_DATA, CKA_DERIVE, -- hasher->hash_block_size); -- /* nss_symkey_log(tkey5, "pss+ipad"); */ -- -- PK11SymKey *tkey6 = pk11_derive_wrapper_lsw(tkey5, -- CKM_CONCATENATE_BASE_AND_DATA, nir, mechanism, CKA_DERIVE, -- 0); -- pfree(nir.ptr); -- /* nss_symkey_log(tkey6, "pss+ipad+nir"); */ -- -- /* PK11SymKey *tkey1 = pk11_derive_wrapper_lsw(shared, CKM_CONCATENATE_DATA_AND_BASE, buf1_chunk, mechanism, CKA_DERIVE, 0); */ -- PK11SymKey *tkey2 = PK11_Derive_lsw(tkey6, mechanism, NULL, -- CKM_CONCATENATE_DATA_AND_BASE, -- CKA_DERIVE, 0); -- /* nss_symkey_log(tkey2, "pss : tkey2"); */ -- -- PK11SymKey *tkey3 = pk11_derive_wrapper_lsw(tkey2, -- CKM_CONCATENATE_DATA_AND_BASE, buf2_chunk, mechanism, CKA_DERIVE, -- 0); -- skeyid = PK11_Derive_lsw(tkey3, mechanism, NULL, -- CKM_CONCATENATE_BASE_AND_DATA, CKA_DERIVE, 0); -- /* nss_symkey_log(tkey2, "pss : tkey3"); */ -- -- PK11_FreeSymKey(tkey4); -- PK11_FreeSymKey(tkey5); -- PK11_FreeSymKey(tkey6); -- PK11_FreeSymKey(tkey2); -- PK11_FreeSymKey(tkey3); -- -- DBG(DBG_CRYPT, -- DBG_log("NSS: skeyid in skeyid_preshared() (pointer) %p: ", -- skeyid)); -- return skeyid; --} -- --/* MUST BE THREAD-SAFE */ --static PK11SymKey *skeyid_digisig(const chunk_t ni, -- const chunk_t nr, -- /*const*/ PK11SymKey *shared, /* NSS doesn't do const */ -- const struct hash_desc *hasher) --{ -- struct hmac_ctx ctx; -- chunk_t nir; -- unsigned int k; -- CK_MECHANISM_TYPE mechanism; -- u_char buf1[HMAC_BUFSIZE * 2], buf2[HMAC_BUFSIZE * 2]; -- chunk_t buf1_chunk, buf2_chunk; -- PK11SymKey *skeyid; -- -- DBG(DBG_CRYPT, { -- DBG_log("skeyid inputs (digi+NI+NR+shared) hasher: %s", -- hasher->common.name); -- DBG_dump_chunk("ni: ", ni); -- DBG_dump_chunk("nr: ", nr); -- }); -- -- /* We need to hmac_init with the concatenation of Ni_b and Nr_b, -- * so we have to build a temporary concatentation. -- */ -- nir.len = ni.len + nr.len; -- nir.ptr = alloc_bytes(nir.len, "Ni + Nr in skeyid_digisig"); -- memcpy(nir.ptr, ni.ptr, ni.len); -- memcpy(nir.ptr + ni.len, nr.ptr, nr.len); -- zero(&buf1); -- if (nir.len <= hasher->hash_block_size) { -- memcpy(buf1, nir.ptr, nir.len); -- } else { -- hasher->hash_init(&ctx.hash_ctx); -- hasher->hash_update(&ctx.hash_ctx, nir.ptr, nir.len); -- hasher->hash_final(buf1, &ctx.hash_ctx); -- } -- -- memcpy(buf2, buf1, hasher->hash_block_size); -- -- for (k = 0; k < hasher->hash_block_size; k++) { -- buf1[k] ^= HMAC_IPAD; -- buf2[k] ^= HMAC_OPAD; -- } -- -- pfree(nir.ptr); -- mechanism = nss_key_derivation_mech(hasher); -- buf1_chunk.ptr = buf1; -- buf1_chunk.len = hasher->hash_block_size; -- -- buf2_chunk.ptr = buf2; -- buf2_chunk.len = hasher->hash_block_size; -- -- PK11SymKey *tkey1 = pk11_derive_wrapper_lsw(shared, -- CKM_CONCATENATE_DATA_AND_BASE, buf1_chunk, mechanism, CKA_DERIVE, -- 0); -- PK11SymKey *tkey2 = PK11_Derive_lsw(tkey1, mechanism, NULL, -- CKM_CONCATENATE_DATA_AND_BASE, -- CKA_DERIVE, 0); -- PK11SymKey *tkey3 = pk11_derive_wrapper_lsw(tkey2, -- CKM_CONCATENATE_DATA_AND_BASE, buf2_chunk, mechanism, CKA_DERIVE, -- 0); -- skeyid = PK11_Derive_lsw(tkey3, mechanism, NULL, -- CKM_CONCATENATE_BASE_AND_DATA, CKA_DERIVE, 0); -- -- PK11_FreeSymKey(tkey1); -- PK11_FreeSymKey(tkey2); -- PK11_FreeSymKey(tkey3); -- -- DBG(DBG_CRYPT, -- DBG_log("NSS: digisig skeyid pointer: %p", skeyid)); -- -- return skeyid; --} -- --/* Generate the SKEYID_* and new IV -- * See draft-ietf-ipsec-ike-01.txt 4.1 -- */ --/* MUST BE THREAD-SAFE */ --static void calc_skeyids_iv(struct pcr_skeyid_q *skq, -- /*const*/ PK11SymKey *shared, /* NSS doesn't do const */ -- const size_t keysize, /* = st->st_oakley.enckeylen/BITS_PER_BYTE; */ -- PK11SymKey **skeyid_out, /* output */ -- PK11SymKey **skeyid_d_out, /* output */ -- PK11SymKey **skeyid_a_out, /* output */ -- PK11SymKey **skeyid_e_out, /* output */ -- chunk_t *new_iv, /* output */ -- PK11SymKey **enc_key_out /* output */ -- ) --{ -- oakley_auth_t auth = skq->auth; -- oakley_hash_t hash = skq->prf_hash; -- const struct hash_desc *hasher = crypto_get_hasher(hash); -- chunk_t ni; -- chunk_t nr; -- chunk_t gi; -- chunk_t gr; -- chunk_t icookie; -- chunk_t rcookie; -- PK11SymKey -- *skeyid, -- *skeyid_d, -- *skeyid_a, -- *skeyid_e, -- *enc_key; -- const struct encrypt_desc *encrypter = skq->encrypter; -- -- /* this doesn't allocate any memory */ -- setchunk_from_wire(gi, skq, &skq->gi); -- setchunk_from_wire(gr, skq, &skq->gr); -- setchunk_from_wire(ni, skq, &skq->ni); -- setchunk_from_wire(nr, skq, &skq->nr); -- setchunk_from_wire(icookie, skq, &skq->icookie); -- setchunk_from_wire(rcookie, skq, &skq->rcookie); -- -- /* Generate the SKEYID */ -- switch (auth) { -- case OAKLEY_PRESHARED_KEY: -- { -- chunk_t pss; -- -- setchunk_from_wire(pss, skq, &skq->pss); -- skeyid = skeyid_preshared(pss, ni, nr, shared, hasher); -- } -- break; -- -- case OAKLEY_RSA_SIG: -- skeyid = skeyid_digisig(ni, nr, shared, hasher); -- break; -- -- /* Not implemented */ -- case OAKLEY_DSS_SIG: -- case OAKLEY_RSA_ENC: -- case OAKLEY_RSA_REVISED_MODE: -- case OAKLEY_ECDSA_P256: -- case OAKLEY_ECDSA_P384: -- case OAKLEY_ECDSA_P521: -- default: -- bad_case(auth); -- } -- -- /* generate SKEYID_* from SKEYID */ -- { -- -- chunk_t hmac_opad, hmac_ipad, hmac_pad, hmac_zerobyte, -- hmac_val1, hmac_val2; -- CK_OBJECT_HANDLE keyhandle; -- SECItem param, param1; -- -- hmac_opad = hmac_pads(HMAC_OPAD, hasher->hash_block_size); -- hmac_ipad = hmac_pads(HMAC_IPAD, hasher->hash_block_size); -- hmac_pad = hmac_pads(0x00, -- hasher->hash_block_size - -- hasher->hash_digest_len); -- hmac_zerobyte = hmac_pads(0x00, 1); -- hmac_val1 = hmac_pads(0x01, 1); -- hmac_val2 = hmac_pads(0x02, 1); -- -- DBG(DBG_CRYPT, DBG_log("NSS: Started key computation")); -- -- /*Deriving SKEYID_d = hmac_xxx(SKEYID, g^xy | CKY-I | CKY-R | 0) */ -- PK11SymKey *tkey1 = pk11_derive_wrapper_lsw(skeyid, -- CKM_CONCATENATE_BASE_AND_DATA, -- hmac_pad, -- CKM_XOR_BASE_AND_DATA, -- CKA_DERIVE, -- hasher->hash_block_size); -- -- passert(tkey1 != NULL); -- -- /*DBG(DBG_CRYPT, DBG_log("Started key computation: 1, length=%d", PK11_GetKeyLength(tkey1))); -- * nss_symkey_log(tkey1, "1"); -- */ -- -- PK11SymKey *tkey2 = pk11_derive_wrapper_lsw(tkey1, -- CKM_XOR_BASE_AND_DATA, -- hmac_ipad, -- CKM_CONCATENATE_BASE_AND_KEY, -- CKA_DERIVE, -- 0); -- -- passert(tkey2 != NULL); -- -- keyhandle = PK11_GetSymKeyHandle(shared); -- param.data = (unsigned char *) &keyhandle; -- param.len = sizeof(keyhandle); -- DBG(DBG_CRYPT, -- DBG_log("NSS: dh shared param len=%d", param.len)); -- -- PK11SymKey *tkey3 = PK11_Derive_lsw(tkey2, -- CKM_CONCATENATE_BASE_AND_KEY, -- ¶m, -- CKM_CONCATENATE_BASE_AND_DATA, -- CKA_DERIVE, -- 0); -- passert(tkey3 != NULL); -- -- PK11SymKey *tkey4 = pk11_derive_wrapper_lsw(tkey3, -- CKM_CONCATENATE_BASE_AND_DATA, -- icookie, -- CKM_CONCATENATE_BASE_AND_DATA, -- CKA_DERIVE, -- 0); -- passert(tkey4 != NULL); -- -- PK11SymKey *tkey5 = pk11_derive_wrapper_lsw(tkey4, -- CKM_CONCATENATE_BASE_AND_DATA, -- rcookie, -- CKM_CONCATENATE_BASE_AND_DATA, -- CKA_DERIVE, -- 0); -- -- passert(tkey5 != NULL); -- -- PK11SymKey *tkey6 = pk11_derive_wrapper_lsw(tkey5, -- CKM_CONCATENATE_BASE_AND_DATA, -- hmac_zerobyte, -- nss_key_derivation_mech(hasher), -- CKA_DERIVE, -- 0); -- -- passert(tkey6 != NULL); -- -- PK11SymKey *tkey7 = PK11_Derive_lsw(tkey6, -- nss_key_derivation_mech(hasher), -- NULL, -- CKM_CONCATENATE_BASE_AND_DATA, -- CKA_DERIVE, -- 0); -- passert(tkey7 != NULL); -- -- PK11SymKey *tkey8 = pk11_derive_wrapper_lsw(tkey1, -- CKM_XOR_BASE_AND_DATA, -- hmac_opad, -- CKM_CONCATENATE_BASE_AND_KEY, -- CKA_DERIVE, -- 0); -- passert(tkey8 != NULL); -- -- keyhandle = PK11_GetSymKeyHandle(tkey7); -- param.data = (unsigned char*)&keyhandle; -- param.len = sizeof(keyhandle); -- -- PK11SymKey *tkey9 = PK11_Derive_lsw(tkey8, -- CKM_CONCATENATE_BASE_AND_KEY, -- ¶m, -- nss_key_derivation_mech(hasher), -- CKA_DERIVE, -- 0); -- passert(tkey9 != NULL); -- -- skeyid_d = PK11_Derive_lsw(tkey9, -- nss_key_derivation_mech(hasher), -- NULL, -- CKM_CONCATENATE_BASE_AND_DATA, -- CKA_DERIVE, -- 0); -- passert(skeyid_d != NULL); -- /* nss_symkey_log(skeyid_d, "skeyid_d"); */ -- /*****End of SKEYID_d derivation***************************************/ -- -- /*Deriving SKEYID_a = hmac_xxx(SKEYID, SKEYID_d | g^xy | CKY-I | CKY-R | 1)*/ -- keyhandle = PK11_GetSymKeyHandle(skeyid_d); -- param.data = (unsigned char*)&keyhandle; -- param.len = sizeof(keyhandle); -- -- PK11SymKey *tkey10 = PK11_Derive_lsw(tkey2, -- CKM_CONCATENATE_BASE_AND_KEY, -- ¶m, -- CKM_CONCATENATE_BASE_AND_KEY, -- CKA_DERIVE, -- 0); -- passert(tkey10 != NULL); -- -- keyhandle = PK11_GetSymKeyHandle(shared); -- param.data = (unsigned char*)&keyhandle; -- param.len = sizeof(keyhandle); -- -- PK11SymKey *tkey11 = PK11_Derive_lsw(tkey10, -- CKM_CONCATENATE_BASE_AND_KEY, -- ¶m, -- CKM_CONCATENATE_BASE_AND_DATA, -- CKA_DERIVE, -- 0); -- passert(tkey11 != NULL); -- -- PK11SymKey *tkey12 = pk11_derive_wrapper_lsw(tkey11, -- CKM_CONCATENATE_BASE_AND_DATA, -- icookie, CKM_CONCATENATE_BASE_AND_DATA, CKA_DERIVE, -- 0); -- passert(tkey12 != NULL); -- -- PK11SymKey *tkey13 = pk11_derive_wrapper_lsw(tkey12, -- CKM_CONCATENATE_BASE_AND_DATA, -- rcookie, -- CKM_CONCATENATE_BASE_AND_DATA, -- CKA_DERIVE, -- 0); -- passert(tkey13 != NULL); -- -- PK11SymKey *tkey14 = pk11_derive_wrapper_lsw(tkey13, -- CKM_CONCATENATE_BASE_AND_DATA, -- hmac_val1, -- nss_key_derivation_mech(hasher), -- CKA_DERIVE, -- 0); -- passert(tkey14 != NULL); -- -- PK11SymKey *tkey15 = PK11_Derive_lsw(tkey14, -- nss_key_derivation_mech(hasher), -- NULL, -- CKM_CONCATENATE_BASE_AND_DATA, -- CKA_DERIVE, -- 0); -- passert(tkey15 != NULL); -- -- keyhandle = PK11_GetSymKeyHandle(tkey15); -- param.data = (unsigned char*)&keyhandle; -- param.len = sizeof(keyhandle); -- -- PK11SymKey *tkey16 = PK11_Derive_lsw(tkey8, -- CKM_CONCATENATE_BASE_AND_KEY, ¶m, -- nss_key_derivation_mech(hasher), -- CKA_DERIVE, -- 0); -- passert(tkey16 != NULL); -- -- skeyid_a = PK11_Derive_lsw(tkey16, -- nss_key_derivation_mech(hasher), -- NULL, -- CKM_CONCATENATE_BASE_AND_DATA, -- CKA_DERIVE, -- 0); -- passert(skeyid_a != NULL); -- /* nss_symkey_log(skeyid_a, "skeyid_a"); */ -- /*****End of SKEYID_a derivation***************************************/ -- -- /*Deriving SKEYID_e = prf(SKEYID, SKEYID_a | g^xy | CKY-I | CKY-R | 2)*/ -- keyhandle = PK11_GetSymKeyHandle(skeyid_a); -- param.data = (unsigned char*)&keyhandle; -- param.len = sizeof(keyhandle); -- -- PK11SymKey *tkey17 = PK11_Derive_lsw(tkey2, -- CKM_CONCATENATE_BASE_AND_KEY, ¶m, CKM_CONCATENATE_BASE_AND_KEY, CKA_DERIVE, -- 0); -- passert(tkey17 != NULL); -- -- keyhandle = PK11_GetSymKeyHandle(shared); -- param.data = (unsigned char*)&keyhandle; -- param.len = sizeof(keyhandle); -- -- PK11SymKey *tkey18 = PK11_Derive_lsw(tkey17, -- CKM_CONCATENATE_BASE_AND_KEY, ¶m, CKM_CONCATENATE_BASE_AND_DATA, CKA_DERIVE, -- 0); -- passert(tkey18 != NULL); -- -- PK11SymKey *tkey19 = pk11_derive_wrapper_lsw(tkey18, -- CKM_CONCATENATE_BASE_AND_DATA, -- icookie, CKM_CONCATENATE_BASE_AND_DATA, CKA_DERIVE, -- 0); -- passert(tkey19 != NULL); -- -- PK11SymKey *tkey20 = pk11_derive_wrapper_lsw(tkey19, -- CKM_CONCATENATE_BASE_AND_DATA, -- rcookie, CKM_CONCATENATE_BASE_AND_DATA, CKA_DERIVE, -- 0); -- passert(tkey20 != NULL); -- -- PK11SymKey *tkey21 = pk11_derive_wrapper_lsw(tkey20, -- CKM_CONCATENATE_BASE_AND_DATA, -- hmac_val2, -- nss_key_derivation_mech( -- hasher), CKA_DERIVE, -- 0); -- passert(tkey21 != NULL); -- -- PK11SymKey *tkey22 = PK11_Derive_lsw(tkey21, nss_key_derivation_mech( -- hasher), NULL, CKM_CONCATENATE_BASE_AND_DATA, CKA_DERIVE, -- 0); -- passert(tkey22 != NULL); -- -- keyhandle = PK11_GetSymKeyHandle(tkey22); -- param.data = (unsigned char*)&keyhandle; -- param.len = sizeof(keyhandle); -- -- PK11SymKey *tkey23 = PK11_Derive_lsw(tkey8, -- CKM_CONCATENATE_BASE_AND_KEY, ¶m, -- nss_key_derivation_mech( -- hasher), CKA_DERIVE, -- 0); -- passert(tkey23 != NULL); -- -- DBG(DBG_CRYPT, DBG_log("NSS: enc keysize=%d", (int)keysize)); -- /* Deriving encryption key from SKEYID_e */ -- /* Oakley Keying Material -- * Derived from Skeyid_e: if it is not big enough, generate more -- * using the PRF. -- * See RFC 2409 "IKE" Appendix B -- */ -- -- CK_EXTRACT_PARAMS bitstart = 0; -- param1.data = (unsigned char*)&bitstart; -- param1.len = sizeof(bitstart); -- -- if (keysize <= hasher->hash_digest_len) { -- skeyid_e = PK11_Derive_lsw(tkey23, -- nss_key_derivation_mech(hasher), -- NULL, -- CKM_EXTRACT_KEY_FROM_KEY, /* note */ -- CKA_DERIVE, 0); -- passert(skeyid_e != NULL); -- /* nss_symkey_log(skeyid_e, "skeyid_e"); */ -- -- enc_key = PK11_DeriveWithFlags(skeyid_e, -- CKM_EXTRACT_KEY_FROM_KEY, ¶m1, -- nss_encryption_mech(encrypter), -- CKA_FLAGS_ONLY, keysize, -- CKF_ENCRYPT | CKF_DECRYPT); -- passert(enc_key != NULL); -- -- /* nss_symkey_log(enc_key, "enc_key"); */ -- } else { -- size_t i = 0; -- PK11SymKey *keymat; -- -- skeyid_e = PK11_Derive_lsw(tkey23, -- nss_key_derivation_mech(hasher), -- NULL, -- CKM_CONCATENATE_BASE_AND_DATA, /* note */ -- CKA_DERIVE, 0); -- passert(skeyid_e != NULL); -- /* nss_symkey_log(skeyid_e, "skeyid_e"); */ -- -- PK11SymKey *tkey25 = pk11_derive_wrapper_lsw(skeyid_e, -- CKM_CONCATENATE_BASE_AND_DATA, -- hmac_pad, CKM_XOR_BASE_AND_DATA, CKA_DERIVE, -- hasher->hash_block_size); -- passert(tkey25 != NULL); -- -- PK11SymKey *tkey26 = pk11_derive_wrapper_lsw(tkey25, -- CKM_XOR_BASE_AND_DATA, -- hmac_ipad, CKM_CONCATENATE_BASE_AND_DATA, CKA_DERIVE, -- 0); -- passert(tkey26 != NULL); -- -- PK11SymKey *tkey27 = pk11_derive_wrapper_lsw(tkey26, -- CKM_CONCATENATE_BASE_AND_DATA, -- hmac_zerobyte, -- nss_key_derivation_mech( -- hasher), CKA_DERIVE, -- 0); -- passert(tkey27 != NULL); -- -- PK11SymKey *tkey28 = PK11_Derive_lsw(tkey27, nss_key_derivation_mech( -- hasher), NULL, -- CKM_CONCATENATE_BASE_AND_DATA, CKA_DERIVE, -- 0); -- passert(tkey28 != NULL); -- -- PK11SymKey *tkey29 = pk11_derive_wrapper_lsw(tkey25, -- CKM_XOR_BASE_AND_DATA, -- hmac_opad, CKM_CONCATENATE_BASE_AND_KEY, CKA_DERIVE, -- 0); -- passert(tkey29 != NULL); -- -- keyhandle = PK11_GetSymKeyHandle(tkey28); -- param.data = (unsigned char*)&keyhandle; -- param.len = sizeof(keyhandle); -- -- PK11SymKey *tkey30 = PK11_Derive_lsw(tkey29, -- CKM_CONCATENATE_BASE_AND_KEY, ¶m, -- nss_key_derivation_mech( -- hasher), CKA_DERIVE, -- 0); -- passert(tkey30 != NULL); -- -- PK11SymKey *tkey31 = PK11_Derive_lsw(tkey30, nss_key_derivation_mech( -- hasher), NULL, CKM_CONCATENATE_BASE_AND_KEY, CKA_DERIVE, -- 0); -- passert(tkey31 != NULL); -- -- keymat = tkey31; -- -- i += hasher->hash_digest_len; -- -- PK11SymKey *tkey32 = pk11_derive_wrapper_lsw(skeyid_e, -- CKM_CONCATENATE_BASE_AND_DATA, -- hmac_pad, CKM_XOR_BASE_AND_DATA, CKA_DERIVE, -- hasher->hash_block_size); -- passert(tkey32 != NULL); -- -- PK11SymKey *tkey33 = pk11_derive_wrapper_lsw(tkey32, -- CKM_XOR_BASE_AND_DATA, -- hmac_ipad, CKM_CONCATENATE_BASE_AND_KEY, CKA_DERIVE, -- 0); -- passert(tkey33 != NULL); -- -- PK11SymKey *tkey36 = pk11_derive_wrapper_lsw(tkey32, -- CKM_XOR_BASE_AND_DATA, -- hmac_opad, CKM_CONCATENATE_BASE_AND_KEY, CKA_DERIVE, -- 0); -- passert(tkey36 != NULL); -- -- for (;; ) { -- -- keyhandle = PK11_GetSymKeyHandle(tkey31); -- param.data = (unsigned char*)&keyhandle; -- param.len = sizeof(keyhandle); -- -- PK11SymKey *tkey34 = PK11_Derive_lsw(tkey33, -- CKM_CONCATENATE_BASE_AND_KEY, ¶m, -- nss_key_derivation_mech( -- hasher), CKA_DERIVE, -- 0); -- passert(tkey34 != NULL); -- -- PK11SymKey *tkey35 = PK11_Derive_lsw(tkey34, nss_key_derivation_mech( -- hasher), NULL, -- CKM_CONCATENATE_BASE_AND_DATA, CKA_DERIVE, -- 0); -- passert(tkey35 != NULL); -- -- keyhandle = PK11_GetSymKeyHandle(tkey35); -- param.data = (unsigned char*)&keyhandle; -- param.len = sizeof(keyhandle); -- -- PK11SymKey *tkey37 = PK11_Derive_lsw(tkey36, -- CKM_CONCATENATE_BASE_AND_KEY, ¶m, -- nss_key_derivation_mech( -- hasher), CKA_DERIVE, -- 0); -- passert(tkey37 != NULL); -- -- PK11SymKey *tkey38 = PK11_Derive_lsw(tkey37, nss_key_derivation_mech( -- hasher), NULL, CKM_CONCATENATE_BASE_AND_KEY, CKA_DERIVE, -- 0); -- passert(tkey38 != NULL); -- -- i += hasher->hash_digest_len; -- -- if (i >= keysize ) { -- -- /*concatenating K1 and K2 */ -- keyhandle = -- PK11_GetSymKeyHandle(tkey38); -- param.data = -- (unsigned char*)&keyhandle; -- param.len = sizeof(keyhandle); -- -- PK11SymKey *tkey39 = PK11_Derive_lsw( -- keymat, -- CKM_CONCATENATE_BASE_AND_KEY, -- ¶m, -- CKM_EXTRACT_KEY_FROM_KEY, -- CKA_DERIVE, 0); -- passert(tkey39 != NULL); -- -- enc_key = PK11_DeriveWithFlags(tkey39, -- CKM_EXTRACT_KEY_FROM_KEY, ¶m1, -- nss_encryption_mech(encrypter), -- CKA_FLAGS_ONLY, /*0*/ keysize, -- CKF_ENCRYPT | CKF_DECRYPT); -- -- /* nss_symkey_log(enc_key, "enc_key"); */ -- passert(enc_key != NULL); -- -- PK11_FreeSymKey(tkey25); -- PK11_FreeSymKey(tkey26); -- PK11_FreeSymKey(tkey27); -- PK11_FreeSymKey(tkey28); -- PK11_FreeSymKey(tkey29); -- PK11_FreeSymKey(tkey30); -- PK11_FreeSymKey(tkey31); -- PK11_FreeSymKey(tkey32); -- PK11_FreeSymKey(tkey33); -- PK11_FreeSymKey(tkey34); -- PK11_FreeSymKey(tkey35); -- PK11_FreeSymKey(tkey36); -- PK11_FreeSymKey(tkey37); -- PK11_FreeSymKey(tkey38); -- PK11_FreeSymKey(tkey39); -- PK11_FreeSymKey(keymat); -- -- DBG(DBG_CRYPT, -- DBG_log( -- "NSS: Freed 25-39 symkeys")); -- break; -- } else { -- -- keyhandle = -- PK11_GetSymKeyHandle(tkey38); -- param.data = -- (unsigned char*)&keyhandle; -- param.len = sizeof(keyhandle); -- -- PK11SymKey *tkey39 = PK11_Derive_lsw( -- keymat, -- CKM_CONCATENATE_BASE_AND_KEY, -- ¶m, -- CKM_CONCATENATE_BASE_AND_KEY, -- CKA_DERIVE, 0); -- passert(tkey39 != NULL); -- -- keymat = tkey39; -- PK11_FreeSymKey(tkey31); -- tkey31 = tkey38; -- PK11_FreeSymKey(tkey34); -- PK11_FreeSymKey(tkey35); -- PK11_FreeSymKey(tkey37); -- -- DBG(DBG_CRYPT, -- DBG_log( -- "NSS: Freed symkeys 31 34 35 37")); -- } -- } /*end for*/ -- } /*end else skeyid_e */ -- -- /*****End of SKEYID_e and encryption key derivation***************************************/ -- -- /********Saving pointers of all derived keys**********************************************/ -- *skeyid_out = skeyid; -- *skeyid_d_out = skeyid_d; -- *skeyid_a_out = skeyid_a; -- *skeyid_e_out = skeyid_e; -- *enc_key_out = enc_key; -- -- DBG(DBG_CRYPT, DBG_log("NSS: pointers skeyid_d %p, skeyid_a %p, skeyid_e %p, enc_key %p", -- skeyid_d, skeyid_a, skeyid_e, enc_key)); -- -- -- /*****Freeing tmp keys***************************************/ -- PK11_FreeSymKey(tkey1); -- PK11_FreeSymKey(tkey2); -- PK11_FreeSymKey(tkey3); -- PK11_FreeSymKey(tkey4); -- PK11_FreeSymKey(tkey5); -- PK11_FreeSymKey(tkey6); -- PK11_FreeSymKey(tkey7); -- PK11_FreeSymKey(tkey8); -- PK11_FreeSymKey(tkey9); -- PK11_FreeSymKey(tkey10); -- PK11_FreeSymKey(tkey11); -- PK11_FreeSymKey(tkey12); -- PK11_FreeSymKey(tkey13); -- PK11_FreeSymKey(tkey14); -- PK11_FreeSymKey(tkey15); -- PK11_FreeSymKey(tkey16); -- PK11_FreeSymKey(tkey17); -- PK11_FreeSymKey(tkey18); -- PK11_FreeSymKey(tkey19); -- PK11_FreeSymKey(tkey20); -- PK11_FreeSymKey(tkey21); -- PK11_FreeSymKey(tkey22); -- PK11_FreeSymKey(tkey23); -- -- DBG(DBG_CRYPT, DBG_log("NSS: Freed symkeys 1-23")); -- -- freeanychunk(hmac_opad); -- freeanychunk(hmac_ipad); -- freeanychunk(hmac_pad); -- freeanychunk(hmac_zerobyte); -- freeanychunk(hmac_val1); -- freeanychunk(hmac_val2); -- DBG(DBG_CRYPT, DBG_log("NSS: Freed padding chunks")); -- } -- -- /* generate IV */ -- { -- union hash_ctx hash_ctx; -- -- new_iv->len = hasher->hash_digest_len; -- new_iv->ptr = alloc_bytes(new_iv->len, "calculated new iv"); -- -- DBG(DBG_CRYPT, { -- DBG_dump_chunk("DH_i:", gi); -- DBG_dump_chunk("DH_r:", gr); -- }); -- hasher->hash_init(&hash_ctx); -- hasher->hash_update(&hash_ctx, gi.ptr, gi.len); -- hasher->hash_update(&hash_ctx, gr.ptr, gr.len); -- hasher->hash_final(new_iv->ptr, &hash_ctx); -- DBG(DBG_CRYPT, DBG_log("end of IV generation")); -- } --} -- --/* MUST BE THREAD-SAFE */ --void calc_dh_iv(struct pluto_crypto_req *r) --{ -- struct pcr_skeyid_r *skr = &r->pcr_d.dhr; -- struct pcr_skeyid_q dhq; -- const struct oakley_group_desc *group; -- PK11SymKey *shared; -- chunk_t g; -- SECKEYPrivateKey *ltsecret; -- PK11SymKey -- *skeyid, -- *skeyid_d, -- *skeyid_a, -- *skeyid_e, -- *enc_key; -- chunk_t new_iv; -- SECKEYPublicKey *pubk; -- -- /* copy the request, since the reply will re-use the memory of the r->pcr_d.dhq */ -- memcpy(&dhq, &r->pcr_d.dhq, sizeof(r->pcr_d.dhq)); -- -- /* clear out the reply */ -- zero(skr); -- INIT_WIRE_ARENA(*skr); -- -- group = lookup_group(dhq.oakley_group); -- passert(group != NULL); -- -- ltsecret = dhq.secret; -- pubk = dhq.pubk; -- -- /* now calculate the (g^x)(g^y) --- -- * need gi on responder, gr on initiator -- */ -- -- setchunk_from_wire(g, &dhq, dhq.role == O_RESPONDER ? &dhq.gi : &dhq.gr); -- -- DBG(DBG_CRYPT, -- DBG_dump_chunk("peer's g: ", g)); -- -- shared = calc_dh_shared(g, ltsecret, group, pubk); -- -- zero(&new_iv); -- -- /* okay, so now calculate IV */ -- calc_skeyids_iv(&dhq, -- shared, -- dhq.key_size, -- &skeyid, -- &skeyid_d, -- &skeyid_a, -- &skeyid_e, -- &new_iv, -- &enc_key); -- -- skr->shared = shared; -- skr->skeyid = skeyid; -- skr->skeyid_d = skeyid_d; -- skr->skeyid_a = skeyid_a; -- skr->skeyid_e = skeyid_e; -- skr->enc_key = enc_key; -- -- -- WIRE_CLONE_CHUNK(*skr, new_iv, new_iv); -- freeanychunk(new_iv); --} - - /* MUST BE THREAD-SAFE */ - void calc_dh(struct pluto_crypto_req *r) -@@ -1128,496 +202,3 @@ - - skr->shared = calc_dh_shared(g, ltsecret, group, pubk); - } -- --static chunk_t chunk_from_symkey(const char *name, PK11SymKey *source_key, -- size_t next_bit, size_t byte_size) --{ -- if (byte_size == 0) { -- DBG(DBG_CRYPT, DBG_log("chunk_from_symkey: %s: zero size", name)); -- return empty_chunk; -- } -- CK_EXTRACT_PARAMS bs = next_bit; -- SECItem param = { .data = (unsigned char*)&bs, .len = sizeof(bs) }; -- PK11SymKey *sym_key = PK11_DeriveWithFlags(source_key, -- CKM_EXTRACT_KEY_FROM_KEY, -- ¶m, -- CKM_VENDOR_DEFINED, -- CKA_FLAGS_ONLY, byte_size, 0); -- if (sym_key == NULL) { -- loglog(RC_LOG_SERIOUS, "NSS: PK11_DeriveWithFlags failed while generating %s", name); -- return empty_chunk; -- } -- SECStatus s = PK11_ExtractKeyValue(sym_key); -- if (s != SECSuccess) { -- loglog(RC_LOG_SERIOUS, "NSS: PK11_ExtractKeyValue failed while generating %s", name); -- return empty_chunk; -- } -- /* Internal structure address, do not free. */ -- SECItem *data = PK11_GetKeyData(sym_key); -- if (data == NULL) { -- loglog(RC_LOG_SERIOUS, "NSS: PK11_GetKeyData failed while generating %s", name); -- return empty_chunk; -- } -- DBG(DBG_CRYPT, -- DBG_log("chunk_from_symkey: %s: extracted len %d bytes at %p", -- name, data->len, data->data)); -- if (data->len != byte_size) { -- loglog(RC_LOG_SERIOUS, "NSS: PK11_GetKeyData returned wrong number of bytes while generating %s", name); -- return empty_chunk; -- } -- chunk_t chunk; -- clonetochunk(chunk, data->data, data->len, name); -- DBG(DBG_CRYPT, DBG_dump_chunk(name, chunk)); -- PK11_FreeSymKey(sym_key); -- return chunk; --} -- --/* -- * IKEv2 - RFC4306 2.14 SKEYSEED - calculation. -- */ -- --/* MUST BE THREAD-SAFE */ --static void calc_skeyseed_v2(struct pcr_skeyid_q *skq, -- PK11SymKey *shared, -- const size_t key_size, -- const size_t salt_size, -- PK11SymKey **skeyseed_out, -- PK11SymKey **SK_d_out, -- PK11SymKey **SK_ai_out, -- PK11SymKey **SK_ar_out, -- PK11SymKey **SK_ei_out, -- PK11SymKey **SK_er_out, -- PK11SymKey **SK_pi_out, -- PK11SymKey **SK_pr_out, -- chunk_t *initiator_salt_out, -- chunk_t *responder_salt_out -- ) --{ -- struct v2prf_stuff vpss; -- -- chunk_t hmac_opad, hmac_ipad, hmac_pad_prf; -- /* chunk_t hmac_pad_integ, hmac_zerobyte, hmac_val1, hmac_val2; */ -- -- CK_OBJECT_HANDLE keyhandle; -- SECItem param, param1; -- DBG(DBG_CRYPT, DBG_log("NSS: Started key computation")); -- -- PK11SymKey -- *skeyseed_k, -- *SK_d_k, -- *SK_ai_k, -- *SK_ar_k, -- *SK_ei_k, -- *SK_er_k, -- *SK_pi_k, -- *SK_pr_k; -- chunk_t initiator_salt; -- chunk_t responder_salt; -- -- zero(&vpss); -- -- /* this doesn't take any memory, it's just moving pointers around */ -- setchunk_from_wire(vpss.ni, skq, &skq->ni); -- setchunk_from_wire(vpss.nr, skq, &skq->nr); -- setchunk_from_wire(vpss.spii, skq, &skq->icookie); -- setchunk_from_wire(vpss.spir, skq, &skq->rcookie); -- -- DBG(DBG_CONTROLMORE, -- DBG_log("calculating skeyseed using prf=%s integ=%s cipherkey-size=%zu salt-size=%zu", -- enum_name(&ikev2_trans_type_prf_names, skq->prf_hash), -- enum_name(&ikev2_trans_type_integ_names, skq->integ_hash), -- key_size, salt_size)); -- -- const struct hash_desc *prf_hasher = (struct hash_desc *) -- ikev2_alg_find(IKE_ALG_HASH, skq->prf_hash); -- passert(prf_hasher != NULL); -- -- const struct encrypt_desc *encrypter = skq->encrypter; -- passert(encrypter != NULL); -- -- hmac_opad = hmac_pads(HMAC_OPAD, prf_hasher->hash_block_size); -- hmac_ipad = hmac_pads(HMAC_IPAD, prf_hasher->hash_block_size); -- hmac_pad_prf = hmac_pads(0x00, -- prf_hasher->hash_block_size - -- prf_hasher->hash_digest_len); -- -- /* generate SKEYSEED from key=(Ni|Nr), hash of shared */ -- skeyseed_k = skeyid_digisig(vpss.ni, vpss.nr, shared, prf_hasher); -- passert(skeyseed_k != NULL); -- -- /* now we have to generate the keys for everything */ -- { -- /* need to know how many bits to generate */ -- /* SK_d needs PRF hasher key bytes */ -- /* SK_p needs PRF hasher*2 key bytes */ -- /* SK_e needs key_size*2 key bytes */ -- /* ..._salt needs salt_size*2 bytes */ -- /* SK_a needs integ's key size*2 bytes */ -- -- int skd_bytes = prf_hasher->hash_key_size; -- int skp_bytes = prf_hasher->hash_key_size; -- const struct hash_desc *integ_hasher = -- (struct hash_desc *)ikev2_alg_find(IKE_ALG_INTEG, skq->integ_hash); -- int integ_size = integ_hasher != NULL ? integ_hasher->hash_key_size : 0; -- size_t total_keysize = skd_bytes + 2*skp_bytes + 2*key_size + 2*salt_size + 2*integ_size; -- DBG(DBG_CRYPT, -- DBG_log("calc_skeyseed_v2: %zd = %d(d) + 2*%d(p) + 2*%zd(key) + 2*%zd(salt) + 2*%d(integ) bytes", -- total_keysize, skd_bytes, skp_bytes, key_size, salt_size, integ_size)); -- vpss.counter[0] = 0x01; -- vpss.t.len = 0; -- -- DBG(DBG_CRYPT, { -- DBG_log("PRF+ input"); -- DBG_dump_chunk("Ni", vpss.ni); -- DBG_dump_chunk("Nr", vpss.nr); -- DBG_dump_chunk("SPIi", vpss.spii); -- DBG_dump_chunk("SPIr", vpss.spir); -- DBG_log("Total keysize needed %zd", -- total_keysize); -- }); -- -- PK11SymKey *finalkey = NULL; -- PK11SymKey *tkey11 = NULL; -- PK11SymKey *tkey1 = pk11_derive_wrapper_lsw(skeyseed_k, -- CKM_CONCATENATE_BASE_AND_DATA, -- hmac_pad_prf, CKM_XOR_BASE_AND_DATA, CKA_DERIVE, -- prf_hasher->hash_block_size); -- passert(tkey1 != NULL); -- -- for (;; ) { -- PK11SymKey *tkey3 = NULL; -- -- if (vpss.counter[0] == 0x01) { -- PK11SymKey *tkey2 = pk11_derive_wrapper_lsw( -- tkey1, CKM_XOR_BASE_AND_DATA, -- hmac_ipad, -- CKM_CONCATENATE_BASE_AND_DATA, -- CKA_DERIVE, -- 0); -- passert(tkey2 != NULL); -- -- tkey3 = pk11_derive_wrapper_lsw(tkey2, -- CKM_CONCATENATE_BASE_AND_DATA, -- vpss.ni, CKM_CONCATENATE_BASE_AND_DATA, CKA_DERIVE, -- 0); -- PK11_FreeSymKey(tkey2); -- } else { -- PK11SymKey *tkey2 = pk11_derive_wrapper_lsw( -- tkey1, CKM_XOR_BASE_AND_DATA, -- hmac_ipad, -- CKM_CONCATENATE_BASE_AND_KEY, -- CKA_DERIVE, -- 0); -- passert(tkey2 != NULL); -- -- keyhandle = PK11_GetSymKeyHandle(tkey11); -- param.data = (unsigned char*)&keyhandle; -- param.len = sizeof(keyhandle); -- -- PK11SymKey *tkey12 = PK11_Derive_lsw(tkey2, -- CKM_CONCATENATE_BASE_AND_KEY, -- ¶m, CKM_CONCATENATE_BASE_AND_DATA, CKA_DERIVE, -- 0); -- passert(tkey12 != NULL); -- -- tkey3 = pk11_derive_wrapper_lsw(tkey12, -- CKM_CONCATENATE_BASE_AND_DATA, -- vpss.ni, CKM_CONCATENATE_BASE_AND_DATA, CKA_DERIVE, -- 0); -- PK11_FreeSymKey(tkey2); -- PK11_FreeSymKey(tkey11); -- PK11_FreeSymKey(tkey12); -- } -- -- passert(tkey3 != NULL); -- -- PK11SymKey *tkey4 = pk11_derive_wrapper_lsw(tkey3, -- CKM_CONCATENATE_BASE_AND_DATA, -- vpss.nr, -- CKM_CONCATENATE_BASE_AND_DATA, -- CKA_DERIVE, -- 0); -- passert(tkey4 != NULL); -- -- PK11SymKey *tkey5 = pk11_derive_wrapper_lsw(tkey4, -- CKM_CONCATENATE_BASE_AND_DATA, -- vpss.spii, -- CKM_CONCATENATE_BASE_AND_DATA, -- CKA_DERIVE, -- 0); -- passert(tkey5 != NULL); -- -- PK11SymKey *tkey6 = pk11_derive_wrapper_lsw(tkey5, -- CKM_CONCATENATE_BASE_AND_DATA, -- vpss.spir, -- CKM_CONCATENATE_BASE_AND_DATA, -- CKA_DERIVE, -- 0); -- passert(tkey6 != NULL); -- -- chunk_t counter; -- -- setchunk(counter, &vpss.counter[0], sizeof(vpss.counter[0])); -- PK11SymKey *tkey7 = pk11_derive_wrapper_lsw(tkey6, -- CKM_CONCATENATE_BASE_AND_DATA, -- counter, -- nss_key_derivation_mech(prf_hasher), -- CKA_DERIVE, -- 0); -- passert(tkey7 != NULL); -- -- PK11SymKey *tkey8 = PK11_Derive_lsw(tkey7, -- nss_key_derivation_mech(prf_hasher), -- NULL, -- CKM_CONCATENATE_BASE_AND_DATA, -- CKA_DERIVE, -- 0); -- passert(tkey8 != NULL); -- -- PK11SymKey *tkey9 = pk11_derive_wrapper_lsw(tkey1, -- CKM_XOR_BASE_AND_DATA, -- hmac_opad, -- CKM_CONCATENATE_BASE_AND_KEY, -- CKA_DERIVE, -- 0); -- passert(tkey9 != NULL); -- -- keyhandle = PK11_GetSymKeyHandle(tkey8); -- param.data = (unsigned char*)&keyhandle; -- param.len = sizeof(keyhandle); -- -- PK11SymKey *tkey10 = PK11_Derive_lsw(tkey9, -- CKM_CONCATENATE_BASE_AND_KEY, -- ¶m, -- nss_key_derivation_mech(prf_hasher), -- CKA_DERIVE, -- 0); -- passert(tkey10 != NULL); -- -- if (vpss.counter[0] == 0x01) { -- finalkey = PK11_Derive_lsw(tkey10, -- nss_key_derivation_mech(prf_hasher), -- NULL, -- CKM_CONCATENATE_BASE_AND_KEY, -- CKA_DERIVE, -- 0); -- passert(finalkey != NULL); -- -- tkey11 = PK11_Derive_lsw(tkey10, -- nss_key_derivation_mech(prf_hasher), -- NULL, -- CKM_CONCATENATE_BASE_AND_KEY, -- CKA_DERIVE, -- 0); -- passert(tkey11 != NULL); -- } else { -- tkey11 = PK11_Derive_lsw(tkey10, -- nss_key_derivation_mech(prf_hasher), -- NULL, -- CKM_EXTRACT_KEY_FROM_KEY, -- CKA_DERIVE, -- 0); -- passert(tkey11 != NULL); -- -- keyhandle = PK11_GetSymKeyHandle(tkey11); -- param.data = (unsigned char*)&keyhandle; -- param.len = sizeof(keyhandle); -- -- if ( total_keysize <= -- (PK11_GetKeyLength(finalkey) + -- PK11_GetKeyLength(tkey11)) ) { -- finalkey = PK11_Derive_lsw(finalkey, -- CKM_CONCATENATE_BASE_AND_KEY, -- ¶m, -- CKM_EXTRACT_KEY_FROM_KEY, -- CKA_DERIVE, -- 0); -- passert(finalkey != NULL); -- } else { -- finalkey = PK11_Derive_lsw(finalkey, -- CKM_CONCATENATE_BASE_AND_KEY, -- ¶m, -- CKM_CONCATENATE_BASE_AND_KEY, -- CKA_DERIVE, -- 0); -- passert(finalkey != NULL); -- } -- } -- -- PK11_FreeSymKey(tkey3); -- PK11_FreeSymKey(tkey4); -- PK11_FreeSymKey(tkey5); -- PK11_FreeSymKey(tkey6); -- PK11_FreeSymKey(tkey7); -- PK11_FreeSymKey(tkey8); -- PK11_FreeSymKey(tkey9); -- PK11_FreeSymKey(tkey10); -- -- if (total_keysize <= PK11_GetKeyLength(finalkey)) { -- PK11_FreeSymKey(tkey1); -- PK11_FreeSymKey(tkey11); -- break; -- } -- -- vpss.counter[0]++; -- } -- -- DBG(DBG_CRYPT, -- DBG_log("NSS ikev2: finished computing key material for IKEv2 SA")); -- -- CK_EXTRACT_PARAMS bs = 0; -- size_t next_bit = 0; -- -- SK_d_k = pk11_extract_derive_wrapper_lsw(finalkey, next_bit, -- CKM_CONCATENATE_BASE_AND_DATA, CKA_DERIVE, -- skd_bytes); -- next_bit += skd_bytes * BITS_PER_BYTE; -- -- SK_ai_k = pk11_extract_derive_wrapper_lsw(finalkey, next_bit, -- CKM_CONCATENATE_BASE_AND_DATA, CKA_DERIVE, -- integ_size); -- next_bit += integ_size * BITS_PER_BYTE; -- -- SK_ar_k = pk11_extract_derive_wrapper_lsw(finalkey, next_bit, -- CKM_CONCATENATE_BASE_AND_DATA, CKA_DERIVE, -- integ_size); -- next_bit += integ_size * BITS_PER_BYTE; -- -- bs = next_bit; -- param1.data = (unsigned char*)&bs; -- param1.len = sizeof(bs); -- SK_ei_k = PK11_DeriveWithFlags(finalkey, -- CKM_EXTRACT_KEY_FROM_KEY, -- ¶m1, -- nss_encryption_mech(encrypter), -- CKA_FLAGS_ONLY, key_size, -- CKF_ENCRYPT | CKF_DECRYPT); -- next_bit += key_size * BITS_PER_BYTE; -- -- initiator_salt = chunk_from_symkey("initiator salt", finalkey, -- next_bit, salt_size); -- next_bit += salt_size * BITS_PER_BYTE; -- -- bs = next_bit; -- param1.data = (unsigned char*)&bs; -- param1.len = sizeof(bs); -- SK_er_k = PK11_DeriveWithFlags(finalkey, -- CKM_EXTRACT_KEY_FROM_KEY, -- ¶m1, -- nss_encryption_mech(encrypter), -- CKA_FLAGS_ONLY, key_size, -- CKF_ENCRYPT | CKF_DECRYPT); -- next_bit += key_size * BITS_PER_BYTE; -- -- responder_salt = chunk_from_symkey("responder salt", finalkey, -- next_bit, salt_size); -- next_bit += salt_size * BITS_PER_BYTE; -- -- SK_pi_k = pk11_extract_derive_wrapper_lsw(finalkey, next_bit, -- CKM_CONCATENATE_BASE_AND_DATA, CKA_DERIVE, -- skp_bytes); -- next_bit += skp_bytes * BITS_PER_BYTE; -- -- SK_pr_k = pk11_extract_derive_wrapper_lsw(finalkey, next_bit, -- CKM_CONCATENATE_BASE_AND_DATA, CKA_DERIVE, -- skp_bytes); -- next_bit += skp_bytes * BITS_PER_BYTE; -- -- DBG(DBG_CRYPT, -- DBG_log("NSS ikev2: finished computing individual keys for IKEv2 SA")); -- PK11_FreeSymKey(finalkey); -- -- *skeyseed_out = skeyseed_k; -- *SK_d_out = SK_d_k; -- *SK_ai_out = SK_ai_k; -- *SK_ar_out = SK_ar_k; -- *SK_ei_out = SK_ei_k; -- *SK_er_out = SK_er_k; -- *SK_pi_out = SK_pi_k; -- *SK_pr_out = SK_pr_k; -- *initiator_salt_out = initiator_salt; -- *responder_salt_out = responder_salt; -- -- freeanychunk(hmac_opad); -- freeanychunk(hmac_ipad); -- freeanychunk(hmac_pad_prf); -- } -- DBG(DBG_CRYPT, -- DBG_log("calc_skeyseed_v2 pointers: shared %p, skeyseed %p, SK_d %p, SK_ai %p, SK_ar %p, SK_ei %p, SK_er %p, SK_pi %p, SK_pr %p", -- shared, skeyseed_k, SK_d_k, SK_ai_k, SK_ar_k, SK_ei_k, SK_er_k, SK_pi_k, SK_pr_k); -- DBG_dump_chunk("calc_skeyseed_v2 initiator salt", initiator_salt); -- DBG_dump_chunk("calc_skeyseed_v2 responder salt", responder_salt)); --} -- --/* MUST BE THREAD-SAFE */ --void calc_dh_v2(struct pluto_crypto_req *r) --{ -- struct pcr_skeycalc_v2_r *skr = &r->pcr_d.dhv2; -- struct pcr_skeyid_q dhq; -- const struct oakley_group_desc *group; -- PK11SymKey *shared; -- chunk_t g; -- SECKEYPrivateKey *ltsecret; -- PK11SymKey *skeyseed; -- PK11SymKey -- *SK_d, -- *SK_ai, -- *SK_ar, -- *SK_ei, -- *SK_er, -- *SK_pi, -- *SK_pr; -- chunk_t initiator_salt; -- chunk_t responder_salt; -- SECKEYPublicKey *pubk; -- -- /* copy the request, since the reply will re-use the memory of the r->pcr_d.dhq */ -- memcpy(&dhq, &r->pcr_d.dhq, sizeof(r->pcr_d.dhq)); -- -- /* clear out the reply */ -- zero(skr); -- INIT_WIRE_ARENA(*skr); -- -- group = lookup_group(dhq.oakley_group); -- passert(group != NULL); -- -- ltsecret = dhq.secret; -- pubk = dhq.pubk; -- -- /* now calculate the (g^x)(g^y) --- need gi on responder, gr on initiator */ -- -- setchunk_from_wire(g, &dhq, dhq.role == O_RESPONDER ? &dhq.gi : &dhq.gr); -- -- DBG(DBG_CRYPT, DBG_dump_chunk("peer's g: ", g)); -- -- shared = calc_dh_shared(g, ltsecret, group, pubk); -- -- /* okay, so now all the shared key material */ -- calc_skeyseed_v2(&dhq, /* input */ -- shared, /* input */ -- dhq.key_size, /* input */ -- dhq.salt_size, /* input */ -- -- &skeyseed, /* output */ -- &SK_d, /* output */ -- &SK_ai, /* output */ -- &SK_ar, /* output */ -- &SK_ei, /* output */ -- &SK_er, /* output */ -- &SK_pi, /* output */ -- &SK_pr, /* output */ -- &initiator_salt, /* output */ -- &responder_salt); /* output */ -- -- skr->shared = shared; -- skr->skeyseed = skeyseed; -- skr->skeyid_d = SK_d; -- skr->skeyid_ai = SK_ai; -- skr->skeyid_ar = SK_ar; -- skr->skeyid_ei = SK_ei; -- skr->skeyid_er = SK_er; -- skr->skeyid_pi = SK_pi; -- skr->skeyid_pr = SK_pr; -- skr->skey_initiator_salt = initiator_salt; -- skr->skey_responder_salt = responder_salt; --} -diff -Naur libreswan-3.12-orig/programs/pluto/crypt_dh.h libreswan-3.12/programs/pluto/crypt_dh.h ---- libreswan-3.12-orig/programs/pluto/crypt_dh.h 1969-12-31 19:00:00.000000000 -0500 -+++ libreswan-3.12/programs/pluto/crypt_dh.h 2015-05-06 11:45:32.918301394 -0400 -@@ -0,0 +1,46 @@ -+/* -+ * DH crypto functions, for libreswan -+ * -+ * Copyright (C) 2007-2008 Michael C. Richardson -+ * Copyright (C) 2008 Antony Antony -+ * Copyright (C) 2009 David McCullough -+ * Copyright (C) 2009-2012 Avesh Agarwal -+ * Copyright (C) 2009-2010 Paul Wouters -+ * Copyright (C) 2010 Tuomo Soini -+ * Copyright (C) 2012-2013 Paul Wouters -+ * Copyright (C) 2012 Wes Hardaker -+ * Copyright (C) 2013 Antony Antony -+ * Copyright (C) 2013 D. Hugh Redelmeier -+ * Copyright (C) 2015 Paul Wouters -+ * Copyright (C) 2015 Andrew Cagney -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * for more details. -+ */ -+ -+#ifndef crypt_dh_h -+#define crypt_dh_h -+ -+#include -+#include "lswalloc.h" -+ -+struct oakley_group_desc; -+ -+PK11SymKey *calc_dh_shared(chunk_t g, /* converted to SECItem */ -+ /*const*/ SECKEYPrivateKey *privk, /* NSS doesn't do const */ -+ const struct oakley_group_desc *group, -+ const SECKEYPublicKey *local_pubk); -+ -+ -+struct pluto_crypto_req; -+ -+void calc_dh(struct pluto_crypto_req *r); -+ -+#endif -diff -Naur libreswan-3.12-orig/programs/pluto/crypto.h libreswan-3.12/programs/pluto/crypto.h ---- libreswan-3.12-orig/programs/pluto/crypto.h 2014-11-06 22:52:50.000000000 -0500 -+++ libreswan-3.12/programs/pluto/crypto.h 2015-05-06 11:45:32.918301394 -0400 -@@ -127,24 +127,14 @@ - aes_xcbc_context ctx_aes_xcbc; - }; - --/* HMAC package -- * Note that hmac_ctx can be (and is) copied since there are -- * no persistent pointers into it. -+/* -+ * HMAC package (new code should use crypt_prf). - */ - -+struct crypt_prf; - struct hmac_ctx { -- const struct hash_desc *h; /* underlying hash function */ -- size_t hmac_digest_len; /* copy of h->hash_digest_len */ -- union hash_ctx hash_ctx; /* ctx for hash function */ -- u_char buf1[HMAC_BUFSIZE], buf2[HMAC_BUFSIZE]; --#ifdef USE_SHA2 -- sha256_context ctx_sha256; -- sha512_context ctx_sha512; --#endif -- aes_xcbc_context ctx_aes_xcbc; -- -- PK11SymKey *ikey, *okey; -- PK11Context *ctx_nss; -+ struct crypt_prf *prf; -+ size_t hmac_digest_len; - }; - - extern void hmac_init(struct hmac_ctx *ctx, -@@ -167,18 +157,7 @@ - } - - extern CK_MECHANISM_TYPE nss_key_derivation_mech(const struct hash_desc *hasher); --extern void nss_symkey_log(PK11SymKey *key, const char *msg); - extern chunk_t hmac_pads(u_char val, unsigned int len); --extern PK11SymKey *pk11_derive_wrapper_lsw(PK11SymKey *base, -- CK_MECHANISM_TYPE mechanism, -- chunk_t data, -- CK_MECHANISM_TYPE target, -- CK_ATTRIBUTE_TYPE operation, -- int keySize); --extern PK11SymKey *PK11_Derive_lsw(PK11SymKey *base, -- CK_MECHANISM_TYPE mechanism, -- SECItem *param, CK_MECHANISM_TYPE target, -- CK_ATTRIBUTE_TYPE operation, int keySize); - - enum crk_proto { - CRK_ESPorAH, -diff -Naur libreswan-3.12-orig/programs/pluto/crypt_prf.c libreswan-3.12/programs/pluto/crypt_prf.c ---- libreswan-3.12-orig/programs/pluto/crypt_prf.c 1969-12-31 19:00:00.000000000 -0500 -+++ libreswan-3.12/programs/pluto/crypt_prf.c 2015-05-06 11:45:32.919301405 -0400 -@@ -0,0 +1,203 @@ -+/* -+ * PRF helper functions, for libreswan -+ * -+ * Copyright (C) 2007-2008 Michael C. Richardson -+ * Copyright (C) 2008 Antony Antony -+ * Copyright (C) 2009 David McCullough -+ * Copyright (C) 2009-2012 Avesh Agarwal -+ * Copyright (C) 2009-2010 Paul Wouters -+ * Copyright (C) 2010 Tuomo Soini -+ * Copyright (C) 2012-2013 Paul Wouters -+ * Copyright (C) 2012 Wes Hardaker -+ * Copyright (C) 2013 Antony Antony -+ * Copyright (C) 2013 D. Hugh Redelmeier -+ * Copyright (C) 2015 Paul Wouters -+ * Copyright (C) 2015 Andrew Cagney -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * for more details. -+ */ -+ -+#include -+ -+//#include "libreswan.h" -+#include "lswalloc.h" -+#include "lswlog.h" -+#include "ike_alg.h" -+#include "crypt_prf.h" -+#include "crypt_symkey.h" -+#include "crypto.h" -+ -+struct crypt_prf { -+ const char *name; -+ const struct hash_desc *hasher; -+ /* for converting chunks to symkeys */ -+ PK11SymKey *scratch; -+ /* Did we allocate KEY? */ -+ bool we_own_key; -+ /* intermediate values */ -+ PK11SymKey *key; -+ PK11SymKey *inner; -+}; -+ -+/* -+ * During the init phase, accumulate the key material in KEY. -+ */ -+struct crypt_prf *crypt_prf_init(const char *name, const struct hash_desc *hasher, -+ PK11SymKey *scratch) -+{ -+ struct crypt_prf *prf = alloc_bytes(sizeof(struct crypt_prf), name); -+ DBG(DBG_CRYPT, DBG_log("%s prf: init %p", name, prf)); -+ prf->name = name; -+ prf->hasher = hasher; -+ prf->scratch = scratch; -+ prf->we_own_key = FALSE; -+ prf->key = NULL; -+ prf->inner = NULL; -+ return prf; -+} -+ -+/* -+ * Update KEY marking it as ours. Only call with a KEY we created. -+ */ -+static void update_key(struct crypt_prf *prf, PK11SymKey *key) -+{ -+ if (prf->we_own_key) { -+ free_any_symkey(__func__, &prf->key); -+ } -+ prf->we_own_key = TRUE; -+ prf->key = key; -+} -+ -+void crypt_prf_init_symkey(const char *name, struct crypt_prf *prf, PK11SymKey *key) -+{ -+ DBG(DBG_CRYPT, DBG_log("%s prf: init symkey %s %p (length %d)", -+ prf->name, name, key, PK11_GetKeyLength(key))); -+ if (prf->key == NULL) { -+ prf->we_own_key = FALSE; -+ prf->key = key; -+ } else { -+ update_key(prf, concat_symkey_symkey(prf->hasher, prf->key, key)); -+ } -+} -+ -+void crypt_prf_init_chunk(const char *name, struct crypt_prf *prf, chunk_t key) -+{ -+ DBG(DBG_CRYPT, DBG_log("%s prf: init chunk %s %p (length %zd)", -+ prf->name, name, key.ptr, key.len)); -+ if (prf->key == NULL) { -+ prf->key = symkey_from_chunk(prf->scratch, key); -+ prf->we_own_key = TRUE; -+ } else { -+ update_key(prf, concat_symkey_chunk(prf->hasher, prf->key, key)); -+ } -+} -+ -+/* -+ * Prepare for update phase (accumulate seed material). -+ */ -+void crypt_prf_update(struct crypt_prf *prf) -+{ -+ DBG(DBG_CRYPT, DBG_log("%s prf: update", prf->name)); -+ /* create the prf key from KEY. */ -+ passert(prf->key != NULL); -+ /* If the key is too big, re-hash it down to size. */ -+ if (PK11_GetKeyLength(prf->key) > prf->hasher->hash_block_size) { -+ update_key(prf, hash_symkey(prf->hasher, prf->key)); -+ } -+ /* If the key is too small, pad it. */ -+ if (PK11_GetKeyLength(prf->key) < prf->hasher->hash_block_size) { -+ /* pad it to block_size. */ -+ chunk_t hmac_pad_prf = hmac_pads(0x00, -+ (prf->hasher->hash_block_size - -+ PK11_GetKeyLength(prf->key))); -+ update_key(prf, concat_symkey_chunk(prf->hasher, prf->key, -+ hmac_pad_prf)); -+ freeanychunk(hmac_pad_prf); -+ } -+ passert(prf->key != NULL); -+ -+ /* Start forming the inner hash input: (key^IPAD)|... */ -+ passert(prf->inner == NULL); -+ chunk_t hmac_ipad = hmac_pads(HMAC_IPAD, prf->hasher->hash_block_size); -+ prf->inner = xor_symkey_chunk(prf->key, hmac_ipad); -+ freeanychunk(hmac_ipad); -+} -+ -+void crypt_prf_update_chunk(const char *name, struct crypt_prf *prf, -+ chunk_t update) -+{ -+ DBG(DBG_CRYPT, DBG_log("%s prf: update chunk %s %p (length %zd)", -+ prf->name, name, update.ptr, update.len)); -+ append_symkey_chunk(prf->hasher, &(prf->inner), update); -+} -+ -+void crypt_prf_update_symkey(const char *name, struct crypt_prf *prf, -+ PK11SymKey *update) -+{ -+ DBG(DBG_CRYPT, DBG_log("%s prf: update symkey %s %p (length %d)", -+ prf->name, name, update, -+ PK11_GetKeyLength(update))); -+ append_symkey_symkey(prf->hasher, &(prf->inner), update); -+} -+ -+void crypt_prf_update_byte(const char *name, struct crypt_prf *prf, -+ uint8_t update) -+{ -+ DBG(DBG_CRYPT, DBG_log("%s prf: update byte %s", prf->name, name)); -+ append_symkey_byte(prf->hasher, &(prf->inner), update); -+} -+ -+void crypt_prf_update_bytes(const char *name, struct crypt_prf *prf, -+ const void *update, size_t sizeof_update) -+{ -+ DBG(DBG_CRYPT, DBG_log("%s prf: update bytes %s %p (length %zd)", -+ prf->name, name, update, sizeof_update)); -+ append_symkey_bytes(prf->hasher, &(prf->inner), update, sizeof_update); -+} -+ -+PK11SymKey *crypt_prf_final(struct crypt_prf *prf) -+{ -+ DBG(DBG_CRYPT, DBG_log("%s prf: final", prf->name)); -+ passert(prf->inner != NULL); -+ /* run that through hasher */ -+ PK11SymKey *hashed_inner = hash_symkey(prf->hasher, prf->inner); -+ free_any_symkey("prf inner", &prf->inner); -+ -+ /* Input to outer hash: (key^OPAD)|hashed_inner. */ -+ chunk_t hmac_opad = hmac_pads(HMAC_OPAD, prf->hasher->hash_block_size); -+ PK11SymKey *outer = xor_symkey_chunk(prf->key, hmac_opad); -+ freeanychunk(hmac_opad); -+ append_symkey_symkey(prf->hasher, &outer, hashed_inner); -+ free_any_symkey("prf hashed inner", &hashed_inner); -+ -+ /* Finally hash that */ -+ PK11SymKey *hashed_outer = hash_symkey(prf->hasher, outer); -+ free_any_symkey("prf outer", &outer); -+ -+ if (prf->we_own_key) { -+ free_any_symkey("prf key", &prf->key); -+ } -+ prf->key = NULL; /* help debug */ -+ pfree(prf); -+ -+ DBG(DBG_CRYPT, DBG_dump_symkey("prf result", hashed_outer)); -+ return hashed_outer; -+} -+ -+void crypt_prf_final_bytes(struct crypt_prf *prf, -+ void *bytes, size_t sizeof_bytes) -+{ -+ const char *name = prf->name; -+ PK11SymKey *result = crypt_prf_final(prf); -+ prf = NULL; /* no longer valid */ -+ bytes_from_symkey_bytes(name, result, 0, bytes, sizeof_bytes); -+ free_any_symkey(__func__, &result); -+} -diff -Naur libreswan-3.12-orig/programs/pluto/crypt_prf.h libreswan-3.12/programs/pluto/crypt_prf.h ---- libreswan-3.12-orig/programs/pluto/crypt_prf.h 1969-12-31 19:00:00.000000000 -0500 -+++ libreswan-3.12/programs/pluto/crypt_prf.h 2015-05-06 11:45:32.919301405 -0400 -@@ -0,0 +1,86 @@ -+/* -+ * prf and keying material helper functions, for libreswan -+ * -+ * Copyright (C) 2007 Michael C. Richardson -+ * Copyright (C) 2010 Paul Wouters -+ * Copyright (C) 2013 D. Hugh Redelmeier -+ * Copyright (C) 2015 Andrew Cagney -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * for more details. -+ */ -+ -+#ifndef crypt_prf_h -+#define crypt_prf_h -+ -+#include -+ -+struct hash_desc; -+struct crypt_prf; -+ -+/* -+ * Primitives implementing PRF described in rfc2104. -+ * -+ * This implementation tries to keep all the input and output material -+ * secure inside SymKeys. To that end, it should be good for -+ * generating keying material. -+ * -+ * The slightly clunky, interface is described in-line below. -+ */ -+ -+/* -+ * Call this first; always. -+ * -+ * SCRATCH is used as a secure starting point when the key is formed -+ * from raw bytes (or memory). -+ */ -+struct crypt_prf *crypt_prf_init(const char *name, -+ const struct hash_desc *hasher, -+ PK11SymKey *scratch); -+ -+/* -+ * Next load up the raw-key by calling one or more of the following. -+ * Multiple calls concatenate the key. -+ * -+ * Even when SCRATCH above was passed the KEY, the below must be -+ * called. -+ */ -+void crypt_prf_init_symkey(const char *name, struct crypt_prf *prf, PK11SymKey *key); -+void crypt_prf_init_chunk(const char *name, struct crypt_prf *prf, -+ chunk_t key); -+void crypt_prf_init_bytes(const char *name, struct crypt_prf *prf, -+ const void *key, size_t sizeof_key); -+ -+/* -+ * Then call this to flip to seed/data/text mode; always. -+ */ -+void crypt_prf_update(struct crypt_prf *prf); -+ -+/* -+ * Call these to accumulate the seed/data/text. -+ */ -+void crypt_prf_update_chunk(const char *name, struct crypt_prf *prf, -+ chunk_t update); -+void crypt_prf_update_symkey(const char *name, struct crypt_prf *prf, -+ PK11SymKey *update); -+void crypt_prf_update_byte(const char *name, struct crypt_prf *prf, uint8_t byte); -+void crypt_prf_update_bytes(const char *name, struct crypt_prf *prf, -+ const void *bytes, size_t count); -+ -+/* -+ * Finally ... -+ * -+ * This will free PRF. -+ */ -+PK11SymKey *crypt_prf_final(struct crypt_prf *prf); -+void crypt_prf_final_bytes(struct crypt_prf *prf, -+ void *bytes, size_t sizeof_bytes); -+ -+#endif -diff -Naur libreswan-3.12-orig/programs/pluto/crypt_symkey.c libreswan-3.12/programs/pluto/crypt_symkey.c ---- libreswan-3.12-orig/programs/pluto/crypt_symkey.c 1969-12-31 19:00:00.000000000 -0500 -+++ libreswan-3.12/programs/pluto/crypt_symkey.c 2015-05-06 11:45:32.920301417 -0400 -@@ -0,0 +1,468 @@ -+/* -+ * SYMKEY manipulation functions, for libreswan -+ * -+ * Copyright (C) 2015 Andrew Cagney -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * for more details. -+ */ -+ -+#include "libreswan.h" -+#include "lswalloc.h" -+#include "lswlog.h" -+#include "ike_alg.h" -+#include "crypt_symkey.h" -+#include "crypto.h" -+ -+/* -+ * XXX: Is there an NSS version of this? -+ */ -+ -+static const char *ckm_to_string(CK_MECHANISM_TYPE mechanism) -+{ -+ const char *t; -+#define CASE(T) case T: t = #T; eat(t, "CKM_"); return t -+ switch (mechanism) { -+ -+ CASE(CKM_CONCATENATE_BASE_AND_DATA); -+ CASE(CKM_CONCATENATE_BASE_AND_KEY); -+ CASE(CKM_CONCATENATE_DATA_AND_BASE); -+ -+ CASE(CKM_XOR_BASE_AND_DATA); -+ -+ CASE(CKM_EXTRACT_KEY_FROM_KEY); -+ -+ CASE(CKM_VENDOR_DEFINED); -+ -+ CASE(CKM_AES_CBC); -+ CASE(CKM_DES3_CBC); -+ CASE(CKM_CAMELLIA_CBC); -+ CASE(CKM_AES_CTR); -+ CASE(CKM_AES_GCM); -+ -+ CASE(CKM_MD5_KEY_DERIVATION); -+ CASE(CKM_SHA1_KEY_DERIVATION); -+ CASE(CKM_SHA256_KEY_DERIVATION); -+ CASE(CKM_SHA384_KEY_DERIVATION); -+ CASE(CKM_SHA512_KEY_DERIVATION); -+ -+ default: -+ DBG(DBG_CRYPT, DBG_log("unknown mechanism 0x%08x", (int) mechanism)); -+ return "unknown-mechanism"; -+ } -+#undef CASE -+} -+ -+void free_any_symkey(const char *prefix, PK11SymKey **key) -+{ -+ if (*key != NULL) { -+ DBG(DBG_CRYPT, DBG_log("%s: free key %p", prefix, *key)); -+ PK11_FreeSymKey(*key); -+ } else { -+ DBG(DBG_CRYPT, DBG_log("%s: free key NULL", prefix)); -+ } -+ *key = NULL; -+} -+ -+void DBG_dump_symkey(const char *prefix, PK11SymKey *key) -+{ -+ if (key == NULL) { -+ /* -+ * For instance, when a zero-length key gets extracted -+ * from an existing key. -+ */ -+ DBG_log("%s key is NULL", prefix); -+ } else { -+ DBG_log("%s key %p %d mechanism(type) %s", -+ prefix, key, PK11_GetKeyLength(key), -+ ckm_to_string(PK11_GetMechanism(key))); -+ if (DBGP(DBG_PRIVATE)) { -+ chunk_t chunk = chunk_from_symkey(prefix, key); -+ DBG_dump_chunk(prefix, chunk); -+ freeanychunk(chunk); -+ } else { -+ DBG_log("%s contents are private", prefix); -+ } -+ } -+} -+ -+/* -+ * XXX: Is there any documentation on this generic operation? -+ */ -+static PK11SymKey *merge_symkey_bytes(PK11SymKey *base_key, -+ const void *bytes, size_t sizeof_bytes, -+ CK_MECHANISM_TYPE derive, -+ CK_MECHANISM_TYPE target) -+{ -+ passert(sizeof_bytes > 0); -+ CK_KEY_DERIVATION_STRING_DATA string = { -+ .pData = (void *)bytes, -+ .ulLen = sizeof_bytes, -+ }; -+ SECItem param = { -+ .data = (unsigned char*)&string, -+ .len = sizeof(string), -+ }; -+ CK_ATTRIBUTE_TYPE operation = CKA_DERIVE; -+ int key_size = 0; -+ -+ DBG(DBG_CRYPT, -+ DBG_log("derive %s using %s", ckm_to_string(derive), -+ ckm_to_string(target)); -+ DBG_dump_symkey("base", base_key); -+ DBG_dump("data", bytes, sizeof_bytes)); -+ PK11SymKey *result = PK11_Derive(base_key, derive, ¶m, target, -+ operation, key_size); -+ DBG(DBG_CRYPT, DBG_dump_symkey("result", result)); -+ -+ return result; -+} -+ -+/* -+ * SYMKEY I/O operations. -+ * -+ * SYMKEY_FROM_CHUNK uses the SCRATCH key as a secure starting point -+ * for creating the key. -+ */ -+ -+PK11SymKey *symkey_from_bytes(PK11SymKey *scratch, const void *bytes, -+ size_t sizeof_bytes) -+{ -+ PK11SymKey *tmp = merge_symkey_bytes(scratch, bytes, sizeof_bytes, -+ CKM_CONCATENATE_DATA_AND_BASE, -+ CKM_EXTRACT_KEY_FROM_KEY); -+ passert(tmp != NULL); -+ PK11SymKey *key = key_from_symkey_bytes(tmp, 0, sizeof_bytes); -+ passert(key != NULL); -+ free_any_symkey(__func__, &tmp); -+ return key; -+} -+ -+PK11SymKey *symkey_from_chunk(PK11SymKey *scratch, chunk_t chunk) -+{ -+ return symkey_from_bytes(scratch, chunk.ptr, chunk.len); -+} -+ -+/* -+ * Concatenate two pieces of keying material creating a -+ * new SYMKEY object. -+ */ -+ -+PK11SymKey *concat_symkey_symkey(const struct hash_desc *hasher, -+ PK11SymKey *lhs, PK11SymKey *rhs) -+{ -+ CK_OBJECT_HANDLE keyhandle = PK11_GetSymKeyHandle(rhs); -+ /* give the parameters explicit names - there are too many */ -+ PK11SymKey *base_key = lhs; -+ CK_MECHANISM_TYPE derive = CKM_CONCATENATE_BASE_AND_KEY; -+ SECItem param = { -+ .data = (unsigned char*)&keyhandle, -+ .len = sizeof(keyhandle) -+ }; -+ CK_MECHANISM_TYPE target = nss_key_derivation_mech(hasher); -+ CK_ATTRIBUTE_TYPE operation = CKA_DERIVE; -+ int key_size = 0; -+ -+ DBG(DBG_CRYPT, -+ DBG_log("concate symkey(base) symkey(key) target %s", -+ ckm_to_string(target)); -+ DBG_dump_symkey("base", lhs); -+ DBG_dump_symkey("key", rhs)); -+ PK11SymKey *result = PK11_Derive(base_key, derive, ¶m, target, -+ operation, key_size); -+ DBG(DBG_CRYPT, DBG_dump_symkey("result", result)); -+ -+ return result; -+} -+ -+PK11SymKey *concat_symkey_bytes(const struct hash_desc *hasher, -+ PK11SymKey *lhs, const void *rhs, -+ size_t sizeof_rhs) -+{ -+ CK_MECHANISM_TYPE mechanism = nss_key_derivation_mech(hasher); -+ return merge_symkey_bytes(lhs, rhs, sizeof_rhs, -+ CKM_CONCATENATE_BASE_AND_DATA, -+ mechanism); -+} -+ -+PK11SymKey *concat_symkey_chunk(const struct hash_desc *hasher, -+ PK11SymKey *lhs, chunk_t rhs) -+{ -+ return concat_symkey_bytes(hasher, lhs, rhs.ptr, rhs.len); -+} -+ -+PK11SymKey *concat_symkey_byte(const struct hash_desc *hasher, -+ PK11SymKey *lhs, uint8_t rhs) -+{ -+ return concat_symkey_bytes(hasher, lhs, &rhs, sizeof(rhs)); -+} -+ -+/* -+ * Append new keying material to an existing key; replace the existing -+ * key with the result. -+ * -+ * Use this to chain a series of concat operations. -+ */ -+ -+void append_symkey_symkey(const struct hash_desc *hasher, -+ PK11SymKey **lhs, PK11SymKey *rhs) -+{ -+ PK11SymKey *newkey = concat_symkey_symkey(hasher, *lhs, rhs); -+ free_any_symkey(__func__, lhs); -+ *lhs = newkey; -+} -+ -+void append_symkey_bytes(const struct hash_desc *hasher, -+ PK11SymKey **lhs, const void *rhs, -+ size_t sizeof_rhs) -+{ -+ PK11SymKey *newkey = concat_symkey_bytes(hasher, *lhs, -+ rhs, sizeof_rhs); -+ free_any_symkey(__func__, lhs); -+ *lhs = newkey; -+} -+ -+void append_symkey_chunk(const struct hash_desc *hasher, -+ PK11SymKey **lhs, chunk_t rhs) -+{ -+ append_symkey_bytes(hasher, lhs, rhs.ptr, rhs.len); -+} -+ -+void append_symkey_byte(const struct hash_desc *hasher, -+ PK11SymKey **lhs, uint8_t rhs) -+{ -+ append_symkey_bytes(hasher, lhs, &rhs, sizeof(rhs)); -+} -+ -+/* -+ * Extract raw-bytes from a SYMKEY. -+ * -+ * Offset into the SYMKEY is in either BITS or BYTES. -+ */ -+ -+static PK11SymKey *key_from_key_bits(PK11SymKey *base_key, -+ CK_MECHANISM_TYPE target, -+ CK_FLAGS flags, -+ size_t next_bit, size_t key_size) -+{ -+ /* spell out all the parameters */ -+ CK_EXTRACT_PARAMS bs = next_bit; -+ SECItem param = { -+ .data = (unsigned char*)&bs, -+ .len = sizeof(bs), -+ }; -+ CK_MECHANISM_TYPE derive = CKM_EXTRACT_KEY_FROM_KEY; -+ CK_ATTRIBUTE_TYPE operation = CKA_FLAGS_ONLY; -+ -+ DBG(DBG_CRYPT, -+ DBG_log("%s key from base key bits %zd length %zd flags 0x%lx", -+ ckm_to_string(target), next_bit, key_size, flags); -+ DBG_dump_symkey("base key", base_key)); -+ PK11SymKey *result = PK11_DeriveWithFlags(base_key, derive, ¶m, -+ target, operation, -+ key_size, flags); -+ DBG(DBG_CRYPT, DBG_dump_symkey("result", result)); -+ -+ return result; -+} -+ -+void *bytes_from_symkey_bits(const char *name, -+ PK11SymKey *source_key, size_t next_bit, -+ void *bytes, size_t sizeof_bytes) -+{ -+ DBG(DBG_CRYPT, -+ DBG_log("%s: extracting %zd bytes starting at bit %zd from symkey %p into %p", -+ name, sizeof_bytes, next_bit, source_key, bytes)); -+ if (sizeof_bytes == 0) { -+ return NULL; -+ } -+ PK11SymKey *sym_key = key_from_key_bits(source_key, -+ CKM_VENDOR_DEFINED, 0, -+ next_bit, sizeof_bytes); -+ if (sym_key == NULL) { -+ loglog(RC_LOG_SERIOUS, "NSS key-from-key failed while generating %s", name); -+ return NULL; -+ } -+ SECStatus s = PK11_ExtractKeyValue(sym_key); -+ if (s != SECSuccess) { -+ loglog(RC_LOG_SERIOUS, "NSS: PK11_ExtractKeyValue failed while generating %s", name); -+ return NULL; -+ } -+ /* Internal structure address, do not free. */ -+ SECItem *data = PK11_GetKeyData(sym_key); -+ if (data == NULL) { -+ loglog(RC_LOG_SERIOUS, "NSS: PK11_GetKeyData failed while generating %s", name); -+ return NULL; -+ } -+ DBG(DBG_CRYPT, -+ DBG_log("chunk_from_symkey: %s: extracted len %d bytes at %p", -+ name, data->len, data->data)); -+ if (data->len != sizeof_bytes) { -+ loglog(RC_LOG_SERIOUS, "NSS: PK11_GetKeyData returned wrong number of bytes while generating %s", name); -+ return NULL; -+ } -+ /* Only alloc, when all looks good. */ -+ if (bytes == NULL) { -+ bytes = alloc_bytes(sizeof_bytes, name); -+ DBG(DBG_CRYPT, -+ DBG_log("%s: allocated %zd bytes at %p", -+ name, sizeof_bytes, bytes)); -+ } -+ memcpy(bytes, data->data, sizeof_bytes); -+ DBG(DBG_PRIVATE, DBG_dump(name, bytes, sizeof_bytes)); -+ free_any_symkey(__func__, &sym_key); -+ -+ return bytes; -+} -+ -+void *bytes_from_symkey_bytes(const char *name, PK11SymKey *source_key, -+ size_t next_byte, void *bytes, -+ size_t sizeof_bytes) -+{ -+ return bytes_from_symkey_bits(name, source_key, -+ next_byte * BITS_PER_BYTE, -+ bytes, sizeof_bytes); -+} -+ -+chunk_t chunk_from_symkey_bits(const char *name, PK11SymKey *source_key, -+ size_t next_bit, size_t sizeof_chunk) -+{ -+ void *bytes = bytes_from_symkey_bits(name, source_key, next_bit, -+ NULL, sizeof_chunk); -+ if (bytes == NULL) { -+ return empty_chunk; -+ } -+ chunk_t chunk; -+ setchunk(chunk, bytes, sizeof_chunk); -+ return chunk; -+} -+ -+chunk_t chunk_from_symkey_bytes(const char *name, PK11SymKey *source_key, -+ size_t next_byte, size_t sizeof_chunk) -+{ -+ return chunk_from_symkey_bits(name, source_key, -+ next_byte * BITS_PER_BYTE, sizeof_chunk); -+} -+ -+chunk_t chunk_from_symkey(const char *name, PK11SymKey *source_key) -+{ -+ return chunk_from_symkey_bits(name, source_key, 0, -+ PK11_GetKeyLength(source_key)); -+} -+ -+/* -+ * Extract SIZEOF_SYMKEY bytes of keying material as an ENCRYPTER key -+ * (i.e., can be used to encrypt/decrypt data using ENCRYPTER). -+ * -+ * Offset into the SYMKEY is in either BITS or BYTES. -+ */ -+ -+PK11SymKey *encrypt_key_from_symkey_bits(PK11SymKey *source_key, -+ const struct encrypt_desc *encrypter, -+ size_t next_bit, size_t sizeof_symkey) -+{ -+ return key_from_key_bits(source_key, -+ nss_encryption_mech(encrypter), -+ CKF_ENCRYPT | CKF_DECRYPT, -+ next_bit, sizeof_symkey); -+} -+ -+PK11SymKey *encrypt_key_from_symkey_bytes(PK11SymKey *source_key, -+ const struct encrypt_desc *encrypter, -+ size_t next_byte, size_t sizeof_symkey) -+{ -+ return encrypt_key_from_symkey_bits(source_key, encrypter, -+ next_byte * BITS_PER_BYTE, -+ sizeof_symkey); -+} -+ -+/* -+ * Extract SIZEOF_KEY bytes of keying material as a KEY. It inherits -+ * the BASE_KEYs type. Good for hash keys. -+ * -+ * Offset into the SYMKEY is in either BITS or BYTES. -+ */ -+ -+PK11SymKey *key_from_symkey_bits(PK11SymKey *base_key, -+ size_t next_bit, size_t key_size) -+{ -+ CK_EXTRACT_PARAMS bs = next_bit; -+ SECItem param = { -+ .data = (unsigned char*)&bs, -+ .len = sizeof(bs), -+ }; -+ CK_MECHANISM_TYPE derive = CKM_EXTRACT_KEY_FROM_KEY; -+ CK_MECHANISM_TYPE target = CKM_CONCATENATE_BASE_AND_DATA; -+ CK_ATTRIBUTE_TYPE operation = CKA_DERIVE; -+ /* XXX: can this use key_from_key_bits? */ -+ -+ DBG(DBG_CRYPT, -+ DBG_log("%s key from symkey(base key) bits %zd length %zd", -+ ckm_to_string(target), -+ next_bit, key_size); -+ DBG_dump_symkey("base key", base_key)); -+ PK11SymKey *result = PK11_Derive(base_key, derive, ¶m, target, -+ operation, key_size); -+ DBG(DBG_CRYPT, DBG_dump_symkey("result", result)); -+ -+ return result; -+} -+ -+PK11SymKey *key_from_symkey_bytes(PK11SymKey *source_key, -+ size_t next_byte, size_t sizeof_key) -+{ -+ return key_from_symkey_bits(source_key, -+ next_byte * BITS_PER_BYTE, -+ sizeof_key); -+} -+ -+/* -+ * Run HASHER on the key. -+ * -+ * This assumes that NSS works. Based on old code, 3.14 may have had -+ * problems with SHA-2. -+ */ -+PK11SymKey *hash_symkey(const struct hash_desc *hasher, -+ PK11SymKey *base_key) -+{ -+ CK_MECHANISM_TYPE derive = nss_key_derivation_mech(hasher); -+ SECItem *param = NULL; -+ CK_MECHANISM_TYPE target = CKM_CONCATENATE_BASE_AND_KEY; -+ CK_ATTRIBUTE_TYPE operation = CKA_DERIVE; -+ int key_size = 0; -+ -+ DBG(DBG_CRYPT, -+ DBG_log("%s hash symkey(base key)", ckm_to_string(derive)); -+ DBG_dump_symkey("base key", base_key)); -+ PK11SymKey *result = PK11_Derive(base_key, derive, param, target, -+ operation, key_size); -+ DBG(DBG_CRYPT, DBG_dump_symkey("result", result)); -+ -+ return result; -+} -+ -+/* -+ * XOR a symkey with a chunk. -+ * -+ * XXX: hmac.c had very similar code, only, instead of -+ * target=CKM_CONCATENATE_BASE_AND_DATA it used -+ * target=hasher-to-ckm(hasher). -+ * -+ * hasher-to-ckm maped hasher->common.alg_id to CMK vis: OAKLEY_MD5 -> -+ * CKM_MD5; OAKLEY_SHA1 -> CKM_SHA_1; OAKLEY_SHA2_256 -> CKM_SHA256; -+ * OAKLEY_SHA2_384 -> CKM_SHA384; OAKLEY_SHA2_512 -> CKM_SHA512; only -+ * in the default case it would set target to 0x80000000???? -+ */ -+PK11SymKey *xor_symkey_chunk(PK11SymKey *lhs, chunk_t rhs) -+{ -+ return merge_symkey_bytes(lhs, rhs.ptr, rhs.len, -+ CKM_XOR_BASE_AND_DATA, -+ CKM_CONCATENATE_BASE_AND_DATA); -+} -diff -Naur libreswan-3.12-orig/programs/pluto/crypt_symkey.h libreswan-3.12/programs/pluto/crypt_symkey.h ---- libreswan-3.12-orig/programs/pluto/crypt_symkey.h 1969-12-31 19:00:00.000000000 -0500 -+++ libreswan-3.12/programs/pluto/crypt_symkey.h 2015-05-06 11:45:32.920301417 -0400 -@@ -0,0 +1,131 @@ -+/* -+ * SYMKEY manipulation functions, for libreswan -+ * -+ * Copyright (C) 2015 Andrew Cagney -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * for more details. -+ */ -+ -+#ifndef crypt_symkey_h -+#define crypt_symkey_h -+ -+#include -+#include -+#include "lswalloc.h" -+ -+struct hash_desc; -+struct encrypt_desc; -+ -+void DBG_dump_symkey(const char *prefix, PK11SymKey *key); -+ -+/* -+ * Free any symkey and then stomp on the pointer. -+ */ -+void free_any_symkey(const char *prefix, PK11SymKey **key); -+ -+/* -+ * Use SCRATCH key as a secure starting point for creating the key -+ * from the raw bytes, or chunk. -+ */ -+ -+PK11SymKey *symkey_from_bytes(PK11SymKey *scratch, const void *bytes, -+ size_t sizeof_bytes); -+ -+PK11SymKey *symkey_from_chunk(PK11SymKey *scratch, chunk_t chunk); -+ -+/* -+ * Concatenate two pieces of keying material creating a -+ * new SYMKEY object. -+ */ -+PK11SymKey *concat_symkey_symkey(const struct hash_desc *hasher, -+ PK11SymKey *lhs, PK11SymKey *rhs); -+PK11SymKey *concat_symkey_bytes(const struct hash_desc *hasher, -+ PK11SymKey *lhs, const void *rhs, -+ size_t sizeof_rhs); -+PK11SymKey *concat_symkey_chunk(const struct hash_desc *hasher, -+ PK11SymKey *lhs, chunk_t rhs); -+PK11SymKey *concat_symkey_byte(const struct hash_desc *hasher, -+ PK11SymKey *lhs, uint8_t rhs); -+ -+/* -+ * Append new keying material to an existing key; replace the existing -+ * key with the result. -+ * -+ * Use this to chain a series of concat operations. -+ */ -+void append_symkey_symkey(const struct hash_desc *hasher, -+ PK11SymKey **lhs, PK11SymKey *rhs); -+void append_symkey_bytes(const struct hash_desc *hasher, -+ PK11SymKey **lhs, const void *rhs, -+ size_t sizeof_rhs); -+void append_symkey_chunk(const struct hash_desc *hasher, -+ PK11SymKey **lhs, chunk_t rhs); -+void append_symkey_byte(const struct hash_desc *hasher, -+ PK11SymKey **lhs, uint8_t rhs); -+ -+/* -+ * Extract raw-bytes from a SYMKEY. -+ * -+ * Offset into the SYMKEY is in either BITS or BYTES. -+ * -+ * bytes_from_ has a querk where, if BYTES is NULL, the buffer is -+ * allocated. -+ */ -+void *bytes_from_symkey_bits(const char *name, PK11SymKey *source_key, -+ size_t next_bit, void *bytes, -+ size_t sizeof_bytes); -+void *bytes_from_symkey_bytes(const char *name, PK11SymKey *source_key, -+ size_t next_byte, void *bytes, -+ size_t sizeof_bytes); -+chunk_t chunk_from_symkey_bits(const char *name, PK11SymKey *source_key, -+ size_t next_bit, size_t sizeof_chunk); -+chunk_t chunk_from_symkey_bytes(const char *name, PK11SymKey *source_key, -+ size_t next_byte, size_t sizeof_chunk); -+chunk_t chunk_from_symkey(const char *name, PK11SymKey *source_key); -+ -+/* -+ * Extract SIZEOF_SYMKEY bytes of keying material as an ENCRYPTER key -+ * (i.e., can be used to encrypt/decrypt data using ENCRYPTER). -+ * -+ * Offset into the SYMKEY is in either BITS or BYTES. -+ */ -+PK11SymKey *encrypt_key_from_symkey_bytes(PK11SymKey *source_key, -+ const struct encrypt_desc *encrypter, -+ size_t next_byte, size_t sizeof_symkey); -+PK11SymKey *encrypt_key_from_symkey_bits(PK11SymKey *source_key, -+ const struct encrypt_desc *encrypter, -+ size_t next_bit, size_t sizeof_symkey); -+ -+/* -+ * Extract SIZEOF_KEY bytes of keying material as a KEY. It inherits -+ * the BASE_KEYs type. Good for hash keys. -+ * -+ * Offset into the SYMKEY is in either BITS or BYTES. -+ */ -+PK11SymKey *key_from_symkey_bits(PK11SymKey *base_key, -+ size_t next_bit, size_t key_size); -+PK11SymKey *key_from_symkey_bytes(PK11SymKey *source_key, -+ size_t next_byte, size_t sizeof_key); -+ -+/* -+ * Hash a symkey using HASHER. -+ * -+ * This gets used by the PRF when the BASE_KEY is too long. -+ */ -+PK11SymKey *hash_symkey(const struct hash_desc *hasher, -+ PK11SymKey *base_key); -+ -+/* -+ * XOR a symkey with a chunk. -+ */ -+PK11SymKey *xor_symkey_chunk(PK11SymKey *lhs, chunk_t rhs); -+ -+#endif -diff -Naur libreswan-3.12-orig/programs/pluto/ctr_test_vectors.c libreswan-3.12/programs/pluto/ctr_test_vectors.c ---- libreswan-3.12-orig/programs/pluto/ctr_test_vectors.c 2015-05-06 11:44:21.564466307 -0400 -+++ libreswan-3.12/programs/pluto/ctr_test_vectors.c 2015-05-06 11:45:32.921301428 -0400 -@@ -12,6 +12,7 @@ - - #include "nss.h" - #include "pk11pub.h" -+#include "crypt_symkey.h" - - struct ctr_test_vector { - // CK_MECHANISM_TYPE cipher_mechanism; -@@ -203,7 +204,8 @@ - ok = 0; - } - -- PK11_FreeSymKey(sym_key); -+ /* Clean up. */ -+ free_any_symkey("sym_key", &sym_key); - DBG(DBG_CRYPT, DBG_log("test_ctr_vector: %s %s", - test->description, ok ? "passed" : "failed")); - return ok; -diff -Naur libreswan-3.12-orig/programs/pluto/gcm_test_vectors.c libreswan-3.12/programs/pluto/gcm_test_vectors.c ---- libreswan-3.12-orig/programs/pluto/gcm_test_vectors.c 2015-05-06 11:44:21.584466542 -0400 -+++ libreswan-3.12/programs/pluto/gcm_test_vectors.c 2015-05-06 11:45:32.921301428 -0400 -@@ -24,6 +24,7 @@ - - #include "nss.h" - #include "pk11pub.h" -+#include "crypt_symkey.h" - - struct gcm_test_vector { - const char *key; -@@ -165,14 +166,16 @@ - } - - freeanychunk(salted_iv); -- freeanychunk(wire_iv); - freeanychunk(salt); -- freeanychunk(tag); -+ freeanychunk(wire_iv); -+ freeanychunk(aad); - freeanychunk(plaintext); - freeanychunk(ciphertext); -+ freeanychunk(tag); - freeanychunk(text_and_tag); - -- PK11_FreeSymKey(sym_key); -+ /* Clean up. */ -+ free_any_symkey("sym_key", &sym_key); - DBG(DBG_CRYPT, DBG_log("test_gcm_vector: %s", ok ? "passed" : "failed")); - return ok; - } -diff -Naur libreswan-3.12-orig/programs/pluto/hmac.c libreswan-3.12/programs/pluto/hmac.c ---- libreswan-3.12-orig/programs/pluto/hmac.c 2014-11-06 22:52:50.000000000 -0500 -+++ libreswan-3.12/programs/pluto/hmac.c 2015-05-06 11:45:32.921301428 -0400 -@@ -5,8 +5,9 @@ - * Copyright (C) 2009 Paul Wouters - * Copyright (C) 2010-2012 Avesh Agarwal - * Copyright (C) 2012 Paul Wouters -- * Copyright (C) 2012-2013 Paul Wouters -+ * Copyright (C) 2012-2015 Paul Wouters - * Copyright (C) 2013 D. Hugh Redelmeier -+ * Copyright (C) 2015, 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 -@@ -40,272 +41,42 @@ - #include - #include "lswconf.h" - #include "lswlog.h" -+#include "crypt_symkey.h" -+#include "crypt_prf.h" - - /* HMAC package - * rfc2104.txt specifies how HMAC works. - */ - --static CK_MECHANISM_TYPE nss_hash_mech(const struct hash_desc *hasher); --static SECOidTag nss_hash_oid(const struct hash_desc *hasher); -- - void hmac_init(struct hmac_ctx *ctx, - const struct hash_desc *h, - /*const*/ PK11SymKey *symkey) /* NSS doesn't like const! */ - { -- SECStatus status; -- PK11SymKey -- *tkey1, -- *tkey2; -- unsigned int klen = PK11_GetKeyLength(symkey); -- chunk_t hmac_opad, hmac_ipad, hmac_pad; -- -- ctx->h = h; -+ /* -+ * Note: The SYMKEY passed to crypt_prf_init is used to -+ * generate secure keying material from nothing. -+ * crypt_prf_init_symkey() establishes the actual key. -+ */ -+ ctx->prf = crypt_prf_init("hmac", h, symkey); - ctx->hmac_digest_len = h->hash_digest_len; -- -- /* DBG(DBG_CRYPT, DBG_log("NSS: hmac init")); */ -- -- hmac_opad = hmac_pads(HMAC_OPAD, h->hash_block_size); -- hmac_ipad = hmac_pads(HMAC_IPAD, h->hash_block_size); -- hmac_pad = hmac_pads(0x00, h->hash_block_size - klen); -- -- if (klen > h->hash_block_size) { -- tkey1 = PK11_Derive_lsw(symkey, nss_key_derivation_mech(h), -- NULL, -- CKM_CONCATENATE_BASE_AND_DATA, -- CKA_DERIVE, -- 0); -- } else { -- tkey1 = symkey; -- } -- -- tkey2 = pk11_derive_wrapper_lsw(tkey1, CKM_CONCATENATE_BASE_AND_DATA, -- hmac_pad, -- CKM_XOR_BASE_AND_DATA, CKA_DERIVE, -- h->hash_block_size); -- passert(tkey2 != NULL); -- -- ctx->ikey = pk11_derive_wrapper_lsw(tkey2, CKM_XOR_BASE_AND_DATA, -- hmac_ipad, nss_hash_mech(h), -- CKA_DIGEST, 0); -- passert(ctx->ikey != NULL); -- -- ctx->okey = pk11_derive_wrapper_lsw(tkey2, CKM_XOR_BASE_AND_DATA, -- hmac_opad, nss_hash_mech(h), -- CKA_DIGEST, 0); -- passert(ctx->okey != NULL); -- -- if (tkey1 != symkey) -- PK11_FreeSymKey(tkey1); -- PK11_FreeSymKey(tkey2); -- -- freeanychunk(hmac_opad); -- freeanychunk(hmac_ipad); -- freeanychunk(hmac_pad); -- ctx->ctx_nss = PK11_CreateDigestContext(nss_hash_oid(h)); -- passert(ctx->ctx_nss != NULL); -- -- status = PK11_DigestBegin(ctx->ctx_nss); -- passert(status == SECSuccess); -- -- status = PK11_DigestKey(ctx->ctx_nss, ctx->ikey); -- passert(status == SECSuccess); -+ crypt_prf_init_symkey("symkey", ctx->prf, symkey); -+ crypt_prf_update(ctx->prf); - } - - void hmac_update(struct hmac_ctx *ctx, - const u_char *data, size_t data_len) - { -- DBG(DBG_CRYPT, DBG_dump("hmac_update data value: ", data, data_len)); -- if (data_len > 0) { -- SECStatus status; -- -- DBG(DBG_CRYPT, DBG_log("hmac_update: inside if")); -- status = PK11_DigestOp(ctx->ctx_nss, data, data_len); -- DBG(DBG_CRYPT, DBG_log("hmac_update: after digest")); -- passert(status == SECSuccess); -- DBG(DBG_CRYPT, DBG_log("hmac_update: after assert")); -- } -+ crypt_prf_update_bytes("data", ctx->prf, data, data_len); - } - - void hmac_final(u_char *output, struct hmac_ctx *ctx) - { -- unsigned int outlen; -- SECStatus status; -- -- status = PK11_DigestFinal(ctx->ctx_nss, output, &outlen, -- ctx->hmac_digest_len); -- passert(status == SECSuccess); -- passert(outlen == ctx->hmac_digest_len); -- PK11_DestroyContext(ctx->ctx_nss, PR_TRUE); -- ctx->ctx_nss = NULL; -- -- ctx->ctx_nss = PK11_CreateDigestContext(nss_hash_oid(ctx->h)); -- passert(ctx->ctx_nss != NULL); -- -- status = PK11_DigestBegin(ctx->ctx_nss); -- passert(status == SECSuccess); -- -- status = PK11_DigestKey(ctx->ctx_nss, ctx->okey); -- passert(status == SECSuccess); -- -- status = PK11_DigestOp(ctx->ctx_nss, output, outlen); -- passert(status == SECSuccess); -- -- status = PK11_DigestFinal(ctx->ctx_nss, output, &outlen, -- ctx->hmac_digest_len); -- passert(status == SECSuccess); -- passert(outlen == ctx->hmac_digest_len); -- PK11_DestroyContext(ctx->ctx_nss, PR_TRUE); -- -- if (ctx->ikey != NULL) -- PK11_FreeSymKey(ctx->ikey); -- if (ctx->okey != NULL) -- PK11_FreeSymKey(ctx->okey); -- /* DBG(DBG_CRYPT, DBG_log("NSS: hmac final end")); */ --} -- --static SECOidTag nss_hash_oid(const struct hash_desc *hasher) --{ -- SECOidTag mechanism; -- -- switch (hasher->common.algo_id) { -- case OAKLEY_MD5: -- mechanism = SEC_OID_MD5; -- break; -- case OAKLEY_SHA1: -- mechanism = SEC_OID_SHA1; -- break; -- case OAKLEY_SHA2_256: -- mechanism = SEC_OID_SHA256; -- break; -- case OAKLEY_SHA2_384: -- mechanism = SEC_OID_SHA384; -- break; -- case OAKLEY_SHA2_512: -- mechanism = SEC_OID_SHA512; -- break; -- default: -- libreswan_log("NSS: key derivation mechanism (hasher->common.algo_id=%d not supported", -- hasher->common.algo_id); -- mechanism = 0; /* ??? what should we do to recover? */ -- break; -- } -- return mechanism; --} -- --static CK_MECHANISM_TYPE nss_hash_mech(const struct hash_desc *hasher) --{ -- CK_MECHANISM_TYPE mechanism; -- -- switch (hasher->common.algo_id) { -- case OAKLEY_MD5: -- mechanism = CKM_MD5; -- break; -- case OAKLEY_SHA1: -- mechanism = CKM_SHA_1; -- break; -- case OAKLEY_SHA2_256: -- mechanism = CKM_SHA256; -- break; -- case OAKLEY_SHA2_384: -- mechanism = CKM_SHA384; -- break; -- case OAKLEY_SHA2_512: -- mechanism = CKM_SHA512; -- break; -- default: -- /* ??? surely this requires more than a DBG entry! */ -- DBG(DBG_CRYPT, -- DBG_log("NSS: key derivation mechanism not supported")); -- mechanism = 0x80000000; /* ??? what should we do to recover? */ -- break; -- } -- return mechanism; --} -- --PK11SymKey *pk11_derive_wrapper_lsw(PK11SymKey *base, -- CK_MECHANISM_TYPE mechanism, -- chunk_t data, CK_MECHANISM_TYPE target, -- CK_ATTRIBUTE_TYPE operation, int keySize) --{ -- CK_KEY_DERIVATION_STRING_DATA string; -- SECItem param; -- -- string.pData = data.ptr; -- string.ulLen = data.len; -- param.data = (unsigned char*)&string; -- param.len = sizeof(string); -- -- return PK11_Derive(base, mechanism, ¶m, target, operation, -- keySize); -+ crypt_prf_final_bytes(ctx->prf, output, ctx->hmac_digest_len); - } - --/* MUST BE THREAD-SAFE */ --PK11SymKey *PK11_Derive_lsw(PK11SymKey *base, CK_MECHANISM_TYPE mechanism, -- SECItem *param, CK_MECHANISM_TYPE target, -- CK_ATTRIBUTE_TYPE operation, int keysize) --{ -- if (param == NULL && keysize == 0) { -- SECOidTag oid; -- PK11Context *ctx; -- unsigned char dkey[HMAC_BUFSIZE * 2]; -- SECItem dkey_param; -- SECStatus status; -- unsigned int len; -- CK_EXTRACT_PARAMS bs; -- chunk_t dkey_chunk; -- -- switch (mechanism) { -- case CKM_SHA256_KEY_DERIVATION: -- oid = SEC_OID_SHA256; -- break; -- case CKM_SHA384_KEY_DERIVATION: -- oid = SEC_OID_SHA384; -- break; -- case CKM_SHA512_KEY_DERIVATION: -- oid = SEC_OID_SHA512; -- break; -- default: -- return PK11_Derive(base, mechanism, param, target, -- operation, keysize); -- } -- -- ctx = PK11_CreateDigestContext(oid); -- passert(ctx != NULL); -- status = PK11_DigestBegin(ctx); -- passert(status == SECSuccess); -- status = PK11_DigestKey(ctx, base); -- passert(status == SECSuccess); -- status = PK11_DigestFinal(ctx, dkey, &len, sizeof dkey); -- passert(status == SECSuccess); -- PK11_DestroyContext(ctx, PR_TRUE); -- -- dkey_chunk.ptr = dkey; -- dkey_chunk.len = len; -- -- PK11SymKey *tkey1 = pk11_derive_wrapper_lsw(base, -- CKM_CONCATENATE_DATA_AND_BASE, dkey_chunk, CKM_EXTRACT_KEY_FROM_KEY, CKA_DERIVE, -- 0); -- passert(tkey1 != NULL); -- -- bs = 0; -- dkey_param.data = (unsigned char*)&bs; -- dkey_param.len = sizeof(bs); -- PK11SymKey *tkey2 = PK11_Derive(tkey1, -- CKM_EXTRACT_KEY_FROM_KEY, -- &dkey_param, target, operation, -- len); -- passert(tkey2 != NULL); -- -- if (tkey1 != NULL) -- PK11_FreeSymKey(tkey1); -- -- return tkey2; -- -- } else { -- return PK11_Derive(base, mechanism, param, target, operation, -- keysize); -- } --} -+/* -+ * XXX: This should be moved to crypt_symkey.c and made private. -+ */ - - CK_MECHANISM_TYPE nss_key_derivation_mech(const struct hash_desc *hasher) - { -@@ -335,6 +106,11 @@ - return mechanism; - } - -+/* -+ * XXX: This has nothing to do with HMAC; it should be made part of -+ * the chunk_t library code. -+ */ -+ - chunk_t hmac_pads(u_char val, unsigned int len) - { - chunk_t ret; -@@ -346,31 +122,3 @@ - - return ret; - } -- --void nss_symkey_log(PK11SymKey *key, const char *msg) --{ -- if (key == NULL) { -- /* ??? should we print this even if !DBG_CRYPT? */ -- DBG_log("NULL key %s", msg); -- } else { -- DBG(DBG_CRYPT, { -- DBG_log("computed key %s with length =%d", msg, -- PK11_GetKeyLength(key)); -- -- if (!PK11_IsFIPS()) { -- SECStatus status = PK11_ExtractKeyValue(key); -- -- if (status == SECSuccess) { -- SECItem *keydata = PK11_GetKeyData(key); -- -- DBG_dump("value: ", keydata->data, -- keydata->len); -- -- SECITEM_FreeItem(keydata, PR_TRUE); /* ??? this was commented out. Why? */ -- } else { -- DBG_log("unobtainable key %s", msg); -- } -- } -- }); -- } --} -diff -Naur libreswan-3.12-orig/programs/pluto/hostpair.c libreswan-3.12/programs/pluto/hostpair.c ---- libreswan-3.12-orig/programs/pluto/hostpair.c 2014-11-06 22:52:50.000000000 -0500 -+++ libreswan-3.12/programs/pluto/hostpair.c 2015-05-06 11:45:32.922301440 -0400 -@@ -286,7 +286,7 @@ - */ - passert(p == *pp); - -- terminate_connection(p->name); -+ // terminate_connection(p->name); - p->interface = NULL; - - *pp = p->hp_next; /* advance *pp */ -diff -Naur libreswan-3.12-orig/programs/pluto/ike_alg_aes.c libreswan-3.12/programs/pluto/ike_alg_aes.c ---- libreswan-3.12-orig/programs/pluto/ike_alg_aes.c 2015-05-06 11:44:21.609466836 -0400 -+++ libreswan-3.12/programs/pluto/ike_alg_aes.c 2015-05-06 11:45:47.617471739 -0400 -@@ -410,7 +410,11 @@ - - void ike_alg_aes_init(void) - { -- bool fips = libreswan_fipsmode(); -+#ifdef FIPS_CHECK -+ bool fips = libreswan_fipsproduct() || libreswan_fipskernel(); -+#else -+ bool fips = FALSE; -+#endif - if (!fips && !test_aes_cbc(&algo_aes_cbc)) { - loglog(RC_LOG_SERIOUS, "CKM_AES_CBC: test failure"); - exit_pluto(6); -diff -Naur libreswan-3.12-orig/programs/pluto/ike_alg.c libreswan-3.12/programs/pluto/ike_alg.c ---- libreswan-3.12-orig/programs/pluto/ike_alg.c 2015-05-06 11:44:21.585466554 -0400 -+++ libreswan-3.12/programs/pluto/ike_alg.c 2015-05-06 11:45:32.922301440 -0400 -@@ -322,3 +322,53 @@ - ret = lookup_group(c->alg_info_esp->esp_pfsgroup); - return ret; - } -+ -+CK_MECHANISM_TYPE nss_encryption_mech(const struct encrypt_desc *encrypter) -+{ -+ /* the best wey have for "undefined" */ -+ CK_MECHANISM_TYPE mechanism = CKM_VENDOR_DEFINED; -+ -+ switch (encrypter->common.algo_id) { -+ case OAKLEY_3DES_CBC: -+ mechanism = CKM_DES3_CBC; -+ break; -+#ifdef NOT_YET -+ case OAKLEY_CAST_CBC: -+ mechanism = CKM_CAST5_CBC: -+ break; -+#endif -+ case OAKLEY_AES_CBC: -+ mechanism = CKM_AES_CBC; -+ break; -+ case OAKLEY_CAMELLIA_CBC: -+ mechanism = CKM_CAMELLIA_CBC; -+ break; -+ case OAKLEY_AES_CTR: -+ mechanism = CKM_AES_CTR; -+ break; -+#ifdef NOT_YET -+ case OAKLEY_AES_CCM_8: -+ case OAKLEY_AES_CCM_12: -+ case OAKLEY_AES_CCM_16: -+ mechanism = CKM_AES_CCM; -+ break; -+#endif -+ case OAKLEY_AES_GCM_8: -+ case OAKLEY_AES_GCM_12: -+ case OAKLEY_AES_GCM_16: -+ mechanism = CKM_AES_GCM; -+ break; -+#ifdef NOT_YET -+ case OAKLEY_TWOFISH_CBC: -+ mechanism = CKM_TWOFISH_CBC; -+ break; -+#endif -+ default: -+ loglog(RC_LOG_SERIOUS, -+ "NSS: Unsupported encryption mechanism for %s", -+ strip_prefix(enum_name(&oakley_enc_names, -+ encrypter->common.algo_id), "OAKLEY_")); -+ break; -+ } -+ return mechanism; -+} -diff -Naur libreswan-3.12-orig/programs/pluto/ike_alg_camellia.c libreswan-3.12/programs/pluto/ike_alg_camellia.c ---- libreswan-3.12-orig/programs/pluto/ike_alg_camellia.c 2015-05-06 11:44:21.610466848 -0400 -+++ libreswan-3.12/programs/pluto/ike_alg_camellia.c 2015-05-06 11:45:47.617471739 -0400 -@@ -95,7 +95,7 @@ - void ike_alg_camellia_init(void) - { - #ifdef FIPS_CHECK -- bool fips = libreswan_fipsmode(); -+ bool fips = libreswan_fipsproduct() || libreswan_fipskernel(); - #else - bool fips = FALSE; - #endif -diff -Naur libreswan-3.12-orig/programs/pluto/ike_alg.h libreswan-3.12/programs/pluto/ike_alg.h ---- libreswan-3.12-orig/programs/pluto/ike_alg.h 2015-05-06 11:44:21.585466554 -0400 -+++ libreswan-3.12/programs/pluto/ike_alg.h 2015-05-06 11:45:32.922301440 -0400 -@@ -186,5 +186,6 @@ - extern void ike_alg_sha2_init(void); - #endif - -+CK_MECHANISM_TYPE nss_encryption_mech(const struct encrypt_desc *encrypter); - - #endif /* _IKE_ALG_H */ -diff -Naur libreswan-3.12-orig/programs/pluto/ikev1_prf.c libreswan-3.12/programs/pluto/ikev1_prf.c ---- libreswan-3.12-orig/programs/pluto/ikev1_prf.c 1969-12-31 19:00:00.000000000 -0500 -+++ libreswan-3.12/programs/pluto/ikev1_prf.c 2015-05-06 11:45:32.923301452 -0400 -@@ -0,0 +1,348 @@ -+/* -+ * Calculate IKEv1 prf and keying material, for libreswan -+ * -+ * Copyright (C) 2007 Michael C. Richardson -+ * Copyright (C) 2010 Paul Wouters -+ * Copyright (C) 2013 D. Hugh Redelmeier -+ * Copyright (C) 2015 Andrew Cagney -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * for more details. -+ */ -+ -+#include -+#include -+ -+#include "libreswan.h" -+#include "lswlog.h" -+#include "constants.h" -+#include "defs.h" -+#include "sysqueue.h" -+#include "crypto.h" -+#include "crypt_dh.h" -+#include "crypt_prf.h" -+#include "ikev1_prf.h" -+#include "ike_alg.h" -+#include "packet.h" -+#include "pluto_crypt.h" -+#include "crypt_symkey.h" -+ -+/* -+ * Compute: SKEYID = prf(Ni_b | Nr_b, g^xy) -+ * -+ * MUST BE THREAD-SAFE -+ */ -+PK11SymKey *ikev1_signature_skeyid(const struct hash_desc *hasher, -+ const chunk_t Ni, -+ const chunk_t Nr, -+ /*const*/ PK11SymKey *dh_secret /* NSS doesn't do const */) -+{ -+ struct crypt_prf *prf = crypt_prf_init("SKEYID sig", hasher, dh_secret); -+ /* key = Ni|Nr */ -+ crypt_prf_init_chunk("Ni", prf, Ni); -+ crypt_prf_init_chunk("Nr", prf, Nr); -+ /* seed = g^xy */ -+ crypt_prf_update(prf); -+ crypt_prf_update_symkey("g^xy", prf, dh_secret); -+ /* generate */ -+ return crypt_prf_final(prf); -+} -+ -+/* -+ * Compute: SKEYID = prf(pre-shared-key, Ni_b | Nr_b) -+ */ -+PK11SymKey *ikev1_pre_shared_key_skeyid(const struct hash_desc *hasher, -+ chunk_t pre_shared_key, -+ chunk_t Ni, chunk_t Nr, -+ PK11SymKey *scratch) -+{ -+ struct crypt_prf *prf = crypt_prf_init("SKEYID psk", hasher, scratch); -+ /* key = pre-shared-key */ -+ crypt_prf_init_chunk("psk", prf, pre_shared_key); -+ /* seed = Ni_b | Nr_b */ -+ crypt_prf_update(prf); -+ crypt_prf_update_chunk("Ni", prf, Ni); -+ crypt_prf_update_chunk("Nr", prf, Nr); -+ /* generate */ -+ return crypt_prf_final(prf); -+} -+ -+/* -+ * SKEYID_d = prf(SKEYID, g^xy | CKY-I | CKY-R | 0) -+ */ -+PK11SymKey *ikev1_skeyid_d(const struct hash_desc *hasher, -+ PK11SymKey *skeyid, -+ PK11SymKey *dh_secret, -+ chunk_t cky_i, chunk_t cky_r) -+{ -+ struct crypt_prf *prf = crypt_prf_init("SKEYID_d", hasher, dh_secret); -+ /* key = SKEYID */ -+ crypt_prf_init_symkey("SKEYID", prf, skeyid); -+ /* seed = g^xy | CKY-I | CKY-R | 0 */ -+ crypt_prf_update(prf); -+ crypt_prf_update_symkey("g^xy", prf, dh_secret); -+ crypt_prf_update_chunk("CKI_i", prf, cky_i); -+ crypt_prf_update_chunk("CKI_r", prf, cky_r); -+ crypt_prf_update_byte("0", prf, 0); -+ /* generate */ -+ return crypt_prf_final(prf); -+} -+ -+/* -+ * SKEYID_a = prf(SKEYID, SKEYID_d | g^xy | CKY-I | CKY-R | 1) -+ */ -+PK11SymKey *ikev1_skeyid_a(const struct hash_desc *hasher, -+ PK11SymKey *skeyid, -+ PK11SymKey *skeyid_d, PK11SymKey *dh_secret, -+ chunk_t cky_i, chunk_t cky_r) -+{ -+ struct crypt_prf *prf = crypt_prf_init("SKEYID_a", hasher, dh_secret); -+ /* key = SKEYID */ -+ crypt_prf_init_symkey("SKEYID", prf, skeyid); -+ /* seed = SKEYID_d | g^xy | CKY-I | CKY-R | 1 */ -+ crypt_prf_update(prf); -+ crypt_prf_update_symkey("SKEYID_d", prf, skeyid_d); -+ crypt_prf_update_symkey("g^xy", prf, dh_secret); -+ crypt_prf_update_chunk("CKI_i", prf, cky_i); -+ crypt_prf_update_chunk("CKI_r", prf, cky_r); -+ crypt_prf_update_byte("1", prf, 1); -+ /* generate */ -+ return crypt_prf_final(prf); -+} -+ -+/* -+ * SKEYID_e = prf(SKEYID, SKEYID_a | g^xy | CKY-I | CKY-R | 2) -+ */ -+PK11SymKey *ikev1_skeyid_e(const struct hash_desc *hasher, -+ PK11SymKey *skeyid, -+ PK11SymKey *skeyid_a, PK11SymKey *dh_secret, -+ chunk_t cky_i, chunk_t cky_r) -+{ -+ struct crypt_prf *prf = crypt_prf_init("SKEYID_e", hasher, dh_secret); -+ /* key = SKEYID */ -+ crypt_prf_init_symkey("SKEYID", prf, skeyid); -+ /* seed = SKEYID_a | g^xy | CKY-I | CKY-R | 2 */ -+ crypt_prf_update(prf); -+ crypt_prf_update_symkey("SKEYID_a", prf, skeyid_a); -+ crypt_prf_update_symkey("g^xy", prf, dh_secret); -+ crypt_prf_update_chunk("CKI_i", prf, cky_i); -+ crypt_prf_update_chunk("CKI_r", prf, cky_r); -+ crypt_prf_update_byte("2", prf, 2); -+ /* generate */ -+ return crypt_prf_final(prf); -+} -+ -+static PK11SymKey *appendix_b_keymat_e(const struct hash_desc *hasher, -+ const struct encrypt_desc *encrypter, -+ PK11SymKey *skeyid_e, -+ unsigned required_keymat) -+{ -+ if (PK11_GetKeyLength(skeyid_e) >= required_keymat) { -+ return encrypt_key_from_symkey_bytes(skeyid_e, encrypter, 0, -+ required_keymat); -+ } -+ /* K1 = prf(skeyid_e, 0) */ -+ PK11SymKey *keymat; -+ { -+ struct crypt_prf *prf = crypt_prf_init("appendix_b", -+ hasher, skeyid_e); -+ crypt_prf_init_symkey("SKEYID_e", prf, skeyid_e); -+ crypt_prf_update(prf); -+ crypt_prf_update_byte("0", prf, 0); -+ keymat = crypt_prf_final(prf); -+ } -+ -+ /* make a copy to keep things easy */ -+ PK11SymKey *old_k = key_from_symkey_bytes(keymat, 0, PK11_GetKeyLength(keymat)); -+ while (PK11_GetKeyLength(keymat) < required_keymat) { -+ /* Kn = prf(skeyid_e, Kn-1) */ -+ struct crypt_prf *prf = crypt_prf_init("SKEYID_e", hasher, skeyid_e); -+ crypt_prf_init_symkey("SKEYID_e", prf, skeyid_e); -+ crypt_prf_update(prf); -+ crypt_prf_update_symkey("old_k", prf, old_k); -+ PK11SymKey *new_k = crypt_prf_final(prf); -+ append_symkey_symkey(hasher, &keymat, new_k); -+ free_any_symkey("old_k#N", &old_k); -+ old_k = new_k; -+ } -+ free_any_symkey("old_k#final", &old_k); -+ PK11SymKey *cryptkey = encrypt_key_from_symkey_bytes(keymat, encrypter, 0, -+ required_keymat); -+ free_any_symkey("keymat", &keymat); -+ return cryptkey; -+} -+ -+/* Generate the SKEYID_* and new IV -+ * See draft-ietf-ipsec-ike-01.txt 4.1 -+ */ -+/* MUST BE THREAD-SAFE */ -+static void calc_skeyids_iv(struct pcr_skeyid_q *skq, -+ /*const*/ PK11SymKey *shared, /* NSS doesn't do const */ -+ const size_t keysize, /* = st->st_oakley.enckeylen/BITS_PER_BYTE; */ -+ PK11SymKey **skeyid_out, /* output */ -+ PK11SymKey **skeyid_d_out, /* output */ -+ PK11SymKey **skeyid_a_out, /* output */ -+ PK11SymKey **skeyid_e_out, /* output */ -+ chunk_t *new_iv, /* output */ -+ PK11SymKey **enc_key_out /* output */ -+ ) -+{ -+ oakley_auth_t auth = skq->auth; -+ oakley_hash_t hash = skq->prf_hash; -+ const struct hash_desc *hasher = crypto_get_hasher(hash); -+ chunk_t ni; -+ chunk_t nr; -+ chunk_t gi; -+ chunk_t gr; -+ chunk_t icookie; -+ chunk_t rcookie; -+ const struct encrypt_desc *encrypter = skq->encrypter; -+ -+ /* this doesn't allocate any memory */ -+ setchunk_from_wire(gi, skq, &skq->gi); -+ setchunk_from_wire(gr, skq, &skq->gr); -+ setchunk_from_wire(ni, skq, &skq->ni); -+ setchunk_from_wire(nr, skq, &skq->nr); -+ setchunk_from_wire(icookie, skq, &skq->icookie); -+ setchunk_from_wire(rcookie, skq, &skq->rcookie); -+ -+ /* Generate the SKEYID */ -+ PK11SymKey *skeyid; -+ switch (auth) { -+ case OAKLEY_PRESHARED_KEY: -+ { -+ chunk_t pss; -+ -+ setchunk_from_wire(pss, skq, &skq->pss); -+ skeyid = ikev1_pre_shared_key_skeyid(hasher, pss, -+ ni, nr, shared); -+ } -+ break; -+ -+ case OAKLEY_RSA_SIG: -+ skeyid = ikev1_signature_skeyid(hasher, ni, nr, shared); -+ break; -+ -+ /* Not implemented */ -+ case OAKLEY_DSS_SIG: -+ case OAKLEY_RSA_ENC: -+ case OAKLEY_RSA_REVISED_MODE: -+ case OAKLEY_ECDSA_P256: -+ case OAKLEY_ECDSA_P384: -+ case OAKLEY_ECDSA_P521: -+ default: -+ bad_case(auth); -+ } -+ -+ /* generate SKEYID_* from SKEYID */ -+ PK11SymKey *skeyid_d = ikev1_skeyid_d(hasher, skeyid, shared, -+ icookie, rcookie); -+ PK11SymKey *skeyid_a = ikev1_skeyid_a(hasher, skeyid, skeyid_d, -+ shared, icookie, rcookie); -+ PK11SymKey *skeyid_e = ikev1_skeyid_e(hasher, skeyid, skeyid_a, -+ shared, icookie, rcookie); -+ -+ PK11SymKey *enc_key = appendix_b_keymat_e(hasher, encrypter, -+ skeyid_e, keysize); -+ -+ *skeyid_out = skeyid; -+ *skeyid_d_out = skeyid_d; -+ *skeyid_a_out = skeyid_a; -+ *skeyid_e_out = skeyid_e; -+ *enc_key_out = enc_key; -+ -+ DBG(DBG_CRYPT, DBG_log("NSS: pointers skeyid_d %p, skeyid_a %p, skeyid_e %p, enc_key %p", -+ skeyid_d, skeyid_a, skeyid_e, enc_key)); -+ -+ /* generate IV */ -+ { -+ union hash_ctx hash_ctx; -+ -+ new_iv->len = hasher->hash_digest_len; -+ new_iv->ptr = alloc_bytes(new_iv->len, "calculated new iv"); -+ -+ DBG(DBG_CRYPT, { -+ DBG_dump_chunk("DH_i:", gi); -+ DBG_dump_chunk("DH_r:", gr); -+ }); -+ hasher->hash_init(&hash_ctx); -+ hasher->hash_update(&hash_ctx, gi.ptr, gi.len); -+ hasher->hash_update(&hash_ctx, gr.ptr, gr.len); -+ hasher->hash_final(new_iv->ptr, &hash_ctx); -+ DBG(DBG_CRYPT, DBG_log("end of IV generation")); -+ } -+} -+ -+/* MUST BE THREAD-SAFE */ -+void calc_dh_iv(struct pluto_crypto_req *r) -+{ -+ struct pcr_skeyid_r *skr = &r->pcr_d.dhr; -+ struct pcr_skeyid_q dhq; -+ const struct oakley_group_desc *group; -+ PK11SymKey *shared; -+ chunk_t g; -+ SECKEYPrivateKey *ltsecret; -+ PK11SymKey -+ *skeyid, -+ *skeyid_d, -+ *skeyid_a, -+ *skeyid_e, -+ *enc_key; -+ chunk_t new_iv; -+ SECKEYPublicKey *pubk; -+ -+ /* copy the request, since the reply will re-use the memory of the r->pcr_d.dhq */ -+ memcpy(&dhq, &r->pcr_d.dhq, sizeof(r->pcr_d.dhq)); -+ -+ /* clear out the reply */ -+ zero(skr); -+ INIT_WIRE_ARENA(*skr); -+ -+ group = lookup_group(dhq.oakley_group); -+ passert(group != NULL); -+ -+ ltsecret = dhq.secret; -+ pubk = dhq.pubk; -+ -+ /* now calculate the (g^x)(g^y) --- -+ * need gi on responder, gr on initiator -+ */ -+ -+ setchunk_from_wire(g, &dhq, dhq.role == O_RESPONDER ? &dhq.gi : &dhq.gr); -+ -+ DBG(DBG_CRYPT, -+ DBG_dump_chunk("peer's g: ", g)); -+ -+ shared = calc_dh_shared(g, ltsecret, group, pubk); -+ -+ zero(&new_iv); -+ -+ /* okay, so now calculate IV */ -+ calc_skeyids_iv(&dhq, -+ shared, -+ dhq.key_size, -+ &skeyid, -+ &skeyid_d, -+ &skeyid_a, -+ &skeyid_e, -+ &new_iv, -+ &enc_key); -+ -+ skr->shared = shared; -+ skr->skeyid = skeyid; -+ skr->skeyid_d = skeyid_d; -+ skr->skeyid_a = skeyid_a; -+ skr->skeyid_e = skeyid_e; -+ skr->enc_key = enc_key; -+ -+ -+ WIRE_CLONE_CHUNK(*skr, new_iv, new_iv); -+ freeanychunk(new_iv); -+} -diff -Naur libreswan-3.12-orig/programs/pluto/ikev1_prf.h libreswan-3.12/programs/pluto/ikev1_prf.h ---- libreswan-3.12-orig/programs/pluto/ikev1_prf.h 1969-12-31 19:00:00.000000000 -0500 -+++ libreswan-3.12/programs/pluto/ikev1_prf.h 2015-05-06 11:45:32.923301452 -0400 -@@ -0,0 +1,66 @@ -+/* -+ * Calculate IKEv1 prf and keying material, for libreswan -+ * -+ * Copyright (C) 2007 Michael C. Richardson -+ * Copyright (C) 2010 Paul Wouters -+ * Copyright (C) 2013 D. Hugh Redelmeier -+ * Copyright (C) 2015 Andrew Cagney -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * for more details. -+ */ -+ -+#ifndef ikev1_prf_h -+#define ikev1_prf_h -+ -+/* -+ * IKE SA SKEYID for authentication -+ * -+ * Be warned, this is not DSS (even though NIST call it Digital -+ * Signature Algorithm). It is used by RSA-SIG. -+ */ -+PK11SymKey *ikev1_signature_skeyid(const struct hash_desc *hasher, -+ const chunk_t Ni_b, const chunk_t Nr_b, -+ PK11SymKey *dh_secret); -+ -+PK11SymKey *ikev1_pre_shared_key_skeyid(const struct hash_desc *hasher, -+ chunk_t pre_shared_key, -+ chunk_t Ni_b, chunk_t Nr_b, -+ PK11SymKey *scratch); -+ -+/* -+ * Authenticated keying material. -+ * -+ * Perhaps this should just return a struct? -+ */ -+ -+PK11SymKey *ikev1_skeyid_d(const struct hash_desc *hasher, -+ PK11SymKey *skeyid, -+ PK11SymKey *dh_secret, -+ chunk_t cky_i, chunk_t cky_r); -+ -+PK11SymKey *ikev1_skeyid_a(const struct hash_desc *hasher, -+ PK11SymKey *skeyid, -+ PK11SymKey *skeyid_d, PK11SymKey *dh_secret, -+ chunk_t cky_i, chunk_t cky_r); -+ -+PK11SymKey *ikev1_skeyid_e(const struct hash_desc *hasher, -+ PK11SymKey *skeyid, -+ PK11SymKey *skeyid_a, PK11SymKey *dh_secret, -+ chunk_t cky_i, chunk_t cky_r); -+ -+/* -+ * Old way. -+ */ -+struct pluto_crypto_req; -+ -+void calc_dh_iv(struct pluto_crypto_req *r); -+ -+#endif -diff -Naur libreswan-3.12-orig/programs/pluto/ikev1_quick.c libreswan-3.12/programs/pluto/ikev1_quick.c ---- libreswan-3.12-orig/programs/pluto/ikev1_quick.c 2014-11-06 22:52:50.000000000 -0500 -+++ libreswan-3.12/programs/pluto/ikev1_quick.c 2015-05-06 11:45:32.923301452 -0400 -@@ -70,6 +70,7 @@ - #include "plutoalg.h" - - #include "pluto_crypt.h" -+#include "crypt_prf.h" - #include "ikev1.h" - #include "ikev1_quick.h" - #include "ikev1_continuations.h" -@@ -470,13 +471,8 @@ - - for (i = 0;; ) { - if (st->st_shared_nss != NULL) { -- /* PFS: include the g^xy */ -- SECStatus s; -- -- s = PK11_DigestKey(ctx_me.ctx_nss, st->st_shared_nss); -- passert(s == SECSuccess); -- s = PK11_DigestKey(ctx_peer.ctx_nss, st->st_shared_nss); -- passert(s == SECSuccess); -+ crypt_prf_update_symkey("g^xy", ctx_me.prf, st->st_shared_nss); -+ crypt_prf_update_symkey("g^xy", ctx_peer.prf, st->st_shared_nss); - } - hmac_update(&ctx_me, &protoid, sizeof(protoid)); - hmac_update(&ctx_peer, &protoid, sizeof(protoid)); -diff -Naur libreswan-3.12-orig/programs/pluto/ikev2_crypto.c libreswan-3.12/programs/pluto/ikev2_crypto.c ---- libreswan-3.12-orig/programs/pluto/ikev2_crypto.c 2014-11-06 22:52:50.000000000 -0500 -+++ libreswan-3.12/programs/pluto/ikev2_crypto.c 2015-05-06 11:45:32.924301463 -0400 -@@ -49,15 +49,16 @@ - #include "crypto.h" /* requires sha1.h and md5.h */ - #include "demux.h" - #include "ikev2.h" --#include "ikev2_prfplus.h" -+#include "ikev2_prf.h" - #include "ike_alg.h" - #include "alg_info.h" - #include "kernel_alg.h" -+#include "crypt_symkey.h" -+#include "ikev2_prf.h" -+ - - void ikev2_derive_child_keys(struct state *st, enum phase1_role role) - { -- struct v2prf_stuff childsacalc; -- - chunk_t ikeymat, rkeymat; - /* ??? note assumption that AH and ESP cannot be combined */ - struct ipsec_proto_info *ipi = -@@ -81,17 +82,6 @@ - passert(ei != NULL); - ipi->attrs.transattrs.ei = ei; - -- zero(&childsacalc); -- childsacalc.prf_hasher = st->st_oakley.prf_hasher; -- -- setchunk(childsacalc.ni, st->st_ni.ptr, st->st_ni.len); -- setchunk(childsacalc.nr, st->st_nr.ptr, st->st_nr.len); -- childsacalc.spii.len = 0; -- childsacalc.spir.len = 0; -- -- childsacalc.counter[0] = 1; -- childsacalc.skeyseed = st->st_skey_d_nss; -- - /* ??? no account is taken of AH */ - /* transid is same as esp_ealg_id */ - switch (ei->transid) { -@@ -150,11 +140,20 @@ - * salt (AES_GCM_SALT_BYTES) - */ - -- v2genbytes(&ikeymat, ipi->keymat_len, -- "initiator keys", &childsacalc); -- -- v2genbytes(&rkeymat, ipi->keymat_len, -- "responder keys", &childsacalc); -+ chunk_t ni; -+ chunk_t nr; -+ setchunk(ni, st->st_ni.ptr, st->st_ni.len); -+ setchunk(nr, st->st_nr.ptr, st->st_nr.len); -+ -+ PK11SymKey *keymat = ikev2_child_sa_keymat(st->st_oakley.prf_hasher, -+ st->st_skey_d_nss, -+ NULL/*dh*/, ni, nr, -+ ipi->keymat_len * 2); -+ ikeymat = chunk_from_symkey_bytes("initiator keys", keymat, -+ 0, ipi->keymat_len); -+ rkeymat = chunk_from_symkey_bytes("initiator keys", keymat, -+ ipi->keymat_len, ipi->keymat_len); -+ free_any_symkey("keymat", &keymat); - - if (role != O_INITIATOR) { - DBG(DBG_CRYPT, { -diff -Naur libreswan-3.12-orig/programs/pluto/ikev2_prf.c libreswan-3.12/programs/pluto/ikev2_prf.c ---- libreswan-3.12-orig/programs/pluto/ikev2_prf.c 1969-12-31 19:00:00.000000000 -0500 -+++ libreswan-3.12/programs/pluto/ikev2_prf.c 2015-05-06 11:45:32.924301463 -0400 -@@ -0,0 +1,405 @@ -+/* -+ * Calculate IKEv2 prf and keying material, for libreswan -+ * -+ * Copyright (C) 2007 Michael C. Richardson -+ * Copyright (C) 2010 Paul Wouters -+ * Copyright (C) 2013 D. Hugh Redelmeier -+ * Copyright (C) 2015 Andrew Cagney -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * for more details. -+ * -+ * This code was developed with the support of Redhat corporation. -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include "sysdep.h" -+#include "constants.h" -+#include "defs.h" -+#include "packet.h" -+#include "demux.h" -+#include "crypto.h" -+#include "rnd.h" -+#include "state.h" -+#include "pluto_crypt.h" -+#include "lswlog.h" -+#include "log.h" -+#include "timer.h" -+#include "ike_alg.h" -+#include "id.h" -+#include "secrets.h" -+#include "keys.h" -+#include "ikev2_prf.h" -+#include "crypt_prf.h" -+#include "crypt_dh.h" -+#include "crypt_symkey.h" -+ -+/* -+ * IKEv2 - RFC4306 2.14 SKEYSEED - calculation. -+ */ -+ -+/* MUST BE THREAD-SAFE */ -+static void calc_skeyseed_v2(struct pcr_skeyid_q *skq, -+ PK11SymKey *shared, -+ const size_t key_size, -+ const size_t salt_size, -+ PK11SymKey **skeyseed_out, -+ PK11SymKey **SK_d_out, -+ PK11SymKey **SK_ai_out, -+ PK11SymKey **SK_ar_out, -+ PK11SymKey **SK_ei_out, -+ PK11SymKey **SK_er_out, -+ PK11SymKey **SK_pi_out, -+ PK11SymKey **SK_pr_out, -+ chunk_t *initiator_salt_out, -+ chunk_t *responder_salt_out -+ ) -+ -+{ -+ DBG(DBG_CRYPT, DBG_log("NSS: Started key computation")); -+ -+ PK11SymKey -+ *skeyseed_k, -+ *SK_d_k, -+ *SK_ai_k, -+ *SK_ar_k, -+ *SK_ei_k, -+ *SK_er_k, -+ *SK_pi_k, -+ *SK_pr_k; -+ chunk_t initiator_salt; -+ chunk_t responder_salt; -+ -+ -+ -+ /* this doesn't take any memory, it's just moving pointers around */ -+ chunk_t ni; -+ chunk_t nr; -+ chunk_t spii; -+ chunk_t spir; -+ setchunk_from_wire(ni, skq, &skq->ni); -+ setchunk_from_wire(nr, skq, &skq->nr); -+ setchunk_from_wire(spii, skq, &skq->icookie); -+ setchunk_from_wire(spir, skq, &skq->rcookie); -+ -+ DBG(DBG_CONTROLMORE, -+ DBG_log("calculating skeyseed using prf=%s integ=%s cipherkey-size=%zu salt-size=%zu", -+ enum_name(&ikev2_trans_type_prf_names, skq->prf_hash), -+ enum_name(&ikev2_trans_type_integ_names, skq->integ_hash), -+ key_size, salt_size)); -+ -+ const struct hash_desc *prf_hasher = (struct hash_desc *) -+ ikev2_alg_find(IKE_ALG_HASH, skq->prf_hash); -+ passert(prf_hasher != NULL); -+ -+ const struct encrypt_desc *encrypter = skq->encrypter; -+ passert(encrypter != NULL); -+ -+ /* generate SKEYSEED from key=(Ni|Nr), hash of shared */ -+ skeyseed_k = ikev2_ike_sa_skeyseed(prf_hasher, ni, nr, shared); -+ passert(skeyseed_k != NULL); -+ -+ /* now we have to generate the keys for everything */ -+ -+ /* need to know how many bits to generate */ -+ /* SK_d needs PRF hasher key bytes */ -+ /* SK_p needs PRF hasher*2 key bytes */ -+ /* SK_e needs key_size*2 key bytes */ -+ /* ..._salt needs salt_size*2 bytes */ -+ /* SK_a needs integ's key size*2 bytes */ -+ -+ int skd_bytes = prf_hasher->hash_key_size; -+ int skp_bytes = prf_hasher->hash_key_size; -+ const struct hash_desc *integ_hasher = -+ (struct hash_desc *)ikev2_alg_find(IKE_ALG_INTEG, skq->integ_hash); -+ int integ_size = integ_hasher != NULL ? integ_hasher->hash_key_size : 0; -+ size_t total_keysize = skd_bytes + 2*skp_bytes + 2*key_size + 2*salt_size + 2*integ_size; -+ PK11SymKey *finalkey = ikev2_ike_sa_keymat(prf_hasher, skeyseed_k, -+ ni, nr, spii, spir, -+ total_keysize); -+ -+ size_t next_byte = 0; -+ -+ SK_d_k = key_from_symkey_bytes(finalkey, next_byte, skd_bytes); -+ next_byte += skd_bytes; -+ -+ SK_ai_k = key_from_symkey_bytes(finalkey, next_byte, integ_size); -+ next_byte += integ_size; -+ -+ SK_ar_k = key_from_symkey_bytes(finalkey, next_byte, integ_size); -+ next_byte += integ_size; -+ -+ /* The encryption key and salt are extracted together. */ -+ SK_ei_k = encrypt_key_from_symkey_bytes(finalkey, encrypter, -+ next_byte, key_size); -+ next_byte += key_size; -+ initiator_salt = chunk_from_symkey_bytes("initiator salt", finalkey, -+ next_byte, salt_size); -+ next_byte += salt_size; -+ -+ /* The encryption key and salt are extracted together. */ -+ SK_er_k = encrypt_key_from_symkey_bytes(finalkey, encrypter, -+ next_byte, key_size); -+ next_byte += key_size; -+ responder_salt = chunk_from_symkey_bytes("responder salt", finalkey, -+ next_byte, salt_size); -+ next_byte += salt_size; -+ -+ SK_pi_k = key_from_symkey_bytes(finalkey, next_byte, skp_bytes); -+ -+ -+ -+ next_byte += skp_bytes; -+ -+ SK_pr_k = key_from_symkey_bytes(finalkey, next_byte, skp_bytes); -+ -+ -+ -+ next_byte += skp_bytes; -+ -+ DBG(DBG_CRYPT, -+ DBG_log("NSS ikev2: finished computing individual keys for IKEv2 SA")); -+ free_any_symkey("finalkey", &finalkey); -+ -+ *skeyseed_out = skeyseed_k; -+ *SK_d_out = SK_d_k; -+ *SK_ai_out = SK_ai_k; -+ *SK_ar_out = SK_ar_k; -+ *SK_ei_out = SK_ei_k; -+ *SK_er_out = SK_er_k; -+ *SK_pi_out = SK_pi_k; -+ *SK_pr_out = SK_pr_k; -+ *initiator_salt_out = initiator_salt; -+ *responder_salt_out = responder_salt; -+ -+ -+ -+ DBG(DBG_PRIVATE, -+ DBG_log("calc_skeyseed_v2 pointers: shared %p, skeyseed %p, SK_d %p, SK_ai %p, SK_ar %p, SK_ei %p, SK_er %p, SK_pi %p, SK_pr %p", -+ shared, skeyseed_k, SK_d_k, SK_ai_k, SK_ar_k, SK_ei_k, SK_er_k, SK_pi_k, SK_pr_k); -+ DBG_dump_chunk("calc_skeyseed_v2 initiator salt", initiator_salt); -+ DBG_dump_chunk("calc_skeyseed_v2 responder salt", responder_salt); -+ ); -+ -+} -+ -+/* MUST BE THREAD-SAFE */ -+void calc_dh_v2(struct pluto_crypto_req *r) -+{ -+ struct pcr_skeycalc_v2_r *skr = &r->pcr_d.dhv2; -+ struct pcr_skeyid_q dhq; -+ const struct oakley_group_desc *group; -+ PK11SymKey *shared; -+ chunk_t g; -+ SECKEYPrivateKey *ltsecret; -+ PK11SymKey *skeyseed; -+ PK11SymKey -+ *SK_d, -+ *SK_ai, -+ *SK_ar, -+ *SK_ei, -+ *SK_er, -+ *SK_pi, -+ *SK_pr; -+ chunk_t initiator_salt; -+ chunk_t responder_salt; -+ -+ -+ SECKEYPublicKey *pubk; -+ -+ /* copy the request, since the reply will re-use the memory of the r->pcr_d.dhq */ -+ memcpy(&dhq, &r->pcr_d.dhq, sizeof(r->pcr_d.dhq)); -+ -+ /* clear out the reply */ -+ zero(skr); -+ INIT_WIRE_ARENA(*skr); -+ -+ group = lookup_group(dhq.oakley_group); -+ passert(group != NULL); -+ -+ ltsecret = dhq.secret; -+ pubk = dhq.pubk; -+ -+ /* now calculate the (g^x)(g^y) --- need gi on responder, gr on initiator */ -+ -+ setchunk_from_wire(g, &dhq, dhq.role == O_RESPONDER ? &dhq.gi : &dhq.gr); -+ -+ DBG(DBG_CRYPT, DBG_dump_chunk("peer's g: ", g)); -+ -+ shared = calc_dh_shared(g, ltsecret, group, pubk); -+ -+ /* okay, so now all the shared key material */ -+ calc_skeyseed_v2(&dhq, /* input */ -+ shared, /* input */ -+ dhq.key_size, /* input */ -+ dhq.salt_size, /* input */ -+ -+ &skeyseed, /* output */ -+ &SK_d, /* output */ -+ &SK_ai, /* output */ -+ &SK_ar, /* output */ -+ &SK_ei, /* output */ -+ &SK_er, /* output */ -+ &SK_pi, /* output */ -+ &SK_pr, /* output */ -+ &initiator_salt, /* output */ -+ &responder_salt /* output */ -+ ); -+ -+ -+ skr->shared = shared; -+ skr->skeyseed = skeyseed; -+ skr->skeyid_d = SK_d; -+ skr->skeyid_ai = SK_ai; -+ skr->skeyid_ar = SK_ar; -+ skr->skeyid_ei = SK_ei; -+ skr->skeyid_er = SK_er; -+ skr->skeyid_pi = SK_pi; -+ skr->skeyid_pr = SK_pr; -+ skr->skey_initiator_salt = initiator_salt; -+ skr->skey_responder_salt = responder_salt; -+ -+ -+} -+ -+static PK11SymKey *ikev2_prfplus(const struct hash_desc *hasher, -+ PK11SymKey *key, PK11SymKey *seed, -+ size_t required_keymat) -+{ -+ uint8_t count = 1; -+ -+ /* T1(prfplus) = prf(KEY, SEED|1) */ -+ PK11SymKey *prfplus; -+ { -+ struct crypt_prf *prf = crypt_prf_init("prf+0", -+ hasher, key); -+ crypt_prf_init_symkey("key", prf, key); -+ crypt_prf_update(prf); -+ crypt_prf_update_symkey("seed", prf, seed); -+ crypt_prf_update_byte("1++", prf, count++); -+ prfplus = crypt_prf_final(prf); -+ } -+ -+ /* make a copy to keep things easy */ -+ PK11SymKey *old_t = key_from_symkey_bytes(prfplus, 0, PK11_GetKeyLength(prfplus)); -+ while (PK11_GetKeyLength(prfplus) < required_keymat) { -+ /* Tn = prf(KEY, Tn-1|SEED|n) */ -+ struct crypt_prf *prf = crypt_prf_init("prf+N", -+ hasher, key); -+ crypt_prf_init_symkey("key", prf, key); -+ crypt_prf_update(prf); -+ crypt_prf_update_symkey("old_t", prf, old_t); -+ crypt_prf_update_symkey("seed", prf, seed); -+ crypt_prf_update_byte("N++", prf, count++); -+ PK11SymKey *new_t = crypt_prf_final(prf); -+ append_symkey_symkey(hasher, &prfplus, new_t); -+ free_any_symkey("old_t[N]", &old_t); -+ old_t = new_t; -+ } -+ free_any_symkey("old_t[final]", &old_t); -+ return prfplus; -+} -+ -+/* -+ * SKEYSEED = prf(Ni | Nr, g^ir) -+ */ -+PK11SymKey *ikev2_ike_sa_skeyseed(const struct hash_desc *hasher, -+ const chunk_t Ni, const chunk_t Nr, -+ PK11SymKey *dh_secret) -+{ -+ struct crypt_prf *prf = crypt_prf_init("ike sa SKEYSEED", -+ hasher, dh_secret); -+ /* key = Ni|Nr */ -+ crypt_prf_init_chunk("Ni", prf, Ni); -+ crypt_prf_init_chunk("Nr", prf, Nr); -+ /* seed = g^ir */ -+ crypt_prf_update(prf); -+ /* generate */ -+ crypt_prf_update_symkey("g^ir", prf, dh_secret); -+ return crypt_prf_final(prf); -+} -+ -+/* -+ * SKEYSEED = prf(SK_d (old), g^ir (new) | Ni | Nr) -+ */ -+PK11SymKey *ikev2_ike_sa_rekey_skeyseed(const struct hash_desc *hasher, -+ PK11SymKey *SK_d_old, -+ PK11SymKey *new_dh_secret, -+ const chunk_t Ni, const chunk_t Nr) -+{ -+ struct crypt_prf *prf = crypt_prf_init("ike sa rekey skeyseed", -+ hasher, new_dh_secret); -+ /* key = SK_d (old) */ -+ crypt_prf_init_symkey("SK_d (old)", prf, SK_d_old); -+ /* seed: g^ir (new) | Ni | Nr) */ -+ crypt_prf_update(prf); -+ crypt_prf_update_symkey("g^ir (new)", prf, new_dh_secret); -+ crypt_prf_update_chunk("Ni", prf, Ni); -+ crypt_prf_update_chunk("Nr", prf, Nr); -+ /* generate */ -+ return crypt_prf_final(prf); -+} -+ -+/* -+ * Compute: prf+ (SKEYSEED, Ni | Nr | SPIi | SPIr) -+ */ -+PK11SymKey *ikev2_ike_sa_keymat(const struct hash_desc *hasher, -+ PK11SymKey *skeyseed, -+ const chunk_t Ni, const chunk_t Nr, -+ const chunk_t SPIi, const chunk_t SPIr, -+ size_t required_bytes) -+{ -+ PK11SymKey *data = symkey_from_chunk(skeyseed, Ni); -+ append_symkey_chunk(hasher, &data, Nr); -+ append_symkey_chunk(hasher, &data, SPIi); -+ append_symkey_chunk(hasher, &data, SPIr); -+ PK11SymKey *prfplus = ikev2_prfplus(hasher, skeyseed, data, -+ required_bytes); -+ free_any_symkey(__func__, &data); -+ return prfplus; -+} -+ -+/* -+ * Compute: prf+(SK_d, [ g^ir (new) | ] Ni | Nr) -+ */ -+PK11SymKey *ikev2_child_sa_keymat(const struct hash_desc *hasher, -+ PK11SymKey *SK_d, -+ PK11SymKey *new_dh_secret, -+ const chunk_t Ni, const chunk_t Nr, -+ size_t required_bytes) -+{ -+ PK11SymKey *data; -+ if (new_dh_secret == NULL) { -+ data = symkey_from_chunk(SK_d, Ni); -+ append_symkey_chunk(hasher, &data, Nr); -+ } else { -+ data = concat_symkey_chunk(hasher, new_dh_secret, Ni); -+ append_symkey_chunk(hasher, &data, Nr); -+ } -+ PK11SymKey *prfplus = ikev2_prfplus(hasher, SK_d, data, -+ required_bytes); -+ free_any_symkey(__func__, &data); -+ return prfplus; -+} -diff -Naur libreswan-3.12-orig/programs/pluto/ikev2_prf.h libreswan-3.12/programs/pluto/ikev2_prf.h ---- libreswan-3.12-orig/programs/pluto/ikev2_prf.h 1969-12-31 19:00:00.000000000 -0500 -+++ libreswan-3.12/programs/pluto/ikev2_prf.h 2015-05-06 11:45:32.924301463 -0400 -@@ -0,0 +1,58 @@ -+/* -+ * Calculate IKEv2 prf and keying material, for libreswan -+ * -+ * Copyright (C) 2007 Michael C. Richardson -+ * Copyright (C) 2010 Paul Wouters -+ * Copyright (C) 2013 D. Hugh Redelmeier -+ * Copyright (C) 2015 Andrew Cagney -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * for more details. -+ */ -+ -+#ifndef _IKEV2_PRF_H -+#define _IKEV2_PRF_H -+ -+/* -+ * IKE SA -+ */ -+PK11SymKey *ikev2_ike_sa_skeyseed(const struct hash_desc *prf_hasher, -+ const chunk_t Ni, const chunk_t Nr, -+ PK11SymKey *dh_secret); -+ -+PK11SymKey *ikev2_ike_sa_rekey_skeyseed(const struct hash_desc *prf_hasher, -+ PK11SymKey *old_SK_d, -+ PK11SymKey *new_dh_secret, -+ const chunk_t Ni, const chunk_t Nr); -+ -+PK11SymKey *ikev2_ike_sa_keymat(const struct hash_desc *prf_hasher, -+ PK11SymKey *skeyseed, -+ const chunk_t Ni, const chunk_t Nr, -+ const chunk_t SPIi, const chunk_t SPIr, -+ size_t required_bytes); -+ -+/* -+ * Child SA -+ */ -+PK11SymKey *ikev2_child_sa_keymat(const struct hash_desc *prf_hasher, -+ PK11SymKey *SK_d, -+ PK11SymKey *new_dh_secret, -+ const chunk_t Ni, const chunk_t Nr, -+ size_t required_bytes); -+ -+/* -+ * Old way ... -+ */ -+ -+struct pluto_crypto_req; -+ -+void calc_dh_v2(struct pluto_crypto_req *r); -+ -+#endif -diff -Naur libreswan-3.12-orig/programs/pluto/ikev2_prfplus.c libreswan-3.12/programs/pluto/ikev2_prfplus.c ---- libreswan-3.12-orig/programs/pluto/ikev2_prfplus.c 2014-11-06 22:52:50.000000000 -0500 -+++ libreswan-3.12/programs/pluto/ikev2_prfplus.c 1969-12-31 19:00:00.000000000 -0500 -@@ -1,106 +0,0 @@ --/* -- * Cryptographic helper function - calculate prf+() for ikev2 -- * -- * Copyright (C) 2007 Michael C. Richardson -- * Copyright (C) 2010 Paul Wouters -- * Copyright (C) 2013 D. Hugh Redelmeier -- * -- * This program is free software; you can redistribute it and/or modify it -- * under the terms of the GNU General Public License as published by the -- * Free Software Foundation; either version 2 of the License, or (at your -- * option) any later version. See . -- * -- * This program is distributed in the hope that it will be useful, but -- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -- * for more details. -- * -- * This code was developed with the support of Redhat corporation. -- * -- */ -- --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include -- --#include -- --#include "sysdep.h" --#include "constants.h" --#include "defs.h" --#include "packet.h" --#include "demux.h" --#include "crypto.h" --#include "rnd.h" --#include "state.h" --#include "pluto_crypt.h" --#include "lswlog.h" --#include "log.h" --#include "timer.h" --#include "ike_alg.h" --#include "id.h" --#include "secrets.h" --#include "keys.h" --#include "ikev2_prfplus.h" -- --static void v2prfplus(struct v2prf_stuff *vps) --{ -- struct hmac_ctx ctx; -- -- hmac_init(&ctx, vps->prf_hasher, vps->skeyseed); -- hmac_update_chunk(&ctx, vps->t); -- hmac_update_chunk(&ctx, vps->ni); -- hmac_update_chunk(&ctx, vps->nr); -- hmac_update_chunk(&ctx, vps->spii); -- hmac_update_chunk(&ctx, vps->spir); -- hmac_update(&ctx, vps->counter, 1); -- hmac_final_chunk(vps->t, "skeyseed_t1", &ctx); -- DBG(DBG_CRYPT, { -- char b[20]; -- snprintf(b, sizeof(b), "prf+[%u]:", vps->counter[0]); -- DBG_dump_chunk(b, vps->t); -- }); -- -- vps->counter[0]++; -- vps->availbytes = vps->t.len; -- vps->nextbytes = 0; --} -- --void v2genbytes(chunk_t *need, -- unsigned int needed, const char *name, -- struct v2prf_stuff *vps) --{ -- u_char *target; -- -- need->ptr = alloc_bytes(needed, name); -- need->len = needed; -- target = need->ptr; -- -- while (needed > vps->availbytes) { -- if (vps->availbytes) { -- /* use any bytes which are presently in the buffer */ -- memcpy(target, &vps->t.ptr[vps->nextbytes], -- vps->availbytes); -- target += vps->availbytes; -- needed -= vps->availbytes; -- vps->availbytes = 0; -- } -- /* generate more bits into t1 */ -- v2prfplus(vps); -- } -- passert(needed <= vps->availbytes); -- -- memcpy(target, &vps->t.ptr[vps->nextbytes], needed); -- vps->availbytes -= needed; -- vps->nextbytes += needed; --} -- -diff -Naur libreswan-3.12-orig/programs/pluto/ikev2_prfplus.h libreswan-3.12/programs/pluto/ikev2_prfplus.h ---- libreswan-3.12-orig/programs/pluto/ikev2_prfplus.h 2014-11-06 22:52:50.000000000 -0500 -+++ libreswan-3.12/programs/pluto/ikev2_prfplus.h 1969-12-31 19:00:00.000000000 -0500 -@@ -1,20 +0,0 @@ --#ifndef _IKEV2_PRF_H --#define _IKEV2_PRF_H --struct v2prf_stuff { -- chunk_t t; -- const struct hash_desc *prf_hasher; -- PK11SymKey *skeyseed; -- chunk_t ni; -- chunk_t nr; -- chunk_t spii; -- chunk_t spir; -- u_char counter[1]; /* why is this an array of 1? */ -- unsigned int availbytes; -- unsigned int nextbytes; --}; -- --extern void v2genbytes(chunk_t *need, -- unsigned int needed, const char *name, -- struct v2prf_stuff *vps); -- --#endif -diff -Naur libreswan-3.12-orig/programs/pluto/ikev2_psk.c libreswan-3.12/programs/pluto/ikev2_psk.c ---- libreswan-3.12-orig/programs/pluto/ikev2_psk.c 2014-11-06 22:52:50.000000000 -0500 -+++ libreswan-3.12/programs/pluto/ikev2_psk.c 2015-05-06 11:45:32.925301475 -0400 -@@ -54,12 +54,14 @@ - #include "server.h" - #include "vendor.h" - #include "keys.h" -+#include "crypt_prf.h" -+#include "crypt_symkey.h" - - #include - #include - --static u_char psk_key_pad_str[] = "Key Pad for IKEv2"; /* 4306 2:15 */ --static int psk_key_pad_str_len = 17; /* sizeof( psk_key_pad_str); -1 */ -+static const char psk_key_pad_str[] = "Key Pad for IKEv2"; /* 4306 2:15 */ -+static const size_t psk_key_pad_str_len = 17; /* sizeof( psk_key_pad_str); -1 */ - - static bool ikev2_calculate_psk_sighash(struct state *st, - enum phase1_role role, -@@ -71,8 +73,7 @@ - const char *nonce_name; - const struct connection *c = st->st_connection; - const chunk_t *pss = get_preshared_secret(c); -- unsigned int hash_len = st->st_oakley.prf_hasher->hash_digest_len; -- unsigned char prf_psk[hash_len]; -+ const size_t hash_len = st->st_oakley.prf_hasher->hash_digest_len; - - if (pss == NULL) { - libreswan_log("No matching PSK found for connection:%s", -@@ -80,52 +81,25 @@ - return FALSE; /* failure: no PSK to use */ - } - -- CK_EXTRACT_PARAMS bs; -- SECItem param; -- - /* RFC 4306 2.15: - * AUTH = prf(prf(Shared Secret,"Key Pad for IKEv2"), ) - */ - - /* calculate inner prf */ -+ PK11SymKey *prf_psk; - { -- struct hmac_ctx id_ctx; -- -- PK11SymKey *tkey1 = pk11_derive_wrapper_lsw(st->st_shared_nss, -- CKM_CONCATENATE_DATA_AND_BASE, *pss, CKM_EXTRACT_KEY_FROM_KEY, CKA_DERIVE, -- 0); -- passert(tkey1 != NULL); -- -- bs = 0; -- param.data = (unsigned char*)&bs; -- param.len = sizeof(bs); -- PK11SymKey *tkey2 = PK11_Derive(tkey1, -- CKM_EXTRACT_KEY_FROM_KEY, -- ¶m, -- CKM_CONCATENATE_BASE_AND_DATA, -- CKA_DERIVE, pss->len); -- passert(tkey2 != NULL); -- -- hmac_init(&id_ctx, st->st_oakley.prf_hasher, tkey2); -- -- PK11_FreeSymKey(tkey1); -- PK11_FreeSymKey(tkey2); -- hmac_update(&id_ctx, psk_key_pad_str, psk_key_pad_str_len); -- hmac_final(prf_psk, &id_ctx); -+ struct crypt_prf *prf = -+ crypt_prf_init(("" -+ " = prf(,\"Key Pad for IKEv2\")"), -+ st->st_oakley.prf_hasher, -+ st->st_shared_nss/*scratch*/); -+ crypt_prf_init_chunk("shared secret", prf, *pss); -+ crypt_prf_update(prf); -+ crypt_prf_update_bytes(psk_key_pad_str/*name*/, prf, -+ psk_key_pad_str, psk_key_pad_str_len); -+ prf_psk = crypt_prf_final(prf); - } - -- DBG(DBG_CRYPT, -- DBG_log("negotiated prf: %s hash length: %lu", -- st->st_oakley.prf_hasher->common.name, -- (long unsigned) hash_len)); -- DBG(DBG_PRIVATE, -- DBG_log("PSK , secret, used %s, length %lu", -- pss->ptr, (long unsigned) pss->len); -- DBG_log("keypad used \"%s\", length %d", psk_key_pad_str, -- psk_key_pad_str_len)); -- DBG(DBG_CRYPT, -- DBG_dump("inner prf output", prf_psk, hash_len)); -- - /* decide nonce based on the role */ - if (role == O_INITIATOR) { - /* on initiator, we need to hash responders nonce */ -@@ -138,52 +112,32 @@ - - /* calculate outer prf */ - { -- struct hmac_ctx id_ctx; -- chunk_t pp_chunk; -- -- pp_chunk.ptr = prf_psk; -- pp_chunk.len = hash_len; -- -- PK11SymKey *tkey1 = pk11_derive_wrapper_lsw(st->st_shared_nss, -- CKM_CONCATENATE_DATA_AND_BASE, -- pp_chunk, -- CKM_EXTRACT_KEY_FROM_KEY, -- CKA_DERIVE, -- 0); -- passert(tkey1 != NULL); -- -- bs = 0; -- param.data = (unsigned char*)&bs; -- param.len = sizeof(bs); -- PK11SymKey *tkey2 = PK11_Derive(tkey1, -- CKM_EXTRACT_KEY_FROM_KEY, -- ¶m, -- CKM_CONCATENATE_BASE_AND_DATA, -- CKA_DERIVE, hash_len); -- passert(tkey2 != NULL); -- -- hmac_init(&id_ctx, st->st_oakley.prf_hasher, tkey2); -- -- PK11_FreeSymKey(tkey1); -- PK11_FreeSymKey(tkey2); -- --/* -- * For the responder, the octets to -- * be signed start with the first octet of the first SPI in the header -- * of the second message and end with the last octet of the last payload -- * in the second message. Appended to this (for purposes of computing -- * the signature) are the initiator's nonce Ni (just the value, not the -- * payload containing it), and the value prf(SK_pr,IDr') where IDr' is -- * the responder's ID payload excluding the fixed header. Note that -- * neither the nonce Ni nor the value prf(SK_pr,IDr') are transmitted. -- */ -- -- hmac_update(&id_ctx, firstpacket.ptr, firstpacket.len); -- hmac_update(&id_ctx, nonce->ptr, nonce->len); -- hmac_update(&id_ctx, idhash, hash_len); -- hmac_final(signed_octets, &id_ctx); -- -+ struct crypt_prf *prf = -+ crypt_prf_init(("" -+ " = prf(, )"), -+ st->st_oakley.prf_hasher, -+ st->st_shared_nss /*scratch*/); -+ crypt_prf_init_symkey("", prf, prf_psk); -+ /* -+ * For the responder, the octets to be signed start -+ * with the first octet of the first SPI in the header -+ * of the second message and end with the last octet -+ * of the last payload in the second message. -+ * Appended to this (for purposes of computing the -+ * signature) are the initiator's nonce Ni (just the -+ * value, not the payload containing it), and the -+ * value prf(SK_pr,IDr') where IDr' is the responder's -+ * ID payload excluding the fixed header. Note that -+ * neither the nonce Ni nor the value prf(SK_pr,IDr') -+ * are transmitted. -+ */ -+ crypt_prf_update(prf); -+ crypt_prf_update_chunk("first-packet", prf, firstpacket); -+ crypt_prf_update_chunk("nonce", prf, *nonce); -+ crypt_prf_update_bytes("hash", prf, idhash, hash_len); -+ crypt_prf_final_bytes(prf, signed_octets, hash_len); - } -+ free_any_symkey("", &prf_psk); - - DBG(DBG_CRYPT, - DBG_dump_chunk("inputs to hash1 (first packet)", firstpacket); -diff -Naur libreswan-3.12-orig/programs/pluto/initiate.c libreswan-3.12/programs/pluto/initiate.c ---- libreswan-3.12-orig/programs/pluto/initiate.c 2014-11-06 22:52:50.000000000 -0500 -+++ libreswan-3.12/programs/pluto/initiate.c 2015-05-06 11:45:32.925301475 -0400 -@@ -132,7 +132,7 @@ - c->name, c->interface->ip_dev->id_rname, - p->ip_dev->id_rname); - } -- terminate_connection(c->name); -+ // terminate_connection(c->name); - c->interface = NULL; /* withdraw orientation */ - return FALSE; - } -diff -Naur libreswan-3.12-orig/programs/pluto/log.c libreswan-3.12/programs/pluto/log.c ---- libreswan-3.12-orig/programs/pluto/log.c 2015-05-06 11:44:21.548466119 -0400 -+++ libreswan-3.12/programs/pluto/log.c 2015-05-06 11:45:32.926301486 -0400 -@@ -1208,7 +1208,7 @@ - if (!st->st_ikev2) { - /* ikev1 takes integ from prf, ecept of cause gcm */ - /* but we dont support gcm in ikev1 for now */ -- snprintf(integname, sizeof(integname), prfname); -+ jam_str(integname, sizeof(integname), prfname); - } else { - snprintf(integname, sizeof(integname), "none"); - } -diff -Naur libreswan-3.12-orig/programs/pluto/Makefile libreswan-3.12/programs/pluto/Makefile ---- libreswan-3.12-orig/programs/pluto/Makefile 2015-05-06 11:44:21.590466613 -0400 -+++ libreswan-3.12/programs/pluto/Makefile 2015-05-06 11:45:32.926301486 -0400 -@@ -129,7 +129,8 @@ - ikev1_dpd.c ikev1_dpd.h ikev1_spdb_struct.c \ - ikev1_msgid.c \ - ikev2.c ikev2_parent.c ikev2_child.c ikev2_crypto.c \ -- ikev2_prfplus.c ikev2_spdb_struct.c \ -+ crypt_symkey.c crypt_prf.c ikev1_prf.c ikev2_prf.c \ -+ ikev2_spdb_struct.c \ - ikev2_rsa.c ikev2_psk.c ikev2_x509.c \ - kernel.c kernel.h \ - ${NETKEY_SRCS} \ -@@ -176,7 +177,8 @@ - OBJSPLUTO += myid.o ipsec_doi.o - OBJSPLUTO += ikev1.o ikev1_main.o ikev1_quick.o ikev1_dpd.o ikev1_spdb_struct.o ikev1_msgid.o - OBJSPLUTO += ikev2.o ikev2_parent.o ikev2_child.o ikev2_spdb_struct.o --OBJSPLUTO += ikev2_rsa.o ikev2_psk.o ikev2_x509.o ikev2_crypto.o ikev2_prfplus.o -+OBJSPLUTO += ikev2_rsa.o ikev2_psk.o ikev2_x509.o ikev2_crypto.o -+OBJSPLUTO += crypt_symkey.o crypt_prf.o ikev1_prf.o ikev2_prf.o - OBJSPLUTO += kernel.o - OBJSPLUTO += $(NETKEY_OBJS) $(BSDKAME_OBJS) ${KLIPS_OBJS} ${MAST_OBJS} ${WIN2K_OBJS} ${PFKEYv2_OBJS} - OBJSPLUTO += kernel_noklips.o rcv_whack.o -@@ -203,14 +205,16 @@ - OBJSWHACK = whack.o - OBJSWHACKINIT = whackinit.o - -+CAVP += cavp -+ - # we can't do tests with two conditions, but we can concatenate the strings - SHOULDWERESTART=${USE_OBJDIR}$(wildcard plutomain.c) - ifeq ($(SHOULDWERESTART),trueplutomain.c) - all programs clean install: - cd ${LIBRESWANSRCDIR} && cd ${OBJDIRTOP}/programs/pluto && $(MAKE) $@ - else --all: $(BINNAMEPLUTO) $(BINNAMEADNSIFNEEDED) $(BINNAMEWHACK) #$(BINNAMEWHACKINIT) --programs: $(BINNAMEPLUTO) $(BINNAMEADNSIFNEEDED) $(BINNAMEWHACK) $(MANPAGES) #$(BINNAMEWHACKINIT) -+all: $(BINNAMEPLUTO) $(BINNAMEADNSIFNEEDED) $(BINNAMEWHACK) $(CAVP) #$(BINNAMEWHACKINIT) -+programs: $(BINNAMEPLUTO) $(BINNAMEADNSIFNEEDED) $(BINNAMEWHACK) $(MANPAGES) $(CAVP) #$(BINNAMEWHACKINIT) - clean: cleanall - install: doinstall - endif -@@ -290,6 +294,20 @@ - - checkprograms: - -+# Cryptographic Algorithm Validation Program (CAVP) -+# see: http://csrc.nist.gov/groups/STM/cavp/index.html -+CAVPSRC += cavp.c -+CAVPSRC += cavp_print.c -+CAVPSRC += cavp_stubs.c -+CAVPSRC += cavp_ikev1.c -+CAVPSRC += cavp_ikev2.c -+DISTSRC += $(CAVPSRC) -+OBJSCAVP = $(CAVPSRC:.c=.o) $(filter-out plutomain.o, $(OBJSPLUTO)) -+cavp: $(OBJSCAVP) -+ $(CC) -o $@ $(OBJSCAVP) \ -+ $(LDFLAGS) $(USERLINK) $(LIBSPLUTO) ${PLUTOMINUSL} -+ -+ - .c.o: - $(CC) $(USERCOMPILE) ${PORTINCLUDE} $(COPTS) $(ALLFLAGS) -c $< - -diff -Naur libreswan-3.12-orig/programs/pluto/pluto_constants.c libreswan-3.12/programs/pluto/pluto_constants.c ---- libreswan-3.12-orig/programs/pluto/pluto_constants.c 2015-05-06 11:44:21.549466131 -0400 -+++ libreswan-3.12/programs/pluto/pluto_constants.c 2015-05-06 11:45:32.926301486 -0400 -@@ -161,6 +161,9 @@ - /* story for state */ - - const char *const state_story[] = { -+ "not defined and probably dead (internal)", /* STATE_UNDEFINED */ -+ "got an ACQUIRE message for this pair (internal)", /* OPPO_QCQUIRE */ -+ "got TXT specifying gateway (internal)", /* OPPO_GW_DISCOVERED */ - "expecting MI1", /* STATE_MAIN_R0 */ - "sent MI1, expecting MR1", /* STATE_MAIN_I1 */ - "sent MR1, expecting MI2", /* STATE_MAIN_R1 */ -@@ -206,7 +209,7 @@ - }; - - enum_names state_stories = -- { STATE_MAIN_R0, STATE_IKEv2_ROOF - 1, state_story, NULL }; -+ { STATE_UNDEFINED, STATE_IKEv2_ROOF - 1, state_story, NULL }; - - static const char *const natt_method_result_name[] = { - }; -diff -Naur libreswan-3.12-orig/programs/pluto/pluto_crypt.c libreswan-3.12/programs/pluto/pluto_crypt.c ---- libreswan-3.12-orig/programs/pluto/pluto_crypt.c 2014-11-06 22:52:50.000000000 -0500 -+++ libreswan-3.12/programs/pluto/pluto_crypt.c 2015-05-06 11:45:32.927301498 -0400 -@@ -63,6 +63,10 @@ - #include "lswconf.h" - - #include "lsw_select.h" -+#include "ikev2_prf.h" -+#include "crypt_dh.h" -+#include "ikev1_prf.h" -+ - - TAILQ_HEAD(req_queue, pluto_crypto_req_cont); - -diff -Naur libreswan-3.12-orig/programs/pluto/pluto_crypt.h libreswan-3.12/programs/pluto/pluto_crypt.h ---- libreswan-3.12-orig/programs/pluto/pluto_crypt.h 2015-05-06 11:44:21.570466378 -0400 -+++ libreswan-3.12/programs/pluto/pluto_crypt.h 2015-05-06 11:45:32.927301498 -0400 -@@ -382,10 +382,6 @@ - extern void finish_dh_v2(struct state *st, - const struct pluto_crypto_req *r); - --extern void calc_dh_iv(struct pluto_crypto_req *r); --extern void calc_dh(struct pluto_crypto_req *r); --extern void calc_dh_v2(struct pluto_crypto_req *r); -- - extern void unpack_KE_from_helper( - struct state *st, - const struct pluto_crypto_req *r, -diff -Naur libreswan-3.12-orig/programs/pluto/state.c libreswan-3.12/programs/pluto/state.c ---- libreswan-3.12-orig/programs/pluto/state.c 2015-05-06 11:44:21.571466389 -0400 -+++ libreswan-3.12/programs/pluto/state.c 2015-05-06 11:45:32.928301510 -0400 -@@ -65,6 +65,7 @@ - #include "md5.h" - #include "cookie.h" - #include "crypto.h" /* requires sha1.h and md5.h */ -+#include "crypt_symkey.h" - #include "spdb.h" - - #include -@@ -525,12 +526,7 @@ - freeanychunk(st->st_nr); - - --# define free_any_nss_symkey(p) { \ -- if ((p) != NULL) { \ -- PK11_FreeSymKey(p); \ -- (p) = NULL; \ -- } \ -- } -+# define free_any_nss_symkey(p) free_any_symkey(#p, &(p)) - /* ??? free_any_nss_symkey(st->st_shared_nss); */ - free_any_nss_symkey(st->st_skeyseed_nss); /* same as st_skeyid_nss */ - free_any_nss_symkey(st->st_skey_d_nss); /* same as st_skeyid_d_nss */ -@@ -1440,7 +1436,7 @@ - c->name, inst, - st->st_remoteport, - enum_name(&state_names, st->st_state), -- state_story[st->st_state - STATE_MAIN_R0], -+ enum_name(&state_stories, st->st_state), - st->st_event ? enum_name(&timer_event_names, - st->st_event->ev_type) : "none", - delta, -diff -Naur libreswan-3.12-orig/programs/pluto/test_buffer.c libreswan-3.12/programs/pluto/test_buffer.c ---- libreswan-3.12-orig/programs/pluto/test_buffer.c 2015-05-06 11:44:21.591466625 -0400 -+++ libreswan-3.12/programs/pluto/test_buffer.c 2015-05-06 11:45:32.928301510 -0400 -@@ -40,7 +40,7 @@ - * If this function fails, crash and burn. Its been fed static data - * so should never ever have a problem. - */ --static chunk_t decode_hex_to_chunk(const char *original, const char *string) -+chunk_t decode_hex_to_chunk(const char *original, const char *string) - { - /* The decoded buffer can't be bigger than the encoded string. */ - chunk_t chunk = zalloc_chunk(strlen(string), original); -@@ -154,8 +154,15 @@ - PK11SymKey *decode_to_key(CK_MECHANISM_TYPE cipher_mechanism, - const char *encoded_key) - { -- PK11SlotInfo *slot = PK11_GetBestSlot(cipher_mechanism, NULL); - chunk_t raw_key = decode_to_chunk("key", encoded_key); -+ PK11SymKey *sym_key = chunk_to_key(cipher_mechanism, raw_key); -+ freeanychunk(raw_key); -+ return sym_key; -+} -+ -+PK11SymKey *chunk_to_key(CK_MECHANISM_TYPE cipher_mechanism, chunk_t raw_key) -+{ -+ PK11SlotInfo *slot = PK11_GetBestSlot(cipher_mechanism, NULL); - SECItem key_item; - key_item.type = siBuffer; - key_item.data = raw_key.ptr; /* ptr to an array of key bytes */ -@@ -163,7 +170,6 @@ - PK11SymKey *sym_key = PK11_ImportSymKey(slot, cipher_mechanism, - PK11_OriginUnwrap, - CKA_ENCRYPT, &key_item, NULL); -- freeanychunk(raw_key); - PK11_FreeSlot(slot); - return sym_key; - } -diff -Naur libreswan-3.12-orig/programs/pluto/test_buffer.h libreswan-3.12/programs/pluto/test_buffer.h ---- libreswan-3.12-orig/programs/pluto/test_buffer.h 2015-05-06 11:44:21.592466636 -0400 -+++ libreswan-3.12/programs/pluto/test_buffer.h 2015-05-06 11:45:32.928301510 -0400 -@@ -13,6 +13,7 @@ - * for more details. - */ - -+chunk_t decode_hex_to_chunk(const char *original, const char *string); - chunk_t decode_to_chunk(const char *prefix, const char *string); - int compare_chunks(const char *prefix, - chunk_t expected, -@@ -24,3 +25,5 @@ - size_t offset, size_t length); - - PK11SymKey *decode_to_key(CK_MECHANISM_TYPE cipher_mechanism, const char *string); -+ -+PK11SymKey *chunk_to_key(CK_MECHANISM_TYPE cipher_mechanism, chunk_t raw_key); diff --git a/SOURCES/libreswan-3.12-826264-ike-aes-gcm.patch b/SOURCES/libreswan-3.12-826264-ike-aes-gcm.patch deleted file mode 100644 index a470a27..0000000 --- a/SOURCES/libreswan-3.12-826264-ike-aes-gcm.patch +++ /dev/null @@ -1,2804 +0,0 @@ -diff -Naur libreswan-3.12-orig/include/alg_info.h libreswan-3.12/include/alg_info.h ---- libreswan-3.12-orig/include/alg_info.h 2014-11-06 22:52:50.000000000 -0500 -+++ libreswan-3.12/include/alg_info.h 2015-01-20 16:53:19.950650944 -0500 -@@ -5,6 +5,7 @@ - * Copyright (C) 2012-2013 Paul Wouters - * Copyright (C) 2013 D. Hugh Redelmeier - * Copyright (C) 2013 Paul Wouters -+ * Copyright (C) 2015 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 -@@ -49,9 +50,9 @@ - char ealg_buf[16]; - char aalg_buf[16]; - char modp_buf[16]; -- int (*ealg_getbyname)(const char *const str, size_t len); -- int (*aalg_getbyname)(const char *const str, size_t len); -- int (*modp_getbyname)(const char *const str, size_t len); -+ int (*ealg_getbyname)(const char *const str); -+ int (*aalg_getbyname)(const char *const str); -+ int (*modp_getbyname)(const char *const str); - char *ealg_str; - char *aalg_str; - char *modp_str; -@@ -110,7 +111,7 @@ - - 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 void alg_info_delref(struct alg_info *alg_info); - - extern struct alg_info_esp *alg_info_esp_create_from_str(const char *alg_str, - char *err_buf, size_t err_buf_len); -@@ -132,8 +133,7 @@ - for ((i) = (aii)->ai.alg_info_cnt, (ai_ike) = (aii)->ike; (i)--; (ai_ike)++) - - extern int alg_enum_search(enum_names *ed, const char *prefix, -- const char *postfix, const char *name, -- size_t name_len); -+ const char *postfix, const char *name); - - struct oakley_group_desc; /* so it isn't local to the function prototype */ - -diff -Naur libreswan-3.12-orig/lib/libswan/alg_info.c libreswan-3.12/lib/libswan/alg_info.c ---- libreswan-3.12-orig/lib/libswan/alg_info.c 2014-11-06 22:52:50.000000000 -0500 -+++ libreswan-3.12/lib/libswan/alg_info.c 2015-01-20 16:53:19.953651026 -0500 -@@ -1,7 +1,9 @@ - /* - * Algorithm info parsing and creation functions - * Author: JuanJo Ciarlante -+ * - * Copyright (C) 2012 Paul Wouters -+ * Copyright (C) 2015 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 -@@ -41,10 +43,52 @@ - - #define MAX_ALG_ALIASES 16 - --typedef struct alg_alias { -+struct alg_alias { - const char *alg; -- const char *alias_set[MAX_ALG_ALIASES]; --} alg_alias; -+ const char *const alias_set[MAX_ALG_ALIASES]; -+}; -+ -+/* if str is a known alias, return the real alg */ -+static const char *find_alg_alias(const struct alg_alias *alias, const char *str) -+{ -+ const struct alg_alias *aa; -+ for (aa = alias; aa->alg != NULL; aa++) { -+ const char *const *aset; -+ for (aset = aa->alias_set; *aset != NULL; aset++) { -+ if (strcaseeq(str, (*aset))) { -+ return aa->alg; -+ } -+ } -+ } -+ return NULL; -+} -+ -+static int alg_getbyname_or_alias(const struct alg_alias *aliases, const char *str, -+ int (*getbyname)(const char *const str)) -+{ -+ const char *alias = find_alg_alias(aliases, str); -+ if (alias != NULL) { -+ return getbyname(alias); -+ } else { -+ return getbyname(str); -+ } -+} -+ -+static int aalg_getbyname_or_alias(const struct parser_context *context, -+ const char *str) -+{ -+ static struct alg_alias aliases[] = { -+ /* alg */ /* aliases */ -+ { "sha2_256", { "sha2", NULL } }, -+ { "sha2_256", { "sha256", NULL } }, -+ { "sha2_384", { "sha384", NULL } }, -+ { "sha2_512", { "sha512", NULL } }, -+ { "sha1", { "sha", NULL } }, -+ { "sha1", { "sha1_96", NULL } }, -+ { NULL, { NULL } } -+ }; -+ return alg_getbyname_or_alias(aliases, str, context->aalg_getbyname); -+} - - /* - * Aliases should NOT be used to match a base cipher to a key size, -@@ -52,26 +96,24 @@ - * examples aes cannot become an alias for aes128 or else a responder - * with esp=aes would reject aes256. - */ --static const alg_alias auth_alg_aliases[] = { -- /* alg */ /* aliases */ -- { "sha2_256", { "sha2", NULL } }, -- { "sha1", { "sha", NULL } }, -- { "sha1", { "sha1_96", NULL } }, -- { NULL, { NULL } } --}; - --static const alg_alias esp_trans_aliases[] = { -- /* alg */ /* aliases */ -- { "aes_ccm_a", { "aes_ccm_8", NULL } }, -- { "aes_ccm_b", { "aes_ccm_12", NULL } }, -- { "aes_ccm_c", { "aes_ccm_16", "aes_ccm", NULL } }, -- { "aes_gcm_a", { "aes_gcm_8", NULL } }, -- { "aes_gcm_b", { "aes_gcm_12", NULL } }, -- { "aes_gcm_c", { "aes_gcm_16", "aes_gcm", NULL } }, -- { "aes_ctr", { "aesctr", NULL } }, -- { "aes", { "aes_cbc", NULL } }, -- { NULL, { NULL } } --}; -+static int ealg_getbyname_or_alias(const struct parser_context *context, -+ const char *str) -+{ -+ static const struct alg_alias aliases[] = { -+ /* alg */ /* aliases */ -+ { "aes_ccm_a", { "aes_ccm_8", NULL } }, -+ { "aes_ccm_b", { "aes_ccm_12", NULL } }, -+ { "aes_ccm_c", { "aes_ccm_16", "aes_ccm", NULL } }, -+ { "aes_gcm_a", { "aes_gcm_8", NULL } }, -+ { "aes_gcm_b", { "aes_gcm_12", NULL } }, -+ { "aes_gcm_c", { "aes_gcm_16", "aes_gcm", NULL } }, -+ { "aes_ctr", { "aesctr", NULL } }, -+ { "aes", { "aes_cbc", NULL } }, -+ { NULL, { NULL } } -+ }; -+ return alg_getbyname_or_alias(aliases, str, context->ealg_getbyname); -+} - - /* - * sadb/ESP aa attrib converters - conflicting for v1 and v2 -@@ -248,12 +290,12 @@ - * Search enum_name array with string, uppercased, prefixed, and postfixed - */ - int alg_enum_search(enum_names *ed, const char *prefix, -- const char *postfix, const char *name, -- size_t name_len) -+ const char *postfix, const char *name) - { - char buf[64]; - size_t prelen = strlen(prefix); - size_t postlen = strlen(postfix); -+ size_t name_len = strlen(name); - - if (prelen + name_len + postlen >= sizeof(buf)) - return -1; /* cannot match */ -@@ -269,19 +311,19 @@ - * Search esp_transformid_names for a match, eg: - * "3des" <=> "ESP_3DES" - */ --static int ealg_getbyname_esp(const char *const str, size_t len) -+static int ealg_getbyname_esp(const char *const str) - { - if (str == NULL || *str == '\0') - return -1; - -- return alg_enum_search(&esp_transformid_names, "ESP_", "", str, len); -+ return alg_enum_search(&esp_transformid_names, "ESP_", "", str); - } - - /* - * Search auth_alg_names for a match, eg: - * "md5" <=> "AUTH_ALGORITHM_HMAC_MD5" - */ --static int aalg_getbyname_esp(const char *str, size_t len) -+static int aalg_getbyname_esp(const char *str) - { - int ret = -1; - static const char null_esp[] = "null"; -@@ -289,12 +331,10 @@ - if (str == NULL || *str == '\0') - return -1; - -- ret = alg_enum_search(&auth_alg_names, "AUTH_ALGORITHM_HMAC_", "", -- str, len); -+ ret = alg_enum_search(&auth_alg_names, "AUTH_ALGORITHM_HMAC_", "", str); - if (ret >= 0) - return ret; -- ret = alg_enum_search(&auth_alg_names, "AUTH_ALGORITHM_", "", -- str, len); -+ ret = alg_enum_search(&auth_alg_names, "AUTH_ALGORITHM_", "", str); - if (ret >= 0) - return ret; - -@@ -303,56 +343,19 @@ - * since 0 is already used. - * ??? this is extremely ugly. - */ -- if (len == sizeof(null_esp)-1 && strncaseeq(str, null_esp, len)) -+ if (strcaseeq(str, null_esp)) - return INT_MAX; - - return ret; - } - --/* if str is a known alias, return the real alg */ --static const char *alg_find_alias(const alg_alias *alias, const char *str) --{ -- const alg_alias *aa; -- int i; -- -- for (aa = alias; aa->alg != NULL; aa++) { -- const char *const *aset = aa->alias_set; -- -- for (i = 0; i < MAX_ALG_ALIASES && aset[i] != NULL; i++) { -- if (strcaseeq(str, aset[i])) -- return aa->alg; -- } -- } -- -- return NULL; --} -- --static int ealg_getbyname_or_alias_esp(const char *str, size_t len) -+static int modp_getbyname_esp(const char *const str) - { -- const char *astr = alg_find_alias(esp_trans_aliases, str); -- -- return astr == NULL ? -- ealg_getbyname_esp(str, len) : -- ealg_getbyname_esp(astr, strlen(astr)); --} -- --static int aalg_getbyname_or_alias_esp(const char *str, size_t len) --{ -- const char *astr = alg_find_alias(auth_alg_aliases, str); -- -- return astr == NULL ? -- aalg_getbyname_esp(str, len) : -- aalg_getbyname_esp(astr, strlen(astr)); --} -- --static int modp_getbyname_esp(const char *const str, size_t len) --{ -- int ret = alg_enum_search(&oakley_group_names, "OAKLEY_GROUP_", "", -- str, len); -+ int ret = alg_enum_search(&oakley_group_names, "OAKLEY_GROUP_", "", str); - - if (ret < 0) - ret = alg_enum_search(&oakley_group_names, "OAKLEY_GROUP_", -- " (extension)", str, len); -+ " (extension)", str); - return ret; - } - -@@ -686,8 +689,8 @@ - p_ctx->aalg_permit = TRUE; - p_ctx->state = ST_INI; - -- p_ctx->ealg_getbyname = ealg_getbyname_or_alias_esp; -- p_ctx->aalg_getbyname = aalg_getbyname_or_alias_esp; -+ p_ctx->ealg_getbyname = ealg_getbyname_esp; -+ p_ctx->aalg_getbyname = aalg_getbyname_esp; - - } - -@@ -706,7 +709,7 @@ - p_ctx->modp_str = p_ctx->modp_buf; - p_ctx->state = ST_INI_AA; - -- p_ctx->aalg_getbyname = aalg_getbyname_or_alias_esp; -+ p_ctx->aalg_getbyname = aalg_getbyname_esp; - - } - -@@ -725,8 +728,7 @@ - - ealg_id = aalg_id = -1; - if (p_ctx->ealg_permit && p_ctx->ealg_buf[0] != '\0') { -- ealg_id = p_ctx->ealg_getbyname(p_ctx->ealg_buf, -- strlen(p_ctx->ealg_buf)); -+ ealg_id = ealg_getbyname_or_alias(p_ctx, p_ctx->ealg_buf); - if (ealg_id < 0) { - return "enc_alg not found"; - } -@@ -780,11 +782,22 @@ - return "CAST is only supported for 128 bits (to avoid padding)"; - } - break; -- case OAKLEY_AES_CBC: -- case OAKLEY_CAMELLIA_CBC: - case OAKLEY_SERPENT_CBC: - case OAKLEY_TWOFISH_CBC: - case OAKLEY_TWOFISH_CBC_SSH: -+ case OAKLEY_AES_CBC: -+ case OAKLEY_AES_CTR: -+ case OAKLEY_AES_GCM_8: -+ case OAKLEY_AES_GCM_12: -+ case OAKLEY_AES_GCM_16: -+ case OAKLEY_AES_CCM_8: -+ case OAKLEY_AES_CCM_12: -+ case OAKLEY_AES_CCM_16: -+ case OAKLEY_CAMELLIA_CBC: -+ case OAKLEY_CAMELLIA_CTR: -+ case OAKLEY_CAMELLIA_CCM_A: -+ case OAKLEY_CAMELLIA_CCM_B: -+ case OAKLEY_CAMELLIA_CCM_C: - if (!COMMON_KEY_LENGTHS(p_ctx->eklen)) { - return "wrong encryption key length - key size must be 128 (default), 192 or 256"; - } -@@ -832,19 +845,21 @@ - - } - if (p_ctx->aalg_permit && *p_ctx->aalg_buf != '\0') { -- aalg_id = p_ctx->aalg_getbyname(p_ctx->aalg_buf, -- strlen(p_ctx->aalg_buf)); -+ aalg_id = aalg_getbyname_or_alias(p_ctx, p_ctx->aalg_buf); - if (aalg_id < 0) { - return "hash_alg not found"; - } - - /* some code stupidly uses INT_MAX for "null" */ - if (aalg_id == AH_NONE || aalg_id == AH_NULL || aalg_id == INT_MAX) { -- if (p_ctx->protoid == PROTO_IPSEC_AH) -- return "AH cannot have null authentication"; -- /* aalg can and must be only be null for AEAD ciphers */ - switch (p_ctx->protoid) { - case PROTO_IPSEC_ESP: -+ /* -+ * ESP AEAD ciphers do not require -+ * separate authentication (by -+ * defintion, authentication is -+ * built-in). -+ */ - switch(ealg_id) { - case ESP_AES_GCM_8: - case ESP_AES_GCM_12: -@@ -858,14 +873,26 @@ - } - break; - case PROTO_ISAKMP: -+ /* -+ * While IKE AEAD ciphers do not -+ * require separate authentication (by -+ * defintion, authentication is -+ * built-in), they do require a PRF. -+ * -+ * The non-empty authentication -+ * algorithm will be used as the PRF. -+ */ - switch(ealg_id) { -- case IKEv2_ENCR_AES_CCM_8: -- case IKEv2_ENCR_AES_CCM_12: -- case IKEv2_ENCR_AES_CCM_16: -- case IKEv2_ENCR_AES_GCM_8: -- case IKEv2_ENCR_AES_GCM_12: -- case IKEv2_ENCR_AES_GCM_16: -- break; /* ok */ -+ case OAKLEY_AES_CCM_8: -+ case OAKLEY_AES_CCM_12: -+ case OAKLEY_AES_CCM_16: -+ case OAKLEY_AES_GCM_8: -+ case OAKLEY_AES_GCM_12: -+ case OAKLEY_AES_GCM_16: -+ case OAKLEY_CAMELLIA_CCM_A: -+ case OAKLEY_CAMELLIA_CCM_B: -+ case OAKLEY_CAMELLIA_CCM_C: -+ return "AEAD IKE cipher cannot have null pseudo-random-function"; - default: - return "non-AEAD IKE cipher cannot have null authentication"; - } -@@ -874,9 +901,17 @@ - return "AH cannot have null authentication"; - } - } else { -- /* auth is non-null, so we cannot have AEAD ciphers */ - switch (p_ctx->protoid) { - case PROTO_IPSEC_ESP: -+ /* -+ * ESP AEAD ciphers do not require -+ * separate authentication (by -+ * defintion, authentication is -+ * built-in). -+ * -+ * Reject any non-null authentication -+ * algorithm -+ */ - switch(ealg_id) { - case ESP_AES_GCM_8: - case ESP_AES_GCM_12: -@@ -890,17 +925,16 @@ - } - break; - case PROTO_ISAKMP: -- switch(ealg_id) { -- case IKEv2_ENCR_AES_CCM_8: -- case IKEv2_ENCR_AES_CCM_12: -- case IKEv2_ENCR_AES_CCM_16: -- case IKEv2_ENCR_AES_GCM_8: -- case IKEv2_ENCR_AES_GCM_12: -- case IKEv2_ENCR_AES_GCM_16: -- return "AEAD IKE cipher must have null authentication"; -- default: -- break; /* ok */ -- } -+ /* -+ * While IKE AEAD ciphers do not -+ * require separate authentication (by -+ * defintion, authentication is -+ * built-in), they do require a PRF. -+ * -+ * So regardless of the algorithm type -+ * allow an explicit authentication. -+ * (IKE AEAD uses it for the PRF). -+ */ - break; - } - } -@@ -921,8 +955,7 @@ - } - - if (p_ctx->modp_getbyname != NULL && *p_ctx->modp_buf != '\0') { -- modp_id = p_ctx->modp_getbyname(p_ctx->modp_buf, -- strlen(p_ctx->modp_buf)); -+ modp_id = p_ctx->modp_getbyname(p_ctx->modp_buf); - if (modp_id < 0) { - return "modp group not found"; - } -@@ -1034,7 +1067,7 @@ - - /* if pfs string not null AND first char is not '0' */ - if (*pfs_name != '\0' && pfs_name[0] != '0') { -- int ret = modp_getbyname_esp(pfs_name, strlen(pfs_name)); -+ int ret = modp_getbyname_esp(pfs_name); - - if (ret < 0) { - /* Bomb if pfsgroup not found */ -@@ -1121,22 +1154,15 @@ - */ - void alg_info_addref(struct alg_info *alg_info) - { -- if (alg_info != NULL) { -- alg_info->ref_cnt++; -- } -+ alg_info->ref_cnt++; - } --void alg_info_delref(struct alg_info **alg_info_p) --{ -- struct alg_info *alg_info = *alg_info_p; - -- if (alg_info != NULL) { -- passert(alg_info->ref_cnt != 0); -- alg_info->ref_cnt--; -- if (alg_info->ref_cnt == 0) { -- alg_info_free(alg_info); -- } -- *alg_info_p = NULL; -- } -+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); - } - - /* snprint already parsed transform list (alg_info) */ -diff -Naur libreswan-3.12-orig/programs/configs/d.ipsec.conf/ike.xml libreswan-3.12/programs/configs/d.ipsec.conf/ike.xml ---- libreswan-3.12-orig/programs/configs/d.ipsec.conf/ike.xml 2015-01-20 16:52:43.582652240 -0500 -+++ libreswan-3.12/programs/configs/d.ipsec.conf/ike.xml 2015-01-20 16:57:03.751796803 -0500 -@@ -14,6 +14,8 @@ - Some examples are - ike=3des-sha1,aes-sha1, - ike=aes, -+ike=aes_ctr, -+ike=aes_gcm256-sha2, - ike=aes128-md5;modp2048, - ike=aes128-sha1;dh22, - ike=3des-md5;modp1024,aes-sha1;modp1536. -@@ -24,7 +26,17 @@ - cipher: 3des or aes128 or aes256 - hash: sha1 or md5 - pfsgroup (DHgroup): modp1024 or modp1536 or modp2048 -- -+ -+ -+Note that AES-GCM is an AEAD algorithm, meaning that it performs encryption+authentication in one step. This -+means that AES-GCM must not specify an authentication algorithm. However, it does require a PRF function, so -+the second argument to an AEAD algorithm denotes the PRF. So ike=aes_gcm-sha2 means propose AES_GCM with no -+authentication and using SHA2 as the prf. Note that for phase2alg, there is no prf, so AES-GCM is -+specified for ESP as phase2=aes_gcm-null. The AES-GCM and AES-CCM algorithms support 8,12 and 16 byte ICV's. -+These can be specified using a postfix, for example aes_gcm_a (for 8), aes_gcm_b (for 12) and aes_gcm_c (for 16). -+The default (aes_gcm without postfix) refers to the 16 byte ICV version. It is strongly recommended to NOT use -+the 8 or 12 byte versions of GCM or CCM. -+ - - Weak algorithms are regularly removed from libreswan. Currently, 1DES and modp768 have been removed and modp1024 - will be removed in the near future. Additionally, md5 and sha1 will be removed within the next few years. Null -diff -Naur libreswan-3.12-orig/programs/configs/d.ipsec.conf/phase2alg.xml libreswan-3.12/programs/configs/d.ipsec.conf/phase2alg.xml ---- libreswan-3.12-orig/programs/configs/d.ipsec.conf/phase2alg.xml 2015-01-20 16:52:43.674654767 -0500 -+++ libreswan-3.12/programs/configs/d.ipsec.conf/phase2alg.xml 2015-01-20 16:57:03.751796803 -0500 -@@ -16,18 +16,28 @@ - The format for AH is AUTH followed by an optional PFSgroup. For - instance, "md5" or "sha1;modp1536". - --AES-GCM and AES-CCM use a syntax like --"phase2alg=aes_ccm-null or phase2alg=aes_gcm-null". The --only supported key sizes are 128, 192 and 256, which are specified similarly --to plain aes, i.e. "phase2alg=aes_gcm256". A subscript (_a or _b or _c) --can be used to refer to the different ICV versions (8,12,16). The default --when not using a subscript is the 16 bute ICV, so phase2alg=aes_gcm_c256-null) --is the same as phase2alg=aes_gcm256-null. -+AEAD algorithms such as AES-GCM and AES-CCM require null for the authentication algorithm, for example -+phase2alg=aes_ccm-null or -+phase2alg=aes_gcm-null. Note that the ike= syntax for aes_gcm does not specify a -+null authentication but specifies the prf instead. -+The supported key sizes are 128, 192 and 256, which are specified similarly -+to plain aes, i.e. phase2alg=aes_gcm256. A -+subscript of _c, _b -+or _a can be used to refer to the different ICV variants -+where a means 8 bytes, b means 12 bytes and c means 16 bytes. The default -+when not using a subscript is the 16 byte ICV, the recommended value by RFC-4106. -+Therefor phase2alg=aes_gcm256-null is equivalent to phase2alg=aes_gcm_c256-null. - It is recommended to migrate to the _c versions (without specifying _c), --as support for smaller ICV's might be removed in the future. --Note that openswan and versions of libreswan up to 3.6 require --adding the salt size to the key size. Therefor, to interop with an older --version of openswan or libreswan, use: "phase2alg=aes_ccm_c-280-null". For -+as support for smaller ICV's might be removed in the near future. -+ -+The supported algorithms depend on the libreswan version, OS and -+kernel stack used. Possible ciphers are aes, 3des, aes_ctr, aes_gcm, -+aes_ccm, camellia, serpent and twofish. -+ -+Note that openswan and versions of libreswan up to 3.6 require manually -+adding the salt size to the key size. Therefor, to configure an older -+version of openswan or libreswan, use: "phase2alg=aes_ccm_c-280-null" to -+interop with a new libreswan using "phase2alg=aes_ccm256". For - CCM, the 'keysize' needs to be increased by 24, resulted in valid keysizes - of 152, 215 and 280. For GCM the 'keysize' needs to be increased by 32, - resulting valid 'keysizes' of 160, 224 and 288. -diff -Naur libreswan-3.12-orig/programs/pluto/connections.c libreswan-3.12/programs/pluto/connections.c ---- libreswan-3.12-orig/programs/pluto/connections.c 2014-11-06 22:52:50.000000000 -0500 -+++ libreswan-3.12/programs/pluto/connections.c 2015-01-20 16:53:19.955651081 -0500 -@@ -236,12 +236,6 @@ - cur_connection == c ? NULL : cur_connection; - - lset_t old_cur_debugging = cur_debugging; -- union { -- struct alg_info **ppai; -- struct alg_info_esp **ppai_esp; -- struct alg_info_ike **ppai_ike; -- } palg_info; -- - set_cur_connection(c); - - /* -@@ -323,10 +317,17 @@ - free_generalNames(c->requested_ca, TRUE); - - gw_delref(&c->gw_info); -- palg_info.ppai_esp = &c->alg_info_esp; -- alg_info_delref(palg_info.ppai); -- palg_info.ppai_ike = &c->alg_info_ike; -- alg_info_delref(palg_info.ppai); -+ -+ if (c->alg_info_ike != NULL) { -+ alg_info_delref(&c->alg_info_ike->ai); -+ c->alg_info_ike = NULL; -+ } -+ -+ if (c->alg_info_esp != NULL) { -+ alg_info_delref(&c->alg_info_esp->ai); -+ c->alg_info_esp = NULL; -+ } -+ - pfree(c); - } - -@@ -758,13 +759,12 @@ - } - - /* increment references to algo's, if any */ -- if (c->alg_info_ike) { -+ if (c->alg_info_ike != NULL) - alg_info_addref(&c->alg_info_ike->ai); -- } - -- if (c->alg_info_esp) { -+ if (c->alg_info_esp != NULL) - alg_info_addref(&c->alg_info_esp->ai); -- } -+ - if (c->pool != NULL) - reference_addresspool(c->pool); - } -@@ -1753,6 +1753,9 @@ - } - unshare_connection_strings(d); - -+ if (c->pool != NULL) -+ reference_addresspool(c->pool); -+ - d->kind = CK_INSTANCE; - - passert(oriented(*d)); -diff -Naur libreswan-3.12-orig/programs/pluto/crypt_dh.c libreswan-3.12/programs/pluto/crypt_dh.c ---- libreswan-3.12-orig/programs/pluto/crypt_dh.c 2015-01-20 16:52:43.649654081 -0500 -+++ libreswan-3.12/programs/pluto/crypt_dh.c 2015-01-20 16:53:19.958651164 -0500 -@@ -114,11 +114,13 @@ - case OAKLEY_AES_CCM_16: - mechanism = CKM_AES_CCM; - break; -+#endif - case OAKLEY_AES_GCM_8: - case OAKLEY_AES_GCM_12: - case OAKLEY_AES_GCM_16: - mechanism = CKM_AES_GCM; - break; -+#ifdef NOT_YET - case OAKLEY_TWOFISH_CBC: - mechanism = CKM_TWOFISH_CBC; - break; -@@ -1192,7 +1194,6 @@ - ) - { - struct v2prf_stuff vpss; -- size_t total_keysize; - - chunk_t hmac_opad, hmac_ipad, hmac_pad_prf; - /* chunk_t hmac_pad_integ, hmac_zerobyte, hmac_val1, hmac_val2; */ -@@ -1227,22 +1228,21 @@ - enum_name(&ikev2_trans_type_integ_names, skq->integ_hash), - key_size, salt_size)); - -- const struct hash_desc *hasher = (struct hash_desc *) -+ const struct hash_desc *prf_hasher = (struct hash_desc *) - ikev2_alg_find(IKE_ALG_HASH, skq->prf_hash); -- -- passert(hasher != NULL); -+ passert(prf_hasher != NULL); - - const struct encrypt_desc *encrypter = skq->encrypter; - passert(encrypter != NULL); - -- hmac_opad = hmac_pads(HMAC_OPAD, hasher->hash_block_size); -- hmac_ipad = hmac_pads(HMAC_IPAD, hasher->hash_block_size); -+ hmac_opad = hmac_pads(HMAC_OPAD, prf_hasher->hash_block_size); -+ hmac_ipad = hmac_pads(HMAC_IPAD, prf_hasher->hash_block_size); - hmac_pad_prf = hmac_pads(0x00, -- hasher->hash_block_size - -- hasher->hash_digest_len); -+ prf_hasher->hash_block_size - -+ prf_hasher->hash_digest_len); - - /* generate SKEYSEED from key=(Ni|Nr), hash of shared */ -- skeyseed_k = skeyid_digisig(vpss.ni, vpss.nr, shared, hasher); -+ skeyseed_k = skeyid_digisig(vpss.ni, vpss.nr, shared, prf_hasher); - passert(skeyseed_k != NULL); - - /* now we have to generate the keys for everything */ -@@ -1252,18 +1252,19 @@ - /* SK_p needs PRF hasher*2 key bytes */ - /* SK_e needs key_size*2 key bytes */ - /* ..._salt needs salt_size*2 bytes */ -- /* SK_a needs hash's key size */ -- const struct hash_desc *integ_hasher = -- (struct hash_desc *)ikev2_alg_find(IKE_ALG_INTEG, -- skq->integ_hash); -- int skd_bytes = hasher->hash_key_size; -- int skp_bytes = hasher->hash_key_size; -- int ska_bytes = integ_hasher->hash_key_size; -+ /* SK_a needs integ's key size*2 bytes */ - -+ int skd_bytes = prf_hasher->hash_key_size; -+ int skp_bytes = prf_hasher->hash_key_size; -+ const struct hash_desc *integ_hasher = -+ (struct hash_desc *)ikev2_alg_find(IKE_ALG_INTEG, skq->integ_hash); -+ int integ_size = integ_hasher != NULL ? integ_hasher->hash_key_size : 0; -+ size_t total_keysize = skd_bytes + 2*skp_bytes + 2*key_size + 2*salt_size + 2*integ_size; -+ DBG(DBG_CRYPT, -+ DBG_log("calc_skeyseed_v2: %zd = %d(d) + 2*%d(p) + 2*%zd(key) + 2*%zd(salt) + 2*%d(integ) bytes", -+ total_keysize, skd_bytes, skp_bytes, key_size, salt_size, integ_size)); - vpss.counter[0] = 0x01; - vpss.t.len = 0; -- total_keysize = skd_bytes + -- (2 * (ska_bytes + key_size + salt_size + skp_bytes)); - - DBG(DBG_CRYPT, { - DBG_log("PRF+ input"); -@@ -1280,7 +1281,7 @@ - PK11SymKey *tkey1 = pk11_derive_wrapper_lsw(skeyseed_k, - CKM_CONCATENATE_BASE_AND_DATA, - hmac_pad_prf, CKM_XOR_BASE_AND_DATA, CKA_DERIVE, -- hasher->hash_block_size); -+ prf_hasher->hash_block_size); - passert(tkey1 != NULL); - - for (;; ) { -@@ -1360,13 +1361,13 @@ - PK11SymKey *tkey7 = pk11_derive_wrapper_lsw(tkey6, - CKM_CONCATENATE_BASE_AND_DATA, - counter, -- nss_key_derivation_mech(hasher), -+ nss_key_derivation_mech(prf_hasher), - CKA_DERIVE, - 0); - passert(tkey7 != NULL); - - PK11SymKey *tkey8 = PK11_Derive_lsw(tkey7, -- nss_key_derivation_mech(hasher), -+ nss_key_derivation_mech(prf_hasher), - NULL, - CKM_CONCATENATE_BASE_AND_DATA, - CKA_DERIVE, -@@ -1388,14 +1389,14 @@ - PK11SymKey *tkey10 = PK11_Derive_lsw(tkey9, - CKM_CONCATENATE_BASE_AND_KEY, - ¶m, -- nss_key_derivation_mech(hasher), -+ nss_key_derivation_mech(prf_hasher), - CKA_DERIVE, - 0); - passert(tkey10 != NULL); - - if (vpss.counter[0] == 0x01) { - finalkey = PK11_Derive_lsw(tkey10, -- nss_key_derivation_mech(hasher), -+ nss_key_derivation_mech(prf_hasher), - NULL, - CKM_CONCATENATE_BASE_AND_KEY, - CKA_DERIVE, -@@ -1403,7 +1404,7 @@ - passert(finalkey != NULL); - - tkey11 = PK11_Derive_lsw(tkey10, -- nss_key_derivation_mech(hasher), -+ nss_key_derivation_mech(prf_hasher), - NULL, - CKM_CONCATENATE_BASE_AND_KEY, - CKA_DERIVE, -@@ -1411,7 +1412,7 @@ - passert(tkey11 != NULL); - } else { - tkey11 = PK11_Derive_lsw(tkey10, -- nss_key_derivation_mech(hasher), -+ nss_key_derivation_mech(prf_hasher), - NULL, - CKM_EXTRACT_KEY_FROM_KEY, - CKA_DERIVE, -@@ -1474,13 +1475,13 @@ - - SK_ai_k = pk11_extract_derive_wrapper_lsw(finalkey, next_bit, - CKM_CONCATENATE_BASE_AND_DATA, CKA_DERIVE, -- ska_bytes); -- next_bit += ska_bytes * BITS_PER_BYTE; -+ integ_size); -+ next_bit += integ_size * BITS_PER_BYTE; - - SK_ar_k = pk11_extract_derive_wrapper_lsw(finalkey, next_bit, - CKM_CONCATENATE_BASE_AND_DATA, CKA_DERIVE, -- ska_bytes); -- next_bit += ska_bytes * BITS_PER_BYTE; -+ integ_size); -+ next_bit += integ_size * BITS_PER_BYTE; - - bs = next_bit; - param1.data = (unsigned char*)&bs; -diff -Naur libreswan-3.12-orig/programs/pluto/gcm_test_vectors.c libreswan-3.12/programs/pluto/gcm_test_vectors.c ---- libreswan-3.12-orig/programs/pluto/gcm_test_vectors.c 1969-12-31 19:00:00.000000000 -0500 -+++ libreswan-3.12/programs/pluto/gcm_test_vectors.c 2015-01-20 16:53:19.959651191 -0500 -@@ -0,0 +1,202 @@ -+/* -+ * Copyright (C) 2015 Andrew Cagney -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * for more details. -+ */ -+ -+#include -+#include -+#include "constants.h" -+#include "lswalloc.h" -+#include "lswlog.h" -+ -+#include "ike_alg.h" -+#include "test_buffer.h" -+#include "gcm_test_vectors.h" -+ -+#include "nss.h" -+#include "pk11pub.h" -+ -+struct gcm_test_vector { -+ const char *key; -+ /* -+ * NIST provides a simple IV, while we require a separate SALT -+ * and wire-IV. The value gets split before being passed to -+ * the do_crypt_hash method. -+ */ -+ const char *salted_iv; -+ const char *aad; -+ const char *plaintext; -+ const char *ciphertext; -+ const char *tag; -+}; -+ -+const int salt_size = 4; -+ -+/* -+ * Ref: http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip -+ * -+ * some select entries -+ */ -+const struct gcm_test_vector aes_gcm_test_vectors[] = { -+ { -+ .key ="0xcf063a34d4a9a76c2c86787d3f96db71", -+ .salted_iv = "0x113b9785971864c83b01c787", -+ .ciphertext = "", -+ .aad = "", -+ .tag = "0x72ac8493e3a5228b5d130a69d2510e42", -+ .plaintext = "" -+ }, -+ { -+ .key = "0xe98b72a9881a84ca6b76e0f43e68647a", -+ .salted_iv = "0x8b23299fde174053f3d652ba", -+ .ciphertext = "0x5a3c1cf1985dbb8bed818036fdd5ab42", -+ .aad = "", -+ .tag = "0x23c7ab0f952b7091cd324835043b5eb5", -+ .plaintext = "0x28286a321293253c3e0aa2704a278032", -+ }, -+ { -+ .key = "0xbfd414a6212958a607a0f5d3ab48471d", -+ .salted_iv = "0x86d8ea0ab8e40dcc481cd0e2", -+ .ciphertext = "0x62171db33193292d930bf6647347652c1ef33316d7feca99d54f1db4fcf513f8", -+ .aad = "", -+ .tag = "0xc28280aa5c6c7a8bd366f28c1cfd1f6e", -+ .plaintext = "0xa6b76a066e63392c9443e60272ceaeb9d25c991b0f2e55e2804e168c05ea591a", -+ }, -+ { -+ .key = "0x006c458100fc5f4d62949d2c833b82d1", -+ .salted_iv = "0xa4e9c4bc5725a21ff42c82b2", -+ .ciphertext = "0xf39b4db3542d8542fb73fd2d66be568f26d7f814b3f87d1eceac3dd09a8d697e", -+ .aad = "0x2efb14fb3657cdd6b9a8ff1a5f5a39b9", -+ .tag = "0x39f045cb23b698c925db134d56c5", -+ .plaintext = "0xf381d3bfbee0a879f7a4e17b623278cedd6978053dd313530a18f1a836100950", -+ }, -+ { -+ .key = NULL, -+ } -+}; -+ -+static bool test_gcm_vector(CK_MECHANISM_TYPE cipher_mechanism, -+ bool (*do_crypt_hash)(u_int8_t *salt, size_t salt_size, -+ u_int8_t *wire_iv, size_t wire_iv_size, -+ u_int8_t *aad, size_t aad_size, -+ u_int8_t *text_and_tag, -+ size_t text_size, size_t tag_size, -+ PK11SymKey *key, bool enc), -+ const struct gcm_test_vector *test) -+{ -+ DBG(DBG_CRYPT, DBG_log("test_gcm_vector: enter")); -+ -+ bool ok = TRUE; -+ -+ PK11SymKey *sym_key = decode_to_key(cipher_mechanism, test->key); -+ -+ chunk_t salted_iv = decode_to_chunk("salted IV", test->salted_iv); -+ chunk_t salt = extract_chunk("salt", salted_iv, 0, salt_size); -+ chunk_t wire_iv = extract_chunk("wire-IV", salted_iv, salt_size, -+ salted_iv.len - salt_size); -+ chunk_t aad = decode_to_chunk("AAD", test->aad); -+ chunk_t plaintext = decode_to_chunk("plaintext", test->plaintext); -+ chunk_t ciphertext = decode_to_chunk("ciphertext", test->ciphertext); -+ passert(plaintext.len == ciphertext.len); -+ chunk_t tag = decode_to_chunk("tag", test->tag); -+ -+ chunk_t text_and_tag; -+ text_and_tag.len = plaintext.len + tag.len; -+ text_and_tag.ptr = alloc_bytes(text_and_tag.len, "GCM data"); -+ -+ int enc; -+ for (enc = 0; enc < 2; enc++) { -+ u_int8_t *ptr = text_and_tag.ptr; -+ chunkcpy(ptr, (enc ? plaintext : ciphertext)); -+ if (enc) { -+ memset(ptr, 0, tag.len); -+ ptr += tag.len; -+ } else { -+ chunkcpy(ptr, tag); -+ } -+ passert(ptr == text_and_tag.ptr + text_and_tag.len); -+ -+ DBG(DBG_CRYPT, -+ DBG_log("test_gcm_vector: %s: aad-size=%zd salt-size=%zd wire-IV-size=%zd text-size=%zd tag-size=%zd", -+ enc ? "encrypt" : "decrypt", -+ aad.len, salt.len, wire_iv.len, plaintext.len, tag.len); -+ DBG_dump_chunk("test_gcm_vector: text+tag on call", -+ text_and_tag)); -+ if (!do_crypt_hash(salt.ptr, salt.len, -+ wire_iv.ptr, wire_iv.len, -+ aad.ptr, aad.len, -+ text_and_tag.ptr, -+ plaintext.len, tag.len, -+ sym_key, enc)) { -+ ok = FALSE; -+ } -+ DBG(DBG_CRYPT, DBG_dump_chunk("test_gcm_vector: text+tag on return", -+ text_and_tag)); -+ -+ size_t offset = 0; -+ if (enc) { -+ if (!compare_chunk("output ciphertext", -+ ciphertext, text_and_tag.ptr + offset)) { -+ ok = FALSE; -+ } -+ offset += ciphertext.len; -+ } else { -+ if (!compare_chunk("output plaintext", -+ plaintext, text_and_tag.ptr + offset)) { -+ ok = FALSE; -+ } -+ offset += plaintext.len; -+ } -+ if (!compare_chunk("TAG", tag, text_and_tag.ptr + offset)) { -+ ok = FALSE; -+ } -+ offset += tag.len; -+ -+ passert(offset == text_and_tag.len); -+ } -+ -+ freeanychunk(salted_iv); -+ freeanychunk(wire_iv); -+ freeanychunk(salt); -+ freeanychunk(tag); -+ freeanychunk(plaintext); -+ freeanychunk(ciphertext); -+ freeanychunk(text_and_tag); -+ -+ PK11_FreeSymKey(sym_key); -+ DBG(DBG_CRYPT, DBG_log("test_gcm_vector: %s", ok ? "passed" : "failed")); -+ return ok; -+} -+ -+static bool test_gcm_vectors(CK_MECHANISM_TYPE cipher_mechanism, -+ bool (*do_crypt_hash)(u_int8_t *salt, size_t salt_size, -+ u_int8_t *wire_iv, size_t wire_iv_size, -+ u_int8_t *aad, size_t aad_size, -+ u_int8_t *text_and_tag, -+ size_t text_size, size_t tag_size, -+ PK11SymKey *key, bool enc), -+ const struct gcm_test_vector *tests) -+{ -+ bool ok = TRUE; -+ const struct gcm_test_vector *test; -+ for (test = tests; test->key != NULL; test++) { -+ if (!test_gcm_vector(cipher_mechanism, do_crypt_hash, test)) { -+ ok = FALSE; -+ } -+ } -+ return ok; -+} -+ -+bool test_aes_gcm() -+{ -+ return test_gcm_vectors(CKM_AES_GCM, do_aes_gcm, aes_gcm_test_vectors); -+} -diff -Naur libreswan-3.12-orig/programs/pluto/gcm_test_vectors.h libreswan-3.12/programs/pluto/gcm_test_vectors.h ---- libreswan-3.12-orig/programs/pluto/gcm_test_vectors.h 1969-12-31 19:00:00.000000000 -0500 -+++ libreswan-3.12/programs/pluto/gcm_test_vectors.h 2015-01-20 16:53:19.960651219 -0500 -@@ -0,0 +1,22 @@ -+/* -+ * Copyright (C) 2015 Andrew Cagney -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * for more details. -+ */ -+ -+bool test_aes_gcm(); -+ -+bool do_aes_gcm(u_int8_t *salt, size_t salt_size, -+ u_int8_t *wire_iv, size_t wire_iv_size, -+ u_int8_t *aad, size_t aad_size, -+ u_int8_t *text_and_tag, -+ size_t text_size, size_t tag_size, -+ PK11SymKey *key, bool enc); -diff -Naur libreswan-3.12-orig/programs/pluto/ike_alg_aes.c libreswan-3.12/programs/pluto/ike_alg_aes.c ---- libreswan-3.12-orig/programs/pluto/ike_alg_aes.c 2015-01-20 16:52:43.652654163 -0500 -+++ libreswan-3.12/programs/pluto/ike_alg_aes.c 2015-01-20 16:53:19.960651219 -0500 -@@ -5,6 +5,7 @@ - * Copyright (C) 2012-2014 Paul Wouters - * Copyright (C) 2013 Florian Weimer - * Copyright (C) 2013 D. Hugh Redelmeier -+ * Copyright (C) 2014-2015 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 -@@ -39,6 +40,7 @@ - #include "ike_alg_nss_cbc.h" - #include "ctr_test_vectors.h" - #include "cbc_test_vectors.h" -+#include "gcm_test_vectors.h" - - static void aes_xcbc_init_thunk(union hash_ctx *ctx) - { -@@ -55,7 +57,6 @@ - aes_xcbc_final(hash, &ctx->ctx_aes_xcbc); - } - -- - static void do_aes_cbc(u_int8_t *buf, size_t buf_len, PK11SymKey *symkey, - u_int8_t *iv, bool enc); - -@@ -178,6 +179,201 @@ - .do_crypt = do_aes_ctr, - }; - -+bool do_aes_gcm(u_int8_t *salt, size_t salt_size, -+ u_int8_t *wire_iv, size_t wire_iv_size, -+ u_int8_t *aad, size_t aad_size, -+ u_int8_t *text_and_tag, -+ size_t text_size, size_t tag_size, -+ PK11SymKey *sym_key, bool enc) -+{ -+ /* See pk11gcmtest.c */ -+ bool ok = TRUE; -+ -+ u_int8_t iv[AES_BLOCK_SIZE]; -+ passert(sizeof iv >= wire_iv_size + salt_size); -+ memcpy(iv, salt, salt_size); -+ memcpy(iv + salt_size, wire_iv, wire_iv_size); -+ -+ CK_GCM_PARAMS gcm_params; -+ gcm_params.pIv = iv; -+ gcm_params.ulIvLen = salt_size + wire_iv_size; -+ gcm_params.pAAD = aad; -+ gcm_params.ulAADLen = aad_size; -+ gcm_params.ulTagBits = tag_size * 8; -+ -+ SECItem param; -+ param.type = siBuffer; -+ param.data = (void*)&gcm_params; -+ param.len = sizeof gcm_params; -+ -+ /* Output buffer for transformed data. */ -+ size_t text_and_tag_size = text_size + tag_size; -+ u_int8_t *out_buf = PR_Malloc(text_and_tag_size); -+ unsigned int out_len = 0; -+ -+ if (enc) { -+ SECStatus rv = PK11_Encrypt(sym_key, CKM_AES_GCM, ¶m, -+ out_buf, &out_len, text_and_tag_size, -+ text_and_tag, text_size); -+ if (rv != SECSuccess) { -+ loglog(RC_LOG_SERIOUS, -+ "do_aes_gcm: PK11_Encrypt failure (err %d)", PR_GetError()); -+ ok = FALSE; -+ } else if (out_len != text_and_tag_size) { -+ loglog(RC_LOG_SERIOUS, -+ "do_aes_gcm: PK11_Encrypt output length of %u not the expected %zd", -+ out_len, text_and_tag_size); -+ ok = FALSE; -+ } -+ } else { -+ SECStatus rv = PK11_Decrypt(sym_key, CKM_AES_GCM, ¶m, -+ out_buf, &out_len, text_and_tag_size, -+ text_and_tag, text_and_tag_size); -+ if (rv != SECSuccess) { -+ loglog(RC_LOG_SERIOUS, -+ "do_aes_gcm: PK11_Decrypt failure (err %d)", PR_GetError()); -+ ok = FALSE; -+ } else if (out_len != text_size) { -+ loglog(RC_LOG_SERIOUS, -+ "do_aes_gcm: PK11_Decrypt output length of %u not the expected %zd", -+ out_len, text_size); -+ ok = FALSE; -+ } -+ } -+ -+ memcpy(text_and_tag, out_buf, out_len); -+ PR_Free(out_buf); -+ -+ return ok; -+} -+ -+static struct encrypt_desc algo_aes_gcm_8 = -+{ -+ .common = { -+ .name = "aes_gcm", -+ .officname = "aes_gcm", -+ .algo_type = IKE_ALG_ENCRYPT, -+ .algo_id = OAKLEY_AES_GCM_8, -+ .algo_v2id = IKEv2_ENCR_AES_GCM_8, -+ .algo_next = NULL, -+ }, -+ .enc_ctxsize = sizeof(aes_context), -+ .enc_blocksize = AES_BLOCK_SIZE, -+ .pad_to_blocksize = FALSE, -+ .wire_iv_size = 8, -+ .salt_size = AES_GCM_SALT_BYTES, -+ .keyminlen = AES_GCM_KEY_MIN_LEN, -+ .keydeflen = AES_GCM_KEY_DEF_LEN, -+ .keymaxlen = AES_GCM_KEY_MAX_LEN, -+ .aead_tag_size = 8, -+ .do_aead_crypt_auth = do_aes_gcm, -+}; -+ -+static struct encrypt_desc algo_aes_gcm_12 = -+{ -+ .common = { -+ .name = "aes_gcm_12", -+ .officname = "aes_gcm_12", -+ .algo_type = IKE_ALG_ENCRYPT, -+ .algo_id = OAKLEY_AES_GCM_12, -+ .algo_v2id = IKEv2_ENCR_AES_GCM_12, -+ .algo_next = NULL, -+ }, -+ .enc_blocksize = AES_BLOCK_SIZE, -+ .wire_iv_size = 8, -+ .pad_to_blocksize = FALSE, -+ .salt_size = AES_GCM_SALT_BYTES, -+ .keyminlen = AEAD_AES_KEY_MIN_LEN, -+ .keydeflen = AEAD_AES_KEY_DEF_LEN, -+ .keymaxlen = AEAD_AES_KEY_MAX_LEN, -+ .aead_tag_size = 12, -+ .do_aead_crypt_auth = do_aes_gcm, -+}; -+ -+static struct encrypt_desc algo_aes_gcm_16 = -+{ -+ .common = { -+ .name = "aes_gcm_16", -+ .officname = "aes_gcm_16", -+ .algo_type = IKE_ALG_ENCRYPT, -+ .algo_id = OAKLEY_AES_GCM_16, -+ .algo_v2id = IKEv2_ENCR_AES_GCM_16, -+ .algo_next = NULL, -+ }, -+ .enc_blocksize = AES_BLOCK_SIZE, -+ .wire_iv_size = 8, -+ .pad_to_blocksize = FALSE, -+ .salt_size = AES_GCM_SALT_BYTES, -+ .keyminlen = AEAD_AES_KEY_MIN_LEN, -+ .keydeflen = AEAD_AES_KEY_DEF_LEN, -+ .keymaxlen = AEAD_AES_KEY_MAX_LEN, -+ .aead_tag_size = 16, -+ .do_aead_crypt_auth = do_aes_gcm, -+}; -+ -+#ifdef NOT_YET -+/* -+ * XXX: This code is duplicated in kernel_netlink.c. Once this is -+ * enabled, the latter can be deleted. -+ */ -+static struct encrypt_desc algo_aes_ccm_8 = -+{ -+ .common = { -+ .name = "aes_ccm_8", -+ .officname = "aes_ccm_8", -+ .algo_type = IKE_ALG_ENCRYPT, -+ .algo_id = OAKLEY_AES_CCM_8, -+ .algo_v2id = IKEv2_ENCR_AES_CCM_8, -+ .algo_next = NULL, -+ }, -+ .enc_blocksize = AES_BLOCK_SIZE, -+ .wire_iv_size = 8, -+ .pad_to_blocksize = FALSE, -+ /* Only 128, 192 and 256 are supported (24 bits KEYMAT for salt not included) */ -+ .keyminlen = AEAD_AES_KEY_MIN_LEN, -+ .keydeflen = AEAD_AES_KEY_DEF_LEN, -+ .keymaxlen = AEAD_AES_KEY_MAX_LEN, -+}; -+ -+static struct encrypt_desc algo_aes_ccm_12 = -+{ -+ .common = { -+ .name = "aes_ccm_12", -+ .officname = "aes_ccm_12", -+ .algo_type = IKE_ALG_ENCRYPT, -+ .algo_id = OAKLEY_AES_CCM_12, -+ .algo_v2id = IKEv2_ENCR_AES_CCM_12, -+ .algo_next = NULL, -+ }, -+ .enc_blocksize = AES_BLOCK_SIZE, -+ .wire_iv_size = 8, -+ .pad_to_blocksize = FALSE, -+ /* Only 128, 192 and 256 are supported (24 bits KEYMAT for salt not included) */ -+ .keyminlen = AEAD_AES_KEY_MIN_LEN, -+ .keydeflen = AEAD_AES_KEY_DEF_LEN, -+ .keymaxlen = AEAD_AES_KEY_MAX_LEN, -+}; -+ -+static struct encrypt_desc algo_aes_ccm_16 = -+{ -+ .common = { -+ .name = "aes_ccm_16", -+ .officname = "aes_ccm_16", -+ .algo_type = IKE_ALG_ENCRYPT, -+ .algo_id = OAKLEY_AES_CCM_16, -+ .algo_v2id = IKEv2_ENCR_AES_CCM_16, -+ .algo_next = NULL, -+ }, -+ .enc_blocksize = AES_BLOCK_SIZE, -+ .wire_iv_size = 8, -+ .pad_to_blocksize = FALSE, -+ /* Only 128, 192 and 256 are supported (24 bits KEYMAT for salt not included) */ -+ .keyminlen = AEAD_AES_KEY_MIN_LEN, -+ .keydeflen = AEAD_AES_KEY_DEF_LEN, -+ .keymaxlen = AEAD_AES_KEY_MAX_LEN, -+}; -+#endif -+ - static struct hash_desc hash_desc_aes_xcbc = { - .common = { .officname = "aes_xcbc", - .algo_type = IKE_ALG_HASH, -@@ -226,6 +422,29 @@ - if (ike_alg_register_enc(&algo_aes_ctr) != 1) - loglog(RC_LOG_SERIOUS, "Warning: failed to register algo_aes_ctr for IKE"); - -+ if (!test_aes_gcm()) { -+ loglog(RC_LOG_SERIOUS, "CKM_AES_GCM: test failure"); -+ } -+ if (ike_alg_register_enc(&algo_aes_gcm_8) != 1) -+ loglog(RC_LOG_SERIOUS, "Warning: failed to register algo_aes_gcm_8 for IKE"); -+ if (ike_alg_register_enc(&algo_aes_gcm_12) != 1) -+ loglog(RC_LOG_SERIOUS, "Warning: failed to register algo_aes_gcm_12 for IKE"); -+ if (ike_alg_register_enc(&algo_aes_gcm_16) != 1) -+ loglog(RC_LOG_SERIOUS, "Warning: failed to register algo_aes_gcm_16 for IKE"); -+ -+#ifdef NOT_YET -+ /* -+ * XXX: This code is duplicated in kernel_netlink.c. Once -+ * this is enabled, the latter can be deleted. -+ */ -+ if (!ike_alg_register_enc(&algo_aes_ccm_8)) -+ loglog(RC_LOG_SERIOUS, "Warning: failed to register algo_aes_ccm_8 for IKE"); -+ if (!ike_alg_register_enc(&algo_aes_ccm_12)) -+ loglog(RC_LOG_SERIOUS, "Warning: failed to register algo_aes_ccm_12 for IKE"); -+ if (!ike_alg_register_enc(&algo_aes_ccm_16)) -+ loglog(RC_LOG_SERIOUS, "Warning: failed to register algo_aes_ccm_16 for IKE"); -+#endif -+ - /* Waiting on NSS support - but we need registration so ESP will work */ - if (ike_alg_register_hash(&hash_desc_aes_xcbc) != 1) - loglog(RC_LOG_SERIOUS, "Warning: failed to register hash algo_aes_xcbc for IKE"); -diff -Naur libreswan-3.12-orig/programs/pluto/ike_alg.c libreswan-3.12/programs/pluto/ike_alg.c ---- libreswan-3.12-orig/programs/pluto/ike_alg.c 2015-01-20 16:52:43.594652570 -0500 -+++ libreswan-3.12/programs/pluto/ike_alg.c 2015-01-20 16:53:19.961651246 -0500 -@@ -59,7 +59,11 @@ - - struct ike_alg *ike_alg_base[IKE_ALG_ROOF] = { NULL, NULL, NULL }; - --/* check if IKE encrypt algo is present */ -+bool ike_alg_enc_requires_integ(const struct encrypt_desc *enc_desc) -+{ -+ return enc_desc != NULL && enc_desc->do_aead_crypt_auth == NULL; -+} -+ - bool ike_alg_enc_present(int ealg) - { - struct encrypt_desc *enc_desc = ike_alg_get_encrypter(ealg); -diff -Naur libreswan-3.12-orig/programs/pluto/ike_alg.h libreswan-3.12/programs/pluto/ike_alg.h ---- libreswan-3.12-orig/programs/pluto/ike_alg.h 2015-01-20 16:52:43.654654218 -0500 -+++ libreswan-3.12/programs/pluto/ike_alg.h 2015-01-20 16:53:19.962651274 -0500 -@@ -54,6 +54,33 @@ - PK11SymKey *key, - u_int8_t *iv, - bool enc); -+ -+ /* -+ * For Authenticated Encryption with Associated Data (AEAD), -+ * the size (in 8-bit bytes) of the authentication tag -+ * appended to the end of the encrypted data. -+ */ -+ size_t aead_tag_size; -+ -+ /* -+ * Perform Authenticated Encryption with Associated Data -+ * (AEAD). -+ * -+ * The salt and wire-IV are concatenated to form the NONCE -+ * (aka. counter variable; IV; ...). -+ * -+ * The Additional Authentication Data (AAD) and the -+ * cipher-text are concatenated when generating/validating the -+ * tag (which is appended to the text). -+ * -+ * All sizes are in 8-bit bytes. -+ */ -+ bool (*do_aead_crypt_auth)(u_int8_t *salt, size_t salt_size, -+ u_int8_t *wire_iv, size_t wire_iv_size, -+ u_int8_t *aad, size_t aad_size, -+ u_int8_t *text_and_tag, -+ size_t text_size, size_t tag_size, -+ PK11SymKey *key, bool enc); - }; - - union hash_ctx; /* forward declaration */ -@@ -90,6 +117,7 @@ - - extern bool ike_alg_enc_present(int ealg); - extern bool ike_alg_hash_present(int halg); -+extern bool ike_alg_enc_requires_integ(const struct encrypt_desc *enc_desc); - extern bool ike_alg_enc_ok(int ealg, unsigned key_len, - struct alg_info_ike *alg_info_ike, const char **, char *, - size_t); -diff -Naur libreswan-3.12-orig/programs/pluto/ikev2_parent.c libreswan-3.12/programs/pluto/ikev2_parent.c ---- libreswan-3.12-orig/programs/pluto/ikev2_parent.c 2015-01-20 16:52:43.657654300 -0500 -+++ libreswan-3.12/programs/pluto/ikev2_parent.c 2015-01-20 16:53:19.965651356 -0500 -@@ -12,6 +12,7 @@ - * Copyright (C) 2013 D. Hugh Redelmeier - * Copyright (C) 2013 David McCullough - * Copyright (C) 2013 Matt Rogers -+ * Copyright (C) 2015 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 -@@ -1375,29 +1376,38 @@ - } - - b12 = e_pbs->cur; -- if (!out_zero(pst->st_oakley.integ_hasher->hash_integ_len, e_pbs, -- "length of truncated HMAC")) -+ size_t integ_size = (ike_alg_enc_requires_integ(pst->st_oakley.encrypter) -+ ? pst->st_oakley.integ_hasher->hash_integ_len -+ : pst->st_oakley.encrypter->aead_tag_size); -+ if (integ_size == 0) { -+ DBG(DBG_CRYPT, DBG_log("ikev2_authloc: HMAC/KEY size is zero")); - return NULL; -+ } -+ -+ if (!out_zero(integ_size, e_pbs, "length of truncated HMAC/KEY")) { -+ return NULL; -+ } - - return b12; - } - - static stf_status ikev2_encrypt_msg(struct state *st, - enum phase1_role role, -- unsigned char *authstart, -- unsigned char *wire_iv, -- unsigned char *encstart, -- unsigned char *authloc, -+ unsigned char *auth_start, -+ unsigned char *wire_iv_start, -+ unsigned char *enc_start, -+ unsigned char *integ_start, - pb_stream *e_pbs UNUSED, - pb_stream *e_pbs_cipher) - { - struct state *pst = st; -- PK11SymKey *cipherkey, *authkey; - - if (IS_CHILD_SA(st)) - pst = state_with_serialno(st->st_clonedfrom); - - chunk_t salt; -+ PK11SymKey *cipherkey; -+ PK11SymKey *authkey; - if (role == O_INITIATOR) { - cipherkey = pst->st_skey_ei_nss; - authkey = pst->st_skey_ai_nss; -@@ -1408,52 +1418,86 @@ - salt = pst->st_skey_responder_salt; - } - -- /* encrypt the block */ -- { -+ /* size of plain or cipher text. */ -+ size_t enc_size = e_pbs_cipher->cur - enc_start; -+ -+ /* encrypt and authenticate the block */ -+ if (ike_alg_enc_requires_integ(st->st_oakley.encrypter)) { - /* note: no iv is longer than MAX_CBC_BLOCK_SIZE */ - unsigned char enc_iv[MAX_CBC_BLOCK_SIZE]; - construct_enc_iv("encryption IV/starting-variable", enc_iv, -- wire_iv, salt, -+ wire_iv_start, salt, - pst->st_oakley.encrypter); - -- unsigned int cipherlen = e_pbs_cipher->cur - encstart; -- - DBG(DBG_CRYPT, -- DBG_dump("data before encryption:", encstart, cipherlen)); -+ DBG_dump("data before encryption:", enc_start, enc_size)); - - /* now, encrypt */ -- (st->st_oakley.encrypter->do_crypt)(encstart, -- cipherlen, -+ (st->st_oakley.encrypter->do_crypt)(enc_start, enc_size, - cipherkey, - enc_iv, TRUE); - - DBG(DBG_CRYPT, -- DBG_dump("data after encryption:", encstart, cipherlen)); -+ DBG_dump("data after encryption:", enc_start, enc_size)); - /* note: saved_iv's updated value is discarded */ -- } - -- /* okay, authenticate from beginning of IV */ -- { -+ /* okay, authenticate from beginning of IV */ - struct hmac_ctx ctx; - DBG(DBG_PARSING, DBG_log("Inside authloc")); - DBG(DBG_CRYPT, - DBG_log("authkey pointer: %p", authkey)); - hmac_init(&ctx, pst->st_oakley.integ_hasher, authkey); - DBG(DBG_PARSING, DBG_log("Inside authloc after init")); -- hmac_update(&ctx, authstart, authloc - authstart); -+ hmac_update(&ctx, auth_start, integ_start - auth_start); - DBG(DBG_PARSING, DBG_log("Inside authloc after update")); -- hmac_final(authloc, &ctx); -+ hmac_final(integ_start, &ctx); - DBG(DBG_PARSING, DBG_log("Inside authloc after final")); - - DBG(DBG_PARSING, { -- DBG_dump("data being hmac:", authstart, authloc - -- authstart); -- DBG_dump("out calculated auth:", authloc, -+ DBG_dump("data being hmac:", auth_start, -+ integ_start - auth_start); -+ DBG_dump("out calculated auth:", integ_start, - pst->st_oakley.integ_hasher-> - hash_integ_len); - }); -+ } else { -+ size_t wire_iv_size = pst->st_oakley.encrypter->wire_iv_size; -+ size_t integ_size = pst->st_oakley.encrypter->aead_tag_size; -+ /* -+ * Additional Authenticated Data - AAD - size. -+ * RFC5282 says: The Initialization Vector and Ciphertext -+ * fields [...] MUST NOT be included in the associated -+ * data. -+ */ -+ unsigned char *aad_start = auth_start; -+ size_t aad_size = enc_start - aad_start - wire_iv_size; -+ -+ DBG(DBG_CRYPT, -+ DBG_dump_chunk("Salt before authenticated encryption:", salt); -+ DBG_dump("IV before authenticated encryption:", -+ wire_iv_start, wire_iv_size); -+ DBG_dump("AAD before authenticated encryption:", -+ aad_start, aad_size); -+ DBG_dump("data before authenticated encryption:", -+ enc_start, enc_size); -+ DBG_dump("integ before authenticated encryption:", -+ integ_start, integ_size)); -+ if (!st->st_oakley.encrypter-> -+ do_aead_crypt_auth(salt.ptr, salt.len, -+ wire_iv_start, wire_iv_size, -+ aad_start, aad_size, -+ enc_start, enc_size, integ_size, -+ cipherkey, TRUE)) { -+ return STF_FAIL; -+ } -+ DBG(DBG_CRYPT, -+ DBG_dump("data after authenticated encryption:", -+ enc_start, enc_size); -+ DBG_dump("integ after authenticated encryption:", -+ integ_start, integ_size)); - } - -+ - return STF_OK; - } - -@@ -1477,14 +1521,6 @@ - struct state *pst = IS_CHILD_SA(st) ? - state_with_serialno(st->st_clonedfrom) : st; - pb_stream *e_pbs = &md->chain[ISAKMP_NEXT_v2E]->pbs; -- unsigned char *authstart = md->packet_pbs.start; -- u_char *wire_iv = e_pbs->cur; /* start of wire-IV, right after header */ -- const size_t wire_iv_size = pst->st_oakley.encrypter->wire_iv_size; -- size_t integ_len = pst->st_oakley.integ_hasher->hash_integ_len; -- const size_t enc_blocksize = pst->st_oakley.encrypter->enc_blocksize; -- const bool pad_to_blocksize = pst->st_oakley.encrypter->pad_to_blocksize; -- unsigned char *roof= e_pbs->roof; -- PK11SymKey *cipherkey, *authkey; - - if (st != NULL && !st->hidden_variables.st_skeyid_calculated) - { -@@ -1499,21 +1535,51 @@ - }); - return STF_FAIL; - } -+ -+ u_char *wire_iv_start = e_pbs->cur; -+ size_t wire_iv_size = pst->st_oakley.encrypter->wire_iv_size; -+ size_t integ_size = (ike_alg_enc_requires_integ(pst->st_oakley.encrypter) -+ ? pst->st_oakley.integ_hasher->hash_integ_len -+ : pst->st_oakley.encrypter->aead_tag_size); -+ - /* -- * check to see if length is plausible. Need room for: -- * - IV (at start) -- * - the padding-length byte -- * - truncated integrity digest (at end) -+ * check to see if length is plausible: -+ * - wire-IV -+ * - encoded data (possibly empty) -+ * - at least one padding-length byte -+ * - truncated integrity digest / tag - */ -- if (roof - wire_iv < (ptrdiff_t)(wire_iv_size + 1 + integ_len)) { -- libreswan_log("encrypted payload impossibly short (%td)", -- roof - wire_iv); -+ u_char *payload_end = e_pbs->roof; -+ if (payload_end < (wire_iv_start + wire_iv_size + 1 + integ_size)) { -+ libreswan_log("encrypted payload impossibly short (%zu)", -+ payload_end - wire_iv_start); - return STF_FAIL; - } - -- roof -= integ_len; /* strip truncated digest */ -+ u_char *auth_start = md->packet_pbs.start; -+ u_char *enc_start = wire_iv_start + wire_iv_size; -+ u_char *integ_start = payload_end - integ_size; -+ size_t enc_size = integ_start - enc_start; -+ -+ /* -+ * Check if block-size is valid. Do this before the payload's -+ * integrity has been verified as block-alignment requirements -+ * aren't exactly secret (originally this was being done -+ * beteen integrity and decrypt). -+ */ -+ size_t enc_blocksize = pst->st_oakley.encrypter->enc_blocksize; -+ bool pad_to_blocksize = pst->st_oakley.encrypter->pad_to_blocksize; -+ if (pad_to_blocksize) { -+ if (enc_size % enc_blocksize != 0) { -+ libreswan_log("cyphertext length (%zu) not a multiple of blocksize (%zu)", -+ enc_size, enc_blocksize); -+ return STF_FAIL; -+ } -+ } - - chunk_t salt; -+ PK11SymKey *cipherkey; -+ PK11SymKey *authkey; - if (role == O_INITIATOR) { - cipherkey = pst->st_skey_er_nss; - authkey = pst->st_skey_ar_nss; -@@ -1524,80 +1590,96 @@ - salt = pst->st_skey_initiator_salt; - } - -- /* -- * check authenticator -- * The last [integ_len] bytes are the truncated digest. -- */ -- { -+ /* authenticate and decrypt the block. */ -+ if (ike_alg_enc_requires_integ(st->st_oakley.encrypter)) { -+ /* -+ * check authenticator. The last INTEG_SIZE bytes are -+ * the truncated digest. -+ */ - unsigned char td[MAX_DIGEST_LEN]; - struct hmac_ctx ctx; - - hmac_init(&ctx, pst->st_oakley.integ_hasher, authkey); -- hmac_update(&ctx, authstart, roof - authstart); -+ hmac_update(&ctx, auth_start, integ_start - auth_start); - hmac_final(td, &ctx); - - DBG(DBG_PARSING, { - DBG_dump("data for hmac:", -- authstart, roof - authstart); -+ auth_start, integ_start - auth_start); - DBG_dump("calculated auth:", -- td, -- pst->st_oakley.integ_hasher-> hash_integ_len); -+ td, integ_size); - DBG_dump(" provided auth:", -- roof, -- pst->st_oakley.integ_hasher->hash_integ_len); -+ integ_start, integ_size); - }); - -- if (!memeq(td, roof, integ_len)) { -+ if (!memeq(td, integ_start, integ_size)) { - libreswan_log("failed to match authenticator"); - return STF_FAIL; - } -- } - -- DBG(DBG_PARSING, DBG_log("authenticator matched")); -+ DBG(DBG_PARSING, DBG_log("authenticator matched")); -+ -+ /* decrypt */ - -- /* decrypt */ -- { -- u_char *encstart = wire_iv + wire_iv_size; -- size_t enclen = roof - encstart; - /* note: no iv is longer than MAX_CBC_BLOCK_SIZE */ - unsigned char enc_iv[MAX_CBC_BLOCK_SIZE]; - construct_enc_iv("decription IV/starting-variable", enc_iv, -- wire_iv, salt, -+ wire_iv_start, salt, - pst->st_oakley.encrypter); - - DBG(DBG_CRYPT, -- DBG_dump("data before decryption:", encstart, enclen)); -- -- if (pad_to_blocksize) { -- if (enclen % enc_blocksize != 0) { -- libreswan_log("cyphertext length (%zu) not a multiple of blocksize (%zu)", -- enclen, enc_blocksize); -- return STF_FAIL; -- } -- } -- -- /* now, decrypt */ -- (pst->st_oakley.encrypter->do_crypt)(encstart, -- enclen, -+ DBG_dump("payload before decryption:", enc_start, enc_size)); -+ (pst->st_oakley.encrypter->do_crypt)(enc_start, enc_size, - cipherkey, - enc_iv, FALSE); -+ DBG(DBG_CRYPT, -+ DBG_dump("payload after decryption:", enc_start, enc_size)); - -- u_char padlen = encstart[enclen - 1] + 1; -- if (padlen > enc_blocksize || padlen > enclen) { -- libreswan_log("invalid padding-length octet: 0x%2x", padlen - 1); -- return STF_FAIL; -- } -+ } else { -+ /* -+ * Additional Authenticated Data - AAD - size. -+ * RFC5282 says: The Initialization Vector and Ciphertext -+ * fields [...] MUST NOT be included in the associated -+ * data. -+ */ -+ unsigned char *aad_start = auth_start; -+ size_t aad_size = enc_start - auth_start - wire_iv_size; - -- /* don't bother to check any other pad octets */ -+ DBG(DBG_CRYPT, -+ DBG_dump_chunk("Salt before authenticated decryption:", salt); -+ DBG_dump("IV before authenticated decryption:", -+ wire_iv_start, wire_iv_size); -+ DBG_dump("AAD before authenticated decryption:", -+ aad_start, aad_size); -+ DBG_dump("data before authenticated decryption:", -+ enc_start, enc_size); -+ DBG_dump("integ before authenticated decryption:", -+ integ_start, integ_size)); -+ if (!st->st_oakley.encrypter-> -+ do_aead_crypt_auth(salt.ptr, salt.len, -+ wire_iv_start, wire_iv_size, -+ aad_start, aad_size, -+ enc_start, enc_size, integ_size, -+ cipherkey, FALSE)) { -+ return STF_FAIL; /* sub-code? */ -+ } -+ DBG(DBG_CRYPT, -+ DBG_dump("data after authenticated decryption:", -+ enc_start, enc_size + integ_size)); -+ } - -- DBG(DBG_CRYPT, { -- DBG_dump("decrypted payload:", encstart, enclen); -- DBG_log("striping %u bytes as pad", padlen); -- }); - -- init_pbs(&md->clr_pbs, encstart, enclen - padlen, "cleartext"); -+ u_char padlen = enc_start[enc_size - 1] + 1; -+ if (padlen > enc_blocksize || padlen > enc_size) { -+ libreswan_log("invalid padding-length octet: 0x%2x", padlen - 1); -+ return STF_FAIL; - } - -+ /* don't bother to check any other pad octets */ -+ DBG(DBG_CRYPT, DBG_log("striping %u bytes as pad", padlen)); -+ -+ init_pbs(&md->clr_pbs, enc_start, enc_size - padlen, "cleartext"); -+ - return ikev2_process_payloads(md, &md->clr_pbs, - md->chain[ISAKMP_NEXT_v2E]->payload.generic.isag_np, - TRUE); -diff -Naur libreswan-3.12-orig/programs/pluto/ikev2_spdb_struct.c libreswan-3.12/programs/pluto/ikev2_spdb_struct.c ---- libreswan-3.12-orig/programs/pluto/ikev2_spdb_struct.c 2015-01-20 16:52:43.631653586 -0500 -+++ libreswan-3.12/programs/pluto/ikev2_spdb_struct.c 2015-01-20 16:53:19.968651438 -0500 -@@ -6,6 +6,7 @@ - * Copyright (C) 2012-2013 Paul Wouters - * Copyright (C) 2012 Avesh Agarwal - * Copyright (C) 2012-2013 D. Hugh Redelmeier -+ * Copyright (C) 2015 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 -@@ -292,48 +293,29 @@ - - static enum ikev2_trans_type_encr v1tov2_encr(int oakley) - { -- switch (oakley) { -- case OAKLEY_DES_CBC: -- return IKEv2_ENCR_DES; -- -- case OAKLEY_IDEA_CBC: -- return IKEv2_ENCR_IDEA; -- -- case OAKLEY_RC5_R16_B64_CBC: -- return IKEv2_ENCR_RC5; -- -- case OAKLEY_3DES_CBC: -- return IKEv2_ENCR_3DES; -- -- case OAKLEY_CAST_CBC: -- return IKEv2_ENCR_CAST; -- -- case OAKLEY_AES_CBC: -- return IKEv2_ENCR_AES_CBC; -- -- case OAKLEY_AES_CTR: -- return IKEv2_ENCR_AES_CTR; -- -- case OAKLEY_CAMELLIA_CBC: -- return IKEv2_ENCR_CAMELLIA_CBC; -- -- case OAKLEY_TWOFISH_CBC_SSH: -- return IKEv2_ENCR_TWOFISH_CBC_SSH; -- -- case OAKLEY_TWOFISH_CBC: -- return IKEv2_ENCR_TWOFISH_CBC; -- -- case OAKLEY_SERPENT_CBC: -- return IKEv2_ENCR_SERPENT_CBC; -- -- /* -- * We have some encryption algorithms in IKEv2 that do not exist in -- * IKEv1. This is a bad hack and the caller should be aware -- */ -- -- default: -- DBG(DBG_CONTROL, DBG_log("v1tov2_encr() missing v1 encr transform '%d'",oakley)); -+ struct ike_alg *alg = ikev1_alg_find(IKE_ALG_ENCRYPT, oakley); -+ if (alg == NULL) { -+ /* -+ * Outch, somehow the v1 algorithm we found earlier -+ * has disappeared! -+ */ -+ DBG(DBG_CONTROL, DBG_log("v1tov2_encr() unknown v1 encrypt algorithm '%d'", oakley)); - return IKEv2_ENCR_INVALID; /* this cannot go over the wire! It's 65536 */ -+ } else if (alg->algo_v2id == 0) { -+ /* -+ * We have some encryption algorithms in IKEv2 that do -+ * not exist in IKEv1 but this code assumes that they -+ * do. Someone will have to add another unofficial -+ * IKEv1 algorithm id to its table or just not use -+ * this function. -+ * -+ * Better, would be to just pass the ike_alg struct -+ * around. -+ */ -+ DBG(DBG_CONTROL, DBG_log("v1tov2_encr() v1 encrypt algorithm '%d' has no v2 counterpart", oakley)); -+ return IKEv2_ENCR_INVALID; /* this cannot go over the wire! It's 65536 */ -+ } else { -+ return alg->algo_v2id; - } - } - -@@ -488,7 +470,6 @@ - break; - - case OAKLEY_ENCRYPTION_ALGORITHM: -- /* XXX fails on IKEv2-only enc algos like CCM/GCM */ - dtfone->encr_transid = - v1tov2_encr( - attr->val); -@@ -503,6 +484,11 @@ - attr->val); - break; - -+ case OAKLEY_PRF: -+ dtfone->prf_transid = -+ v1tov2_prf(attr->val); -+ break; -+ - case OAKLEY_GROUP_DESCRIPTION: - dtfone->group_transid = - attr->val; -@@ -722,7 +708,8 @@ - int integ_keylen, - unsigned prf_transform, - int prf_keylen, -- unsigned dh_transform) -+ unsigned dh_transform, -+ bool enc_requires_integ) - { - unsigned int pd_cnt; - -@@ -730,16 +717,17 @@ - struct db_v2_prop *pd = &sadb->prop_disj[pd_cnt]; - struct db_v2_prop_conj *pj; - unsigned int tr_cnt; -- bool -- encr_matched = FALSE, -- integ_matched = FALSE, -- prf_matched = FALSE, -- dh_matched = FALSE; -+ bool encr_matched = FALSE; -+ bool integ_matched = FALSE; -+ bool integ_checked = FALSE; -+ bool prf_matched = FALSE; -+ bool dh_matched = FALSE; - int - encrid = 0, -- integid = 0, - prfid = 0, - dhid = 0; -+ unsigned int integid = 0; -+ - int - encrwin = -2, - integwin = -2, -@@ -757,8 +745,6 @@ - - for (tr_cnt = 0; tr_cnt < pj->trans_cnt; tr_cnt++) { - struct db_v2_trans *tr = &pj->trans[tr_cnt]; -- int keylen = -1; -- unsigned int attr_cnt; - - DBG(DBG_CONTROL, DBG_log( - "considering Transform Type %s, TransID %d", -@@ -766,8 +752,9 @@ - tr->transform_type), - tr->transid)); - -- for (attr_cnt = 0; attr_cnt < tr->attr_cnt; -- attr_cnt++) { -+ int keylen = -1; -+ unsigned int attr_cnt; -+ for (attr_cnt = 0; attr_cnt < tr->attr_cnt; attr_cnt++) { - struct db_attr *attr = &tr->attrs[attr_cnt]; - - if (attr->type.v2 == IKEv2_KEY_LENGTH) { -@@ -802,11 +789,27 @@ - break; - - case IKEv2_TRANS_TYPE_INTEG: -+ /* -+ * When AEAD, current logic -+ * (2015-01-08) still sends a single -+ * AUTH_NONE INTEG transform, handle -+ * that. -+ */ - integid = tr->transid; -- if (tr->transid == integ_transform && -- keylen == integ_keylen) { -- integ_matched = TRUE; -- integwin = keylen; -+ integ_checked = TRUE; -+ if (enc_requires_integ) { -+ if (integid != IKEv2_AUTH_NONE && -+ integid == integ_transform && -+ keylen == integ_keylen) { -+ integ_matched = TRUE; -+ integwin = keylen; -+ } -+ } else { -+ if (integid == IKEv2_AUTH_NONE && -+ integ_transform == IKEv2_AUTH_NONE) { -+ integ_matched = TRUE; -+ integwin = 0; -+ } - } - DBG(DBG_CONTROLMORE, { - struct esb_buf esb; -@@ -859,11 +862,26 @@ - } - - /* TODO: esn_matched not tested! */ -- /* TODO: This does not support AES GCM with no integ */ - if (dh_matched && prf_matched && integ_matched && encr_matched) { - return TRUE; - } - } -+ if (!enc_requires_integ && !integ_checked) { -+ /* -+ * Catch AEAD case where integrity isn't -+ * required and we didn't send any over the -+ * wire. If INTEG_CHECKED then it must have been -+ * rejected. -+ * -+ * Since pluto currently (2015-01-08) always -+ * sends an INTEG transform this code -+ * shouldn't be reached; but just in case ... -+ */ -+ if (dh_matched && prf_matched && encr_matched) { -+ return TRUE; -+ } -+ } -+ - DBG(DBG_CONTROLMORE, { - /* note: enum_show uses a static buffer so more than one call per - statement is dangerous */ -@@ -877,7 +895,6 @@ - enum_show(&ikev2_trans_type_encr_names, - encr_transform), - encr_keylen); -- /* TODO: We could have no integ with aes_gcm, see how we fixed this for child SA */ - DBG_log(" %s integ=(policy:%s vs offered:%s)", - integ_matched ? "succeeded" : "failed", - enum_showb(&ikev2_trans_type_integ_names, integid, &esb), -@@ -924,79 +941,61 @@ - unsigned int esn_i; - }; - --/* should be generalised and put somewhere universal */ --/* we should really have an enum for ESP_* which is shares between IKEv1 and IKEv2 */ --static bool ikev2_enc_requires_integ(enum ikev2_trans_type_encr t) --{ -- switch (t) { -- case IKEv2_ENCR_AES_GCM_8: -- case IKEv2_ENCR_AES_GCM_12: -- case IKEv2_ENCR_AES_GCM_16: -- case IKEv2_ENCR_AES_CCM_8: -- case IKEv2_ENCR_AES_CCM_12: -- case IKEv2_ENCR_AES_CCM_16: -- return FALSE; -- default: -- return TRUE; -- } --} -- - static bool ikev2_match_transform_list_parent(struct db_sa *sadb, - unsigned int propnum, u_int8_t ipprotoid, - struct ikev2_transform_list *itl) - { -- bool need_integ; -- unsigned int i; -- - DBG(DBG_CONTROL,DBG_log("ipprotoid is '%d'", ipprotoid)); -+ passert(ipprotoid == PROTO_v2_ISAKMP); - -- if (ipprotoid == PROTO_v2_ESP && itl->encr_trans_next < 1) { -- libreswan_log("ignored ESP proposal %u with no cipher transforms", -- propnum); -- return FALSE; -- } -- if (ipprotoid == PROTO_v2_AH && itl->encr_trans_next > 1) { -- libreswan_log("ignored AH proposal %u with cipher transform(s)", -- propnum); -- return FALSE; -- } -- -+ const struct encrypt_desc *alg = (const struct encrypt_desc*) -+ ikev2_alg_find(IKE_ALG_ENCRYPT, itl->encr_transforms[0]); -+ bool enc_requires_integ = ike_alg_enc_requires_integ(alg); - -- need_integ = ikev2_enc_requires_integ(itl->encr_transforms[0]); -- -- if (ipprotoid == PROTO_v2_ESP) { -- for (i = 1; i < itl->encr_trans_next; i++) { -- if (ikev2_enc_requires_integ(itl->encr_transforms[i]) != need_integ) { -- libreswan_log("rejecting proposal %u: encryption transforms mix CCM/GCM and non-CCM/GCM", -- propnum); -- return FALSE; -- } -+ unsigned int i; -+ for (i = 1; i < itl->encr_trans_next; i++) { -+ const struct encrypt_desc *alg2 = (const struct encrypt_desc*) -+ ikev2_alg_find(IKE_ALG_ENCRYPT, itl->encr_transforms[i]); -+ if (ike_alg_enc_requires_integ(alg2) != enc_requires_integ) { -+ libreswan_log("rejecting ISAKMP proposal %u: encryption transforms mix AEAD (GCM, CCM) and non-AEAD", -+ propnum); -+ return FALSE; - } -+ } - -- /* AES CCM (RFC 4309) and GCM (RFC 4106) do not have a separate integ */ -- if (need_integ) { -- if (itl->integ_trans_next == 0) { -- libreswan_log("rejecting proposal %u: encryption transform requires an integ transform", -- propnum); -- return FALSE; -- } -- } else { -- if (itl->integ_trans_next != 0) { -- libreswan_log("rejecting proposal %u: CCM/GCM encryption transform forbids an integ transform", -- propnum); -- return FALSE; -- } -+ /* -+ * AEAD algorithms (e.x, AES_GCM) do not require separate -+ * integrity. Only allow NONE. -+ * -+ * If there was no integrity transform on the wire a single -+ * AUTH_NONE transform will have been added by -+ * ikev2_process_transforms. -+ */ -+ passert(itl->integ_trans_next >= 1); -+ if (enc_requires_integ) { -+ if (itl->integ_trans_next == 1 && -+ itl->integ_transforms[0] == IKEv2_AUTH_NONE) { -+ libreswan_log("rejecting ISAKMP proposal %u: encryption transform requires an integrity transform", -+ propnum); -+ return FALSE; -+ } -+ } else { -+ if (itl->integ_trans_next > 1 || -+ (itl->integ_trans_next == 1 && itl->integ_transforms[0] != IKEv2_AUTH_NONE)) { -+ libreswan_log("rejecting ISAKMP proposal %u: AEAD (i.e., CCM, GCM) encryption transform forbids an integrity transform", -+ propnum); -+ return FALSE; - } - } - - if (itl->prf_trans_next == 0) { -- libreswan_log("ignored proposal %u with no PRF transform", -+ libreswan_log("ignored ISAKMP proposal %u with no PRF transform", - propnum); - return FALSE; - } - if (itl->dh_trans_next == 0) { - libreswan_log( -- "ignored proposal %u with no Diffie-Hellman transform", -+ "ignored ISAKMP proposal %u with no Diffie-Hellman transform", - propnum); - return FALSE; - } -@@ -1022,7 +1021,8 @@ - itl->integ_keylens[itl->integ_i], - itl->prf_transforms[itl->prf_i], - itl->prf_keylens[itl->prf_i], -- itl->dh_transforms[itl->dh_i])) -+ itl->dh_transforms[itl->dh_i], -+ enc_requires_integ)) - return TRUE; - } - } -@@ -1110,16 +1110,29 @@ - break; - } - } -+ - if (itl->integ_trans_next == 0) { -+ /* -+ * If there's no integrity (hash) transform, such as -+ * for AEAD (e.x., AES_GCM) then fake up an AUTH_NONE -+ * transform. A single AUTH_NONE transform (fake or -+ * real) should be ignored, and for-loops further in -+ * assume at least one is present. -+ */ - itl->integ_transforms[0] = IKEv2_AUTH_NONE; - itl->integ_keylens[0] = 0; - itl->integ_trans_next = 1; - } else if (itl->integ_trans_next > 1) { -+ /* -+ * If the integrity (hash) transform set contains more -+ * than one algorithm than AUTH_NONE cannot be a -+ * member. But, as a single proposal it is ok and, -+ * like the above hack, should be ignored. -+ */ - unsigned int i; - - for (i=0; i < itl->integ_trans_next; i++) { - if (itl->integ_transforms[i] == IKEv2_AUTH_NONE) { -- /* NONE cannot be part of a set of integ algos */ - libreswan_log("IKEv2_AUTH_NONE integ transform cannot be part of a set - rejecting proposal"); - return STF_FAIL + v2N_INVALID_SYNTAX; - } -@@ -1442,8 +1455,6 @@ - - ta.integ_hasher = (struct hash_desc *)ikev2_alg_find(IKE_ALG_INTEG, - ta.integ_hash); -- /* XXX not true for AES_GCM */ -- passert(ta.integ_hasher != NULL); - - ta.prf_hasher = (struct hash_desc *)ikev2_alg_find(IKE_ALG_HASH, - ta.prf_hash); -diff -Naur libreswan-3.12-orig/programs/pluto/ipsec_doi.c libreswan-3.12/programs/pluto/ipsec_doi.c ---- libreswan-3.12-orig/programs/pluto/ipsec_doi.c 2014-11-06 22:52:50.000000000 -0500 -+++ libreswan-3.12/programs/pluto/ipsec_doi.c 2015-01-20 16:53:19.969651466 -0500 -@@ -1,4 +1,5 @@ - /* IPsec DOI and Oakley resolution routines -+ * - * Copyright (C) 1997 Angelos D. Keromytis. - * Copyright (C) 1998-2002,2010-2013 D. Hugh Redelmeier - * Copyright (C) 2003-2006 Michael Richardson -@@ -9,6 +10,7 @@ - * Copyright (C) 2012-2013 Paul Wouters - * Copyright (C) 2013 David McCullough - * Copyright (C) 2013 Matt Rogers -+ * Copyright (C) 2014 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 -@@ -170,28 +172,46 @@ - return justship_nonce(n, outs, np, name); - } - --/** The whole message must be a multiple of 4 octets. -- * I'm not sure where this is spelled out, but look at -- * rfc2408 3.6 Transform Payload. -- * Note: it talks about 4 BYTE boundaries! -+/* -+ * In IKEv1, some implementations (including freeswan/openswan/libreswan) -+ * interpreted the RFC that the whole IKE message must padded to a multiple -+ * of 4 octets, but other implementations (i.e. Checkpoint in Aggressive Mode) -+ * drop padded IKE packets. Some of the text on this topic can be found in the -+ * IKEv1 RFC 2408 section 3.6 Transform Payload. -+ * -+ * The ikepad= option can be set to yes or no on a per-connection basis, -+ * and defaults to yes. -+ * -+ * In IKEv2, there is no padding specified in the RFC and some implementations -+ * will reject IKEv2 messages that are padded. As there are no known IKEv2 -+ * clients that REQUIRE padding, padding is never done for IKEv2. If IKEv2 -+ * clients are discovered in the wild, we will revisit this - please contact -+ * the libreswan developers if you find such an implementation. -+ * Therefor, the ikepad= option has no effect on IKEv2 connections. - * - * @param pbs PB Stream - */ - bool close_message(pb_stream *pbs, struct state *st) - { -- size_t padding = pad_up(pbs_offset(pbs), 4); -+ size_t padding; -+ if (st->st_ikev2) { -+ DBG(DBG_CONTROLMORE, DBG_log("no IKE message padding required for IKEv2")); -+ close_output_pbs(pbs); -+ return TRUE; -+ } -+ -+ padding = pad_up(pbs_offset(pbs), 4); - -- /* Workaround for overzealous Checkpoint firewall */ - if (padding != 0 && st != NULL && st->st_connection != NULL && - (st->st_connection->policy & POLICY_NO_IKEPAD)) { -- DBG(DBG_CONTROLMORE, DBG_log("IKE message padding of %zu bytes skipped by policy", -+ DBG(DBG_CONTROLMORE, DBG_log("IKEv1 message padding of %zu bytes skipped by policy", - padding)); - } else if (padding != 0) { -- DBG(DBG_CONTROLMORE, DBG_log("padding IKE message with %zu bytes", padding)); -+ DBG(DBG_CONTROLMORE, DBG_log("padding IKEv1 message with %zu bytes", padding)); - if (!out_zero(padding, pbs, "message padding")) - return FALSE; - } else { -- DBG(DBG_CONTROLMORE, DBG_log("no IKE message padding required")); -+ DBG(DBG_CONTROLMORE, DBG_log("no IKEv1 message padding required")); - } - - close_output_pbs(pbs); -@@ -601,43 +621,72 @@ - add_str(sadetails, sad_len, b, "}"); - } - --void fmt_isakmp_sa_established(struct state *st, char *sadetails, size_t sad_len) -+void fmt_isakmp_sa_established(struct state *st, char *sa_details, -+ size_t sa_details_size) - { -- -- /* document ISAKMP SA details for admin's pleasure */ -- char *b = sadetails; -- const char *authname, *prfname; -- const char *integstr, *integname; -- char integname_tmp[20]; -- - passert(st->st_oakley.encrypter != NULL); - passert(st->st_oakley.prf_hasher != NULL); - passert(st->st_oakley.group != NULL); -+ /* -+ * Note: for IKEv1 and AEAD encrypters, -+ * st->st_oakley.integ_hasher is NULL! -+ */ -+ -+ const char *auth_name; -+ if (st->st_ikev2) { -+ auth_name = "IKEv2"; -+ } else { -+ auth_name = enum_show(&oakley_auth_names, st->st_oakley.auth); -+ auth_name = strip_prefix(auth_name, "OAKLEY_"); -+ } - -+ /* -+ * [2015-01-10] Some PRFs get their common.name set to -+ * "OAKLEY_..." and this leads to the below printing the full -+ * uppercase name (e.x., prf=OAKLEY_SHA2_256). This is an -+ * historic "feature". See ike_alg.c:ike_alg_register_hash -+ * for where those names come from. -+ */ -+ const char *prf_common_name = -+ strip_prefix(st->st_oakley.prf_hasher->common.name, -+ "oakley_"); -+ -+ char prf_name[30] = ""; - if (st->st_ikev2) { -- authname = "IKEv2"; -- integstr = " integ="; -- prfname = "prf="; -- snprintf(integname_tmp, sizeof(integname_tmp), "%s_%zu", -- st->st_oakley.integ_hasher->common.officname, -- st->st_oakley.integ_hasher->hash_integ_len * -- BITS_PER_BYTE); -- integname = (const char*)integname_tmp; -+ snprintf(prf_name, sizeof(prf_name), -+ " prf=%s", prf_common_name); -+ } -+ -+ char integ_name[30] = ""; -+ if (st->st_ikev2) { -+ if (st->st_oakley.integ_hasher == NULL) { -+ jam_str(integ_name, sizeof(integ_name), " integ=n/a"); -+ } else { -+ snprintf(integ_name, sizeof(integ_name), -+ " integ=%s_%zu", -+ st->st_oakley.integ_hasher->common.officname, -+ (st->st_oakley.integ_hasher->hash_integ_len * -+ BITS_PER_BYTE)); -+ } - } else { -- authname = enum_show(&oakley_auth_names, st->st_oakley.auth); -- integstr = ""; -- integname = ""; -- prfname = "integ="; -+ /* -+ * For IKEv1, since the INTEG algorithm is potentially -+ * (always?) NULL. Display the PRF. The choice and -+ * behaviour are historic. -+ */ -+ snprintf(integ_name, sizeof(integ_name), -+ " integ=%s", prf_common_name); - } - -- snprintf(b, sad_len - (b - sadetails) - 1, -- " {auth=%s cipher=%s_%d%s%s %s%s group=%s}", -- strip_prefix(authname,"OAKLEY_"), -+ const char *group_name = enum_name(&oakley_group_names, -+ st->st_oakley.group->group); -+ group_name = strip_prefix(group_name, "OAKLEY_GROUP_"); -+ -+ snprintf(sa_details, sa_details_size, -+ " {auth=%s cipher=%s_%d%s%s group=%s}", -+ auth_name, - st->st_oakley.encrypter->common.name, - st->st_oakley.enckeylen, -- integstr, integname, -- prfname, -- strip_prefix(st->st_oakley.prf_hasher->common.name,"oakley_"), -- strip_prefix(enum_name(&oakley_group_names, st->st_oakley.group->group), "OAKLEY_GROUP_")); -+ integ_name, prf_name, group_name); - st->hidden_variables.st_logged_p1algos = TRUE; - } -diff -Naur libreswan-3.12-orig/programs/pluto/kernel_netlink.c libreswan-3.12/programs/pluto/kernel_netlink.c ---- libreswan-3.12-orig/programs/pluto/kernel_netlink.c 2015-01-20 16:52:43.658654327 -0500 -+++ libreswan-3.12/programs/pluto/kernel_netlink.c 2015-01-20 16:53:19.971651521 -0500 -@@ -235,6 +235,10 @@ - memcpy(xaddr->a6, &addr->u.v6.sin6_addr, sizeof(xaddr->a6)); - } - -+/* -+ * XXX: This code is duplicated in ike_alg_aes.c. When the latter is -+ * enabled, this should be deleted. -+ */ - - static struct encrypt_desc algo_aes_ccm_8 = - { -@@ -290,60 +294,6 @@ - .keymaxlen = AEAD_AES_KEY_MAX_LEN, - }; - --static struct encrypt_desc algo_aes_gcm_8 = --{ -- .common = { -- .name = "aes_gcm_8", -- .officname = "aes_gcm_8", -- .algo_type = IKE_ALG_ENCRYPT, -- .algo_v2id = IKEv2_ENCR_AES_GCM_8, -- .algo_next = NULL, -- }, -- .enc_blocksize = AES_BLOCK_SIZE, -- .wire_iv_size = 8, -- .pad_to_blocksize = FALSE, -- /* Only 128, 192 and 256 are supported (32 bits KEYMAT for salt not included) */ -- .keyminlen = AEAD_AES_KEY_MIN_LEN, -- .keydeflen = AEAD_AES_KEY_DEF_LEN, -- .keymaxlen = AEAD_AES_KEY_MAX_LEN, --}; -- --static struct encrypt_desc algo_aes_gcm_12 = --{ -- .common = { -- .name = "aes_gcm_12", -- .officname = "aes_gcm_12", -- .algo_type = IKE_ALG_ENCRYPT, -- .algo_v2id = IKEv2_ENCR_AES_GCM_12, -- .algo_next = NULL, -- }, -- .enc_blocksize = AES_BLOCK_SIZE, -- .wire_iv_size = 8, -- .pad_to_blocksize = FALSE, -- /* Only 128, 192 and 256 are supported (32 bits KEYMAT for salt not included) */ -- .keyminlen = AEAD_AES_KEY_MIN_LEN, -- .keydeflen = AEAD_AES_KEY_DEF_LEN, -- .keymaxlen = AEAD_AES_KEY_MAX_LEN, --}; -- --static struct encrypt_desc algo_aes_gcm_16 = --{ -- .common = { -- .name = "aes_gcm_16", -- .officname = "aes_gcm_16", -- .algo_type = IKE_ALG_ENCRYPT, -- .algo_v2id = IKEv2_ENCR_AES_GCM_16, -- .algo_next = NULL, -- }, -- .enc_blocksize = AES_BLOCK_SIZE, -- .wire_iv_size = 8, -- .pad_to_blocksize = FALSE, -- /* Only 128, 192 and 256 are supported (32 bits KEYMAT for salt not included) */ -- .keyminlen = AEAD_AES_KEY_MIN_LEN, -- .keydeflen = AEAD_AES_KEY_DEF_LEN, -- .keymaxlen = AEAD_AES_KEY_MAX_LEN, --}; -- - /* - * wire-in Authenticated Encryption with Associated Data transforms - * (do both enc and auth in one transform) -@@ -361,21 +311,21 @@ - alg.sadb_alg_maxbits = 256; - alg.sadb_alg_id = SADB_X_EALG_AES_GCM_ICV8; - if (kernel_alg_add(SADB_SATYPE_ESP, SADB_EXT_SUPPORTED_ENCRYPT, &alg) != 1) -- loglog(RC_LOG_SERIOUS, "Warning: failed to register algo_aes_gcm_8 for ESP"); -+ loglog(RC_LOG_SERIOUS, "Warning: failed to register AES_GCM_A(8) for ESP"); - - alg.sadb_alg_ivlen = 12; - alg.sadb_alg_minbits = 128; - alg.sadb_alg_maxbits = 256; - alg.sadb_alg_id = SADB_X_EALG_AES_GCM_ICV12; - if (kernel_alg_add(SADB_SATYPE_ESP, SADB_EXT_SUPPORTED_ENCRYPT, &alg) != 1) -- loglog(RC_LOG_SERIOUS, "Warning: failed to register algo_aes_gcm_12 for ESP"); -+ loglog(RC_LOG_SERIOUS, "Warning: failed to register AES_GCM_B(12) for ESP"); - - alg.sadb_alg_ivlen = 16; - alg.sadb_alg_minbits = 128; - alg.sadb_alg_maxbits = 256; - alg.sadb_alg_id = SADB_X_EALG_AES_GCM_ICV16; - if (kernel_alg_add(SADB_SATYPE_ESP, SADB_EXT_SUPPORTED_ENCRYPT, &alg) != 1) -- loglog(RC_LOG_SERIOUS, "Warning: failed to register algo_aes_gcm_16 for ESP"); -+ loglog(RC_LOG_SERIOUS, "Warning: failed to register AES_GCM_C(16) for ESP"); - - /* keeping aes-ccm behaviour intact as before */ - alg.sadb_alg_ivlen = 8; -@@ -383,29 +333,26 @@ - alg.sadb_alg_maxbits = 256; - alg.sadb_alg_id = SADB_X_EALG_AES_CCM_ICV8; - if (kernel_alg_add(SADB_SATYPE_ESP, SADB_EXT_SUPPORTED_ENCRYPT, &alg) != 1) -- loglog(RC_LOG_SERIOUS, "Warning: failed to register algo_aes_ccm_8 for ESP"); -+ loglog(RC_LOG_SERIOUS, "Warning: failed to register AES_CCM_A(8) for ESP"); - - alg.sadb_alg_id = SADB_X_EALG_AES_CCM_ICV12; - if (kernel_alg_add(SADB_SATYPE_ESP, SADB_EXT_SUPPORTED_ENCRYPT, &alg) != 1) -- loglog(RC_LOG_SERIOUS, "Warning: failed to register algo_aes_ccm_12 for ESP"); -+ loglog(RC_LOG_SERIOUS, "Warning: failed to register AES_CCM_B(12) for ESP"); - - alg.sadb_alg_id = SADB_X_EALG_AES_CCM_ICV16; - if (kernel_alg_add(SADB_SATYPE_ESP, SADB_EXT_SUPPORTED_ENCRYPT, &alg) != 1) -- loglog(RC_LOG_SERIOUS, "Warning: failed to register algo_aes_ccm_16 for ESP"); -+ loglog(RC_LOG_SERIOUS, "Warning: failed to register AES_CCM_C(16) for ESP"); - -- /* IKE algos (encryption and authentication combined) */ -+ /* -+ * XXX: This code is duplicated in ike_alg_aes.c. When the -+ * latter is enabled, this should be deleted. -+ */ - if (!ike_alg_register_enc(&algo_aes_ccm_8)) - loglog(RC_LOG_SERIOUS, "Warning: failed to register algo_aes_ccm_8 for IKE"); - if (!ike_alg_register_enc(&algo_aes_ccm_12)) - loglog(RC_LOG_SERIOUS, "Warning: failed to register algo_aes_ccm_12 for IKE"); - if (!ike_alg_register_enc(&algo_aes_ccm_16)) - loglog(RC_LOG_SERIOUS, "Warning: failed to register algo_aes_ccm_16 for IKE"); -- if (!ike_alg_register_enc(&algo_aes_gcm_8)) -- loglog(RC_LOG_SERIOUS, "Warning: failed to register algo_aes_gcm_8 for IKE"); -- if (!ike_alg_register_enc(&algo_aes_gcm_12)) -- loglog(RC_LOG_SERIOUS, "Warning: failed to register algo_aes_gcm_12 for IKE"); -- if (!ike_alg_register_enc(&algo_aes_gcm_16)) -- loglog(RC_LOG_SERIOUS, "Warning: failed to register algo_aes_gcm_16 for IKE"); - - DBG(DBG_CONTROLMORE, - DBG_log("Registered AEAD AES CCM/GCM algorithms")); -diff -Naur libreswan-3.12-orig/programs/pluto/Makefile libreswan-3.12/programs/pluto/Makefile ---- libreswan-3.12-orig/programs/pluto/Makefile 2015-01-20 16:52:43.660654383 -0500 -+++ libreswan-3.12/programs/pluto/Makefile 2015-01-20 16:53:19.972651548 -0500 -@@ -111,6 +111,7 @@ - ike_alg_nss_cbc.h ike_alg_nss_cbc.c \ - cbc_test_vectors.h cbc_test_vectors.c \ - ctr_test_vectors.h ctr_test_vectors.c \ -+ gcm_test_vectors.h gcm_test_vectors.c \ - test_buffer.h test_buffer.c \ - connections.c initiate.c terminate.c connections.h \ - pending.c pending.h \ -@@ -167,6 +168,7 @@ - OBJSPLUTO += ike_alg_nss_cbc.o - OBJSPLUTO += cbc_test_vectors.o - OBJSPLUTO += ctr_test_vectors.o -+OBJSPLUTO += gcm_test_vectors.o - OBJSPLUTO += test_buffer.o - OBJSPLUTO += pending.o cookie.o crypto.o defs.o - OBJSPLUTO += foodgroups.o log.o state.o plutomain.o plutoalg.o server.o -diff -Naur libreswan-3.12-orig/programs/pluto/plutoalg.c libreswan-3.12/programs/pluto/plutoalg.c ---- libreswan-3.12-orig/programs/pluto/plutoalg.c 2015-01-20 16:52:43.634653668 -0500 -+++ libreswan-3.12/programs/pluto/plutoalg.c 2015-01-20 16:53:19.974651603 -0500 -@@ -5,6 +5,7 @@ - * (C)opyright 2012 Paul Wouters - * (C)opyright 2012-2013 Paul Wouters - * (C)opyright 2012-2013 D. Hugh Redelmeier -+ * (C)opyright 2015 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 -@@ -46,20 +47,18 @@ - * "3des_cbc" <=> "OAKLEY_3DES_CBC" - * - * @param str String containing ALG name (eg: AES, 3DES) -- * @param len Length of str (note: not NUL-terminated) - * @return int Registered # of ALG if loaded or -1 on failure. - */ --static int ealg_getbyname_ike(const char *const str, size_t len) -+static int ealg_getbyname_ike(const char *const str) - { - int ret; - - if (str == NULL || *str == '\0') - return -1; -- ret = alg_enum_search(&oakley_enc_names, "OAKLEY_", "", str, len); -+ ret = alg_enum_search(&oakley_enc_names, "OAKLEY_", "", str); - if (ret >= 0) - return ret; -- return alg_enum_search(&oakley_enc_names, "OAKLEY_", "_CBC", str, -- len); -+ return alg_enum_search(&oakley_enc_names, "OAKLEY_", "_CBC", str); - } - - /** -@@ -69,46 +68,27 @@ - * @param len Length of str (note: not NUL-terminated) - * @return int Registered # of Hash ALG if loaded. - */ --static int aalg_getbyname_ike(const char *str, size_t len) -+static int aalg_getbyname_ike(const char *str) - { - int ret = -1; - int num_read; -- static const char sha2_256_aka[] = "sha2"; -- static const char sha1_aka[] = "sha"; - - DBG(DBG_CONTROL, DBG_log("entering aalg_getbyname_ike()")); - if (str == NULL || str == '\0') - return ret; - -- /* handle "sha2" as "sha2_256" */ -- if (len == sizeof(sha2_256_aka)-1 && -- strncaseeq(str, sha2_256_aka, sizeof(sha2_256_aka)-1)) { -- DBG_log("interpreting sha2 as sha2_256"); -- str = "sha2_256"; -- len = strlen(str); -- } -- -- /* now "sha" as "sha1" */ -- if (len == sizeof(sha1_aka)-1 && -- strncaseeq(str, sha1_aka, sizeof(sha1_aka)-1)) { -- DBG_log("interpreting sha as sha1"); -- str = "sha1"; -- len = strlen(str); -- } -- -- ret = alg_enum_search(&oakley_hash_names, "OAKLEY_", "", str, len); -+ ret = alg_enum_search(&oakley_hash_names, "OAKLEY_", "", str); - if (ret >= 0) - return ret; - - /* Special value for no authentication since zero is already used. */ -- ret = INT_MAX; -- if (len == 4 && strncaseeq(str, "null", len)) -- return ret; -+ if (strcaseeq(str, "null")) -+ return INT_MAX; - - /* support idXXX as syntax, matching iana numbers directly */ -- /* ??? this sscanf is bogus since we don't know what appears at str[len] */ - num_read = -1; -- if (sscanf(str, "id%d%n", &ret, &num_read) >= 1 && num_read == (int)len) -+ if (sscanf(str, "id%d%n", &ret, &num_read) >= 1 && -+ num_read == (int) strlen(str)) - return ret; - - return -1; -@@ -117,21 +97,19 @@ - * Search oakley_group_names for a match, eg: - * "modp1024" <=> "OAKLEY_GROUP_MODP1024" - * @param str String MODP Name (eg: MODP) -- * @param len Length of str (note: not NUL-terminated) - * @return int Registered # of MODP Group, if supported. - */ --static int modp_getbyname_ike(const char *const str, size_t len) -+static int modp_getbyname_ike(const char *const str) - { - int ret = -1; - - if (str == NULL || *str == '\0') - return -1; -- ret = alg_enum_search(&oakley_group_names, "OAKLEY_GROUP_", "", -- str, len); -+ ret = alg_enum_search(&oakley_group_names, "OAKLEY_GROUP_", "", str); - if (ret >= 0) - return ret; - return alg_enum_search(&oakley_group_names, "OAKLEY_GROUP_", -- " (extension)", str, len); -+ " (extension)", str); - } - - /* -@@ -169,9 +147,12 @@ - ike_info[cnt].ike_modp = modp_id; - alg_info->ai.alg_info_cnt++; - DBG(DBG_CRYPT, DBG_log("raw_alg_info_ike_add() " -- "ealg=%d aalg=%d modp_id=%d, cnt=%d", -- ealg_id, aalg_id, modp_id, -- alg_info->ai.alg_info_cnt)); -+ "ealg_id=%d ek_bits=%d " -+ "aalg_id=%d ak_bits=%d " -+ "modp_id=%d, cnt=%d", -+ ealg_id, ek_bits, -+ aalg_id, ak_bits, -+ modp_id, alg_info->ai.alg_info_cnt)); - } - - /* -diff -Naur libreswan-3.12-orig/programs/pluto/spdb_struct.c libreswan-3.12/programs/pluto/spdb_struct.c ---- libreswan-3.12-orig/programs/pluto/spdb_struct.c 2014-11-06 22:52:50.000000000 -0500 -+++ libreswan-3.12/programs/pluto/spdb_struct.c 2015-01-20 16:53:19.975651631 -0500 -@@ -2,6 +2,7 @@ - * Copyright (C) 1998-2001 D. Hugh Redelmeier. - * Copyright (C) 2003-2007 Michael Richardson - * Copyright (C) 2003-2008 Paul Wouters -+ * Copyright (C) 2015 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 -@@ -119,39 +120,50 @@ - struct db_sa *emp_sp; - - if (!ike_info->ike_default) { -- struct encrypt_desc *enc_desc; -- struct db_attr *enc, *hash, *auth, *grp, *enc_keylen; - - unsigned ealg = ike_info->ike_ealg; - unsigned halg = ike_info->ike_halg; - unsigned modp = ike_info->ike_modp; - unsigned eklen = ike_info->ike_eklen; -+ DBG(DBG_CONTROL, -+ DBG_log("oakley_alg_makedb() " -+ "processing ealg=%u halg=%u modp=%u eklen=%u", -+ ealg, halg, modp, eklen)); - -- if (!ike_alg_enc_present(ealg)) { -+ struct encrypt_desc *enc_desc = ike_alg_get_encrypter(ealg); -+ if (enc_desc == NULL) { - DBG_log("oakley_alg_makedb() " - "ike enc ealg=%d not present", - ealg); - continue; - } -- if (!ike_alg_hash_present(halg)) { -- DBG_log("oakley_alg_makedb() " -- "ike hash halg=%d not present", -- halg); -- continue; -- } -- enc_desc = ike_alg_get_encrypter(ealg); -- - passert(enc_desc != NULL); - -+ if (ike_alg_enc_requires_integ(enc_desc)) { -+ if (!ike_alg_hash_present(halg)) { -+ DBG_log("oakley_alg_makedb() " -+ "ike hash halg=%d not present but required for integrity", -+ halg); -+ continue; -+ } -+ } else { -+ if (!ike_alg_hash_present(halg)) { -+ DBG_log("oakley_alg_makedb() " -+ "ike PRF=%d not present but needed for AEAD", -+ halg); -+ continue; -+ } -+ } -+ - if (eklen != 0 && - (eklen < enc_desc->keyminlen || - eklen > enc_desc->keymaxlen)) { -- DBG_log("ike_alg_db_new() ealg=%d (specified) keylen:%d, not valid min=%d, max=%d", -- ealg, -- eklen, -- enc_desc->keyminlen, -- enc_desc->keymaxlen); -- continue; -+ DBG_log("ike_alg_db_new() ealg=%d (specified) keylen:%d, not valid min=%d, max=%d", -+ ealg, -+ eklen, -+ enc_desc->keyminlen, -+ enc_desc->keymaxlen); -+ continue; - } - - /* -@@ -164,47 +176,56 @@ - /* duplicate, but change auth to match template */ - emp_sp = sa_copy_sa(&oakley_empty, 0); - -- passert(emp_sp->dynamic); - emp_sp->prop_conjs[0].props[0].trans[0].attrs[2] = - base->prop_conjs[0].props[0].trans[0].attrs[2]; - } else { - emp_sp = sa_copy_sa_first(base); - } - -+ passert(emp_sp->dynamic); - passert(emp_sp->prop_conj_cnt == 1); - passert(emp_sp->prop_conjs[0].prop_cnt == 1); - passert(emp_sp->prop_conjs[0].props[0].trans_cnt == 1); - -- { -- struct db_trans *trans = &emp_sp->prop_conjs[0].props[0].trans[0]; -+ struct db_trans *trans = &emp_sp->prop_conjs[0].props[0].trans[0]; - -- passert(emp_sp->dynamic); -- passert(trans->attr_cnt == 4 || trans->attr_cnt == 5); -- enc = &trans->attrs[0]; -- hash = &trans->attrs[1]; -- auth = &trans->attrs[2]; -- grp = &trans->attrs[3]; -- -- if (eklen > 0) { -- enc_keylen = &trans->attrs[4]; -- enc_keylen->val = eklen; -- } else { -- trans->attr_cnt = 4; -- } -+ /* -+ * See "struct db_attr otempty" above for -+ * where these magic values come from. -+ */ -+ passert(trans->attr_cnt == 4 || trans->attr_cnt == 5); -+ struct db_attr *enc = &trans->attrs[0]; -+ struct db_attr *hash = &trans->attrs[1]; -+ struct db_attr *auth = &trans->attrs[2]; -+ struct db_attr *grp = &trans->attrs[3]; -+ -+ if (eklen > 0) { -+ passert(trans->attr_cnt == 5); -+ struct db_attr *enc_keylen = &trans->attrs[4]; -+ passert(enc_keylen->type.oakley == OAKLEY_KEY_LENGTH); -+ enc_keylen->val = eklen; -+ } else { -+ /* truncate */ -+ trans->attr_cnt = 4; - } - -- passert(enc->type.oakley == -- OAKLEY_ENCRYPTION_ALGORITHM); -+ passert(enc->type.oakley == OAKLEY_ENCRYPTION_ALGORITHM); - if (ealg > 0) - enc->val = ealg; - -- passert(hash->type.oakley == OAKLEY_HASH_ALGORITHM); -- if (halg > 0) -+ passert(hash->type.oakley == OAKLEY_HASH_ALGORITHM || -+ hash->type.oakley == OAKLEY_PRF); -+ if (halg > 0) { - hash->val = halg; -+ if (ike_alg_enc_requires_integ(enc_desc)) { -+ hash->type.oakley = OAKLEY_HASH_ALGORITHM; -+ } else { -+ hash->type.oakley = OAKLEY_PRF; -+ } -+ } - - /* - * auth type for IKE must be set -- * (??? until we support AES-GCM in IKE) - */ - passert(auth->type.oakley == - OAKLEY_AUTHENTICATION_METHOD); -@@ -339,5 +360,7 @@ - if (gsp != NULL) - gsp->parentSA = TRUE; - -+ DBG(DBG_CONTROL, -+ DBG_log("oakley_alg_makedb() returning %p", gsp)); - return gsp; - } -diff -Naur libreswan-3.12-orig/programs/pluto/test_buffer.c libreswan-3.12/programs/pluto/test_buffer.c ---- libreswan-3.12-orig/programs/pluto/test_buffer.c 2015-01-20 16:52:43.664654492 -0500 -+++ libreswan-3.12/programs/pluto/test_buffer.c 2015-01-20 16:53:19.976651658 -0500 -@@ -1,3 +1,18 @@ -+/* -+ * Copyright (C) 2014 Andrew Cagney -+ * Copyright (C) 2015 Andrew Cagney -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * for more details. -+ */ -+ - #include - - #include "defs.h" -@@ -116,6 +131,17 @@ - return compare_chunk(prefix, expected, actual.ptr); - } - -+chunk_t extract_chunk(const char *prefix, const chunk_t input, size_t offset, size_t length) -+{ -+ chunk_t output; -+ DBG(DBG_CRYPT, DBG_log("extract_chunk: %s: offset %zd length %zd", -+ prefix, offset, length)); -+ passert(offset + length <= input.len); -+ clonetochunk(output, input.ptr + offset, length, prefix); -+ DBG(DBG_CRYPT, DBG_dump_chunk(prefix, output)); -+ return output; -+} -+ - /* - * Turn the raw key into a SECItem and then SymKey. - * -@@ -129,7 +155,7 @@ - const char *encoded_key) - { - PK11SlotInfo *slot = PK11_GetBestSlot(cipher_mechanism, NULL); -- chunk_t raw_key = decode_to_chunk("Key: ", encoded_key); -+ chunk_t raw_key = decode_to_chunk("key", encoded_key); - SECItem key_item; - key_item.type = siBuffer; - key_item.data = raw_key.ptr; /* ptr to an array of key bytes */ -diff -Naur libreswan-3.12-orig/programs/pluto/test_buffer.h libreswan-3.12/programs/pluto/test_buffer.h ---- libreswan-3.12-orig/programs/pluto/test_buffer.h 2015-01-20 16:52:43.665654520 -0500 -+++ libreswan-3.12/programs/pluto/test_buffer.h 2015-01-20 16:53:19.977651686 -0500 -@@ -1,3 +1,17 @@ -+/* -+ * Copyright (C) 2014 Andrew Cagney -+ * Copyright (C) 2015 Andrew Cagney -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * for more details. -+ */ - - chunk_t decode_to_chunk(const char *prefix, const char *string); - int compare_chunks(const char *prefix, -@@ -6,4 +20,7 @@ - int compare_chunk(const char *prefix, - chunk_t expected, - u_char *actual); -+chunk_t extract_chunk(const char *prefix, chunk_t input, -+ size_t offset, size_t length); -+ - PK11SymKey *decode_to_key(CK_MECHANISM_TYPE cipher_mechanism, const char *string); diff --git a/SOURCES/libreswan-3.12-CVE-2015-3204.patch b/SOURCES/libreswan-3.12-CVE-2015-3204.patch deleted file mode 100644 index 8dfd1f5..0000000 --- a/SOURCES/libreswan-3.12-CVE-2015-3204.patch +++ /dev/null @@ -1,169 +0,0 @@ -diff --git a/lib/libswan/constants.c b/lib/libswan/constants.c -index a003e99..8f3a107 100644 ---- a/lib/libswan/constants.c -+++ b/lib/libswan/constants.c -@@ -43,12 +43,11 @@ - * The buffer bound (size) must be greater than 0. - * That allows a guarantee that the result is NUL-terminated. - * -- * The result is a pointer: -- * if the string fits, to the NUL at the end of the string in dest; -- * if the string was truncated, to the roof of dest. -+ * The result is a pointer to the NUL at the end of the string in dest. - * -- * Warning: Is it really wise to silently truncate? Only the caller knows. -- * The caller SHOULD check by seeing if the result equals dest's roof. -+ * Warning: no indication of truncation is returned. -+ * An earlier version did indicate truncation, but that feature was never used. -+ * This version is more robust and has a simpler contract. - */ - char *jam_str(char *dest, size_t size, const char *src) - { -@@ -56,12 +55,11 @@ char *jam_str(char *dest, size_t size, const char *src) - - { - size_t full_len = strlen(src); -- bool oflow = size - 1 < full_len; -- size_t copy_len = oflow ? size - 1 : full_len; -+ size_t copy_len = size - 1 < full_len ? size - 1 : full_len; - - memcpy(dest, src, copy_len); - dest[copy_len] = '\0'; -- return dest + copy_len + (oflow ? 1 : 0); -+ return dest + copy_len; - } - } - -diff --git a/include/packet.h b/include/packet.h -index c9b0df9..55f8b11 100644 ---- a/include/packet.h -+++ b/include/packet.h -@@ -657,6 +657,8 @@ struct isakmp_nat_oa { - extern struct_desc isakmp_nat_d; - extern struct_desc isakmp_nat_oa; - -+extern struct_desc isakmp_ignore_desc; /* generic payload (when ignoring) */ -+ - /* ISAKMP IKE Fragmentation Payload - * Cisco proprietary, undocumented - * Microsoft documentation link: http://msdn.microsoft.com/en-us/library/cc233452.aspx -diff --git a/programs/pluto/ikev1.c b/programs/pluto/ikev1.c -index e8157bb..155a27c 100644 ---- a/programs/pluto/ikev1.c -+++ b/programs/pluto/ikev1.c -@@ -1810,8 +1810,7 @@ void process_packet_tail(struct msg_digest **mdp) - switch (np) { - case ISAKMP_NEXT_NATD_RFC: - case ISAKMP_NEXT_NATOA_RFC: -- if (st == NULL || -- (st->hidden_variables.st_nat_traversal & NAT_T_WITH_RFC_VALUES) == LEMPTY) { -+ if ((st->hidden_variables.st_nat_traversal & NAT_T_WITH_RFC_VALUES) == LEMPTY) { - /* - * don't accept NAT-D/NAT-OA reloc directly in message, - * unless we're using NAT-T RFC -@@ -1832,6 +1831,7 @@ void process_packet_tail(struct msg_digest **mdp) - /* payload type is out of range or requires special handling */ - switch (np) { - case ISAKMP_NEXT_ID: -+ /* ??? two kinds of ID payloads */ - sd = (IS_PHASE1(from_state) || - IS_PHASE15(from_state)) ? - &isakmp_identification_desc : -@@ -1839,20 +1839,48 @@ void process_packet_tail(struct msg_digest **mdp) - break; - - case ISAKMP_NEXT_NATD_DRAFTS: -- np = ISAKMP_NEXT_NATD_RFC; /* NAT-D was a private use type before RFC-3947 */ -+ /* NAT-D was a private use type before RFC-3947 -- same format */ -+ np = ISAKMP_NEXT_NATD_RFC; - sd = payload_desc(np); - break; - - case ISAKMP_NEXT_NATOA_DRAFTS: -- np = ISAKMP_NEXT_NATOA_RFC; /* NAT-OA was a private use type before RFC-3947 */ -+ /* NAT-OA was a private use type before RFC-3947 -- same format */ -+ np = ISAKMP_NEXT_NATOA_RFC; - sd = payload_desc(np); - break; - -- case ISAKMP_NEXT_SAK: /* AKA ISAKMP_NEXT_NATD_BADDRAFTS */ -+ case ISAKMP_NEXT_SAK: /* or ISAKMP_NEXT_NATD_BADDRAFTS */ -+ /* -+ * Official standards say that this is ISAKMP_NEXT_SAK, -+ * a part of Group DOI, something we don't implement. -+ * Old non-updated Cisco gear abused this number in ancient NAT drafts. -+ * We ignore (rather than reject) this in support of people -+ * with crufty Cisco machines. -+ */ - loglog(RC_LOG_SERIOUS, -- "%smessage with unsupported payload ISAKMP_NEXT_SAK (as ISAKMP_NEXT_NATD_BADDRAFTS) ignored", -+ "%smessage with unsupported payload ISAKMP_NEXT_SAK (or ISAKMP_NEXT_NATD_BADDRAFTS) ignored", - excuse); -- break; -+ /* -+ * Hack to discard payload, whatever it was. -+ * Since we are skipping the rest of the loop -+ * body we must do some things ourself: -+ * - demarshall the payload -+ * - grab the next payload number (np) -+ * - don't keep payload (don't increment pd) -+ * - skip rest of loop body -+ */ -+ if (!in_struct(&pd->payload, &isakmp_ignore_desc, &md->message_pbs, -+ &pd->pbs)) { -+ loglog(RC_LOG_SERIOUS, -+ "%smalformed payload in packet", -+ excuse); -+ SEND_NOTIFICATION(PAYLOAD_MALFORMED); -+ return; -+ } -+ np = pd->payload.generic.isag_np; -+ /* NOTE: we do not increment pd! */ -+ continue; /* skip rest of the loop */ - - default: - loglog(RC_LOG_SERIOUS, -@@ -1865,6 +1893,8 @@ void process_packet_tail(struct msg_digest **mdp) - passert(sd != NULL); - } - -+ passert(np < LELEM_ROOF); -+ - { - lset_t s = LELEM(np); - -diff --git a/programs/pluto/packet.c b/programs/pluto/packet.c -index 2b104db..e759b5e 100644 ---- a/programs/pluto/packet.c -+++ b/programs/pluto/packet.c -@@ -81,9 +81,6 @@ static field_desc isag_fields[] = { - { ft_end, 0, NULL, NULL } - }; - --static struct_desc isakmp_generic_desc = -- { "ISAKMP Generic Payload", isag_fields, sizeof(struct isakmp_generic) }; -- - /* ISAKMP Data Attribute (generic representation within payloads) - * layout from RFC 2408 "ISAKMP" section 3.3 - * This is not a payload type. -@@ -647,6 +644,11 @@ struct_desc isakmp_nat_oa = - { "ISAKMP NAT-OA Payload", isanat_oa_fields, - sizeof(struct isakmp_nat_oa) }; - -+/* Generic payload (when ignoring) */ -+ -+struct_desc isakmp_ignore_desc = -+ { "ignored ISAKMP Generic Payload", isag_fields, sizeof(struct isakmp_generic) }; -+ - /* ISAKMP IKE Fragmentation Payload - * Cisco proprietary, undocumented - * -@@ -1892,7 +1894,7 @@ bool out_generic(u_int8_t np, struct_desc *sd, - { - struct isakmp_generic gen; - -- passert(sd->fields == isakmp_generic_desc.fields); -+ passert(sd->fields == isag_fields); - gen.isag_np = np; - return out_struct(&gen, sd, outs, obj_pbs); - } diff --git a/SOURCES/libreswan-3.15-1166146.patch b/SOURCES/libreswan-3.15-1166146.patch new file mode 100644 index 0000000..a65133e --- /dev/null +++ b/SOURCES/libreswan-3.15-1166146.patch @@ -0,0 +1,23 @@ +diff -Naur libreswan-3.15-orig/programs/pluto/connections.c libreswan-3.15/programs/pluto/connections.c +--- libreswan-3.15-orig/programs/pluto/connections.c 2015-08-24 16:52:43.000000000 -0400 ++++ libreswan-3.15/programs/pluto/connections.c 2015-09-24 13:19:16.151982555 -0400 +@@ -3334,6 +3334,11 @@ + struct connection *d; + struct spd_route *sr; + ++ /* weird things can happen to our interfaces */ ++ if (!oriented(*c)) { ++ return NULL; ++ } ++ + DBG(DBG_CONTROLMORE, { + char s1[SUBNETTOT_BUF]; + char d1[SUBNETTOT_BUF]; +@@ -3378,7 +3383,6 @@ + (sr->that.protocol == peer_protocol) && + (!sr->that.port || + sr->that.port == peer_port)) { +- passert(oriented(*c)); + if (routed(sr->routing)) + return c; + diff --git a/SOURCES/libreswan-3.15-1271811-fipsfiles.patch b/SOURCES/libreswan-3.15-1271811-fipsfiles.patch new file mode 100644 index 0000000..2735548 --- /dev/null +++ b/SOURCES/libreswan-3.15-1271811-fipsfiles.patch @@ -0,0 +1,65 @@ +commit 19b50a501772a06fb7648b531852fb588efb0021 +Author: Paul Wouters +Date: Tue Oct 13 13:41:24 2015 -0400 + + pluto: fixup fips.h to only require libexec/ components that are compiled. + + When disabling MAST, the fips.h file list wanted to checksum updown.mast + which was not installed, and cause a FIPS selftest failure. + +diff --git a/programs/pluto/fips.h b/programs/pluto/fips.h +index 10bfff0..9c550d8 100644 +--- a/programs/pluto/fips.h ++++ b/programs/pluto/fips.h +@@ -22,32 +22,40 @@ + + const char *fips_package_files[] = { IPSEC_EXECDIR "/pluto", + IPSEC_EXECDIR "/setup", ++#ifdef USE_ADNS ++ IPSEC_EXECDIR "/_pluto_adns", ++#endif + IPSEC_EXECDIR "/addconn", + IPSEC_EXECDIR "/auto", + IPSEC_EXECDIR "/barf", +- IPSEC_EXECDIR "/eroute", + IPSEC_EXECDIR "/ikeping", + IPSEC_EXECDIR "/readwriteconf", + IPSEC_EXECDIR "/_keycensor", +- IPSEC_EXECDIR "/klipsdebug", + IPSEC_EXECDIR "/look", + IPSEC_EXECDIR "/newhostkey", +- IPSEC_EXECDIR "/pf_key", +- IPSEC_EXECDIR "/_pluto_adns", + IPSEC_EXECDIR "/_plutorun", +- IPSEC_EXECDIR "/rsasigkey", + IPSEC_EXECDIR "/_secretcensor", ++ IPSEC_EXECDIR "/rsasigkey", + IPSEC_EXECDIR "/secrets", + IPSEC_EXECDIR "/showhostkey", +- IPSEC_EXECDIR "/spi", +- IPSEC_EXECDIR "/spigrp", + IPSEC_EXECDIR "/_stackmanager", +- IPSEC_EXECDIR "/tncfg", + IPSEC_EXECDIR "/_updown", +- IPSEC_EXECDIR "/_updown.klips", +- IPSEC_EXECDIR "/_updown.mast", +- IPSEC_EXECDIR "/_updown.netkey", + IPSEC_EXECDIR "/verify", + IPSEC_EXECDIR "/whack", + IPSEC_SBINDIR "/ipsec", ++#ifdef KLIPS ++ IPSEC_EXECDIR "/pf_key", ++ IPSEC_EXECDIR "/klipsdebug", ++ IPSEC_EXECDIR "/eroute", ++ IPSEC_EXECDIR "/spi", ++ IPSEC_EXECDIR "/spigrp", ++ IPSEC_EXECDIR "/_updown.klips", ++ IPSEC_EXECDIR "/tncfg", ++#ifdef KLIPS_MAST ++ IPSEC_EXECDIR "/_updown.mast", ++#endif ++#endif ++#ifdef NETKEY_SUPPORT ++ IPSEC_EXECDIR "/_updown.netkey", ++#endif + NULL }; diff --git a/SOURCES/libreswan-3.15-609343.patch b/SOURCES/libreswan-3.15-609343.patch new file mode 100644 index 0000000..02dd768 --- /dev/null +++ b/SOURCES/libreswan-3.15-609343.patch @@ -0,0 +1,26 @@ +diff --git a/programs/pluto/hostpair.c b/programs/pluto/hostpair.c +index 9b14341..e3afecd 100644 +--- a/programs/pluto/hostpair.c ++++ b/programs/pluto/hostpair.c +@@ -284,7 +284,8 @@ void release_dead_interfaces(void) + */ + passert(p == *pp); + +- p->interface = NULL; ++ terminate_connection(p->name); ++ p->interface = NULL; /* withdraw orientation */ + + *pp = p->hp_next; /* advance *pp */ + p->host_pair = NULL; +diff --git a/programs/pluto/initiate.c b/programs/pluto/initiate.c +index 056af59..eed8bf3 100644 +--- a/programs/pluto/initiate.c ++++ b/programs/pluto/initiate.c +@@ -119,6 +119,7 @@ bool orient(struct connection *c) + c->name, c->interface->ip_dev->id_rname, + p->ip_dev->id_rname); + } ++ terminate_connection(c->name); + c->interface = NULL; /* withdraw orientation */ + return FALSE; + } diff --git a/SOURCES/libreswan-3.15-NLMSG_OK.patch b/SOURCES/libreswan-3.15-NLMSG_OK.patch new file mode 100644 index 0000000..dbd552b --- /dev/null +++ b/SOURCES/libreswan-3.15-NLMSG_OK.patch @@ -0,0 +1,444 @@ +diff -Naur libreswan-3.15-orig/programs/addconn/addconn.c libreswan-3.15/programs/addconn/addconn.c +--- libreswan-3.15-orig/programs/addconn/addconn.c 2015-08-24 16:52:43.000000000 -0400 ++++ libreswan-3.15/programs/addconn/addconn.c 2015-09-04 09:21:23.866861084 -0400 +@@ -64,6 +64,8 @@ + * If DST is not specified, full route table will be returned. + * 16kB was too small for biggish router, so do 32kB. + * TODO: This should be dynamic! Fix it in netlink_read_reply(). ++ * Note: due to our hack to dodge a bug in NLMSG_OK, ++ * RTNL_BUFSIZE must be less than or equal to USHRT_MAX. + */ + #define RTNL_BUFSIZE 32768 + +@@ -139,30 +141,34 @@ + static + ssize_t netlink_read_reply(int sock, char *buf, unsigned int seqnum, __u32 pid) + { +- struct nlmsghdr *nlhdr; +- struct sockaddr_nl sa; +- socklen_t salen = sizeof(sa); +- ssize_t readlen = 0; + ssize_t msglen = 0; + + /* TODO: use dynamic buf */ +- do { ++ for (;;) { ++ struct sockaddr_nl sa; ++ ssize_t readlen; ++ + /* Read netlink message, verifying kernel origin. */ + do { ++ socklen_t salen = sizeof(sa); ++ + readlen = recvfrom(sock, buf, RTNL_BUFSIZE - msglen, 0, + (struct sockaddr *)&sa, &salen); +- if (readlen < 0) ++ if (readlen < 0 || salen != sizeof(sa)) + return -1; + } while (sa.nl_pid != 0); + + /* Verify it's valid */ +- nlhdr = (struct nlmsghdr *) buf; ++ struct nlmsghdr *nlhdr = (struct nlmsghdr *) buf; ++ + /* +- * CAST TO unsigned short IS TO AVOID netlink.h:NLMSG_OK error +- * which triggers a GCC warning in recent GCCs: ++ * The cast to unsigned short is to dodge an error in ++ * netlink.h:NLMSG_OK() which triggers a GCC warning in recent ++ * versions of GCC (2014 August): + * error: comparison between signed and unsigned integer expressions ++ * Note: as long as RTNL_BUFSIZE <= USHRT_MAX, this is safe. + */ +- if (NLMSG_OK(nlhdr, (unsigned short)readlen) == 0 || ++ if (!NLMSG_OK(nlhdr, (unsigned short)readlen) || + nlhdr->nlmsg_type == NLMSG_ERROR) + return -1; + +@@ -174,11 +180,16 @@ + buf += readlen; + msglen += readlen; + +- /* All done if it's not a multi part */ ++ /* all done if it's not a multi part */ + if ((nlhdr->nlmsg_flags & NLM_F_MULTI) == 0) + break; +- } while (nlhdr->nlmsg_seq != seqnum || +- nlhdr->nlmsg_pid != pid); ++ ++ /* all done if this is the one we were searching for */ ++ if (nlhdr->nlmsg_seq == seqnum && ++ nlhdr->nlmsg_pid == pid) ++ break; ++ } ++ + return msglen; + } + +@@ -188,31 +199,33 @@ + static + ssize_t netlink_query(char *msgbuf) + { +- struct nlmsghdr *nlmsg; +- int sock; ++ int sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); + +- /* Create socket */ +- if ((sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)) < 0) { ++ if (sock < 0) { + int e = errno; +- printf("create netlink socket: (%d: %s)", e, strerror(e)); ++ ++ printf("create netlink socket failure: (%d: %s)\n", e, strerror(e)); + return -1; + } + + /* Send request */ +- nlmsg = (struct nlmsghdr *)msgbuf; ++ struct nlmsghdr *nlmsg = (struct nlmsghdr *)msgbuf; ++ + if (send(sock, nlmsg, nlmsg->nlmsg_len, 0) < 0) { + int e = errno; +- printf("write netlink socket: (%d: %s)", e, strerror(e)); ++ ++ printf("write netlink socket failure: (%d: %s)\n", e, strerror(e)); + return -1; + } + + /* Read response */ ++ errno = 0; /* in case failure does not set it */ + ssize_t len = netlink_read_reply(sock, msgbuf, 1, getpid()); + + if (len < 0) { + int e = errno; + +- printf("read netlink socket: (%d: %s)", e, strerror(e)); ++ printf("read netlink socket failure: (%d: %s)\n", e, strerror(e)); + return -1; + } + close(sock); +@@ -331,11 +344,9 @@ + * 1) find out default gateway + * 2) find out src for that default gateway + */ +- if (!has_dst) { +- if (seeking_src && seeking_gateway) { +- seeking_src = FALSE; +- query_again = 1; +- } ++ if (!has_dst && seeking_src && seeking_gateway) { ++ seeking_src = FALSE; ++ query_again = 1; + } + if (seeking_gateway) { + struct nlmsghdr *nlmsg = (struct nlmsghdr *)msgbuf; +@@ -358,19 +369,17 @@ + struct nlmsghdr *nlmsg = (struct nlmsghdr *)msgbuf; + + /* +- * CAST TO unsigned short IS TO AVOID netlink.h:NLMSG_OK error +- * which triggers a GCC warning in recent GCCs: ++ * The cast to unsigned short is to dodge an error in ++ * netlink.h:NLMSG_OK() which triggers a GCC warning in recent ++ * versions of GCC (2014 August): + * error: comparison between signed and unsigned integer expressions ++ * Note: as long as RTNL_BUFSIZE <= USHRT_MAX, this is safe. + */ +- for (; NLMSG_OK(nlmsg, (unsigned short)len); nlmsg = NLMSG_NEXT(nlmsg, len)) { +- struct rtmsg *rtmsg; +- struct rtattr *rtattr; +- int rtlen; ++ for (; NLMSG_OK(nlmsg, (unsigned short)len); nlmsg = NLMSG_NEXT(nlmsg, len)) { + char r_interface[IF_NAMESIZE+1]; + char r_source[ADDRTOT_BUF]; + char r_gateway[ADDRTOT_BUF]; + char r_destination[ADDRTOT_BUF]; +- bool ignore; + + if (nlmsg->nlmsg_type == NLMSG_DONE) + break; +@@ -378,23 +387,23 @@ + if (nlmsg->nlmsg_type == NLMSG_ERROR) { + printf("netlink error\n"); + return -1; +- break; + } + + /* ignore all but IPv4 and IPv6 */ +- rtmsg = (struct rtmsg *) NLMSG_DATA(nlmsg); ++ struct rtmsg *rtmsg = (struct rtmsg *) NLMSG_DATA(nlmsg); ++ + if (rtmsg->rtm_family != AF_INET && + rtmsg->rtm_family != AF_INET6) + continue; + + /* Parse one route entry */ +- r_interface[0] = r_interface[IF_NAMESIZE] = r_source[0] = +- r_gateway[0] = r_destination[0] = '\0'; +- rtattr = (struct rtattr *) RTM_RTA(rtmsg); +- rtlen = RTM_PAYLOAD(nlmsg); +- for (; +- RTA_OK(rtattr, rtlen); +- rtattr = RTA_NEXT(rtattr, rtlen)) { ++ zero(&r_interface); ++ r_source[0] = r_gateway[0] = r_destination[0] = '\0'; ++ ++ struct rtattr *rtattr = (struct rtattr *) RTM_RTA(rtmsg); ++ int rtlen = RTM_PAYLOAD(nlmsg); ++ ++ while (RTA_OK(rtattr, rtlen)) { + switch (rtattr->rta_type) { + case RTA_OIF: + if_indextoname(*(int *)RTA_DATA(rtattr), +@@ -417,13 +426,14 @@ + sizeof(r_destination)); + break; + } ++ rtattr = RTA_NEXT(rtattr, rtlen); + } + + /* + * Ignore if not main table. + * Ignore ipsecX or mastX interfaces. + */ +- ignore = rtmsg->rtm_table != RT_TABLE_MAIN || ++ bool ignore = rtmsg->rtm_table != RT_TABLE_MAIN || + startswith(r_interface, "ipsec") || + startswith(r_interface, "mast"); + +@@ -548,20 +558,23 @@ + int main(int argc, char *argv[]) + { + int opt = 0; +- int autoall = 0; ++ bool autoall = FALSE; + int configsetup = 0; + int checkconfig = 0; +- char *export = "export"; /* display export before the foo=bar or not */ +- int listroute = 0, liststart = 0, listignore = 0, listadd = 0, +- listall = 0, dolist = 0, liststack = 0; +- struct starter_config *cfg = NULL; +- err_t err = NULL; +- char *confdir = NULL; ++ const char *export = "export"; /* display export before the foo=bar or not */ ++ bool ++ dolist = FALSE, ++ listadd = FALSE, ++ listroute = FALSE, ++ liststart = FALSE, ++ listignore = FALSE, ++ listall = FALSE, ++ liststack = FALSE; + char *configfile = NULL; +- char *varprefix = ""; ++ const char *varprefix = ""; + int exit_status = 0; + struct starter_conn *conn = NULL; +- char *ctlbase = NULL; ++ const char *ctlbase = NULL; + bool resolvip = TRUE; /* default to looking up names */ + + #if 0 +@@ -586,7 +599,7 @@ + break; + + case 'a': +- autoall = 1; ++ autoall = TRUE; + break; + + case 'D': +@@ -595,11 +608,11 @@ + break; + + case 'T': +- configsetup++; ++ configsetup++; /* ??? is this not idempotent? */ + break; + + case 'K': +- checkconfig++; ++ checkconfig++; /* ??? is this not idempotent? */ + break; + + case 'N': +@@ -615,33 +628,33 @@ + break; + + case 'L': +- listadd = 1; +- dolist = 1; ++ listadd = TRUE; ++ dolist = TRUE; + break; + + case 'r': +- listroute = 1; +- dolist = 1; ++ listroute = TRUE; ++ dolist = TRUE; + break; + + case 's': +- liststart = 1; +- dolist = 1; ++ liststart = TRUE; ++ dolist = TRUE; + break; + + case 'S': +- liststack = 1; +- dolist = 1; ++ liststack = TRUE; ++ dolist = TRUE; + break; + + case 'i': +- listignore = 1; +- dolist = 1; ++ listignore = TRUE; ++ dolist = TRUE; + break; + + case 'A': +- listall = 1; +- dolist = 1; ++ listall = TRUE; ++ dolist = TRUE; + break; + + case 'P': +@@ -672,9 +685,7 @@ + yydebug = 1; + } + +- /* find config file */ +- if (confdir == NULL) +- confdir = IPSEC_CONFDIR; ++ char *confdir = IPSEC_CONFDIR; + + if (configfile == NULL) { + /* ??? see code clone in programs/readwriteconf/readwriteconf.c */ +@@ -694,29 +705,32 @@ + + starter_use_log(verbose != 0, TRUE, verbose == 0); + +- err = NULL; /* reset to no error */ +- + if (configsetup || checkconfig || dolist) { + /* skip if we have no use for them... causes delays */ + resolvip = FALSE; + } + +- cfg = confread_load(configfile, &err, resolvip, ctlbase, configsetup); ++ struct starter_config *cfg = NULL; + +- if (cfg == NULL) { +- fprintf(stderr, "cannot load config '%s': %s\n", +- configfile, err); +- exit(3); +- } else if (checkconfig) { +- confread_free(cfg); +- exit(0); ++ { ++ err_t err = NULL; ++ ++ cfg = confread_load(configfile, &err, resolvip, ctlbase, configsetup); ++ ++ if (cfg == NULL) { ++ fprintf(stderr, "cannot load config '%s': %s\n", ++ configfile, err); ++ exit(3); ++ } else if (checkconfig) { ++ confread_free(cfg); ++ exit(0); ++ } + } + + if (autoall) { + if (verbose) + printf("loading all conns according to their auto= settings\n"); + +- + /* + * Load all conns marked as auto=add or better. + * First, do the auto=route and auto=add conns to quickly +@@ -727,7 +741,6 @@ + if (verbose) + printf(" Pass #1: Loading auto=add, auto=route and auto=start connections\n"); + +- + for (conn = cfg->conns.tqh_first; + conn != NULL; + conn = conn->link.tqe_next) { +@@ -828,7 +841,6 @@ + conn-> + strings[KSF_CONNALIAS] + )) { +- + if (conn->state == + STATE_ADDED) { + printf("\nalias: %s conn %s already added\n", +@@ -875,12 +887,10 @@ + printf("%s ", conn->name); + printf("\n"); + } else { +- + if (listadd) { + if (verbose) + printf("listing all conns marked as auto=add\n"); + +- + /* list all conns marked as auto=add */ + for (conn = cfg->conns.tqh_first; + conn != NULL; +@@ -893,7 +903,6 @@ + if (verbose) + printf("listing all conns marked as auto=route and auto=start\n"); + +- + /* + * list all conns marked as auto=route or start or + * better +@@ -911,7 +920,6 @@ + if (verbose) + printf("listing all conns marked as auto=start\n"); + +- + /* list all conns marked as auto=start */ + for (conn = cfg->conns.tqh_first; + conn != NULL; +@@ -925,7 +933,6 @@ + if (verbose) + printf("listing all conns marked as auto=ignore\n"); + +- + /* list all conns marked as auto=start */ + for (conn = cfg->conns.tqh_first; + conn != NULL; +@@ -942,14 +949,14 @@ + + for (kd = ipsec_conf_keywords_v2; kd->keyname != NULL; kd++) { + if (strstr(kd->keyname, "protostack")) { +- if (cfg->setup.strings[kd->field]) ++ if (cfg->setup.strings[kd->field]) { + printf("%s\n", + cfg->setup.strings[kd->field]); +- else ++ } else { + /* implicit default */ + printf("netkey\n"); ++ } + } +- + } + confread_free(cfg); + exit(0); +@@ -1008,7 +1015,6 @@ + } + confread_free(cfg); + exit(0); +- + } + + confread_free(cfg); diff --git a/SOURCES/libreswan-3.15-cisco-delete.patch b/SOURCES/libreswan-3.15-cisco-delete.patch new file mode 100644 index 0000000..6cea96e --- /dev/null +++ b/SOURCES/libreswan-3.15-cisco-delete.patch @@ -0,0 +1,107 @@ +diff --git a/programs/pluto/ikev1_main.c b/programs/pluto/ikev1_main.c +index de20a83..31d959b 100644 +--- a/programs/pluto/ikev1_main.c ++++ b/programs/pluto/ikev1_main.c +@@ -2983,13 +2983,12 @@ bool accept_delete(struct msg_digest *md, + * IPSEC (ESP/AH) + */ + ipsec_spi_t spi; /* network order */ +- bool bogus; +- struct state *dst; + + if (!in_raw(&spi, sizeof(spi), &p->pbs, "SPI")) + return self_delete; + +- dst = find_phase2_state_to_delete(st, ++ bool bogus; ++ struct state *dst = find_phase2_state_to_delete(st, + d->isad_protoid, + spi, + &bogus); +@@ -2997,14 +2996,19 @@ bool accept_delete(struct msg_digest *md, + passert(dst != st); /* st is an IKE SA */ + if (dst == NULL) { + loglog(RC_LOG_SERIOUS, +- "ignoring Delete SA payload: %s SA(0x%08" PRIx32 ") not found (%s)", ++ "ignoring Delete SA payload: %s SA(0x%08" PRIx32 ") not found (maybe expired)", + enum_show(&protocol_names, + d->isad_protoid), +- ntohl(spi), +- bogus ? +- "our SPI - bogus implementation" : +- "maybe expired"); ++ ntohl(spi)); + } else { ++ if (bogus) { ++ loglog(RC_LOG_SERIOUS, ++ "warning: Delete SA payload: %s SA(0x%08" PRIx32 ") is our own SPI (bogus implementation) - deleting anyway", ++ enum_show(&protocol_names, ++ d->isad_protoid), ++ ntohl(spi)); ++ } ++ + struct connection *rc = dst->st_connection; + struct connection *oldc = cur_connection; + +diff --git a/programs/pluto/state.c b/programs/pluto/state.c +index b2eac62..c5d4484 100644 +--- a/programs/pluto/state.c ++++ b/programs/pluto/state.c +@@ -1537,37 +1537,52 @@ struct state *find_likely_sender(size_t packet_len, u_char *packet) + return NULL; + } + ++/* ++ * find_phase2_state_to_delete: find an AH or ESP SA to delete ++ * ++ * We are supposed to be given the other side's SPI. ++ * Certain CISCO implementations send our side's SPI instead. ++ * We'll accept this, but mark it as bogus. ++ */ + struct state *find_phase2_state_to_delete(const struct state *p1st, + u_int8_t protoid, + ipsec_spi_t spi, + bool *bogus) + { +- struct state *st; ++ struct state *bogusst = NULL; + int i; + + *bogus = FALSE; + for (i = 0; i < STATE_TABLE_SIZE; i++) { ++ struct state *st; ++ + FOR_EACH_ENTRY(st, i, { + if (IS_IPSEC_SA_ESTABLISHED(st->st_state) && + p1st->st_connection->host_pair == + st->st_connection->host_pair && + same_peer_ids(p1st->st_connection, +- st->st_connection, NULL)) { ++ st->st_connection, NULL)) ++ { + struct ipsec_proto_info *pr = + protoid == PROTO_IPSEC_AH ? + &st->st_ah : &st->st_esp; + + if (pr->present) { +- if (pr->attrs.spi == spi) ++ if (pr->attrs.spi == spi) { ++ *bogus = FALSE; + return st; ++ } + +- if (pr->our_spi == spi) ++ if (pr->our_spi == spi) { + *bogus = TRUE; ++ bogusst = st; ++ /* don't return! */ ++ } + } + } + }); + } +- return NULL; ++ return bogusst; + } + + /* diff --git a/SOURCES/libreswan-3.15-gcc-osw-interop-conf.patch b/SOURCES/libreswan-3.15-gcc-osw-interop-conf.patch new file mode 100644 index 0000000..27fe3f5 --- /dev/null +++ b/SOURCES/libreswan-3.15-gcc-osw-interop-conf.patch @@ -0,0 +1,910 @@ +diff -Naur libreswan-3.15-orig/include/ipsecconf/confread.h libreswan-3.15/include/ipsecconf/confread.h +--- libreswan-3.15-orig/include/ipsecconf/confread.h 2015-08-24 16:52:43.000000000 -0400 ++++ libreswan-3.15/include/ipsecconf/confread.h 2015-09-03 11:43:09.630000000 -0400 +@@ -132,7 +132,7 @@ + extern struct starter_config *confread_load(const char *file, + err_t *perr, + bool resolvip, +- char *ctlbase, ++ const char *ctlbase, + bool setuponly); + extern struct starter_conn *alloc_add_conn(struct starter_config *cfg, + char *name); +diff -Naur libreswan-3.15-orig/include/ipsecconf/keywords.h libreswan-3.15/include/ipsecconf/keywords.h +--- libreswan-3.15-orig/include/ipsecconf/keywords.h 2015-08-24 16:52:43.000000000 -0400 ++++ libreswan-3.15/include/ipsecconf/keywords.h 2015-09-03 11:43:10.538000000 -0400 +@@ -305,8 +305,7 @@ + struct kw_list { + struct kw_list *next; + struct keyword keyword; +- char *string; +- double decimal; ++ char *string; + unsigned int number; + }; + +diff -Naur libreswan-3.15-orig/lib/libipsecconf/confread.c libreswan-3.15/lib/libipsecconf/confread.c +--- libreswan-3.15-orig/lib/libipsecconf/confread.c 2015-08-24 16:52:43.000000000 -0400 ++++ libreswan-3.15/lib/libipsecconf/confread.c 2015-09-03 11:42:22.941000000 -0400 +@@ -1418,7 +1418,7 @@ + struct starter_config *confread_load(const char *file, + err_t *perr, + bool resolvip, +- char *ctlbase, ++ const char *ctlbase, + bool setuponly) + { + struct starter_config *cfg = NULL; +diff -Naur libreswan-3.15-orig/lib/libipsecconf/confwrite.c libreswan-3.15/lib/libipsecconf/confwrite.c +--- libreswan-3.15-orig/lib/libipsecconf/confwrite.c 2015-08-24 16:52:43.000000000 -0400 ++++ libreswan-3.15/lib/libipsecconf/confwrite.c 2015-09-03 11:42:22.941000000 -0400 +@@ -412,9 +412,9 @@ + + int alsoplace = 0; + +- fprintf(out, "\t#also = "); ++ fprintf(out, "\t#also ="); + while (conn->alsos[alsoplace] != NULL) { +- fprintf(out, "%s ", conn->alsos[alsoplace]); ++ fprintf(out, " %s", conn->alsos[alsoplace]); + alsoplace++; + } + fprintf(out, "\n"); +diff -Naur libreswan-3.15-orig/lib/libipsecconf/Makefile libreswan-3.15/lib/libipsecconf/Makefile +--- libreswan-3.15-orig/lib/libipsecconf/Makefile 2015-08-24 16:52:43.000000000 -0400 ++++ libreswan-3.15/lib/libipsecconf/Makefile 2015-09-03 11:42:22.941000000 -0400 +@@ -38,21 +38,45 @@ + # since all the $(OBJS) indirectly depend on the header anyway. + $(OBJS): parser.tab.h + +-# Use UNIX basename to strip off the directory. Use grep to workaround flex < 2.5.35 ++# Use UNIX basename to strip off the directory. ++# Use sed to work around two bugs: ++# ++# - flex < 2.5.35 generates an extern that isn't good ++# ++# - flex on RHEL 7 generates code that provokes GCC to warn ++# about comparing a signed value with an unsigned value ++# (Combination of a new GCC and an old flex). ++# Adding one cast makes RHEL 6's GCC unhappy, so we add two. ++# On RHEL 6, i is int and _yybytes_len is int. ++# On RHEL 7, i is int and _yybytes_len is yy_size_t ++# On Fedora 21, i is yy_size_t and _yybytes_len is yy_size_t ++# On some architectures, yy_size_t is wider than int; ++# which makes a mixed comparison OK. ++# ++# Avoid sed -i which somehow causes unwritable files ++# on fedora 20 with 9p filesystem mount. ++# Avoid creating the target file until it is done. + lex.yy.c: parser.l +- cd $(builddir) && $(LEX) -t $(srcdir)/$$(basename $<) | grep -v '^extern int isatty' > $@ ++ cd $(builddir) && \ ++ $(LEX) -o $@.$$$$ $(srcdir)/$$(basename $<) && \ ++ sed -e 's/for ( i = 0; i < _yybytes_len; ++i )$$/for ( i = 0; (yy_size_t)i < (yy_size_t)_yybytes_len; ++i )/' \ ++ -e '/^extern int isatty.*$$/d' $@.$$$$ >SEDTMP$$$$ && \ ++ rm $@.$$$$ && \ ++ mv SEDTMP$$$$ $@ + + # Use wild card rule so that GNU Make knows that both are output from + # a single recipe. + # - sed command for workaround for older bison vs GCC warning + # - avoid sed -i which somehow causes unwritable files + # on fedora 20 with 9p filesystem mount ++# - avoid creating the target file until it is done + %.tab.h %.tab.c: %.y + cd $(builddir) && \ +- $(BISON) ${BISONOSFLAGS} -v -d $(srcdir)/$$(basename $<) && \ ++ $(BISON) ${BISONOSFLAGS} -v --defines=$$(basename $< .y).tab.h -o $$(basename $< .y).tab.c$$$$ $(srcdir)/$$(basename $<) && \ + sed -e '/^ *#/s/if YYENABLE_NLS/if defined(YYENABLE_NLS) \&\& YYENABLE_NLS/' \ + -e '/^ *#/s/if YYLTYPE_IS_TRIVIAL/if defined(YYLTYPE_IS_TRIVIAL) \&\& YYLTYPE_IS_TRIVIAL/' \ +- $$(basename $< .y).tab.c >SEDTMP$$$$ && \ ++ $$(basename $< .y).tab.c$$$$ >SEDTMP$$$$ && \ ++ rm $$(basename $< .y).tab.c$$$$ && \ + mv SEDTMP$$$$ $$(basename $< .y).tab.c + + clean: parser-clean +diff -Naur libreswan-3.15-orig/lib/libipsecconf/parser.l libreswan-3.15/lib/libipsecconf/parser.l +--- libreswan-3.15-orig/lib/libipsecconf/parser.l 2015-08-24 16:52:43.000000000 -0400 ++++ libreswan-3.15/lib/libipsecconf/parser.l 2015-09-03 11:42:22.942000000 -0400 +@@ -373,7 +373,17 @@ + + [0-9]+ { + /* process a number */ +- yylval.num = strtoul(yytext, NULL, 10); ++ unsigned long val = (errno = 0, strtoul(yytext, NULL, 10)); ++ ++ if (errno != 0 || val > UINT_MAX) { ++ char ebuf[128]; ++ ++ snprintf(ebuf, sizeof(ebuf), ++ "number too large: %s", ++ yytext); ++ yyerror(ebuf); ++ } ++ yylval.num = val; + BEGIN INITIAL; + return INTEGER; + } +diff -Naur libreswan-3.15-orig/lib/libipsecconf/parser.y libreswan-3.15/lib/libipsecconf/parser.y +--- libreswan-3.15-orig/lib/libipsecconf/parser.y 2015-08-24 16:52:43.000000000 -0400 ++++ libreswan-3.15/lib/libipsecconf/parser.y 2015-09-03 11:42:22.942000000 -0400 +@@ -26,7 +26,7 @@ + #include + #include + #include +- ++#include + #define YYDEBUG 1 + + #include "ipsecconf/keywords.h" +@@ -41,16 +41,15 @@ + * Bison + */ + static char parser_errstring[ERRSTRING_LEN+1]; +-static struct kw_list *alloc_kwlist(void); +-static struct starter_comments *alloc_comment(void); + + /** + * Static Globals + */ +-static int _save_errors_; +-static struct config_parsed *_parser_cfg; +-static struct kw_list **_parser_kw, *_parser_kw_last; +-static struct starter_comments_list *_parser_comments; ++static bool save_errors; ++static struct config_parsed *parser_cfg; ++static struct kw_list **parser_kw, *parser_kw_last; ++static void new_parser_kw(struct keyword *keyword, char *string, unsigned int number); /* forward */ ++static struct starter_comments_list *parser_comments; + + /** + * Functions +@@ -60,7 +59,7 @@ + + %union { + char *s; +- unsigned int num; ++ unsigned int num; + struct keyword k; + } + %token EQUAL FIRST_SPACES EOL CONFIG SETUP CONN INCLUDE VERSION +@@ -72,6 +71,8 @@ + %token BOOLWORD + %token PERCENTWORD + %token COMMENT ++ ++%type duration + %% + + /* +@@ -84,8 +85,8 @@ + /* we have configs shipped with version 2 (INTEGER) and with version 2.0 (STRING, now NUMBER/float was removed */ + + versionstmt: /* NULL */ +- | VERSION STRING EOL blanklines +- | VERSION INTEGER EOL blanklines ++ | VERSION STRING EOL blanklines ++ | VERSION INTEGER EOL blanklines + ; + + blanklines: /* NULL */ +@@ -98,40 +99,40 @@ + + section_or_include: + CONFIG SETUP EOL { +- _parser_kw = &(_parser_cfg->config_setup); +- _parser_kw_last = NULL; +- _parser_comments = &_parser_cfg->comments; ++ parser_kw = &parser_cfg->config_setup; ++ parser_kw_last = NULL; ++ parser_comments = &parser_cfg->comments; + if (yydebug) + fprintf(stderr, "\nconfig setup read\n"); + + } kw_sections + | CONN STRING EOL { +- struct section_list *section; +- section = (struct section_list *)malloc(sizeof(struct section_list)); +- if (section != NULL) { ++ struct section_list *section = malloc(sizeof(struct section_list)); ++ ++ if (section == NULL) { ++ parser_kw = NULL; ++ parser_kw_last = NULL; ++ yyerror("can't allocate memory in section_or_include/conn"); ++ } else { + section->name = $2; + section->kw = NULL; + +- TAILQ_INSERT_TAIL(&_parser_cfg->sections, section, link); ++ TAILQ_INSERT_TAIL(&parser_cfg->sections, section, link); + +- /* setup keyword section to record values */ +- _parser_kw = &(section->kw); +- _parser_kw_last = NULL; ++ /* setup keyword section to record values */ ++ parser_kw = §ion->kw; ++ parser_kw_last = NULL; + + /* and comments */ + TAILQ_INIT(§ion->comments); +- _parser_comments = §ion->comments; ++ parser_comments = §ion->comments; + +- if(yydebug) ++ if (yydebug) + fprintf(stderr, "\nread conn %s\n", section->name); +- } else { +- _parser_kw = NULL; +- _parser_kw_last = NULL; +- yyerror("can't allocate memory in section_or_include/conn"); + } + } kw_sections + | INCLUDE STRING EOL { +- parser_y_include($2); ++ parser_y_include($2); + } + ; + +@@ -144,198 +145,174 @@ + + statement_kw: + KEYWORD EQUAL KEYWORD { +- struct kw_list *new; ++ struct keyword kw = $1; + +- assert(_parser_kw != NULL); +- new = alloc_kwlist(); +- if (new == NULL) { +- yyerror("can't allocate memory in statement_kw"); +- } else { +- struct keyword kw; +- /* because the third argument was also a keyword, we dig up the string representation. */ +- const char *value = $3.keydef->keyname; +- +- kw = $1; +- new->keyword = kw; +- +- switch(kw.keydef->type) { +- case kt_list: +- new->number = parser_enum_list(kw.keydef, value, TRUE); +- break; +- case kt_enum: +- new->number = parser_enum_list(kw.keydef, value, FALSE); +- break; +- case kt_rsakey: +- case kt_loose_enum: +- new->number = parser_loose_enum(&new->keyword, value); +- break; +- case kt_string: +- case kt_appendstring: +- case kt_appendlist: +- case kt_filename: +- case kt_dirname: +- case kt_ipaddr: +- case kt_bitstring: +- case kt_idtype: +- case kt_range: +- case kt_subnet: +- new->string = strdup(value); +- break; +- +- case kt_bool: +- case kt_invertbool: +- case kt_number: +- case kt_time: +- case kt_percent: ++ /* because the third argument was also a keyword, we dig up the string representation. */ ++ const char *value = $3.keydef->keyname; ++ ++ char *string = NULL; /* neutral placeholding value */ ++ unsigned int number = 0; /* neutral placeholding value */ ++ ++ switch(kw.keydef->type) { ++ case kt_list: ++ number = parser_enum_list(kw.keydef, value, TRUE); ++ break; ++ case kt_enum: ++ number = parser_enum_list(kw.keydef, value, FALSE); ++ break; ++ case kt_rsakey: ++ case kt_loose_enum: ++ number = parser_loose_enum(&kw, value); ++ break; ++ case kt_string: ++ case kt_appendstring: ++ case kt_appendlist: ++ case kt_filename: ++ case kt_dirname: ++ case kt_ipaddr: ++ case kt_bitstring: ++ case kt_idtype: ++ case kt_range: ++ case kt_subnet: ++ string = strdup(value); ++ break; ++ ++ case kt_bool: ++ case kt_invertbool: ++ case kt_number: ++ case kt_time: ++ case kt_percent: + yyerror("keyword value is a keyword, but type not a string"); + assert(kw.keydef->type != kt_bool); + break; + +- case kt_comment: +- break; ++ case kt_comment: ++ break; + +- case kt_obsolete: +- case kt_obsolete_quiet: +- break; +- } +- new->next = NULL; +- +- if (_parser_kw_last) +- _parser_kw_last->next = new; +- _parser_kw_last = new; +- if (*_parser_kw == NULL) +- *_parser_kw = new; ++ case kt_obsolete: ++ case kt_obsolete_quiet: ++ break; + } ++ ++ new_parser_kw(&kw, string, number); + } + | COMMENT EQUAL STRING { +- struct starter_comments *new; ++ struct starter_comments *new = ++ malloc(sizeof(struct starter_comments)); + +- new = alloc_comment(); + if (new == NULL) { +- yyerror("can't allocate memory in statement_kw"); ++ yyerror("can't allocate memory in statement_kw"); + } else { +- new->x_comment = strdup($1.string); +- new->commentvalue = strdup($3); +- TAILQ_INSERT_TAIL(_parser_comments, new, link); ++ new->x_comment = strdup($1.string); ++ new->commentvalue = strdup($3); ++ TAILQ_INSERT_TAIL(parser_comments, new, link); + } + } + | KEYWORD EQUAL STRING { +- struct kw_list *new; ++ struct keyword kw = $1; + +- assert(_parser_kw != NULL); +- new = alloc_kwlist(); +- if (new == NULL) { +- yyerror("can't allocate memory in statement_kw"); +- } else { +- struct keyword kw; ++ char *string = NULL; /* neutral placeholding value */ ++ unsigned int number = 0; /* neutral placeholding value */ + +- kw = $1; +- new->keyword = kw; ++ switch(kw.keydef->type) { ++ case kt_list: ++ number = parser_enum_list(kw.keydef, $3, TRUE); ++ break; ++ case kt_enum: ++ number = parser_enum_list(kw.keydef, $3, FALSE); ++ break; ++ case kt_rsakey: ++ case kt_loose_enum: ++ number = parser_loose_enum(&kw, $3); ++ break; ++ case kt_string: ++ case kt_appendstring: ++ case kt_appendlist: ++ case kt_filename: ++ case kt_dirname: ++ case kt_ipaddr: ++ case kt_bitstring: ++ case kt_idtype: ++ case kt_range: ++ case kt_subnet: ++ string = $3; ++ break; + +- switch(kw.keydef->type) { +- case kt_list: +- new->number = parser_enum_list(kw.keydef, $3, TRUE); +- break; +- case kt_enum: +- new->number = parser_enum_list(kw.keydef, $3, FALSE); +- break; +- case kt_rsakey: +- case kt_loose_enum: +- new->number = parser_loose_enum(&new->keyword, $3); +- break; +- case kt_string: +- case kt_appendstring: +- case kt_appendlist: +- case kt_filename: +- case kt_dirname: +- case kt_ipaddr: +- case kt_bitstring: +- case kt_idtype: +- case kt_range: +- case kt_subnet: +- new->string = $3; +- break; +- +- case kt_bool: +- case kt_invertbool: +- case kt_number: +- case kt_time: +- case kt_percent: ++ case kt_bool: ++ case kt_invertbool: ++ case kt_number: ++ case kt_time: ++ case kt_percent: + yyerror("valid keyword, but value is not a number"); +- assert(!(kw.keydef->type == kt_bool)); ++ assert(kw.keydef->type != kt_bool); ++ break; ++ case kt_comment: ++ break; ++ case kt_obsolete: ++ case kt_obsolete_quiet: + break; +- case kt_comment: +- break; +- case kt_obsolete: +- case kt_obsolete_quiet: +- break; +- } +- new->next = NULL; +- +- if (_parser_kw_last) +- _parser_kw_last->next = new; +- _parser_kw_last = new; +- if (!*_parser_kw) *_parser_kw = new; + } ++ ++ new_parser_kw(&kw, string, number); + } + + | BOOLWORD EQUAL BOOL { +- struct kw_list *new; +- +- assert(_parser_kw != NULL); +- new = alloc_kwlist(); +- if (new == NULL) { +- yyerror("can't allocate memory in statement_kw"); +- } else { +- new->keyword = $1; +- new->number = $3; /* Should not be necessary! */ +- new->next = NULL; +- if (_parser_kw_last) +- _parser_kw_last->next = new; +- _parser_kw_last = new; +- if (!*_parser_kw) *_parser_kw = new; +- } ++ new_parser_kw(&$1, NULL, $3); + } + | KEYWORD EQUAL INTEGER { +- struct kw_list *new; +- +- assert(_parser_kw != NULL); +- new = alloc_kwlist(); +- if (new == NULL) { +- yyerror("can't allocate memory in statement_kw"); +- } else { +- new->keyword = $1; +- new->number = $3; /* Should not be necessary! */ +- new->next = NULL; +- if (_parser_kw_last) +- _parser_kw_last->next = new; +- _parser_kw_last = new; +- if (!*_parser_kw) *_parser_kw = new; +- } ++ new_parser_kw(&$1, NULL, $3); + } +- | TIMEWORD EQUAL STRING { +- struct kw_list *new; +- char *endptr, *str; +- unsigned int val; ++ | TIMEWORD EQUAL duration { ++ new_parser_kw(&$1, NULL, $3); ++ } ++ | PERCENTWORD EQUAL STRING { + struct keyword kw = $1; +- bool fail; +- char buf[80]; +- +- +- fail = FALSE; +- +- str = $3; +- +- val = strtoul(str, &endptr, 10); +- +- if(endptr == str) { +- snprintf(buf, sizeof(buf), "bad duration value %s=%s", kw.keydef->keyname, str); +- yyerror(buf); +- fail = TRUE; ++ const char *const str = $3; ++ /*const*/ char *endptr; ++ char buf[80]; ++ unsigned long val = (errno = 0, strtoul(str, &endptr, 10)); ++ ++ if (endptr == str) { ++ snprintf(buf, sizeof(buf), ++ "malformed percentage %s=%s", ++ kw.keydef->keyname, str); ++ yyerror(buf); ++ } else if (*endptr != '%' || endptr[1] != '\0') { ++ snprintf(buf, sizeof(buf), ++ "bad percentage multiplier \"%s\" on %s", ++ endptr, str); ++ yyerror(buf); ++ } else if (errno != 0 || val > UINT_MAX) { ++ snprintf(buf, sizeof(buf), ++ "percentage way too large \"%s\"", str); ++ yyerror(buf); ++ } else { ++ new_parser_kw(&kw, NULL, (unsigned int)val); + } ++ } ++ | KEYWORD EQUAL BOOL { ++ new_parser_kw(&$1, NULL, $3); ++ } ++ | KEYWORD EQUAL { /* this is meaningless, we ignore it */ } ++ ; + +- if(!fail) +- { ++duration: ++ INTEGER { ++ $$ = $1; ++ } ++ | STRING { ++ const char *const str = $1; ++ /*const*/ char *endptr; ++ char buf[80]; ++ ++ unsigned long val = (errno = 0, strtoul(str, &endptr, 10)); ++ int strtoul_errno = errno; ++ ++ if (endptr == str) { ++ snprintf(buf, sizeof(buf), "bad duration value \"%s\"", str); ++ yyerror(buf); ++ } else { ++ bool bad_suffix = FALSE; + unsigned scale; + + if (*endptr == '\0') { +@@ -350,194 +327,87 @@ + case 'd': scale = secs_per_day; break; + case 'w': scale = 7*secs_per_day; break; + default: +- snprintf(buf, sizeof(buf), +- "bad duration multiplier '%c' on %s", +- *endptr, str); +- yyerror(buf); +- fail=TRUE; ++ bad_suffix = TRUE; + } + } else { ++ bad_suffix = TRUE; ++ } ++ ++ if (bad_suffix) { + snprintf(buf, sizeof(buf), + "bad duration multiplier \"%s\" on %s", + endptr, str); + yyerror(buf); +- fail=TRUE; +- } +- +- if (!fail) { +- if (UINT_MAX / scale < val) { +- snprintf(buf, sizeof(buf), +- "overflow scaling %s", +- str); +- yyerror(buf); +- fail=TRUE; +- } else { +- val *= scale; +- } ++ } else if (strtoul_errno != 0 || UINT_MAX / scale < val) { ++ snprintf(buf, sizeof(buf), ++ "duration too large: \"%s\" is more than %u seconds", ++ str, UINT_MAX); ++ yyerror(buf); ++ } else { ++ $$ = val * scale; + } +- } +- +- if(!fail) +- { +- assert(_parser_kw != NULL); +- new = alloc_kwlist(); +- if (new == NULL) { +- yyerror("can't allocate memory in statement_kw"); +- } else { +- new->keyword = $1; +- new->number = val; +- new->next = NULL; +- if (_parser_kw_last) +- _parser_kw_last->next = new; +- _parser_kw_last = new; +- if (*_parser_kw == NULL) +- *_parser_kw = new; +- } +- } +- } +- | PERCENTWORD EQUAL STRING { +- struct kw_list *new; +- char *endptr, *str; +- struct keyword kw = $1; +- unsigned int val; +- bool fail; +- char buf[80]; +- +- +- fail = FALSE; +- +- str = $3; +- +- val = strtoul(str, &endptr, 10); +- +- if(endptr == str) { +- snprintf(buf, sizeof(buf), "bad percent value %s=%s", kw.keydef->keyname, str); +- yyerror(buf); +- fail = TRUE; +- +- } +- +- if(!fail) +- { +- if ((*endptr == '%') && (endptr[1] == '\0')) { } +- else { +- snprintf(buf, sizeof(buf), "bad percentage multiplier '%c' on %s", *endptr, str); +- yyerror(buf); +- fail=TRUE; +- } +- } +- +- if(!fail) +- { +- assert(_parser_kw != NULL); +- new = alloc_kwlist(); +- if (new == NULL) { +- yyerror("can't allocate memory in statement_kw"); +- } else { +- new->keyword = $1; +- new->number = val; +- new->next = NULL; +- if (_parser_kw_last) +- _parser_kw_last->next = new; +- _parser_kw_last = new; +- if (*_parser_kw == NULL) +- *_parser_kw = new; +- } +- } +- } +- | KEYWORD EQUAL BOOL { +- struct kw_list *new; +- +- assert(_parser_kw != NULL); +- new = alloc_kwlist(); +- if (new != NULL) { +- yyerror("can't allocate memory in statement_kw"); +- } else { +- new->keyword = $1; +- new->number = $3; /* Should not be necessary! */ +- new->next = NULL; +- if (_parser_kw_last) +- _parser_kw_last->next = new; +- _parser_kw_last = new; +- if (*_parser_kw == NULL) +- *_parser_kw = new; + } +- } +- | KEYWORD EQUAL { /* this is meaningless, we ignore it */ } +- ; +- ++ }; + %% + + void yyerror(const char *s) + { +- if (_save_errors_) ++ if (save_errors) + parser_y_error(parser_errstring, ERRSTRING_LEN, s); + } + + struct config_parsed *parser_load_conf(const char *file, err_t *perr) + { +- struct config_parsed *cfg=NULL; +- int err = 0; +- FILE *f; +- +- zero(&parser_errstring); ++ parser_errstring[0] = '\0'; + if (perr != NULL) + *perr = NULL; + +- cfg = (struct config_parsed *)malloc(sizeof(struct config_parsed)); +- if (cfg == NULL) +- { +- snprintf(parser_errstring, ERRSTRING_LEN, "can't allocate memory"); +- err++; +- goto end; ++ struct config_parsed *cfg = malloc(sizeof(struct config_parsed)); ++ ++ if (cfg == NULL) { ++ snprintf(parser_errstring, ERRSTRING_LEN, "can't allocate memory"); ++ goto err; + } + zero(cfg); /* ??? pointer fields may not be NULLed */ +- if (strncmp(file, "-", sizeof("-")) == 0) { +- f = fdopen(STDIN_FILENO, "r"); +- } +- else { +- f = fopen(file, "r"); +- } +- if (!f) +- { +- snprintf(parser_errstring, ERRSTRING_LEN, "can't load file '%s'", +- file); +- err++; +- goto end; ++ ++ FILE *f = streq(file, "-") ? ++ fdopen(STDIN_FILENO, "r") : fopen(file, "r"); ++ ++ if (f == NULL) { ++ snprintf(parser_errstring, ERRSTRING_LEN, "can't load file '%s'", ++ file); ++ goto err; + } + + yyin = f; + parser_y_init(file, f); +- _save_errors_=1; ++ save_errors = TRUE; + TAILQ_INIT(&cfg->sections); + TAILQ_INIT(&cfg->comments); +- _parser_cfg = cfg; ++ parser_cfg = cfg; + +- if (yyparse()!=0) { +- if (parser_errstring[0]=='\0') { +- snprintf(parser_errstring, ERRSTRING_LEN, +- "Unknown error..."); +- } +- _save_errors_=0; +- while (yyparse()!=0); +- err++; +- goto end; +- } +- if (parser_errstring[0]!='\0') { +- err++; +- goto end; +- } +- /** +- * Config valid +- */ +-end: +- if (err) { +- if (perr) *perr = (err_t)strdup(parser_errstring); +- if (cfg) parser_free_conf (cfg); +- cfg = NULL; ++ if (yyparse() != 0) { ++ if (parser_errstring[0] == '\0') { ++ snprintf(parser_errstring, ERRSTRING_LEN, ++ "Unknown error..."); ++ } ++ save_errors = FALSE; ++ do {} while (yyparse() != 0); ++ } else if (parser_errstring[0] == '\0') { ++ /** ++ * Config valid ++ */ ++ return cfg; + } ++ /* falls through on error */ ++ ++err: ++ if (perr != NULL) ++ *perr = (err_t)strdup(parser_errstring); ++ if (cfg != NULL) ++ parser_free_conf(cfg); + +- return cfg; ++ return NULL; + } + + static void parser_free_kwlist(struct kw_list *list) +@@ -546,7 +416,7 @@ + struct kw_list *elt = list; + + list = list->next; +- if (elt->string) ++ if (elt->string != NULL) + free(elt->string); + free(elt); + } +@@ -554,16 +424,18 @@ + + void parser_free_conf(struct config_parsed *cfg) + { +- struct section_list *seci, *sec; +- if (cfg) { ++ if (cfg != NULL) { ++ struct section_list *seci; ++ + parser_free_kwlist(cfg->config_setup); + +- for(seci = cfg->sections.tqh_first; seci != NULL; ) +- { +- sec = seci; ++ for (seci = cfg->sections.tqh_first; seci != NULL; ) { ++ struct section_list *sec = seci; ++ + seci = seci->link.tqe_next; + +- if (sec->name) free(sec->name); ++ if (sec->name != NULL) ++ free(sec->name); + parser_free_kwlist(sec->kw); + free(sec); + } +@@ -572,20 +444,32 @@ + } + } + +-static struct kw_list *alloc_kwlist(void) ++static void new_parser_kw(struct keyword *keyword, char *string, unsigned int number) + { +- struct kw_list *new; +- +- new = (struct kw_list *)malloc(sizeof(struct kw_list)); +- zero(new); /* ??? pointer members might not be set to NULL */ +- return new; +-} ++ struct kw_list *new = malloc(sizeof(struct kw_list)); + +-static struct starter_comments *alloc_comment(void) +-{ +- struct starter_comments *new; ++ if (new == NULL) { ++ yyerror("cannot allocate memory for a kw_list"); ++ } else { ++ /* ++ * fill the values into new ++ * (either string or number might have a placeholder value ++ */ ++ new->keyword = *keyword; ++ new->string = string; ++ new->number = number; ++ new->next = NULL; ++ ++ /* link the new kw_list into the list */ ++ ++ if (*parser_kw == NULL) ++ *parser_kw = new; /* first in (some) list */ ++ ++ /* connect to previous last on list */ ++ if (parser_kw_last != NULL) ++ parser_kw_last->next = new; + +- new = (struct starter_comments *)malloc(sizeof(struct starter_comments)); +- zero(new); /* ??? pointer members might not be set to NULL */ +- return new; ++ /* new is new last on list */ ++ parser_kw_last = new; ++ } + } diff --git a/SOURCES/libreswan-3.15-ikev1-pam.patch b/SOURCES/libreswan-3.15-ikev1-pam.patch new file mode 100644 index 0000000..178fe26 --- /dev/null +++ b/SOURCES/libreswan-3.15-ikev1-pam.patch @@ -0,0 +1,263 @@ +diff -Naur libreswan-3.15-orig/programs/pluto/ikev1_xauth.c libreswan-3.15/programs/pluto/ikev1_xauth.c +--- libreswan-3.15-orig/programs/pluto/ikev1_xauth.c 2015-08-24 16:52:43.000000000 -0400 ++++ libreswan-3.15/programs/pluto/ikev1_xauth.c 2015-09-03 11:32:27.525000000 -0400 +@@ -1001,81 +1001,6 @@ + return STF_OK; + } + +-#ifdef XAUTH_HAVE_PAM +- +-/** Do authentication via PAM (Plugable Authentication Modules) +- * +- * We try to authenticate the user in our own PAM session. +- * +- * @return bool success +- */ +-/* IN AN AUTH THREAD */ +-static bool do_pam_authentication(void *varg) +-{ +- struct xauth_thread_arg *arg = varg; +- int retval; +- pam_handle_t *pamh = NULL; +- struct pam_conv conv; +- const char *what; +- +- /* This do-while structure is designed to allow a logical cascade +- * without excessive indentation. No actual looping happens. +- * Failure is handled by "break". +- */ +- do { +- ipstr_buf ra; +- +- conv.conv = pam_conv; +- conv.appdata_ptr = varg; +- +- what = "pam_start"; +- retval = pam_start("pluto", arg->name, &conv, &pamh); +- if (retval != PAM_SUCCESS) +- break; +- +- DBG(DBG_CONTROL, DBG_log("pam_start SUCCESS")); +- +- /* Send the remote host address to PAM */ +- what = "pam_set_item"; +- retval = pam_set_item(pamh, PAM_RHOST, +- ipstr(&arg->st->st_remoteaddr, &ra)); +- if (retval != PAM_SUCCESS) +- break; +- +- DBG(DBG_CONTROL, DBG_log("pam_set_item SUCCESS")); +- +- /* Two factor authentication - Check that the user is valid, +- * and then check if they are permitted access +- */ +- what = "pam_authenticate"; +- retval = pam_authenticate(pamh, PAM_SILENT); /* is user really user? */ +- +- if (retval != PAM_SUCCESS) +- break; +- +- DBG(DBG_CONTROL, DBG_log("pam_authenticate SUCCESS")); +- +- what = "pam_acct_mgmt"; +- retval = pam_acct_mgmt(pamh, 0); /* permitted access? */ +- if (retval != PAM_SUCCESS) +- break; +- +- /* success! */ +- libreswan_log("XAUTH: PAM_SUCCESS"); +- pam_end(pamh, PAM_SUCCESS); +- return TRUE; +- } while (FALSE); +- +- /* common failure code */ +- +- DBG(DBG_CONTROL, +- DBG_log("%s failed with '%s", what, pam_strerror(pamh, retval))); +- libreswan_log("XAUTH: %s failed with '%s'", what, pam_strerror(pamh, retval)); +- pam_end(pamh, retval); +- return FALSE; +-} +-#endif /* XAUTH_HAVE_PAM */ +- + /** Do authentication via /etc/ipsec.d/passwd file using MD5 passwords + * + * Structure is one entry per line. +@@ -1256,6 +1181,43 @@ + return win; + } + ++/* IN AN AUTH THREAD */ ++static bool ikev1_do_pam_authentication(const struct xauth_thread_arg *arg) ++{ ++ struct state *st = arg->st; ++ libreswan_log("XAUTH: pam authentication being called to authenticate user %s", ++ arg->name); ++ struct pam_thread_arg parg; ++ ipstr_buf ra; ++ struct timeval start_time; ++ struct timeval served_time; ++ struct timeval served_delta; ++ bool results = FALSE; ++ ++ parg.name = arg->name; ++ parg.password = arg->password; ++ parg.c_name = arg->connname; ++ parg.ra = clone_str(ipstr(&st->st_remoteaddr, &ra), "st remote address"); ++ parg.st_serialno = st->st_serialno; ++ parg.c_instance_serial = st->st_connection->instance_serial; ++ parg.atype = "XAUTH"; ++ gettimeofday(&start_time, NULL); ++ results = do_pam_authentication(&parg); ++ gettimeofday(&served_time, NULL); ++ timersub(&served_time, &start_time, &served_delta); ++ DBG(DBG_CONTROL, DBG_log("XAUTH PAM helper thread call " ++ "state #%lu, %s[%lu] user=%s %s. " ++ "elapsed time %lu.%06lu", ++ parg.st_serialno, parg.c_name, ++ parg.c_instance_serial, parg.name, ++ results ? "SUCCESS" : "FAIL", ++ (unsigned long)served_delta.tv_sec, ++ (unsigned long)(served_delta.tv_usec * 1000000))); ++ ++ pfreeany(parg.ra); ++ return (results); ++} ++ + /* + * Main authentication routine will then call the actual compiled-in + * method to verify the user/password +@@ -1330,10 +1292,7 @@ + switch (st->st_connection->xauthby) { + #ifdef XAUTH_HAVE_PAM + case XAUTHBY_PAM: +- libreswan_log( +- "XAUTH: pam authentication being called to authenticate user %s", +- arg->name); +- results = do_pam_authentication(varg); ++ results = ikev1_do_pam_authentication(arg); + break; + #endif + case XAUTHBY_FILE: +diff -Naur libreswan-3.15-orig/programs/pluto/ikev2_parent.c libreswan-3.15/programs/pluto/ikev2_parent.c +--- libreswan-3.15-orig/programs/pluto/ikev2_parent.c 2015-09-03 11:29:05.518000000 -0400 ++++ libreswan-3.15/programs/pluto/ikev2_parent.c 2015-09-03 11:32:27.526000000 -0400 +@@ -2417,7 +2417,7 @@ + pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL); + pthread_setcancelstate (PTHREAD_CANCEL_ASYNCHRONOUS, NULL); + +- p->pam_status = ikev2_do_pam_authentication(&p->pam); ++ p->pam_status = do_pam_authentication(&p->pam); + gettimeofday(&p->done_time, NULL); + timersub(&p->done_time, &p->start_time, &done_delta); + +@@ -2580,6 +2580,7 @@ + p->pam.ra = clone_str(ipstr(&st->st_remoteaddr, &ra), "st remote address"); + p->pam.c_instance_serial = st->st_connection->instance_serial; + p->pam.st_serialno = st->st_serialno; ++ p->pam.atype = "IKEv2"; + + p->next = pluto_v2_pam_helpers; + pluto_v2_pam_helpers = p; +diff -Naur libreswan-3.15-orig/programs/pluto/pam_conv.c libreswan-3.15/programs/pluto/pam_conv.c +--- libreswan-3.15-orig/programs/pluto/pam_conv.c 2015-08-24 16:52:43.000000000 -0400 ++++ libreswan-3.15/programs/pluto/pam_conv.c 2015-09-03 11:32:27.526000000 -0400 +@@ -10,7 +10,7 @@ + * Copyright (C) 2012-2013 Paul Wouters + * Copyright (C) 2012-2013 Philippe Vouters + * Copyright (C) 2013 David McCullough +- * Copyright (C) 2013 Antony Antony ++ * Copyright (C) 2013-2015 Antony Antony + * + * 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 +@@ -109,15 +109,25 @@ + return PAM_SUCCESS; + } + ++static void log_pam_step(const struct pam_thread_arg *arg, const char *what, ++ const char *how) ++{ ++ DBG(DBG_CONTROL, DBG_log("%s helper thread %s %s for " ++ "state #%lu, %s[%lu] user=%s.", ++ arg->atype, what, how, ++ arg->st_serialno, arg->c_name, ++ arg->c_instance_serial, arg->name)); ++ ++} ++ + /* + * Do IKEv2 second authentication via PAM (Plugable Authentication Modules) + * + * @return bool success + */ + /* IN AN AUTH THREAD */ +-bool ikev2_do_pam_authentication(void *varg) ++bool do_pam_authentication(struct pam_thread_arg *arg) + { +- struct pam_thread_arg *arg = varg; + int retval; + pam_handle_t *pamh = NULL; + struct pam_conv conv; +@@ -129,22 +139,20 @@ + */ + do { + conv.conv = pam_conv; +- conv.appdata_ptr = varg; ++ conv.appdata_ptr = arg; + + what = "pam_start"; + retval = pam_start("pluto", arg->name, &conv, &pamh); + if (retval != PAM_SUCCESS) + break; +- +- DBG(DBG_CONTROL, DBG_log("pam_start SUCCESS")); ++ log_pam_step(arg, what, "SUCCESS"); + + /* Send the remote host address to PAM */ + what = "pam_set_item"; + retval = pam_set_item(pamh, PAM_RHOST, arg->ra); + if (retval != PAM_SUCCESS) + break; +- +- DBG(DBG_CONTROL, DBG_log("pam_set_item SUCCESS")); ++ log_pam_step(arg, what, "SUCCESS"); + + /* Two factor authentication - Check that the user is valid, + * and then check if they are permitted access +@@ -154,16 +162,16 @@ + + if (retval != PAM_SUCCESS) + break; ++ log_pam_step(arg, what, "SUCCESS"); + +- DBG(DBG_CONTROL, DBG_log("pam_authenticate SUCCESS")); +- +- what = "pam_acct_mgmt"; + retval = pam_acct_mgmt(pamh, 0); /* permitted access? */ + if (retval != PAM_SUCCESS) + break; + ++ what = "pam"; ++ log_pam_step(arg, what, "SUCCESS"); ++ + /* success! */ +- libreswan_log("IKEv2: PAM_SUCCESS"); + pam_end(pamh, PAM_SUCCESS); + return TRUE; + } while (FALSE); +diff -Naur libreswan-3.15-orig/programs/pluto/pam_conv.h libreswan-3.15/programs/pluto/pam_conv.h +--- libreswan-3.15-orig/programs/pluto/pam_conv.h 2015-08-24 16:52:43.000000000 -0400 ++++ libreswan-3.15/programs/pluto/pam_conv.h 2015-09-03 11:32:27.527000000 -0400 +@@ -23,9 +23,10 @@ + char *ra; + so_serial_t st_serialno; + unsigned long c_instance_serial; ++ char *atype; /* string XAUTH or IKEv2 */ + }; + +-extern bool ikev2_do_pam_authentication(void *varg); ++extern bool do_pam_authentication(struct pam_thread_arg *arg); + int pam_conv(int num_msg, const struct pam_message **msgm, + struct pam_response **response, void + *appdata_ptr); diff --git a/SOURCES/libreswan-3.15-migration.patch b/SOURCES/libreswan-3.15-migration.patch new file mode 100644 index 0000000..0b3c664 --- /dev/null +++ b/SOURCES/libreswan-3.15-migration.patch @@ -0,0 +1,20 @@ +diff -Naur libreswan-3.15-orig/lib/libipsecconf/keywords.c libreswan-3.15/lib/libipsecconf/keywords.c +--- libreswan-3.15-orig/lib/libipsecconf/keywords.c 2015-08-24 16:52:43.000000000 -0400 ++++ libreswan-3.15/lib/libipsecconf/keywords.c 2015-09-24 12:52:54.377592510 -0400 +@@ -342,6 +342,8 @@ + { "interfaces", kv_config, kt_string, KSF_INTERFACES, NOT_ENUM }, + { "curl-iface", kv_config, kt_string, KSF_CURLIFACE, NOT_ENUM }, + { "curl-timeout", kv_config, kt_number, KBF_CURLTIMEOUT, NOT_ENUM }, ++ { "curl_iface", kv_config | kv_alias, kt_string, KSF_CURLIFACE, NOT_ENUM }, ++ { "curl_timeout", kv_config | kv_alias, kt_number, KBF_CURLTIMEOUT, NOT_ENUM }, + { "myid", kv_config, kt_string, KSF_MYID, NOT_ENUM }, + { "myvendorid", kv_config, kt_string, KSF_MYVENDORID, NOT_ENUM }, + { "syslog", kv_config, kt_string, KSF_SYSLOG, NOT_ENUM }, +@@ -383,6 +385,7 @@ + { "ocsp-trustname", kv_config, kt_string, KSF_OCSPTRUSTNAME, NOT_ENUM }, + { "crlcheckinterval", kv_config, kt_time, KBF_CRLCHECKINTERVAL, NOT_ENUM }, + { "crl_strict", kv_config | kv_alias, kt_bool, KBF_STRICTCRLPOLICY, NOT_ENUM }, /* obsolete _ */ ++ { "strictcrlpolicy", kv_config | kv_alias, kt_bool, KBF_STRICTCRLPOLICY, NOT_ENUM }, /* obsolete used on openswan */ + { "ocsp_strict", kv_config | kv_alias, kt_bool, KBF_STRICTOCSPPOLICY, NOT_ENUM }, /* obsolete _ */ + { "ocsp_enable", kv_config | kv_alias, kt_bool, KBF_OCSPENABLE, NOT_ENUM }, /* obsolete _ */ + { "ocsp_uri", kv_config | kv_alias, kt_string, KSF_OCSPURI, NOT_ENUM }, /* obsolete _ */ diff --git a/SOURCES/libreswan-3.15-newest-labeled.patch b/SOURCES/libreswan-3.15-newest-labeled.patch new file mode 100644 index 0000000..f2c1e42 --- /dev/null +++ b/SOURCES/libreswan-3.15-newest-labeled.patch @@ -0,0 +1,13 @@ +diff -Naur libreswan-3.15-orig/programs/pluto/ikev1_main.c libreswan-3.15/programs/pluto/ikev1_main.c +--- libreswan-3.15-orig/programs/pluto/ikev1_main.c 2015-08-24 16:52:43.000000000 -0400 ++++ libreswan-3.15/programs/pluto/ikev1_main.c 2015-09-03 11:57:52.632000000 -0400 +@@ -3011,6 +3011,9 @@ + dst); + + if (rc->newest_ipsec_sa == dst->st_serialno && ++#ifdef HAVE_LABELED_IPSEC ++ dst->sec_ctx == NULL && ++#endif + (rc->policy & POLICY_UP)) { + /* + * Last IPsec SA for a permanent diff --git a/SOURCES/libreswan-3.15-racoon-padding.patch b/SOURCES/libreswan-3.15-racoon-padding.patch new file mode 100644 index 0000000..114fa0d --- /dev/null +++ b/SOURCES/libreswan-3.15-racoon-padding.patch @@ -0,0 +1,86 @@ +diff --git a/programs/pluto/ikev2_parent.c b/programs/pluto/ikev2_parent.c +index 28e93b0..cc033aa 100644 +--- a/programs/pluto/ikev2_parent.c ++++ b/programs/pluto/ikev2_parent.c +@@ -1601,16 +1601,21 @@ static stf_status ikev2_verify_and_decrypt_sk_payload(struct msg_digest *md, + size_t enc_size = integ_start - enc_start; + + /* +- * Check if block-size is valid. Do this before the payload's +- * integrity has been verified as block-alignment requirements +- * aren't exactly secret (originally this was being done +- * beteen integrity and decrypt). ++ * Check that the payload is block-size aligned. ++ * ++ * Per rfc7296 "the recipient MUST accept any length that ++ * results in proper alignment". ++ * ++ * Do this before the payload's integrity has been verified as ++ * block-alignment requirements aren't exactly secret ++ * (originally this was being done between integrity and ++ * decrypt). + */ + size_t enc_blocksize = pst->st_oakley.encrypter->enc_blocksize; + bool pad_to_blocksize = pst->st_oakley.encrypter->pad_to_blocksize; + if (pad_to_blocksize) { + if (enc_size % enc_blocksize != 0) { +- libreswan_log("cyphertext length (%zu) not a multiple of blocksize (%zu)", ++ libreswan_log("discarding invalid packet: %zu octet payload length is not a multiple of encryption block-size (%zu)", + enc_size, enc_blocksize); + return STF_FAIL; + } +@@ -1707,17 +1712,47 @@ static stf_status ikev2_verify_and_decrypt_sk_payload(struct msg_digest *md, + enc_start, enc_size + integ_size)); + } + +- +- u_char padlen = enc_start[enc_size - 1] + 1; +- if (padlen > enc_blocksize || padlen > enc_size) { +- libreswan_log("invalid padding-length octet: 0x%2x", padlen - 1); ++ /* ++ * Check the padding. ++ * ++ * Per rfc7296 "The sender SHOULD set the Pad Length to the ++ * minimum value that makes the combination of the payloads, ++ * the Padding, and the Pad Length a multiple of the block ++ * size, but the recipient MUST accept any length that results ++ * in proper alignment." ++ * ++ * Notice the "should". RACOON, for instance, sends extra ++ * blocks of padding that contain random bytes. ++ */ ++ u_int8_t padlen = enc_start[enc_size - 1] + 1; ++ if (padlen > enc_size) { ++ libreswan_log("discarding invalid packet: padding-length %u (octet 0x%02x) is larger than %zu octet payload length", ++ padlen, padlen - 1, enc_size); + return STF_FAIL; + } ++ if (pad_to_blocksize) { ++ if (padlen > enc_blocksize) { ++ /* probably racoon */ ++ DBG(DBG_CRYPT, ++ DBG_log("payload contains %zu blocks of extra padding (padding-length: %d (octet 0x%2x), encryption block-size: %zu)", ++ (padlen - 1) / enc_blocksize, ++ padlen, padlen - 1, enc_blocksize)); ++ } ++ } else { ++ if (padlen > 1) { ++ DBG(DBG_CRYPT, ++ DBG_log("payload contains %u octets of extra padding (padding-length: %u (octet 0x%2x))", ++ padlen - 1, padlen, padlen - 1)); ++ } ++ } + +- /* don't bother to check any other pad octets */ +- DBG(DBG_CRYPT, DBG_log("striping %u bytes as pad", padlen)); +- ++ /* ++ * Don't check the contents of the pad octets; racoon, for ++ * instance, sets them to random values. ++ */ ++ DBG(DBG_CRYPT, DBG_log("stripping %u octets as pad", padlen)); + setchunk(*chunk, enc_start, enc_size - padlen); ++ + return STF_OK; + } + diff --git a/SOURCES/libreswan-3.15-s90-gcc.patch b/SOURCES/libreswan-3.15-s90-gcc.patch new file mode 100644 index 0000000..309e3da --- /dev/null +++ b/SOURCES/libreswan-3.15-s90-gcc.patch @@ -0,0 +1,28 @@ +diff --git a/programs/pluto/ikev2_parent.c b/programs/pluto/ikev2_parent.c +index 8fd0bba..db890f5 100644 +--- a/programs/pluto/ikev2_parent.c ++++ b/programs/pluto/ikev2_parent.c +@@ -1596,8 +1596,8 @@ static stf_status ikev2_verify_and_decrypt_sk_payload(struct msg_digest *md, + */ + u_char *payload_end = chunk->ptr + chunk->len; + if (payload_end < (wire_iv_start + wire_iv_size + 1 + integ_size)) { +- libreswan_log("encrypted payload impossibly short (%zu)", +- payload_end - wire_iv_start); ++ libreswan_log("encrypted payload impossibly short (%tu)", ++ payload_end - wire_iv_start); + return STF_FAIL; + } + +@@ -4105,9 +4105,9 @@ stf_status process_encrypted_informational_ikev2(struct msg_digest *md) + } + + if (v2del->isad_nrspi * v2del->isad_spisize != pbs_left(&p->pbs)) { +- libreswan_log("IPsec Delete Notification payload size is %tu but %u is required", +- pbs_left(&p->pbs), +- v2del->isad_nrspi * v2del->isad_spisize); ++ libreswan_log("IPsec Delete Notification payload size is %lu but %lu is required", ++ (long unsigned int) pbs_left(&p->pbs), ++ (long unsigned int) (v2del->isad_nrspi * v2del->isad_spisize)); + return STF_FAIL + v2N_INVALID_SYNTAX; + } + diff --git a/SOURCES/libreswan-3.15-seeddev.patch b/SOURCES/libreswan-3.15-seeddev.patch new file mode 100644 index 0000000..1492a56 --- /dev/null +++ b/SOURCES/libreswan-3.15-seeddev.patch @@ -0,0 +1,13 @@ +diff --git a/programs/newhostkey/newhostkey.in b/programs/newhostkey/newhostkey.in +index a25583e..31226c2 100755 +--- a/programs/newhostkey/newhostkey.in ++++ b/programs/newhostkey/newhostkey.in +@@ -24,7 +24,7 @@ usage="Usage: $me [--output filename] [--seeddev device] [--bits n] \\ + bits= + verbose= + host= +-seeddev="--seeddev /dev/seeddev" ++seeddev="--seeddev /dev/random" + output="@FINALCONFDIR@/ipsec.secrets" + configdir="@FINALNSSDIR@" + password= diff --git a/SOURCES/libreswan-3.15-trafficstatus.patch b/SOURCES/libreswan-3.15-trafficstatus.patch new file mode 100644 index 0000000..90712de --- /dev/null +++ b/SOURCES/libreswan-3.15-trafficstatus.patch @@ -0,0 +1,96 @@ +diff -Naur libreswan-3.15-orig/programs/pluto/state.c libreswan-3.15/programs/pluto/state.c +--- libreswan-3.15-orig/programs/pluto/state.c 2015-08-24 16:52:43.000000000 -0400 ++++ libreswan-3.15/programs/pluto/state.c 2015-09-04 09:31:28.815818376 -0400 +@@ -1652,21 +1652,20 @@ + char *mbcp = traffic_buf + snprintf(traffic_buf, + sizeof(traffic_buf) - 1, ", type=%s, add_time=%" PRIu64, mode, st->st_esp.add_time); + +- if (get_sa_info(st, TRUE, NULL)) { ++ if (get_sa_info(st, FALSE, NULL)) { + size_t buf_len = traffic_buf + sizeof(traffic_buf) - mbcp; +- u_int inb = st->st_esp.present ? st->st_esp.peer_bytes : ++ u_int outb = st->st_esp.present ? st->st_esp.peer_bytes : + st->st_ah.present ? st->st_ah.peer_bytes : + st->st_ipcomp.present ? st->st_ipcomp.peer_bytes : 0; +- +- mbcp += snprintf(mbcp, buf_len - 1, ", inBytes=%u", inb); ++ mbcp += snprintf(mbcp, buf_len - 1, ", outBytes=%u", outb); + } +- if (get_sa_info(st, FALSE, NULL)) { ++ ++ if (get_sa_info(st, TRUE, NULL)) { + size_t buf_len = traffic_buf + sizeof(traffic_buf) - mbcp; +- u_int outb = st->st_esp.present ? st->st_esp.our_bytes : ++ u_int inb = st->st_esp.present ? st->st_esp.our_bytes: + st->st_ah.present ? st->st_ah.our_bytes : + st->st_ipcomp.present ? st->st_ipcomp.our_bytes : 0; +- +- snprintf(mbcp, buf_len - 1, ", outBytes=%u", outb); ++ snprintf(mbcp, buf_len - 1, ", inBytes=%u", inb); + } + } + +@@ -1815,7 +1814,7 @@ + mbcp, + traffic_buf + + sizeof(traffic_buf), +- " AHin="); ++ " AHout="); + } + #endif + add_said(&c->spd.this.host_addr, st->st_ah.our_spi, +@@ -1826,7 +1825,7 @@ + mbcp, + traffic_buf + + sizeof(traffic_buf), +- " AHout="); ++ " AHin="); + } + #endif + mbcp = humanize_number( +@@ -1842,23 +1841,23 @@ + SA_ESP); + /* ??? needs proper fix, via kernel_ops? */ + #if defined(linux) && defined(NETKEY_SUPPORT) +- if (get_sa_info(st, FALSE, NULL)) { ++ if (get_sa_info(st, TRUE, NULL)) { + mbcp = humanize_number(st->st_esp.peer_bytes, + mbcp, + traffic_buf + + sizeof(traffic_buf), +- " ESPin="); ++ " ESPout="); + } + #endif + add_said(&c->spd.this.host_addr, st->st_esp.our_spi, + SA_ESP); + #if defined(linux) && defined(NETKEY_SUPPORT) +- if (get_sa_info(st, TRUE, NULL)) { ++ if (get_sa_info(st, FALSE, NULL)) { + mbcp = humanize_number(st->st_esp.our_bytes, + mbcp, + traffic_buf + + sizeof(traffic_buf), +- " ESPout="); ++ " ESPin="); + } + #endif + +@@ -1879,7 +1878,7 @@ + mbcp, + traffic_buf + + sizeof(traffic_buf), +- " IPCOMPin="); ++ " IPCOMPout="); + } + #endif + add_said(&c->spd.this.host_addr, st->st_ipcomp.our_spi, +@@ -1891,7 +1890,7 @@ + mbcp, + traffic_buf + + sizeof(traffic_buf), +- " IPCOMPout="); ++ " IPCOMPin="); + } + #endif + diff --git a/SOURCES/v6neighbor-hole.conf b/SOURCES/v6neighbor-hole.conf deleted file mode 100644 index 8ac7616..0000000 --- a/SOURCES/v6neighbor-hole.conf +++ /dev/null @@ -1,58 +0,0 @@ -# Passthrough For proper IPv6 Neighbor Discovery (RFC 4861) -# -# The unicast Neighbor Advertisement reply message must be sent -# in plaintext) even if we have an IPsec SA for the destination, -# because the other end might have crashed or rebooted and lost -# its IPsec SA with our end. It will use IPv6 Neighbor Discovery -# to find our end again. Without this policy hole, the neighbor -# discovery answer packet is caught by the kernel and encrypted. -# As a result, the rebooted end won't be able to find us and won't -# be able to send us an IKE packet to re-establish the IPsec SA. -# -# While the Neighbor Solicitation is multicast and would not -# not be caught by the IPsec stack, we use it in the configuration -# to limit the range of ipv6-icmp covered. In a way, this would -# only need to be an outbound SA, but SA's come in bundles, so we -# need an unbound SA as well. Leaving protoport empty or set to -# any ipv6-icmp would cause us to send out more unencrypted traffic, -# which would be dropped once the IPsec SA has re-established. -# So we set the inbound protoport to ipv6-icmp Neighbor Advertisement. -# (solution by Jaroslav Aster) -# -# Configuration -# -# ipv6-icmp Neighbor Solicitation is Type 135, Code 0. -# ipv6-icmp Neighbor Advertisement is Type 136, Code 0. -# As per RFC 4301/5996, icmp type is put in the most significant 8 bits -# and the icmp code is in the least significant 8 bits of port field. -# proto is 58 (ipv6-icmp) -# type = 135 (0x87) or 136 (0x88) -# code = 0 (0x00) -# so "port" in protoport is 0x8700 (34560) for Neighbor Solicitation. -# so "port" in protoport is 0x8800 (34816) for Neighbor Advertisement. - -conn v6neighbor-hole-in - left=::1 - leftsubnet=::0/0 - leftprotoport=58/34560 - rightprotoport=58/34816 - rightsubnet=::0/0 - right=::0 - connaddrfamily=ipv6 - authby=never - type=passthrough - auto=route - priority=10 - -conn v6neighbor-hole-out - left=::1 - leftsubnet=::0/0 - leftprotoport=58/34816 - rightprotoport=58/34560 - rightsubnet=::0/0 - right=::0 - connaddrfamily=ipv6 - authby=never - type=passthrough - auto=route - priority=10 diff --git a/SPECS/libreswan.spec b/SPECS/libreswan.spec index ef05c54..bca4df7 100644 --- a/SPECS/libreswan.spec +++ b/SPECS/libreswan.spec @@ -7,67 +7,77 @@ %global USE_LINUX_AUDIT true %global _hardened_build 1 - %global buildefence 0 %global development 0 +%global cavstests 1 + +%if 0%{?fedora} +%global rhel 7 +%endif #global prever rc1 Name: libreswan Summary: IPsec implementation with IKEv1 and IKEv2 keying protocols -Version: 3.12 -Release: %{?prever:0.}10.1%{?prever:.%{prever}}%{?dist} +Version: 3.15 +Release: %{?prever:0.}5%{?prever:.%{prever}}%{?dist} License: GPLv2 -Url: https://www.libreswan.org/ -Source: https://download.libreswan.org/%{name}-%{version}%{?prever}.tar.gz -Source1: v6neighbor-hole.conf -Source2: ikev1_dsa.fax.bz2 -Source3: ikev1_psk.fax.bz2 -Source4: ikev2.fax.bz2 Group: System Environment/Daemons +Url: https://libreswan.org/ +Source: https://download.libreswan.org/%{?prever:development/}%{name}-%{version}%{?prever}.tar.gz +Source1: ikev1_dsa.fax.bz2 +Source2: ikev1_psk.fax.bz2 +Source3: ikev2.fax.bz2 + +Patch1: libreswan-3.15-racoon-padding.patch +Patch2: libreswan-3.15-seeddev.patch +Patch3: libreswan-3.15-ikev1-pam.patch +Patch4: libreswan-3.15-gcc-osw-interop-conf.patch +Patch5: libreswan-3.15-newest-labeled.patch +Patch6: libreswan-3.15-s90-gcc.patch +Patch7: libreswan-3.15-NLMSG_OK.patch +Patch8: libreswan-3.15-trafficstatus.patch +Patch9: libreswan-3.15-cisco-delete.patch +Patch10: libreswan-3.15-migration.patch +Patch11: libreswan-3.15-1166146.patch +Patch12: libreswan-3.15-609343.patch +# rhbz#1273719 +Patch13: libreswan-3.15-1271811-fipsfiles.patch + +Requires: iproute >= 2.6.8 nss-tools nss-softokn + BuildRequires: gmp-devel bison flex redhat-rpm-config pkgconfig +BuildRequires: nss-devel >= 3.16.1 nspr-devel +BuildRequires: pam-devel +BuildRequires: xmlto + +%if %{?rhel} <= 6 +BuildRequires: libevent2-devel net-tools + +Requires(post): coreutils bash +Requires(preun): initscripts chkconfig +Requires(post): /sbin/chkconfig +Requires(preun): /sbin/chkconfig +Requires(preun): /sbin/service +%else +BuildRequires: libevent-devel hostname + BuildRequires: systemd Requires(post): coreutils bash systemd Requires(preun): systemd Requires(postun): systemd -Requires: iproute - -Patch1: libreswan-3.12-1052811.patch -Patch2: libreswan-3.12-1105171-manpage.patch -Patch3: libreswan-3.12-1144120-camellia-ikev2.patch -Patch4: libreswan-3.12-1074018-audit.patch -Patch5: libreswan-3.12-1131503-invalid-ke.patch -Patch6: libreswan-3.12-1134297-aes_ctr.patch -Patch7: libreswan-3.12-1162770-gcm-man.patch -Patch8: libreswan-3.12-826264-ike-aes-gcm.patch -#rhbz 1198650 -Patch9: libreswan-3.12-1170018-netlink-label.patch -#rhbz 1198649 -Patch10: libreswan-3.12-1182224-bsi-random.patch -#rhbz 1211146 -Patch11: libreswan-3.12-1203794-fipstest.patch -# rhbz 1213652 -Patch12: libreswan-3.12-1212121-cavs.patch -# rhbz 1208022 -Patch13: libreswan-3.12-1207689-blacklist.patch -Patch14: libreswan-3.12-CVE-2015-3204.patch - -Conflicts: openswan < %{version}-%{release} -Obsoletes: openswan < %{version}-%{release} -Provides: openswan = %{version}-%{release} -Provides: openswan-doc = %{version}-%{release} +%endif -BuildRequires: pkgconfig hostname -BuildRequires: nss-devel >= 3.12.6-2, nspr-devel -BuildRequires: pam-devel %if %{USE_DNSSEC} BuildRequires: unbound-devel %endif + %if %{USE_FIPSCHECK} BuildRequires: fipscheck-devel # we need fipshmac Requires: fipscheck%{_isa} %endif + %if %{USE_LINUX_AUDIT} Buildrequires: audit-libs-devel %endif @@ -75,16 +85,23 @@ Buildrequires: audit-libs-devel %if %{USE_LIBCAP_NG} BuildRequires: libcap-ng-devel %endif + %if %{USE_CRL_FETCHING} BuildRequires: openldap-devel curl-devel %endif + %if %{buildefence} BuildRequires: ElectricFence %endif -# Needed if xml man pages are modified and need regeneration -BuildRequires: xmlto -Requires: nss-tools, nss-softokn +Conflicts: openswan < %{version}-%{release} +Provides: openswan = %{version}-%{release} +Provides: openswan-doc = %{version}-%{release} + +%if %{?rhel} == 7 +# Will be obsoleted in RHEL6 when moved from optional to core +Obsoletes: openswan < %{version}-%{release} +%endif %description Libreswan is a free implementation of IPsec & IKE for Linux. IPsec is @@ -96,9 +113,10 @@ decrypted by the gateway at the other end of the tunnel. The resulting tunnel is a virtual private network or VPN. This package contains the daemons and userland tools for setting up -Libreswan. To build KLIPS, see the kmod-libreswan.spec file. +Libreswan. It supports the NETKEY/XFRM IPsec kernel stack that exists +in the default Linux kernel. -Libreswan also supports IKEv2 (RFC4309) and Secure Labeling +Libreswan also supports IKEv2 (RFC-7296) and Secure Labeling Libreswan is based on Openswan-2.6.38 which in turn is based on FreeS/WAN-2.04 @@ -117,25 +135,24 @@ Libreswan is based on Openswan-2.6.38 which in turn is based on FreeS/WAN-2.04 %patch11 -p1 %patch12 -p1 %patch13 -p1 -%patch14 -p1 - -# remove man page for ipsec.conf so it is forced to regenerate -rm ./programs/configs/ipsec.conf.5 %build %if %{buildefence} %define efence "-lefence" %endif -#796683: -fno-strict-aliasing -%{__make} \ +make %{?_smp_mflags} \ %if %{development} - USERCOMPILE="-g -DGCC_LINT %(echo %{optflags} | sed -e s/-O[0-9]*/ /) %{?efence} -fPIE -pie -fno-strict-aliasing -Wformat-nonliteral -Wformat-security" \ + USERCOMPILE="-g -DGCC_LINT %(echo %{optflags} | sed -e s/-O[0-9]*/ /) %{?efence} -fPIE -pie " \ %else - USERCOMPILE="-g -DGCC_LINT %{optflags} %{?efence} -fPIE -pie -fno-strict-aliasing -Wformat-nonliteral -Wformat-security" \ + USERCOMPILE="-g -DGCC_LINT %{optflags} %{?efence} -fPIE -pie " \ %endif USERLINK="-g -pie -Wl,-z,relro,-z,now %{?efence}" \ +%if %{?rhel} <= 6 + INITSYSTEM=sysvinit \ +%else INITSYSTEM=systemd \ +%endif USE_NM=%{USE_NM} \ USE_XAUTHPAM=true \ %if %{USE_FIPSCHECK} @@ -155,23 +172,36 @@ rm ./programs/configs/ipsec.conf.5 FINALLIBEXECDIR=%{_libexecdir}/ipsec \ MANTREE=%{_mandir} \ INC_RCDEFAULT=%{_initrddir} \ + MODPROBE="modprobe -q -b" \ programs FS=$(pwd) %if %{USE_FIPSCHECK} # Add generation of HMAC checksums of the final stripped binaries +%if %{?rhel} <= 6 +%define __spec_install_post \ + %{?__debug_package:%{__debug_install_post}} \ + %{__arch_install_post} \ + %{__os_install_post} \ + fipshmac %{buildroot}%{_libexecdir}/ipsec/* \ + fipshmac %{buildroot}%{_sbindir}/ipsec \ +%{nil} + +%else %define __spec_install_post \ %{?__debug_package:%{__debug_install_post}} \ %{__arch_install_post} \ %{__os_install_post} \ - fipshmac -d %{buildroot}%{_libdir}/fipscheck %{buildroot}%{_libexecdir}/ipsec/* \ - fipshmac -d %{buildroot}%{_libdir}/fipscheck %{buildroot}%{_sbindir}/ipsec \ + mkdir -p %{buildroot}%{_libdir}/fipscheck/ \ + fipshmac -d %{buildroot}%{_libdir}/fipscheck %{buildroot}%{_libexecdir}/ipsec/* \ + fipshmac -d %{buildroot}%{_libdir}/fipscheck %{buildroot}%{_sbindir}/ipsec \ %{nil} %endif +%endif %install rm -rf ${RPM_BUILD_ROOT} -%{__make} \ +make \ DESTDIR=%{buildroot} \ INC_USRLOCAL=%{_prefix} \ FINALLIBDIR=%{_libexecdir}/ipsec \ @@ -179,85 +209,147 @@ rm -rf ${RPM_BUILD_ROOT} MANTREE=%{buildroot}%{_mandir} \ INC_RCDEFAULT=%{_initrddir} \ INSTMANFLAGS="-m 644" \ +%if %{?rhel} <= 6 + INITSYSTEM=sysvinit \ +%else INITSYSTEM=systemd \ +%endif install FS=$(pwd) rm -rf %{buildroot}/usr/share/doc/libreswan +# needed to activate v6neighbor-hole.conf +sed -i "s:^#include /etc/ipsec.d/\*.conf$:include /etc/ipsec.d/*.conf:" %{buildroot}%{_sysconfdir}/ipsec.conf install -d -m 0755 %{buildroot}%{_localstatedir}/run/pluto # used when setting --perpeerlog without --perpeerlogbase install -d -m 0700 %{buildroot}%{_localstatedir}/log/pluto/peer install -d %{buildroot}%{_sbindir} +%if %{?rhel} <= 6 +# replace with rhel6 specific version +install -m 0755 initsystems/sysvinit/init.rhel %{buildroot}%{_initrddir}/ipsec +rm -fr %{buildroot}/etc/rc.d/rc* +%endif %if %{USE_FIPSCHECK} +%if %{?rhel} == 7 mkdir -p %{buildroot}%{_libdir}/fipscheck +%endif install -d %{buildroot}%{_sysconfdir}/prelink.conf.d/ install -m644 packaging/fedora/libreswan-prelink.conf %{buildroot}%{_sysconfdir}/prelink.conf.d/libreswan-fips.conf %endif echo "include /etc/ipsec.d/*.secrets" > %{buildroot}%{_sysconfdir}/ipsec.secrets -rm -fr %{buildroot}/etc/rc.d/rc* -install -m644 %{SOURCE1} %{buildroot}%{_sysconfdir}/ipsec.d/v6neighbor-hole.conf -sed -i "s/#include \/etc\/ipsec.d\/\*.conf/include \/etc\/ipsec.d\/\*.conf/" %{buildroot}%{_sysconfdir}/ipsec.conf # cavs testing -cp -a OBJ.*/programs/pluto/cavp %{buildroot}%{_libexecdir}/ipsec +cp -a OBJ.linux.*/programs/pluto/cavp %{buildroot}%{_libexecdir}/ipsec +%if %{cavstests} %check # There is an elaborate upstream testing infrastructure which we do not run here # We only run the CAVS tests here -cp %{SOURCE2} %{SOURCE3} %{SOURCE4} . +cp %{SOURCE1} %{SOURCE2} %{SOURCE3} . bunzip2 *.fax.bz2 -echo "starting CAVS test for IKEv2" + +# work around for rhel6 builders on xen +export NSS_DISABLE_HW_GCM=1 + +: "starting CAVS test for IKEv2" OBJ.linux.*/programs/pluto/cavp -v2 ikev2.fax | diff -u ikev2.fax - > /dev/null -echo "starting CAVS test for IKEv1 RSASIG" +: "starting CAVS test for IKEv1 RSASIG" OBJ.linux.*/programs/pluto/cavp -v1sig ikev1_dsa.fax | diff -u ikev1_dsa.fax - > /dev/null -echo "starting CAVS test for IKEv1 PSK" +: "starting CAVS test for IKEv1 PSK" OBJ.linux.*/programs/pluto/cavp -v1psk ikev1_psk.fax | diff -u ikev1_psk.fax - > /dev/null -echo "CAVS tests passed" +: "CAVS tests passed" +%endif + +%if %{?rhel} <= 6 +%post +/sbin/chkconfig --add ipsec || : +%if %{USE_FIPSCHECK} +prelink -u %{_libexecdir}/ipsec/* 2>/dev/null || : +%endif + +%preun +if [ $1 -eq 0 ]; then + /sbin/service ipsec stop > /dev/null 2>&1 || : + /sbin/chkconfig --del ipsec +fi + +%postun +if [ $1 -ge 1 ] ; then + /sbin/service ipsec condrestart 2>&1 >/dev/null || : +fi +%else +%preun +%systemd_preun ipsec.service + +%postun +%systemd_postun_with_restart ipsec.service + +%post +%systemd_post ipsec.service +%endif %files %doc CHANGES COPYING CREDITS README* LICENSE -%doc docs/*.* docs/examples +%doc docs/*.* docs/examples packaging/rhel/libreswan-sysctl.conf %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/ipsec.conf -%attr(0644,root,root) %config(noreplace) %{_sysconfdir}/sysconfig/pluto %attr(0600,root,root) %config(noreplace) %{_sysconfdir}/ipsec.secrets +%attr(0644,root,root) %config(noreplace) %{_sysconfdir}/sysconfig/pluto %attr(0700,root,root) %dir %{_sysconfdir}/ipsec.d %attr(0644,root,root) %{_sysconfdir}/ipsec.d/v6neighbor-hole.conf -%attr(0700,root,root) %dir %{_sysconfdir}/ipsec.d/cacerts -%attr(0700,root,root) %dir %{_sysconfdir}/ipsec.d/crls %attr(0700,root,root) %dir %{_sysconfdir}/ipsec.d/policies %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/ipsec.d/policies/* %attr(0700,root,root) %dir %{_localstatedir}/log/pluto/peer %attr(0755,root,root) %dir %{_localstatedir}/run/pluto -%attr(0644,root,root) %{_unitdir}/ipsec.service %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/pam.d/pluto %{_sbindir}/ipsec -%{_libexecdir}/ipsec -%doc %{_mandir}/*/* +%attr(0755,root,root) %dir %{_libexecdir}/ipsec +%{_libexecdir}/ipsec/* +%attr(0644,root,root) %{_mandir}/*/*.gz +%if %{?rhel} <= 6 +%{_initrddir}/ipsec +%else +%attr(0644,root,root) %{_unitdir}/ipsec.service +%endif %if %{USE_FIPSCHECK} +%if %{?rhel} <= 6 +%{_sbindir}/.ipsec.hmac +%{_libexecdir}/ipsec/.*.hmac +%else %{_libdir}/fipscheck/*.hmac +%endif + # We own the directory so we don't have to require prelink %attr(0755,root,root) %dir %{_sysconfdir}/prelink.conf.d/ %{_sysconfdir}/prelink.conf.d/libreswan-fips.conf %endif -%preun -%systemd_preun ipsec.service - -%postun -%systemd_postun_with_restart ipsec.service +%changelog +* Wed Oct 21 2015 Paul Wouters - 3.15-5 +- Resolves: rhbz#1273719 libreswan FIPS test mistakenly looks for non-existent file hashes -%post -%systemd_post ipsec.service -if [ ! -f %{_sysconfdir}/ipsec.d/cert8.db ] ; then - certutil -N -d %{_sysconfdir}/ipsec.d --empty-password || : - restorecon %{_sysconfdir}/ipsec.d/*db 2>/dev/null || : -fi +* Wed Oct 07 2015 Paul Wouters - 3.15-4 +- Resolves: rhbz#1268775 libreswan should support strictcrlpolicy alias +- Resolves: rhbz#1268776 Pluto crashes after stop when I use floating ip address +- Resolves: rhbz#1268773 Pluto crashes on INITIATOR site during 'service ipsec stop' +- Resolves: rhbz#1208022 libreswan ignores module blacklist rules +- Resolves: rhbz#1270673 ipsec does not work properly on loopback + +* Tue Sep 15 2015 Paul Wouters - 3.15-2 +- Resolves: rhbz#1259208 CVE-2015-3240 +- Merge rhel6 and rhel7 spec into one +- Be lenient for racoon padding behaviour +- Fix seedev option to /dev/random +- Some IKEv1 PAM methods always gave 'Permission denied' +- Parser workarounds for differences in gcc/flex/bison on rhel6/rhel7 +- Parser fix to allow specifying time without unit (openswan compat) +- Fix Labeled IPsec on rekeyed IPsec SA's +- Workaround for wrong padding by racoon2 +- Disable NSS HW GCM to workaround rhel6 xen builers bug -%changelog * Fri May 29 2015 Paul Wouters - 3.12-10.1 - Resolves: rhbz#1226407 CVE-2015-3204 libreswan: crafted IKE packet causes daemon restart