diff options
author | Rene Mayrhofer <rene@mayrhofer.eu.org> | 2010-11-28 11:42:20 +0000 |
---|---|---|
committer | Rene Mayrhofer <rene@mayrhofer.eu.org> | 2010-11-28 11:42:20 +0000 |
commit | f73fba54dc8b30c6482e1e8abf15bbf455592fcd (patch) | |
tree | a449515607c5e51a5c703d7a9b1149c9e4a11560 /src/libtls/tls_prf.c | |
parent | b8064f4099997a9e2179f3ad4ace605f5ccac3a1 (diff) | |
download | vyos-strongswan-f73fba54dc8b30c6482e1e8abf15bbf455592fcd.tar.gz vyos-strongswan-f73fba54dc8b30c6482e1e8abf15bbf455592fcd.zip |
[svn-upgrade] new version strongswan (4.5.0)
Diffstat (limited to 'src/libtls/tls_prf.c')
-rw-r--r-- | src/libtls/tls_prf.c | 190 |
1 files changed, 190 insertions, 0 deletions
diff --git a/src/libtls/tls_prf.c b/src/libtls/tls_prf.c new file mode 100644 index 000000000..f181d01d3 --- /dev/null +++ b/src/libtls/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; +} |