Navigation Menu

Skip to content

Commit

Permalink
IKEv2: Adds support for session resumption (rfc-5723)
Browse files Browse the repository at this point in the history
  • Loading branch information
murex971 committed Aug 31, 2020
1 parent 072f099 commit aac2a69
Show file tree
Hide file tree
Showing 37 changed files with 1,003 additions and 148 deletions.
8 changes: 8 additions & 0 deletions include/ike_alg_prf_ikev2_ops.h
Expand Up @@ -43,6 +43,14 @@ struct prf_ikev2_ops {
PK11SymKey *new_dh_secret,
const chunk_t Ni, const chunk_t Nr,
struct logger *logger);
/*
* IKEv2 - RFC5723 5.1 SKEYSEED - calculation
* SKEYSEED = prf(SK_d (old), "Resumption" | Ni | Nr)
*/
PK11SymKey *(*ike_sa_session_resume_skeyseed)(const struct prf_desc *prf_desc,
PK11SymKey *old_SK_d,
const chunk_t Ni, const chunk_t Nr,
struct logger *logger);
/* KEYMAT = prf+ (SKEYSEED, Ni | Nr | SPIi | SPIr) */
PK11SymKey *(*ike_sa_keymat)(const struct prf_desc *prf_desc,
PK11SymKey *skeyseed,
Expand Down
1 change: 1 addition & 0 deletions include/ipsecconf/keywords.h
Expand Up @@ -271,6 +271,7 @@ enum keyword_numeric_conn_field {
KNCF_NIC_OFFLOAD, /* xfrm offload to network device */
KNCF_TCP, /* TCP (yes/no/fallback) */
KNCF_REMOTE_TCPPORT, /* TCP remote port - default 4500 */
KNCF_SESSION_RESUME,

KNCF_ROOF
};
Expand Down
8 changes: 7 additions & 1 deletion include/pluto_constants.h
Expand Up @@ -10,6 +10,7 @@
* Copyright (C) 2017-2018 Sahana Prasad <sahana.prasad07@gmail.com>
* Copyright (C) 2017 Vukasin Karadzic <vukasin.karadzic@gmail.com>
* Copyright (C) 2019-2019 Andrew Cagney <cagney@gnu.org>
* Copyright (C) 2020 Nupur Agrawal <nupur202000@gmail.com>
*
* 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
Expand Down Expand Up @@ -504,12 +505,14 @@ enum state_kind {
/* IKE SA */

STATE_PARENT_I0 = STATE_IKEv2_FLOOR, /* waiting for KE to finish */
STATE_PARENT_RESUME_I0, /* resuming */
STATE_PARENT_I1, /* IKE_SA_INIT: sent initial message, waiting for reply */
STATE_PARENT_I2, /* IKE_AUTH: sent auth message, waiting for reply */

STATE_PARENT_R0, /* just starting */
STATE_PARENT_R1, /* IKE_SA_INIT: sent response */


STATE_V2_ESTABLISHED_IKE_SA,

/* IKE exchange can also create a child */
Expand Down Expand Up @@ -914,7 +917,9 @@ enum sa_policy_bits {
POLICY_ESN_NO_IX, /* send/accept ESNno */
POLICY_ESN_YES_IX, /* send/accept ESNyes */
POLICY_RSASIG_v1_5_IX,
#define POLICY_IX_LAST POLICY_RSASIG_v1_5_IX

POLICY_SESSION_RESUME_IX,
#define POLICY_IX_LAST POLICY_SESSION_RESUME_IX
};

#define POLICY_PSK LELEM(POLICY_PSK_IX)
Expand Down Expand Up @@ -965,6 +970,7 @@ enum sa_policy_bits {
#define POLICY_ESN_NO LELEM(POLICY_ESN_NO_IX) /* accept or request ESNno */
#define POLICY_ESN_YES LELEM(POLICY_ESN_YES_IX) /* accept or request ESNyes */
#define POLICY_RSASIG_v1_5 LELEM(POLICY_RSASIG_v1_5_IX)
#define POLICY_SESSION_RESUME LELEM(POLICY_SESSION_RESUME_IX)

#define NEGOTIATE_AUTH_HASH_SHA1 LELEM(IKEv2_HASH_ALGORITHM_SHA1) /* rfc7427 does responder support SHA1? */
#define NEGOTIATE_AUTH_HASH_SHA2_256 LELEM(IKEv2_HASH_ALGORITHM_SHA2_256) /* rfc7427 does responder support SHA2-256? */
Expand Down
3 changes: 3 additions & 0 deletions include/whack.h
Expand Up @@ -355,6 +355,9 @@ struct whack_message {

char *active_redirect_dests;

/* for RFC 5723 - IKEv2 Session Resumption */
bool whack_suspend;

/* what metric to put on ipsec routes */
int metric;

Expand Down
2 changes: 2 additions & 0 deletions lib/libipsecconf/confread.c
Expand Up @@ -1237,6 +1237,8 @@ static bool load_conn(struct starter_conn *conn,

KW_POLICY_FLAG(KNCF_MOBIKE, POLICY_MOBIKE);

KW_POLICY_FLAG(KNCF_SESSION_RESUME, POLICY_SESSION_RESUME);

KW_POLICY_FLAG(KNCF_IKEv2_PAM_AUTHORIZE,
POLICY_IKEV2_PAM_AUTHORIZE);

Expand Down
2 changes: 2 additions & 0 deletions lib/libipsecconf/keywords.c
Expand Up @@ -9,6 +9,7 @@
* Copyright (C) 2013-2016 Antony Antony <antony@phenome.org>
* Copyright (C) 2016-2019 Andrew Cagney <cagney@gnu.org>
* Copyright (C) 2017 Mayank Totale <mtotale@gmail.com>
* Copyright (C) 2020 Nupur Agrawal <nupur202000@gmail.com>
*
* 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
Expand Down Expand Up @@ -528,6 +529,7 @@ const struct keyword_def ipsec_conf_keywords[] = {
{ "accept-redirect", kv_conn, kt_enum, KNCF_ACCEPT_REDIRECT, &kw_yna_list, NULL, },
{ "accept-redirect-to", kv_conn, kt_string, KSCF_ACCEPT_REDIRECT_TO, NULL, NULL, },
{ "pfs", kv_conn, kt_bool, KNCF_PFS, NULL, NULL, },
{ "session-resumption", kv_conn, kt_bool, KNCF_SESSION_RESUME, NULL, NULL, },

{ "nat_keepalive", kv_conn | kv_alias, kt_bool, KNCF_NAT_KEEPALIVE, NULL, NULL, }, /* obsolete _ */
{ "nat-keepalive", kv_conn, kt_bool, KNCF_NAT_KEEPALIVE, NULL, NULL, },
Expand Down
1 change: 1 addition & 0 deletions lib/libswan/ike_alg.c
Expand Up @@ -515,6 +515,7 @@ static void prf_desc_check(const struct ike_alg *alg, struct logger *logger)
pexpect_ike_alg(logger, alg, prf->prf_ikev2_ops->prfplus != NULL);
pexpect_ike_alg(logger, alg, prf->prf_ikev2_ops->ike_sa_skeyseed != NULL);
pexpect_ike_alg(logger, alg, prf->prf_ikev2_ops->ike_sa_rekey_skeyseed != NULL);
pexpect_ike_alg(logger, alg, prf->prf_ikev2_ops->ike_sa_session_resume_skeyseed != NULL);
pexpect_ike_alg(logger, alg, prf->prf_ikev2_ops->ike_sa_keymat != NULL);
pexpect_ike_alg(logger, alg, prf->prf_ikev2_ops->child_sa_keymat != NULL);
pexpect_ike_alg(logger, alg, prf->prf_ikev2_ops->psk_auth != NULL);
Expand Down
29 changes: 29 additions & 0 deletions lib/libswan/ike_alg_prf_ikev2_mac_ops.c
Expand Up @@ -151,6 +151,34 @@ static PK11SymKey *ike_sa_rekey_skeyseed(const struct prf_desc *prf_desc,
return crypt_prf_final_symkey(&prf);
}

/*
* SKEYSEED = prf(SK_d (old), "Resumption" | Ni | Nr)
*/
static PK11SymKey *ike_sa_session_resume_skeyseed(const struct prf_desc *prf_desc,
PK11SymKey *SK_d_old,
const chunk_t Ni, const chunk_t Nr,
struct logger *logger)
{
/* key = SK_d (old) */
struct crypt_prf *prf = crypt_prf_init_symkey("ike sa session resume skeyseed", prf_desc,
"SK_d (old)", SK_d_old,
logger);

if (prf == NULL) {
pexpect_fail(logger, HERE,
"failed to create IKEv2 PRF for computing SKEYSEED = prf(SK_d (old), 'Resumption' | Ni | Nr)");
return NULL;
}

/* seed: 'resumption' | Ni | Nr) */
static const char sr_str[] = "Resumption";
crypt_prf_update_bytes(prf,sr_str, sr_str, sizeof(sr_str) - 1);
crypt_prf_update_hunk(prf, "Ni", Ni);
crypt_prf_update_hunk(prf, "Nr", Nr);
/* generate */
return crypt_prf_final_symkey(&prf);
}

/*
* Compute: prf+ (SKEYSEED, Ni | Nr | SPIi | SPIr)
*/
Expand Down Expand Up @@ -275,6 +303,7 @@ const struct prf_ikev2_ops ike_alg_prf_ikev2_mac_ops = {
.prfplus = prfplus,
.ike_sa_skeyseed = ike_sa_skeyseed,
.ike_sa_rekey_skeyseed = ike_sa_rekey_skeyseed,
.ike_sa_session_resume_skeyseed = ike_sa_session_resume_skeyseed,
.ike_sa_keymat = ike_sa_keymat,
.child_sa_keymat = child_sa_keymat,
.psk_auth = psk_auth,
Expand Down
1 change: 1 addition & 0 deletions programs/pluto/Makefile
Expand Up @@ -205,6 +205,7 @@ OBJS += ikev2_ecdsa.o ikev2_rsa.o ikev2_psk.o ikev2_ppk.o ikev2_crypto.o
OBJS += ikev2_redirect.o
OBJS += ikev1_prf.o
OBJS += ikev2_prf.o
OBJS += ikev2_resume.o
OBJS += cert_decode_helper.o
OBJS += kernel.o
OBJS += rcv_whack.o pluto_stats.o
Expand Down
5 changes: 3 additions & 2 deletions programs/pluto/connections.c
Expand Up @@ -4028,12 +4028,13 @@ void show_one_connection(struct show *s,
}

SHOW_JAMBUF(RC_COMMENT, s, buf) {
jam(buf, "\"%s\"%s: newest ISAKMP SA: #%lu; newest IPsec SA: #%lu; conn serial: "PRI_CO"",
jam(buf, "\"%s\"%s: newest ISAKMP SA: #%lu; newest IPsec SA: #%lu; conn serial: "PRI_CO"; ticket: %lubytes",
c->name,
instance,
c->newest_isakmp_sa,
c->newest_ipsec_sa,
pri_co(c->serialno));
pri_co(c->serialno),
c->temp_vars.ticket_variables.stored_ticket.len);
if (c->serial_from.co/*oops*/ != 0) {
jam(buf, ", instantiated from: "PRI_CO";",
pri_co(c->serial_from));
Expand Down
22 changes: 22 additions & 0 deletions programs/pluto/connections.h
Expand Up @@ -269,6 +269,28 @@ struct ephemeral_variables {
realtime_t first_redirect_time;
ip_address redirect_ip; /* where to redirect */
ip_address old_gw_address; /* address of old gateway */

/* this struct will be used for
* storing variables required for session
* resumption.
*/
struct {
unsigned long sr_serialco;
id_buf peer_id;

chunk_t sk_d_old;

int sr_encr;
int sr_prf;
int sr_integ;
int sr_dh;
int sr_enc_keylen;
enum keyword_authby sr_auth_method;

deltatime_t sr_server_expire;
deltatime_t sr_our_expire;
chunk_t stored_ticket;
} ticket_variables;
};

struct connection {
Expand Down
93 changes: 93 additions & 0 deletions programs/pluto/crypt_dh_v2.c
Expand Up @@ -34,6 +34,7 @@
#include "ikev2_prf.h"
#include "crypt_dh.h"
#include "state.h"
#include "connections.h"

void cancelled_dh_v2(struct pcr_dh_v2 *dh)
{
Expand Down Expand Up @@ -390,3 +391,95 @@ void calc_dh_v2(struct pluto_crypto_req *r, struct logger *logger)
&sk->skey_chunk_SK_pr, /* output */
logger);
}

bool skeyseed_v2_sr (struct state *st, PK11SymKey *sk_d_old, struct logger *logger)
{
PK11SymKey *skeyseed_k = ikev2_ike_sa_session_resume_skeyseed(st->st_oakley.ta_prf,
sk_d_old, st->st_ni, st->st_nr,
logger);

passert(skeyseed_k != NULL);
const size_t salt_size = st->st_oakley.ta_encrypt != NULL ?
st->st_oakley.ta_encrypt->salt_size : 0;
const size_t key_size = st->st_oakley.enckeylen / BITS_PER_BYTE;

const struct encrypt_desc *encrypter = st->st_oakley.ta_encrypt;

int skd_bytes = st->st_oakley.ta_prf->prf_key_size;
int skp_bytes = st->st_oakley.ta_prf->prf_key_size;
int integ_size = st->st_oakley.ta_integ ? st->st_oakley.ta_integ->integ_keymat_size : 0;
size_t total_keysize = skd_bytes + 2*skp_bytes + 2*key_size + 2*salt_size + 2*integ_size;
PK11SymKey *finalkey = ikev2_ike_sa_keymat(st->st_oakley.ta_prf, skeyseed_k,
st->st_ni, st->st_nr, &st->st_ike_spis,
total_keysize, logger);

size_t next_byte = 0;

st->st_skey_d_nss = key_from_symkey_bytes(finalkey, next_byte, skd_bytes,
HERE, logger);
next_byte += skd_bytes;

st->st_skey_ai_nss = key_from_symkey_bytes(finalkey, next_byte, integ_size,
HERE, logger);
next_byte += integ_size;

st->st_skey_ar_nss = key_from_symkey_bytes(finalkey, next_byte, integ_size,
HERE, logger);
next_byte += integ_size;

/* The encryption key and salt are extracted together. */

if (encrypter != NULL)
st->st_skey_ei_nss = encrypt_key_from_symkey_bytes("SK_ei_k",
encrypter,
next_byte, key_size,
finalkey,
HERE, logger);
else
st->st_skey_ei_nss = NULL;

next_byte += key_size;
PK11SymKey *initiator_salt_key = key_from_symkey_bytes(finalkey, next_byte,
salt_size,
HERE, logger);
st->st_skey_initiator_salt = chunk_from_symkey("initiator salt",
initiator_salt_key,
logger);
release_symkey(__func__, "initiator-salt-key", &initiator_salt_key);

next_byte += salt_size;

/* The encryption key and salt are extracted together. */
if (encrypter != NULL)
st->st_skey_ar_nss = encrypt_key_from_symkey_bytes("SK_er_k",
encrypter,
next_byte, key_size,
finalkey,
HERE, logger);
else
st->st_skey_ar_nss = NULL;

next_byte += key_size;
PK11SymKey *responder_salt_key = key_from_symkey_bytes(finalkey, next_byte,
salt_size,
HERE, logger);
st->st_skey_responder_salt = chunk_from_symkey("responder salt",
responder_salt_key,
logger);
release_symkey(__func__, "responder-salt-key", &responder_salt_key);
next_byte += salt_size;

st->st_skey_pi_nss = key_from_symkey_bytes(finalkey, next_byte, skp_bytes, HERE, logger);
st->st_skey_chunk_SK_pi = chunk_from_symkey("chunk_SK_pi", st->st_skey_pi_nss, logger);
next_byte += skp_bytes;

st->st_skey_pr_nss = key_from_symkey_bytes(finalkey, next_byte, skp_bytes, HERE, logger);
st->st_skey_chunk_SK_pr = chunk_from_symkey("chunk_SK_pr", st->st_skey_pr_nss, logger);

DBG(DBG_CRYPT,
DBG_log("NSS ikev2: finished computing individual keys for IKEv2 SA Session Resume"));
release_symkey(__func__, "finalkey", &finalkey);

st->hidden_variables.st_skeyid_calculated = TRUE;
return true;
}
5 changes: 5 additions & 0 deletions programs/pluto/demux.h
Expand Up @@ -110,6 +110,11 @@ enum v2_pbs {
PBS_v2N_INVALID_KE_PAYLOAD,
PBS_v2N_INVALID_MAJOR_VERSION,
PBS_v2N_TS_UNACCEPTABLE,
PBS_v2N_TICKET_LT_OPAQUE,
PBS_v2N_TICKET_REQUEST,
PBS_v2N_TICKET_ACK,
PBS_v2N_TICKET_NACK,
PBS_v2N_TICKET_OPAQUE,

PBS_v2_ROOF,
};
Expand Down

0 comments on commit aac2a69

Please sign in to comment.