Merge branch 'ikev2-ppk'

Adds support for Postquantum Preshared Keys for IKEv2.

Fixes #2710.
This commit is contained in:
Tobias Brunner
2018-09-10 18:05:12 +02:00
59 changed files with 1599 additions and 117 deletions
+5 -3
View File
@@ -385,8 +385,8 @@ METHOD(keymat_t, get_aead, aead_t*,
METHOD(keymat_v2_t, get_auth_octets, bool,
private_tkm_keymat_t *this, bool verify, chunk_t ike_sa_init,
chunk_t nonce, identification_t *id, char reserved[3], chunk_t *octets,
array_t *schemes)
chunk_t nonce, chunk_t ppk, identification_t *id, char reserved[3],
chunk_t *octets, array_t *schemes)
{
sign_info_t *sign;
@@ -428,7 +428,8 @@ METHOD(keymat_v2_t, get_skd, pseudo_random_function_t,
METHOD(keymat_v2_t, get_psk_sig, bool,
private_tkm_keymat_t *this, bool verify, chunk_t ike_sa_init, chunk_t nonce,
chunk_t secret, identification_t *id, char reserved[3], chunk_t *sig)
chunk_t secret, chunk_t ppk, identification_t *id, char reserved[3],
chunk_t *sig)
{
return FALSE;
}
@@ -522,6 +523,7 @@ tkm_keymat_t *tkm_keymat_create(bool initiator)
.destroy = _destroy,
},
.derive_ike_keys = _derive_ike_keys,
.derive_ike_keys_ppk = (void*)return_false,
.derive_child_keys = _derive_child_keys,
.get_skd = _get_skd,
.get_auth_octets = _get_auth_octets,
+2 -2
View File
@@ -237,8 +237,8 @@ static bool build_auth(private_pretend_auth_t *this,
return FALSE;
}
keymat = (keymat_v2_t*)ike_sa->get_keymat(ike_sa);
if (!keymat->get_auth_octets(keymat, TRUE, this->ike_init,
this->nonce, this->id, this->reserved,
if (!keymat->get_auth_octets(keymat, TRUE, this->ike_init, this->nonce,
chunk_empty, this->id, this->reserved,
&octets, NULL))
{
private->destroy(private);
+2 -2
View File
@@ -136,8 +136,8 @@ static bool rebuild_auth(private_rebuild_auth_t *this, ike_sa_t *ike_sa,
return FALSE;
}
keymat = (keymat_v2_t*)ike_sa->get_keymat(ike_sa);
if (!keymat->get_auth_octets(keymat, FALSE, this->ike_init,
this->nonce, id, reserved, &octets, NULL))
if (!keymat->get_auth_octets(keymat, FALSE, this->ike_init, this->nonce,
chunk_empty, id, reserved, &octets, NULL))
{
private->destroy(private);
id->destroy(id);
+40 -5
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2007-2017 Tobias Brunner
* Copyright (C) 2007-2018 Tobias Brunner
* Copyright (C) 2005-2009 Martin Willi
* Copyright (C) 2005 Jan Hutter
* HSR Hochschule fuer Technik Rapperswil
@@ -155,6 +155,16 @@ struct private_peer_cfg_t {
*/
linked_list_t *remote_auth;
/**
* PPK ID
*/
identification_t *ppk_id;
/**
* Whether a PPK is required
*/
bool ppk_required;
#ifdef ME
/**
* Is this a mediation connection?
@@ -577,6 +587,18 @@ METHOD(peer_cfg_t, create_auth_cfg_enumerator, enumerator_t*,
return this->remote_auth->create_enumerator(this->remote_auth);
}
METHOD(peer_cfg_t, get_ppk_id, identification_t*,
private_peer_cfg_t *this)
{
return this->ppk_id;
}
METHOD(peer_cfg_t, ppk_required, bool,
private_peer_cfg_t *this)
{
return this->ppk_required;
}
#ifdef ME
METHOD(peer_cfg_t, is_mediation, bool,
private_peer_cfg_t *this)
@@ -651,6 +673,14 @@ static bool auth_cfg_equal(private_peer_cfg_t *this, private_peer_cfg_t *other)
return equal;
}
/**
* Check if two identities are equal, or both are not set
*/
static bool id_equal(identification_t *this, identification_t *other)
{
return this == other || (this && other && this->equals(this, other));
}
METHOD(peer_cfg_t, equals, bool,
private_peer_cfg_t *this, private_peer_cfg_t *other)
{
@@ -684,13 +714,13 @@ METHOD(peer_cfg_t, equals, bool,
this->dpd == other->dpd &&
this->aggressive == other->aggressive &&
this->pull_mode == other->pull_mode &&
auth_cfg_equal(this, other)
auth_cfg_equal(this, other) &&
this->ppk_required == other->ppk_required &&
id_equal(this->ppk_id, other->ppk_id)
#ifdef ME
&& this->mediation == other->mediation &&
streq(this->mediated_by, other->mediated_by) &&
(this->peer_id == other->peer_id ||
(this->peer_id && other->peer_id &&
this->peer_id->equals(this->peer_id, other->peer_id)))
id_equal(this->peer_id, other->peer_id)
#endif /* ME */
);
}
@@ -720,6 +750,7 @@ METHOD(peer_cfg_t, destroy, void,
DESTROY_IF(this->peer_id);
free(this->mediated_by);
#endif /* ME */
DESTROY_IF(this->ppk_id);
this->lock->destroy(this->lock);
free(this->name);
free(this);
@@ -774,6 +805,8 @@ peer_cfg_t *peer_cfg_create(char *name, ike_cfg_t *ike_cfg,
.create_pool_enumerator = _create_pool_enumerator,
.add_auth_cfg = _add_auth_cfg,
.create_auth_cfg_enumerator = _create_auth_cfg_enumerator,
.get_ppk_id = _get_ppk_id,
.ppk_required = _ppk_required,
.equals = (void*)_equals,
.get_ref = _get_ref,
.destroy = _destroy,
@@ -799,6 +832,8 @@ peer_cfg_t *peer_cfg_create(char *name, ike_cfg_t *ike_cfg,
.pull_mode = !data->push_mode,
.dpd = data->dpd,
.dpd_timeout = data->dpd_timeout,
.ppk_id = data->ppk_id,
.ppk_required = data->ppk_required,
.vips = linked_list_create(),
.pools = linked_list_create(),
.local_auth = linked_list_create(),
+19 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2007-2017 Tobias Brunner
* Copyright (C) 2007-2018 Tobias Brunner
* Copyright (C) 2005-2009 Martin Willi
* Copyright (C) 2005 Jan Hutter
* HSR Hochschule fuer Technik Rapperswil
@@ -311,6 +311,20 @@ struct peer_cfg_t {
*/
enumerator_t* (*create_pool_enumerator)(peer_cfg_t *this);
/**
* Get the PPK ID to use with this peer.
*
* @return PPK id
*/
identification_t *(*get_ppk_id)(peer_cfg_t *this);
/**
* Whether a PPK is required with this peer.
*
* @return TRUE, if a PPK is required
*/
bool (*ppk_required)(peer_cfg_t *this);
#ifdef ME
/**
* Is this a mediation connection?
@@ -393,6 +407,10 @@ struct peer_cfg_create_t {
uint32_t dpd;
/** DPD timeout interval (IKEv1 only), if 0 default applies */
uint32_t dpd_timeout;
/** Postquantum Preshared Key ID (adopted) */
identification_t *ppk_id;
/** TRUE if a PPK is required, FALSE if it's optional */
bool ppk_required;
#ifdef ME
/** TRUE if this is a mediation connection */
bool mediation;
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2006-2018 Tobias Brunner
* Copyright (C) 2005-2010 Martin Willi
* Copyright (C) 2010 revosec AG
* Copyright (C) 2006-2008 Tobias Brunner
* Copyright (C) 2006 Daniel Roethlisberger
* Copyright (C) 2005 Jan Hutter
* HSR Hochschule fuer Technik Rapperswil
@@ -114,7 +114,11 @@ ENUM_NEXT(notify_type_names, INITIAL_CONTACT, SIGNATURE_HASH_ALGORITHMS, MS_NOTI
"SENDER_REQUEST_ID",
"FRAGMENTATION_SUPPORTED",
"SIGNATURE_HASH_ALGORITHMS");
ENUM_NEXT(notify_type_names, INITIAL_CONTACT_IKEV1, INITIAL_CONTACT_IKEV1, SIGNATURE_HASH_ALGORITHMS,
ENUM_NEXT(notify_type_names, USE_PPK, NO_PPK_AUTH, SIGNATURE_HASH_ALGORITHMS,
"USE_PPK",
"PPK_IDENTITY",
"NO_PPK_AUTH");
ENUM_NEXT(notify_type_names, INITIAL_CONTACT_IKEV1, INITIAL_CONTACT_IKEV1, NO_PPK_AUTH,
"INITIAL_CONTACT");
ENUM_NEXT(notify_type_names, DPD_R_U_THERE, DPD_R_U_THERE_ACK, INITIAL_CONTACT_IKEV1,
"DPD_R_U_THERE",
@@ -224,7 +228,11 @@ ENUM_NEXT(notify_type_short_names, INITIAL_CONTACT, SIGNATURE_HASH_ALGORITHMS, M
"SENDER_REQ_ID",
"FRAG_SUP",
"HASH_ALG");
ENUM_NEXT(notify_type_short_names, INITIAL_CONTACT_IKEV1, INITIAL_CONTACT_IKEV1, SIGNATURE_HASH_ALGORITHMS,
ENUM_NEXT(notify_type_short_names, USE_PPK, NO_PPK_AUTH, SIGNATURE_HASH_ALGORITHMS,
"USE_PPK",
"PPK_ID",
"NO_PPK");
ENUM_NEXT(notify_type_short_names, INITIAL_CONTACT_IKEV1, INITIAL_CONTACT_IKEV1, NO_PPK_AUTH,
"INITIAL_CONTACT");
ENUM_NEXT(notify_type_short_names, DPD_R_U_THERE, DPD_R_U_THERE_ACK, INITIAL_CONTACT_IKEV1,
"DPD",
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2006-2008 Tobias Brunner
* Copyright (C) 2006-2018 Tobias Brunner
* Copyright (C) 2006 Daniel Roethlisberger
* Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005 Jan Hutter
@@ -153,6 +153,12 @@ enum notify_type_t {
FRAGMENTATION_SUPPORTED = 16430,
/* Signature Hash Algorithms, RFC 7427 */
SIGNATURE_HASH_ALGORITHMS = 16431,
/* Use Postquantum Preshared Key (draft-ietf-ipsecme-qr-ikev2) */
USE_PPK = 16435,
/* Postquantum Preshared Key Identity (draft-ietf-ipsecme-qr-ikev2) */
PPK_IDENTITY = 16436,
/* No Postquantum Preshared Key Auth (draft-ietf-ipsecme-qr-ikev2) */
NO_PPK_AUTH = 16437,
/* IKEv1 initial contact */
INITIAL_CONTACT_IKEV1 = 24578,
/* IKEv1 DPD */
+12 -4
View File
@@ -2,7 +2,7 @@
* Copyright (C) 2014 Martin Willi
* Copyright (C) 2014 revosec AG
*
* Copyright (C) 2015-2017 Tobias Brunner
* Copyright (C) 2015-2018 Tobias Brunner
* Copyright (C) 2015-2018 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
@@ -304,6 +304,8 @@ typedef struct {
bool mobike;
bool send_certreq;
bool pull;
identification_t *ppk_id;
bool ppk_required;
cert_policy_t send_cert;
uint64_t dpd_delay;
uint64_t dpd_timeout;
@@ -403,6 +405,8 @@ static void log_peer_data(peer_data_t *data)
DBG2(DBG_CFG, " remote_port = %u", data->remote_port);
DBG2(DBG_CFG, " send_certreq = %u", data->send_certreq);
DBG2(DBG_CFG, " send_cert = %N", cert_policy_names, data->send_cert);
DBG2(DBG_CFG, " ppk_id = %Y", data->ppk_id);
DBG2(DBG_CFG, " ppk_required = %u", data->ppk_required);
DBG2(DBG_CFG, " mobike = %u", data->mobike);
DBG2(DBG_CFG, " aggressive = %u", data->aggressive);
DBG2(DBG_CFG, " dscp = 0x%.2x", data->dscp);
@@ -469,6 +473,7 @@ static void free_peer_data(peer_data_t *data)
free(data->pools);
free(data->local_addrs);
free(data->remote_addrs);
DESTROY_IF(data->ppk_id);
#ifdef ME
free(data->mediated_by);
DESTROY_IF(data->peer_id);
@@ -1584,9 +1589,8 @@ CALLBACK(parse_hosts, bool,
return TRUE;
}
#ifdef ME
/**
* Parse peer ID
* Parse peer/ppk ID
*/
CALLBACK(parse_peer_id, bool,
identification_t **out, chunk_t v)
@@ -1600,7 +1604,7 @@ CALLBACK(parse_peer_id, bool,
*out = identification_create_from_string(buf);
return TRUE;
}
#endif /* ME */
CALLBACK(cert_kv, bool,
cert_data_t *cert, vici_message_t *message, char *name, chunk_t value)
@@ -1744,6 +1748,8 @@ CALLBACK(peer_kv, bool,
{ "rekey_time", parse_time, &peer->rekey_time },
{ "over_time", parse_time, &peer->over_time },
{ "rand_time", parse_time, &peer->rand_time },
{ "ppk_id", parse_peer_id, &peer->ppk_id },
{ "ppk_required", parse_bool, &peer->ppk_required },
#ifdef ME
{ "mediation", parse_bool, &peer->mediation },
{ "mediated_by", parse_string, &peer->mediated_by },
@@ -2480,6 +2486,8 @@ CALLBACK(config_sn, bool,
.push_mode = !peer.pull,
.dpd = peer.dpd_delay,
.dpd_timeout = peer.dpd_timeout,
.ppk_id = peer.ppk_id ? peer.ppk_id->clone(peer.ppk_id) : NULL,
.ppk_required = peer.ppk_required,
};
#ifdef ME
cfg.mediation = peer.mediation;
+4
View File
@@ -442,6 +442,10 @@ CALLBACK(load_shared, vici_message_t*,
{
type = SHARED_NT_HASH;
}
else if (strcaseeq(str, "ppk"))
{
type = SHARED_PPK;
}
else
{
return create_reply("invalid shared key type: %s", str);
+12
View File
@@ -417,6 +417,7 @@ static void list_ike(private_vici_query_t *this, vici_builder_t *b,
b->add_kv(b, "dh-group", "%N", diffie_hellman_group_names, alg);
}
}
add_condition(b, ike_sa, "ppk", COND_PPK);
if (ike_sa->get_state(ike_sa) == IKE_ESTABLISHED)
{
@@ -787,6 +788,7 @@ CALLBACK(list_conns, vici_message_t*,
child_cfg_t *child_cfg;
char *ike, *str, *interface;
uint32_t manual_prio, dpd_delay, dpd_timeout;
identification_t *ppk_id;
linked_list_t *list;
traffic_selector_t *ts;
lifetime_cfg_t *lft;
@@ -849,6 +851,16 @@ CALLBACK(list_conns, vici_message_t*,
b->add_kv(b, "dpd_timeout", "%u", dpd_timeout);
}
ppk_id = peer_cfg->get_ppk_id(peer_cfg);
if (ppk_id)
{
b->add_kv(b, "ppk_id", "%Y", ppk_id);
}
if (peer_cfg->ppk_required(peer_cfg))
{
b->add_kv(b, "ppk_required", "yes");
}
build_auth_cfgs(peer_cfg, TRUE, b);
build_auth_cfgs(peer_cfg, FALSE, b);
+12 -1
View File
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2008-2018 Tobias Brunner
* Copyright (C) 2005-2009 Martin Willi
* Copyright (C) 2008 Tobias Brunner
* Copyright (C) 2005 Jan Hutter
* HSR Hochschule fuer Technik Rapperswil
*
@@ -156,6 +156,17 @@ struct authenticator_t {
*/
status_t (*build)(authenticator_t *this, message_t *message);
/**
* Optional method to set a Postquantum Preshared Key (PPK) to be used
* during authentication.
*
* Has to be called before the final call to process()/build().
*
* @param ppk PPK to use
* @param no_ppk_auth whether to add a NO_PPK_AUTH notify in build()
*/
void (*use_ppk)(authenticator_t *this, chunk_t ppk, bool no_ppk_auth);
/**
* Check if the authenticator is capable of mutual authentication.
*
+10
View File
@@ -156,6 +156,11 @@ enum ike_extension_t {
* IKEv2 Message ID sync, RFC 6311
*/
EXT_IKE_MESSAGE_ID_SYNC = (1<<14),
/**
* Postquantum Preshared Keys, draft-ietf-ipsecme-qr-ikev2
*/
EXT_PPK = (1<<15),
};
/**
@@ -227,6 +232,11 @@ enum ike_condition_t {
* Online certificate revocation checking is suspended for this IKE_SA
*/
COND_ONLINE_VALIDATION_SUSPENDED = (1<<12),
/**
* A Postquantum Preshared Key was used when this IKE_SA was created
*/
COND_PPK = (1<<13),
};
/**
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2012 Tobias Brunner
* Copyright (C) 2012-2018 Tobias Brunner
* Copyright (C) 2006-2009 Martin Willi
* HSR Hochschule fuer Technik Rapperswil
*
@@ -64,6 +64,16 @@ struct private_eap_authenticator_t {
*/
char reserved[3];
/**
* PPK to use
*/
chunk_t ppk;
/**
* Add a NO_PPK_AUTH notify
*/
bool no_ppk_auth;
/**
* Current EAP method processing
*/
@@ -444,6 +454,7 @@ static bool verify_auth(private_eap_authenticator_t *this, message_t *message,
chunk_t nonce, chunk_t init)
{
auth_payload_t *auth_payload;
notify_payload_t *notify;
chunk_t auth_data, recv_auth_data;
identification_t *other_id;
auth_cfg_t *auth;
@@ -458,14 +469,26 @@ static bool verify_auth(private_eap_authenticator_t *this, message_t *message,
DBG1(DBG_IKE, "AUTH payload missing");
return FALSE;
}
recv_auth_data = auth_payload->get_data(auth_payload);
if (this->ike_sa->supports_extension(this->ike_sa, EXT_PPK) &&
!this->ppk.ptr)
{ /* look for a NO_PPK_AUTH notify if we have no PPK */
notify = message->get_notify(message, NO_PPK_AUTH);
if (notify)
{
DBG1(DBG_IKE, "no PPK available, using NO_PPK_AUTH notify");
recv_auth_data = notify->get_notification_data(notify);
}
}
other_id = this->ike_sa->get_other_id(this->ike_sa);
keymat = (keymat_v2_t*)this->ike_sa->get_keymat(this->ike_sa);
if (!keymat->get_psk_sig(keymat, TRUE, init, nonce,
this->msk, other_id, this->reserved, &auth_data))
if (!keymat->get_psk_sig(keymat, TRUE, init, nonce, this->msk, this->ppk,
other_id, this->reserved, &auth_data))
{
return FALSE;
}
recv_auth_data = auth_payload->get_data(auth_payload);
if (!auth_data.len || !chunk_equals_const(auth_data, recv_auth_data))
{
DBG1(DBG_IKE, "verification of AUTH payload with%s EAP MSK failed",
@@ -507,8 +530,8 @@ static bool build_auth(private_eap_authenticator_t *this, message_t *message,
DBG1(DBG_IKE, "authentication of '%Y' (myself) with %N",
my_id, auth_class_names, AUTH_CLASS_EAP);
if (!keymat->get_psk_sig(keymat, FALSE, init, nonce,
this->msk, my_id, this->reserved, &auth_data))
if (!keymat->get_psk_sig(keymat, FALSE, init, nonce, this->msk, this->ppk,
my_id, this->reserved, &auth_data))
{
return FALSE;
}
@@ -517,6 +540,18 @@ static bool build_auth(private_eap_authenticator_t *this, message_t *message,
auth_payload->set_data(auth_payload, auth_data);
message->add_payload(message, (payload_t*)auth_payload);
chunk_free(&auth_data);
if (this->no_ppk_auth)
{
if (!keymat->get_psk_sig(keymat, FALSE, init, nonce, this->msk,
chunk_empty, my_id, this->reserved, &auth_data))
{
DBG1(DBG_IKE, "failed adding NO_PPK_AUTH notify");
return FALSE;
}
message->add_notify(message, FALSE, NO_PPK_AUTH, auth_data);
chunk_free(&auth_data);
}
return TRUE;
}
@@ -698,6 +733,13 @@ METHOD(authenticator_t, is_mutual, bool,
return TRUE;
}
METHOD(authenticator_t, use_ppk, void,
private_eap_authenticator_t *this, chunk_t ppk, bool no_ppk_auth)
{
this->ppk = ppk;
this->no_ppk_auth = no_ppk_auth;
}
METHOD(authenticator_t, destroy, void,
private_eap_authenticator_t *this)
{
@@ -723,6 +765,7 @@ eap_authenticator_t *eap_authenticator_create_builder(ike_sa_t *ike_sa,
.authenticator = {
.build = _build_client,
.process = _process_client,
.use_ppk = _use_ppk,
.is_mutual = _is_mutual,
.destroy = _destroy,
},
@@ -753,6 +796,7 @@ eap_authenticator_t *eap_authenticator_create_verifier(ike_sa_t *ike_sa,
.authenticator = {
.build = _build_server,
.process = _process_server,
.use_ppk = _use_ppk,
.is_mutual = _is_mutual,
.destroy = _destroy,
},
@@ -1,4 +1,5 @@
/*
* Copyright (C) 2018 Tobias Brunner
* Copyright (C) 2005-2009 Martin Willi
* Copyright (C) 2005 Jan Hutter
* HSR Hochschule fuer Technik Rapperswil
@@ -51,6 +52,16 @@ struct private_psk_authenticator_t {
* Reserved bytes of ID payload
*/
char reserved[3];
/**
* PPK to use
*/
chunk_t ppk;
/**
* Add a NO_PPK_AUTH notify
*/
bool no_ppk_auth;
};
METHOD(authenticator_t, build, status_t,
@@ -68,18 +79,19 @@ METHOD(authenticator_t, build, status_t,
DBG1(DBG_IKE, "authentication of '%Y' (myself) with %N",
my_id, auth_method_names, AUTH_PSK);
key = lib->credmgr->get_shared(lib->credmgr, SHARED_IKE, my_id, other_id);
if (key == NULL)
if (!key)
{
DBG1(DBG_IKE, "no shared key found for '%Y' - '%Y'", my_id, other_id);
return NOT_FOUND;
}
if (!keymat->get_psk_sig(keymat, FALSE, this->ike_sa_init, this->nonce,
key->get_key(key), my_id, this->reserved, &auth_data))
key->get_key(key), this->ppk, my_id,
this->reserved, &auth_data))
{
key->destroy(key);
return FAILED;
}
key->destroy(key);
DBG2(DBG_IKE, "successfully created shared key MAC");
auth_payload = auth_payload_create();
auth_payload->set_auth_method(auth_payload, AUTH_PSK);
@@ -87,6 +99,21 @@ METHOD(authenticator_t, build, status_t,
chunk_free(&auth_data);
message->add_payload(message, (payload_t*)auth_payload);
if (this->no_ppk_auth)
{
if (!keymat->get_psk_sig(keymat, FALSE, this->ike_sa_init, this->nonce,
key->get_key(key), chunk_empty, my_id,
this->reserved, &auth_data))
{
DBG1(DBG_IKE, "failed adding NO_PPK_AUTH notify");
key->destroy(key);
return SUCCESS;
}
DBG2(DBG_IKE, "successfully created shared key MAC without PPK");
message->add_notify(message, FALSE, NO_PPK_AUTH, auth_data);
chunk_free(&auth_data);
}
key->destroy(key);
return SUCCESS;
}
@@ -96,6 +123,7 @@ METHOD(authenticator_t, process, status_t,
chunk_t auth_data, recv_auth_data;
identification_t *my_id, *other_id;
auth_payload_t *auth_payload;
notify_payload_t *notify;
auth_cfg_t *auth;
shared_key_t *key;
enumerator_t *enumerator;
@@ -108,8 +136,20 @@ METHOD(authenticator_t, process, status_t,
{
return FAILED;
}
keymat = (keymat_v2_t*)this->ike_sa->get_keymat(this->ike_sa);
recv_auth_data = auth_payload->get_data(auth_payload);
if (this->ike_sa->supports_extension(this->ike_sa, EXT_PPK) &&
!this->ppk.ptr)
{ /* look for a NO_PPK_AUTH notify if we have no PPK */
notify = message->get_notify(message, NO_PPK_AUTH);
if (notify)
{
DBG1(DBG_IKE, "no PPK available, using NO_PPK_AUTH notify");
recv_auth_data = notify->get_notification_data(notify);
}
}
keymat = (keymat_v2_t*)this->ike_sa->get_keymat(this->ike_sa);
my_id = this->ike_sa->get_my_id(this->ike_sa);
other_id = this->ike_sa->get_other_id(this->ike_sa);
enumerator = lib->credmgr->create_shared_enumerator(lib->credmgr,
@@ -119,7 +159,8 @@ METHOD(authenticator_t, process, status_t,
keys_found++;
if (!keymat->get_psk_sig(keymat, TRUE, this->ike_sa_init, this->nonce,
key->get_key(key), other_id, this->reserved, &auth_data))
key->get_key(key), this->ppk, other_id,
this->reserved, &auth_data))
{
continue;
}
@@ -150,6 +191,13 @@ METHOD(authenticator_t, process, status_t,
return SUCCESS;
}
METHOD(authenticator_t, use_ppk, void,
private_psk_authenticator_t *this, chunk_t ppk, bool no_ppk_auth)
{
this->ppk = ppk;
this->no_ppk_auth = no_ppk_auth;
}
METHOD(authenticator_t, destroy, void,
private_psk_authenticator_t *this)
{
@@ -170,6 +218,7 @@ psk_authenticator_t *psk_authenticator_create_builder(ike_sa_t *ike_sa,
.authenticator = {
.build = _build,
.process = (void*)return_failed,
.use_ppk = _use_ppk,
.is_mutual = (void*)return_false,
.destroy = _destroy,
},
@@ -197,6 +246,7 @@ psk_authenticator_t *psk_authenticator_create_verifier(ike_sa_t *ike_sa,
.authenticator = {
.build = (void*)return_failed,
.process = _process,
.use_ppk = _use_ppk,
.is_mutual = (void*)return_false,
.destroy = _destroy,
},
@@ -56,6 +56,16 @@ struct private_pubkey_authenticator_t {
* Reserved bytes of ID payload
*/
char reserved[3];
/**
* PPK to use
*/
chunk_t ppk;
/**
* Add a NO_PPK_AUTH notify
*/
bool no_ppk_auth;
};
/**
@@ -203,18 +213,43 @@ CALLBACK(destroy_scheme, void,
signature_params_destroy(params);
}
/**
* Adds the given auth data to the message, either in an AUTH payload or
* a NO_PPK_AUTH notify.
*
* The data is freed.
*/
static void add_auth_to_message(message_t *message, auth_method_t method,
chunk_t data, bool notify)
{
auth_payload_t *auth_payload;
if (notify)
{
message->add_notify(message, FALSE, NO_PPK_AUTH, data);
}
else
{
auth_payload = auth_payload_create();
auth_payload->set_auth_method(auth_payload, method);
auth_payload->set_data(auth_payload, data);
message->add_payload(message, (payload_t*)auth_payload);
}
chunk_free(&data);
}
/**
* Create a signature using RFC 7427 signature authentication
*/
static status_t sign_signature_auth(private_pubkey_authenticator_t *this,
auth_cfg_t *auth, private_key_t *private,
identification_t *id, chunk_t *auth_data)
auth_cfg_t *auth, private_key_t *private,
identification_t *id, message_t *message)
{
enumerator_t *enumerator;
keymat_v2_t *keymat;
signature_params_t *params = NULL;
array_t *schemes;
chunk_t octets = chunk_empty;
chunk_t octets = chunk_empty, auth_data;
status_t status = FAILED;
keymat = (keymat_v2_t*)this->ike_sa->get_keymat(this->ike_sa);
@@ -227,26 +262,46 @@ static status_t sign_signature_auth(private_pubkey_authenticator_t *this,
return FAILED;
}
if (keymat->get_auth_octets(keymat, FALSE, this->ike_sa_init,
this->nonce, id, this->reserved, &octets,
schemes))
if (keymat->get_auth_octets(keymat, FALSE, this->ike_sa_init, this->nonce,
this->ppk, id, this->reserved, &octets, schemes))
{
enumerator = array_create_enumerator(schemes);
while (enumerator->enumerate(enumerator, &params))
{
if (private->sign(private, params->scheme, params->params, octets,
auth_data) &&
build_signature_auth_data(auth_data, params))
{
status = SUCCESS;
break;
}
else
if (!private->sign(private, params->scheme, params->params, octets,
&auth_data) ||
!build_signature_auth_data(&auth_data, params))
{
DBG2(DBG_IKE, "unable to create %N signature for %N key",
signature_scheme_names, params->scheme, key_type_names,
private->get_type(private));
continue;
}
add_auth_to_message(message, AUTH_DS, auth_data, FALSE);
status = SUCCESS;
if (this->no_ppk_auth)
{
chunk_free(&octets);
if (keymat->get_auth_octets(keymat, FALSE, this->ike_sa_init,
this->nonce, chunk_empty, id,
this->reserved, &octets, schemes) &&
private->sign(private, params->scheme, params->params,
octets, &auth_data) &&
build_signature_auth_data(&auth_data, params))
{
add_auth_to_message(message, AUTH_DS, auth_data, TRUE);
}
else
{
DBG2(DBG_IKE, "unable to create %N signature for %N key "
"without PPK", signature_scheme_names, params->scheme,
key_type_names, private->get_type(private));
status = FAILED;
}
}
break;
}
enumerator->destroy(enumerator);
}
@@ -281,8 +336,8 @@ static status_t sign_signature_auth(private_pubkey_authenticator_t *this,
* keymat).
*/
static bool get_auth_octets_scheme(private_pubkey_authenticator_t *this,
bool verify, identification_t *id,
chunk_t *octets, signature_params_t **scheme)
bool verify, identification_t *id, chunk_t ppk,
chunk_t *octets, signature_params_t **scheme)
{
keymat_v2_t *keymat;
array_t *schemes;
@@ -293,7 +348,8 @@ static bool get_auth_octets_scheme(private_pubkey_authenticator_t *this,
keymat = (keymat_v2_t*)this->ike_sa->get_keymat(this->ike_sa);
if (keymat->get_auth_octets(keymat, verify, this->ike_sa_init, this->nonce,
id, this->reserved, octets, schemes) &&
ppk, id, this->reserved, octets,
schemes) &&
array_remove(schemes, 0, scheme))
{
success = TRUE;
@@ -311,19 +367,19 @@ static bool get_auth_octets_scheme(private_pubkey_authenticator_t *this,
*/
static status_t sign_classic(private_pubkey_authenticator_t *this,
auth_cfg_t *auth, private_key_t *private,
identification_t *id, auth_method_t *auth_method,
chunk_t *auth_data)
identification_t *id, message_t *message)
{
signature_scheme_t scheme;
signature_params_t *params;
chunk_t octets = chunk_empty;
auth_method_t auth_method = AUTH_NONE;
chunk_t octets = chunk_empty, auth_data;
status_t status = FAILED;
switch (private->get_type(private))
{
case KEY_RSA:
scheme = SIGN_RSA_EMSA_PKCS1_SHA1;
*auth_method = AUTH_RSA;
auth_method = AUTH_RSA;
break;
case KEY_ECDSA:
/* deduct the signature scheme from the keysize */
@@ -331,15 +387,15 @@ static status_t sign_classic(private_pubkey_authenticator_t *this,
{
case 256:
scheme = SIGN_ECDSA_256;
*auth_method = AUTH_ECDSA_256;
auth_method = AUTH_ECDSA_256;
break;
case 384:
scheme = SIGN_ECDSA_384;
*auth_method = AUTH_ECDSA_384;
auth_method = AUTH_ECDSA_384;
break;
case 521:
scheme = SIGN_ECDSA_521;
*auth_method = AUTH_ECDSA_521;
auth_method = AUTH_ECDSA_521;
break;
default:
DBG1(DBG_IKE, "%d bit ECDSA private key size not supported",
@@ -356,17 +412,34 @@ static status_t sign_classic(private_pubkey_authenticator_t *this,
INIT(params,
.scheme = scheme,
);
if (get_auth_octets_scheme(this, FALSE, id, &octets, &params) &&
private->sign(private, params->scheme, NULL, octets, auth_data))
if (get_auth_octets_scheme(this, FALSE, id, this->ppk, &octets, &params) &&
private->sign(private, params->scheme, NULL, octets, &auth_data))
{
add_auth_to_message(message, auth_method, auth_data, FALSE);
status = SUCCESS;
if (this->no_ppk_auth)
{
chunk_free(&octets);
if (get_auth_octets_scheme(this, FALSE, id, chunk_empty, &octets,
&params) &&
private->sign(private, params->scheme, NULL, octets,
&auth_data))
{
add_auth_to_message(message, auth_method, auth_data, TRUE);
}
else
{
status = FAILED;
}
}
}
if (params)
{
signature_params_destroy(params);
}
DBG1(DBG_IKE, "authentication of '%Y' (myself) with %N %s", id,
auth_method_names, *auth_method,
auth_method_names, auth_method,
status == SUCCESS ? "successful" : "failed");
chunk_free(&octets);
return status;
@@ -378,10 +451,7 @@ METHOD(authenticator_t, build, status_t,
private_key_t *private;
identification_t *id;
auth_cfg_t *auth;
chunk_t auth_data;
status_t status;
auth_payload_t *auth_payload;
auth_method_t auth_method = AUTH_NONE;
id = this->ike_sa->get_my_id(this->ike_sa);
auth = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
@@ -394,24 +464,13 @@ METHOD(authenticator_t, build, status_t,
if (this->ike_sa->supports_extension(this->ike_sa, EXT_SIGNATURE_AUTH))
{
auth_method = AUTH_DS;
status = sign_signature_auth(this, auth, private, id, &auth_data);
status = sign_signature_auth(this, auth, private, id, message);
}
else
{
status = sign_classic(this, auth, private, id, &auth_method,
&auth_data);
status = sign_classic(this, auth, private, id, message);
}
private->destroy(private);
if (status == SUCCESS)
{
auth_payload = auth_payload_create();
auth_payload->set_auth_method(auth_payload, auth_method);
auth_payload->set_data(auth_payload, auth_data);
chunk_free(&auth_data);
message->add_payload(message, (payload_t*)auth_payload);
}
return status;
}
@@ -444,6 +503,7 @@ METHOD(authenticator_t, process, status_t,
public_key_t *public;
auth_method_t auth_method;
auth_payload_t *auth_payload;
notify_payload_t *notify;
chunk_t auth_data, octets;
identification_t *id;
auth_cfg_t *auth, *current_auth;
@@ -459,9 +519,21 @@ METHOD(authenticator_t, process, status_t,
{
return FAILED;
}
INIT(params);
auth_method = auth_payload->get_auth_method(auth_payload);
auth_data = auth_payload->get_data(auth_payload);
if (this->ike_sa->supports_extension(this->ike_sa, EXT_PPK) &&
!this->ppk.ptr)
{ /* look for a NO_PPK_AUTH notify if we have no PPK */
notify = message->get_notify(message, NO_PPK_AUTH);
if (notify)
{
DBG1(DBG_IKE, "no PPK available, using NO_PPK_AUTH notify");
auth_data = notify->get_notification_data(notify);
}
}
INIT(params);
switch (auth_method)
{
case AUTH_RSA:
@@ -491,7 +563,7 @@ METHOD(authenticator_t, process, status_t,
return INVALID_ARG;
}
id = this->ike_sa->get_other_id(this->ike_sa);
if (!get_auth_octets_scheme(this, TRUE, id, &octets, &params))
if (!get_auth_octets_scheme(this, TRUE, id, this->ppk, &octets, &params))
{
return FAILED;
}
@@ -551,6 +623,13 @@ METHOD(authenticator_t, process, status_t,
return status;
}
METHOD(authenticator_t, use_ppk, void,
private_pubkey_authenticator_t *this, chunk_t ppk, bool no_ppk_auth)
{
this->ppk = ppk;
this->no_ppk_auth = no_ppk_auth;
}
METHOD(authenticator_t, destroy, void,
private_pubkey_authenticator_t *this)
{
@@ -571,6 +650,7 @@ pubkey_authenticator_t *pubkey_authenticator_create_builder(ike_sa_t *ike_sa,
.authenticator = {
.build = _build,
.process = (void*)return_failed,
.use_ppk = _use_ppk,
.is_mutual = (void*)return_false,
.destroy = _destroy,
},
@@ -598,6 +678,7 @@ pubkey_authenticator_t *pubkey_authenticator_create_verifier(ike_sa_t *ike_sa,
.authenticator = {
.build = (void*)return_failed,
.process = _process,
.use_ppk = _use_ppk,
.is_mutual = (void*)return_false,
.destroy = _destroy,
},
+124 -12
View File
@@ -491,6 +491,93 @@ failure:
return this->skp_build.len && this->skp_verify.len;
}
/**
* Derives a key from the given key and a PRF that was initialized with a PPK
*/
static bool derive_ppk_key(prf_t *prf, char *name, chunk_t key,
chunk_t *new_key)
{
prf_plus_t *prf_plus;
prf_plus = prf_plus_create(prf, TRUE, key);
if (!prf_plus ||
!prf_plus->allocate_bytes(prf_plus, key.len, new_key))
{
DBG1(DBG_IKE, "unable to derive %s with PPK", name);
DESTROY_IF(prf_plus);
return FALSE;
}
prf_plus->destroy(prf_plus);
return TRUE;
}
/**
* Use the given PPK to derive a new SK_pi/r
*/
static bool derive_skp_ppk(private_keymat_v2_t *this, chunk_t ppk, chunk_t skp,
chunk_t *new_skp)
{
if (!this->prf->set_key(this->prf, ppk))
{
DBG1(DBG_IKE, "unable to set PPK in PRF");
return FALSE;
}
return derive_ppk_key(this->prf, "SK_p", skp, new_skp);
}
METHOD(keymat_v2_t, derive_ike_keys_ppk, bool,
private_keymat_v2_t *this, chunk_t ppk)
{
chunk_t skd = chunk_empty, new_skpi = chunk_empty, new_skpr = chunk_empty;
chunk_t *skpi, *skpr;
if (!this->skd.ptr)
{
return FALSE;
}
if (this->initiator)
{
skpi = &this->skp_build;
skpr = &this->skp_verify;
}
else
{
skpi = &this->skp_verify;
skpr = &this->skp_build;
}
DBG4(DBG_IKE, "derive keys using PPK %B", &ppk);
if (!this->prf->set_key(this->prf, ppk))
{
DBG1(DBG_IKE, "unable to set PPK in PRF");
return FALSE;
}
if (!derive_ppk_key(this->prf, "Sk_d", this->skd, &skd) ||
!derive_ppk_key(this->prf, "Sk_pi", *skpi, &new_skpi) ||
!derive_ppk_key(this->prf, "Sk_pr", *skpr, &new_skpr))
{
chunk_clear(&skd);
chunk_clear(&new_skpi);
chunk_clear(&new_skpr);
return FALSE;
}
DBG4(DBG_IKE, "Sk_d secret %B", &skd);
chunk_clear(&this->skd);
this->skd = skd;
DBG4(DBG_IKE, "Sk_pi secret %B", &new_skpi);
chunk_clear(skpi);
*skpi = new_skpi;
DBG4(DBG_IKE, "Sk_pr secret %B", &new_skpr);
chunk_clear(skpr);
*skpr = new_skpr;
return TRUE;
}
METHOD(keymat_v2_t, derive_child_keys, bool,
private_keymat_v2_t *this, proposal_t *proposal, diffie_hellman_t *dh,
chunk_t nonce_i, chunk_t nonce_r, chunk_t *encr_i, chunk_t *integ_i,
@@ -632,13 +719,23 @@ METHOD(keymat_t, get_aead, aead_t*,
METHOD(keymat_v2_t, get_auth_octets, bool,
private_keymat_v2_t *this, bool verify, chunk_t ike_sa_init,
chunk_t nonce, identification_t *id, char reserved[3], chunk_t *octets,
array_t *schemes)
chunk_t nonce, chunk_t ppk, identification_t *id, char reserved[3],
chunk_t *octets, array_t *schemes)
{
chunk_t chunk, idx;
chunk_t skp_ppk = chunk_empty;
chunk_t skp;
skp = verify ? this->skp_verify : this->skp_build;
if (ppk.ptr)
{
DBG4(DBG_IKE, "PPK %B", &ppk);
if (!derive_skp_ppk(this, ppk, skp, &skp_ppk))
{
return FALSE;
}
skp = skp_ppk;
}
chunk = chunk_alloca(4);
chunk.ptr[0] = id->get_type(id);
@@ -650,8 +747,10 @@ METHOD(keymat_v2_t, get_auth_octets, bool,
if (!this->prf->set_key(this->prf, skp) ||
!this->prf->allocate_bytes(this->prf, idx, &chunk))
{
chunk_clear(&skp_ppk);
return FALSE;
}
chunk_clear(&skp_ppk);
*octets = chunk_cat("ccm", ike_sa_init, nonce, chunk);
DBG3(DBG_IKE, "octets = message + nonce + prf(Sk_px, IDx') %B", octets);
return TRUE;
@@ -665,41 +764,53 @@ METHOD(keymat_v2_t, get_auth_octets, bool,
METHOD(keymat_v2_t, get_psk_sig, bool,
private_keymat_v2_t *this, bool verify, chunk_t ike_sa_init, chunk_t nonce,
chunk_t secret, identification_t *id, char reserved[3], chunk_t *sig)
chunk_t secret, chunk_t ppk, identification_t *id, char reserved[3],
chunk_t *sig)
{
chunk_t key_pad, key, octets;
chunk_t skp_ppk = chunk_empty, key = chunk_empty, octets = chunk_empty;
chunk_t key_pad;
bool success = FALSE;
if (!secret.len)
{ /* EAP uses SK_p if no MSK has been established */
secret = verify ? this->skp_verify : this->skp_build;
if (ppk.ptr)
{
if (!derive_skp_ppk(this, ppk, secret, &skp_ppk))
{
return FALSE;
}
secret = skp_ppk;
}
}
if (!get_auth_octets(this, verify, ike_sa_init, nonce, id, reserved,
if (!get_auth_octets(this, verify, ike_sa_init, nonce, ppk, id, reserved,
&octets, NULL))
{
return FALSE;
goto failure;
}
/* AUTH = prf(prf(Shared Secret,"Key Pad for IKEv2"), <msg octets>) */
key_pad = chunk_create(IKEV2_KEY_PAD, IKEV2_KEY_PAD_LENGTH);
if (!this->prf->set_key(this->prf, secret) ||
!this->prf->allocate_bytes(this->prf, key_pad, &key))
{
chunk_free(&octets);
return FALSE;
goto failure;
}
if (!this->prf->set_key(this->prf, key) ||
!this->prf->allocate_bytes(this->prf, octets, sig))
{
chunk_free(&key);
chunk_free(&octets);
return FALSE;
goto failure;
}
DBG4(DBG_IKE, "secret %B", &secret);
DBG4(DBG_IKE, "prf(secret, keypad) %B", &key);
DBG3(DBG_IKE, "AUTH = prf(prf(secret, keypad), octets) %B", sig);
success = TRUE;
failure:
chunk_clear(&skp_ppk);
chunk_free(&octets);
chunk_free(&key);
return success;
return TRUE;
}
METHOD(keymat_v2_t, hash_algorithm_supported, bool,
@@ -752,6 +863,7 @@ keymat_v2_t *keymat_v2_create(bool initiator)
.destroy = _destroy,
},
.derive_ike_keys = _derive_ike_keys,
.derive_ike_keys_ppk = _derive_ike_keys_ppk,
.derive_child_keys = _derive_child_keys,
.get_skd = _get_skd,
.get_auth_octets = _get_auth_octets,
+16 -4
View File
@@ -57,6 +57,16 @@ struct keymat_v2_t {
pseudo_random_function_t rekey_function,
chunk_t rekey_skd);
/**
* Derive SK_d, SK_pi and SK_pr after authentication using the given
* Postquantum Preshared Key and the previous values of these keys that
* were derived by derive_ike_keys().
*
* @param ppk the postquantum preshared key
* @return TRUE on success
*/
bool (*derive_ike_keys_ppk)(keymat_v2_t *this, chunk_t ppk);
/**
* Derive keys for a CHILD_SA.
*
@@ -95,9 +105,10 @@ struct keymat_v2_t {
* key. PSK and EAP authentication include a secret into the data, use
* the get_psk_sig() method instead.
*
* @param verify TRUE to create for verfification, FALSE to sign
* @param verify TRUE to create for verification, FALSE to sign
* @param ike_sa_init encoded ike_sa_init message
* @param nonce nonce value
* @param ppk optional postquantum preshared key
* @param id identity
* @param reserved reserved bytes of id_payload
* @param octests chunk receiving allocated auth octets
@@ -107,7 +118,7 @@ struct keymat_v2_t {
* @return TRUE if octets created successfully
*/
bool (*get_auth_octets)(keymat_v2_t *this, bool verify, chunk_t ike_sa_init,
chunk_t nonce, identification_t *id,
chunk_t nonce, chunk_t ppk, identification_t *id,
char reserved[3], chunk_t *octets,
array_t *schemes);
/**
@@ -117,17 +128,18 @@ struct keymat_v2_t {
* includes the secret into the signature. If no secret is given, SK_p is
* used as secret (used for EAP methods without MSK).
*
* @param verify TRUE to create for verfification, FALSE to sign
* @param verify TRUE to create for verification, FALSE to sign
* @param ike_sa_init encoded ike_sa_init message
* @param nonce nonce value
* @param secret optional secret to include into signature
* @param ppk optional postquantum preshared key
* @param id identity
* @param reserved reserved bytes of id_payload
* @param sign chunk receiving allocated signature octets
* @return TRUE if signature created successfully
*/
bool (*get_psk_sig)(keymat_v2_t *this, bool verify, chunk_t ike_sa_init,
chunk_t nonce, chunk_t secret,
chunk_t nonce, chunk_t secret, chunk_t ppk,
identification_t *id, char reserved[3], chunk_t *sig);
/**
+316 -19
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2012-2015 Tobias Brunner
* Copyright (C) 2012-2018 Tobias Brunner
* Copyright (C) 2005-2009 Martin Willi
* Copyright (C) 2005 Jan Hutter
* HSR Hochschule fuer Technik Rapperswil
@@ -24,6 +24,7 @@
#include <encoding/payloads/auth_payload.h>
#include <encoding/payloads/eap_payload.h>
#include <encoding/payloads/nonce_payload.h>
#include <sa/ikev2/keymat_v2.h>
#include <sa/ikev2/authenticators/eap_authenticator.h>
#include <processing/jobs/delete_ike_sa_job.h>
@@ -59,6 +60,16 @@ struct private_ike_auth_t {
*/
chunk_t other_nonce;
/**
* PPK_ID sent or received
*/
identification_t *ppk_id;
/**
* Optional PPK to use
*/
chunk_t ppk;
/**
* IKE_SA_INIT message sent by us
*/
@@ -144,7 +155,7 @@ static status_t collect_my_init_data(private_ike_auth_t *this,
/* get the nonce that was generated in ike_init */
nonce = (nonce_payload_t*)message->get_payload(message, PLV2_NONCE);
if (nonce == NULL)
if (!nonce)
{
return FAILED;
}
@@ -170,7 +181,7 @@ static status_t collect_other_init_data(private_ike_auth_t *this,
/* get the nonce that was generated in ike_init */
nonce = (nonce_payload_t*)message->get_payload(message, PLV2_NONCE);
if (nonce == NULL)
if (!nonce)
{
return FAILED;
}
@@ -278,6 +289,29 @@ static bool do_another_auth(private_ike_auth_t *this)
return do_another;
}
/**
* Check if this is the first authentication round
*/
static bool is_first_round(private_ike_auth_t *this, bool local)
{
enumerator_t *done;
auth_cfg_t *cfg;
if (!this->ike_sa->supports_extension(this->ike_sa, EXT_MULTIPLE_AUTH))
{
return TRUE;
}
done = this->ike_sa->create_auth_cfg_enumerator(this->ike_sa, local);
if (done->enumerate(done, &cfg))
{
done->destroy(done);
return FALSE;
}
done->destroy(done);
return TRUE;
}
/**
* Get peer configuration candidates from backends
*/
@@ -313,7 +347,7 @@ static bool load_cfg_candidates(private_ike_auth_t *this)
continue;
}
peer_cfg->get_ref(peer_cfg);
if (this->peer_cfg == NULL)
if (!this->peer_cfg)
{ /* best match */
this->peer_cfg = peer_cfg;
}
@@ -404,6 +438,151 @@ static bool update_cfg_candidates(private_ike_auth_t *this, bool strict)
return this->peer_cfg != NULL;
}
/**
* Currently defined PPK_ID types
*/
#define PPK_ID_OPAQUE 1
#define PPK_ID_FIXED 2
/**
* Parse the payload data of the given PPK_IDENTITY notify
*/
static bool parse_ppk_identity(notify_payload_t *notify, identification_t **id)
{
chunk_t data;
data = notify->get_notification_data(notify);
if (data.len < 2)
{
return FALSE;
}
switch (data.ptr[0])
{
case PPK_ID_OPAQUE:
/* we currently don't support this */
default:
return FALSE;
case PPK_ID_FIXED:
data = chunk_skip(data, 1);
break;
}
*id = identification_create_from_data(data);
return TRUE;
}
/**
* Add a PPK_IDENTITY with the given PPK_ID to the given message
*/
static void add_ppk_identity(identification_t *id, message_t *msg)
{
chunk_t data;
uint8_t type = PPK_ID_FIXED;
/* we currently only support one type */
data = chunk_cata("cc", chunk_from_thing(type), id->get_encoding(id));
msg->add_notify(msg, FALSE, PPK_IDENTITY, data);
}
/**
* Use the given PPK_ID to find a PPK and store it and the ID in the task
*/
static bool get_ppk(private_ike_auth_t *this, identification_t *ppk_id)
{
shared_key_t *key;
key = lib->credmgr->get_shared(lib->credmgr, SHARED_PPK, ppk_id, NULL);
if (!key)
{
if (this->peer_cfg->ppk_required(this->peer_cfg))
{
DBG1(DBG_CFG, "PPK required but no PPK found for '%Y'", ppk_id);
return FALSE;
}
DBG1(DBG_CFG, "no PPK for '%Y' found, ignored because PPK is not "
"required", ppk_id);
return TRUE;
}
this->ppk = chunk_clone(key->get_key(key));
this->ppk_id = ppk_id->clone(ppk_id);
key->destroy(key);
return TRUE;
}
/**
* Check if we have a PPK available and, if not, whether we require one as
* initiator
*/
static bool get_ppk_i(private_ike_auth_t *this)
{
identification_t *ppk_id;
if (!this->ike_sa->supports_extension(this->ike_sa, EXT_PPK))
{
if (this->peer_cfg->ppk_required(this->peer_cfg))
{
DBG1(DBG_CFG, "PPK required but peer does not support PPK");
return FALSE;
}
return TRUE;
}
ppk_id = this->peer_cfg->get_ppk_id(this->peer_cfg);
if (!ppk_id)
{
if (this->peer_cfg->ppk_required(this->peer_cfg))
{
DBG1(DBG_CFG, "PPK required but no PPK_ID configured");
return FALSE;
}
return TRUE;
}
return get_ppk(this, ppk_id);
}
/**
* Check if we have a PPK available and if not whether we require one as
* responder
*/
static bool get_ppk_r(private_ike_auth_t *this, message_t *msg)
{
notify_payload_t *notify;
identification_t *ppk_id, *ppk_id_cfg;
bool result;
if (!this->ike_sa->supports_extension(this->ike_sa, EXT_PPK))
{
if (this->peer_cfg->ppk_required(this->peer_cfg))
{
DBG1(DBG_CFG, "PPK required but peer does not support PPK");
return FALSE;
}
return TRUE;
}
notify = msg->get_notify(msg, PPK_IDENTITY);
if (!notify || !parse_ppk_identity(notify, &ppk_id))
{
if (this->peer_cfg->ppk_required(this->peer_cfg))
{
DBG1(DBG_CFG, "PPK required but no PPK_IDENTITY received");
return FALSE;
}
return TRUE;
}
ppk_id_cfg = this->peer_cfg->get_ppk_id(this->peer_cfg);
if (ppk_id_cfg && !ppk_id->matches(ppk_id, ppk_id_cfg))
{
DBG1(DBG_CFG, "received PPK_ID '%Y', but require '%Y'", ppk_id,
ppk_id_cfg);
ppk_id->destroy(ppk_id);
return FALSE;
}
result = get_ppk(this, ppk_id);
ppk_id->destroy(ppk_id);
return result;
}
METHOD(task_t, build_i, status_t,
private_ike_auth_t *this, message_t *message)
{
@@ -414,7 +593,7 @@ METHOD(task_t, build_i, status_t,
return collect_my_init_data(this, message);
}
if (this->peer_cfg == NULL)
if (!this->peer_cfg)
{
this->peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
this->peer_cfg->get_ref(this->peer_cfg);
@@ -433,6 +612,12 @@ METHOD(task_t, build_i, status_t,
/* indicate support for RFC 6311 Message ID synchronization */
message->add_notify(message, FALSE, IKEV2_MESSAGE_ID_SYNC_SUPPORTED,
chunk_empty);
/* only use a PPK in the first round */
if (!get_ppk_i(this))
{
charon->bus->alert(charon->bus, ALERT_LOCAL_AUTH_FAILED);
return FAILED;
}
}
if (!this->do_another_auth && !this->my_auth)
@@ -441,7 +626,7 @@ METHOD(task_t, build_i, status_t,
}
/* check if an authenticator is in progress */
if (this->my_auth == NULL)
if (!this->my_auth)
{
identification_t *idi, *idr = NULL;
id_payload_t *id_payload;
@@ -508,6 +693,14 @@ METHOD(task_t, build_i, status_t,
return FAILED;
}
}
/* for authentication methods that return NEED_MORE, the PPK will be reset
* in process_i() for messages without PPK_ID notify, so we always set it
* during the first round (afterwards the PPK won't be available) */
if (this->ppk.ptr && this->my_auth->use_ppk)
{
this->my_auth->use_ppk(this->my_auth, this->ppk,
!this->peer_cfg->ppk_required(this->peer_cfg));
}
switch (this->my_auth->build(this->my_auth, message))
{
case SUCCESS:
@@ -522,6 +715,12 @@ METHOD(task_t, build_i, status_t,
return FAILED;
}
/* add a PPK_IDENTITY notify to the message that contains AUTH */
if (this->ppk_id && message->get_payload(message, PLV2_AUTH))
{
add_ppk_identity(this->ppk_id, message);
}
/* check for additional authentication rounds */
if (do_another_auth(this))
{
@@ -549,7 +748,7 @@ METHOD(task_t, process_r, status_t,
return collect_other_init_data(this, message);
}
if (this->my_auth == NULL && this->do_another_auth)
if (!this->my_auth && this->do_another_auth)
{
/* handle (optional) IDr payload, apply proposed identity */
id_payload = (id_payload_t*)message->get_payload(message, PLV2_ID_RESPONDER);
@@ -586,7 +785,7 @@ METHOD(task_t, process_r, status_t,
}
}
if (this->other_auth == NULL)
if (!this->other_auth)
{
/* handle IDi payload */
id_payload = (id_payload_t*)message->get_payload(message, PLV2_ID_INITIATOR);
@@ -601,7 +800,7 @@ METHOD(task_t, process_r, status_t,
cfg = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
cfg->add(cfg, AUTH_RULE_IDENTITY, id->clone(id));
if (this->peer_cfg == NULL)
if (!this->peer_cfg)
{
if (!load_cfg_candidates(this))
{
@@ -609,7 +808,7 @@ METHOD(task_t, process_r, status_t,
return NEED_MORE;
}
}
if (message->get_payload(message, PLV2_AUTH) == NULL)
if (!message->get_payload(message, PLV2_AUTH))
{ /* before authenticating with EAP, we need a EAP config */
cand = get_auth_cfg(this, FALSE);
while (!cand || (
@@ -655,6 +854,19 @@ METHOD(task_t, process_r, status_t,
return NEED_MORE;
}
}
if (message->get_payload(message, PLV2_AUTH) &&
is_first_round(this, FALSE))
{
if (!get_ppk_r(this, message))
{
this->authentication_failed = TRUE;
return NEED_MORE;
}
else if (this->ppk.ptr && this->other_auth->use_ppk)
{
this->other_auth->use_ppk(this->other_auth, this->ppk, FALSE);
}
}
switch (this->other_auth->process(this->other_auth, message))
{
case SUCCESS:
@@ -688,7 +900,7 @@ METHOD(task_t, process_r, status_t,
return NEED_MORE;
}
if (message->get_notify(message, ANOTHER_AUTH_FOLLOWS) == NULL)
if (!message->get_notify(message, ANOTHER_AUTH_FOLLOWS))
{
this->expect_another_auth = FALSE;
if (!update_cfg_candidates(this, TRUE))
@@ -700,6 +912,37 @@ METHOD(task_t, process_r, status_t,
return NEED_MORE;
}
/**
* Clear the PPK and PPK_ID
*/
static void clear_ppk(private_ike_auth_t *this)
{
DESTROY_IF(this->ppk_id);
this->ppk_id = NULL;
chunk_clear(&this->ppk);
}
/**
* Derive new keys and clear the PPK
*/
static bool apply_ppk(private_ike_auth_t *this)
{
keymat_v2_t *keymat;
if (this->ppk.ptr)
{
keymat = (keymat_v2_t*)this->ike_sa->get_keymat(this->ike_sa);
if (!keymat->derive_ike_keys_ppk(keymat, this->ppk))
{
return FALSE;
}
DBG1(DBG_CFG, "using PPK for PPK_ID '%Y'", this->ppk_id);
this->ike_sa->set_condition(this->ike_sa, COND_PPK, TRUE);
}
clear_ppk(this);
return TRUE;
}
METHOD(task_t, build_r, status_t,
private_ike_auth_t *this, message_t *message)
{
@@ -716,12 +959,12 @@ METHOD(task_t, build_r, status_t,
return collect_my_init_data(this, message);
}
if (this->authentication_failed || this->peer_cfg == NULL)
if (this->authentication_failed || !this->peer_cfg)
{
goto peer_auth_failed;
}
if (this->my_auth == NULL && this->do_another_auth)
if (!this->my_auth && this->do_another_auth)
{
identification_t *id, *id_cfg;
id_payload_t *id_payload;
@@ -806,6 +1049,10 @@ METHOD(task_t, build_r, status_t,
}
if (this->my_auth)
{
if (this->ppk.ptr && this->my_auth->use_ppk)
{
this->my_auth->use_ppk(this->my_auth, this->ppk, FALSE);
}
switch (this->my_auth->build(this->my_auth, message))
{
case SUCCESS:
@@ -820,6 +1067,16 @@ METHOD(task_t, build_r, status_t,
}
}
/* add a PPK_IDENTITY notify and derive new keys and clear the PPK */
if (this->ppk.ptr)
{
message->add_notify(message, FALSE, PPK_IDENTITY, chunk_empty);
if (!apply_ppk(this))
{
goto local_auth_failed;
}
}
/* check for additional authentication rounds */
if (do_another_auth(this))
{
@@ -955,7 +1212,7 @@ METHOD(task_t, process_i, status_t,
enumerator_t *enumerator;
payload_t *payload;
auth_cfg_t *cfg;
bool mutual_eap = FALSE;
bool mutual_eap = FALSE, ppk_id_received = FALSE;
if (message->get_exchange_type(message) == IKE_SA_INIT)
{
@@ -1011,6 +1268,9 @@ METHOD(task_t, process_i, status_t,
this->ike_sa->enable_extension(this->ike_sa,
EXT_IKE_MESSAGE_ID_SYNC);
break;
case PPK_IDENTITY:
ppk_id_received = TRUE;
break;
default:
{
if (type <= 16383)
@@ -1032,7 +1292,7 @@ METHOD(task_t, process_i, status_t,
if (this->expect_another_auth)
{
if (this->other_auth == NULL)
if (!this->other_auth)
{
id_payload_t *id_payload;
identification_t *id;
@@ -1072,6 +1332,11 @@ METHOD(task_t, process_i, status_t,
}
if (this->other_auth)
{
if (ppk_id_received && is_first_round(this, FALSE) &&
this->other_auth->use_ppk)
{
this->other_auth->use_ppk(this->other_auth, this->ppk, FALSE);
}
switch (this->other_auth->process(this->other_auth, message))
{
case SUCCESS:
@@ -1107,6 +1372,14 @@ METHOD(task_t, process_i, status_t,
if (this->my_auth)
{
/* while we already set the PPK in build_i(), we MUST not use it if
* the peer did not reply with a PPK_ID notify */
if (this->ppk.ptr && this->my_auth->use_ppk)
{
this->my_auth->use_ppk(this->my_auth,
ppk_id_received ? this->ppk : chunk_empty,
FALSE);
}
switch (this->my_auth->process(this->my_auth, message))
{
case SUCCESS:
@@ -1122,11 +1395,29 @@ METHOD(task_t, process_i, status_t,
case NEED_MORE:
break;
default:
charon->bus->alert(charon->bus, ALERT_LOCAL_AUTH_FAILED);
send_auth_failed_informational(this, message);
return FAILED;
goto local_auth_failed;
}
}
/* change keys and clear PPK after we are done with our authentication, so
* we only explicitly use it for the first round, afterwards we just use the
* changed SK_p keys implicitly */
if (!this->my_auth && this->ppk_id)
{
if (ppk_id_received)
{
if (!apply_ppk(this))
{
goto local_auth_failed;
}
}
else
{
DBG1(DBG_CFG, "peer didn't use PPK for PPK_ID '%Y'", this->ppk_id);
}
clear_ppk(this);
}
if (mutual_eap)
{
if (!this->my_auth || !this->my_auth->is_mutual(this->my_auth))
@@ -1137,7 +1428,7 @@ METHOD(task_t, process_i, status_t,
DBG1(DBG_IKE, "allow mutual EAP-only authentication");
}
if (message->get_notify(message, ANOTHER_AUTH_FOLLOWS) == NULL)
if (!message->get_notify(message, ANOTHER_AUTH_FOLLOWS))
{
this->expect_another_auth = FALSE;
}
@@ -1175,6 +1466,10 @@ peer_auth_failed:
charon->bus->alert(charon->bus, ALERT_PEER_AUTH_FAILED);
send_auth_failed_informational(this, message);
return FAILED;
local_auth_failed:
charon->bus->alert(charon->bus, ALERT_LOCAL_AUTH_FAILED);
send_auth_failed_informational(this, message);
return FAILED;
}
METHOD(task_t, get_type, task_type_t,
@@ -1186,6 +1481,7 @@ METHOD(task_t, get_type, task_type_t,
METHOD(task_t, migrate, void,
private_ike_auth_t *this, ike_sa_t *ike_sa)
{
clear_ppk(this);
chunk_free(&this->my_nonce);
chunk_free(&this->other_nonce);
DESTROY_IF(this->my_packet);
@@ -1212,6 +1508,7 @@ METHOD(task_t, migrate, void,
METHOD(task_t, destroy, void,
private_ike_auth_t *this)
{
clear_ppk(this);
chunk_free(&this->my_nonce);
chunk_free(&this->other_nonce);
DESTROY_IF(this->my_packet);
+44
View File
@@ -269,6 +269,38 @@ static void handle_supported_hash_algorithms(private_ike_init_t *this,
}
}
/**
* Check whether to send a USE_PPK notify
*/
static bool send_use_ppk(private_ike_init_t *this)
{
peer_cfg_t *peer;
enumerator_t *keys;
shared_key_t *key;
bool use_ppk = FALSE;
if (this->initiator)
{
peer = this->ike_sa->get_peer_cfg(this->ike_sa);
if (peer->get_ppk_id(peer))
{
use_ppk = TRUE;
}
}
else if (this->ike_sa->supports_extension(this->ike_sa, EXT_PPK))
{
/* check if we have at least one PPK available */
keys = lib->credmgr->create_shared_enumerator(lib->credmgr, SHARED_PPK,
NULL, NULL);
if (keys->enumerate(keys, &key, NULL, NULL))
{
use_ppk = TRUE;
}
keys->destroy(keys);
}
return use_ppk;
}
/**
* build the payloads for the message
*/
@@ -396,6 +428,11 @@ static bool build_payloads(private_ike_init_t *this, message_t *message)
chunk_empty);
}
}
/* notify the peer if we want to use/support PPK */
if (!this->old_sa && send_use_ppk(this))
{
message->add_notify(message, FALSE, USE_PPK, chunk_empty);
}
return TRUE;
}
@@ -510,6 +547,13 @@ static void process_payloads(private_ike_init_t *this, message_t *message)
handle_supported_hash_algorithms(this, notify);
}
break;
case USE_PPK:
if (!this->old_sa)
{
this->ike_sa->enable_extension(this->ike_sa,
EXT_PPK);
}
break;
case REDIRECTED_FROM:
{
identification_t *gateway;
@@ -15,12 +15,14 @@
#include "shared_key.h"
ENUM(shared_key_type_names, SHARED_ANY, SHARED_PIN,
ENUM(shared_key_type_names, SHARED_ANY, SHARED_PPK,
"ANY",
"IKE",
"EAP",
"PRIVATE_KEY_PASS",
"PIN",
"NTLM",
"PPK",
);
typedef struct private_shared_key_t private_shared_key_t;
@@ -93,7 +95,7 @@ shared_key_t *shared_key_create(shared_key_type_t type, chunk_t key)
.get_key = _get_key,
.get_ref = _get_ref,
.destroy = _destroy,
},
},
.type = type,
.key = key,
.ref = 1,
@@ -43,6 +43,8 @@ enum shared_key_type_t {
SHARED_PIN,
/** Calculated NT Hash = MD4(UTF-16LE(password)) */
SHARED_NT_HASH,
/** Postquantum Preshared Key */
SHARED_PPK,
};
/**
+9 -1
View File
@@ -238,7 +238,7 @@ CALLBACK(conns, int,
void *null, vici_res_t *res, char *name)
{
int ret;
char *version, *reauth_time, *rekey_time, *dpd_delay;
char *version, *reauth_time, *rekey_time, *dpd_delay, *ppk_id, *ppk_req;
hashtable_t *ike;
version = vici_find_str(res, "", "%s.version", name);
@@ -282,6 +282,14 @@ CALLBACK(conns, int,
}
printf("\n");
ppk_id = vici_find_str(res, NULL, "%s.ppk_id", name);
ppk_req = vici_find_str(res, NULL, "%s.ppk_required", name);
if (ppk_id || ppk_req)
{
printf(" ppk: %s%s%srequired\n", ppk_id ?: "", ppk_id ? ", " : "",
!ppk_req || !streq(ppk_req, "yes") ? "not " : "");
}
ret = vici_parse_cb(res, conn_sn, NULL, conn_list, ike);
free_hashtable(ike);
return ret;
+4
View File
@@ -266,6 +266,10 @@ CALLBACK(ike_sa, int,
}
printf("/%s", ike->get(ike, "prf-alg"));
printf("/%s", ike->get(ike, "dh-group"));
if (streq(ike->get(ike, "ppk"), "yes"))
{
printf("/PPK");
}
printf("\n");
}
+2 -1
View File
@@ -665,6 +665,7 @@ static bool load_secret(load_ctx_t *ctx, char *section)
"xauth",
"ntlm",
"ike",
"ppk",
"private",
"rsa",
"ecdsa",
@@ -688,7 +689,7 @@ static bool load_secret(load_ctx_t *ctx, char *section)
return FALSE;
}
if (!streq(type, "eap") && !streq(type, "xauth") && !streq(type, "ntlm") &&
!streq(type, "ike"))
!streq(type, "ike") && !streq(type, "ppk"))
{ /* skip non-shared secrets */
return TRUE;
}
+6
View File
@@ -188,6 +188,12 @@ connections.<conn>.send_cert = ifasked
certificate payloads altogether, _always_ causes certificate payloads to be
sent unconditionally whenever certificate authentication is used.
connections.<conn>.ppk_id =
String identifying the Postquantum Preshared Key (PPK) to be used.
connections.<conn>.ppk_required = no
Whether a Postquantum Preshared Key (PPK) is required for this connection.
connections.<conn>.keyingtries = 1
Number of retransmission sequences to perform during initial connect.
+11
View File
@@ -0,0 +1,11 @@
The roadwarriors <b>carol</b> and <b>dave</b> set up a connection each
to gateway <b>moon</b>. The authentication is based on <b>X.509 certificates</b>
and includes a <b>Postquantum Preshared Key (PPK)</b> that's also mixed into the
derived key material. The PPK_ID used by <b>dave</b> is unknown to <b>moon</b>
but since both peers don't enforce the use of a PPK they fall back to regular
authentication by use of the authentication data provided in the NO_PPK_AUTH
notify.
Upon the successful establishment of the IPsec tunnels, the updown script
automatically inserts iptables-based firewall rules that let pass the tunneled traffic.
In order to test both tunnel and firewall, both <b>carol</b> and <b>dave</b> ping
the client <b>alice</b> behind the gateway <b>moon</b>.
+15
View File
@@ -0,0 +1,15 @@
carol::swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.100 local-port=4500 [email protected] remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=CURVE_25519 ppk=yes.*child-sas.*home.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.100/32] remote-ts=\[10.1.0.0/16]::YES
dave:: swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.200 local-port=4500 [email protected] remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=CURVE_25519.*child-sas.*home.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.200/32] remote-ts=\[10.1.0.0/16]::YES
moon:: swanctl --list-sas --ike-id 1 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.100 remote-port=4500 [email protected].*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=CURVE_25519 ppk=yes.*child-sas.*net.*reqid=1 state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/16] remote-ts=\[192.168.0.100/32]::YES
moon:: swanctl --list-sas --ike-id 2 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.200 remote-port=4500 [email protected].*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=CURVE_25519.*child-sas.*net.*reqid=2 state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/16] remote-ts=\[192.168.0.200/32]::YES
carol::cat /var/log/daemon.log::using PPK for PPK_ID '[email protected]'::YES
dave:: cat /var/log/daemon.log::peer didn't use PPK for PPK_ID '[email protected]'::YES
moon:: cat /var/log/daemon.log::using PPK for PPK_ID '[email protected]'::YES
moon:: cat /var/log/daemon.log::no PPK for '[email protected]' found, ignored because PPK is not required::YES
moon:: cat /var/log/daemon.log::no PPK available, using NO_PPK_AUTH notify::YES
alice::ping -c 1 192.168.0.100::64 bytes from 192.168.0.100: icmp_.eq=1::YES
alice::ping -c 1 192.168.0.200::64 bytes from 192.168.0.200: icmp_.eq=1::YES
moon::tcpdump::IP moon.strongswan.org > carol.strongswan.org: ESP::YES
moon::tcpdump::IP carol.strongswan.org > moon.strongswan.org: ESP::YES
moon::tcpdump::IP moon.strongswan.org > dave.strongswan.org: ESP::YES
moon::tcpdump::IP dave.strongswan.org > moon.strongswan.org: ESP::YES
@@ -0,0 +1,9 @@
# /etc/strongswan.conf - strongSwan configuration file
swanctl {
load = pem pkcs1 x509 revocation constraints pubkey openssl random
}
charon-systemd {
load = random nonce sha1 sha2 aes hmac pem pkcs1 x509 revocation constraints pubkey curve25519 gmp curl kernel-netlink socket-default updown vici
}
@@ -0,0 +1,30 @@
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-128-CBC,7E1D40A7901772BA4D22AF58AA2DC76F
1jt4EsxtHvgpSLN8PA/kSVKgoAsBEBQb8RK6VGnZywMCnpJdLKdPisGGYKNPg53b
/0AFBmQVE60M8icbSAIUrAtyKxaBkoc9A7ibNCjobi0UzXTm3GcZZ1EC4/lE9PQZ
/2FbcPgQWN3kZraZDkeP9XBXl6PorES8xvQUxJ9pd4hL7/c28fIApGhEimkIZO8o
Qb7bR2cNCLYQAR6PeDoqhV39gvWoh77wp1WB3tQVbkS6MI/xl3wY2QVdq3Sbszh+
f6lDU/SZS8BU0f44FRoInPp0GasgJ7MCiuEIshjuNPa50QkMcnNJsSgVEuw2hjN6
LvAXx7vPt9pKpQfnu7YSJUsXDYN6PyXt7sZ8hDqraYIcI6eMpEBaTpItPSV2eckv
06KC24Oa66E1yufNFAY49S2OY+pJA0W5zmcCqCjdrfJ+wNQYKZpbrfGz4VRzlFJC
e3VkmAFwA5rcZdlp/mU2XREy+TaWsHMnpL0NcMHGmsfkTgaJIkRWalrdxlNTeitr
3boNHWk0ESyMcBYRpM3eNXsGpiYy93u0bhrPbnqJsV6miKqpbs1aBNjlJ9s1Y2fC
sko5/v7uMjb5tLF3lWQZfTu+bYtpGxFrqHJjhd8yd4gL1cFi30JcjczhwRY3Dily
c0BFekMGmPc1djn6tfIFu13X9xTxyidCpVaT9UGnOaQs9OF1u8XAnZDaQgPwjLiy
UlOE8xQ60LrhWLD582FsFnZz56bZ+QOQRWDMsB8nJeqnFXKfcRlnr0qlG6lTfA8h
XkK/qGpdVvivS+CpbhVP6ixdEfa91Rx4NjLj53LGqOYwFEkM/OAIuMJetBfx3v9T
iQfv594KE32nv9besnKlmJr2cGQWBYg1pUOtFj/aZ00yuXacv8qwzbrt4xGGDYGO
Aj5Yf93UEcVkTySO1xJ1yiC6GJv1lLm0i5StwykHypxFijKe/zOpgtHVa5v5igjO
v6cfhfJGGgIPTYrtt+EDKXcayvy2e2U/3HYVCHYiiMPX8AvP/R6m7MGrzYxm/WyO
t68EWXSDLfuR3qcIlpP4aSBxuSpKhY/dIkS/beKZ7Njx1s4jSuYDMbKuuCRFSU2H
8ISHS0kh3FetiS8IyIYzxab+KQZwnVtiGj4oaAhgFTIIoH26Fv5+xka74JdzOSUA
jR9puKuxaegVWQVBx4cCyg6hAdewRm64PAcbApZWrPvMPBfTZFnXeifmaurcdK8p
p/1eLrrPnNM6+Fh6lcKdX74yHPz3eWP3K1njZegzWnChhEWElPhJr6qYNQjd+lAS
7650RJ3CJLUxBffnRR9nTArxFNI5jGWg/plLJTaRT5x5qg1dGNMqntpoeiY++Ttk
GFDGVIOICBze6SOvzkZBbuXLJSWmWj5g9J2cYsLoOvlwsDT7FzKl8p6VY4V+SQb+
4PN8qZWmOeczaLEhZ1QLmTKFpz9+wUZsXeBd1s78bWJR0zhraMPa0UJ9GBGq6uQ0
yZ4Xm5KHKcgoewCUQMekU9ECsmR5NuC7VFDaa1OdPEVnEYR1xtaWUY0lYKOiixnd
+85fSq/yAXI/r0O4ISA55o9y1kDqVibTwJacb6xXGg8dHSH+TtigwD8fK9mekkDC
-----END RSA PRIVATE KEY-----
@@ -0,0 +1,42 @@
connections {
home {
local_addrs = 192.168.0.100
remote_addrs = 192.168.0.1
ppk_id = [email protected]
ppk_required = yes
local {
auth = pubkey
certs = carolCert.pem
id = [email protected]
}
remote {
auth = pubkey
id = moon.strongswan.org
}
children {
home {
remote_ts = 10.1.0.0/16
updown = /usr/local/libexec/ipsec/_updown iptables
esp_proposals = aes128gcm128-x25519
}
}
version = 2
proposals = aes128-sha256-x25519
}
}
secrets {
rsa-carol {
file = carolKey.pem
secret = "nH5ZQEWtku0RJEZ6"
}
ppk-carol {
id = [email protected]
secret = 0x98c61dd0f8c7daf07759617546f7b3ae156f19a7bc935c61523c7ca998e5eedb
}
}
@@ -0,0 +1,9 @@
# /etc/strongswan.conf - strongSwan configuration file
swanctl {
load = pem pkcs1 x509 revocation constraints pubkey openssl random
}
charon-systemd {
load = random nonce sha1 sha2 aes hmac pem pkcs1 x509 revocation constraints pubkey curve25519 gmp curl kernel-netlink socket-default updown vici
}
@@ -0,0 +1,38 @@
connections {
home {
local_addrs = 192.168.0.200
remote_addrs = 192.168.0.1
ppk_id = [email protected]
ppk_required = no
local {
auth = pubkey
certs = daveCert.pem
id = [email protected]
}
remote {
auth = pubkey
id = moon.strongswan.org
}
children {
home {
remote_ts = 10.1.0.0/16
updown = /usr/local/libexec/ipsec/_updown iptables
esp_proposals = aes128gcm128-x25519
}
}
version = 2
proposals = aes128-sha256-x25519
}
}
secrets {
ppk-dave {
id = [email protected]
secret = 0x06918e49398db61094438a5be8b743894f155f4e8521e6bcd1d47690557e4b13
}
}
@@ -0,0 +1,9 @@
# /etc/strongswan.conf - strongSwan configuration file
swanctl {
load = pem pkcs1 x509 revocation constraints pubkey openssl random
}
charon-systemd {
load = random nonce sha1 sha2 aes hmac pem pkcs1 x509 revocation constraints pubkey curve25519 gmp curl kernel-netlink socket-default updown vici
}
@@ -0,0 +1,33 @@
connections {
rw {
local_addrs = 192.168.0.1
local {
auth = pubkey
certs = moonCert.pem
id = moon.strongswan.org
}
remote {
auth = pubkey
}
children {
net {
local_ts = 10.1.0.0/16
updown = /usr/local/libexec/ipsec/_updown iptables
esp_proposals = aes128gcm128-x25519
}
}
version = 2
proposals = aes128-sha256-x25519
}
}
secrets {
ppk-carol {
id = [email protected]
secret = 0x98c61dd0f8c7daf07759617546f7b3ae156f19a7bc935c61523c7ca998e5eedb
}
}
+8
View File
@@ -0,0 +1,8 @@
carol::swanctl --terminate --ike home
dave::swanctl --terminate --ike home
carol::systemctl stop strongswan-swanctl
dave::systemctl stop strongswan-swanctl
moon::systemctl stop strongswan-swanctl
moon::iptables-restore < /etc/iptables.flush
carol::iptables-restore < /etc/iptables.flush
dave::iptables-restore < /etc/iptables.flush
+11
View File
@@ -0,0 +1,11 @@
moon::iptables-restore < /etc/iptables.rules
carol::iptables-restore < /etc/iptables.rules
dave::iptables-restore < /etc/iptables.rules
moon::systemctl start strongswan-swanctl
carol::systemctl start strongswan-swanctl
dave::systemctl start strongswan-swanctl
moon::expect-connection rw
carol::expect-connection home
carol::swanctl --initiate --child home 2> /dev/null
dave::expect-connection home
dave::swanctl --initiate --child home 2> /dev/null
+25
View File
@@ -0,0 +1,25 @@
#!/bin/bash
#
# This configuration file provides information on the
# guest instances used for this test
# All guest instances that are required for this test
#
VIRTHOSTS="alice moon carol winnetou dave"
# Corresponding block diagram
#
DIAGRAM="a-m-c-w-d.png"
# Guest instances on which tcpdump is to be started
#
TCPDUMPHOSTS="moon"
# Guest instances on which IPsec is started
# Used for IPsec logging purposes
#
IPSECHOSTS="moon carol dave"
# charon controlled by swanctl
#
SWANCTL=1
@@ -0,0 +1,11 @@
The roadwarriors <b>carol</b> and <b>dave</b> set up a connection to gateway <b>moon</b>.
At the outset the gateway authenticates itself to the clients by sending
an IKEv2 <b>RSA signature</b> accompanied by a certificate.
The roadwarrios then use the <i>Extensible Authentication Protocol</i>
in association with an <i>MD5</i> challenge and response protocol
(<b>EAP-MD5</b>) to authenticate against the gateway <b>moon</b> and includes
a <b>Postquantum Preshared Key (PPK)</b> that's also mixed into the
derived key material. The PPK_ID used by <b>dave</b> is unknown to <b>moon</b>
but since both peers don't enforce the use of a PPK they fall back to regular
authentication by use of the authentication data provided in the NO_PPK_AUTH
notify.
@@ -0,0 +1,27 @@
carol::cat /var/log/daemon.log::authentication of 'moon.strongswan.org' with RSA.* successful::YES
carol::cat /var/log/daemon.log::server requested EAP_MD5 authentication::YES
carol::cat /var/log/daemon.log::authentication of 'moon.strongswan.org' with EAP successful::YES
carol::cat /var/log/daemon.log::using PPK for PPK_ID '[email protected]'::YES
dave:: cat /var/log/daemon.log::authentication of 'moon.strongswan.org' with RSA.* successful::YES
dave:: cat /var/log/daemon.log::server requested EAP_MD5 authentication::YES
dave:: cat /var/log/daemon.log::authentication of 'moon.strongswan.org' with EAP successful::YES
dave:: cat /var/log/daemon.log::peer didn't use PPK for PPK_ID '[email protected]'::YES
moon:: cat /var/log/daemon.log::received EAP identity.*carol
moon:: cat /var/log/daemon.log::EAP method EAP_MD5 succeeded, no MSK established
moon:: cat /var/log/daemon.log::authentication of '192.168.0.100' with EAP successful::YES
moon:: cat /var/log/daemon.log::received EAP identity.*dave
moon:: cat /var/log/daemon.log::EAP method EAP_MD5 succeeded, no MSK established
moon:: cat /var/log/daemon.log::authentication of '192.168.0.200' with EAP successful::YES
moon:: cat /var/log/daemon.log::using PPK for PPK_ID '[email protected]'::YES
moon:: cat /var/log/daemon.log::no PPK for '[email protected]' found, ignored because PPK is not required::YES
moon:: cat /var/log/daemon.log::no PPK available, using NO_PPK_AUTH notify::YES
carol::ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_.eq=1::YES
carol::swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.100 local-port=4500 local-id=192.168.0.100 remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=CURVE_25519 ppk=yes.*child-sas.*home.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.100/32] remote-ts=\[10.1.0.0/16]::YES
dave:: ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_.eq=1::YES
dave:: swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.200 local-port=4500 local-id=192.168.0.200 remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=CURVE_25519.*child-sas.*home.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.200/32] remote-ts=\[10.1.0.0/16]::YES
moon:: swanctl --list-sas --ike-id 1 --raw 2> /dev/null::rw-eap.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.100 remote-port=4500 remote-id=192.168.0.100.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=CURVE_25519 ppk=yes.*child-sas.*net.*reqid=1 state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/16] remote-ts=\[192.168.0.100/32]::YES
moon:: swanctl --list-sas --ike-id 2 --raw 2> /dev/null::rw-eap.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.200 remote-port=4500 remote-id=192.168.0.200.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=CURVE_25519.*child-sas.*net.*reqid=2 state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/16] remote-ts=\[192.168.0.200/32]::YES
moon::tcpdump::IP carol.strongswan.org > moon.strongswan.org: ESP::YES
moon::tcpdump::IP moon.strongswan.org > carol.strongswan.org: ESP::YES
moon::tcpdump::IP dave.strongswan.org > moon.strongswan.org: ESP::YES
moon::tcpdump::IP moon.strongswan.org > dave.strongswan.org: ESP::YES
@@ -0,0 +1,9 @@
# /etc/strongswan.conf - strongSwan configuration file
swanctl {
load = pem pkcs1 x509 revocation constraints pubkey openssl random
}
charon-systemd {
load = random nonce aes md5 sha1 sha2 pem pkcs1 curve25519 gmp x509 curl revocation hmac vici kernel-netlink socket-default eap-identity eap-md5 updown
}
@@ -0,0 +1,41 @@
connections {
home {
local_addrs = 192.168.0.100
remote_addrs = 192.168.0.1
ppk_id = [email protected]
ppk_required = yes
local {
auth = eap
eap_id = carol
}
remote {
auth = pubkey
id = moon.strongswan.org
}
children {
home {
remote_ts = 10.1.0.0/16
updown = /usr/local/libexec/ipsec/_updown iptables
esp_proposals = aes128gcm128-x25519
}
}
version = 2
proposals = aes128-sha256-x25519
}
}
secrets {
eap-carol {
id = carol
secret = Ar3etTnp
}
ppk-carol {
id = [email protected]
secret = 0x98c61dd0f8c7daf07759617546f7b3ae156f19a7bc935c61523c7ca998e5eedb
}
}
@@ -0,0 +1,9 @@
# /etc/strongswan.conf - strongSwan configuration file
swanctl {
load = pem pkcs1 x509 revocation constraints pubkey openssl random
}
charon-systemd {
load = random nonce aes md5 sha1 sha2 pem pkcs1 curve25519 gmp x509 curl revocation hmac vici kernel-netlink socket-default eap-identity eap-md5 updown
}
@@ -0,0 +1,39 @@
connections {
home {
remote_addrs = 192.168.0.1
ppk_id = [email protected]
local {
auth = eap
eap_id = dave
}
remote {
auth = pubkey
id = moon.strongswan.org
}
children {
home {
remote_ts = 10.1.0.0/16
updown = /usr/local/libexec/ipsec/_updown iptables
esp_proposals = aes128gcm128-x25519
}
}
version = 2
proposals = aes128-sha256-x25519
}
}
secrets {
eap-dave {
id = dave
secret = W7R0g3do
}
ppk-dave {
id = [email protected]
secret = 0x06918e49398db61094438a5be8b743894f155f4e8521e6bcd1d47690557e4b13
}
}
@@ -0,0 +1,9 @@
# /etc/strongswan.conf - strongSwan configuration file
swanctl {
load = pem pkcs1 x509 revocation constraints pubkey openssl random
}
charon-systemd {
load = random nonce aes md5 sha1 sha2 pem pkcs1 curve25519 gmp x509 curl revocation hmac vici kernel-netlink socket-default eap-identity eap-md5 updown
}
@@ -0,0 +1,44 @@
connections {
rw-eap {
local_addrs = 192.168.0.1
local {
auth = pubkey
certs = moonCert.pem
id = moon.strongswan.org
}
remote {
auth = eap-md5
eap_id = %any
}
children {
net {
local_ts = 10.1.0.0/16
updown = /usr/local/libexec/ipsec/_updown iptables
esp_proposals = aes128gcm128-x25519
}
}
version = 2
send_certreq = no
proposals = aes128-sha256-x25519
}
}
secrets {
eap-carol {
id = carol
secret = Ar3etTnp
}
eap-dave {
id = dave
secret = W7R0g3do
}
ppk-carol {
id = [email protected]
secret = 0x98c61dd0f8c7daf07759617546f7b3ae156f19a7bc935c61523c7ca998e5eedb
}
}
@@ -0,0 +1,8 @@
carol::swanctl --terminate --ike home
carol::systemctl stop strongswan-swanctl
dave::swanctl --terminate --ike home
dave::systemctl stop strongswan-swanctl
moon::systemctl stop strongswan-swanctl
moon::iptables-restore < /etc/iptables.flush
carol::iptables-restore < /etc/iptables.flush
dave::iptables-restore < /etc/iptables.flush
@@ -0,0 +1,13 @@
moon::iptables-restore < /etc/iptables.rules
carol::iptables-restore < /etc/iptables.rules
dave::iptables-restore < /etc/iptables.rules
carol::cd /etc/swanctl; rm rsa/* x509/*
dave::cd /etc/swanctl; rm rsa/* x509/*
moon::systemctl start strongswan-swanctl
carol::systemctl start strongswan-swanctl
dave::systemctl start strongswan-swanctl
moon::expect-connection rw-eap
carol::expect-connection home
carol::swanctl --initiate --child home 2> /dev/null
dave::expect-connection home
dave::swanctl --initiate --child home 2> /dev/null
@@ -0,0 +1,25 @@
#!/bin/bash
#
# This configuration file provides information on the
# guest instances used for this test
# All guest instances that are required for this test
#
VIRTHOSTS="alice carol moon dave"
# Corresponding block diagram
#
DIAGRAM="a-m-c-w-d.png"
# Guest instances on which tcpdump is to be started
#
TCPDUMPHOSTS="moon"
# Guest instances on which IPsec is started
# Used for IPsec logging purposes
#
IPSECHOSTS="moon carol dave"
# charon controlled by swanctl
#
SWANCTL=1
+11
View File
@@ -0,0 +1,11 @@
The roadwarriors <b>carol</b> and <b>dave</b> set up a connection each
to gateway <b>moon</b>. The authentication is based on distinct <b>pre-shared keys</b>
and <b>Fully Qualified Domain Names</b> and includes a <b>Postquantum Preshared Key (PPK)</b>
that's also mixed into the derived key material. The PPK_ID used by <b>dave</b> is
unknown to <b>moon</b> but since both peers don't enforce the use of a PPK they fall back
to regular authentication by use of the authentication data provided in the NO_PPK_AUTH
notify.
Upon the successful establishment of the IPsec tunnels,
<b>leftfirewall=yes</b> automatically inserts iptables-based firewall rules that
let pass the tunneled traffic. In order to test both tunnel and firewall, both
<b>carol</b> and <b>dave</b> ping the client <b>alice</b> behind the gateway <b>moon</b>.
+15
View File
@@ -0,0 +1,15 @@
carol::swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.100 local-port=4500 [email protected] remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=CURVE_25519 ppk=yes.*child-sas.*home.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.100/32] remote-ts=\[10.1.0.0/16]::YES
dave:: swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.200 local-port=4500 [email protected] remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=CURVE_25519.*child-sas.*home.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.200/32] remote-ts=\[10.1.0.0/16]::YES
moon:: swanctl --list-sas --ike-id 1 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.100 remote-port=4500 [email protected].*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=CURVE_25519 ppk=yes.*child-sas.*net.*reqid=1 state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/16] remote-ts=\[192.168.0.100/32]::YES
moon:: swanctl --list-sas --ike-id 2 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.200 remote-port=4500 [email protected].*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=CURVE_25519.*child-sas.*net.*reqid=2 state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/16] remote-ts=\[192.168.0.200/32]::YES
carol::cat /var/log/daemon.log::using PPK for PPK_ID '[email protected]'::YES
dave:: cat /var/log/daemon.log::peer didn't use PPK for PPK_ID '[email protected]'::YES
moon:: cat /var/log/daemon.log::using PPK for PPK_ID '[email protected]'::YES
moon:: cat /var/log/daemon.log::no PPK for '[email protected]' found, ignored because PPK is not required::YES
moon:: cat /var/log/daemon.log::no PPK available, using NO_PPK_AUTH notify::YES
alice::ping -c 1 -W 1 192.168.0.100::64 bytes from 192.168.0.100: icmp_.eq=1::YES
alice::ping -c 1 -W 1 192.168.0.200::64 bytes from 192.168.0.200: icmp_.eq=1::YES
moon::tcpdump::IP moon.strongswan.org > carol.strongswan.org: ESP::YES
moon::tcpdump::IP carol.strongswan.org > moon.strongswan.org: ESP::YES
moon::tcpdump::IP moon.strongswan.org > dave.strongswan.org: ESP::YES
moon::tcpdump::IP dave.strongswan.org > moon.strongswan.org: ESP::YES
@@ -0,0 +1,14 @@
# /etc/strongswan.conf - strongSwan configuration file
swanctl {
load = random openssl
}
charon-systemd {
load = random nonce aes sha1 sha2 hmac curve25519 kernel-netlink socket-default updown vici
syslog {
daemon {
ike = 4
}
}
}
@@ -0,0 +1,43 @@
connections {
home {
local_addrs = 192.168.0.100
remote_addrs = 192.168.0.1
ppk_id = [email protected]
ppk_required = yes
local {
auth = psk
id = [email protected]
}
remote {
auth = psk
id = moon.strongswan.org
}
children {
home {
remote_ts = 10.1.0.0/16
updown = /usr/local/libexec/ipsec/_updown iptables
esp_proposals = aes128gcm128-x25519
}
}
version = 2
proposals = aes128-sha256-x25519
}
}
secrets {
ike-moon {
id = moon.strongswan.org
# hex value equal to base64 0sFpZAZqEN6Ti9sqt4ZP5EWcqx
secret = 0x16964066a10de938bdb2ab7864fe4459cab1
}
ppk-carol {
id = [email protected]
secret = 0x98c61dd0f8c7daf07759617546f7b3ae156f19a7bc935c61523c7ca998e5eedb
}
}
@@ -0,0 +1,9 @@
# /etc/strongswan.conf - strongSwan configuration file
swanctl {
load = random openssl
}
charon-systemd {
load = random nonce aes sha1 sha2 hmac curve25519 kernel-netlink socket-default updown vici
}
@@ -0,0 +1,40 @@
connections {
home {
local_addrs = 192.168.0.200
remote_addrs = 192.168.0.1
ppk_id = [email protected]
local {
auth = psk
id = [email protected]
}
remote {
auth = psk
id = moon.strongswan.org
}
children {
home {
remote_ts = 10.1.0.0/16
updown = /usr/local/libexec/ipsec/_updown iptables
esp_proposals = aes128gcm128-x25519
}
}
version = 2
proposals = aes128-sha256-x25519
}
}
secrets {
ike-moon {
id = moon.strongswan.org
secret = 0sjVzONCF02ncsgiSlmIXeqhGN
}
ppk-dave {
id = [email protected]
secret = 0x06918e49398db61094438a5be8b743894f155f4e8521e6bcd1d47690557e4b13
}
}
@@ -0,0 +1,9 @@
# /etc/strongswan.conf - strongSwan configuration file
swanctl {
load = random openssl
}
charon-systemd {
load = random nonce aes sha1 sha2 hmac curve25519 kernel-netlink socket-default updown vici
}
@@ -0,0 +1,42 @@
connections {
rw {
local_addrs = 192.168.0.1
ppk_id = *@strongswan.org
local {
auth = psk
id = moon.strongswan.org
}
remote {
auth = psk
}
children {
net {
local_ts = 10.1.0.0/16
updown = /usr/local/libexec/ipsec/_updown iptables
esp_proposals = aes128gcm128-x25519
}
}
version = 2
proposals = aes128-sha256-x25519
}
}
secrets {
ike-carol {
id = [email protected]
secret = 0sFpZAZqEN6Ti9sqt4ZP5EWcqx
}
ike-dave {
id = [email protected]
secret = 0sjVzONCF02ncsgiSlmIXeqhGN
}
ppk-carol {
id = [email protected]
secret = 0x98c61dd0f8c7daf07759617546f7b3ae156f19a7bc935c61523c7ca998e5eedb
}
}
+8
View File
@@ -0,0 +1,8 @@
carol::swanctl --terminate --ike home
dave::swanctl --terminate --ike home
carol::systemctl stop strongswan-swanctl
dave::systemctl stop strongswan-swanctl
moon::systemctl stop strongswan-swanctl
moon::iptables-restore < /etc/iptables.flush
carol::iptables-restore < /etc/iptables.flush
dave::iptables-restore < /etc/iptables.flush
+14
View File
@@ -0,0 +1,14 @@
moon::iptables-restore < /etc/iptables.rules
carol::iptables-restore < /etc/iptables.rules
dave::iptables-restore < /etc/iptables.rules
moon::cd /etc/swanctl; rm rsa/* x509/* x509ca/*
carol::cd /etc/swanctl; rm rsa/* x509/* x509ca/*
dave::cd /etc/swanctl; rm rsa/* x509/* x509ca/*
moon::systemctl start strongswan-swanctl
carol::systemctl start strongswan-swanctl
dave::systemctl start strongswan-swanctl
moon::expect-connection rw
carol::expect-connection home
carol::swanctl --initiate --child home 2> /dev/null
dave::expect-connection home
dave::swanctl --initiate --child home 2> /dev/null
+25
View File
@@ -0,0 +1,25 @@
#!/bin/bash
#
# This configuration file provides information on the
# guest instances used for this test
# All guest instances that are required for this test
#
VIRTHOSTS="alice moon carol winnetou dave"
# Corresponding block diagram
#
DIAGRAM="a-m-c-w-d.png"
# Guest instances on which tcpdump is to be started
#
TCPDUMPHOSTS="moon"
# Guest instances on which IPsec is started
# Used for IPsec logging purposes
#
IPSECHOSTS="moon carol dave"
# charon controlled by swanctl
#
SWANCTL=1