diff options
author | Martin Willi <martin@revosec.ch> | 2010-02-04 10:08:07 +0100 |
---|---|---|
committer | Martin Willi <martin@revosec.ch> | 2010-08-03 15:39:24 +0200 |
commit | 149b7e6d015cdad60cbbef68faa422b5e02a99af (patch) | |
tree | ace95e63e12840e45ce0314c122622b40364e5ab | |
parent | 3ddd164e5e5e8675754dd72129e546949a19b262 (diff) | |
download | strongswan-149b7e6d015cdad60cbbef68faa422b5e02a99af.tar.bz2 strongswan-149b7e6d015cdad60cbbef68faa422b5e02a99af.tar.xz |
Implemented the TLS specific PRF in its TLSv1.0 and TLSv1.2 variants
-rw-r--r-- | src/charon/plugins/eap_tls/Makefile.am | 1 | ||||
-rw-r--r-- | src/charon/plugins/eap_tls/tls/tls_prf.c | 190 | ||||
-rw-r--r-- | src/charon/plugins/eap_tls/tls/tls_prf.h | 72 |
3 files changed, 263 insertions, 0 deletions
diff --git a/src/charon/plugins/eap_tls/Makefile.am b/src/charon/plugins/eap_tls/Makefile.am index 75e9cfbaa..d18dda2aa 100644 --- a/src/charon/plugins/eap_tls/Makefile.am +++ b/src/charon/plugins/eap_tls/Makefile.am @@ -11,6 +11,7 @@ libstrongswan_eap_tls_la_SOURCES = eap_tls_plugin.h eap_tls_plugin.c \ tls/tls_compression.h tls/tls_compression.c \ tls/tls_fragmentation.h tls/tls_fragmentation.c \ tls/tls_crypto.h tls/tls_crypto.c \ + tls/tls_prf.h tls/tls_prf.c \ tls/tls_reader.h tls/tls_reader.c \ tls/tls_writer.h tls/tls_writer.c \ tls/tls_peer.h tls/tls_peer.c \ diff --git a/src/charon/plugins/eap_tls/tls/tls_prf.c b/src/charon/plugins/eap_tls/tls/tls_prf.c new file mode 100644 index 000000000..f181d01d3 --- /dev/null +++ b/src/charon/plugins/eap_tls/tls/tls_prf.c @@ -0,0 +1,190 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 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 + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "tls_prf.h" + +typedef struct private_tls_prf12_t private_tls_prf12_t; + +/** + * Private data of an tls_prf_t object. + */ +struct private_tls_prf12_t { + + /** + * Public tls_prf_t interface. + */ + tls_prf_t public; + + /** + * Underlying primitive PRF + */ + prf_t *prf; +}; + +METHOD(tls_prf_t, set_key12, void, + private_tls_prf12_t *this, chunk_t key) +{ + this->prf->set_key(this->prf, key); +} + +/** + * The P_hash function as in TLS 1.0/1.2 + */ +static void p_hash(prf_t *prf, char *label, chunk_t seed, size_t block_size, + size_t bytes, char *out) +{ + char buf[block_size], abuf[block_size]; + chunk_t a; + + /* seed = label + seed */ + seed = chunk_cata("cc", chunk_create(label, strlen(label)), seed); + /* A(0) = seed */ + a = seed; + + while (TRUE) + { + /* A(i) = HMAC_hash(secret, A(i-1)) */ + prf->get_bytes(prf, a, abuf); + a = chunk_from_thing(abuf); + /* HMAC_hash(secret, A(i) + seed) */ + prf->get_bytes(prf, a, NULL); + prf->get_bytes(prf, seed, buf); + + if (bytes <= block_size) + { + memcpy(out, buf, bytes); + break; + } + memcpy(out, buf, block_size); + out += block_size; + bytes -= block_size; + } +} + +METHOD(tls_prf_t, get_bytes12, void, + private_tls_prf12_t *this, char *label, chunk_t seed, + size_t bytes, char *out) +{ + p_hash(this->prf, label, seed, this->prf->get_block_size(this->prf), + bytes, out); +} + +METHOD(tls_prf_t, destroy12, void, + private_tls_prf12_t *this) +{ + this->prf->destroy(this->prf); + free(this); +} + +/** + * See header + */ +tls_prf_t *tls_prf_create_12(pseudo_random_function_t prf) +{ + private_tls_prf12_t *this; + + INIT(this, + .public = { + .set_key = _set_key12, + .get_bytes = _get_bytes12, + .destroy = _destroy12, + }, + .prf = lib->crypto->create_prf(lib->crypto, prf), + ); + if (!this->prf) + { + free(this); + return NULL; + } + return &this->public; +} + + +typedef struct private_tls_prf10_t private_tls_prf10_t; + +/** + * Private data of an tls_prf_t object. + */ +struct private_tls_prf10_t { + + /** + * Public tls_prf_t interface. + */ + tls_prf_t public; + + /** + * Underlying MD5 PRF + */ + prf_t *md5; + + /** + * Underlying SHA1 PRF + */ + prf_t *sha1; +}; + +METHOD(tls_prf_t, set_key10, void, + private_tls_prf10_t *this, chunk_t key) +{ + size_t len = key.len / 2 + key.len % 2; + + this->md5->set_key(this->md5, chunk_create(key.ptr, len)); + this->sha1->set_key(this->sha1, chunk_create(key.ptr + key.len - len, len)); +} + +METHOD(tls_prf_t, get_bytes10, void, + private_tls_prf10_t *this, char *label, chunk_t seed, + size_t bytes, char *out) +{ + char buf[bytes]; + + p_hash(this->md5, label, seed, this->md5->get_block_size(this->md5), + bytes, out); + p_hash(this->sha1, label, seed, this->sha1->get_block_size(this->sha1), + bytes, buf); + memxor(out, buf, bytes); +} + +METHOD(tls_prf_t, destroy10, void, + private_tls_prf10_t *this) +{ + DESTROY_IF(this->md5); + DESTROY_IF(this->sha1); + free(this); +} + +/** + * See header + */ +tls_prf_t *tls_prf_create_10(pseudo_random_function_t prf) +{ + private_tls_prf10_t *this; + + INIT(this, + .public = { + .set_key = _set_key10, + .get_bytes = _get_bytes10, + .destroy = _destroy10, + }, + .md5 = lib->crypto->create_prf(lib->crypto, PRF_HMAC_MD5), + .sha1 = lib->crypto->create_prf(lib->crypto, PRF_HMAC_SHA1), + ); + if (!this->md5 || !this->sha1) + { + destroy10(this); + return NULL; + } + return &this->public; +} diff --git a/src/charon/plugins/eap_tls/tls/tls_prf.h b/src/charon/plugins/eap_tls/tls/tls_prf.h new file mode 100644 index 000000000..7326be98c --- /dev/null +++ b/src/charon/plugins/eap_tls/tls/tls_prf.h @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 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 + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup tls_prf tls_prf + * @{ @ingroup tls + */ + +#ifndef TLS_PRF_H_ +#define TLS_PRF_H_ + +typedef struct tls_prf_t tls_prf_t; + +#include <crypto/prfs/prf.h> + +/** + * The PRF function specified on TLS, based on HMAC. + */ +struct tls_prf_t { + + /** + * Set the key of the PRF function. + * + * @param key key to set + */ + void (*set_key)(tls_prf_t *this, chunk_t key); + + /** + * Generate a series of bytes using a label and a seed. + * + * @param label ASCII input label + * @param seed seed input value + * @param bytes number of bytes to get + * @param out buffer receiving bytes + */ + void (*get_bytes)(tls_prf_t *this, char *label, chunk_t seed, + size_t bytes, char *out); + + /** + * Destroy a tls_prf_t. + */ + void (*destroy)(tls_prf_t *this); +}; + +/** + * Create a tls_prf instance with specific algorithm as in TLS 1.2. + * + * @param hash underlying PRF function to use + * @return TLS PRF algorithm + */ +tls_prf_t *tls_prf_create_12(pseudo_random_function_t prf); + +/** + * Create a tls_prf instance with XOred SHA1/MD5 as in TLS 1.0/1.1. + * + * @return TLS PRF algorithm + */ +tls_prf_t *tls_prf_create_10(); + +#endif /** TLS_PRF_H_ @}*/ |