aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/libtls/tls_crypto.c138
-rw-r--r--src/libtls/tls_crypto.h30
-rw-r--r--src/libtls/tls_server.c72
3 files changed, 143 insertions, 97 deletions
diff --git a/src/libtls/tls_crypto.c b/src/libtls/tls_crypto.c
index 1f6179565..af0d6302f 100644
--- a/src/libtls/tls_crypto.c
+++ b/src/libtls/tls_crypto.c
@@ -624,6 +624,55 @@ METHOD(tls_crypto_t, select_cipher_suite, tls_cipher_suite_t,
return 0;
}
+METHOD(tls_crypto_t, get_signature_algorithms, void,
+ private_tls_crypto_t *this, tls_writer_t *writer)
+{
+ tls_writer_t *supported;
+ enumerator_t *enumerator;
+ hash_algorithm_t alg;
+ tls_hash_algorithm_t hash;
+
+ supported = tls_writer_create(32);
+ enumerator = lib->crypto->create_hasher_enumerator(lib->crypto);
+ while (enumerator->enumerate(enumerator, &alg))
+ {
+ switch (alg)
+ {
+ 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;
+ }
+ supported->write_uint8(supported, hash);
+ supported->write_uint8(supported, TLS_SIG_RSA);
+ if (alg != HASH_MD5 && alg != HASH_SHA224)
+ {
+ supported->write_uint8(supported, hash);
+ supported->write_uint8(supported, TLS_SIG_ECDSA);
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ writer->write_data16(writer, supported->get_buf(supported));
+ supported->destroy(supported);
+}
+
METHOD(tls_crypto_t, set_protection, void,
private_tls_crypto_t *this, tls_protection_t *protection)
{
@@ -642,9 +691,9 @@ METHOD(tls_crypto_t, append_handshake, void,
}
/**
- * Create a hash of the stored handshake data
+ * Create a hash using the suites HASH algorithm
*/
-static bool hash_handshake(private_tls_crypto_t *this, chunk_t *hash)
+static bool hash_data(private_tls_crypto_t *this, chunk_t data, chunk_t *hash)
{
if (this->tls->get_version(this->tls) >= TLS_1_2)
{
@@ -662,7 +711,7 @@ static bool hash_handshake(private_tls_crypto_t *this, chunk_t *hash)
DBG1(DBG_TLS, "%N not supported", hash_algorithm_names, alg->hash);
return FALSE;
}
- hasher->allocate_hash(hasher, this->handshake, hash);
+ hasher->allocate_hash(hasher, data, hash);
hasher->destroy(hasher);
}
else
@@ -676,7 +725,7 @@ static bool hash_handshake(private_tls_crypto_t *this, chunk_t *hash)
DBG1(DBG_TLS, "%N not supported", hash_algorithm_names, HASH_MD5);
return FALSE;
}
- md5->get_hash(md5, this->handshake, buf);
+ md5->get_hash(md5, data, buf);
md5->destroy(md5);
sha1 = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
if (!sha1)
@@ -684,7 +733,7 @@ static bool hash_handshake(private_tls_crypto_t *this, chunk_t *hash)
DBG1(DBG_TLS, "%N not supported", hash_algorithm_names, HASH_SHA1);
return FALSE;
}
- sha1->get_hash(sha1, this->handshake, buf + HASH_SIZE_MD5);
+ sha1->get_hash(sha1, data, buf + HASH_SIZE_MD5);
sha1->destroy(sha1);
*hash = chunk_clone(chunk_from_thing(buf));
@@ -745,9 +794,9 @@ static signature_scheme_t hashsig_to_scheme(key_type_t type,
}
}
-METHOD(tls_crypto_t, sign_handshake, bool,
+METHOD(tls_crypto_t, sign, bool,
private_tls_crypto_t *this, private_key_t *key, tls_writer_t *writer,
- chunk_t hashsig)
+ chunk_t data, chunk_t hashsig)
{
if (this->tls->get_version(this->tls) >= TLS_1_2)
{
@@ -757,6 +806,11 @@ METHOD(tls_crypto_t, sign_handshake, bool,
chunk_t sig;
bool done = FALSE;
+ if (!hashsig.len)
+ { /* fallback if none given */
+ hashsig = chunk_from_chars(
+ TLS_HASH_SHA1, TLS_SIG_RSA, TLS_HASH_SHA1, TLS_SIG_ECDSA);
+ }
reader = tls_reader_create(hashsig);
while (reader->remaining(reader) >= 2)
{
@@ -765,7 +819,7 @@ METHOD(tls_crypto_t, sign_handshake, bool,
{
scheme = hashsig_to_scheme(key->get_type(key), hash, alg);
if (scheme != SIGN_UNKNOWN &&
- key->sign(key, scheme, this->handshake, &sig))
+ key->sign(key, scheme, data, &sig))
{
done = TRUE;
break;
@@ -778,7 +832,7 @@ METHOD(tls_crypto_t, sign_handshake, bool,
DBG1(DBG_TLS, "none of the proposed hash/sig algorithms supported");
return FALSE;
}
- DBG2(DBG_TLS, "signed handshake data with %N/%N",
+ DBG2(DBG_TLS, "created signature with %N/%N",
tls_hash_algorithm_names, hash, tls_signature_algorithm_names, alg);
writer->write_uint8(writer, hash);
writer->write_uint8(writer, alg);
@@ -788,29 +842,29 @@ METHOD(tls_crypto_t, sign_handshake, bool,
else
{
chunk_t sig, hash;
+ bool done;
switch (key->get_type(key))
{
case KEY_RSA:
- if (!hash_handshake(this, &hash))
+ if (!hash_data(this, data, &hash))
{
return FALSE;
}
- if (!key->sign(key, SIGN_RSA_EMSA_PKCS1_NULL, hash, &sig))
+ done = key->sign(key, SIGN_RSA_EMSA_PKCS1_NULL, hash, &sig);
+ free(hash.ptr);
+ if (!done)
{
- free(hash.ptr);
return FALSE;
}
- DBG2(DBG_TLS, "signed handshake data with SHA1+MD5/RSA");
- free(hash.ptr);
+ DBG2(DBG_TLS, "created signature with MD5+SHA1/RSA");
break;
case KEY_ECDSA:
- if (!key->sign(key, SIGN_ECDSA_WITH_SHA1_DER,
- this->handshake, &sig))
+ if (!key->sign(key, SIGN_ECDSA_WITH_SHA1_DER, data, &sig))
{
return FALSE;
}
- DBG2(DBG_TLS, "signed handshake data with SHA1/ECDSA");
+ DBG2(DBG_TLS, "created signature with SHA1/ECDSA");
break;
default:
return FALSE;
@@ -821,8 +875,9 @@ METHOD(tls_crypto_t, sign_handshake, bool,
return TRUE;
}
-METHOD(tls_crypto_t, verify_handshake, bool,
- private_tls_crypto_t *this, public_key_t *key, tls_reader_t *reader)
+METHOD(tls_crypto_t, verify, bool,
+ private_tls_crypto_t *this, public_key_t *key, tls_reader_t *reader,
+ chunk_t data)
{
if (this->tls->get_version(this->tls) >= TLS_1_2)
{
@@ -834,56 +889,55 @@ METHOD(tls_crypto_t, verify_handshake, bool,
!reader->read_uint8(reader, &alg) ||
!reader->read_data16(reader, &sig))
{
- DBG1(DBG_TLS, "received invalid Certificate Verify");
+ DBG1(DBG_TLS, "received invalid signature");
return FALSE;
}
scheme = hashsig_to_scheme(key->get_type(key), hash, alg);
if (scheme == SIGN_UNKNOWN)
{
- DBG1(DBG_TLS, "Certificate Verify algorithms %N/%N not supported",
+ DBG1(DBG_TLS, "signature algorithms %N/%N not supported",
tls_hash_algorithm_names, hash,
tls_signature_algorithm_names, alg);
return FALSE;
}
- if (!key->verify(key, scheme, this->handshake, sig))
+ if (!key->verify(key, scheme, data, sig))
{
return FALSE;
}
- DBG2(DBG_TLS, "verified handshake data with %N/%N",
+ DBG2(DBG_TLS, "verified signature with %N/%N",
tls_hash_algorithm_names, hash, tls_signature_algorithm_names, alg);
}
else
{
chunk_t sig, hash;
+ bool done;
if (!reader->read_data16(reader, &sig))
{
- DBG1(DBG_TLS, "received invalid Certificate Verify");
+ DBG1(DBG_TLS, "received invalid signature");
return FALSE;
}
switch (key->get_type(key))
{
case KEY_RSA:
- if (!hash_handshake(this, &hash))
+ if (!hash_data(this, data, &hash))
{
return FALSE;
}
- if (!key->verify(key, SIGN_RSA_EMSA_PKCS1_NULL, hash, sig))
+ done = key->verify(key, SIGN_RSA_EMSA_PKCS1_NULL, hash, sig);
+ free(hash.ptr);
+ if (!done)
{
- free(hash.ptr);
return FALSE;
}
- DBG2(DBG_TLS, "verified handshake data with SHA1+MD5/RSA");
- free(hash.ptr);
+ DBG2(DBG_TLS, "verified signature data with MD5+SHA1/RSA");
break;
case KEY_ECDSA:
- if (!key->verify(key, SIGN_ECDSA_WITH_SHA1_DER,
- this->handshake, sig))
+ if (!key->verify(key, SIGN_ECDSA_WITH_SHA1_DER, data, sig))
{
- free(hash.ptr);
return FALSE;
}
- DBG2(DBG_TLS, "verified handshake data with SHA1/ECDSA");
+ DBG2(DBG_TLS, "verified signature with SHA1/ECDSA");
break;
default:
return FALSE;
@@ -892,6 +946,19 @@ METHOD(tls_crypto_t, verify_handshake, bool,
return TRUE;
}
+METHOD(tls_crypto_t, sign_handshake, bool,
+ private_tls_crypto_t *this, private_key_t *key, tls_writer_t *writer,
+ chunk_t hashsig)
+{
+ return sign(this, key, writer, this->handshake, hashsig);
+}
+
+METHOD(tls_crypto_t, verify_handshake, bool,
+ private_tls_crypto_t *this, public_key_t *key, tls_reader_t *reader)
+{
+ return verify(this, key, reader, this->handshake);
+}
+
METHOD(tls_crypto_t, calculate_finished, bool,
private_tls_crypto_t *this, char *label, char out[12])
{
@@ -901,7 +968,7 @@ METHOD(tls_crypto_t, calculate_finished, bool,
{
return FALSE;
}
- if (!hash_handshake(this, &seed))
+ if (!hash_data(this, this->handshake, &seed))
{
return FALSE;
}
@@ -1062,8 +1129,11 @@ tls_crypto_t *tls_crypto_create(tls_t *tls)
.public = {
.get_cipher_suites = _get_cipher_suites,
.select_cipher_suite = _select_cipher_suite,
+ .get_signature_algorithms = _get_signature_algorithms,
.set_protection = _set_protection,
.append_handshake = _append_handshake,
+ .sign = _sign,
+ .verify = _verify,
.sign_handshake = _sign_handshake,
.verify_handshake = _verify_handshake,
.calculate_finished = _calculate_finished,
diff --git a/src/libtls/tls_crypto.h b/src/libtls/tls_crypto.h
index be4005dad..833928a8a 100644
--- a/src/libtls/tls_crypto.h
+++ b/src/libtls/tls_crypto.h
@@ -329,6 +329,13 @@ struct tls_crypto_t {
tls_cipher_suite_t *suites, int count);
/**
+ * Write the list of supported hash/sig algorithms to writer.
+ *
+ * @param writer writer to write supported hash/sig algorithms
+ */
+ void (*get_signature_algorithms)(tls_crypto_t *this, tls_writer_t *writer);
+
+ /**
* Set the protection layer of the TLS stack to control it.
*
* @param protection protection layer to work on
@@ -345,6 +352,29 @@ struct tls_crypto_t {
tls_handshake_type_t type, chunk_t data);
/**
+ * Sign a blob of data, append signature to writer.
+ *
+ * @param key private key to use for signature
+ * @param writer TLS writer to write signature to
+ * @param data data to sign
+ * @param hashsig list of TLS1.2 hash/sig algorithms to select from
+ * @return TRUE if signature create successfully
+ */
+ bool (*sign)(tls_crypto_t *this, private_key_t *key,
+ tls_writer_t *writer, chunk_t data, chunk_t hashsig);
+
+ /**
+ * Verify a blob of data, read signature from a reader.
+ *
+ * @param key public key to verify signature with
+ * @param reader TLS reader to read signature from
+ * @param data data to verify signature
+ * @return TRUE if signature valid
+ */
+ bool (*verify)(tls_crypto_t *this, public_key_t *key,
+ tls_reader_t *reader, chunk_t data);
+
+ /**
* Create a signature of the handshake data using a given private key.
*
* @param key private key to use for signature
diff --git a/src/libtls/tls_server.c b/src/libtls/tls_server.c
index 493b07e69..9b38c7f7d 100644
--- a/src/libtls/tls_server.c
+++ b/src/libtls/tls_server.c
@@ -532,12 +532,16 @@ static status_t send_certificate(private_tls_server_t *this,
}
/**
- * Create a list of supported certificate types and hash/sig algorithms
+ * Send Certificate Request
*/
-static void get_supported_algorithms(private_tls_server_t *this,
- tls_writer_t *writer)
+static status_t send_certificate_request(private_tls_server_t *this,
+ tls_handshake_type_t *type, tls_writer_t *writer)
{
- tls_writer_t *supported;
+ tls_writer_t *authorities, *supported;
+ enumerator_t *enumerator;
+ certificate_t *cert;
+ x509_t *x509;
+ identification_t *id;
supported = tls_writer_create(4);
/* we propose both RSA and ECDSA */
@@ -545,68 +549,10 @@ static void get_supported_algorithms(private_tls_server_t *this,
supported->write_uint8(supported, TLS_ECDSA_SIGN);
writer->write_data8(writer, supported->get_buf(supported));
supported->destroy(supported);
-
if (this->tls->get_version(this->tls) >= TLS_1_2)
{
- enumerator_t *enumerator;
- hash_algorithm_t alg;
- tls_hash_algorithm_t hash;
-
- supported = tls_writer_create(32);
- enumerator = lib->crypto->create_hasher_enumerator(lib->crypto);
- while (enumerator->enumerate(enumerator, &alg))
- {
- switch (alg)
- {
- 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;
- }
- supported->write_uint8(supported, hash);
- supported->write_uint8(supported, TLS_SIG_RSA);
- if (alg != HASH_MD5 && alg != HASH_SHA224)
- {
- supported->write_uint8(supported, hash);
- supported->write_uint8(supported, TLS_SIG_ECDSA);
- }
- }
- enumerator->destroy(enumerator);
-
- writer->write_data16(writer, supported->get_buf(supported));
- supported->destroy(supported);
+ this->crypto->get_signature_algorithms(this->crypto, writer);
}
-}
-
-/**
- * Send Certificate Request
- */
-static status_t send_certificate_request(private_tls_server_t *this,
- tls_handshake_type_t *type, tls_writer_t *writer)
-{
- tls_writer_t *authorities;
- enumerator_t *enumerator;
- certificate_t *cert;
- x509_t *x509;
- identification_t *id;
-
- get_supported_algorithms(this, writer);
authorities = tls_writer_create(64);
enumerator = lib->credmgr->create_cert_enumerator(lib->credmgr,