diff --git a/.gitignore b/.gitignore index 2444f03..d372f53 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/libreswan-3.8.tar.gz +SOURCES/libreswan-3.12.tar.gz diff --git a/.libreswan.metadata b/.libreswan.metadata index abb0225..effea6f 100644 --- a/.libreswan.metadata +++ b/.libreswan.metadata @@ -1 +1 @@ -42dc3c1f58cc11a5d5405c83a9c47e14a60e0416 SOURCES/libreswan-3.8.tar.gz +bca50e25b044df1b9fc4b732be38b28c25216674 SOURCES/libreswan-3.12.tar.gz diff --git a/SOURCES/libreswan-3.12-1052811.patch b/SOURCES/libreswan-3.12-1052811.patch new file mode 100644 index 0000000..8634e1f --- /dev/null +++ b/SOURCES/libreswan-3.12-1052811.patch @@ -0,0 +1,35 @@ +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 new file mode 100644 index 0000000..9f4ed33 --- /dev/null +++ b/SOURCES/libreswan-3.12-1074018-audit.patch @@ -0,0 +1,527 @@ +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 new file mode 100644 index 0000000..a13c8db --- /dev/null +++ b/SOURCES/libreswan-3.12-1105171-manpage.patch @@ -0,0 +1,13 @@ +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 new file mode 100644 index 0000000..a6ca14b --- /dev/null +++ b/SOURCES/libreswan-3.12-1131503-invalid-ke.patch @@ -0,0 +1,592 @@ +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 new file mode 100644 index 0000000..0a5f163 --- /dev/null +++ b/SOURCES/libreswan-3.12-1134297-aes_ctr.patch @@ -0,0 +1,2061 @@ +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 new file mode 100644 index 0000000..d1f55ba --- /dev/null +++ b/SOURCES/libreswan-3.12-1144120-camellia-ikev2.patch @@ -0,0 +1,127 @@ +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 new file mode 100644 index 0000000..881cc6d --- /dev/null +++ b/SOURCES/libreswan-3.12-1162770-gcm-man.patch @@ -0,0 +1,25 @@ +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-826264-ike-aes-gcm.patch b/SOURCES/libreswan-3.12-826264-ike-aes-gcm.patch new file mode 100644 index 0000000..a470a27 --- /dev/null +++ b/SOURCES/libreswan-3.12-826264-ike-aes-gcm.patch @@ -0,0 +1,2804 @@ +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.8-1092047.patch b/SOURCES/libreswan-3.8-1092047.patch deleted file mode 100644 index 1410e89..0000000 --- a/SOURCES/libreswan-3.8-1092047.patch +++ /dev/null @@ -1,58 +0,0 @@ -diff -Naur libreswan-3.8-orig/programs/pluto/plutomain.c libreswan-3.8/programs/pluto/plutomain.c ---- libreswan-3.8-orig/programs/pluto/plutomain.c 2014-07-14 14:06:22.408265468 -0400 -+++ libreswan-3.8/programs/pluto/plutomain.c 2014-07-14 14:34:39.150794888 -0400 -@@ -447,23 +447,7 @@ - leak_detective = 0; - #endif - --#ifdef HAVE_LIBCAP_NG -- /* -- * Drop capabilities - this generates a false positive valgrind warning -- * See: http://marc.info/?l=linux-security-module&m=125895232029657 -- */ -- capng_clear(CAPNG_SELECT_BOTH); - -- capng_updatev(CAPNG_ADD, CAPNG_EFFECTIVE | CAPNG_PERMITTED, -- CAP_NET_BIND_SERVICE, CAP_NET_ADMIN, CAP_NET_RAW, -- CAP_IPC_LOCK, CAP_AUDIT_WRITE, -- CAP_SETGID, CAP_SETUID, /* for google authenticator pam */ -- -1); -- /* our children must be able to CAP_NET_ADMIN to change routes. -- */ -- capng_updatev(CAPNG_ADD, CAPNG_BOUNDING_SET, CAP_NET_ADMIN, CAP_DAC_READ_SEARCH, -1); /* DAC needed for google authenticator pam */ -- capng_apply(CAPNG_SELECT_BOTH); --#endif - - libreswan_passert_fail = passert_fail; - -@@ -1104,6 +1088,30 @@ - pluto_init_log(); - pluto_init_nss(oco->confddir); - -+#ifdef HAVE_LIBCAP_NG -+ /* -+ * Drop capabilities - this generates a false positive valgrind warning -+ * See: http://marc.info/?l=linux-security-module&m=125895232029657 -+ * -+ * We drop these after creating the pluto socket or else we can't -+ * create a socket if the parent dir is non-root -+ */ -+ capng_clear(CAPNG_SELECT_BOTH); -+ -+ capng_updatev(CAPNG_ADD, CAPNG_EFFECTIVE | CAPNG_PERMITTED, -+ CAP_NET_BIND_SERVICE, CAP_NET_ADMIN, CAP_NET_RAW, -+ CAP_IPC_LOCK, CAP_AUDIT_WRITE, -+ CAP_SETGID, CAP_SETUID, /* for google authenticator pam */ -+ -1); -+ /* our children must be able to CAP_NET_ADMIN to change routes. -+ */ -+ capng_updatev(CAPNG_ADD, CAPNG_BOUNDING_SET, CAP_NET_ADMIN, CAP_DAC_READ_SEARCH, -1); /* DAC needed for google authenticator pam */ -+ capng_apply(CAPNG_SELECT_BOTH); -+ libreswan_log("libcap-ng support [enabled]"); -+#else -+ libreswan_log("libcap-ng support [disabled]"); -+#endif -+ - #ifdef FIPS_CHECK - /* - * FIPS Kernel mode: fips=1 kernel boot parameter diff --git a/SOURCES/libreswan-3.8-create_child_stub.patch b/SOURCES/libreswan-3.8-create_child_stub.patch deleted file mode 100644 index f241dce..0000000 --- a/SOURCES/libreswan-3.8-create_child_stub.patch +++ /dev/null @@ -1,394 +0,0 @@ -diff -Naur libreswan-3.8-orig/include/ietf_constants.h libreswan-3.8/include/ietf_constants.h ---- libreswan-3.8-orig/include/ietf_constants.h 2014-01-16 02:46:24.000000000 -0500 -+++ libreswan-3.8/include/ietf_constants.h 2014-04-10 15:55:22.303340560 -0400 -@@ -607,7 +607,7 @@ - /* IKEv2 things */ - ISAKMP_v2_SA_INIT = 34, - ISAKMP_v2_AUTH = 35, -- ISAKMP_v2_CHILD_SA = 36, -+ ISAKMP_v2_CREATE_CHILD_SA = 36, - ISAKMP_v2_INFORMATIONAL = 37, - ISAKMP_v2_IKE_SESSION_RESUME = 38, /* RFC 5723 */ - -diff -Naur libreswan-3.8-orig/include/pluto_constants.h libreswan-3.8/include/pluto_constants.h ---- libreswan-3.8-orig/include/pluto_constants.h 2014-01-16 02:46:24.000000000 -0500 -+++ libreswan-3.8/include/pluto_constants.h 2014-04-10 15:55:22.303340560 -0400 -@@ -424,6 +424,11 @@ - - #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) -+ - /* - * Issue here is that our child sa appears as a STATE_PARENT_I3/STATE_PARENT_R2 state which it should not - * So we fall back to checking if it is cloned, and therefor really a child -diff -Naur libreswan-3.8-orig/lib/libswan/constants.c libreswan-3.8/lib/libswan/constants.c ---- libreswan-3.8-orig/lib/libswan/constants.c 2014-01-16 02:46:24.000000000 -0500 -+++ libreswan-3.8/lib/libswan/constants.c 2014-04-10 15:55:22.303340560 -0400 -@@ -269,7 +269,7 @@ - static const char *const exchange_name_ikev2[] = { - "ISAKMP_v2_SA_INIT", - "ISAKMP_v2_AUTH", -- "ISAKMP_v2_CHILD_SA", -+ "ISAKMP_v2_CREATE_CHILD_SA", - "ISAKMP_v2_INFORMATIONAL", - "ISAKMP_v2_IKE_SESSION_RESUME", - }; -diff -Naur libreswan-3.8-orig/programs/pluto/ikev2.c libreswan-3.8/programs/pluto/ikev2.c ---- libreswan-3.8-orig/programs/pluto/ikev2.c 2014-01-16 02:46:24.000000000 -0500 -+++ libreswan-3.8/programs/pluto/ikev2.c 2014-04-10 15:55:37.668690909 -0400 -@@ -150,6 +150,31 @@ - * TSi, TSr} - * [Child SA established] - * -+ * -+ * CREATE_CHILD_SA Exchanges: -+ * -+ * New Child SA -+ * -+ * HDR, SK {SA, Ni, [KEi], -+ * TSi, TSr} --> -+ * -+ * <-- HDR, SK {SA, Nr, [KEr], -+ * TSi, TSr} -+ * -+ * Rekey Child SA -+ * -+ * HDR, SK {N(REKEY_SA), SA, Ni, [KEi], -+ * TSi, TSr} --> -+ * -+ * <-- HDR, SK {SA, Nr, [KEr], -+ * TSi, TSr} -+ * -+ * Rekey IKE SA (yes, IKE SA can be rekeyed using CREATE_CHILD_SA) -+ * -+ * HDR, SK {SA, Ni, KEi} --> -+ * -+ * <-- HDR, SK {SA, Nr, KEr} -+ * - */ - - /* Short forms for building payload type sets */ -@@ -287,6 +312,36 @@ - .processor = process_informational_ikev2, - .recv_type = ISAKMP_v2_INFORMATIONAL, }, - -+ /* -+ * There are three different CREATE_CHILD_SA's invocations, -+ * this is the combined write up (not in RFC). See above for -+ * individual cases from RFC -+ * -+ * HDR, SK {SA, Ni, [KEi], [N(REKEY_SA)], [TSi, TSr]} --> -+ * <-- HDR, SK {N} -+ * <-- HDR, SK {SA, Nr, [KEr], [TSi, TSr]} -+ */ -+ -+ /* Create Child SA Exchange*/ -+ { .state = STATE_PARENT_I3, -+ .next_state = STATE_PARENT_I3, -+ .flags = SMF2_STATENEEDED | SMF2_REPLY, -+ .req_clear_payloads = P(E), -+ .req_enc_payloads = P(SA) | P(Ni), -+ .opt_enc_payloads = P(KE) | P(N) | P(TSi) | P(TSr), -+ .processor = ikev2_in_create_child_sa, -+ .recv_type = ISAKMP_v2_CREATE_CHILD_SA, }, -+ -+ /* Create Child SA Exchange*/ -+ { .state = STATE_PARENT_R2, -+ .next_state = STATE_PARENT_R2, -+ .flags = SMF2_STATENEEDED | SMF2_REPLY, -+ .req_clear_payloads = P(E), -+ .req_enc_payloads = P(SA) | P(Ni), -+ .opt_enc_payloads = P(KE) | P(N) | P(TSi) | P(TSr), -+ .processor = ikev2_in_create_child_sa, -+ .recv_type = ISAKMP_v2_CREATE_CHILD_SA, }, -+ - /* Informational Exchange*/ - { .state = STATE_PARENT_R2, - .next_state = STATE_PARENT_R2, -@@ -607,7 +662,11 @@ - continue; - - /* ??? not sure that this is necessary, but it ought to be correct */ -- if ( ((svm->flags&SMF2_INITIATOR) != 0) != ((md->hdr.isa_flags & ISAKMP_FLAGS_R) != 0) ) -+ /* This check cannot apply for an informational exchange since one -+ * can be initiated by the initial responder. -+ */ -+ if (ix != ISAKMP_v2_INFORMATIONAL && -+ (((svm->flags&SMF2_INITIATOR) != 0) != ((md->hdr.isa_flags & ISAKMP_FLAGS_R) != 0))) - continue; - - /* must be the right state */ -@@ -832,6 +891,10 @@ - - case RESPONDER: - pst->st_msgid_lastrecv = md->msgid_received; -+ /* the responder requires msgid_nextuse if it ever needs to -+ * initiate an informational exchange -+ */ -+ pst->st_msgid_nextuse = md->msgid_received + 1; - break; - } - } -diff -Naur libreswan-3.8-orig/programs/pluto/ikev2.h libreswan-3.8/programs/pluto/ikev2.h ---- libreswan-3.8-orig/programs/pluto/ikev2.h 2014-01-16 02:46:24.000000000 -0500 -+++ libreswan-3.8/programs/pluto/ikev2.h 2014-04-10 15:55:22.304340582 -0400 -@@ -35,6 +35,8 @@ - extern stf_status ikev2_send_informational(struct state *st); - - extern stf_status process_informational_ikev2(struct msg_digest *md); -+extern stf_status ikev2_in_create_child_sa(struct msg_digest *md); -+ - extern stf_status ikev2parent_inI1outR1(struct msg_digest *md); - extern stf_status ikev2parent_inR1(struct msg_digest *md); - extern stf_status ikev2parent_inR1outI2(struct msg_digest *md); -diff -Naur libreswan-3.8-orig/programs/pluto/ikev2_parent.c libreswan-3.8/programs/pluto/ikev2_parent.c ---- libreswan-3.8-orig/programs/pluto/ikev2_parent.c 2014-01-16 02:46:24.000000000 -0500 -+++ libreswan-3.8/programs/pluto/ikev2_parent.c 2014-04-10 15:55:37.668690909 -0400 -@@ -2722,8 +2722,125 @@ - delete_state(pst); - } - -+static stf_status ikev2_in_create_child_sa_refuse(struct msg_digest *md) -+{ -+ struct state *st = md->st; -+ struct state *pst = st; -+ { -+ unsigned char *authstart; -+ unsigned char *encstart; -+ unsigned char *iv; -+ int ivsize; -+ struct ikev2_generic e; -+ pb_stream e_pbs, e_pbs_cipher; -+ pb_stream request; -+ -+ zero(&reply_buffer); -+ init_pbs(&request, reply_buffer, sizeof(reply_buffer), -+ "create child SA exchange request response"); -+ authstart = request.cur; -+ -+ /* HDR out */ -+ { -+ struct isakmp_hdr r_hdr; -+ zero(&r_hdr); -+ r_hdr.isa_version = build_ike_version(); -+ memcpy(r_hdr.isa_rcookie, pst->st_rcookie, -+ COOKIE_SIZE); -+ memcpy(r_hdr.isa_icookie, pst->st_icookie, -+ COOKIE_SIZE); -+ r_hdr.isa_xchg = ISAKMP_v2_CREATE_CHILD_SA; -+ r_hdr.isa_np = ISAKMP_NEXT_v2E; -+ r_hdr.isa_flags |= ISAKMP_FLAGS_R; -+ r_hdr.isa_msgid = htonl(pst->st_msgid_nextuse); -+ -+ /* encryption role based on original state not md state */ -+ if (IS_V2_INITIATOR(pst->st_state)) -+ md->role = INITIATOR; -+ else -+ md->role = RESPONDER; -+ -+ if (!out_struct(&r_hdr, &isakmp_hdr_desc, -+ &request, &md->rbody)) { -+ libreswan_log("error initializing hdr for " -+ "CREATE_CHILD_SA message"); -+ return STF_FATAL; -+ } -+ } /* HDR done*/ -+ -+ /* insert an Encryption payload header */ -+ e.isag_np = ISAKMP_NEXT_v2N; -+ e.isag_critical = ISAKMP_PAYLOAD_NONCRITICAL; -+ if (!out_struct(&e, &ikev2_e_desc, &md->rbody, &e_pbs)) -+ return STF_FATAL; -+ -+ /* IV */ -+ iv = e_pbs.cur; -+ ivsize = pst->st_oakley.encrypter->iv_size; -+ if (!out_zero(ivsize, &e_pbs, "iv")) -+ return STF_FATAL; -+ -+ get_rnd_bytes(iv, ivsize); -+ -+ /* note where cleartext starts */ -+ init_pbs(&e_pbs_cipher, e_pbs.cur, e_pbs.roof - e_pbs.cur, -+ "cleartext"); -+ e_pbs_cipher.container = &e_pbs; -+ e_pbs_cipher.desc = NULL; -+ e_pbs_cipher.cur = e_pbs.cur; -+ encstart = e_pbs_cipher.cur; -+ -+ chunk_t child_spi; -+ memset(&child_spi, 0, sizeof(child_spi)); -+ -+ ship_v2N(ISAKMP_NEXT_v2NONE, -+ ISAKMP_PAYLOAD_NONCRITICAL, -+ PROTO_ISAKMP, -+ &child_spi, -+ v2N_NO_ADDITIONAL_SAS, NULL, -+ &e_pbs_cipher); -+ -+ ikev2_padup_pre_encrypt(md, &e_pbs_cipher); -+ close_output_pbs(&e_pbs_cipher); -+ -+ { -+ stf_status ret; -+ unsigned char *authloc = ikev2_authloc(md, &e_pbs); -+ -+ if (!authloc) -+ return STF_FATAL; -+ -+ close_output_pbs(&e_pbs); -+ close_output_pbs(&md->rbody); -+ close_output_pbs(&request); -+ -+ ret = ikev2_encrypt_msg(md, md->role, -+ authstart, -+ iv, encstart, authloc, -+ &e_pbs, &e_pbs_cipher); -+ if (ret != STF_OK) -+ return ret; -+ } -+ -+ /* keep it for a retransmit if necessary */ -+ freeanychunk(pst->st_tpacket); -+ clonetochunk(pst->st_tpacket, request.start, -+ pbs_offset(&request), -+ "reply packet for CREATE_CHILD_SA exchange"); -+ send_ike_msg(pst, __FUNCTION__); -+ } -+ -+ return STF_OK; -+} -+ -+stf_status ikev2_in_create_child_sa(struct msg_digest *md) -+{ -+ return ikev2_in_create_child_sa_refuse(md); -+} -+ - stf_status process_informational_ikev2(struct msg_digest *md) - { -+ enum phase1_role prole; - /* verify that there is in fact an encrypted payload */ - if (md->chain[ISAKMP_NEXT_v2E] == NULL) { - libreswan_log( -@@ -2734,15 +2851,23 @@ - /* decrypt things. */ - { - stf_status ret; -+ struct state *ost = md->st; - -- if (md->hdr.isa_flags & ISAKMP_FLAGS_I) { -+ /* -+ * Since an informational exchange can be started by the original responder, -+ * things such as encryption, decryption should be done based on the original -+ * role and not the md->role -+ */ -+ if (IS_V2_INITIATOR(ost->st_state)) { -+ prole = INITIATOR; - DBG(DBG_CONTROLMORE, -- DBG_log("received informational exchange request from INITIATOR")); -- ret = ikev2_decrypt_msg(md, RESPONDER); -+ DBG_log("received informational exchange request from the original responder")); -+ ret = ikev2_decrypt_msg(md, INITIATOR); - } else { -+ prole = RESPONDER; - DBG(DBG_CONTROLMORE, -- DBG_log("received informational exchange request from RESPONDER")); -- ret = ikev2_decrypt_msg(md, INITIATOR); -+ DBG_log("received informational exchange request from the original initiator")); -+ ret = ikev2_decrypt_msg(md, RESPONDER); - } - - if (ret != STF_OK) -@@ -2791,10 +2916,6 @@ - r_hdr.isa_np = ISAKMP_NEXT_v2E; - r_hdr.isa_msgid = htonl(md->msgid_received); - -- /*set initiator bit if we are initiator*/ -- if (md->role == INITIATOR) -- r_hdr.isa_flags |= ISAKMP_FLAGS_I; -- - r_hdr.isa_flags |= ISAKMP_FLAGS_R; - - if (!out_struct(&r_hdr, &isakmp_hdr_desc, -@@ -3016,7 +3137,7 @@ - close_output_pbs(&md->rbody); - close_output_pbs(&reply_stream); - -- ret = ikev2_encrypt_msg(md, md->role, -+ ret = ikev2_encrypt_msg(md, prole, - authstart, - iv, encstart, authloc, - &e_pbs, &e_pbs_cipher); -@@ -3158,7 +3279,7 @@ - - stf_status ikev2_send_informational(struct state *st) - { -- struct state *pst = NULL; -+ struct state *pst = st; - - if (IS_CHILD_SA(st)) { - pst = state_with_serialno(st->st_clonedfrom); -@@ -3169,8 +3290,6 @@ - DBG_log("INFORMATIONAL exchange can not be sent")); - return STF_IGNORE; - } -- } else { -- pst = st; - } - - { -@@ -3180,7 +3299,6 @@ - int ivsize; - struct msg_digest md; - struct ikev2_generic e; -- enum phase1_role role; - pb_stream e_pbs, e_pbs_cipher; - pb_stream rbody; - pb_stream request; -@@ -3204,18 +3322,14 @@ - COOKIE_SIZE); - r_hdr.isa_xchg = ISAKMP_v2_INFORMATIONAL; - r_hdr.isa_np = ISAKMP_NEXT_v2E; -+ r_hdr.isa_flags |= ISAKMP_FLAGS_I; -+ r_hdr.isa_msgid = htonl(pst->st_msgid_nextuse); - -- if (pst->st_state == STATE_PARENT_I2 || -- pst->st_state == STATE_PARENT_I3) { -- r_hdr.isa_flags |= ISAKMP_FLAGS_I; -- role = INITIATOR; -- r_hdr.isa_msgid = htonl(pst->st_msgid_nextuse); -- } else { -- role = RESPONDER; -- r_hdr.isa_msgid = htonl( -- pst->st_msgid_lastrecv + 1); -- } -- -+ /* encryption role based on original state not md state */ -+ if (IS_V2_INITIATOR(pst->st_state)) -+ md.role = INITIATOR; -+ else -+ md.role = RESPONDER; - if (!out_struct(&r_hdr, &isakmp_hdr_desc, - &request, &rbody)) { - libreswan_log( -@@ -3261,7 +3375,7 @@ - close_output_pbs(&rbody); - close_output_pbs(&request); - -- ret = ikev2_encrypt_msg(&md, role, -+ ret = ikev2_encrypt_msg(&md, md.role, - authstart, - iv, encstart, authloc, - &e_pbs, &e_pbs_cipher); -@@ -3276,7 +3390,6 @@ - "reply packet for informational exchange"); - pst->st_pend_liveness = TRUE; /* we should only do this when dpd/liveness is active? */ - send_ike_msg(pst, __FUNCTION__); -- ikev2_update_counters(&md); - } - - return STF_OK; diff --git a/SOURCES/libreswan-3.8-docupdate.patch b/SOURCES/libreswan-3.8-docupdate.patch deleted file mode 100644 index 5794cff..0000000 --- a/SOURCES/libreswan-3.8-docupdate.patch +++ /dev/null @@ -1,562 +0,0 @@ -diff -Naur libreswan-3.8-orig/README libreswan-3.8/README ---- libreswan-3.8-orig/README 2014-01-16 02:46:24.000000000 -0500 -+++ libreswan-3.8/README 2014-02-21 18:41:44.887838212 -0500 -@@ -2,28 +2,48 @@ - # Libreswan 3.X Release Notes - ######################################################################### - -+The Libreswan Project https://libreswan.org/ -+ - Libreswan is an IPsec implementation for Linux. It has support for most - of the extensions (RFC + IETF drafts) related to IPsec, including - IKEv2, X.509 Digital Certificates, NAT Traversal, and many others. -+Libreswan uses the native Linux IPsec stack (NETKEY/XFRM) per default. -+For more information about the alternative Libreswan kernel IPsec stack, -+see README.KLIPS. - --Libreswan has been forked from Openswan 2.6.38, which was forked from --FreeS/WAN 1.99. -+Libreswan was forked from Openswan 2.6.38, which was forked from -+FreeS/WAN 1.99. See the CREDITS files for contributor acknowledgments. - --Download it from -+It can be downloaded from various locations: - - https://download.libreswan.org/ - ftp://ftp.libreswan.org/ - -+A git repository is available at: -+ -+ https://github.com/libreswan/libreswan/ -+ -+######################################################################### -+# LICENSE -+######################################################################### -+ -+The bulk of libreswan is licensed under the GNU General Public License -+version 2; see the LICENSE and CREDIT.* files. Some smaller parts have -+a different license. -+ - ######################################################################### - # REQUIREMENTS - ######################################################################### - - A recent Linux distribution based on either Kernel 2.4.x, 2.6.x or 3.x --are the currently supported platforms. -+are the currently supported platforms. Libreswan has been ported to -+Win2k/BSD/OSX as well. - --Most recent distributions have package support for libreswan. Unless --a source based build is truly needed, it is often best to use the pre-built --distributions packaged version. -+Most distributions have native packaged support for libreswan. Libreswan is -+available for RHEL, Fedora, Ubuntu, Debian, Arch, openwrt and more. -+ -+Unless a source based build is truly needed, it is often best to use -+the pre-built version of the distribution you are using. - - There are a few packages required for Libreswan to compile from source: - -@@ -45,7 +65,7 @@ - - Runtime requirements (usually already present on the system) - -- iproute2, iptables, sed, awk, bash, cut and possible other tools -+ nss, iproute2, iptables, sed, awk, bash, cut - - (note: the busybox version of "ip" does not support 'ip xfrm', so - ensure you enable the iproute(2) package for busybox) -@@ -53,106 +73,72 @@ - python is used for "ipsec verify", which helps debugging problems - - ######################################################################### --# HOW TO INSTALL on Kernel 2.6 and higher -+# Compiling the userland and IKE daemon - ######################################################################### - --NETKEY/XFRM (Native linux IPsec stack) ----------------------------------- -- --To use Libreswan with the linux native (builtin) IPsec stack, the --following steps should be all that are needed. Please use at least kernel --version 2.6.9, as prior versions of the kernel have serious bugs in the --native IPsec stack. From the libreswan directory: -- - make programs - sudo make install - --Note: The ipsec-tools package or setkey is not needed. Instead iproute2 >= 2.6.8 --is required. Run 'ipsec verify' to determine if your system misses anything. --of the requirements. -- --KLIPS/KLIPSNG (Libreswan IPsec stack) -------------------------------------- -- --To use the Libreswan KLIPS IPsec stack (ipsec0 devices) for Linux --Kernels 2.4 and higher, the following steps should work. From the --libreswan directory: -- -- make programs -- make module -- sudo make module_install -- --This builds a module against the running kernel. To compile a module for --another kernel (for which the headers are installed), use: -- -- make KERNELSRC=/lib/modules/`uname -r`/build module -- sudo make KERNELSRC=/lib/modules/`uname -r`/build module_install -+Note: The ipsec-tools package or setkey is not needed. Instead the iproute2 -+pacakge (>= 2.6.8) is required. Run 'ipsec verify' to determine if your -+system misses any of the requirements. This will also tell you if any of -+the kernel sysctl values needs changing. - --For Linux 2.6 Kernels before 2.6.23, including 2.4 linux systems, the kernel --requires patching if NAT-T support or SAref tracking is required. Full kernel --source will be required as the kernel sources are being patched, built and --installed. It is good practice to build and install an unpatched kernel --before starting to ensure the process is correct. See your distribution --documentation on how to build and install a new kernel -- -- Determine the linux source directory, for example /usr/src/linux on -- most full source installs. It may also be /usr/src/linux-2.[46].X -- -- Add NAT-T support (if required). -- -- From the Libreswan source directory: -- -- make KERNELSRC=/usr/src/linux nattpatch | patch -d /usr/src/linux -p1 -- -- Add SAref tracking support (if required). -+######################################################################### -+# Starting Libreswan -+######################################################################### - -- Premade patches for some distributions kernels can be found in -- patches/kernel/ It is recommended that kernel 2.6.32 or higher is -- used. Documentation on SAref/MAST can be found in docs/HACKING/Mast* -- and doc/klips/mast.xml. To understand what SAref tracking does, see -- doc/ipsecsaref.png and the overlapip= entry in the ipsec.conf man page. -+The install will detect the init system used (systemd, upstart, sysvinit, -+openrc) and should integrate with the linux distribution. The service -+name is called "ipsec". For example, on RHEL7, one would use: - -- From the Libreswan source directory: -+ systemctl enable ipsec.service -+ systemctl start ipsec.service - -- make KERNELSRC=/usr/src/linux sarefpatch | patch -d /usr/src/linux -p1 -+If unsure, the "ipsec" command can also be used to start or stop the ipsec -+service: - -- Add OCF HW offloading support -+ ipsec setup start -+ ipsec setup stop - -- For OCF HW offloading support, you need also need a patched kernel -- See: http://ocf-linux.sourceforge.net/ for more details. -+######################################################################### -+# Configuration -+######################################################################### - -- Build and install a new kernel -+Most of the libreswan configuration is stored in /etc/ipsec.conf and -+/etc/ipsec.secrets. See their respective man pages for more information. - -- See your distribution documentation on how to install a new kernel. -- It should be something similar to: -+######################################################################### -+# NSS initialisation -+######################################################################### - -- cd /usr/src/linux -- make oldconfig -- make dep - this step is ignore on 2.6 systems) -- make bzImage install -+Libreswan uses NSS to store private keys and X.509 certificates. The NSS -+database should have been initialised by the package installer. If not, -+the NSS database can be initialised using: - -- Build Libreswan -+ ipsec initnss - -- From the Libreswan source directory: -+PKCS#12 certificates (.p12 files) can be imported using: - -- make programs -- make KERNELSRC=/usr/src/linux module -- sudo make KERNELSRC=/usr/src/linux install minstall -+ ipsec import /path/to/your.p12 - --The Libreswan configuration file can select which ipsec stack to use at --runtime by using the "protostack=" options in ipsec.conf. --See the ipsec.conf man page for more information on configuration options. -+See README.NSS and 'certutil --help' for more details on using NSS and -+migrating from the old openswan /etc/ipsec.d/ directories to using NSS. - - ######################################################################### - # UPGRADING - ######################################################################### - --1. If you are upgrading from FreeS/WAN 1.x or Openswan 2.x to Libreswan 3.x, -- you might need to adjust your config files. See 'man ipsec.conf. -- details on what has changed. -- --2. You can run 'make install' on top of your old version - it will not -- overwrite your your /etc/ipsec.* config files -+If you are upgrading from FreeS/WAN 1.x or Openswan 2.x to Libreswan 3.x, -+you might need to adjust your config files, although great care has been -+put into making the configuration files full backwards compatible. -+ -+See 'man ipsec.conf' for the list of options to find any new features. -+ -+You can run 'make install' on top of your old version - it will not -+overwrite your your /etc/ipsec.* configuration files. The default install -+target installs in /usr/local. Ensure you do not install libreswan twice, -+one from a distribution package in /usr and once manually in /usr/local. - - ######################################################################### - # SUPPORT -@@ -160,12 +146,12 @@ - - Mailing Lists: - -- https://lists.libreswan.org is home of the mailing lists -+ https://lists.libreswan.org/ is home of all our the mailing lists - - Wiki: - - https://libreswan.org is home to the Libreswan WIKI. It has the most -- up to date documentation, interop guides and other related information. -+ up to date documentation, interop guides and other useful information. - - IRC: - -@@ -176,35 +162,37 @@ - # BUGS - ######################################################################### - --Bugs with the package can be filed into our bug tracking system, at --https://bugs.libreswan.org -+Bugs can be reported on the mailing list or using our bug tracking system, -+at https://bugs.libreswan.org/ - - ######################################################################### --# SECURITY HOLES -+# SECURITY INFORMATION - ######################################################################### - --All security vulnerabilities found that require public disclosure will --receive proper CVE tracking numbers (see http://mitre.org/) and co-ordinated --via the vendor-sec (or successor) mailing list. A complete list of known --security vulnerabilities is available at: https://www.libreswan.org/security/ -+All security issues found that require public disclosure will -+receive proper CVE tracking numbers (see http://mitre.org/) and -+will be co-ordinated via the vendor-sec / oss-security lists. A -+complete list of known security vulnerabilities is available at: -+ -+https://www.libreswan.org/security/ - - ######################################################################### - # DEVELOPMENT - ######################################################################### - --Those interested in the development, patches, beta releases of Libreswan --can join the development mailing list (http://lists.libreswan.org - --dev@lists.libreswan.org) or join the development team on IRC in #swan --on irc.freenode.net -+Those interested in the development, patches, and beta releases of -+Libreswan can join the development mailing list "swan-dev" or talk to the -+development team on IRC in #swan on irc.freenode.net - - For those who want to track things a bit more closely, the --commits@lists.libreswan.org mailinglist will mail all the commit messages. -+commits@lists.libreswan.org mailinglist will mail all the commit messages -+when they happen. This list is quite busy during active development -+periods. - - ######################################################################### - # DOCUMENTATION - ######################################################################### - --The most up to date docs are in the man pages and at https://libreswan.org/ -+The most up to date docs are in the man pages that come with the software -+and at https://libreswan.org/ - --The bulk of this software is under the GNU General Public License; see --LICENSE. Some parts of it are not; see CREDITS for the details. -diff -Naur libreswan-3.8-orig/README.nss libreswan-3.8/README.nss ---- libreswan-3.8-orig/README.nss 1969-12-31 19:00:00.000000000 -0500 -+++ libreswan-3.8/README.nss 2014-02-21 18:42:01.769172404 -0500 -@@ -0,0 +1,265 @@ -+ -+######################################################################### -+# Using the NSS crypto library with Pluto (Libreswan) -+# Based on initial documentation by Avesh Agarwal -+######################################################################### -+ -+For detailed developer information about NSS, see -+http://www.mozilla.org/projects/security/pki/nss/ -+ -+The NSS crypto library is user space library. It is only used with the -+libreswan userspace IKE daemon pluto for cryptographic operations. NSS -+does not perform IPsec crypto operations inside the kernel (KLIPS -+nor NETKEY) -+ -+The NSS library exports a PKCS#11 API for the application to -+communicate to a cryptographic device. The cryptographic device is -+usually the "soft token" but can also be a Hardware Security Module -+(HSM). -+ -+The advantage of using NSS is that pluto does need to know in detail how -+the cryptographic device works. Pluto does not access any private keys or -+data itself. Instead, it uses the PK11 wrapper API of NSS irrespective -+of the cryptographic device used. Pluto hands over work using the PK11 -+interface to NSS and never has direct access to the private key material -+itself. Both IKEv1 and IKEv2 operations are performed using NSS. Private -+RSA keys (raw RSA as well as X.509 based private RSA keys) are stored -+inside NSS. RSA keys are still referenced in /etc/ipsec.secrets. X.509 -+keys and certificates are referenced using their "nickname" instead of -+their filename in /etc/ipsec.conf. -+ -+While PreShared Key (PSK) calculations are done using NSS, the actual -+preshared key ("secret") is still stored in /etc/ipsec.secrets. -+ -+NSS as shipped by Red Hat is a FIPS certified library. Libreswan is -+currently being FIPS certified for RHEL7. -+ -+######################################################################### -+# The NSS command line tools used with libreswan -+######################################################################### -+ -+- certutil: Look and modify the NSS db. "ipsec initnss" and "ipsec look" -+ use certutil under the hood. -+ -+http://www.mozilla.org/projects/security/pki/nss/tools/certutil.html -+ -+- pk12util: import and export certificates and keys from and to the NSS db. -+ The "ipsec import" command is a simple wrapper around this utility. -+ -+http://www.mozilla.org/projects/security/pki/nss/tools/pk12util.html -+ -+- modutil: Put NSS into FIPS mode -+ -+http://www.mozilla.org/projects/security/pki/nss/tools/modutil.html -+ -+######################################################################### -+# Creating the NSS db for use with libreswan's pluto IKE daemon -+######################################################################### -+ -+If you are not using a packaged libreswan version, you might need to -+create a new NSS db before you can start libreswan. This can be done -+using: -+ -+ ipsec initnss -+ -+By default the NSS db is created in /etc/ipsec.d/ -+ -+When creating a database, you are prompted for a password. The default -+libreswan package install for RHEL/Fedora/CentOS uses an empty password. -+It is up to the administrator to decide on whether to use a password -+or not. However, a non-empty database password must be provided when -+running in FIPS mode. -+ -+To change the empty password, run: -+ -+ certutil -W -d /etc/ipsec.d -+ -+Enter return for the "old password", then enter your new password. -+ -+If you create the database with a password, and want to run NSS in FIPS -+mode, you must create a password file with the name "nsspassword" in -+the /etc/ipsec.d direcotry before starting libreswan. The "nsspassword" -+file must contain the password you provided when creating NSS database. -+ -+If the NSS db is protected with a non-empty password, the "nsspassword" -+file must exist for pluto to start. -+ -+The syntax of the "nsspassword" file is: -+ -+token_1_name:the_password -+token_2_name:the_password -+ -+The name of NSS softtoken (the default software NSS db) when NOT running -+in FIPS mode is "NSS Certificate DB". If you wish to use software NSS -+db with password "secret", you would have the following entry in the -+nsspassword file: -+ -+NSS Certificate DB:secret -+ -+If running NSS in FIPS mode, the name of NSS softtoken is -+"NSS FIPS 140-2 Certificate DB". If there are smartcards in the system, the -+entries for passwords should be entered in this file as well. -+ -+Note: do not enter any spaces before or after the token name or password. -+ -+######################################################################### -+# Using raw RSA keys with NSS -+######################################################################### -+ -+The "ipsec newhostkey" and "ipsec rsasigkey" utilities are used for -+creating raw RSA keys. If a non-default NSS directory is used, this can -+be specified using the -d option. -+ -+ ipsec newhostkey --configdir /etc/ipsec.d [--password password] --output \ -+ /etc/ipsec.secrets -+ -+The password is only required if the NSS database is protected with a -+non-empty password. All "private" compontents of the raw RSA key in -+/etc/ipsec.secrets such as the exponents and primes are filled in with -+the CKA ID, which serves as an identifier for NSS to look up the proper -+information in the NSS db during the IKE negotiation. -+ -+Public key information is directly available in /etc/ipsec.secrets and the -+"ipsec showhostkey" command can be used to generate left/rightrsasigkey= -+entries for /etc/ipsec.conf. -+ -+######################################################################### -+# Using certificates with NSS -+######################################################################### -+ -+Any X.509 certificate management system can be used to generate Certificate -+Agencies, certificates, pkcs12 files and CRLs. Common tools people use are -+the openssl command, the GTK utility tinyca2, or the NSS certutil command. -+ -+An example using openssl can be found as part of the libreswan test suite at -+https://github.com/libreswan/libreswan/tree/master/testing/x509 -+ -+Below, we will be using the nss tools to generate certificates -+ -+* To create a certificate authority (CA certficate): -+ -+certutil -S -k rsa -n "ExampleCA" -s "CN=Example CA Inc" -w 12 \ -+ -d . -t "C,C,C" -x -d /etc/ipsec.d -+ -+It creates a certificate with RSA keys (-k rsa) with the nick name -+"ExampleCA", and with common name "Example CA Inc". The option -+"-w" specifies the certificates validy period. "-t" specifies the attributes -+of the certificate. "C" is required for creating a CA certificate. "-x" mean -+self signed. "-d" specifies the path of the database directory. -+ -+NOTE: It is not a requirement to create the CA in NSS database. The CA -+certificate can be obtained from anywhere in the world. -+ -+* To create a user certificate signed by the above CA -+ -+certutil -S -k rsa -c "ExampleCA" -n "user1" \ -+ -s "CN=User Common Name" -w 12 -t "u,u,u" -d /etc/ipsec.d -+ -+It creates a user cert with nick name "user1" with attributes -+"u,u,u" signed by the CA cert "ExampleCA". -+ -+NOTE: You must provide a nick name when creating a user -+certificate, because pluto reads the user certificate from the NSS database based on -+the user certificate's nickname. -+ -+ -+######################################################################### -+# Configuring certificates in ipsec.conf and ipsec.secrets -+######################################################################### -+ -+In ipsec.conf, the leftcert= option takes a certificate nickname as argument. For -+example if the nickname of the user cert is "hugh", then it can be -+"leftcert=hugh". -+ -+NOTE: if you are migrating from openswan, you are used to specifying a filename for the leftcert= option. Filenames -+are not valid for the left/rightcert= options in libreswan. -+ -+In ipsec.secrets, we need to list the certificate nickname to inform pluto there is a certificate within the NSS db. -+This is specified using: -+ -+ : RSA nickname -+ -+NOTE: In openswan and freeswan it was required to specify a file name or password. With libreswan, this is not required. -+NOTE: openswan and freeswan stored private keys in /etc/ipsec.d/private/ This directory does not exist for libreswan. -+ -+The directories /etc/ipsec.d/cacerts/ and /etc/ipsec.d/crls/ can still be used. -+ -+NOTE: the freeswan and openswan directories /etc/ipsec.d/aacerts/ and /etc/ipsec.d/acerts/ are not used with libreswan. -+ -+If you use an external CA certificate, you can either import it into the NSS db or place it in the /etc/ipsec.d/cacerts/ -+directory. Note that the preferred method is to store it inside the NSS db. -+ -+######################################################################### -+# Importing third-party certificates into NSS -+######################################################################### -+ -+If you do not have the third-party certificate in PKCS#12 format, use openssl -+to create a PKCS#12 file: -+ -+ openssl pkcs12 -export -in cert.pem -inkey key.pem -certfile cacert.pem \ -+ -out certkey.p12 [-name YourName] -+ -+Now you can import the file into the NSS db: -+ -+ ipsec import certkey.p12 -+ -+NOTE: the ipsec command uses "pk12util -i certkey.p12 -d /etc/ipsec.d" -+ -+If you did not pick a name using the -name option, you can use certutil -L -d /etc/ipsec.d -+to figure out the name NSS picked durnig the import. -+ -+Add following to /etc/ipsec.secrets file: -+ -+ : RSA "YourName" -+ -+To specify the certificate in ipsec.conf, use a line like: -+ -+ leftcert=YourName -+ -+######################################################################### -+# Exporting a CA(?) certificate to load on another libreswan machine -+######################################################################### -+ -+ -+Paul: wouldn't this also include the private key which we don't want????? -+Paul: add "ipsec export" ? -+ -+To export the CA certificate: -+ -+ pk12util -o cacert1.p12 -n cacert1 -d /etc/ipsec.d -+ -+Copy the file "cacert1.p12" to the new machine and import it using: -+ -+ ipsec import cacert1.p12 -+ certutil -M -n cacert1 -t "C,C,C" -d /etc/ipsec.d -+ -+ -+Example connection for ipsec.conf: -+ -+conn pluto-1-2 -+ left=1.2.3.4 -+ leftid="CN=usercert1" -+ leftrsasigkey=%cert -+ leftcert=usercert1 -+ right=5.6.7.8 -+ rightid="CN=usercert2" -+ rightrsasigkey=%cert -+ auto=add -+ -+######################################################################### -+# Configuring a smartcard with NSS -+######################################################################### -+ -+Required library: libcoolkey -+ -+To make smartcard tokens visible through NSS -+ -+modutil -add -libfile libcoolkeypk11.so -dbdir \ -+ -mechanisms -+ -+An example of mechanisms can be -+RC2:RC4:DES:DH:SHA1:MD5:MD2:SSL:TLS:AES:CAMELLIA. -+ -+To check whether the token is visible or not, please run -+ -+modutil -list -dbdir -diff -Naur libreswan-3.8-orig/README.x509 libreswan-3.8/README.x509 ---- libreswan-3.8-orig/README.x509 1969-12-31 19:00:00.000000000 -0500 -+++ libreswan-3.8/README.x509 2014-02-21 18:42:04.673229900 -0500 -@@ -0,0 +1,3 @@ -+ -+See README.NSS or check the wiki at https://libreswan.org/ -+ diff --git a/SOURCES/libreswan-3.8-log-1069024.patch b/SOURCES/libreswan-3.8-log-1069024.patch deleted file mode 100644 index 7676459..0000000 --- a/SOURCES/libreswan-3.8-log-1069024.patch +++ /dev/null @@ -1,25 +0,0 @@ -diff -Naur libreswan-3.8-orig/programs/pluto/ikev1_main.c libreswan-3.8/programs/pluto/ikev1_main.c ---- libreswan-3.8-orig/programs/pluto/ikev1_main.c 2014-01-16 07:46:24.000000000 +0000 -+++ libreswan-3.8/programs/pluto/ikev1_main.c 2014-03-05 00:31:03.263419508 +0000 -@@ -649,10 +649,10 @@ - - for (; d != NULL; d = d->hp_next) { - if (d->policy & POLICY_IKEV1_DISABLE) { -- loglog(RC_LOG_SERIOUS, -+ DBG(DBG_CONTROL,DBG_log( - "discard matching conn %s for " - "I1 from %s:%u. %s %s %s has " -- "ikev2=insist ", c->name, -+ "ikev2=insist ", d->name, - ip_str(&md->iface->ip_addr), - ntohs(portof(&md->iface->ip_addr)), - d->name, -@@ -660,7 +660,7 @@ - " with policy=" : "", - (policy != LEMPTY) ? - bitnamesof(sa_policy_bit_names, -- policy) : ""); -+ policy) : "")); - d=NULL; - continue; - } diff --git a/SOURCES/libreswan-3.8-newhostkey-1058813.patch b/SOURCES/libreswan-3.8-newhostkey-1058813.patch deleted file mode 100644 index 8638b03..0000000 --- a/SOURCES/libreswan-3.8-newhostkey-1058813.patch +++ /dev/null @@ -1,179 +0,0 @@ -commit 82299d151c379ba47ea93c1ef18b6372b4a6c445 -Author: Paul Wouters -Date: Fri Feb 21 19:19:43 2014 -0500 - - newhostkey: return proper error codes, no longer allow stdout. - - Return proper error codes when there is a failure, such as key too - small, no NSS db, etc. - - No longer allow just output to stdout, because with NSS we always - leave a key in the NSS db, so if the output is lost for ipsec.secrets, - it will cause a dangling unused key in NSS. - -diff --git a/programs/newhostkey/newhostkey.in b/programs/newhostkey/newhostkey.in -index 50d41c5..6e76f67 100755 ---- a/programs/newhostkey/newhostkey.in -+++ b/programs/newhostkey/newhostkey.in -@@ -1,6 +1,10 @@ - #! /bin/sh -+# - # generate new key for this host -+# - # Copyright (C) 2001, 2002 Henry Spencer. -+# Copyright (C) 2014 Paul Wouters -+# Copyright (C) 2014 Tuomo Soini - # - # 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 -@@ -14,9 +18,8 @@ - # - - me="ipsec newhostkey" --usage="Usage: $me [--output filename] [--random device] [--bits n] [--quiet] [--hostname host] [--configdir nssdbdir] [--password password] -- or -- $me --output - [--random device] [--bits n] [--quiet] [--verbose] [--hostname host] [--configdir nssdbdir] [--password password] >filename" -+usage="Usage: $me [--output filename] [--random device] [--bits n] \\ -+ [--quiet] [--hostname host] [--configdir nssdbdir] [--password password] " - - bits= - verbose= -@@ -25,56 +28,100 @@ random="--random /dev/random" - output="@FINALCONFDIR@/ipsec.secrets" - configdir="@FINALCONFDDIR@" - password= --for dummy --do -- case "$1" in -- --bits) bits="$2" ; shift ;; -- --quiet) verbose= ;; -- --hostname) host="--hostname $2" ; shift ;; -- --output) output="$2" ; shift ;; -- --verbose) verbose=--verbose ;; -- --version) echo "$me $IPSEC_VERSION" ; exit 0 ;; -- --random) random="--random $2" ; shift ;; -- --configdir) configdir="$2" ; shift ;; -- --password) password="--password $2" ; shift ;; -- --help) echo "$usage" ; exit 0 ;; -- --) shift ; break ;; -- -*) echo "$me: unknown option \`$1'" >&2 ; exit 2 ;; -- *) break ;; -- esac -- shift -+for dummy; do -+ case "$1" in -+ --bits) -+ bits="${2}" -+ shift -+ ;; -+ --quiet) -+ verbose= -+ ;; -+ --hostname) -+ host="--hostname ${2}" -+ shift -+ ;; -+ --output) -+ output="${2}" -+ shift -+ ;; -+ --verbose) -+ verbose="--verbose" -+ ;; -+ --version) -+ echo "$me $IPSEC_VERSION" -+ exit 0 -+ ;; -+ --random) -+ random="--random ${2}" -+ shift -+ ;; -+ --configdir) -+ configdir="${2}" -+ shift -+ ;; -+ --password) -+ password="--password ${2}" -+ shift -+ ;; -+ --help) -+ echo "$usage" -+ exit 0 -+ ;; -+ --) -+ shift -+ break -+ ;; -+ -*) -+ echo "$me: unknown option \`$1'" >&2 -+ exit 2 -+ ;; -+ *) -+ break -+ ;; -+ esac -+ shift - done - --if test " $verbose" != " " -a " $output" != " -" -a -s "$output" --then -- echo "$0: WARNING: file \`$output' exists, appending to it" >&2 -+if [ -d "${output}" ]; then -+ echo "ERROR: output file should be a secrets file, not a directory" -+ exit 255 - fi - --if test ! -d $configdir --then -- echo "No such directory: $configdir" -- exit 255 -+if [ -s "${output}" ]; then -+ echo "${0}: WARNING: file \"${output}\" exists, appending to it" >&2 -+fi -+ -+if [ ! -d ${configdir} ]; then -+ echo "No such directory: ${configdir}" -+ exit 255 - fi - - certutil -L -d $configdir >/dev/null 2>/dev/null - RETVAL=$? --if [ $RETVAL -eq 255 ]; --then -- echo "NSS database in $configdir not initialized. Please run 'ipsec initnss --configdir $configdir'" -- exit 255 -+if [ ${RETVAL} -eq 255 ]; then -+ echo "NSS database in $configdir not initialized." -+ echo " Please run 'ipsec initnss --configdir $configdir'" -+ exit 255 - fi - --( -+key=$(ipsec rsasigkey ${verbose} ${random} --configdir ${configdir} ${password} ${host} ${bits}) -+RETVAL=$? -+if [ ${RETVAL} -eq 0 ]; then -+ umask 077 -+ TEMPFILE=$(/bin/mktemp ${output}.XXXXXXX) -+ ( - echo ': RSA {' -- ipsec rsasigkey $verbose $random --configdir $configdir $password $host $bits -+ echo "${key}" - echo ' }' - echo '# do not change the indenting of that "}"' --) | --if test " $output" = " -" --then -- cat -+ ) > ${TEMPFILE} -+ if [ -s "${output}" ]; then -+ cat ${TEMPFILE} >> ${output} -+ rm ${TEMPFILE} -+ else -+ mv ${TEMPFILE} ${output} -+ fi - else -- umask 077 -- cat >>$output.new -- mv $output.new $output -+ exit ${RETVAL} - fi diff --git a/SOURCES/libreswan-3.8-no-acerts.patch b/SOURCES/libreswan-3.8-no-acerts.patch deleted file mode 100644 index 3eaefd0..0000000 --- a/SOURCES/libreswan-3.8-no-acerts.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff -Naur libreswan-3.8-orig/programs/pluto/plutomain.c libreswan-3.8/programs/pluto/plutomain.c ---- libreswan-3.8-orig/programs/pluto/plutomain.c 2014-01-16 02:46:24.000000000 -0500 -+++ libreswan-3.8/programs/pluto/plutomain.c 2014-02-21 18:54:48.108282499 -0500 -@@ -1345,7 +1345,9 @@ - /* loading X.509 CRLs - must happen after CAs are loaded */ - load_crls(); - /* loading attribute certificates from disk (should prob be removed) */ -+#if 0 - load_acerts(); -+#endif - - #ifdef HAVE_LABELED_IPSEC - init_avc(); diff --git a/SPECS/libreswan.spec b/SPECS/libreswan.spec index 74d601d..5b4280e 100644 --- a/SPECS/libreswan.spec +++ b/SPECS/libreswan.spec @@ -15,8 +15,8 @@ Name: libreswan Summary: IPsec implementation with IKEv1 and IKEv2 keying protocols -Version: 3.8 -Release: %{?prever:0.}6%{?prever:.%{prever}}%{?dist} +Version: 3.12 +Release: %{?prever:0.}5%{?prever:.%{prever}}%{?dist} License: GPLv2 Url: https://www.libreswan.org/ Source: https://download.libreswan.org/%{name}-%{version}%{?prever}.tar.gz @@ -28,13 +28,14 @@ Requires(preun): systemd Requires(postun): systemd Requires: iproute -Patch1: libreswan-3.8-docupdate.patch -Patch2: libreswan-3.8-no-acerts.patch -Patch3: libreswan-3.8-newhostkey-1058813.patch -Patch4: libreswan-3.8-log-1069024.patch -Patch5: libreswan-3.8-create_child_stub.patch -# rhbz#1119723 -Patch6: libreswan-3.8-1092047.patch +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 Conflicts: openswan < %{version}-%{release} Obsoletes: openswan < %{version}-%{release} @@ -65,8 +66,8 @@ BuildRequires: openldap-devel curl-devel %if %{buildefence} BuildRequires: ElectricFence %endif -# Only needed if xml man pages are modified and need regeneration -# BuildRequires: xmlto +# Needed if xml man pages are modified and need regeneration +BuildRequires: xmlto Requires: nss-tools, nss-softokn @@ -94,6 +95,10 @@ Libreswan is based on Openswan-2.6.38 which in turn is based on FreeS/WAN-2.04 %patch4 -p1 %patch5 -p1 %patch6 -p1 +%patch7 -p1 +%patch8 -p1 +# remove man page for ipsec.conf so it is forced to regenerate +rm ./programs/configs/ipsec.conf.5 %build %if %{buildefence} @@ -117,6 +122,7 @@ Libreswan is based on Openswan-2.6.38 which in turn is based on FreeS/WAN-2.04 %endif USE_LIBCAP_NG="%{USE_LIBCAP_NG}" \ USE_LABELED_IPSEC="%{USE_LABELED_IPSEC}" \ + USE_LINUX_AUDIT="%{USE_LINUX_AUDIT}" \ %if %{USE_CRL_FETCHING} USE_LDAP=true \ USE_LIBCURL=true \ @@ -172,8 +178,8 @@ rm -fr %{buildroot}/etc/rc.d/rc* %files %doc CHANGES COPYING CREDITS README* LICENSE -# do not include obsoleted libreswan-3.8 documentation - use docs/* after rebase to 3.9+ -%doc docs/CHANGES.* docs/CREDITS.* docs/README.labeledipsec docs/README.DPD docs/README.XAUTH +%doc docs/*.* docs/examples + %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 @@ -188,7 +194,7 @@ rm -fr %{buildroot}/etc/rc.d/rc* %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/pam.d/pluto %{_sbindir}/ipsec %{_libexecdir}/ipsec -%attr(0644,root,root) %doc %{_mandir}/*/* +%doc %{_mandir}/*/* %if %{USE_FIPSCHECK} %{_libdir}/fipscheck/*.hmac @@ -206,17 +212,60 @@ rm -fr %{buildroot}/etc/rc.d/rc* %post %systemd_post ipsec.service if [ ! -f %{_sysconfdir}/ipsec.d/cert8.db ] ; then - TEMPFILE=$(/bin/mktemp %{_sysconfdir}/ipsec.d/nsspw.XXXXXXX) - [ $? -gt 0 ] && TEMPFILE=%{_sysconfdir}/ipsec.d/nsspw.$$ - echo > ${TEMPFILE} - certutil -N -f ${TEMPFILE} -d %{_sysconfdir}/ipsec.d + certutil -N -d %{_sysconfdir}/ipsec.d --empty-password || : restorecon %{_sysconfdir}/ipsec.d/*db 2>/dev/null || : - rm -f ${TEMPFILE} fi %changelog -* Tue Jul 15 2014 Paul Wouters - 3.8-6 -- Resolves: rhbz#1119723 pluto cannot write to directories not owned by root +* Tue Jan 20 2015 Paul Wouters - 3.12-5 +- Resolves: rhbz#826264 aes-gcm implementation support (for IKEv2) +- Resolves: rhbz#1074018 Audit key agreement (integ gcm fixup) + +* Tue Dec 30 2014 Paul Wouters - 3.12-4 +- Resolves: rhbz#1134297 aes-ctr cipher is not supported +- Resolves: rhbz#1131503 non-zero rSPI on INVALID_KE (and proper INVALID_KE handling) + +* Thu Dec 04 2014 Paul Wouters - 3.12-2 +- Resolves: rhbz#1105171 (Update man page entry) +- Resolves: rhbz#1144120 (Update for ESP CAMELLIA with IKEv2) +- Resolves: rhbz#1074018 Audit key agreement + +* Fri Nov 07 2014 Paul Wouters - 3.12-1 +- Resolves: rhbz#1136124 rebase to libreswan 3.12 +- Resolves: rhbz#1052811 [TAHI] (also clear reserved flags for isakmp_sa header) +- Resolves: rhbz#1157379 [TAHI][IKEv2] IKEv2.EN.R.1.3.3.1: Non RESERVED fields in INFORMATIONAL request + +* Mon Oct 27 2014 Paul Wouters - 3.11-2 +- Resolves: rhbz#1136124 rebase to libreswan 3.11 (coverity fixup, dpdaction=clear fix) + +* Wed Oct 22 2014 Paul Wouters - 3.11-1 +- Resolves: rhbz#1136124 rebase to libreswan 3.11 +- Resolves: rhbz#1099905 ikev2 delete payloads are not delivered to peer +- Resolves: rhbz#1147693 NetworkManger-libreswan can not connect to Red Hat IPSec Xauth VPN +- Resolves: rhbz#1055865 [TAHI][IKEv2] libreswan do not ignore the content of version bit +- Resolves: rhbz#1146106 Pluto crashes after start when some ah algorithms are used +- Resolves: rhbz#1108256 addconn compatibility with openswan +- Resolves: rhbz#1152625 [TAHI][IKEv2] IKEv2.EN.I.1.1.6.2 Part D: Integrity Algorithm AUTH_AES_XCBC_96 fail +- Resolves: rhbz#1119704 [TAHI][IKEv2]IKEv2Interop.1.13a test fail +- Resolves: rhbz#1100261 libreswan does not send response when when it receives Delete Payload for a CHILD_SA +- Resolves: rhbz#1100239 ikev2 IKE SA responder does not send delete request to IKE SA initiator +- Resolves: rhbz#1052811 [TAHI][IKEv2]IKEv2.EN.I.1.1.11.1: Non zero RESERVED fields in IKE_SA_INIT response +- Resolves: rhbz#1126868 ikev2 sequence numbers are implemented incorrectly +- Resolves: rhbz#1145245 Libreswan appears to start with systemd before all the NICs are up and running. +- Resolves: rhbz#1145231 libreswan 3.10 upgrade breaks old ipsec.secrets configs +- Resolves: rhbz#1144123 Add ESP support for AES_XCBC hash for USGv6 and IPsec-v3 compliance +- Resolves: rhbz#1144120 Add ESP support for CAMELLIA for USGv6 and IPsec-v3 compliance +- Resolves: rhbz#1099877 Missing man-pages ipsec_whack, ipsec_manual +- Resolves: rhbz#1100255 libreswan Ikev2 implementation does not send an INFORMATIONAL response when it receives an INFORMATIONAL request with a Delete Payload for an IKE_SA + +* Tue Sep 09 2014 Paul Wouters - 3.10-3 +- Resolves: rhbz#1136124 rebase to 3.10 (auto=route bug on startup) + +* Mon Sep 08 2014 Paul Wouters - 3.10-2 +- Resolves: rhbz#1136124 rebase to libreswan 3.10 + +* Mon Jul 14 2014 Paul Wouters - 3.8-6 +- Resolves: rhbz#1092047 pluto cannot write to directories not owned by root * Thu Apr 10 2014 Paul Wouters - 3.8-5 - Resolves: rhbz#1052834 create_child_sa message ID handling