diff options
Diffstat (limited to 'src/libcharon/sa')
-rw-r--r-- | src/libcharon/sa/ikev1/authenticators/pubkey_v1_authenticator.c | 4 | ||||
-rw-r--r-- | src/libcharon/sa/ikev1/iv_manager.c | 1 | ||||
-rw-r--r-- | src/libcharon/sa/ikev2/authenticators/pubkey_authenticator.c | 127 | ||||
-rw-r--r-- | src/libcharon/sa/ikev2/keymat_v2.h | 5 | ||||
-rw-r--r-- | src/libcharon/sa/ikev2/tasks/ike_init.c | 5 |
5 files changed, 88 insertions, 54 deletions
diff --git a/src/libcharon/sa/ikev1/authenticators/pubkey_v1_authenticator.c b/src/libcharon/sa/ikev1/authenticators/pubkey_v1_authenticator.c index 344c1bf5d..41be15a08 100644 --- a/src/libcharon/sa/ikev1/authenticators/pubkey_v1_authenticator.c +++ b/src/libcharon/sa/ikev1/authenticators/pubkey_v1_authenticator.c @@ -110,7 +110,7 @@ METHOD(authenticator_t, build, status_t, } free(dh.ptr); - if (private->sign(private, scheme, hash, &sig)) + if (private->sign(private, scheme, NULL, hash, &sig)) { sig_payload = hash_payload_create(PLV1_SIGNATURE); sig_payload->set_hash(sig_payload, sig); @@ -176,7 +176,7 @@ METHOD(authenticator_t, process, status_t, id, auth, TRUE); while (enumerator->enumerate(enumerator, &public, ¤t_auth)) { - if (public->verify(public, scheme, hash, sig)) + if (public->verify(public, scheme, NULL, hash, sig)) { DBG1(DBG_IKE, "authentication of '%Y' with %N successful", id, signature_scheme_names, scheme); diff --git a/src/libcharon/sa/ikev1/iv_manager.c b/src/libcharon/sa/ikev1/iv_manager.c index c9f737ccd..2a6e5c04f 100644 --- a/src/libcharon/sa/ikev1/iv_manager.c +++ b/src/libcharon/sa/ikev1/iv_manager.c @@ -15,6 +15,7 @@ #include "iv_manager.h" +#include <library.h> #include <collections/linked_list.h> /** diff --git a/src/libcharon/sa/ikev2/authenticators/pubkey_authenticator.c b/src/libcharon/sa/ikev2/authenticators/pubkey_authenticator.c index b2b1ef289..578a32902 100644 --- a/src/libcharon/sa/ikev2/authenticators/pubkey_authenticator.c +++ b/src/libcharon/sa/ikev2/authenticators/pubkey_authenticator.c @@ -1,8 +1,8 @@ /* - * Copyright (C) 2008-2015 Tobias Brunner + * Copyright (C) 2008-2017 Tobias Brunner * Copyright (C) 2005-2009 Martin Willi * Copyright (C) 2005 Jan Hutter - * Hochschule fuer Technik Rapperswil + * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -61,10 +61,9 @@ struct private_pubkey_authenticator_t { * Parse authentication data used for Signature Authentication as per RFC 7427 */ static bool parse_signature_auth_data(chunk_t *auth_data, key_type_t *key_type, - signature_scheme_t *scheme) + signature_params_t *params) { uint8_t len; - int oid; if (!auth_data->len) { @@ -72,14 +71,11 @@ static bool parse_signature_auth_data(chunk_t *auth_data, key_type_t *key_type, } len = auth_data->ptr[0]; *auth_data = chunk_skip(*auth_data, 1); - /* we currently don't support schemes that require parameters */ - oid = asn1_parse_algorithmIdentifier(*auth_data, 1, NULL); - *scheme = signature_scheme_from_oid(oid); - if (*scheme == SIGN_UNKNOWN) + if (!signature_params_parse(*auth_data, 1, params)) { return FALSE; } - *key_type = key_type_from_signature_scheme(*scheme); + *key_type = key_type_from_signature_scheme(params->scheme); *auth_data = chunk_skip(*auth_data, len); return TRUE; } @@ -88,18 +84,16 @@ static bool parse_signature_auth_data(chunk_t *auth_data, key_type_t *key_type, * Build authentication data used for Signature Authentication as per RFC 7427 */ static bool build_signature_auth_data(chunk_t *auth_data, - signature_scheme_t scheme) + signature_params_t *params) { chunk_t data; uint8_t len; - int oid; - oid = signature_scheme_to_oid(scheme); - if (oid == OID_UNKNOWN) + if (!signature_params_build(params, &data)) { + chunk_free(auth_data); return FALSE; } - data = asn1_algorithmIdentifier(oid); len = data.len; *auth_data = chunk_cat("cmm", chunk_from_thing(len), data, *auth_data); return TRUE; @@ -114,13 +108,13 @@ static array_t *select_signature_schemes(keymat_v2_t *keymat, { enumerator_t *enumerator; signature_scheme_t scheme; - uintptr_t config; + signature_params_t *config; auth_rule_t rule; key_type_t key_type; bool have_config = FALSE; array_t *selected; - selected = array_create(sizeof(signature_scheme_t), 0); + selected = array_create(0, 0); key_type = private->get_type(private); enumerator = auth->create_enumerator(auth); while (enumerator->enumerate(enumerator, &rule, &config)) @@ -130,12 +124,12 @@ static array_t *select_signature_schemes(keymat_v2_t *keymat, continue; } have_config = TRUE; - if (key_type == key_type_from_signature_scheme(config) && + if (key_type == key_type_from_signature_scheme(config->scheme) && keymat->hash_algorithm_supported(keymat, - hasher_from_signature_scheme(config))) + hasher_from_signature_scheme(config->scheme, + config->params))) { - scheme = config; - array_insert(selected, ARRAY_TAIL, &scheme); + array_insert(selected, ARRAY_TAIL, signature_params_clone(config)); } } enumerator->destroy(enumerator); @@ -146,12 +140,20 @@ static array_t *select_signature_schemes(keymat_v2_t *keymat, * and supported by the other peer */ enumerator = signature_schemes_for_key(key_type, private->get_keysize(private)); - while (enumerator->enumerate(enumerator, &scheme)) + while (enumerator->enumerate(enumerator, &config)) { + if (config->scheme == SIGN_RSA_EMSA_PSS && + !lib->settings->get_bool(lib->settings, "%s.rsa_pss", FALSE, + lib->ns)) + { + continue; + } if (keymat->hash_algorithm_supported(keymat, - hasher_from_signature_scheme(scheme))) + hasher_from_signature_scheme(config->scheme, + config->params))) { - array_insert(selected, ARRAY_TAIL, &scheme); + array_insert(selected, ARRAY_TAIL, + signature_params_clone(config)); } } enumerator->destroy(enumerator); @@ -180,9 +182,13 @@ static array_t *select_signature_schemes(keymat_v2_t *keymat, } } if (!found && keymat->hash_algorithm_supported(keymat, - hasher_from_signature_scheme(scheme))) + hasher_from_signature_scheme(scheme, + NULL))) { - array_insert(selected, ARRAY_TAIL, &scheme); + INIT(config, + .scheme = scheme, + ) + array_insert(selected, ARRAY_TAIL, config); } } } @@ -190,6 +196,12 @@ static array_t *select_signature_schemes(keymat_v2_t *keymat, return selected; } +CALLBACK(destroy_scheme, void, + signature_params_t *params, int idx, void *user) +{ + signature_params_destroy(params); +} + /** * Create a signature using RFC 7427 signature authentication */ @@ -199,7 +211,8 @@ static status_t sign_signature_auth(private_pubkey_authenticator_t *this, { enumerator_t *enumerator; keymat_v2_t *keymat; - signature_scheme_t scheme = SIGN_UNKNOWN, *schemep; + signature_scheme_t scheme = SIGN_UNKNOWN; + signature_params_t *params; array_t *schemes; chunk_t octets = chunk_empty; status_t status = FAILED; @@ -219,11 +232,12 @@ static status_t sign_signature_auth(private_pubkey_authenticator_t *this, schemes)) { enumerator = array_create_enumerator(schemes); - while (enumerator->enumerate(enumerator, &schemep)) + while (enumerator->enumerate(enumerator, ¶ms)) { - scheme = *schemep; - if (private->sign(private, scheme, octets, auth_data) && - build_signature_auth_data(auth_data, scheme)) + scheme = params->scheme; + if (private->sign(private, scheme, params->params, octets, + auth_data) && + build_signature_auth_data(auth_data, params)) { status = SUCCESS; break; @@ -240,7 +254,7 @@ static status_t sign_signature_auth(private_pubkey_authenticator_t *this, DBG1(DBG_IKE, "authentication of '%Y' (myself) with %N %s", id, signature_scheme_names, scheme, status == SUCCESS ? "successful" : "failed"); - array_destroy(schemes); + array_destroy_function(schemes, destroy_scheme, NULL); chunk_free(&octets); return status; } @@ -251,23 +265,27 @@ static status_t sign_signature_auth(private_pubkey_authenticator_t *this, */ static bool get_auth_octets_scheme(private_pubkey_authenticator_t *this, bool verify, identification_t *id, - chunk_t *octets, signature_scheme_t *scheme) + chunk_t *octets, signature_params_t **scheme) { keymat_v2_t *keymat; array_t *schemes; bool success = FALSE; - schemes = array_create(sizeof(signature_scheme_t), 0); - array_insert(schemes, ARRAY_TAIL, scheme); + schemes = array_create(0, 0); + array_insert(schemes, ARRAY_TAIL, *scheme); 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) && - array_get(schemes, 0, &scheme)) + array_remove(schemes, 0, scheme)) { success = TRUE; } - array_destroy(schemes); + else + { + *scheme = NULL; + } + array_destroy_function(schemes, destroy_scheme, NULL); return success; } @@ -280,6 +298,7 @@ static status_t sign_classic(private_pubkey_authenticator_t *this, chunk_t *auth_data) { signature_scheme_t scheme; + signature_params_t *params; chunk_t octets = chunk_empty; status_t status = FAILED; @@ -317,11 +336,18 @@ static status_t sign_classic(private_pubkey_authenticator_t *this, return FAILED; } - if (get_auth_octets_scheme(this, FALSE, id, &octets, &scheme) && - private->sign(private, scheme, octets, auth_data)) + INIT(params, + .scheme = scheme, + ); + if (get_auth_octets_scheme(this, FALSE, id, &octets, ¶ms) && + private->sign(private, params->scheme, NULL, octets, auth_data)) { status = SUCCESS; } + if (params) + { + signature_params_destroy(params); + } DBG1(DBG_IKE, "authentication of '%Y' (myself) with %N %s", id, auth_method_names, *auth_method, status == SUCCESS ? "successful" : "failed"); @@ -383,7 +409,7 @@ METHOD(authenticator_t, process, status_t, auth_cfg_t *auth, *current_auth; enumerator_t *enumerator; key_type_t key_type = KEY_ECDSA; - signature_scheme_t scheme; + signature_params_t *params; status_t status = NOT_FOUND; const char *reason = "unsupported"; bool online; @@ -393,25 +419,26 @@ 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); switch (auth_method) { case AUTH_RSA: key_type = KEY_RSA; - scheme = SIGN_RSA_EMSA_PKCS1_SHA1; + params->scheme = SIGN_RSA_EMSA_PKCS1_SHA1; break; case AUTH_ECDSA_256: - scheme = SIGN_ECDSA_256; + params->scheme = SIGN_ECDSA_256; break; case AUTH_ECDSA_384: - scheme = SIGN_ECDSA_384; + params->scheme = SIGN_ECDSA_384; break; case AUTH_ECDSA_521: - scheme = SIGN_ECDSA_521; + params->scheme = SIGN_ECDSA_521; break; case AUTH_DS: - if (parse_signature_auth_data(&auth_data, &key_type, &scheme)) + if (parse_signature_auth_data(&auth_data, &key_type, params)) { break; } @@ -420,10 +447,11 @@ METHOD(authenticator_t, process, status_t, default: DBG1(DBG_IKE, "%N authentication %s", auth_method_names, auth_method, reason); + signature_params_destroy(params); return INVALID_ARG; } id = this->ike_sa->get_other_id(this->ike_sa); - if (!get_auth_octets_scheme(this, TRUE, id, &octets, &scheme)) + if (!get_auth_octets_scheme(this, TRUE, id, &octets, ¶ms)) { return FAILED; } @@ -434,15 +462,17 @@ METHOD(authenticator_t, process, status_t, key_type, id, auth, online); while (enumerator->enumerate(enumerator, &public, ¤t_auth)) { - if (public->verify(public, scheme, octets, auth_data)) + if (public->verify(public, params->scheme, params->params, octets, + auth_data)) { DBG1(DBG_IKE, "authentication of '%Y' with %N successful", id, auth_method == AUTH_DS ? signature_scheme_names : auth_method_names, - auth_method == AUTH_DS ? scheme : auth_method); + auth_method == AUTH_DS ? params->scheme : auth_method); status = SUCCESS; auth->merge(auth, current_auth, FALSE); auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY); - auth->add(auth, AUTH_RULE_IKE_SIGNATURE_SCHEME, (uintptr_t)scheme); + auth->add(auth, AUTH_RULE_IKE_SIGNATURE_SCHEME, + signature_params_clone(params)); if (!online) { auth->add(auth, AUTH_RULE_CERT_VALIDATION_SUSPENDED, TRUE); @@ -457,6 +487,7 @@ METHOD(authenticator_t, process, status_t, } enumerator->destroy(enumerator); chunk_free(&octets); + signature_params_destroy(params); if (status == NOT_FOUND) { DBG1(DBG_IKE, "no trusted %N public key found for '%Y'", diff --git a/src/libcharon/sa/ikev2/keymat_v2.h b/src/libcharon/sa/ikev2/keymat_v2.h index 36bf149fe..084ed40f0 100644 --- a/src/libcharon/sa/ikev2/keymat_v2.h +++ b/src/libcharon/sa/ikev2/keymat_v2.h @@ -101,8 +101,9 @@ struct keymat_v2_t { * @param id identity * @param reserved reserved bytes of id_payload * @param octests chunk receiving allocated auth octets - * @param schemes array containing signature schemes in case they - * need to be modified by the keymat implementation + * @param schemes array containing signature schemes + * (signature_params_t*) in case they need to be + * modified by the keymat implementation * @return TRUE if octets created successfully */ bool (*get_auth_octets)(keymat_v2_t *this, bool verify, chunk_t ike_sa_init, diff --git a/src/libcharon/sa/ikev2/tasks/ike_init.c b/src/libcharon/sa/ikev2/tasks/ike_init.c index f974b9f58..d75d21715 100644 --- a/src/libcharon/sa/ikev2/tasks/ike_init.c +++ b/src/libcharon/sa/ikev2/tasks/ike_init.c @@ -158,7 +158,7 @@ static void send_supported_hash_algorithms(private_ike_init_t *this, peer_cfg_t *peer; auth_cfg_t *auth; auth_rule_t rule; - uintptr_t config; + signature_params_t *config; int written; size_t len = BUF_LEN; char buf[len]; @@ -177,7 +177,8 @@ static void send_supported_hash_algorithms(private_ike_init_t *this, { if (rule == AUTH_RULE_IKE_SIGNATURE_SCHEME) { - hash = hasher_from_signature_scheme(config); + hash = hasher_from_signature_scheme(config->scheme, + config->params); if (hasher_algorithm_for_ikev2(hash)) { algos->add(algos, hash); |