diff options
author | Yves-Alexis Perez <corsac@debian.org> | 2018-09-24 15:11:14 +0200 |
---|---|---|
committer | Yves-Alexis Perez <corsac@debian.org> | 2018-09-24 15:11:14 +0200 |
commit | e0e280b7669435b991b7e457abd8aa450930b3e8 (patch) | |
tree | 3e6084f13b14ad2df104e2ce6e589eb96c5f7ac9 /src/libcharon/sa/ikev2/authenticators | |
parent | 51a71ee15c1bcf0e82f363a16898f571e211f9c3 (diff) | |
download | vyos-strongswan-e0e280b7669435b991b7e457abd8aa450930b3e8.tar.gz vyos-strongswan-e0e280b7669435b991b7e457abd8aa450930b3e8.zip |
New upstream version 5.7.0
Diffstat (limited to 'src/libcharon/sa/ikev2/authenticators')
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, ¶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, }, |