aboutsummaryrefslogtreecommitdiffstats
path: root/src/libtls/tls_crypto.c
diff options
context:
space:
mode:
authorMartin Willi <martin@revosec.ch>2014-01-15 15:51:03 +0100
committerMartin Willi <martin@revosec.ch>2014-03-31 15:56:12 +0200
commit48d6b57c30f799e1773adbfdd5e1880bab2ab9e4 (patch)
tree1d12b0e1251b31aa1b736e9f12356c8c09f4a5d5 /src/libtls/tls_crypto.c
parentd06890d6e2bcea757c20cdf192badfd17fac8172 (diff)
downloadstrongswan-48d6b57c30f799e1773adbfdd5e1880bab2ab9e4.tar.bz2
strongswan-48d6b57c30f799e1773adbfdd5e1880bab2ab9e4.tar.xz
tls: Offer TLS signature schemes in ClientHello in order of preference
Additionally, we now query plugin features to find out what schemes we exactly support.
Diffstat (limited to 'src/libtls/tls_crypto.c')
-rw-r--r--src/libtls/tls_crypto.c149
1 files changed, 59 insertions, 90 deletions
diff --git a/src/libtls/tls_crypto.c b/src/libtls/tls_crypto.c
index 0783b12b0..a4e24543b 100644
--- a/src/libtls/tls_crypto.c
+++ b/src/libtls/tls_crypto.c
@@ -1,6 +1,6 @@
/*
- * Copyright (C) 2010 Martin Willi
- * Copyright (C) 2010 revosec AG
+ * Copyright (C) 2010-2014 Martin Willi
+ * Copyright (C) 2010-2014 revosec AG
*
* 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
@@ -16,6 +16,7 @@
#include "tls_crypto.h"
#include <utils/debug.h>
+#include <plugins/plugin_feature.h>
ENUM_BEGIN(tls_cipher_suite_names, TLS_NULL_WITH_NULL_NULL,
TLS_DH_anon_WITH_3DES_EDE_CBC_SHA,
@@ -1166,54 +1167,52 @@ METHOD(tls_crypto_t, get_dh_group, diffie_hellman_group_t,
return MODP_NONE;
}
+/**
+ * Map signature schemes to TLS key types and hashes, ordered by preference
+ */
+static struct {
+ tls_signature_algorithm_t sig;
+ tls_hash_algorithm_t hash;
+ signature_scheme_t scheme;
+} schemes[] = {
+ { TLS_SIG_ECDSA, TLS_HASH_SHA256, SIGN_ECDSA_WITH_SHA256_DER },
+ { TLS_SIG_ECDSA, TLS_HASH_SHA384, SIGN_ECDSA_WITH_SHA384_DER },
+ { TLS_SIG_ECDSA, TLS_HASH_SHA512, SIGN_ECDSA_WITH_SHA512_DER },
+ { TLS_SIG_ECDSA, TLS_HASH_SHA1, SIGN_ECDSA_WITH_SHA1_DER },
+ { TLS_SIG_RSA, TLS_HASH_SHA256, SIGN_RSA_EMSA_PKCS1_SHA256 },
+ { TLS_SIG_RSA, TLS_HASH_SHA384, SIGN_RSA_EMSA_PKCS1_SHA384 },
+ { TLS_SIG_RSA, TLS_HASH_SHA512, SIGN_RSA_EMSA_PKCS1_SHA512 },
+ { TLS_SIG_RSA, TLS_HASH_SHA224, SIGN_RSA_EMSA_PKCS1_SHA224 },
+ { TLS_SIG_RSA, TLS_HASH_SHA1, SIGN_RSA_EMSA_PKCS1_SHA1 },
+ { TLS_SIG_RSA, TLS_HASH_MD5, SIGN_RSA_EMSA_PKCS1_MD5 },
+};
+
METHOD(tls_crypto_t, get_signature_algorithms, void,
private_tls_crypto_t *this, bio_writer_t *writer)
{
bio_writer_t *supported;
- enumerator_t *enumerator;
- hash_algorithm_t alg;
- tls_hash_algorithm_t hash;
- const char *plugin_name;
+ int i;
supported = bio_writer_create(32);
- enumerator = lib->crypto->create_hasher_enumerator(lib->crypto);
- while (enumerator->enumerate(enumerator, &alg, &plugin_name))
+
+ for (i = 0; i < countof(schemes); i++)
{
- switch (alg)
+ if (schemes[i].sig == TLS_SIG_RSA && !this->rsa)
{
- case HASH_MD5:
- hash = TLS_HASH_MD5;
- break;
- case HASH_SHA1:
- hash = TLS_HASH_SHA1;
- break;
- case HASH_SHA224:
- hash = TLS_HASH_SHA224;
- break;
- case HASH_SHA256:
- hash = TLS_HASH_SHA256;
- break;
- case HASH_SHA384:
- hash = TLS_HASH_SHA384;
- break;
- case HASH_SHA512:
- hash = TLS_HASH_SHA512;
- break;
- default:
- continue;
+ continue;
}
- if (this->rsa)
+ if (schemes[i].sig == TLS_SIG_ECDSA && !this->ecdsa)
{
- supported->write_uint8(supported, hash);
- supported->write_uint8(supported, TLS_SIG_RSA);
+ continue;
}
- if (this->ecdsa && alg != HASH_MD5 && alg != HASH_SHA224)
- { /* currently we have no signature scheme for MD5/SHA224 */
- supported->write_uint8(supported, hash);
- supported->write_uint8(supported, TLS_SIG_ECDSA);
+ if (!lib->plugins->has_feature(lib->plugins,
+ PLUGIN_PROVIDE(PUBKEY_VERIFY, schemes[i].scheme)))
+ {
+ continue;
}
+ supported->write_uint8(supported, schemes[i].hash);
+ supported->write_uint8(supported, schemes[i].sig);
}
- enumerator->destroy(enumerator);
supported->wrap16(supported);
writer->write_data16(writer, supported->get_buf(supported));
@@ -1221,6 +1220,29 @@ METHOD(tls_crypto_t, get_signature_algorithms, void,
}
/**
+ * Get the signature scheme from a TLS 1.2 hash/sig algorithm pair
+ */
+static signature_scheme_t hashsig_to_scheme(key_type_t type,
+ tls_hash_algorithm_t hash,
+ tls_signature_algorithm_t sig)
+{
+ int i;
+
+ if ((sig == TLS_SIG_RSA && type == KEY_RSA) ||
+ (sig == TLS_SIG_ECDSA && type == KEY_ECDSA))
+ {
+ for (i = 0; i < countof(schemes); i++)
+ {
+ if (schemes[i].sig == sig && schemes[i].hash == hash)
+ {
+ return schemes[i].scheme;
+ }
+ }
+ }
+ return SIGN_UNKNOWN;
+}
+
+/**
* Mapping groups to TLS named curves
*/
static struct {
@@ -1337,59 +1359,6 @@ static bool hash_data(private_tls_crypto_t *this, chunk_t data, chunk_t *hash)
return TRUE;
}
-/**
- * Get the signature scheme from a TLS 1.2 hash/sig algorithm pair
- */
-static signature_scheme_t hashsig_to_scheme(key_type_t type,
- tls_hash_algorithm_t hash, tls_signature_algorithm_t sig)
-{
- switch (sig)
- {
- case TLS_SIG_RSA:
- if (type != KEY_RSA)
- {
- return SIGN_UNKNOWN;
- }
- switch (hash)
- {
- case TLS_HASH_MD5:
- return SIGN_RSA_EMSA_PKCS1_MD5;
- case TLS_HASH_SHA1:
- return SIGN_RSA_EMSA_PKCS1_SHA1;
- case TLS_HASH_SHA224:
- return SIGN_RSA_EMSA_PKCS1_SHA224;
- case TLS_HASH_SHA256:
- return SIGN_RSA_EMSA_PKCS1_SHA256;
- case TLS_HASH_SHA384:
- return SIGN_RSA_EMSA_PKCS1_SHA384;
- case TLS_HASH_SHA512:
- return SIGN_RSA_EMSA_PKCS1_SHA512;
- default:
- return SIGN_UNKNOWN;
- }
- case TLS_SIG_ECDSA:
- if (type != KEY_ECDSA)
- {
- return SIGN_UNKNOWN;
- }
- switch (hash)
- {
- case TLS_HASH_SHA224:
- return SIGN_ECDSA_WITH_SHA1_DER;
- case TLS_HASH_SHA256:
- return SIGN_ECDSA_WITH_SHA256_DER;
- case TLS_HASH_SHA384:
- return SIGN_ECDSA_WITH_SHA384_DER;
- case TLS_HASH_SHA512:
- return SIGN_ECDSA_WITH_SHA512_DER;
- default:
- return SIGN_UNKNOWN;
- }
- default:
- return SIGN_UNKNOWN;
- }
-}
-
METHOD(tls_crypto_t, sign, bool,
private_tls_crypto_t *this, private_key_t *key, bio_writer_t *writer,
chunk_t data, chunk_t hashsig)