aboutsummaryrefslogtreecommitdiffstats
path: root/src/libcharon/sa
diff options
context:
space:
mode:
authorTobias Brunner <tobias@strongswan.org>2017-11-08 16:48:37 +0100
committerTobias Brunner <tobias@strongswan.org>2017-11-08 16:53:35 +0100
commit1c4b392a5b2badf05e86478da7370fef55b11329 (patch)
tree004082e4053fa6e0bfebe0f098f43a85a5c9f7c0 /src/libcharon/sa
parent43b59d13239e0d9593649b77bdea3651150f6132 (diff)
parentfde0c763b6c1066d206dad3d09920e8e900f6f18 (diff)
downloadstrongswan-1c4b392a5b2badf05e86478da7370fef55b11329.tar.bz2
strongswan-1c4b392a5b2badf05e86478da7370fef55b11329.tar.xz
Merge branch 'rsassa-pss'
This adds support for RSASSA-PSS signatures in IKEv2 digital signature authentication (RFC 7427), certificates and CRLs etc., and when signing credentials via pki tool. For interoperability with older versions, the default is to use classic PKCS#1 signatures. To use PSS padding either enable rsa_pss via strongswan.conf or explicitly use it either via ike:rsa/pss... auth token or the --rsa-padding option of the pki tool. References #2427.
Diffstat (limited to 'src/libcharon/sa')
-rw-r--r--src/libcharon/sa/ikev1/authenticators/pubkey_v1_authenticator.c4
-rw-r--r--src/libcharon/sa/ikev1/iv_manager.c1
-rw-r--r--src/libcharon/sa/ikev2/authenticators/pubkey_authenticator.c127
-rw-r--r--src/libcharon/sa/ikev2/keymat_v2.h5
-rw-r--r--src/libcharon/sa/ikev2/tasks/ike_init.c5
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, &current_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, &params))
{
- 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, &params) &&
+ 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, &params))
{
return FAILED;
}
@@ -434,15 +462,17 @@ METHOD(authenticator_t, process, status_t,
key_type, id, auth, online);
while (enumerator->enumerate(enumerator, &public, &current_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);