diff options
author | Yves-Alexis Perez <corsac@debian.org> | 2013-10-17 21:23:38 +0200 |
---|---|---|
committer | Yves-Alexis Perez <corsac@debian.org> | 2013-10-17 21:23:38 +0200 |
commit | 9d37ad77ef660b92ea51b69d74e14f931d2a04e2 (patch) | |
tree | d6bbb4a5fed1959f8675df9ee7c03713b543fcc9 /src/libtls | |
parent | 104f57d4b0fb6d7547d6898352eaa5fb4b222010 (diff) | |
parent | e5ee4e7fcdd58b7d86bf1b458da2c63e8e19627b (diff) | |
download | vyos-strongswan-9d37ad77ef660b92ea51b69d74e14f931d2a04e2.tar.gz vyos-strongswan-9d37ad77ef660b92ea51b69d74e14f931d2a04e2.zip |
Merge tag 'v5.1.0-1' into sid
tag strongSwan 5.1.0-1
Diffstat (limited to 'src/libtls')
-rw-r--r-- | src/libtls/Makefile.am | 27 | ||||
-rw-r--r-- | src/libtls/Makefile.in | 222 | ||||
-rw-r--r-- | src/libtls/tls.c | 34 | ||||
-rw-r--r-- | src/libtls/tls.h | 20 | ||||
-rw-r--r-- | src/libtls/tls_alert.c | 4 | ||||
-rw-r--r-- | src/libtls/tls_cache.c | 6 | ||||
-rw-r--r-- | src/libtls/tls_crypto.c | 99 | ||||
-rw-r--r-- | src/libtls/tls_crypto.h | 3 | ||||
-rw-r--r-- | src/libtls/tls_eap.c | 61 | ||||
-rw-r--r-- | src/libtls/tls_fragmentation.c | 43 | ||||
-rw-r--r-- | src/libtls/tls_handshake.h | 14 | ||||
-rw-r--r-- | src/libtls/tls_peer.c | 65 | ||||
-rw-r--r-- | src/libtls/tls_peer.h | 8 | ||||
-rw-r--r-- | src/libtls/tls_prf.c | 46 | ||||
-rw-r--r-- | src/libtls/tls_prf.h | 6 | ||||
-rw-r--r-- | src/libtls/tls_protection.c | 47 | ||||
-rw-r--r-- | src/libtls/tls_server.c | 101 | ||||
-rw-r--r-- | src/libtls/tls_server.h | 7 | ||||
-rw-r--r-- | src/libtls/tls_socket.c | 274 | ||||
-rw-r--r-- | src/libtls/tls_socket.h | 37 |
20 files changed, 786 insertions, 338 deletions
diff --git a/src/libtls/Makefile.am b/src/libtls/Makefile.am index 4cc1a1bdb..9e3712abe 100644 --- a/src/libtls/Makefile.am +++ b/src/libtls/Makefile.am @@ -1,17 +1,16 @@ - -INCLUDES = -I$(top_srcdir)/src/libstrongswan +AM_CPPFLAGS = \ + -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..df721f79e 100644 --- a/src/libtls/Makefile.in +++ b/src/libtls/Makefile.in @@ -1,9 +1,9 @@ -# Makefile.in generated by automake 1.11.1 from Makefile.am. +# Makefile.in generated by automake 1.11.6 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, -# Inc. +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. @@ -15,7 +15,25 @@ @SET_MAKE@ + VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ @@ -35,7 +53,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 \ @@ -45,10 +64,11 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \ $(top_srcdir)/m4/macros/with.m4 \ $(top_srcdir)/m4/macros/enable-disable.m4 \ $(top_srcdir)/m4/macros/add-plugin.m4 \ - $(top_srcdir)/configure.in + $(top_srcdir)/configure.ac 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 +92,14 @@ 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__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(ipseclibdir)" \ + "$(DESTDIR)$(tls_includedir)" LTLIBRARIES = $(ipseclib_LTLIBRARIES) libtls_la_LIBADD = am_libtls_la_OBJECTS = tls_protection.lo tls_compression.lo \ @@ -80,42 +107,75 @@ 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@ +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ - --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ - $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ CCLD = $(CC) -LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ - --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ - $(LDFLAGS) -o $@ +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; SOURCES = $(libtls_la_SOURCES) DIST_SOURCES = $(libtls_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +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) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ +BFDLIB = @BFDLIB@ BTLIB = @BTLIB@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ +CHECK_CFLAGS = @CHECK_CFLAGS@ +CHECK_LIBS = @CHECK_LIBS@ +COVERAGE_CFLAGS = @COVERAGE_CFLAGS@ +COVERAGE_LDFLAGS = @COVERAGE_LDFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLIB = @DLLIB@ +DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ @@ -124,13 +184,16 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +GENHTML = @GENHTML@ GPERF = @GPERF@ +GPRBUILD = @GPRBUILD@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ @@ -143,6 +206,7 @@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MYSQLCFLAG = @MYSQLCFLAG@ MYSQLCONFIG = @MYSQLCONFIG@ @@ -170,11 +234,13 @@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ RUBY = @RUBY@ RUBYINCLUDE = @RUBYINCLUDE@ +RUBYLIB = @RUBYLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SOCKLIB = @SOCKLIB@ STRIP = @STRIP@ +UNWINDLIB = @UNWINDLIB@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ @@ -182,6 +248,7 @@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ @@ -190,8 +257,6 @@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ attest_plugins = @attest_plugins@ -axis2c_CFLAGS = @axis2c_CFLAGS@ -axis2c_LIBS = @axis2c_LIBS@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ @@ -200,14 +265,19 @@ 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@ +cmd_plugins = @cmd_plugins@ datadir = @datadir@ datarootdir = @datarootdir@ dbusservicedir = @dbusservicedir@ -default_pkcs11 = @default_pkcs11@ +dev_headers = @dev_headers@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ +fips_mode = @fips_mode@ gtk_CFLAGS = @gtk_CFLAGS@ gtk_LIBS = @gtk_LIBS@ h_plugins = @h_plugins@ @@ -221,17 +291,17 @@ 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@ localedir = @localedir@ localstatedir = @localstatedir@ -lt_ECHO = @lt_ECHO@ maemo_CFLAGS = @maemo_CFLAGS@ maemo_LIBS = @maemo_LIBS@ manager_plugins = @manager_plugins@ @@ -241,16 +311,15 @@ 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@ pcsclite_CFLAGS = @pcsclite_CFLAGS@ pcsclite_LIBS = @pcsclite_LIBS@ 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@ @@ -278,21 +347,20 @@ top_srcdir = @top_srcdir@ urandom_device = @urandom_device@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ -INCLUDES = -I$(top_srcdir)/src/libstrongswan +AM_CPPFLAGS = \ + -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 @@ -330,7 +398,6 @@ $(ACLOCAL_M4): $(am__aclocal_m4_deps) $(am__aclocal_m4_deps): install-ipseclibLTLIBRARIES: $(ipseclib_LTLIBRARIES) @$(NORMAL_INSTALL) - test -z "$(ipseclibdir)" || $(MKDIR_P) "$(DESTDIR)$(ipseclibdir)" @list='$(ipseclib_LTLIBRARIES)'; test -n "$(ipseclibdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ @@ -338,6 +405,8 @@ install-ipseclibLTLIBRARIES: $(ipseclib_LTLIBRARIES) else :; fi; \ done; \ test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(ipseclibdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(ipseclibdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(ipseclibdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(ipseclibdir)"; \ } @@ -359,8 +428,8 @@ clean-ipseclibLTLIBRARIES: echo "rm -f \"$${dir}/so_locations\""; \ rm -f "$${dir}/so_locations"; \ done -libtls.la: $(libtls_la_OBJECTS) $(libtls_la_DEPENDENCIES) - $(LINK) -rpath $(ipseclibdir) $(libtls_la_OBJECTS) $(libtls_la_LIBADD) $(LIBS) +libtls.la: $(libtls_la_OBJECTS) $(libtls_la_DEPENDENCIES) $(EXTRA_libtls_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) -rpath $(ipseclibdir) $(libtls_la_OBJECTS) $(libtls_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) @@ -382,31 +451,55 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tls_socket.Plo@am__quote@ .c.o: -@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(COMPILE) -c $< +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< .c.obj: -@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: -@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs +install-nobase_tls_includeHEADERS: $(nobase_tls_include_HEADERS) + @$(NORMAL_INSTALL) + @list='$(nobase_tls_include_HEADERS)'; test -n "$(tls_includedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(tls_includedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(tls_includedir)" || exit 1; \ + fi; \ + $(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)`; \ + dir='$(DESTDIR)$(tls_includedir)'; $(am__uninstall_files_from_dir) ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ @@ -492,9 +585,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 @@ -507,10 +600,15 @@ install-am: all-am installcheck: installcheck-am install-strip: - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - `test -z '$(STRIP)' || \ - echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi mostlyclean-generic: clean-generic: @@ -545,7 +643,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 +690,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 +702,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.c b/src/libtls/tls.c index 2bcaffbc8..6d33d843d 100644 --- a/src/libtls/tls.c +++ b/src/libtls/tls.c @@ -15,7 +15,7 @@ #include "tls.h" -#include <debug.h> +#include <utils/debug.h> #include "tls_protection.h" #include "tls_compression.h" @@ -107,16 +107,6 @@ struct private_tls_t { bool is_server; /** - * Server identity - */ - identification_t *server; - - /** - * Peer identity - */ - identification_t *peer; - - /** * Negotiated TLS version */ tls_version_t version; @@ -359,6 +349,18 @@ METHOD(tls_t, is_server, bool, return this->is_server; } +METHOD(tls_t, get_server_id, identification_t*, + private_tls_t *this) +{ + return this->handshake->get_server_id(this->handshake); +} + +METHOD(tls_t, get_peer_id, identification_t*, + private_tls_t *this) +{ + return this->handshake->get_peer_id(this->handshake); +} + METHOD(tls_t, get_version, tls_version_t, private_tls_t *this) { @@ -421,8 +423,6 @@ METHOD(tls_t, destroy, void, this->fragmentation->destroy(this->fragmentation); this->crypto->destroy(this->crypto); this->handshake->destroy(this->handshake); - DESTROY_IF(this->peer); - this->server->destroy(this->server); DESTROY_IF(this->application); this->alert->destroy(this->alert); @@ -457,6 +457,8 @@ tls_t *tls_create(bool is_server, identification_t *server, .process = _process, .build = _build, .is_server = _is_server, + .get_server_id = _get_server_id, + .get_peer_id = _get_peer_id, .get_version = _get_version, .set_version = _set_version, .get_purpose = _get_purpose, @@ -466,8 +468,6 @@ tls_t *tls_create(bool is_server, identification_t *server, }, .is_server = is_server, .version = TLS_1_2, - .server = server->clone(server), - .peer = peer ? peer->clone(peer) : NULL, .application = application, .purpose = purpose, ); @@ -477,12 +477,12 @@ tls_t *tls_create(bool is_server, identification_t *server, if (is_server) { this->handshake = &tls_server_create(&this->public, this->crypto, - this->alert, this->server, this->peer)->handshake; + this->alert, server, peer)->handshake; } else { this->handshake = &tls_peer_create(&this->public, this->crypto, - this->alert, this->peer, this->server)->handshake; + this->alert, peer, server)->handshake; } this->fragmentation = tls_fragmentation_create(this->handshake, this->alert, this->application); diff --git a/src/libtls/tls.h b/src/libtls/tls.h index e22b0facc..7f45b1e09 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; @@ -187,6 +193,20 @@ struct tls_t { bool (*is_server)(tls_t *this); /** + * Return the server identity. + * + * @return server identity + */ + identification_t* (*get_server_id)(tls_t *this); + + /** + * Return the peer identity. + * + * @return peer identity + */ + identification_t* (*get_peer_id)(tls_t *this); + + /** * Get the negotiated TLS/SSL version. * * @return negotiated TLS version diff --git a/src/libtls/tls_alert.c b/src/libtls/tls_alert.c index 8a4fa7d77..7dd219db8 100644 --- a/src/libtls/tls_alert.c +++ b/src/libtls/tls_alert.c @@ -15,8 +15,8 @@ #include "tls_alert.h" -#include <debug.h> -#include <utils/linked_list.h> +#include <utils/debug.h> +#include <collections/linked_list.h> ENUM_BEGIN(tls_alert_desc_names, TLS_CLOSE_NOTIFY, TLS_CLOSE_NOTIFY, "close notify", diff --git a/src/libtls/tls_cache.c b/src/libtls/tls_cache.c index a89201ad7..c13b1e851 100644 --- a/src/libtls/tls_cache.c +++ b/src/libtls/tls_cache.c @@ -15,9 +15,9 @@ #include "tls_cache.h" -#include <debug.h> -#include <utils/linked_list.h> -#include <utils/hashtable.h> +#include <utils/debug.h> +#include <collections/linked_list.h> +#include <collections/hashtable.h> #include <threading/rwlock.h> typedef struct private_tls_cache_t private_tls_cache_t; diff --git a/src/libtls/tls_crypto.c b/src/libtls/tls_crypto.c index 4d84876d0..12aa049a2 100644 --- a/src/libtls/tls_crypto.c +++ b/src/libtls/tls_crypto.c @@ -15,7 +15,7 @@ #include "tls_crypto.h" -#include <debug.h> +#include <utils/debug.h> ENUM_BEGIN(tls_cipher_suite_names, TLS_NULL_WITH_NULL_NULL, TLS_DH_anon_WITH_3DES_EDE_CBC_SHA, @@ -1110,6 +1110,7 @@ METHOD(tls_crypto_t, get_signature_algorithms, void, } enumerator->destroy(enumerator); + supported->wrap16(supported); writer->write_data16(writer, supported->get_buf(supported)); supported->destroy(supported); } @@ -1196,12 +1197,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 +1211,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 +1463,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 +1475,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 +1484,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 +1523,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 +1536,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 +1561,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 +1600,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 +1632,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 +1753,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..68cebb994 100644 --- a/src/libtls/tls_eap.c +++ b/src/libtls/tls_eap.c @@ -18,11 +18,14 @@ #include "tls.h" -#include <debug.h> +#include <utils/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..6e4347e3c 100644 --- a/src/libtls/tls_fragmentation.c +++ b/src/libtls/tls_fragmentation.c @@ -16,7 +16,12 @@ #include "tls_fragmentation.h" #include <bio/bio_reader.h> -#include <debug.h> +#include <utils/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); @@ -222,7 +223,7 @@ static status_t process_application(private_tls_fragmentation_t *this, continue; case SUCCESS: this->application_finished = TRUE; - return SUCCESS; + /* FALL */ case FAILED: default: this->alert->add(this->alert, TLS_FATAL, TLS_CLOSE_NOTIFY); @@ -367,7 +368,7 @@ static status_t build_application(private_tls_fragmentation_t *this) break; case SUCCESS: this->application_finished = TRUE; - break; + /* FALL */ case FAILED: default: this->alert->add(this->alert, TLS_FATAL, TLS_CLOSE_NOTIFY); @@ -390,6 +391,10 @@ METHOD(tls_fragmentation_t, build, status_t, this->state = ALERT_SENT; return INVALID_STATE; case ALERT_SENT: + if (this->application_finished) + { + return SUCCESS; + } return FAILED; case ALERT_NONE: break; @@ -427,14 +432,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_handshake.h b/src/libtls/tls_handshake.h index bea0024eb..7fa660c58 100644 --- a/src/libtls/tls_handshake.h +++ b/src/libtls/tls_handshake.h @@ -84,6 +84,20 @@ struct tls_handshake_t { bool (*finished)(tls_handshake_t *this); /** + * Get the peer identity authenticated/to authenticate during handshake. + * + * @return peer identity + */ + identification_t* (*get_peer_id)(tls_handshake_t *this); + + /** + * Get the server identity authenticated/to authenticate during handshake. + * + * @return server identity + */ + identification_t* (*get_server_id)(tls_handshake_t *this); + + /** * Destroy a tls_handshake_t. */ void (*destroy)(tls_handshake_t *this); diff --git a/src/libtls/tls_peer.c b/src/libtls/tls_peer.c index 6091702cf..b429da300 100644 --- a/src/libtls/tls_peer.c +++ b/src/libtls/tls_peer.c @@ -15,7 +15,7 @@ #include "tls_peer.h" -#include <debug.h> +#include <utils/debug.h> #include <credentials/certificates/x509.h> #include <time.h> @@ -665,6 +665,8 @@ METHOD(tls_handshake_t, process, status_t, { return process_certreq(this, reader); } + /* no cert request, server does not want to authenticate us */ + DESTROY_IF(this->peer); this->peer = NULL; /* fall through since TLS_CERTIFICATE_REQUEST is optional */ case STATE_CERTREQ_RECEIVED: @@ -709,13 +711,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 */ @@ -758,6 +762,7 @@ static status_t send_client_hello(private_tls_peer_t *this, enumerator->destroy(enumerator); if (curves) { + curves->wrap16(curves); extensions->write_data16(extensions, curves->get_buf(curves)); curves->destroy(curves); @@ -847,6 +852,7 @@ static status_t send_certificate(private_tls_peer_t *this, { DBG1(DBG_TLS, "no TLS peer certificate found for '%Y', " "skipping client authentication", this->peer); + this->peer->destroy(this->peer); this->peer = NULL; } @@ -903,20 +909,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 +968,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); @@ -1120,11 +1135,25 @@ METHOD(tls_handshake_t, finished, bool, return this->state == STATE_FINISHED_RECEIVED; } +METHOD(tls_handshake_t, get_peer_id, identification_t*, + private_tls_peer_t *this) +{ + return this->peer; +} + +METHOD(tls_handshake_t, get_server_id, identification_t*, + private_tls_peer_t *this) +{ + return this->server; +} + METHOD(tls_handshake_t, destroy, void, private_tls_peer_t *this) { DESTROY_IF(this->private); DESTROY_IF(this->dh); + DESTROY_IF(this->peer); + this->server->destroy(this->server); this->peer_auth->destroy(this->peer_auth); this->server_auth->destroy(this->server_auth); free(this->hashsig.ptr); @@ -1149,6 +1178,8 @@ tls_peer_t *tls_peer_create(tls_t *tls, tls_crypto_t *crypto, tls_alert_t *alert .cipherspec_changed = _cipherspec_changed, .change_cipherspec = _change_cipherspec, .finished = _finished, + .get_peer_id = _get_peer_id, + .get_server_id = _get_server_id, .destroy = _destroy, }, }, @@ -1156,8 +1187,8 @@ tls_peer_t *tls_peer_create(tls_t *tls, tls_crypto_t *crypto, tls_alert_t *alert .tls = tls, .crypto = crypto, .alert = alert, - .peer = peer, - .server = server, + .peer = peer ? peer->clone(peer) : NULL, + .server = server->clone(server), .peer_auth = auth_cfg_create(), .server_auth = auth_cfg_create(), ); diff --git a/src/libtls/tls_peer.h b/src/libtls/tls_peer.h index f773ea72e..e4ff6f83c 100644 --- a/src/libtls/tls_peer.h +++ b/src/libtls/tls_peer.h @@ -41,11 +41,15 @@ struct tls_peer_t { /** * Create a tls_peer instance. -* + * + * If a peer identity is given, but the client does not get requested or is + * otherwise unable to perform client authentication, NULL is returned in + * tls_handshake_t.get_peer_id() instead of the peer identity. + * * @param tls TLS stack * @param crypto TLS crypto helper * @param alert TLS alert handler - * @param peer peer identity + * @param peer peer identity, NULL to skip client authentication * @param server server identity */ tls_peer_t *tls_peer_create(tls_t *tls, tls_crypto_t *crypto, tls_alert_t *alert, 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..0d5df18f7 100644 --- a/src/libtls/tls_protection.c +++ b/src/libtls/tls_protection.c @@ -15,7 +15,7 @@ #include "tls_protection.h" -#include <debug.h> +#include <utils/debug.h> typedef struct private_tls_protection_t private_tls_protection_t; @@ -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..aeb5a714f 100644 --- a/src/libtls/tls_server.c +++ b/src/libtls/tls_server.c @@ -17,7 +17,7 @@ #include <time.h> -#include <debug.h> +#include <utils/debug.h> #include <credentials/certificates/x509.h> typedef struct private_tls_server_t private_tls_server_t; @@ -80,6 +80,11 @@ struct private_tls_server_t { identification_t *peer; /** + * Is it acceptable if we couldn't verify the peer certificate? + */ + bool peer_auth_optional; + + /** * State we are in */ server_state_t state; @@ -266,13 +271,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 +318,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); @@ -365,6 +372,12 @@ static status_t process_certificate(private_tls_server_t *this, DBG1(DBG_TLS, "received TLS peer certificate '%Y'", cert->get_subject(cert)); first = FALSE; + if (this->peer == NULL) + { /* apply identity to authenticate */ + this->peer = cert->get_subject(cert); + this->peer = this->peer->clone(this->peer); + this->peer_auth_optional = TRUE; + } } else { @@ -407,13 +420,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 +449,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 +502,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; @@ -539,13 +561,22 @@ static status_t process_cert_verify(private_tls_server_t *this, { DBG1(DBG_TLS, "no trusted certificate found for '%Y' to verify TLS peer", this->peer); - this->alert->add(this->alert, TLS_FATAL, TLS_CERTIFICATE_UNKNOWN); - return NEED_MORE; + if (!this->peer_auth_optional) + { /* client authentication is required */ + this->alert->add(this->alert, TLS_FATAL, TLS_CERTIFICATE_UNKNOWN); + return NEED_MORE; + } + /* reset peer identity, we couldn't authenticate it */ + this->peer->destroy(this->peer); + this->peer = NULL; + this->state = STATE_KEY_EXCHANGE_RECEIVED; + } + else + { + this->state = STATE_CERT_VERIFY_RECEIVED; } - this->crypto->append_handshake(this->crypto, TLS_CERTIFICATE_VERIFY, reader->peek(reader)); - this->state = STATE_CERT_VERIFY_RECEIVED; return NEED_MORE; } @@ -968,11 +999,7 @@ METHOD(tls_handshake_t, build, status_t, } /* otherwise fall through to next state */ case STATE_KEY_EXCHANGE_SENT: - if (this->peer) - { - return send_certificate_request(this, type, writer); - } - /* otherwise fall through to next state */ + return send_certificate_request(this, type, writer); case STATE_CERTREQ_SENT: return send_hello_done(this, type, writer); case STATE_CIPHERSPEC_CHANGED_OUT: @@ -1034,11 +1061,25 @@ METHOD(tls_handshake_t, finished, bool, return this->state == STATE_FINISHED_SENT; } +METHOD(tls_handshake_t, get_peer_id, identification_t*, + private_tls_server_t *this) +{ + return this->peer; +} + +METHOD(tls_handshake_t, get_server_id, identification_t*, + private_tls_server_t *this) +{ + return this->server; +} + METHOD(tls_handshake_t, destroy, void, private_tls_server_t *this) { DESTROY_IF(this->private); DESTROY_IF(this->dh); + DESTROY_IF(this->peer); + this->server->destroy(this->server); this->peer_auth->destroy(this->peer_auth); this->server_auth->destroy(this->server_auth); free(this->hashsig.ptr); @@ -1064,14 +1105,16 @@ tls_server_t *tls_server_create(tls_t *tls, .cipherspec_changed = _cipherspec_changed, .change_cipherspec = _change_cipherspec, .finished = _finished, + .get_peer_id = _get_peer_id, + .get_server_id = _get_server_id, .destroy = _destroy, }, }, .tls = tls, .crypto = crypto, .alert = alert, - .server = server, - .peer = peer, + .server = server->clone(server), + .peer = peer ? peer->clone(peer) : NULL, .state = STATE_INIT, .peer_auth = auth_cfg_create(), .server_auth = auth_cfg_create(), diff --git a/src/libtls/tls_server.h b/src/libtls/tls_server.h index 6289dc8eb..d6b8de153 100644 --- a/src/libtls/tls_server.h +++ b/src/libtls/tls_server.h @@ -42,11 +42,16 @@ struct tls_server_t { /** * Create a tls_server instance. * + * If a peer identity is given, the client must authenticate with a valid + * certificate for this identity, or the connection fails. If peer is NULL, + * but the client authenticates nonetheless, the authenticated identity + * gets returned by tls_handshake_t.get_peer_id(). + * * @param tls TLS stack * @param crypto TLS crypto helper * @param alert TLS alert handler * @param server server identity - * @param peer peer identity + * @param peer peer identity, or NULL */ tls_server_t *tls_server_create(tls_t *tls, tls_crypto_t *crypto, tls_alert_t *alert, diff --git a/src/libtls/tls_socket.c b/src/libtls/tls_socket.c index 3abff596d..4ba964000 100644 --- a/src/libtls/tls_socket.c +++ b/src/libtls/tls_socket.c @@ -18,7 +18,7 @@ #include <unistd.h> #include <errno.h> -#include <debug.h> +#include <utils/debug.h> #include <threading/thread.h> /** @@ -42,14 +42,39 @@ struct private_tls_application_t { tls_application_t application; /** - * Chunk of data to send + * Output buffer to write to */ chunk_t out; /** - * Chunk of data received + * Number of bytes written to out + */ + size_t out_done; + + /** + * Input buffer to read to */ chunk_t in; + + /** + * Number of bytes read to in + */ + size_t in_done; + + /** + * Cached input data + */ + chunk_t cache; + + /** + * Bytes consumed in cache + */ + size_t cache_done; + + /** + * Close TLS connection? + */ + bool close; }; /** @@ -82,22 +107,44 @@ METHOD(tls_application_t, process, status_t, private_tls_application_t *this, bio_reader_t *reader) { chunk_t data; + size_t len; - if (!reader->read_data(reader, reader->remaining(reader), &data)) + if (this->close) { - return FAILED; + return SUCCESS; + } + len = min(reader->remaining(reader), this->in.len - this->in_done); + if (len) + { /* copy to read buffer as much as fits in */ + if (!reader->read_data(reader, len, &data)) + { + return FAILED; + } + memcpy(this->in.ptr + this->in_done, data.ptr, data.len); + this->in_done += data.len; + } + else + { /* read buffer is full, cache for next read */ + if (!reader->read_data(reader, reader->remaining(reader), &data)) + { + return FAILED; + } + this->cache = chunk_cat("mc", this->cache, data); } - this->in = chunk_cat("mc", this->in, data); return NEED_MORE; } METHOD(tls_application_t, build, status_t, private_tls_application_t *this, bio_writer_t *writer) { - if (this->out.len) + if (this->close) + { + return SUCCESS; + } + if (this->out.len > this->out_done) { writer->write_data(writer, this->out); - this->out = chunk_empty; + this->out_done = this->out.len; return NEED_MORE; } return INVALID_STATE; @@ -106,11 +153,12 @@ METHOD(tls_application_t, build, status_t, /** * TLS data exchange loop */ -static bool exchange(private_tls_socket_t *this, bool wr) +static bool exchange(private_tls_socket_t *this, bool wr, bool block) { char buf[CRYPTO_BUF_SIZE], *pos; - ssize_t len, out; - int round = 0; + ssize_t in, out; + size_t len; + int round = 0, flags; for (round = 0; TRUE; round++) { @@ -137,6 +185,8 @@ static bool exchange(private_tls_socket_t *this, bool wr) continue; case INVALID_STATE: break; + case SUCCESS: + return TRUE; default: return FALSE; } @@ -144,55 +194,97 @@ static bool exchange(private_tls_socket_t *this, bool wr) } if (wr) { - if (this->app.out.len == 0) + if (this->app.out_done == this->app.out.len) { /* all data written */ return TRUE; } } else { - if (this->app.in.len) - { /* some data received */ + if (this->app.in_done == this->app.in.len) + { /* buffer fully received */ return TRUE; } - if (round > 0) - { /* did some handshaking, return empty chunk to not block */ - return TRUE; + } + + flags = 0; + if (this->app.out_done == this->app.out.len) + { + if (!block || this->app.in_done) + { + flags |= MSG_DONTWAIT; } } - len = read(this->fd, buf, sizeof(buf)); - if (len <= 0) + in = recv(this->fd, buf, sizeof(buf), flags); + if (in < 0) { + if (errno == EAGAIN || errno == EWOULDBLOCK) + { + if (this->app.in_done == 0) + { + /* reading, nothing got yet, and call would block */ + errno = EWOULDBLOCK; + this->app.in_done = -1; + } + return TRUE; + } return FALSE; } - if (this->tls->process(this->tls, buf, len) != NEED_MORE) + if (in == 0) + { /* EOF */ + return TRUE; + } + switch (this->tls->process(this->tls, buf, in)) { - return FALSE; + case NEED_MORE: + break; + case SUCCESS: + return TRUE; + default: + return FALSE; } } } -METHOD(tls_socket_t, read_, bool, - private_tls_socket_t *this, chunk_t *buf) +METHOD(tls_socket_t, read_, ssize_t, + private_tls_socket_t *this, void *buf, size_t len, bool block) { - if (exchange(this, FALSE)) + if (this->app.cache.len) { - *buf = this->app.in; - this->app.in = chunk_empty; - return TRUE; + size_t cache; + + cache = min(len, this->app.cache.len - this->app.cache_done); + memcpy(buf, this->app.cache.ptr + this->app.cache_done, cache); + + this->app.cache_done += cache; + if (this->app.cache_done == this->app.cache.len) + { + chunk_free(&this->app.cache); + this->app.cache_done = 0; + } + return cache; } - return FALSE; + this->app.in.ptr = buf; + this->app.in.len = len; + this->app.in_done = 0; + if (exchange(this, FALSE, block)) + { + return this->app.in_done; + } + return -1; } -METHOD(tls_socket_t, write_, bool, - private_tls_socket_t *this, chunk_t buf) +METHOD(tls_socket_t, write_, ssize_t, + private_tls_socket_t *this, void *buf, size_t len) { - this->app.out = buf; - if (exchange(this, TRUE)) + this->app.out.ptr = buf; + this->app.out.len = len; + this->app.out_done = 0; + if (exchange(this, TRUE, FALSE)) { - return TRUE; + return this->app.out_done; } - return FALSE; + return -1; } METHOD(tls_socket_t, splice, bool, @@ -200,68 +292,85 @@ METHOD(tls_socket_t, splice, bool, { char buf[PLAIN_BUF_SIZE], *pos; fd_set set; - chunk_t data; - ssize_t len; - bool old; + ssize_t in, out; + bool old, plain_eof = FALSE, crypto_eof = FALSE; - while (TRUE) + while (!plain_eof && !crypto_eof) { FD_ZERO(&set); FD_SET(rfd, &set); FD_SET(this->fd, &set); old = thread_cancelability(TRUE); - len = select(max(rfd, this->fd) + 1, &set, NULL, NULL, NULL); + in = select(max(rfd, this->fd) + 1, &set, NULL, NULL, NULL); thread_cancelability(old); - if (len == -1) + if (in == -1) { DBG1(DBG_TLS, "TLS select error: %s", strerror(errno)); return FALSE; } - if (FD_ISSET(this->fd, &set)) + while (!plain_eof && FD_ISSET(this->fd, &set)) { - if (!read_(this, &data)) - { - DBG2(DBG_TLS, "TLS read error/disconnect"); - return TRUE; - } - pos = data.ptr; - while (data.len) + in = read_(this, buf, sizeof(buf), FALSE); + switch (in) { - len = write(wfd, pos, data.len); - if (len == -1) - { - free(data.ptr); - DBG1(DBG_TLS, "TLS plain write error: %s", strerror(errno)); - return FALSE; - } - data.len -= len; - pos += len; + case 0: + plain_eof = TRUE; + break; + case -1: + if (errno != EWOULDBLOCK) + { + DBG1(DBG_TLS, "TLS read error: %s", strerror(errno)); + return FALSE; + } + break; + default: + pos = buf; + while (in) + { + out = write(wfd, pos, in); + if (out == -1) + { + DBG1(DBG_TLS, "TLS plain write error: %s", + strerror(errno)); + return FALSE; + } + in -= out; + pos += out; + } + continue; } - free(data.ptr); + break; } - if (FD_ISSET(rfd, &set)) + if (!crypto_eof && FD_ISSET(rfd, &set)) { - len = read(rfd, buf, sizeof(buf)); - if (len > 0) - { - if (!write_(this, chunk_create(buf, len))) - { - DBG1(DBG_TLS, "TLS write error"); - return FALSE; - } - } - else + in = read(rfd, buf, sizeof(buf)); + switch (in) { - if (len < 0) - { + case 0: + crypto_eof = TRUE; + break; + case -1: DBG1(DBG_TLS, "TLS plain read error: %s", strerror(errno)); return FALSE; - } - return TRUE; + default: + pos = buf; + while (in) + { + out = write_(this, pos, in); + if (out == -1) + { + DBG1(DBG_TLS, "TLS write error"); + return FALSE; + } + in -= out; + pos += out; + } + break; } } } + return TRUE; } METHOD(tls_socket_t, get_fd, int, @@ -270,11 +379,26 @@ METHOD(tls_socket_t, get_fd, int, return this->fd; } +METHOD(tls_socket_t, get_server_id, identification_t*, + private_tls_socket_t *this) +{ + return this->tls->get_server_id(this->tls); +} + +METHOD(tls_socket_t, get_peer_id, identification_t*, + private_tls_socket_t *this) +{ + return this->tls->get_peer_id(this->tls); +} + METHOD(tls_socket_t, destroy, void, private_tls_socket_t *this) { + /* send a TLS close notify if not done yet */ + this->app.close = TRUE; + write_(this, NULL, 0); + free(this->app.cache.ptr); this->tls->destroy(this->tls); - free(this->app.in.ptr); free(this); } @@ -292,6 +416,8 @@ tls_socket_t *tls_socket_create(bool is_server, identification_t *server, .write = _write_, .splice = _splice, .get_fd = _get_fd, + .get_server_id = _get_server_id, + .get_peer_id = _get_peer_id, .destroy = _destroy, }, .app = { diff --git a/src/libtls/tls_socket.h b/src/libtls/tls_socket.h index edd05fd29..75130a4d3 100644 --- a/src/libtls/tls_socket.h +++ b/src/libtls/tls_socket.h @@ -35,24 +35,27 @@ typedef struct tls_socket_t tls_socket_t; struct tls_socket_t { /** - * Read data from secured socket, return allocated chunk. + * Read data from secured socket. * * This call is blocking, you may use select() on the underlying socket to - * wait for data. If the there was non-application data available, the - * read function can return an empty chunk. + * wait for data. If "block" is FALSE and no application data is available, + * the function returns -1 and sets errno to EWOULDBLOCK. * - * @param data pointer to allocate received data - * @return TRUE if data received successfully + * @param buf buffer to write received data to + * @param len size of buffer + * @param block TRUE to block this call, FALSE to fail if it would block + * @return number of bytes read, 0 on EOF, -1 on error */ - bool (*read)(tls_socket_t *this, chunk_t *data); + ssize_t (*read)(tls_socket_t *this, void *buf, size_t len, bool block); /** - * Write a chunk of data over the secured socket. + * Write data over the secured socket. * - * @param data data to send - * @return TRUE if data sent successfully + * @param buf data to send + * @param len number of bytes to write from buf + * @return number of bytes written, -1 on error */ - bool (*write)(tls_socket_t *this, chunk_t data); + ssize_t (*write)(tls_socket_t *this, void *buf, size_t len); /** * Read/write plain data from file descriptor. @@ -74,6 +77,20 @@ struct tls_socket_t { int (*get_fd)(tls_socket_t *this); /** + * Return the server identity. + * + * @return server identity + */ + identification_t* (*get_server_id)(tls_socket_t *this); + + /** + * Return the peer identity. + * + * @return peer identity + */ + identification_t* (*get_peer_id)(tls_socket_t *this); + + /** * Destroy a tls_socket_t. */ void (*destroy)(tls_socket_t *this); |