aboutsummaryrefslogtreecommitdiffstats
path: root/src/libtls/tls_crypto.c
diff options
context:
space:
mode:
authorMartin Willi <martin@revosec.ch>2011-12-31 01:41:56 +0100
committerMartin Willi <martin@revosec.ch>2011-12-31 13:14:49 +0100
commit6a5c86b7ada9dd6a57290f228fd06b20cdf7011b (patch)
tree5879b5f15615624aef0c62d0c0230b6ca9bdf4e3 /src/libtls/tls_crypto.c
parentca5767621ba5491b2a2a0c011178249124f32cf7 (diff)
downloadstrongswan-6a5c86b7ada9dd6a57290f228fd06b20cdf7011b.tar.bz2
strongswan-6a5c86b7ada9dd6a57290f228fd06b20cdf7011b.tar.xz
Implemented TLS session resumption both as client and as server
Diffstat (limited to 'src/libtls/tls_crypto.c')
-rw-r--r--src/libtls/tls_crypto.c104
1 files changed, 81 insertions, 23 deletions
diff --git a/src/libtls/tls_crypto.c b/src/libtls/tls_crypto.c
index 98c504973..7487da96d 100644
--- a/src/libtls/tls_crypto.c
+++ b/src/libtls/tls_crypto.c
@@ -370,6 +370,11 @@ struct private_tls_crypto_t {
tls_t *tls;
/**
+ * TLS session cache
+ */
+ tls_cache_t *cache;
+
+ /**
* All handshake data concatentated
*/
chunk_t handshake;
@@ -1462,13 +1467,15 @@ METHOD(tls_crypto_t, calculate_finished, bool,
return TRUE;
}
-METHOD(tls_crypto_t, derive_secrets, void,
- private_tls_crypto_t *this, chunk_t premaster,
- chunk_t client_random, chunk_t server_random)
+/**
+ * Derive master secret from premaster, optionally save session
+ */
+static void derive_master(private_tls_crypto_t *this, chunk_t premaster,
+ chunk_t session, identification_t *id,
+ chunk_t client_random, chunk_t server_random)
{
char master[48];
- chunk_t seed, block, client_write, server_write;
- int mks, eks = 0, ivs = 0;
+ chunk_t seed;
/* derive master secret */
seed = chunk_cata("cc", client_random, server_random);
@@ -1477,7 +1484,22 @@ METHOD(tls_crypto_t, derive_secrets, void,
sizeof(master), master);
this->prf->set_key(this->prf, chunk_from_thing(master));
- memset(master, 0, sizeof(master));
+ if (this->cache && session.len)
+ {
+ this->cache->create(this->cache, session, id, chunk_from_thing(master),
+ this->suite);
+ }
+ memwipe(master, sizeof(master));
+}
+
+/**
+ * Expand key material from master secret
+ */
+static void expand_keys(private_tls_crypto_t *this,
+ chunk_t client_random, chunk_t server_random)
+{
+ chunk_t seed, block, client_write, server_write;
+ int mks, eks = 0, ivs = 0;
/* derive key block for key expansion */
mks = this->signer_out->get_key_size(this->signer_out);
@@ -1546,6 +1568,55 @@ METHOD(tls_crypto_t, derive_secrets, void,
}
}
}
+
+ /* EAP-MSK */
+ if (this->msk_label)
+ {
+ this->msk = chunk_alloc(64);
+ this->prf->get_bytes(this->prf, this->msk_label, seed,
+ this->msk.len, this->msk.ptr);
+ }
+}
+
+METHOD(tls_crypto_t, derive_secrets, void,
+ private_tls_crypto_t *this, chunk_t premaster, chunk_t session,
+ identification_t *id, chunk_t client_random, chunk_t server_random)
+{
+ derive_master(this, premaster, session, id, client_random, server_random);
+ expand_keys(this, client_random, server_random);
+}
+
+METHOD(tls_crypto_t, resume_session, tls_cipher_suite_t,
+ private_tls_crypto_t *this, chunk_t session, identification_t *id,
+ chunk_t client_random, chunk_t server_random)
+{
+ chunk_t master;
+
+ if (this->cache && session.len)
+ {
+ this->suite = this->cache->lookup(this->cache, session, id, &master);
+ if (this->suite)
+ {
+ select_cipher_suite(this, &this->suite, 1, KEY_ANY);
+ if (this->suite)
+ {
+ this->prf->set_key(this->prf, master);
+ expand_keys(this, client_random, server_random);
+ }
+ chunk_clear(&master);
+ }
+ }
+ return this->suite;
+}
+
+METHOD(tls_crypto_t, get_session, chunk_t,
+ private_tls_crypto_t *this, identification_t *server)
+{
+ if (this->cache)
+ {
+ return this->cache->check(this->cache, server);
+ }
+ return chunk_empty;
}
METHOD(tls_crypto_t, change_cipher, void,
@@ -1566,21 +1637,6 @@ METHOD(tls_crypto_t, change_cipher, void,
}
}
-METHOD(tls_crypto_t, derive_eap_msk, void,
- private_tls_crypto_t *this, chunk_t client_random, chunk_t server_random)
-{
- if (this->msk_label)
- {
- chunk_t seed;
-
- seed = chunk_cata("cc", client_random, server_random);
- free(this->msk.ptr);
- this->msk = chunk_alloc(64);
- this->prf->get_bytes(this->prf, this->msk_label, seed,
- this->msk.len, this->msk.ptr);
- }
-}
-
METHOD(tls_crypto_t, get_eap_msk, chunk_t,
private_tls_crypto_t *this)
{
@@ -1606,7 +1662,7 @@ METHOD(tls_crypto_t, destroy, void,
/**
* See header
*/
-tls_crypto_t *tls_crypto_create(tls_t *tls)
+tls_crypto_t *tls_crypto_create(tls_t *tls, tls_cache_t *cache)
{
private_tls_crypto_t *this;
enumerator_t *enumerator;
@@ -1628,12 +1684,14 @@ tls_crypto_t *tls_crypto_create(tls_t *tls)
.verify_handshake = _verify_handshake,
.calculate_finished = _calculate_finished,
.derive_secrets = _derive_secrets,
+ .resume_session = _resume_session,
+ .get_session = _get_session,
.change_cipher = _change_cipher,
- .derive_eap_msk = _derive_eap_msk,
.get_eap_msk = _get_eap_msk,
.destroy = _destroy,
},
.tls = tls,
+ .cache = cache,
);
enumerator = lib->creds->create_builder_enumerator(lib->creds);