diff options
author | Martin Willi <martin@revosec.ch> | 2011-12-31 01:41:56 +0100 |
---|---|---|
committer | Martin Willi <martin@revosec.ch> | 2011-12-31 13:14:49 +0100 |
commit | 6a5c86b7ada9dd6a57290f228fd06b20cdf7011b (patch) | |
tree | 5879b5f15615624aef0c62d0c0230b6ca9bdf4e3 /src/libtls/tls_crypto.c | |
parent | ca5767621ba5491b2a2a0c011178249124f32cf7 (diff) | |
download | strongswan-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.c | 104 |
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); |