summaryrefslogtreecommitdiff
path: root/src/libcharon/sa/ikev2/authenticators
diff options
context:
space:
mode:
authorYves-Alexis Perez <corsac@debian.org>2018-09-24 15:11:14 +0200
committerYves-Alexis Perez <corsac@debian.org>2018-09-24 15:11:14 +0200
commite0e280b7669435b991b7e457abd8aa450930b3e8 (patch)
tree3e6084f13b14ad2df104e2ce6e589eb96c5f7ac9 /src/libcharon/sa/ikev2/authenticators
parent51a71ee15c1bcf0e82f363a16898f571e211f9c3 (diff)
downloadvyos-strongswan-e0e280b7669435b991b7e457abd8aa450930b3e8.tar.gz
vyos-strongswan-e0e280b7669435b991b7e457abd8aa450930b3e8.zip
New upstream version 5.7.0
Diffstat (limited to 'src/libcharon/sa/ikev2/authenticators')
-rw-r--r--src/libcharon/sa/ikev2/authenticators/eap_authenticator.c56
-rw-r--r--src/libcharon/sa/ikev2/authenticators/psk_authenticator.c60
-rw-r--r--src/libcharon/sa/ikev2/authenticators/pubkey_authenticator.c171
3 files changed, 231 insertions, 56 deletions
diff --git a/src/libcharon/sa/ikev2/authenticators/eap_authenticator.c b/src/libcharon/sa/ikev2/authenticators/eap_authenticator.c
index bcf262725..e1e6cd7ee 100644
--- a/src/libcharon/sa/ikev2/authenticators/eap_authenticator.c
+++ b/src/libcharon/sa/ikev2/authenticators/eap_authenticator.c
@@ -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
*
@@ -65,6 +65,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
*/
eap_method_t *method;
@@ -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,
},
diff --git a/src/libcharon/sa/ikev2/authenticators/psk_authenticator.c b/src/libcharon/sa/ikev2/authenticators/psk_authenticator.c
index c1decb130..76571e702 100644
--- a/src/libcharon/sa/ikev2/authenticators/psk_authenticator.c
+++ b/src/libcharon/sa/ikev2/authenticators/psk_authenticator.c
@@ -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,
},
diff --git a/src/libcharon/sa/ikev2/authenticators/pubkey_authenticator.c b/src/libcharon/sa/ikev2/authenticators/pubkey_authenticator.c
index 652b837fe..1fcef03cc 100644
--- a/src/libcharon/sa/ikev2/authenticators/pubkey_authenticator.c
+++ b/src/libcharon/sa/ikev2/authenticators/pubkey_authenticator.c
@@ -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;
};
/**
@@ -204,17 +214,42 @@ CALLBACK(destroy_scheme, void,
}
/**
+ * Adds the given auth data to the message, either in an AUTH payload or
+ * a NO_PPK_AUTH notify.
+ *
+ * The data is freed.
+ */
+static void add_auth_to_message(message_t *message, auth_method_t method,
+ chunk_t data, bool notify)
+{
+ auth_payload_t *auth_payload;
+
+ if (notify)
+ {
+ message->add_notify(message, FALSE, NO_PPK_AUTH, data);
+ }
+ else
+ {
+ auth_payload = auth_payload_create();
+ auth_payload->set_auth_method(auth_payload, method);
+ auth_payload->set_data(auth_payload, data);
+ message->add_payload(message, (payload_t*)auth_payload);
+ }
+ chunk_free(&data);
+}
+
+/**
* Create a signature using RFC 7427 signature authentication
*/
static status_t sign_signature_auth(private_pubkey_authenticator_t *this,
- auth_cfg_t *auth, private_key_t *private,
- identification_t *id, chunk_t *auth_data)
+ auth_cfg_t *auth, private_key_t *private,
+ identification_t *id, message_t *message)
{
enumerator_t *enumerator;
keymat_v2_t *keymat;
signature_params_t *params = NULL;
array_t *schemes;
- chunk_t octets = chunk_empty;
+ chunk_t octets = chunk_empty, auth_data;
status_t status = FAILED;
keymat = (keymat_v2_t*)this->ike_sa->get_keymat(this->ike_sa);
@@ -227,26 +262,46 @@ static status_t sign_signature_auth(private_pubkey_authenticator_t *this,
return FAILED;
}
- if (keymat->get_auth_octets(keymat, FALSE, this->ike_sa_init,
- this->nonce, id, this->reserved, &octets,
- schemes))
+ if (keymat->get_auth_octets(keymat, FALSE, this->ike_sa_init, this->nonce,
+ this->ppk, id, this->reserved, &octets, schemes))
{
enumerator = array_create_enumerator(schemes);
while (enumerator->enumerate(enumerator, &params))
{
- if (private->sign(private, params->scheme, params->params, octets,
- auth_data) &&
- build_signature_auth_data(auth_data, params))
- {
- status = SUCCESS;
- break;
- }
- else
+ if (!private->sign(private, params->scheme, params->params, octets,
+ &auth_data) ||
+ !build_signature_auth_data(&auth_data, params))
{
DBG2(DBG_IKE, "unable to create %N signature for %N key",
signature_scheme_names, params->scheme, key_type_names,
private->get_type(private));
+ continue;
}
+ add_auth_to_message(message, AUTH_DS, auth_data, FALSE);
+ status = SUCCESS;
+
+ if (this->no_ppk_auth)
+ {
+ chunk_free(&octets);
+
+ if (keymat->get_auth_octets(keymat, FALSE, this->ike_sa_init,
+ this->nonce, chunk_empty, id,
+ this->reserved, &octets, schemes) &&
+ private->sign(private, params->scheme, params->params,
+ octets, &auth_data) &&
+ build_signature_auth_data(&auth_data, params))
+ {
+ add_auth_to_message(message, AUTH_DS, auth_data, TRUE);
+ }
+ else
+ {
+ DBG2(DBG_IKE, "unable to create %N signature for %N key "
+ "without PPK", signature_scheme_names, params->scheme,
+ key_type_names, private->get_type(private));
+ status = FAILED;
+ }
+ }
+ break;
}
enumerator->destroy(enumerator);
}
@@ -281,8 +336,8 @@ static status_t sign_signature_auth(private_pubkey_authenticator_t *this,
* keymat).
*/
static bool get_auth_octets_scheme(private_pubkey_authenticator_t *this,
- bool verify, identification_t *id,
- chunk_t *octets, signature_params_t **scheme)
+ bool verify, identification_t *id, chunk_t ppk,
+ chunk_t *octets, signature_params_t **scheme)
{
keymat_v2_t *keymat;
array_t *schemes;
@@ -293,7 +348,8 @@ static bool get_auth_octets_scheme(private_pubkey_authenticator_t *this,
keymat = (keymat_v2_t*)this->ike_sa->get_keymat(this->ike_sa);
if (keymat->get_auth_octets(keymat, verify, this->ike_sa_init, this->nonce,
- id, this->reserved, octets, schemes) &&
+ ppk, id, this->reserved, octets,
+ schemes) &&
array_remove(schemes, 0, scheme))
{
success = TRUE;
@@ -311,19 +367,19 @@ static bool get_auth_octets_scheme(private_pubkey_authenticator_t *this,
*/
static status_t sign_classic(private_pubkey_authenticator_t *this,
auth_cfg_t *auth, private_key_t *private,
- identification_t *id, auth_method_t *auth_method,
- chunk_t *auth_data)
+ identification_t *id, message_t *message)
{
signature_scheme_t scheme;
signature_params_t *params;
- chunk_t octets = chunk_empty;
+ auth_method_t auth_method = AUTH_NONE;
+ chunk_t octets = chunk_empty, auth_data;
status_t status = FAILED;
switch (private->get_type(private))
{
case KEY_RSA:
scheme = SIGN_RSA_EMSA_PKCS1_SHA1;
- *auth_method = AUTH_RSA;
+ auth_method = AUTH_RSA;
break;
case KEY_ECDSA:
/* deduct the signature scheme from the keysize */
@@ -331,15 +387,15 @@ static status_t sign_classic(private_pubkey_authenticator_t *this,
{
case 256:
scheme = SIGN_ECDSA_256;
- *auth_method = AUTH_ECDSA_256;
+ auth_method = AUTH_ECDSA_256;
break;
case 384:
scheme = SIGN_ECDSA_384;
- *auth_method = AUTH_ECDSA_384;
+ auth_method = AUTH_ECDSA_384;
break;
case 521:
scheme = SIGN_ECDSA_521;
- *auth_method = AUTH_ECDSA_521;
+ auth_method = AUTH_ECDSA_521;
break;
default:
DBG1(DBG_IKE, "%d bit ECDSA private key size not supported",
@@ -356,17 +412,34 @@ static status_t sign_classic(private_pubkey_authenticator_t *this,
INIT(params,
.scheme = scheme,
);
- if (get_auth_octets_scheme(this, FALSE, id, &octets, &params) &&
- private->sign(private, params->scheme, NULL, octets, auth_data))
+ if (get_auth_octets_scheme(this, FALSE, id, this->ppk, &octets, &params) &&
+ private->sign(private, params->scheme, NULL, octets, &auth_data))
{
+ add_auth_to_message(message, auth_method, auth_data, FALSE);
status = SUCCESS;
+
+ if (this->no_ppk_auth)
+ {
+ chunk_free(&octets);
+ if (get_auth_octets_scheme(this, FALSE, id, chunk_empty, &octets,
+ &params) &&
+ private->sign(private, params->scheme, NULL, octets,
+ &auth_data))
+ {
+ add_auth_to_message(message, auth_method, auth_data, TRUE);
+ }
+ else
+ {
+ status = FAILED;
+ }
+ }
}
if (params)
{
signature_params_destroy(params);
}
DBG1(DBG_IKE, "authentication of '%Y' (myself) with %N %s", id,
- auth_method_names, *auth_method,
+ auth_method_names, auth_method,
status == SUCCESS ? "successful" : "failed");
chunk_free(&octets);
return status;
@@ -378,10 +451,7 @@ METHOD(authenticator_t, build, status_t,
private_key_t *private;
identification_t *id;
auth_cfg_t *auth;
- chunk_t auth_data;
status_t status;
- auth_payload_t *auth_payload;
- auth_method_t auth_method = AUTH_NONE;
id = this->ike_sa->get_my_id(this->ike_sa);
auth = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
@@ -394,24 +464,13 @@ METHOD(authenticator_t, build, status_t,
if (this->ike_sa->supports_extension(this->ike_sa, EXT_SIGNATURE_AUTH))
{
- auth_method = AUTH_DS;
- status = sign_signature_auth(this, auth, private, id, &auth_data);
+ status = sign_signature_auth(this, auth, private, id, message);
}
else
{
- status = sign_classic(this, auth, private, id, &auth_method,
- &auth_data);
+ status = sign_classic(this, auth, private, id, message);
}
private->destroy(private);
-
- if (status == SUCCESS)
- {
- auth_payload = auth_payload_create();
- auth_payload->set_auth_method(auth_payload, auth_method);
- auth_payload->set_data(auth_payload, auth_data);
- chunk_free(&auth_data);
- message->add_payload(message, (payload_t*)auth_payload);
- }
return status;
}
@@ -444,6 +503,7 @@ METHOD(authenticator_t, process, status_t,
public_key_t *public;
auth_method_t auth_method;
auth_payload_t *auth_payload;
+ notify_payload_t *notify;
chunk_t auth_data, octets;
identification_t *id;
auth_cfg_t *auth, *current_auth;
@@ -459,9 +519,21 @@ METHOD(authenticator_t, process, status_t,
{
return FAILED;
}
- INIT(params);
auth_method = auth_payload->get_auth_method(auth_payload);
auth_data = auth_payload->get_data(auth_payload);
+
+ if (this->ike_sa->supports_extension(this->ike_sa, EXT_PPK) &&
+ !this->ppk.ptr)
+ { /* look for a NO_PPK_AUTH notify if we have no PPK */
+ notify = message->get_notify(message, NO_PPK_AUTH);
+ if (notify)
+ {
+ DBG1(DBG_IKE, "no PPK available, using NO_PPK_AUTH notify");
+ auth_data = notify->get_notification_data(notify);
+ }
+ }
+
+ INIT(params);
switch (auth_method)
{
case AUTH_RSA:
@@ -491,7 +563,7 @@ METHOD(authenticator_t, process, status_t,
return INVALID_ARG;
}
id = this->ike_sa->get_other_id(this->ike_sa);
- if (!get_auth_octets_scheme(this, TRUE, id, &octets, &params))
+ if (!get_auth_octets_scheme(this, TRUE, id, this->ppk, &octets, &params))
{
return FAILED;
}
@@ -551,6 +623,13 @@ METHOD(authenticator_t, process, status_t,
return status;
}
+METHOD(authenticator_t, use_ppk, void,
+ private_pubkey_authenticator_t *this, chunk_t ppk, bool no_ppk_auth)
+{
+ this->ppk = ppk;
+ this->no_ppk_auth = no_ppk_auth;
+}
+
METHOD(authenticator_t, destroy, void,
private_pubkey_authenticator_t *this)
{
@@ -571,6 +650,7 @@ pubkey_authenticator_t *pubkey_authenticator_create_builder(ike_sa_t *ike_sa,
.authenticator = {
.build = _build,
.process = (void*)return_failed,
+ .use_ppk = _use_ppk,
.is_mutual = (void*)return_false,
.destroy = _destroy,
},
@@ -598,6 +678,7 @@ pubkey_authenticator_t *pubkey_authenticator_create_verifier(ike_sa_t *ike_sa,
.authenticator = {
.build = (void*)return_failed,
.process = _process,
+ .use_ppk = _use_ppk,
.is_mutual = (void*)return_false,
.destroy = _destroy,
},