Merge branch 'ikev2-ppk'
Adds support for Postquantum Preshared Keys for IKEv2. Fixes #2710.
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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, ¶ms))
|
||||
{
|
||||
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, ¶ms) &&
|
||||
private->sign(private, params->scheme, NULL, octets, auth_data))
|
||||
if (get_auth_octets_scheme(this, FALSE, id, this->ppk, &octets, ¶ms) &&
|
||||
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,
|
||||
¶ms) &&
|
||||
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, ¶ms))
|
||||
if (!get_auth_octets_scheme(this, TRUE, id, this->ppk, &octets, ¶ms))
|
||||
{
|
||||
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,
|
||||
},
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
Executable
+25
@@ -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
|
||||
}
|
||||
+41
@@ -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
|
||||
}
|
||||
+39
@@ -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
|
||||
}
|
||||
+44
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
Executable
+14
@@ -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
|
||||
Executable
+25
@@ -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
|
||||
Reference in New Issue
Block a user