summaryrefslogtreecommitdiff
path: root/src/libtls
diff options
context:
space:
mode:
authorYves-Alexis Perez <corsac@debian.org>2013-01-02 14:18:20 +0100
committerYves-Alexis Perez <corsac@debian.org>2013-01-02 14:18:20 +0100
commitc1343b3278cdf99533b7902744d15969f9d6fdc1 (patch)
treed5ed3dc5677a59260ec41cd39bb284d3e94c91b3 /src/libtls
parentb34738ed08c2227300d554b139e2495ca5da97d6 (diff)
downloadvyos-strongswan-c1343b3278cdf99533b7902744d15969f9d6fdc1.tar.gz
vyos-strongswan-c1343b3278cdf99533b7902744d15969f9d6fdc1.zip
Imported Upstream version 5.0.1
Diffstat (limited to 'src/libtls')
-rw-r--r--src/libtls/Makefile.am23
-rw-r--r--src/libtls/Makefile.in90
-rw-r--r--src/libtls/tls.h6
-rw-r--r--src/libtls/tls_crypto.c96
-rw-r--r--src/libtls/tls_crypto.h3
-rw-r--r--src/libtls/tls_eap.c59
-rw-r--r--src/libtls/tls_fragmentation.c33
-rw-r--r--src/libtls/tls_peer.c39
-rw-r--r--src/libtls/tls_prf.c46
-rw-r--r--src/libtls/tls_prf.h6
-rw-r--r--src/libtls/tls_protection.c45
-rw-r--r--src/libtls/tls_server.c45
12 files changed, 319 insertions, 172 deletions
diff --git a/src/libtls/Makefile.am b/src/libtls/Makefile.am
index 4cc1a1bdb..772950606 100644
--- a/src/libtls/Makefile.am
+++ b/src/libtls/Makefile.am
@@ -3,15 +3,14 @@ INCLUDES = -I$(top_srcdir)/src/libstrongswan
ipseclib_LTLIBRARIES = libtls.la
libtls_la_SOURCES = \
- tls_protection.h tls_protection.c \
- tls_compression.h tls_compression.c \
- tls_fragmentation.h tls_fragmentation.c \
- tls_alert.h tls_alert.c \
- tls_crypto.h tls_crypto.c \
- tls_prf.h tls_prf.c \
- tls_socket.h tls_socket.c \
- tls_eap.h tls_eap.c \
- tls_cache.h tls_cache.c \
- tls_peer.h tls_peer.c \
- tls_server.h tls_server.c \
- tls_handshake.h tls_application.h tls.h tls.c
+ tls_protection.c tls_compression.c tls_fragmentation.c tls_alert.c \
+ tls_crypto.c tls_prf.c tls_socket.c tls_eap.c tls_cache.c tls_peer.c \
+ tls_server.c tls.c
+
+if USE_DEV_HEADERS
+tls_includedir = ${dev_headers}/tls
+nobase_tls_include_HEADERS = \
+ tls_protection.h tls_compression.h tls_fragmentation.h tls_alert.h \
+ tls_crypto.h tls_prf.h tls_socket.h tls_eap.h tls_cache.h tls_peer.h \
+ tls_server.h tls_handshake.h tls_application.h tls.h
+endif
diff --git a/src/libtls/Makefile.in b/src/libtls/Makefile.in
index 844b65156..fb1136ee0 100644
--- a/src/libtls/Makefile.in
+++ b/src/libtls/Makefile.in
@@ -15,6 +15,7 @@
@SET_MAKE@
+
VPATH = @srcdir@
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
@@ -35,7 +36,8 @@ POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
subdir = src/libtls
-DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+DIST_COMMON = $(am__nobase_tls_include_HEADERS_DIST) \
+ $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
$(top_srcdir)/m4/config/ltoptions.m4 \
@@ -49,6 +51,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
@@ -72,7 +75,8 @@ am__nobase_list = $(am__nobase_strip_setup); \
am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
-am__installdirs = "$(DESTDIR)$(ipseclibdir)"
+am__installdirs = "$(DESTDIR)$(ipseclibdir)" \
+ "$(DESTDIR)$(tls_includedir)"
LTLIBRARIES = $(ipseclib_LTLIBRARIES)
libtls_la_LIBADD =
am_libtls_la_OBJECTS = tls_protection.lo tls_compression.lo \
@@ -80,7 +84,7 @@ am_libtls_la_OBJECTS = tls_protection.lo tls_compression.lo \
tls_socket.lo tls_eap.lo tls_cache.lo tls_peer.lo \
tls_server.lo tls.lo
libtls_la_OBJECTS = $(am_libtls_la_OBJECTS)
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -95,6 +99,11 @@ LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
$(LDFLAGS) -o $@
SOURCES = $(libtls_la_SOURCES)
DIST_SOURCES = $(libtls_la_SOURCES)
+am__nobase_tls_include_HEADERS_DIST = tls_protection.h \
+ tls_compression.h tls_fragmentation.h tls_alert.h tls_crypto.h \
+ tls_prf.h tls_socket.h tls_eap.h tls_cache.h tls_peer.h \
+ tls_server.h tls_handshake.h tls_application.h tls.h
+HEADERS = $(nobase_tls_include_HEADERS)
ETAGS = etags
CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
@@ -106,6 +115,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -200,11 +210,14 @@ build_os = @build_os@
build_vendor = @build_vendor@
builddir = @builddir@
c_plugins = @c_plugins@
+charon_natt_port = @charon_natt_port@
+charon_plugins = @charon_plugins@
+charon_udp_port = @charon_udp_port@
clearsilver_LIBS = @clearsilver_LIBS@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -221,11 +234,12 @@ imcvdir = @imcvdir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
+ipsec_script = @ipsec_script@
+ipsec_script_upper = @ipsec_script_upper@
ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -241,6 +255,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -250,7 +265,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
@@ -281,18 +295,15 @@ xml_LIBS = @xml_LIBS@
INCLUDES = -I$(top_srcdir)/src/libstrongswan
ipseclib_LTLIBRARIES = libtls.la
libtls_la_SOURCES = \
- tls_protection.h tls_protection.c \
- tls_compression.h tls_compression.c \
- tls_fragmentation.h tls_fragmentation.c \
- tls_alert.h tls_alert.c \
- tls_crypto.h tls_crypto.c \
- tls_prf.h tls_prf.c \
- tls_socket.h tls_socket.c \
- tls_eap.h tls_eap.c \
- tls_cache.h tls_cache.c \
- tls_peer.h tls_peer.c \
- tls_server.h tls_server.c \
- tls_handshake.h tls_application.h tls.h tls.c
+ tls_protection.c tls_compression.c tls_fragmentation.c tls_alert.c \
+ tls_crypto.c tls_prf.c tls_socket.c tls_eap.c tls_cache.c tls_peer.c \
+ tls_server.c tls.c
+
+@USE_DEV_HEADERS_TRUE@tls_includedir = ${dev_headers}/tls
+@USE_DEV_HEADERS_TRUE@nobase_tls_include_HEADERS = \
+@USE_DEV_HEADERS_TRUE@ tls_protection.h tls_compression.h tls_fragmentation.h tls_alert.h \
+@USE_DEV_HEADERS_TRUE@ tls_crypto.h tls_prf.h tls_socket.h tls_eap.h tls_cache.h tls_peer.h \
+@USE_DEV_HEADERS_TRUE@ tls_server.h tls_handshake.h tls_application.h tls.h
all: all-am
@@ -407,6 +418,29 @@ mostlyclean-libtool:
clean-libtool:
-rm -rf .libs _libs
+install-nobase_tls_includeHEADERS: $(nobase_tls_include_HEADERS)
+ @$(NORMAL_INSTALL)
+ test -z "$(tls_includedir)" || $(MKDIR_P) "$(DESTDIR)$(tls_includedir)"
+ @list='$(nobase_tls_include_HEADERS)'; test -n "$(tls_includedir)" || list=; \
+ $(am__nobase_list) | while read dir files; do \
+ xfiles=; for file in $$files; do \
+ if test -f "$$file"; then xfiles="$$xfiles $$file"; \
+ else xfiles="$$xfiles $(srcdir)/$$file"; fi; done; \
+ test -z "$$xfiles" || { \
+ test "x$$dir" = x. || { \
+ echo "$(MKDIR_P) '$(DESTDIR)$(tls_includedir)/$$dir'"; \
+ $(MKDIR_P) "$(DESTDIR)$(tls_includedir)/$$dir"; }; \
+ echo " $(INSTALL_HEADER) $$xfiles '$(DESTDIR)$(tls_includedir)/$$dir'"; \
+ $(INSTALL_HEADER) $$xfiles "$(DESTDIR)$(tls_includedir)/$$dir" || exit $$?; }; \
+ done
+
+uninstall-nobase_tls_includeHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(nobase_tls_include_HEADERS)'; test -n "$(tls_includedir)" || list=; \
+ $(am__nobase_strip_setup); files=`$(am__nobase_strip)`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(tls_includedir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(tls_includedir)" && rm -f $$files
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
@@ -492,9 +526,9 @@ distdir: $(DISTFILES)
done
check-am: all-am
check: check-am
-all-am: Makefile $(LTLIBRARIES)
+all-am: Makefile $(LTLIBRARIES) $(HEADERS)
installdirs:
- for dir in "$(DESTDIR)$(ipseclibdir)"; do \
+ for dir in "$(DESTDIR)$(ipseclibdir)" "$(DESTDIR)$(tls_includedir)"; do \
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
done
install: install-am
@@ -545,7 +579,8 @@ info: info-am
info-am:
-install-data-am: install-ipseclibLTLIBRARIES
+install-data-am: install-ipseclibLTLIBRARIES \
+ install-nobase_tls_includeHEADERS
install-dvi: install-dvi-am
@@ -591,7 +626,8 @@ ps: ps-am
ps-am:
-uninstall-am: uninstall-ipseclibLTLIBRARIES
+uninstall-am: uninstall-ipseclibLTLIBRARIES \
+ uninstall-nobase_tls_includeHEADERS
.MAKE: install-am install-strip
@@ -602,12 +638,14 @@ uninstall-am: uninstall-ipseclibLTLIBRARIES
install install-am install-data install-data-am install-dvi \
install-dvi-am install-exec install-exec-am install-html \
install-html-am install-info install-info-am \
- install-ipseclibLTLIBRARIES install-man install-pdf \
- install-pdf-am install-ps install-ps-am install-strip \
- installcheck installcheck-am installdirs maintainer-clean \
+ install-ipseclibLTLIBRARIES install-man \
+ install-nobase_tls_includeHEADERS install-pdf install-pdf-am \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
maintainer-clean-generic mostlyclean mostlyclean-compile \
mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
- tags uninstall uninstall-am uninstall-ipseclibLTLIBRARIES
+ tags uninstall uninstall-am uninstall-ipseclibLTLIBRARIES \
+ uninstall-nobase_tls_includeHEADERS
# Tell versions [3.59,3.63) of GNU make to not export all variables.
diff --git a/src/libtls/tls.h b/src/libtls/tls.h
index e22b0facc..6b4876f73 100644
--- a/src/libtls/tls.h
+++ b/src/libtls/tls.h
@@ -26,6 +26,12 @@
#ifndef TLS_H_
#define TLS_H_
+/**
+ * Maximum size of a TLS fragment
+ * as defined by section 6.2.1. "Fragmentation" of RFC 5246 TLS 1.2
+ */
+#define TLS_MAX_FRAGMENT_LEN 16384
+
typedef enum tls_version_t tls_version_t;
typedef enum tls_content_type_t tls_content_type_t;
typedef enum tls_handshake_type_t tls_handshake_type_t;
diff --git a/src/libtls/tls_crypto.c b/src/libtls/tls_crypto.c
index 4d84876d0..f74984879 100644
--- a/src/libtls/tls_crypto.c
+++ b/src/libtls/tls_crypto.c
@@ -1196,12 +1196,12 @@ static bool hash_data(private_tls_crypto_t *this, chunk_t data, chunk_t *hash)
return FALSE;
}
hasher = lib->crypto->create_hasher(lib->crypto, alg->hash);
- if (!hasher)
+ if (!hasher || !hasher->allocate_hash(hasher, data, hash))
{
DBG1(DBG_TLS, "%N not supported", hash_algorithm_names, alg->hash);
+ DESTROY_IF(hasher);
return FALSE;
}
- hasher->allocate_hash(hasher, data, hash);
hasher->destroy(hasher);
}
else
@@ -1210,20 +1210,20 @@ static bool hash_data(private_tls_crypto_t *this, chunk_t data, chunk_t *hash)
char buf[HASH_SIZE_MD5 + HASH_SIZE_SHA1];
md5 = lib->crypto->create_hasher(lib->crypto, HASH_MD5);
- if (!md5)
+ if (!md5 || !md5->get_hash(md5, data, buf))
{
DBG1(DBG_TLS, "%N not supported", hash_algorithm_names, HASH_MD5);
+ DESTROY_IF(md5);
return FALSE;
}
- md5->get_hash(md5, data, buf);
md5->destroy(md5);
sha1 = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
- if (!sha1)
+ if (!sha1 || !sha1->get_hash(sha1, data, buf + HASH_SIZE_MD5))
{
DBG1(DBG_TLS, "%N not supported", hash_algorithm_names, HASH_SHA1);
+ DESTROY_IF(sha1);
return FALSE;
}
- sha1->get_hash(sha1, data, buf + HASH_SIZE_MD5);
sha1->destroy(sha1);
*hash = chunk_clone(chunk_from_thing(buf));
@@ -1462,7 +1462,11 @@ METHOD(tls_crypto_t, calculate_finished, bool,
{
return FALSE;
}
- this->prf->get_bytes(this->prf, label, seed, 12, out);
+ if (!this->prf->get_bytes(this->prf, label, seed, 12, out))
+ {
+ free(seed.ptr);
+ return FALSE;
+ }
free(seed.ptr);
return TRUE;
}
@@ -1470,7 +1474,7 @@ METHOD(tls_crypto_t, calculate_finished, bool,
/**
* Derive master secret from premaster, optionally save session
*/
-static void derive_master(private_tls_crypto_t *this, chunk_t premaster,
+static bool derive_master(private_tls_crypto_t *this, chunk_t premaster,
chunk_t session, identification_t *id,
chunk_t client_random, chunk_t server_random)
{
@@ -1479,23 +1483,28 @@ static void derive_master(private_tls_crypto_t *this, chunk_t premaster,
/* derive master secret */
seed = chunk_cata("cc", client_random, server_random);
- this->prf->set_key(this->prf, premaster);
- this->prf->get_bytes(this->prf, "master secret", seed,
- sizeof(master), master);
- this->prf->set_key(this->prf, chunk_from_thing(master));
+ if (!this->prf->set_key(this->prf, premaster) ||
+ !this->prf->get_bytes(this->prf, "master secret", seed,
+ sizeof(master), master) ||
+ !this->prf->set_key(this->prf, chunk_from_thing(master)))
+ {
+ return FALSE;
+ }
+
if (this->cache && session.len)
{
this->cache->create(this->cache, session, id, chunk_from_thing(master),
this->suite);
}
memwipe(master, sizeof(master));
+ return TRUE;
}
/**
* Expand key material from master secret
*/
-static void expand_keys(private_tls_crypto_t *this,
+static bool expand_keys(private_tls_crypto_t *this,
chunk_t client_random, chunk_t server_random)
{
chunk_t seed, block, client_write, server_write;
@@ -1513,7 +1522,11 @@ static void expand_keys(private_tls_crypto_t *this,
}
seed = chunk_cata("cc", server_random, client_random);
block = chunk_alloca((mks + eks + ivs) * 2);
- this->prf->get_bytes(this->prf, "key expansion", seed, block.len, block.ptr);
+ if (!this->prf->get_bytes(this->prf, "key expansion", seed,
+ block.len, block.ptr))
+ {
+ return FALSE;
+ }
/* signer keys */
client_write = chunk_create(block.ptr, mks);
@@ -1522,13 +1535,19 @@ static void expand_keys(private_tls_crypto_t *this,
block = chunk_skip(block, mks);
if (this->tls->is_server(this->tls))
{
- this->signer_in->set_key(this->signer_in, client_write);
- this->signer_out->set_key(this->signer_out, server_write);
+ if (!this->signer_in->set_key(this->signer_in, client_write) ||
+ !this->signer_out->set_key(this->signer_out, server_write))
+ {
+ return FALSE;
+ }
}
else
{
- this->signer_out->set_key(this->signer_out, client_write);
- this->signer_in->set_key(this->signer_in, server_write);
+ if (!this->signer_out->set_key(this->signer_out, client_write) ||
+ !this->signer_in->set_key(this->signer_in, server_write))
+ {
+ return FALSE;
+ }
}
/* crypter keys, and IVs if < TLSv1.2 */
@@ -1541,13 +1560,19 @@ static void expand_keys(private_tls_crypto_t *this,
if (this->tls->is_server(this->tls))
{
- this->crypter_in->set_key(this->crypter_in, client_write);
- this->crypter_out->set_key(this->crypter_out, server_write);
+ if (!this->crypter_in->set_key(this->crypter_in, client_write) ||
+ !this->crypter_out->set_key(this->crypter_out, server_write))
+ {
+ return FALSE;
+ }
}
else
{
- this->crypter_out->set_key(this->crypter_out, client_write);
- this->crypter_in->set_key(this->crypter_in, server_write);
+ if (!this->crypter_out->set_key(this->crypter_out, client_write) ||
+ !this->crypter_in->set_key(this->crypter_in, server_write))
+ {
+ return FALSE;
+ }
}
if (ivs)
{
@@ -1574,17 +1599,22 @@ static void expand_keys(private_tls_crypto_t *this,
{
seed = chunk_cata("cc", client_random, server_random);
this->msk = chunk_alloc(64);
- this->prf->get_bytes(this->prf, this->msk_label, seed,
- this->msk.len, this->msk.ptr);
+ if (!this->prf->get_bytes(this->prf, this->msk_label, seed,
+ this->msk.len, this->msk.ptr))
+ {
+ return FALSE;
+ }
}
+ return TRUE;
}
-METHOD(tls_crypto_t, derive_secrets, void,
+METHOD(tls_crypto_t, derive_secrets, bool,
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);
+ return 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,
@@ -1601,8 +1631,11 @@ METHOD(tls_crypto_t, resume_session, tls_cipher_suite_t,
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);
+ if (!this->prf->set_key(this->prf, master) ||
+ !expand_keys(this, client_random, server_random))
+ {
+ this->suite = 0;
+ }
}
chunk_clear(&master);
}
@@ -1719,11 +1752,14 @@ tls_crypto_t *tls_crypto_create(tls_t *tls, tls_cache_t *cache)
switch (tls->get_purpose(tls))
{
case TLS_PURPOSE_EAP_TLS:
- case TLS_PURPOSE_EAP_PEAP:
/* MSK PRF ASCII constant label according to EAP-TLS RFC 5216 */
this->msk_label = "client EAP encryption";
build_cipher_suite_list(this, FALSE);
break;
+ case TLS_PURPOSE_EAP_PEAP:
+ this->msk_label = "client EAP encryption";
+ build_cipher_suite_list(this, TRUE);
+ break;
case TLS_PURPOSE_EAP_TTLS:
/* MSK PRF ASCII constant label according to EAP-TTLS RFC 5281 */
this->msk_label = "ttls keying material";
diff --git a/src/libtls/tls_crypto.h b/src/libtls/tls_crypto.h
index 7430aea66..5512b1f48 100644
--- a/src/libtls/tls_crypto.h
+++ b/src/libtls/tls_crypto.h
@@ -515,8 +515,9 @@ struct tls_crypto_t {
* @param id identity the session is bound to
* @param client_random random data from client hello
* @param server_random random data from server hello
+ * @return TRUE if secrets derived successfully
*/
- void (*derive_secrets)(tls_crypto_t *this, chunk_t premaster,
+ bool (*derive_secrets)(tls_crypto_t *this, chunk_t premaster,
chunk_t session, identification_t *id,
chunk_t client_random, chunk_t server_random);
diff --git a/src/libtls/tls_eap.c b/src/libtls/tls_eap.c
index 685904fdf..928aadcb3 100644
--- a/src/libtls/tls_eap.c
+++ b/src/libtls/tls_eap.c
@@ -21,8 +21,11 @@
#include <debug.h>
#include <library.h>
-/** Size limit for a single TLS message */
-#define MAX_TLS_MESSAGE_LEN 65536
+/**
+ * Size limit for a TLS message allowing for worst-case protection overhead
+ * according to section 6.2.3. "Payload Protection" of RFC 5246 TLS 1.2
+ */
+#define TLS_MAX_MESSAGE_LEN 4 * (TLS_MAX_FRAGMENT_LEN + 2048)
typedef struct private_tls_eap_t private_tls_eap_t;
@@ -79,7 +82,7 @@ struct private_tls_eap_t {
int processed;
/**
- * Maximum number of processed EAP messages/fragments
+ * Maximum number of processed EAP messages/fragments
*/
int max_msg_count;
};
@@ -138,7 +141,7 @@ METHOD(tls_eap_t, initiate, status_t,
*out = chunk_clone(chunk_from_thing(pkt));
DBG2(DBG_TLS, "sending %N start packet (%u bytes)",
- eap_type_names, this->type, sizeof(eap_tls_packet_t));
+ eap_type_names, this->type, sizeof(eap_tls_packet_t));
DBG3(DBG_TLS, "%B", out);
return NEED_MORE;
}
@@ -150,10 +153,12 @@ METHOD(tls_eap_t, initiate, status_t,
*/
static status_t process_pkt(private_tls_eap_t *this, eap_tls_packet_t *pkt)
{
- u_int32_t msg_len;
u_int16_t pkt_len;
+ u_int32_t msg_len;
+ size_t msg_len_offset = 0;
pkt_len = untoh16(&pkt->length);
+
if (pkt->flags & EAP_TLS_LENGTH)
{
if (pkt_len < sizeof(eap_tls_packet_t) + sizeof(msg_len))
@@ -163,16 +168,17 @@ static status_t process_pkt(private_tls_eap_t *this, eap_tls_packet_t *pkt)
}
msg_len = untoh32(pkt + 1);
if (msg_len < pkt_len - sizeof(eap_tls_packet_t) - sizeof(msg_len) ||
- msg_len > MAX_TLS_MESSAGE_LEN)
+ msg_len > TLS_MAX_MESSAGE_LEN)
{
- DBG1(DBG_TLS, "invalid %N packet length", eap_type_names, this->type);
+ DBG1(DBG_TLS, "invalid %N packet length (%u bytes)", eap_type_names,
+ this->type, msg_len);
return FAILED;
}
- return this->tls->process(this->tls, (char*)(pkt + 1) + sizeof(msg_len),
- pkt_len - sizeof(eap_tls_packet_t) - sizeof(msg_len));
+ msg_len_offset = sizeof(msg_len);
}
- return this->tls->process(this->tls, (char*)(pkt + 1),
- pkt_len - sizeof(eap_tls_packet_t));
+
+ return this->tls->process(this->tls, (char*)(pkt + 1) + msg_len_offset,
+ pkt_len - sizeof(eap_tls_packet_t) - msg_len_offset);
}
/**
@@ -182,7 +188,7 @@ static status_t build_pkt(private_tls_eap_t *this, chunk_t *out)
{
char buf[this->frag_size];
eap_tls_packet_t *pkt;
- size_t len, reclen;
+ size_t len, reclen, msg_len_offset;
status_t status;
char *kind;
@@ -214,15 +220,16 @@ static status_t build_pkt(private_tls_eap_t *this, chunk_t *out)
if (this->first_fragment)
{
len = sizeof(buf) - sizeof(eap_tls_packet_t) - sizeof(u_int32_t);
- status = this->tls->build(this->tls, buf + sizeof(eap_tls_packet_t) +
- sizeof(u_int32_t), &len, &reclen);
+ msg_len_offset = sizeof(u_int32_t);
}
else
{
len = sizeof(buf) - sizeof(eap_tls_packet_t);
- status = this->tls->build(this->tls, buf + sizeof(eap_tls_packet_t),
- &len, &reclen);
+ msg_len_offset = 0;
}
+ status = this->tls->build(this->tls, buf + sizeof(eap_tls_packet_t) +
+ msg_len_offset, &len, &reclen);
+
switch (status)
{
case NEED_MORE:
@@ -230,7 +237,7 @@ static status_t build_pkt(private_tls_eap_t *this, chunk_t *out)
kind = "further fragment";
if (this->first_fragment)
{
- pkt->flags |= EAP_TLS_LENGTH;
+ pkt->flags |= EAP_TLS_LENGTH;
this->first_fragment = FALSE;
kind = "first fragment";
}
@@ -244,11 +251,15 @@ static status_t build_pkt(private_tls_eap_t *this, chunk_t *out)
}
kind = "packet";
}
- else
+ else if (this->type != EAP_TNC)
{
this->first_fragment = TRUE;
kind = "final fragment";
}
+ else
+ {
+ kind = "packet";
+ }
break;
default:
return status;
@@ -256,7 +267,7 @@ static status_t build_pkt(private_tls_eap_t *this, chunk_t *out)
if (reclen)
{
if (pkt->flags & EAP_TLS_LENGTH)
- {
+ {
htoun32(pkt + 1, reclen);
len += sizeof(u_int32_t);
pkt->flags |= EAP_TLS_LENGTH;
@@ -264,15 +275,15 @@ static status_t build_pkt(private_tls_eap_t *this, chunk_t *out)
else
{
/* get rid of the reserved length field */
- memcpy(buf+sizeof(eap_packet_t),
- buf+sizeof(eap_packet_t)+sizeof(u_int32_t), len);
+ memmove(buf + sizeof(eap_tls_packet_t),
+ buf + sizeof(eap_tls_packet_t) + sizeof(u_int32_t), len);
}
}
len += sizeof(eap_tls_packet_t);
htoun16(&pkt->length, len);
*out = chunk_clone(chunk_create(buf, len));
DBG2(DBG_TLS, "sending %N %s (%u bytes)",
- eap_type_names, this->type, kind, len);
+ eap_type_names, this->type, kind, len);
DBG3(DBG_TLS, "%B", out);
return NEED_MORE;
}
@@ -319,7 +330,7 @@ METHOD(tls_eap_t, process, status_t,
eap_tls_packet_t *pkt;
status_t status;
- if (++this->processed > this->max_msg_count)
+ if (this->max_msg_count && ++this->processed > this->max_msg_count)
{
DBG1(DBG_TLS, "%N packet count exceeded (%d > %d)",
eap_type_names, this->type,
@@ -441,7 +452,7 @@ tls_eap_t *tls_eap_create(eap_type_t type, tls_t *tls, size_t frag_size,
},
.type = type,
.is_server = tls->is_server(tls),
- .first_fragment = TRUE,
+ .first_fragment = (type != EAP_TNC),
.frag_size = frag_size,
.max_msg_count = max_msg_count,
.include_length = include_length,
diff --git a/src/libtls/tls_fragmentation.c b/src/libtls/tls_fragmentation.c
index 62e36aaec..f2fa77cfd 100644
--- a/src/libtls/tls_fragmentation.c
+++ b/src/libtls/tls_fragmentation.c
@@ -18,6 +18,11 @@
#include <bio/bio_reader.h>
#include <debug.h>
+/**
+ * Maximum size of a TLS handshake message we accept
+ */
+#define TLS_MAX_HANDSHAKE_LEN 65536
+
typedef struct private_tls_fragmentation_t private_tls_fragmentation_t;
/**
@@ -94,16 +99,6 @@ struct private_tls_fragmentation_t {
};
/**
- * Maximum size of a TLS fragment
- */
-#define MAX_TLS_FRAGMENT_LEN 16384
-
-/**
- * Maximum size of a TLS handshake message we accept
- */
-#define MAX_TLS_HANDSHAKE_LEN 65536
-
-/**
* Process a TLS alert
*/
static status_t process_alert(private_tls_fragmentation_t *this,
@@ -134,7 +129,7 @@ static status_t process_handshake(private_tls_fragmentation_t *this,
status_t status;
chunk_t data;
- if (reader->remaining(reader) > MAX_TLS_FRAGMENT_LEN)
+ if (reader->remaining(reader) > TLS_MAX_FRAGMENT_LEN)
{
DBG1(DBG_TLS, "TLS fragment has invalid length");
this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR);
@@ -151,7 +146,7 @@ static status_t process_handshake(private_tls_fragmentation_t *this,
return NEED_MORE;
}
this->type = type;
- if (len > MAX_TLS_HANDSHAKE_LEN)
+ if (len > TLS_MAX_HANDSHAKE_LEN)
{
DBG1(DBG_TLS, "TLS handshake exceeds maximum length");
this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR);
@@ -202,12 +197,18 @@ static status_t process_handshake(private_tls_fragmentation_t *this,
static status_t process_application(private_tls_fragmentation_t *this,
bio_reader_t *reader)
{
+ if (!this->handshake->finished(this->handshake))
+ {
+ DBG1(DBG_TLS, "received TLS application data, "
+ "but handshake not finished");
+ return FAILED;
+ }
while (reader->remaining(reader))
{
status_t status;
chunk_t data;
- if (reader->remaining(reader) > MAX_TLS_FRAGMENT_LEN)
+ if (reader->remaining(reader) > TLS_MAX_FRAGMENT_LEN)
{
DBG1(DBG_TLS, "TLS fragment has invalid length");
this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR);
@@ -427,14 +428,14 @@ METHOD(tls_fragmentation_t, build, status_t,
if (this->output.len)
{
*type = this->output_type;
- if (this->output.len <= MAX_TLS_FRAGMENT_LEN)
+ if (this->output.len <= TLS_MAX_FRAGMENT_LEN)
{
*data = this->output;
this->output = chunk_empty;
return NEED_MORE;
}
- *data = chunk_create(this->output.ptr, MAX_TLS_FRAGMENT_LEN);
- this->output = chunk_clone(chunk_skip(this->output, MAX_TLS_FRAGMENT_LEN));
+ *data = chunk_create(this->output.ptr, TLS_MAX_FRAGMENT_LEN);
+ this->output = chunk_clone(chunk_skip(this->output, TLS_MAX_FRAGMENT_LEN));
return NEED_MORE;
}
return status;
diff --git a/src/libtls/tls_peer.c b/src/libtls/tls_peer.c
index 6091702cf..65072d087 100644
--- a/src/libtls/tls_peer.c
+++ b/src/libtls/tls_peer.c
@@ -709,13 +709,15 @@ static status_t send_client_hello(private_tls_peer_t *this,
htoun32(&this->client_random, time(NULL));
rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
- if (!rng)
+ if (!rng ||
+ !rng->get_bytes(rng, sizeof(this->client_random) - 4,
+ this->client_random + 4))
{
- DBG1(DBG_TLS, "no suitable RNG found to generate client random");
+ DBG1(DBG_TLS, "failed to generate client random");
this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
+ DESTROY_IF(rng);
return NEED_MORE;
}
- rng->get_bytes(rng, sizeof(this->client_random) - 4, this->client_random + 4);
rng->destroy(rng);
/* TLS version */
@@ -903,20 +905,24 @@ static status_t send_key_exchange_encrypt(private_tls_peer_t *this,
chunk_t encrypted;
rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG);
- if (!rng)
+ if (!rng || !rng->get_bytes(rng, sizeof(premaster) - 2, premaster + 2))
{
- DBG1(DBG_TLS, "no suitable RNG found for TLS premaster secret");
+ DBG1(DBG_TLS, "failed to generate TLS premaster secret");
this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
+ DESTROY_IF(rng);
return NEED_MORE;
}
- rng->get_bytes(rng, sizeof(premaster) - 2, premaster + 2);
rng->destroy(rng);
htoun16(premaster, TLS_1_2);
- this->crypto->derive_secrets(this->crypto, chunk_from_thing(premaster),
- this->session, this->server,
- chunk_from_thing(this->client_random),
- chunk_from_thing(this->server_random));
+ if (!this->crypto->derive_secrets(this->crypto, chunk_from_thing(premaster),
+ this->session, this->server,
+ chunk_from_thing(this->client_random),
+ chunk_from_thing(this->server_random)))
+ {
+ this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
+ return NEED_MORE;
+ }
public = find_public_key(this);
if (!public)
@@ -958,10 +964,15 @@ static status_t send_key_exchange_dhe(private_tls_peer_t *this,
this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
return NEED_MORE;
}
- this->crypto->derive_secrets(this->crypto, premaster,
- this->session, this->server,
- chunk_from_thing(this->client_random),
- chunk_from_thing(this->server_random));
+ if (!this->crypto->derive_secrets(this->crypto, premaster,
+ this->session, this->server,
+ chunk_from_thing(this->client_random),
+ chunk_from_thing(this->server_random)))
+ {
+ this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
+ chunk_clear(&premaster);
+ return NEED_MORE;
+ }
chunk_clear(&premaster);
this->dh->get_my_public_value(this->dh, &pub);
diff --git a/src/libtls/tls_prf.c b/src/libtls/tls_prf.c
index f181d01d3..918de1e50 100644
--- a/src/libtls/tls_prf.c
+++ b/src/libtls/tls_prf.c
@@ -33,16 +33,16 @@ struct private_tls_prf12_t {
prf_t *prf;
};
-METHOD(tls_prf_t, set_key12, void,
+METHOD(tls_prf_t, set_key12, bool,
private_tls_prf12_t *this, chunk_t key)
{
- this->prf->set_key(this->prf, key);
+ return 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,
+static bool 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];
@@ -56,11 +56,17 @@ static void p_hash(prf_t *prf, char *label, chunk_t seed, size_t block_size,
while (TRUE)
{
/* A(i) = HMAC_hash(secret, A(i-1)) */
- prf->get_bytes(prf, a, abuf);
+ if (!prf->get_bytes(prf, a, abuf))
+ {
+ return FALSE;
+ }
a = chunk_from_thing(abuf);
/* HMAC_hash(secret, A(i) + seed) */
- prf->get_bytes(prf, a, NULL);
- prf->get_bytes(prf, seed, buf);
+ if (!prf->get_bytes(prf, a, NULL) ||
+ !prf->get_bytes(prf, seed, buf))
+ {
+ return FALSE;
+ }
if (bytes <= block_size)
{
@@ -71,14 +77,15 @@ static void p_hash(prf_t *prf, char *label, chunk_t seed, size_t block_size,
out += block_size;
bytes -= block_size;
}
+ return TRUE;
}
-METHOD(tls_prf_t, get_bytes12, void,
+METHOD(tls_prf_t, get_bytes12, bool,
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);
+ return p_hash(this->prf, label, seed, this->prf->get_block_size(this->prf),
+ bytes, out);
}
METHOD(tls_prf_t, destroy12, void,
@@ -135,26 +142,31 @@ struct private_tls_prf10_t {
prf_t *sha1;
};
-METHOD(tls_prf_t, set_key10, void,
+METHOD(tls_prf_t, set_key10, bool,
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));
+ return 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,
+METHOD(tls_prf_t, get_bytes10, bool,
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);
+ if (!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))
+ {
+ return FALSE;
+ }
memxor(out, buf, bytes);
+ return TRUE;
}
METHOD(tls_prf_t, destroy10, void,
diff --git a/src/libtls/tls_prf.h b/src/libtls/tls_prf.h
index 9fb9bc2de..095eaea3a 100644
--- a/src/libtls/tls_prf.h
+++ b/src/libtls/tls_prf.h
@@ -34,8 +34,9 @@ struct tls_prf_t {
* Set the key of the PRF function.
*
* @param key key to set
+ * @return TRUE if key set successfully
*/
- void (*set_key)(tls_prf_t *this, chunk_t key);
+ bool (*set_key)(tls_prf_t *this, chunk_t key);
/**
* Generate a series of bytes using a label and a seed.
@@ -44,8 +45,9 @@ struct tls_prf_t {
* @param seed seed input value
* @param bytes number of bytes to get
* @param out buffer receiving bytes
+ * @return TRUE if bytes generated successfully
*/
- void (*get_bytes)(tls_prf_t *this, char *label, chunk_t seed,
+ bool (*get_bytes)(tls_prf_t *this, char *label, chunk_t seed,
size_t bytes, char *out);
/**
diff --git a/src/libtls/tls_protection.c b/src/libtls/tls_protection.c
index dc734545c..8263728bb 100644
--- a/src/libtls/tls_protection.c
+++ b/src/libtls/tls_protection.c
@@ -93,7 +93,7 @@ struct private_tls_protection_t {
/**
* Create the header and feed it into a signer for MAC verification
*/
-static void sigheader(signer_t *signer, u_int32_t seq, u_int8_t type,
+static bool sigheader(signer_t *signer, u_int32_t seq, u_int8_t type,
u_int16_t version, u_int16_t length)
{
/* we only support 32 bit sequence numbers, but TLS uses 64 bit */
@@ -110,7 +110,7 @@ static void sigheader(signer_t *signer, u_int32_t seq, u_int8_t type,
htoun16(&header.version, version);
htoun16(&header.length, length);
- signer->get_signature(signer, chunk_from_thing(header), NULL);
+ return signer->get_signature(signer, chunk_from_thing(header), NULL);
}
METHOD(tls_protection_t, process, status_t,
@@ -150,7 +150,12 @@ METHOD(tls_protection_t, process, status_t,
return NEED_MORE;
}
}
- this->crypter_in->decrypt(this->crypter_in, data, iv, NULL);
+ if (!this->crypter_in->decrypt(this->crypter_in, data, iv, NULL))
+ {
+ free(next_iv.ptr);
+ this->alert->add(this->alert, TLS_FATAL, TLS_BAD_RECORD_MAC);
+ return NEED_MORE;
+ }
if (next_iv.len)
{ /* next record IV is last ciphertext block of this record */
@@ -180,8 +185,9 @@ METHOD(tls_protection_t, process, status_t,
mac = chunk_skip(data, data.len - bs);
data.len -= bs;
- sigheader(this->signer_in, this->seq_in, type, this->version, data.len);
- if (!this->signer_in->verify_signature(this->signer_in, data, mac))
+ if (!sigheader(this->signer_in, this->seq_in, type,
+ this->version, data.len) ||
+ !this->signer_in->verify_signature(this->signer_in, data, mac))
{
DBG1(DBG_TLS, "TLS record MAC verification failed");
this->alert->add(this->alert, TLS_FATAL, TLS_BAD_RECORD_MAC);
@@ -218,9 +224,13 @@ METHOD(tls_protection_t, build, status_t,
{
chunk_t mac;
- sigheader(this->signer_out, this->seq_out, *type,
- this->version, data->len);
- this->signer_out->allocate_signature(this->signer_out, *data, &mac);
+ if (!sigheader(this->signer_out, this->seq_out, *type,
+ this->version, data->len) ||
+ !this->signer_out->allocate_signature(this->signer_out,
+ *data, &mac))
+ {
+ return FAILED;
+ }
if (this->crypter_out)
{
chunk_t padding, iv;
@@ -238,20 +248,29 @@ METHOD(tls_protection_t, build, status_t,
}
else
{ /* TLSv1.1 uses random IVs, prepended to record */
- if (!this->rng)
+ iv.len = this->crypter_out->get_iv_size(this->crypter_out);
+ if (!this->rng ||
+ !this->rng->allocate_bytes(this->rng, iv.len, &iv))
{
- DBG1(DBG_TLS, "no RNG supported to generate TLS IV");
+ DBG1(DBG_TLS, "failed to generate TLS IV");
free(data->ptr);
return FAILED;
}
- iv.len = this->crypter_out->get_iv_size(this->crypter_out);
- this->rng->allocate_bytes(this->rng, iv.len, &iv);
}
*data = chunk_cat("mmcc", *data, mac, padding,
chunk_from_thing(padding_length));
/* encrypt inline */
- this->crypter_out->encrypt(this->crypter_out, *data, iv, NULL);
+ if (!this->crypter_out->encrypt(this->crypter_out, *data,
+ iv, NULL))
+ {
+ if (!this->iv_out.len)
+ {
+ free(iv.ptr);
+ }
+ free(data->ptr);
+ return FAILED;
+ }
if (this->iv_out.len)
{ /* next record IV is last ciphertext block of this record */
diff --git a/src/libtls/tls_server.c b/src/libtls/tls_server.c
index e3617dc9a..a66448d24 100644
--- a/src/libtls/tls_server.c
+++ b/src/libtls/tls_server.c
@@ -266,13 +266,15 @@ static status_t process_client_hello(private_tls_server_t *this,
htoun32(&this->server_random, time(NULL));
rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
- if (!rng)
+ if (!rng ||
+ !rng->get_bytes(rng, sizeof(this->server_random) - 4,
+ this->server_random + 4))
{
- DBG1(DBG_TLS, "no suitable RNG found to generate server random");
+ DBG1(DBG_TLS, "failed to generate server random");
this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
+ DESTROY_IF(rng);
return NEED_MORE;
}
- rng->get_bytes(rng, sizeof(this->server_random) - 4, this->server_random + 4);
rng->destroy(rng);
if (!this->tls->set_version(this->tls, version))
@@ -311,11 +313,11 @@ static status_t process_client_hello(private_tls_server_t *this,
return NEED_MORE;
}
rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG);
- if (rng)
+ if (!rng || !rng->allocate_bytes(rng, SESSION_ID_SIZE, &this->session))
{
- rng->allocate_bytes(rng, SESSION_ID_SIZE, &this->session);
- rng->destroy(rng);
+ DBG1(DBG_TLS, "generating TLS session identifier failed, skipped");
}
+ DESTROY_IF(rng);
DBG1(DBG_TLS, "negotiated %N using suite %N",
tls_version_names, this->tls->get_version(this->tls),
tls_cipher_suite_names, this->suite);
@@ -407,13 +409,13 @@ static status_t process_key_exchange_encrypted(private_tls_server_t *this,
htoun16(premaster, this->client_version);
/* pre-randomize premaster for failure cases */
rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
- if (!rng)
+ if (!rng || !rng->get_bytes(rng, sizeof(premaster) - 2, premaster + 2))
{
- DBG1(DBG_TLS, "creating RNG failed");
+ DBG1(DBG_TLS, "failed to generate premaster secret");
this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
+ DESTROY_IF(rng);
return NEED_MORE;
}
- rng->get_bytes(rng, sizeof(premaster) - 2, premaster + 2);
rng->destroy(rng);
if (this->private &&
@@ -436,10 +438,14 @@ static status_t process_key_exchange_encrypted(private_tls_server_t *this,
DBG1(DBG_TLS, "decrypting Client Key Exchange failed");
}
- this->crypto->derive_secrets(this->crypto, chunk_from_thing(premaster),
- this->session, this->peer,
- chunk_from_thing(this->client_random),
- chunk_from_thing(this->server_random));
+ if (!this->crypto->derive_secrets(this->crypto, chunk_from_thing(premaster),
+ this->session, this->peer,
+ chunk_from_thing(this->client_random),
+ chunk_from_thing(this->server_random)))
+ {
+ this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
+ return NEED_MORE;
+ }
this->state = STATE_KEY_EXCHANGE_RECEIVED;
return NEED_MORE;
@@ -485,10 +491,15 @@ static status_t process_key_exchange_dhe(private_tls_server_t *this,
return NEED_MORE;
}
- this->crypto->derive_secrets(this->crypto, premaster,
- this->session, this->peer,
- chunk_from_thing(this->client_random),
- chunk_from_thing(this->server_random));
+ if (!this->crypto->derive_secrets(this->crypto, premaster,
+ this->session, this->peer,
+ chunk_from_thing(this->client_random),
+ chunk_from_thing(this->server_random)))
+ {
+ this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
+ chunk_clear(&premaster);
+ return NEED_MORE;
+ }
chunk_clear(&premaster);
this->state = STATE_KEY_EXCHANGE_RECEIVED;