summaryrefslogtreecommitdiff
path: root/release/src/router/cyassl/src
diff options
context:
space:
mode:
Diffstat (limited to 'release/src/router/cyassl/src')
-rw-r--r--release/src/router/cyassl/src/Makefile.am43
-rw-r--r--release/src/router/cyassl/src/Makefile.in730
-rw-r--r--release/src/router/cyassl/src/cyassl_int.c5379
-rw-r--r--release/src/router/cyassl/src/cyassl_io.c190
-rw-r--r--release/src/router/cyassl/src/keys.c751
-rw-r--r--release/src/router/cyassl/src/sniffer.c2187
-rw-r--r--release/src/router/cyassl/src/ssl.c3496
-rw-r--r--release/src/router/cyassl/src/tls.c457
8 files changed, 13233 insertions, 0 deletions
diff --git a/release/src/router/cyassl/src/Makefile.am b/release/src/router/cyassl/src/Makefile.am
new file mode 100644
index 00000000..5d3181ba
--- /dev/null
+++ b/release/src/router/cyassl/src/Makefile.am
@@ -0,0 +1,43 @@
+INCLUDES = -I../include -I../ctaocrypt/include -I../include/openssl
+
+lib_LTLIBRARIES = libcyassl.la
+libcyassl_la_SOURCES = \
+ cyassl_int.c cyassl_io.c keys.c ssl.c tls.c \
+ ../ctaocrypt/src/asn.c ../ctaocrypt/src/coding.c ../ctaocrypt/src/des3.c \
+ ../ctaocrypt/src/hmac.c ../ctaocrypt/src/md5.c ../ctaocrypt/src/md4.c \
+ ../ctaocrypt/src/random.c ../ctaocrypt/src/rsa.c ../ctaocrypt/src/sha.c \
+ ../ctaocrypt/src/aes.c ../ctaocrypt/src/sha256.c ../ctaocrypt/src/dh.c \
+ ../ctaocrypt/src/dsa.c ../ctaocrypt/src/arc4.c ../ctaocrypt/src/rabbit.c \
+ ../ctaocrypt/src/pwdbased.c
+libcyassl_la_LDFLAGS = -no-undefined -version-info 0:0:0
+EXTRA_DIST = ../include/*.h ../include/openssl/*.h ../include/*.rc
+
+if BUILD_AESNI
+libcyassl_la_SOURCES += ../ctaocrypt/src/aes_asm.s
+endif
+
+if BUILD_RIPEMD
+libcyassl_la_SOURCES += ../ctaocrypt/src/ripemd.c
+endif
+
+if BUILD_SHA512
+libcyassl_la_SOURCES += ../ctaocrypt/src/sha512.c
+endif
+
+if BUILD_SNIFFER
+libcyassl_la_SOURCES += sniffer.c
+endif
+
+if BUILD_HC128
+libcyassl_la_SOURCES += ../ctaocrypt/src/hc128.c
+endif
+
+if BUILD_FASTMATH
+libcyassl_la_SOURCES += ../ctaocrypt/src/tfm.c
+else
+libcyassl_la_SOURCES += ../ctaocrypt/src/integer.c
+endif
+
+if BUILD_ECC
+libcyassl_la_SOURCES += ../ctaocrypt/src/ecc.c
+endif
diff --git a/release/src/router/cyassl/src/Makefile.in b/release/src/router/cyassl/src/Makefile.in
new file mode 100644
index 00000000..0f61b4e1
--- /dev/null
+++ b/release/src/router/cyassl/src/Makefile.in
@@ -0,0 +1,730 @@
+# Makefile.in generated by automake 1.10 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006 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.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+@BUILD_AESNI_TRUE@am__append_1 = ../ctaocrypt/src/aes_asm.s
+@BUILD_RIPEMD_TRUE@am__append_2 = ../ctaocrypt/src/ripemd.c
+@BUILD_SHA512_TRUE@am__append_3 = ../ctaocrypt/src/sha512.c
+@BUILD_SNIFFER_TRUE@am__append_4 = sniffer.c
+@BUILD_HC128_TRUE@am__append_5 = ../ctaocrypt/src/hc128.c
+@BUILD_FASTMATH_TRUE@am__append_6 = ../ctaocrypt/src/tfm.c
+@BUILD_FASTMATH_FALSE@am__append_7 = ../ctaocrypt/src/integer.c
+@BUILD_ECC_TRUE@am__append_8 = ../ctaocrypt/src/ecc.c
+subdir = src
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/acx_pthread.m4 \
+ $(top_srcdir)/m4/lib_socket_nsl.m4 $(top_srcdir)/m4/libtool.m4 \
+ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+ $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/ctaocrypt/include/config.h
+CONFIG_CLEAN_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+am__installdirs = "$(DESTDIR)$(libdir)"
+libLTLIBRARIES_INSTALL = $(INSTALL)
+LTLIBRARIES = $(lib_LTLIBRARIES)
+libcyassl_la_LIBADD =
+am__libcyassl_la_SOURCES_DIST = cyassl_int.c cyassl_io.c keys.c ssl.c \
+ tls.c ../ctaocrypt/src/asn.c ../ctaocrypt/src/coding.c \
+ ../ctaocrypt/src/des3.c ../ctaocrypt/src/hmac.c \
+ ../ctaocrypt/src/md5.c ../ctaocrypt/src/md4.c \
+ ../ctaocrypt/src/random.c ../ctaocrypt/src/rsa.c \
+ ../ctaocrypt/src/sha.c ../ctaocrypt/src/aes.c \
+ ../ctaocrypt/src/sha256.c ../ctaocrypt/src/dh.c \
+ ../ctaocrypt/src/dsa.c ../ctaocrypt/src/arc4.c \
+ ../ctaocrypt/src/rabbit.c ../ctaocrypt/src/pwdbased.c \
+ ../ctaocrypt/src/aes_asm.s ../ctaocrypt/src/ripemd.c \
+ ../ctaocrypt/src/sha512.c sniffer.c ../ctaocrypt/src/hc128.c \
+ ../ctaocrypt/src/tfm.c ../ctaocrypt/src/integer.c \
+ ../ctaocrypt/src/ecc.c
+@BUILD_AESNI_TRUE@am__objects_1 = aes_asm.lo
+@BUILD_RIPEMD_TRUE@am__objects_2 = ripemd.lo
+@BUILD_SHA512_TRUE@am__objects_3 = sha512.lo
+@BUILD_SNIFFER_TRUE@am__objects_4 = sniffer.lo
+@BUILD_HC128_TRUE@am__objects_5 = hc128.lo
+@BUILD_FASTMATH_TRUE@am__objects_6 = tfm.lo
+@BUILD_FASTMATH_FALSE@am__objects_7 = integer.lo
+@BUILD_ECC_TRUE@am__objects_8 = ecc.lo
+am_libcyassl_la_OBJECTS = cyassl_int.lo cyassl_io.lo keys.lo ssl.lo \
+ tls.lo asn.lo coding.lo des3.lo hmac.lo md5.lo md4.lo \
+ random.lo rsa.lo sha.lo aes.lo sha256.lo dh.lo dsa.lo arc4.lo \
+ rabbit.lo pwdbased.lo $(am__objects_1) $(am__objects_2) \
+ $(am__objects_3) $(am__objects_4) $(am__objects_5) \
+ $(am__objects_6) $(am__objects_7) $(am__objects_8)
+libcyassl_la_OBJECTS = $(am_libcyassl_la_OBJECTS)
+libcyassl_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(libcyassl_la_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I. -I$(top_builddir)/ctaocrypt/include@am__isrc@
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+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)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+CCASCOMPILE = $(CCAS) $(AM_CCASFLAGS) $(CCASFLAGS)
+LTCCASCOMPILE = $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CCAS) $(AM_CCASFLAGS) $(CCASFLAGS)
+SOURCES = $(libcyassl_la_SOURCES)
+DIST_SOURCES = $(am__libcyassl_la_SOURCES_DIST)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCAS = @CCAS@
+CCASDEPMODE = @CCASDEPMODE@
+CCASFLAGS = @CCASFLAGS@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBM = @LIBM@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PTHREAD_CC = @PTHREAD_CC@
+PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+acx_pthread_config = @acx_pthread_config@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+INCLUDES = -I../include -I../ctaocrypt/include -I../include/openssl
+lib_LTLIBRARIES = libcyassl.la
+libcyassl_la_SOURCES = cyassl_int.c cyassl_io.c keys.c ssl.c tls.c \
+ ../ctaocrypt/src/asn.c ../ctaocrypt/src/coding.c \
+ ../ctaocrypt/src/des3.c ../ctaocrypt/src/hmac.c \
+ ../ctaocrypt/src/md5.c ../ctaocrypt/src/md4.c \
+ ../ctaocrypt/src/random.c ../ctaocrypt/src/rsa.c \
+ ../ctaocrypt/src/sha.c ../ctaocrypt/src/aes.c \
+ ../ctaocrypt/src/sha256.c ../ctaocrypt/src/dh.c \
+ ../ctaocrypt/src/dsa.c ../ctaocrypt/src/arc4.c \
+ ../ctaocrypt/src/rabbit.c ../ctaocrypt/src/pwdbased.c \
+ $(am__append_1) $(am__append_2) $(am__append_3) \
+ $(am__append_4) $(am__append_5) $(am__append_6) \
+ $(am__append_7) $(am__append_8)
+libcyassl_la_LDFLAGS = -no-undefined -version-info 0:0:0
+EXTRA_DIST = ../include/*.h ../include/openssl/*.h ../include/*.rc
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj .s
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)"
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ if test -f $$p; then \
+ f=$(am__strip_dir) \
+ echo " $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \
+ $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \
+ else :; fi; \
+ done
+
+uninstall-libLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ p=$(am__strip_dir) \
+ echo " $(LIBTOOL) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \
+ $(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \
+ done
+
+clean-libLTLIBRARIES:
+ -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libcyassl.la: $(libcyassl_la_OBJECTS) $(libcyassl_la_DEPENDENCIES)
+ $(libcyassl_la_LINK) -rpath $(libdir) $(libcyassl_la_OBJECTS) $(libcyassl_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/aes.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arc4.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asn.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/coding.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cyassl_int.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cyassl_io.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/des3.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dh.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dsa.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ecc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hc128.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hmac.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/integer.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/keys.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/md4.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/md5.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pwdbased.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rabbit.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/random.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ripemd.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rsa.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sha.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sha256.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sha512.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sniffer.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ssl.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tfm.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tls.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+asn.lo: ../ctaocrypt/src/asn.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT asn.lo -MD -MP -MF $(DEPDIR)/asn.Tpo -c -o asn.lo `test -f '../ctaocrypt/src/asn.c' || echo '$(srcdir)/'`../ctaocrypt/src/asn.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/asn.Tpo $(DEPDIR)/asn.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../ctaocrypt/src/asn.c' object='asn.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o asn.lo `test -f '../ctaocrypt/src/asn.c' || echo '$(srcdir)/'`../ctaocrypt/src/asn.c
+
+coding.lo: ../ctaocrypt/src/coding.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT coding.lo -MD -MP -MF $(DEPDIR)/coding.Tpo -c -o coding.lo `test -f '../ctaocrypt/src/coding.c' || echo '$(srcdir)/'`../ctaocrypt/src/coding.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/coding.Tpo $(DEPDIR)/coding.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../ctaocrypt/src/coding.c' object='coding.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o coding.lo `test -f '../ctaocrypt/src/coding.c' || echo '$(srcdir)/'`../ctaocrypt/src/coding.c
+
+des3.lo: ../ctaocrypt/src/des3.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT des3.lo -MD -MP -MF $(DEPDIR)/des3.Tpo -c -o des3.lo `test -f '../ctaocrypt/src/des3.c' || echo '$(srcdir)/'`../ctaocrypt/src/des3.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/des3.Tpo $(DEPDIR)/des3.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../ctaocrypt/src/des3.c' object='des3.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o des3.lo `test -f '../ctaocrypt/src/des3.c' || echo '$(srcdir)/'`../ctaocrypt/src/des3.c
+
+hmac.lo: ../ctaocrypt/src/hmac.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT hmac.lo -MD -MP -MF $(DEPDIR)/hmac.Tpo -c -o hmac.lo `test -f '../ctaocrypt/src/hmac.c' || echo '$(srcdir)/'`../ctaocrypt/src/hmac.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/hmac.Tpo $(DEPDIR)/hmac.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../ctaocrypt/src/hmac.c' object='hmac.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o hmac.lo `test -f '../ctaocrypt/src/hmac.c' || echo '$(srcdir)/'`../ctaocrypt/src/hmac.c
+
+md5.lo: ../ctaocrypt/src/md5.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT md5.lo -MD -MP -MF $(DEPDIR)/md5.Tpo -c -o md5.lo `test -f '../ctaocrypt/src/md5.c' || echo '$(srcdir)/'`../ctaocrypt/src/md5.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/md5.Tpo $(DEPDIR)/md5.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../ctaocrypt/src/md5.c' object='md5.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o md5.lo `test -f '../ctaocrypt/src/md5.c' || echo '$(srcdir)/'`../ctaocrypt/src/md5.c
+
+md4.lo: ../ctaocrypt/src/md4.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT md4.lo -MD -MP -MF $(DEPDIR)/md4.Tpo -c -o md4.lo `test -f '../ctaocrypt/src/md4.c' || echo '$(srcdir)/'`../ctaocrypt/src/md4.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/md4.Tpo $(DEPDIR)/md4.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../ctaocrypt/src/md4.c' object='md4.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o md4.lo `test -f '../ctaocrypt/src/md4.c' || echo '$(srcdir)/'`../ctaocrypt/src/md4.c
+
+random.lo: ../ctaocrypt/src/random.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT random.lo -MD -MP -MF $(DEPDIR)/random.Tpo -c -o random.lo `test -f '../ctaocrypt/src/random.c' || echo '$(srcdir)/'`../ctaocrypt/src/random.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/random.Tpo $(DEPDIR)/random.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../ctaocrypt/src/random.c' object='random.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o random.lo `test -f '../ctaocrypt/src/random.c' || echo '$(srcdir)/'`../ctaocrypt/src/random.c
+
+rsa.lo: ../ctaocrypt/src/rsa.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsa.lo -MD -MP -MF $(DEPDIR)/rsa.Tpo -c -o rsa.lo `test -f '../ctaocrypt/src/rsa.c' || echo '$(srcdir)/'`../ctaocrypt/src/rsa.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/rsa.Tpo $(DEPDIR)/rsa.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../ctaocrypt/src/rsa.c' object='rsa.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsa.lo `test -f '../ctaocrypt/src/rsa.c' || echo '$(srcdir)/'`../ctaocrypt/src/rsa.c
+
+sha.lo: ../ctaocrypt/src/sha.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sha.lo -MD -MP -MF $(DEPDIR)/sha.Tpo -c -o sha.lo `test -f '../ctaocrypt/src/sha.c' || echo '$(srcdir)/'`../ctaocrypt/src/sha.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/sha.Tpo $(DEPDIR)/sha.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../ctaocrypt/src/sha.c' object='sha.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sha.lo `test -f '../ctaocrypt/src/sha.c' || echo '$(srcdir)/'`../ctaocrypt/src/sha.c
+
+aes.lo: ../ctaocrypt/src/aes.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT aes.lo -MD -MP -MF $(DEPDIR)/aes.Tpo -c -o aes.lo `test -f '../ctaocrypt/src/aes.c' || echo '$(srcdir)/'`../ctaocrypt/src/aes.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/aes.Tpo $(DEPDIR)/aes.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../ctaocrypt/src/aes.c' object='aes.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o aes.lo `test -f '../ctaocrypt/src/aes.c' || echo '$(srcdir)/'`../ctaocrypt/src/aes.c
+
+sha256.lo: ../ctaocrypt/src/sha256.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sha256.lo -MD -MP -MF $(DEPDIR)/sha256.Tpo -c -o sha256.lo `test -f '../ctaocrypt/src/sha256.c' || echo '$(srcdir)/'`../ctaocrypt/src/sha256.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/sha256.Tpo $(DEPDIR)/sha256.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../ctaocrypt/src/sha256.c' object='sha256.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sha256.lo `test -f '../ctaocrypt/src/sha256.c' || echo '$(srcdir)/'`../ctaocrypt/src/sha256.c
+
+dh.lo: ../ctaocrypt/src/dh.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dh.lo -MD -MP -MF $(DEPDIR)/dh.Tpo -c -o dh.lo `test -f '../ctaocrypt/src/dh.c' || echo '$(srcdir)/'`../ctaocrypt/src/dh.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/dh.Tpo $(DEPDIR)/dh.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../ctaocrypt/src/dh.c' object='dh.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dh.lo `test -f '../ctaocrypt/src/dh.c' || echo '$(srcdir)/'`../ctaocrypt/src/dh.c
+
+dsa.lo: ../ctaocrypt/src/dsa.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dsa.lo -MD -MP -MF $(DEPDIR)/dsa.Tpo -c -o dsa.lo `test -f '../ctaocrypt/src/dsa.c' || echo '$(srcdir)/'`../ctaocrypt/src/dsa.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/dsa.Tpo $(DEPDIR)/dsa.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../ctaocrypt/src/dsa.c' object='dsa.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dsa.lo `test -f '../ctaocrypt/src/dsa.c' || echo '$(srcdir)/'`../ctaocrypt/src/dsa.c
+
+arc4.lo: ../ctaocrypt/src/arc4.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT arc4.lo -MD -MP -MF $(DEPDIR)/arc4.Tpo -c -o arc4.lo `test -f '../ctaocrypt/src/arc4.c' || echo '$(srcdir)/'`../ctaocrypt/src/arc4.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/arc4.Tpo $(DEPDIR)/arc4.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../ctaocrypt/src/arc4.c' object='arc4.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o arc4.lo `test -f '../ctaocrypt/src/arc4.c' || echo '$(srcdir)/'`../ctaocrypt/src/arc4.c
+
+rabbit.lo: ../ctaocrypt/src/rabbit.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rabbit.lo -MD -MP -MF $(DEPDIR)/rabbit.Tpo -c -o rabbit.lo `test -f '../ctaocrypt/src/rabbit.c' || echo '$(srcdir)/'`../ctaocrypt/src/rabbit.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/rabbit.Tpo $(DEPDIR)/rabbit.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../ctaocrypt/src/rabbit.c' object='rabbit.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rabbit.lo `test -f '../ctaocrypt/src/rabbit.c' || echo '$(srcdir)/'`../ctaocrypt/src/rabbit.c
+
+pwdbased.lo: ../ctaocrypt/src/pwdbased.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT pwdbased.lo -MD -MP -MF $(DEPDIR)/pwdbased.Tpo -c -o pwdbased.lo `test -f '../ctaocrypt/src/pwdbased.c' || echo '$(srcdir)/'`../ctaocrypt/src/pwdbased.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/pwdbased.Tpo $(DEPDIR)/pwdbased.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../ctaocrypt/src/pwdbased.c' object='pwdbased.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o pwdbased.lo `test -f '../ctaocrypt/src/pwdbased.c' || echo '$(srcdir)/'`../ctaocrypt/src/pwdbased.c
+
+ripemd.lo: ../ctaocrypt/src/ripemd.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ripemd.lo -MD -MP -MF $(DEPDIR)/ripemd.Tpo -c -o ripemd.lo `test -f '../ctaocrypt/src/ripemd.c' || echo '$(srcdir)/'`../ctaocrypt/src/ripemd.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/ripemd.Tpo $(DEPDIR)/ripemd.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../ctaocrypt/src/ripemd.c' object='ripemd.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ripemd.lo `test -f '../ctaocrypt/src/ripemd.c' || echo '$(srcdir)/'`../ctaocrypt/src/ripemd.c
+
+sha512.lo: ../ctaocrypt/src/sha512.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sha512.lo -MD -MP -MF $(DEPDIR)/sha512.Tpo -c -o sha512.lo `test -f '../ctaocrypt/src/sha512.c' || echo '$(srcdir)/'`../ctaocrypt/src/sha512.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/sha512.Tpo $(DEPDIR)/sha512.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../ctaocrypt/src/sha512.c' object='sha512.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sha512.lo `test -f '../ctaocrypt/src/sha512.c' || echo '$(srcdir)/'`../ctaocrypt/src/sha512.c
+
+hc128.lo: ../ctaocrypt/src/hc128.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT hc128.lo -MD -MP -MF $(DEPDIR)/hc128.Tpo -c -o hc128.lo `test -f '../ctaocrypt/src/hc128.c' || echo '$(srcdir)/'`../ctaocrypt/src/hc128.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/hc128.Tpo $(DEPDIR)/hc128.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../ctaocrypt/src/hc128.c' object='hc128.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o hc128.lo `test -f '../ctaocrypt/src/hc128.c' || echo '$(srcdir)/'`../ctaocrypt/src/hc128.c
+
+tfm.lo: ../ctaocrypt/src/tfm.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tfm.lo -MD -MP -MF $(DEPDIR)/tfm.Tpo -c -o tfm.lo `test -f '../ctaocrypt/src/tfm.c' || echo '$(srcdir)/'`../ctaocrypt/src/tfm.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/tfm.Tpo $(DEPDIR)/tfm.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../ctaocrypt/src/tfm.c' object='tfm.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tfm.lo `test -f '../ctaocrypt/src/tfm.c' || echo '$(srcdir)/'`../ctaocrypt/src/tfm.c
+
+integer.lo: ../ctaocrypt/src/integer.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT integer.lo -MD -MP -MF $(DEPDIR)/integer.Tpo -c -o integer.lo `test -f '../ctaocrypt/src/integer.c' || echo '$(srcdir)/'`../ctaocrypt/src/integer.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/integer.Tpo $(DEPDIR)/integer.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../ctaocrypt/src/integer.c' object='integer.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o integer.lo `test -f '../ctaocrypt/src/integer.c' || echo '$(srcdir)/'`../ctaocrypt/src/integer.c
+
+ecc.lo: ../ctaocrypt/src/ecc.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ecc.lo -MD -MP -MF $(DEPDIR)/ecc.Tpo -c -o ecc.lo `test -f '../ctaocrypt/src/ecc.c' || echo '$(srcdir)/'`../ctaocrypt/src/ecc.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/ecc.Tpo $(DEPDIR)/ecc.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../ctaocrypt/src/ecc.c' object='ecc.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ecc.lo `test -f '../ctaocrypt/src/ecc.c' || echo '$(srcdir)/'`../ctaocrypt/src/ecc.c
+
+.s.o:
+ $(CCASCOMPILE) -c -o $@ $<
+
+.s.obj:
+ $(CCASCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.s.lo:
+ $(LTCCASCOMPILE) -c -o $@ $<
+
+aes_asm.lo: ../ctaocrypt/src/aes_asm.s
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CCAS) $(AM_CCASFLAGS) $(CCASFLAGS) -c -o aes_asm.lo `test -f '../ctaocrypt/src/aes_asm.s' || echo '$(srcdir)/'`../ctaocrypt/src/aes_asm.s
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(libdir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-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
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-exec-am: install-libLTLIBRARIES
+
+install-html: install-html-am
+
+install-info: install-info-am
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-ps: install-ps-am
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-libLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libLTLIBRARIES clean-libtool ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ 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-libLTLIBRARIES install-man 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-libLTLIBRARIES
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/release/src/router/cyassl/src/cyassl_int.c b/release/src/router/cyassl/src/cyassl_int.c
new file mode 100644
index 00000000..ffdc9ae7
--- /dev/null
+++ b/release/src/router/cyassl/src/cyassl_int.c
@@ -0,0 +1,5379 @@
+/* cyassl_int.c
+ *
+ * Copyright (C) 2006-2011 Sawtooth Consulting Ltd.
+ *
+ * This file is part of CyaSSL.
+ *
+ * CyaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * CyaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+
+#include "cyassl_int.h"
+#include "cyassl_error.h"
+#include "asn.h"
+
+#ifdef HAVE_LIBZ
+ #include "zlib.h"
+#endif
+
+#ifdef HAVE_NTRU
+ #include "crypto_ntru.h"
+#endif
+
+#if defined(DEBUG_CYASSL) || defined(SHOW_SECRETS)
+ #include <stdio.h>
+#endif
+
+#ifdef __sun
+ #include <sys/filio.h>
+#endif
+
+#define TRUE 1
+#define FALSE 0
+
+
+#if defined(OPENSSL_EXTRA) && defined(NO_DH)
+ #error OPENSSL_EXTRA needs DH, please remove NO_DH
+#endif
+
+
+int CyaSSL_negotiate(SSL*);
+
+
+#ifndef NO_CYASSL_CLIENT
+ static int DoHelloVerifyRequest(SSL* ssl, const byte* input, word32*);
+ static int DoServerHello(SSL* ssl, const byte* input, word32*);
+ static int DoCertificateRequest(SSL* ssl, const byte* input, word32*);
+ static int DoServerKeyExchange(SSL* ssl, const byte* input, word32*);
+#endif
+
+
+#ifndef NO_CYASSL_SERVER
+ static int DoClientHello(SSL* ssl, const byte* input, word32*, word32,
+ word32);
+ static int DoCertificateVerify(SSL* ssl, byte*, word32*, word32);
+ static int DoClientKeyExchange(SSL* ssl, byte* input, word32*);
+#endif
+
+typedef enum {
+ doProcessInit = 0,
+#ifndef NO_CYASSL_SERVER
+ runProcessOldClientHello,
+#endif
+ getRecordLayerHeader,
+ getData,
+ runProcessingOneMessage
+} processReply;
+
+static void Hmac(SSL* ssl, byte* digest, const byte* buffer, word32 sz,
+ int content, int verify);
+
+static void BuildCertHashes(SSL* ssl, Hashes* hashes);
+
+
+void BuildTlsFinished(SSL* ssl, Hashes* hashes, const byte* sender);
+
+
+#ifndef min
+
+ static INLINE word32 min(word32 a, word32 b)
+ {
+ return a > b ? b : a;
+ }
+
+#endif /* min */
+
+
+int IsTLS(const SSL* ssl)
+{
+ if (ssl->version.major == SSLv3_MAJOR && ssl->version.minor >=TLSv1_MINOR)
+ return 1;
+
+ return 0;
+}
+
+
+int IsAtLeastTLSv1_2(const SSL* ssl)
+{
+ if (ssl->version.major == SSLv3_MAJOR && ssl->version.minor >=TLSv1_2_MINOR)
+ return 1;
+
+ return 0;
+}
+
+
+#ifdef HAVE_NTRU
+
+static byte GetEntropy(ENTROPY_CMD cmd, byte* out)
+{
+ /* TODO: add locking? */
+ static RNG rng;
+
+ if (cmd == INIT) {
+ int ret = InitRng(&rng);
+ if (ret == 0)
+ return 1;
+ else
+ return 0;
+ }
+
+ if (out == NULL)
+ return 0;
+
+ if (cmd == GET_BYTE_OF_ENTROPY) {
+ RNG_GenerateBlock(&rng, out, 1);
+ return 1;
+ }
+
+ if (cmd == GET_NUM_BYTES_PER_BYTE_OF_ENTROPY) {
+ *out = 1;
+ return 1;
+ }
+
+ return 0;
+}
+
+#endif /* HAVE_NTRU */
+
+static INLINE void c32to24(word32 in, word24 out)
+{
+ out[0] = (in >> 16) & 0xff;
+ out[1] = (in >> 8) & 0xff;
+ out[2] = in & 0xff;
+}
+
+
+static INLINE void c32to48(word32 in, byte out[6])
+{
+ out[0] = 0;
+ out[1] = 0;
+ out[2] = (in >> 24) & 0xff;
+ out[3] = (in >> 16) & 0xff;
+ out[4] = (in >> 8) & 0xff;
+ out[5] = in & 0xff;
+}
+
+
+/* convert 16 bit integer to opaque */
+static void INLINE c16toa(word16 u16, byte* c)
+{
+ c[0] = (u16 >> 8) & 0xff;
+ c[1] = u16 & 0xff;
+}
+
+
+/* convert 32 bit integer to opaque */
+static INLINE void c32toa(word32 u32, byte* c)
+{
+ c[0] = (u32 >> 24) & 0xff;
+ c[1] = (u32 >> 16) & 0xff;
+ c[2] = (u32 >> 8) & 0xff;
+ c[3] = u32 & 0xff;
+}
+
+
+/* convert a 24 bit integer into a 32 bit one */
+static INLINE void c24to32(const word24 u24, word32* u32)
+{
+ *u32 = 0;
+ *u32 = (u24[0] << 16) | (u24[1] << 8) | u24[2];
+}
+
+
+/* convert opaque to 16 bit integer */
+static INLINE void ato16(const byte* c, word16* u16)
+{
+ *u16 = 0;
+ *u16 = (c[0] << 8) | (c[1]);
+}
+
+
+/* convert opaque to 32 bit integer */
+static INLINE void ato32(const byte* c, word32* u32)
+{
+ *u32 = 0;
+ *u32 = (c[0] << 24) | (c[1] << 16) | (c[2] << 8) | c[3];
+}
+
+
+#ifdef HAVE_LIBZ
+
+ /* alloc user allocs to work with zlib */
+ void* myAlloc(void* opaque, unsigned int item, unsigned int size)
+ {
+ return XMALLOC(item * size, opaque, DYNAMIC_TYPE_LIBZ);
+ }
+
+
+ void myFree(void* opaque, void* memory)
+ {
+ XFREE(memory, opaque, DYNAMIC_TYPE_LIBZ);
+ }
+
+
+ /* init zlib comp/decomp streams, 0 on success */
+ static int InitStreams(SSL* ssl)
+ {
+ ssl->c_stream.zalloc = (alloc_func)myAlloc;
+ ssl->c_stream.zfree = (free_func)myFree;
+ ssl->c_stream.opaque = (voidpf)ssl->heap;
+
+ if (deflateInit(&ssl->c_stream, 8) != Z_OK) return ZLIB_INIT_ERROR;
+
+ ssl->didStreamInit = 1;
+
+ ssl->d_stream.zalloc = (alloc_func)myAlloc;
+ ssl->d_stream.zfree = (free_func)myFree;
+ ssl->d_stream.opaque = (voidpf)ssl->heap;
+
+ if (inflateInit(&ssl->d_stream) != Z_OK) return ZLIB_INIT_ERROR;
+
+ return 0;
+ }
+
+
+ static void FreeStreams(SSL* ssl)
+ {
+ if (ssl->didStreamInit) {
+ deflateEnd(&ssl->c_stream);
+ inflateEnd(&ssl->d_stream);
+ }
+ }
+
+
+ /* compress in to out, return out size or error */
+ static int Compress(SSL* ssl, byte* in, int inSz, byte* out, int outSz)
+ {
+ int err;
+ int currTotal = ssl->c_stream.total_out;
+
+ /* put size in front of compression */
+ c16toa((word16)inSz, out);
+ out += 2;
+ outSz -= 2;
+
+ ssl->c_stream.next_in = in;
+ ssl->c_stream.avail_in = inSz;
+ ssl->c_stream.next_out = out;
+ ssl->c_stream.avail_out = outSz;
+
+ err = deflate(&ssl->c_stream, Z_SYNC_FLUSH);
+ if (err != Z_OK && err != Z_STREAM_END) return ZLIB_COMPRESS_ERROR;
+
+ return ssl->c_stream.total_out - currTotal + sizeof(word16);
+ }
+
+
+ /* decompress in to out, returnn out size or error */
+ static int DeCompress(SSL* ssl, byte* in, int inSz, byte* out, int outSz)
+ {
+ int err;
+ int currTotal = ssl->d_stream.total_out;
+ word16 len;
+
+ /* find size in front of compression */
+ ato16(in, &len);
+ in += 2;
+ inSz -= 2;
+
+ ssl->d_stream.next_in = in;
+ ssl->d_stream.avail_in = inSz;
+ ssl->d_stream.next_out = out;
+ ssl->d_stream.avail_out = outSz;
+
+ err = inflate(&ssl->d_stream, Z_SYNC_FLUSH);
+ if (err != Z_OK && err != Z_STREAM_END) return ZLIB_DECOMPRESS_ERROR;
+
+ return ssl->d_stream.total_out - currTotal;
+ }
+
+#endif /* HAVE_LIBZ */
+
+
+void InitSSL_Method(SSL_METHOD* method, ProtocolVersion pv)
+{
+ method->version = pv;
+ method->side = CLIENT_END;
+ method->verifyPeer = 0;
+ method->verifyNone = 0;
+ method->failNoCert = 0;
+ method->downgrade = 0;
+}
+
+
+void InitSSL_Ctx(SSL_CTX* ctx, SSL_METHOD* method)
+{
+ ctx->method = method;
+ ctx->certificate.buffer = 0;
+ ctx->privateKey.buffer = 0;
+ ctx->haveDH = 0;
+ ctx->haveNTRU = 0; /* start off */
+ ctx->haveECDSA = 0; /* start off */
+ ctx->heap = ctx; /* defaults to self */
+#ifndef NO_PSK
+ ctx->havePSK = 0;
+ ctx->server_hint[0] = 0;
+ ctx->client_psk_cb = 0;
+ ctx->server_psk_cb = 0;
+#endif /* NO_PSK */
+
+#ifdef OPENSSL_EXTRA
+ ctx->passwd_cb = 0;
+ ctx->userdata = 0;
+#endif /* OPENSSL_EXTRA */
+
+#ifndef CYASSL_USER_IO
+ ctx->CBIORecv = EmbedReceive;
+ ctx->CBIOSend = EmbedSend;
+#else
+ /* user will set */
+ ctx->CBIORecv = NULL;
+ ctx->CBIOSend = NULL;
+#endif
+ ctx->partialWrite = 0;
+ ctx->verifyCallback = 0;
+
+ ctx->caList = 0;
+#ifdef HAVE_NTRU
+ if (method->side == CLIENT_END)
+ ctx->haveNTRU = 1; /* always on cliet side */
+ /* server can turn on by loading key */
+#endif
+#ifdef HAVE_ECC
+ if (method->side == CLIENT_END)
+ ctx->haveECDSA = 1; /* always on cliet side */
+ /* server can turn on by loading key */
+#endif
+ /* remove DH later if server didn't set, add psk later */
+ InitSuites(&ctx->suites, method->version, TRUE, FALSE, ctx->haveNTRU,
+ ctx->haveECDSA, method->side);
+ ctx->verifyPeer = 0;
+ ctx->verifyNone = 0;
+ ctx->failNoCert = 0;
+ ctx->sessionCacheOff = 0; /* initially on */
+ ctx->sessionCacheFlushOff = 0; /* initially on */
+ ctx->sendVerify = 0;
+ ctx->quietShutdown = 0;
+
+}
+
+
+/* In case contexts are held in array and don't want to free actual ctx */
+void SSL_CtxResourceFree(SSL_CTX* ctx)
+{
+ XFREE(ctx->privateKey.buffer, ctx->heap, DYNAMIC_TYPE_KEY);
+ XFREE(ctx->certificate.buffer, ctx->heap, DYNAMIC_TYPE_CERT);
+ XFREE(ctx->method, ctx->heap, DYNAMIC_TYPE_METHOD);
+
+ FreeSigners(ctx->caList, ctx->heap);
+}
+
+
+void FreeSSL_Ctx(SSL_CTX* ctx)
+{
+ SSL_CtxResourceFree(ctx);
+ XFREE(ctx, ctx->heap, DYNAMIC_TYPE_CTX);
+}
+
+
+
+void InitSuites(Suites* suites, ProtocolVersion pv, byte haveDH, byte havePSK,
+ byte haveNTRU, byte haveECDSA, int side)
+{
+ word32 idx = 0;
+ int tls = pv.major == 3 && pv.minor >= 1;
+ int haveRSA = 1;
+
+ (void)tls; /* shut up compiler */
+
+ if (side == SERVER_END && haveECDSA)
+ haveRSA = 0; /* can't do RSA with ECDSA cert */
+
+#ifdef CYASSL_DTLS
+ if (pv.major == DTLS_MAJOR && pv.minor == DTLS_MINOR)
+ tls = 1;
+#endif
+
+ suites->setSuites = 0; /* user hasn't set yet */
+
+#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_256_CBC_SHA
+ if (tls && haveNTRU && haveRSA) {
+ suites->suites[idx++] = 0;
+ suites->suites[idx++] = TLS_NTRU_RSA_WITH_AES_256_CBC_SHA;
+ }
+#endif
+
+#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_128_CBC_SHA
+ if (tls && haveNTRU && haveRSA) {
+ suites->suites[idx++] = 0;
+ suites->suites[idx++] = TLS_NTRU_RSA_WITH_AES_128_CBC_SHA;
+ }
+#endif
+
+#ifdef BUILD_TLS_NTRU_RSA_WITH_RC4_128_SHA
+ if (tls && haveNTRU && haveRSA) {
+ suites->suites[idx++] = 0;
+ suites->suites[idx++] = TLS_NTRU_RSA_WITH_RC4_128_SHA;
+ }
+#endif
+
+#ifdef BUILD_TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA
+ if (tls && haveNTRU && haveRSA) {
+ suites->suites[idx++] = 0;
+ suites->suites[idx++] = TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA;
+ }
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
+ if (tls && haveECDSA) {
+ suites->suites[idx++] = ECC_BYTE;
+ suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA;
+ }
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
+ if (tls && haveECDSA) {
+ suites->suites[idx++] = ECC_BYTE;
+ suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA;
+ }
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
+ if (tls && haveECDSA) {
+ suites->suites[idx++] = ECC_BYTE;
+ suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_RC4_128_SHA;
+ }
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
+ if (tls && haveECDSA) {
+ suites->suites[idx++] = ECC_BYTE;
+ suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA;
+ }
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
+ if (tls && haveRSA) {
+ suites->suites[idx++] = ECC_BYTE;
+ suites->suites[idx++] = TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA;
+ }
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
+ if (tls && haveRSA) {
+ suites->suites[idx++] = ECC_BYTE;
+ suites->suites[idx++] = TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA;
+ }
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_RC4_128_SHA
+ if (tls && haveRSA) {
+ suites->suites[idx++] = ECC_BYTE;
+ suites->suites[idx++] = TLS_ECDHE_RSA_WITH_RC4_128_SHA;
+ }
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
+ if (tls && haveRSA) {
+ suites->suites[idx++] = ECC_BYTE;
+ suites->suites[idx++] = TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA;
+ }
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA
+ if (tls && haveDH && haveRSA) {
+ suites->suites[idx++] = 0;
+ suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_256_CBC_SHA;
+ }
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA
+ if (tls && haveDH && haveRSA) {
+ suites->suites[idx++] = 0;
+ suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_128_CBC_SHA;
+ }
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA
+ if (tls && haveRSA) {
+ suites->suites[idx++] = 0;
+ suites->suites[idx++] = TLS_RSA_WITH_AES_256_CBC_SHA;
+ }
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA
+ if (tls && haveRSA) {
+ suites->suites[idx++] = 0;
+ suites->suites[idx++] = TLS_RSA_WITH_AES_128_CBC_SHA;
+ }
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA
+ if (tls && havePSK) {
+ suites->suites[idx++] = 0;
+ suites->suites[idx++] = TLS_PSK_WITH_AES_256_CBC_SHA;
+ }
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA
+ if (tls && havePSK) {
+ suites->suites[idx++] = 0;
+ suites->suites[idx++] = TLS_PSK_WITH_AES_128_CBC_SHA;
+ }
+#endif
+
+#ifdef BUILD_SSL_RSA_WITH_RC4_128_SHA
+ if (haveRSA ) {
+ suites->suites[idx++] = 0;
+ suites->suites[idx++] = SSL_RSA_WITH_RC4_128_SHA;
+ }
+#endif
+
+#ifdef BUILD_SSL_RSA_WITH_RC4_128_MD5
+ if (haveRSA ) {
+ suites->suites[idx++] = 0;
+ suites->suites[idx++] = SSL_RSA_WITH_RC4_128_MD5;
+ }
+#endif
+
+#ifdef BUILD_SSL_RSA_WITH_3DES_EDE_CBC_SHA
+ if (haveRSA ) {
+ suites->suites[idx++] = 0;
+ suites->suites[idx++] = SSL_RSA_WITH_3DES_EDE_CBC_SHA;
+ }
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_HC_128_CBC_MD5
+ if (tls && haveRSA) {
+ suites->suites[idx++] = 0;
+ suites->suites[idx++] = TLS_RSA_WITH_HC_128_CBC_MD5;
+ }
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_HC_128_CBC_SHA
+ if (tls && haveRSA) {
+ suites->suites[idx++] = 0;
+ suites->suites[idx++] = TLS_RSA_WITH_HC_128_CBC_SHA;
+ }
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_RABBIT_CBC_SHA
+ if (tls && haveRSA) {
+ suites->suites[idx++] = 0;
+ suites->suites[idx++] = TLS_RSA_WITH_RABBIT_CBC_SHA;
+ }
+#endif
+
+ suites->suiteSz = idx;
+}
+
+
+int InitSSL(SSL* ssl, SSL_CTX* ctx)
+{
+ int ret;
+ byte havePSK = 0;
+
+ ssl->ctx = ctx; /* only for passing to calls, options could change */
+ ssl->version = ctx->method->version;
+ ssl->suites = ctx->suites;
+
+#ifdef HAVE_LIBZ
+ ssl->didStreamInit = 0;
+#endif
+
+ ssl->buffers.certificate.buffer = 0;
+ ssl->buffers.key.buffer = 0;
+ ssl->buffers.inputBuffer.length = 0;
+ ssl->buffers.inputBuffer.idx = 0;
+ ssl->buffers.inputBuffer.buffer = ssl->buffers.inputBuffer.staticBuffer;
+ ssl->buffers.inputBuffer.bufferSize = STATIC_BUFFER_LEN;
+ ssl->buffers.inputBuffer.dynamicFlag = 0;
+ ssl->buffers.outputBuffer.length = 0;
+ ssl->buffers.outputBuffer.idx = 0;
+ ssl->buffers.outputBuffer.buffer = ssl->buffers.outputBuffer.staticBuffer;
+ ssl->buffers.outputBuffer.bufferSize = STATIC_BUFFER_LEN;
+ ssl->buffers.outputBuffer.dynamicFlag = 0;
+ ssl->buffers.domainName.buffer = 0;
+ ssl->buffers.serverDH_P.buffer = 0;
+ ssl->buffers.serverDH_G.buffer = 0;
+ ssl->buffers.serverDH_Pub.buffer = 0;
+ ssl->buffers.serverDH_Priv.buffer = 0;
+ ssl->buffers.clearOutputBuffer.buffer = 0;
+ ssl->buffers.clearOutputBuffer.length = 0;
+ ssl->buffers.prevSent = 0;
+ ssl->buffers.plainSz = 0;
+
+ if ( (ret = InitRng(&ssl->rng)) )
+ return ret;
+
+ InitMd5(&ssl->hashMd5);
+ InitSha(&ssl->hashSha);
+#ifndef NO_SHA256
+ InitSha256(&ssl->hashSha256);
+#endif
+ InitRsaKey(&ssl->peerRsaKey, ctx->heap);
+
+ ssl->peerRsaKeyPresent = 0;
+ ssl->options.side = ctx->method->side;
+ ssl->options.downgrade = ctx->method->downgrade;
+ ssl->error = 0;
+ ssl->options.connReset = 0;
+ ssl->options.isClosed = 0;
+ ssl->options.closeNotify = 0;
+ ssl->options.sentNotify = 0;
+ ssl->options.usingCompression = 0;
+ ssl->options.haveDH = ctx->haveDH;
+ ssl->options.haveNTRU = ctx->haveNTRU;
+ ssl->options.haveECDSA = ctx->haveECDSA;
+ ssl->options.havePeerCert = 0;
+ ssl->options.usingPSK_cipher = 0;
+ ssl->options.sendAlertState = 0;
+#ifndef NO_PSK
+ havePSK = ctx->havePSK;
+ ssl->options.havePSK = ctx->havePSK;
+ ssl->options.client_psk_cb = ctx->client_psk_cb;
+ ssl->options.server_psk_cb = ctx->server_psk_cb;
+#endif /* NO_PSK */
+
+ ssl->options.serverState = NULL_STATE;
+ ssl->options.clientState = NULL_STATE;
+ ssl->options.connectState = CONNECT_BEGIN;
+ ssl->options.acceptState = ACCEPT_BEGIN;
+ ssl->options.handShakeState = NULL_STATE;
+ ssl->options.processReply = doProcessInit;
+
+#ifdef CYASSL_DTLS
+ ssl->keys.dtls_sequence_number = 0;
+ ssl->keys.dtls_peer_sequence_number = 0;
+ ssl->keys.dtls_handshake_number = 0;
+ ssl->keys.dtls_epoch = 0;
+ ssl->keys.dtls_peer_epoch = 0;
+#endif
+ ssl->keys.encryptionOn = 0; /* initially off */
+ ssl->options.sessionCacheOff = ctx->sessionCacheOff;
+ ssl->options.sessionCacheFlushOff = ctx->sessionCacheFlushOff;
+
+ ssl->options.verifyPeer = ctx->verifyPeer;
+ ssl->options.verifyNone = ctx->verifyNone;
+ ssl->options.failNoCert = ctx->failNoCert;
+ ssl->options.sendVerify = ctx->sendVerify;
+
+ ssl->options.resuming = 0;
+ ssl->hmac = Hmac; /* default to SSLv3 */
+ ssl->heap = ctx->heap; /* defaults to self */
+ ssl->options.tls = 0;
+ ssl->options.tls1_1 = 0;
+ ssl->options.dtls = 0;
+ ssl->options.partialWrite = ctx->partialWrite;
+ ssl->options.quietShutdown = ctx->quietShutdown;
+
+ /* SSL_CTX still owns certificate, key, and caList buffers */
+ ssl->buffers.certificate = ctx->certificate;
+ ssl->buffers.key = ctx->privateKey;
+ ssl->caList = ctx->caList;
+
+#ifdef OPENSSL_EXTRA
+ ssl->peerCert.issuer.sz = 0;
+ ssl->peerCert.subject.sz = 0;
+#endif
+
+ /* make sure server has cert and key unless using PSK */
+ if (ssl->options.side == SERVER_END && !havePSK)
+ if (!ssl->buffers.certificate.buffer || !ssl->buffers.key.buffer)
+ return NO_PRIVATE_KEY;
+
+#ifndef NO_PSK
+ ssl->arrays.client_identity[0] = 0;
+ if (ctx->server_hint[0]) /* set in CTX */
+ XSTRNCPY(ssl->arrays.server_hint, ctx->server_hint, MAX_PSK_ID_LEN);
+ else
+ ssl->arrays.server_hint[0] = 0;
+#endif /* NO_PSK */
+
+#ifdef CYASSL_CALLBACKS
+ ssl->hsInfoOn = 0;
+ ssl->toInfoOn = 0;
+#endif
+
+#ifdef HAVE_ECC
+ ssl->peerEccKeyPresent = 0;
+ ecc_init(&ssl->peerEccKey);
+ ssl->peerEccDsaKeyPresent = 0;
+ ecc_init(&ssl->peerEccDsaKey);
+ ssl->eccDsaKeyPresent = 0;
+ ecc_init(&ssl->eccDsaKey);
+ ssl->eccTempKeyPresent = 0;
+ ecc_init(&ssl->eccTempKey);
+
+ /* make ECDHE for server side */
+ if (ssl->options.side == SERVER_END) {
+ if (ecc_make_key(&ssl->rng, ECDHE_SIZE, &ssl->eccTempKey) != 0)
+ return ECC_MAKEKEY_ERROR;
+ ssl->eccTempKeyPresent = 1;
+ }
+#endif
+
+ /* make sure server has DH parms, and add PSK if there, add NTRU too */
+ if (!ssl->ctx->suites.setSuites) { /* trust user override */
+ if (ssl->options.side == SERVER_END)
+ InitSuites(&ssl->suites, ssl->version,ssl->options.haveDH, havePSK,
+ ssl->options.haveNTRU, ssl->options.haveECDSA,
+ ssl->ctx->method->side);
+ else
+ InitSuites(&ssl->suites, ssl->version, TRUE, havePSK,
+ ssl->options.haveNTRU, ssl->options.haveECDSA,
+ ssl->ctx->method->side);
+ }
+
+ ssl->rfd = -1; /* set to invalid descriptor */
+ ssl->wfd = -1;
+ ssl->biord = 0;
+ ssl->biowr = 0;
+
+ ssl->IOCB_ReadCtx = &ssl->rfd; /* prevent invalid pointer acess if not */
+ ssl->IOCB_WriteCtx = &ssl->wfd; /* correctly set */
+
+#ifdef SESSION_CERTS
+ ssl->session.chain.count = 0;
+#endif
+
+ ssl->cipher.ssl = ssl;
+
+ return 0;
+}
+
+
+int BIO_free(BIO*); /* cyassl_int doesn't have */
+
+
+/* In case holding SSL object in array and don't want to free actual ssl */
+void SSL_ResourceFree(SSL* ssl)
+{
+ XFREE(ssl->buffers.serverDH_Priv.buffer, ssl->heap, DYNAMIC_TYPE_DH);
+ XFREE(ssl->buffers.serverDH_Pub.buffer, ssl->heap, DYNAMIC_TYPE_DH);
+ XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap, DYNAMIC_TYPE_DH);
+ XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, DYNAMIC_TYPE_DH);
+ XFREE(ssl->buffers.domainName.buffer, ssl->heap, DYNAMIC_TYPE_DOMAIN);
+ FreeRsaKey(&ssl->peerRsaKey);
+ if (ssl->buffers.inputBuffer.dynamicFlag)
+ ShrinkInputBuffer(ssl, FORCED_FREE);
+ if (ssl->buffers.outputBuffer.dynamicFlag)
+ ShrinkOutputBuffer(ssl);
+#if defined(OPENSSL_EXTRA) || defined(GOAHEAD_WS)
+ BIO_free(ssl->biord);
+ if (ssl->biord != ssl->biowr) /* in case same as write */
+ BIO_free(ssl->biowr);
+#endif
+#ifdef HAVE_LIBZ
+ FreeStreams(ssl);
+#endif
+#ifdef HAVE_ECC
+ ecc_free(&ssl->peerEccKey);
+ ecc_free(&ssl->peerEccDsaKey);
+ ecc_free(&ssl->eccTempKey);
+ ecc_free(&ssl->eccDsaKey);
+#endif
+}
+
+
+void FreeSSL(SSL* ssl)
+{
+ SSL_ResourceFree(ssl);
+ XFREE(ssl, ssl->heap, DYNAMIC_TYPE_SSL);
+}
+
+
+ProtocolVersion MakeSSLv3(void)
+{
+ ProtocolVersion pv;
+ pv.major = SSLv3_MAJOR;
+ pv.minor = SSLv3_MINOR;
+
+ return pv;
+}
+
+
+#ifdef CYASSL_DTLS
+
+ProtocolVersion MakeDTLSv1(void)
+{
+ ProtocolVersion pv;
+ pv.major = DTLS_MAJOR;
+ pv.minor = DTLS_MINOR;
+
+ return pv;
+}
+
+#endif /* CYASSL_DTLS */
+
+
+
+
+#ifdef USE_WINDOWS_API
+
+ timer_d Timer(void)
+ {
+ static int init = 0;
+ static LARGE_INTEGER freq;
+ LARGE_INTEGER count;
+
+ if (!init) {
+ QueryPerformanceFrequency(&freq);
+ init = 1;
+ }
+
+ QueryPerformanceCounter(&count);
+
+ return (double)count.QuadPart / freq.QuadPart;
+ }
+
+
+ word32 LowResTimer(void)
+ {
+ return (word32)Timer();
+ }
+
+
+#elif defined(THREADX)
+
+ #include "rtptime.h"
+
+ word32 LowResTimer(void)
+ {
+ return (word32)rtp_get_system_sec();
+ }
+
+
+#elif defined(MICRIUM)
+
+ word32 LowResTimer(void)
+ {
+ NET_SECURE_OS_TICK clk;
+
+ #if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED)
+ clk = NetSecure_OS_TimeGet();
+ #endif
+ return (word32)clk;
+ }
+
+#elif defined(USER_TICKS)
+
+ word32 LowResTimer(void)
+ {
+ /*
+ write your own clock tick function if don't want time(0)
+ needs second accuracy but doesn't have to correlated to EPOCH
+ */
+ }
+
+#else /* !USE_WINDOWS_API && !THREADX && !MICRIUM && !USER_TICKS */
+
+ #include <time.h>
+
+ word32 LowResTimer(void)
+ {
+ return time(0);
+ }
+
+
+#endif /* USE_WINDOWS_API */
+
+
+/* add output to md5 and sha handshake hashes, exclude record header */
+static void HashOutput(SSL* ssl, const byte* output, int sz, int ivSz)
+{
+ const byte* buffer = output + RECORD_HEADER_SZ + ivSz;
+ sz -= RECORD_HEADER_SZ;
+
+#ifdef CYASSL_DTLS
+ if (ssl->options.dtls) {
+ buffer += DTLS_RECORD_EXTRA;
+ sz -= DTLS_RECORD_EXTRA;
+ }
+#endif
+
+ Md5Update(&ssl->hashMd5, buffer, sz);
+ ShaUpdate(&ssl->hashSha, buffer, sz);
+#ifndef NO_SHA256
+ if (IsAtLeastTLSv1_2(ssl))
+ Sha256Update(&ssl->hashSha256, buffer, sz);
+#endif
+}
+
+
+/* add input to md5 and sha handshake hashes, include handshake header */
+static void HashInput(SSL* ssl, const byte* input, int sz)
+{
+ const byte* buffer = input - HANDSHAKE_HEADER_SZ;
+ sz += HANDSHAKE_HEADER_SZ;
+
+#ifdef CYASSL_DTLS
+ if (ssl->options.dtls) {
+ buffer -= DTLS_HANDSHAKE_EXTRA;
+ sz += DTLS_HANDSHAKE_EXTRA;
+ }
+#endif
+
+ Md5Update(&ssl->hashMd5, buffer, sz);
+ ShaUpdate(&ssl->hashSha, buffer, sz);
+#ifndef NO_SHA256
+ if (IsAtLeastTLSv1_2(ssl))
+ Sha256Update(&ssl->hashSha256, buffer, sz);
+#endif
+}
+
+
+/* add record layer header for message */
+static void AddRecordHeader(byte* output, word32 length, byte type, SSL* ssl)
+{
+ RecordLayerHeader* rl;
+
+ /* record layer header */
+ rl = (RecordLayerHeader*)output;
+ rl->type = type;
+ rl->version = ssl->version; /* type and version same in each */
+
+ if (!ssl->options.dtls)
+ c16toa((word16)length, rl->length);
+ else {
+#ifdef CYASSL_DTLS
+ DtlsRecordLayerHeader* dtls;
+
+ /* dtls record layer header extensions */
+ dtls = (DtlsRecordLayerHeader*)output;
+ c16toa(ssl->keys.dtls_epoch, dtls->epoch);
+ c32to48(ssl->keys.dtls_sequence_number++, dtls->sequence_number);
+ c16toa((word16)length, dtls->length);
+#endif
+ }
+}
+
+
+/* add handshake header for message */
+static void AddHandShakeHeader(byte* output, word32 length, byte type, SSL* ssl)
+{
+ HandShakeHeader* hs;
+
+ /* handshake header */
+ hs = (HandShakeHeader*)output;
+ hs->type = type;
+ c32to24(length, hs->length); /* type and length same for each */
+#ifdef CYASSL_DTLS
+ if (ssl->options.dtls) {
+ DtlsHandShakeHeader* dtls;
+
+ /* dtls handshake header extensions */
+ dtls = (DtlsHandShakeHeader*)output;
+ c16toa(ssl->keys.dtls_handshake_number++, dtls->message_seq);
+ c32to24(0, dtls->fragment_offset);
+ c32to24(length, dtls->fragment_length);
+ }
+#endif
+}
+
+
+/* add both headers for handshake message */
+static void AddHeaders(byte* output, word32 length, byte type, SSL* ssl)
+{
+ if (!ssl->options.dtls) {
+ AddRecordHeader(output, length + HANDSHAKE_HEADER_SZ, handshake, ssl);
+ AddHandShakeHeader(output + RECORD_HEADER_SZ, length, type, ssl);
+ }
+ else {
+ AddRecordHeader(output, length+DTLS_HANDSHAKE_HEADER_SZ, handshake,ssl);
+ AddHandShakeHeader(output + DTLS_RECORD_HEADER_SZ, length, type, ssl);
+ }
+}
+
+
+static int Receive(SSL* ssl, byte* buf, word32 sz, int flags)
+{
+ int recvd;
+
+retry:
+ recvd = ssl->ctx->CBIORecv((char *)buf, (int)sz, ssl->IOCB_ReadCtx);
+ if (recvd < 0)
+ switch (recvd) {
+ case IO_ERR_GENERAL: /* general/unknown error */
+ return -1;
+
+ case IO_ERR_WANT_READ: /* want read, would block */
+ return WANT_READ;
+
+ case IO_ERR_CONN_RST: /* connection reset */
+ ssl->options.connReset = 1;
+ return -1;
+
+ case IO_ERR_ISR: /* interrupt */
+ /* see if we got our timeout */
+ #ifdef CYASSL_CALLBACKS
+ if (ssl->toInfoOn) {
+ struct itimerval timeout;
+ getitimer(ITIMER_REAL, &timeout);
+ if (timeout.it_value.tv_sec == 0 &&
+ timeout.it_value.tv_usec == 0) {
+ XSTRNCPY(ssl->timeoutInfo.timeoutName,
+ "recv() timeout", MAX_TIMEOUT_NAME_SZ);
+ return 0;
+ }
+ }
+ #endif
+ goto retry;
+
+ case IO_ERR_CONN_CLOSE: /* peer closed connection */
+ ssl->options.isClosed = 1;
+ return -1;
+ }
+
+ return recvd;
+}
+
+
+/* Switch dynamic output buffer back to static, buffer is assumed clear */
+void ShrinkOutputBuffer(SSL* ssl)
+{
+ CYASSL_MSG("Shrinking output buffer\n");
+ XFREE(ssl->buffers.outputBuffer.buffer, ssl->heap, DYNAMIC_TYPE_OUT_BUFFER);
+ ssl->buffers.outputBuffer.buffer = ssl->buffers.outputBuffer.staticBuffer;
+ ssl->buffers.outputBuffer.bufferSize = STATIC_BUFFER_LEN;
+ ssl->buffers.outputBuffer.dynamicFlag = 0;
+}
+
+
+/* Switch dynamic input buffer back to static, keep any remaining input */
+/* forced free means cleaning up */
+void ShrinkInputBuffer(SSL* ssl, int forcedFree)
+{
+ int usedLength = ssl->buffers.inputBuffer.length -
+ ssl->buffers.inputBuffer.idx;
+ if (!forcedFree && usedLength > STATIC_BUFFER_LEN)
+ return;
+
+ CYASSL_MSG("Shrinking input buffer\n");
+
+ if (!forcedFree && usedLength)
+ XMEMCPY(ssl->buffers.inputBuffer.staticBuffer,
+ ssl->buffers.inputBuffer.buffer + ssl->buffers.inputBuffer.idx,
+ usedLength);
+
+ XFREE(ssl->buffers.inputBuffer.buffer, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
+ ssl->buffers.inputBuffer.buffer = ssl->buffers.inputBuffer.staticBuffer;
+ ssl->buffers.inputBuffer.bufferSize = STATIC_BUFFER_LEN;
+ ssl->buffers.inputBuffer.dynamicFlag = 0;
+ ssl->buffers.inputBuffer.idx = 0;
+ ssl->buffers.inputBuffer.length = usedLength;
+}
+
+
+int SendBuffered(SSL* ssl)
+{
+ while (ssl->buffers.outputBuffer.length > 0) {
+ int sent = ssl->ctx->CBIOSend((char*)ssl->buffers.outputBuffer.buffer +
+ ssl->buffers.outputBuffer.idx,
+ (int)ssl->buffers.outputBuffer.length,
+ ssl->IOCB_WriteCtx);
+ if (sent < 0) {
+ switch (sent) {
+
+ case IO_ERR_WANT_WRITE: /* would block */
+ return WANT_WRITE;
+
+ case IO_ERR_CONN_RST: /* connection reset */
+ ssl->options.connReset = 1;
+ break;
+
+ case IO_ERR_ISR: /* interrupt */
+ /* see if we got our timeout */
+ #ifdef CYASSL_CALLBACKS
+ if (ssl->toInfoOn) {
+ struct itimerval timeout;
+ getitimer(ITIMER_REAL, &timeout);
+ if (timeout.it_value.tv_sec == 0 &&
+ timeout.it_value.tv_usec == 0) {
+ XSTRNCPY(ssl->timeoutInfo.timeoutName,
+ "send() timeout", MAX_TIMEOUT_NAME_SZ);
+ return WANT_WRITE;
+ }
+ }
+ #endif
+ continue;
+
+ case IO_ERR_CONN_CLOSE: /* epipe / conn closed, same as reset */
+ ssl->options.connReset = 1;
+ break;
+ }
+
+ return SOCKET_ERROR_E;
+ }
+
+ ssl->buffers.outputBuffer.idx += sent;
+ ssl->buffers.outputBuffer.length -= sent;
+ }
+
+ ssl->buffers.outputBuffer.idx = 0;
+
+ if (ssl->buffers.outputBuffer.dynamicFlag)
+ ShrinkOutputBuffer(ssl);
+
+ return 0;
+}
+
+
+/* Grow the output buffer, should only be to send cert, should be blank */
+static INLINE int GrowOutputBuffer(SSL* ssl, int size)
+{
+ byte* tmp = (byte*) XMALLOC(size + ssl->buffers.outputBuffer.length,
+ ssl->heap, DYNAMIC_TYPE_OUT_BUFFER);
+ CYASSL_MSG("growing output buffer\n");
+
+ if (!tmp) return -1;
+
+ if (ssl->buffers.outputBuffer.length)
+ XMEMCPY(tmp, ssl->buffers.outputBuffer.buffer,
+ ssl->buffers.outputBuffer.length);
+
+ if (ssl->buffers.outputBuffer.dynamicFlag)
+ XFREE(ssl->buffers.outputBuffer.buffer, ssl->heap,
+ DYNAMIC_TYPE_OUT_BUFFER);
+ ssl->buffers.outputBuffer.dynamicFlag = 1;
+ ssl->buffers.outputBuffer.buffer = tmp;
+ ssl->buffers.outputBuffer.bufferSize = size +
+ ssl->buffers.outputBuffer.length;
+ return 0;
+}
+
+
+/* Grow the input buffer, should only be to read cert or big app data */
+static INLINE int GrowInputBuffer(SSL* ssl, int size, int usedLength)
+{
+ byte* tmp = (byte*) XMALLOC(size + usedLength, ssl->heap,
+ DYNAMIC_TYPE_IN_BUFFER);
+ CYASSL_MSG("growing input buffer\n");
+
+ if (!tmp) return -1;
+
+ if (usedLength)
+ XMEMCPY(tmp, ssl->buffers.inputBuffer.buffer +
+ ssl->buffers.inputBuffer.idx, usedLength);
+
+ if (ssl->buffers.inputBuffer.dynamicFlag)
+ XFREE(ssl->buffers.inputBuffer.buffer,ssl->heap,DYNAMIC_TYPE_IN_BUFFER);
+
+ ssl->buffers.inputBuffer.dynamicFlag = 1;
+ ssl->buffers.inputBuffer.buffer = tmp;
+ ssl->buffers.inputBuffer.bufferSize = size + usedLength;
+ ssl->buffers.inputBuffer.idx = 0;
+ ssl->buffers.inputBuffer.length = usedLength;
+
+ return 0;
+}
+
+
+/* check avalaible size into outbut buffer */
+static INLINE int CheckAvalaibleSize(SSL *ssl, int size)
+{
+ if ((word32)size > ssl->buffers.outputBuffer.bufferSize)
+ if (GrowOutputBuffer(ssl, size) < 0)
+ return MEMORY_E;
+
+ if (ssl->buffers.outputBuffer.bufferSize - ssl->buffers.outputBuffer.length
+ < (word32)size) {
+ if (SendBuffered(ssl) == SOCKET_ERROR_E)
+ return SOCKET_ERROR_E;
+ if (ssl->buffers.outputBuffer.bufferSize -
+ ssl->buffers.outputBuffer.length < (word32)size)
+ return WANT_WRITE;
+ }
+ return 0;
+}
+
+/* do all verify and sanity checks on record header */
+static int GetRecordHeader(SSL* ssl, const byte* input, word32* inOutIdx,
+ RecordLayerHeader* rh, word16 *size)
+{
+ if (!ssl->options.dtls) {
+ XMEMCPY(rh, input + *inOutIdx, RECORD_HEADER_SZ);
+ *inOutIdx += RECORD_HEADER_SZ;
+ ato16(rh->length, size);
+ }
+ else {
+#ifdef CYASSL_DTLS
+ /* type and version in same sport */
+ XMEMCPY(rh, input + *inOutIdx, ENUM_LEN + VERSION_SZ);
+ *inOutIdx += ENUM_LEN + VERSION_SZ;
+ *inOutIdx += 4; /* skip epoch and first 2 seq bytes for now */
+ ato32(input + *inOutIdx, &ssl->keys.dtls_peer_sequence_number);
+ *inOutIdx += 4; /* advance past rest of seq */
+ ato16(input + *inOutIdx, size);
+ *inOutIdx += LENGTH_SZ;
+#endif
+ }
+
+ /* catch version mismatch */
+ if (rh->version.major != ssl->version.major ||
+ rh->version.minor != ssl->version.minor) {
+
+ if (ssl->options.side == SERVER_END && ssl->options.downgrade == 1 &&
+ ssl->options.acceptState == ACCEPT_BEGIN)
+ ; /* haven't negotiated yet */
+ else
+ return VERSION_ERROR; /* only use requested version */
+ }
+
+ /* record layer length check */
+ if (*size > (MAX_RECORD_SIZE + MAX_COMP_EXTRA + MAX_MSG_EXTRA))
+ return LENGTH_ERROR;
+
+ /* verify record type here as well */
+ switch ((enum ContentType)rh->type) {
+ case handshake:
+ case change_cipher_spec:
+ case application_data:
+ case alert:
+ break;
+ default:
+ return UNKNOWN_RECORD_TYPE;
+ }
+
+ return 0;
+}
+
+
+static int GetHandShakeHeader(SSL* ssl, const byte* input, word32* inOutIdx,
+ byte *type, word32 *size)
+{
+ const byte *ptr = input + *inOutIdx;
+ *inOutIdx += HANDSHAKE_HEADER_SZ;
+
+#ifdef CYASSL_DTLS
+ if (ssl->options.dtls)
+ *inOutIdx += DTLS_HANDSHAKE_EXTRA;
+#endif
+
+ *type = ptr[0];
+ c24to32(&ptr[1], size);
+
+ return 0;
+}
+
+
+/* fill with MD5 pad size since biggest required */
+static const byte PAD1[PAD_MD5] =
+ { 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36
+ };
+static const byte PAD2[PAD_MD5] =
+ { 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+ 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+ 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+ 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+ 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+ 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c
+ };
+
+/* calculate MD5 hash for finished */
+static void BuildMD5(SSL* ssl, Hashes* hashes, const byte* sender)
+{
+ byte md5_result[MD5_DIGEST_SIZE];
+
+ /* make md5 inner */
+ Md5Update(&ssl->hashMd5, sender, SIZEOF_SENDER);
+ Md5Update(&ssl->hashMd5, ssl->arrays.masterSecret, SECRET_LEN);
+ Md5Update(&ssl->hashMd5, PAD1, PAD_MD5);
+ Md5Final(&ssl->hashMd5, md5_result);
+
+ /* make md5 outer */
+ Md5Update(&ssl->hashMd5, ssl->arrays.masterSecret, SECRET_LEN);
+ Md5Update(&ssl->hashMd5, PAD2, PAD_MD5);
+ Md5Update(&ssl->hashMd5, md5_result, MD5_DIGEST_SIZE);
+
+ Md5Final(&ssl->hashMd5, hashes->md5);
+}
+
+
+/* calculate SHA hash for finished */
+static void BuildSHA(SSL* ssl, Hashes* hashes, const byte* sender)
+{
+ byte sha_result[SHA_DIGEST_SIZE];
+
+ /* make sha inner */
+ ShaUpdate(&ssl->hashSha, sender, SIZEOF_SENDER);
+ ShaUpdate(&ssl->hashSha, ssl->arrays.masterSecret, SECRET_LEN);
+ ShaUpdate(&ssl->hashSha, PAD1, PAD_SHA);
+ ShaFinal(&ssl->hashSha, sha_result);
+
+ /* make sha outer */
+ ShaUpdate(&ssl->hashSha, ssl->arrays.masterSecret, SECRET_LEN);
+ ShaUpdate(&ssl->hashSha, PAD2, PAD_SHA);
+ ShaUpdate(&ssl->hashSha, sha_result, SHA_DIGEST_SIZE);
+
+ ShaFinal(&ssl->hashSha, hashes->sha);
+}
+
+
+static void BuildFinished(SSL* ssl, Hashes* hashes, const byte* sender)
+{
+ /* store current states, building requires get_digest which resets state */
+ Md5 md5 = ssl->hashMd5;
+ Sha sha = ssl->hashSha;
+#ifndef NO_SHA256
+ Sha256 sha256;
+ if (IsAtLeastTLSv1_2(ssl))
+ sha256 = ssl->hashSha256;
+#endif
+
+ if (ssl->options.tls)
+ BuildTlsFinished(ssl, hashes, sender);
+ else {
+ BuildMD5(ssl, hashes, sender);
+ BuildSHA(ssl, hashes, sender);
+ }
+
+ /* restore */
+ ssl->hashMd5 = md5;
+ ssl->hashSha = sha;
+#ifndef NO_SHA256
+ if (IsAtLeastTLSv1_2(ssl))
+ ssl->hashSha256 = sha256;
+#endif
+}
+
+
+static int DoCertificate(SSL* ssl, byte* input, word32* inOutIdx)
+{
+ word32 listSz, i = *inOutIdx;
+ int ret = 0;
+ int anyError = 0;
+ int firstTime = 1; /* peer's is at front */
+ char domain[ASN_NAME_MAX];
+
+ #ifdef CYASSL_CALLBACKS
+ if (ssl->hsInfoOn) AddPacketName("Certificate", &ssl->handShakeInfo);
+ if (ssl->toInfoOn) AddLateName("Certificate", &ssl->timeoutInfo);
+ #endif
+ c24to32(&input[i], &listSz);
+ i += CERT_HEADER_SZ;
+
+ while (listSz) {
+ /* cert size */
+ buffer myCert;
+ word32 certSz;
+ DecodedCert dCert;
+ word32 idx = 0;
+
+ c24to32(&input[i], &certSz);
+ i += CERT_HEADER_SZ;
+
+ myCert.length = certSz;
+ myCert.buffer = input + i;
+ i += certSz;
+
+ listSz -= certSz + CERT_HEADER_SZ;
+
+ if (ret != 0 && anyError == 0)
+ anyError = ret; /* save error from last time */
+
+#ifdef SESSION_CERTS
+ if (ssl->session.chain.count < MAX_CHAIN_DEPTH &&
+ myCert.length < MAX_X509_SIZE) {
+ ssl->session.chain.certs[ssl->session.chain.count].length =
+ myCert.length;
+ XMEMCPY(ssl->session.chain.certs[ssl->session.chain.count].buffer,
+ myCert.buffer, myCert.length);
+ ssl->session.chain.count++;
+ } else {
+ CYASSL_MSG("Couldn't store chain cert for session");
+ }
+#endif
+
+ InitDecodedCert(&dCert, myCert.buffer, ssl->heap);
+ ret = ParseCertRelative(&dCert, myCert.length, CERT_TYPE,
+ !ssl->options.verifyNone, ssl->caList);
+
+ if (!firstTime) {
+ FreeDecodedCert(&dCert);
+ continue;
+ }
+
+ /* get rest of peer info in case user wants to continue */
+ if (ret != 0) {
+ if (!(ret == ASN_BEFORE_DATE_E || ret == ASN_AFTER_DATE_E ||
+ ret == ASN_SIG_CONFIRM_E)) {
+ FreeDecodedCert(&dCert);
+ continue;
+ }
+ }
+
+ /* first one has peer's key */
+ firstTime = 0;
+
+ ssl->options.havePeerCert = 1;
+ /* set X509 format */
+#ifdef OPENSSL_EXTRA
+ ssl->peerCert.issuer.sz = (int)XSTRLEN(dCert.issuer) + 1;
+ XSTRNCPY(ssl->peerCert.issuer.name, dCert.issuer, ASN_NAME_MAX);
+ ssl->peerCert.subject.sz = (int)XSTRLEN(dCert.subject) + 1;
+ XSTRNCPY(ssl->peerCert.subject.name, dCert.subject, ASN_NAME_MAX);
+#endif
+
+ XMEMCPY(domain, dCert.subjectCN, dCert.subjectCNLen);
+ domain[dCert.subjectCNLen] = '\0';
+
+ if (!ssl->options.verifyNone && ssl->buffers.domainName.buffer)
+ if (XSTRNCMP((char*)ssl->buffers.domainName.buffer,
+ dCert.subjectCN,
+ ssl->buffers.domainName.length - 1)) {
+ ret = DOMAIN_NAME_MISMATCH; /* try to get peer key still */
+ }
+
+ /* decode peer key */
+ if (dCert.keyOID == RSAk) {
+ if (RsaPublicKeyDecode(dCert.publicKey, &idx,
+ &ssl->peerRsaKey, dCert.pubKeySize) != 0) {
+ ret = PEER_KEY_ERROR;
+ FreeDecodedCert(&dCert);
+ continue;
+ }
+ ssl->peerRsaKeyPresent = 1;
+ }
+#ifdef HAVE_NTRU
+ else if (dCert.keyOID == NTRUk) {
+ if (dCert.pubKeySize > sizeof(ssl->peerNtruKey)) {
+ ret = PEER_KEY_ERROR;
+ FreeDecodedCert(&dCert);
+ continue;
+ }
+ XMEMCPY(ssl->peerNtruKey, dCert.publicKey, dCert.pubKeySize);
+ ssl->peerNtruKeyLen = (word16)dCert.pubKeySize;
+ ssl->peerNtruKeyPresent = 1;
+ }
+#endif /* HAVE_NTRU */
+#ifdef HAVE_ECC
+ else if (dCert.keyOID == ECDSAk) {
+ if (ecc_import_x963(dCert.publicKey, dCert.pubKeySize,
+ &ssl->peerEccDsaKey) != 0) {
+ ret = PEER_KEY_ERROR;
+ FreeDecodedCert(&dCert);
+ continue;
+ }
+ ssl->peerEccDsaKeyPresent = 1;
+ }
+#endif /* HAVE_ECC */
+
+ FreeDecodedCert(&dCert);
+ }
+
+ if (anyError != 0)
+ ret = anyError;
+
+ if (ret == 0 && ssl->options.side == CLIENT_END)
+ ssl->options.serverState = SERVER_CERT_COMPLETE;
+
+ if (ret != 0) {
+ if (!ssl->options.verifyNone) {
+ int why = bad_certificate;
+ if (ret == ASN_AFTER_DATE_E || ret == ASN_BEFORE_DATE_E)
+ why = certificate_expired;
+ if (ssl->ctx->verifyCallback) {
+ int ok;
+ X509_STORE_CTX store;
+
+ store.error = ret;
+ store.error_depth = 1;
+ store.domain = domain;
+#ifdef OPENSSL_EXTRA
+ store.current_cert = &ssl->peerCert;
+#else
+ store.current_cert = NULL;
+#endif
+ ok = ssl->ctx->verifyCallback(0, &store);
+ if (ok)
+ ret = 0;
+ }
+ if (ret != 0) {
+ SendAlert(ssl, alert_fatal, why); /* try to send */
+ ssl->options.isClosed = 1;
+ }
+ }
+ ssl->error = ret;
+ }
+
+ *inOutIdx = i;
+ return ret;
+}
+
+
+int DoFinished(SSL* ssl, const byte* input, word32* inOutIdx, int sniff)
+{
+ byte verifyMAC[SHA_DIGEST_SIZE];
+ int finishedSz = ssl->options.tls ? TLS_FINISHED_SZ : FINISHED_SZ;
+ int headerSz = HANDSHAKE_HEADER_SZ;
+ word32 macSz = finishedSz + HANDSHAKE_HEADER_SZ,
+ idx = *inOutIdx,
+ padSz = ssl->keys.encryptSz - HANDSHAKE_HEADER_SZ - finishedSz -
+ ssl->specs.hash_size;
+ const byte* mac;
+
+ #ifdef CYASSL_DTLS
+ if (ssl->options.dtls) {
+ headerSz += DTLS_HANDSHAKE_EXTRA;
+ macSz += DTLS_HANDSHAKE_EXTRA;
+ padSz -= DTLS_HANDSHAKE_EXTRA;
+ }
+ #endif
+
+ #ifdef CYASSL_CALLBACKS
+ if (ssl->hsInfoOn) AddPacketName("Finished", &ssl->handShakeInfo);
+ if (ssl->toInfoOn) AddLateName("Finished", &ssl->timeoutInfo);
+ #endif
+ if (sniff == NO_SNIFF) {
+ if (XMEMCMP(input + idx, &ssl->verifyHashes, finishedSz))
+ return VERIFY_FINISHED_ERROR;
+ }
+
+ ssl->hmac(ssl, verifyMAC, input + idx - headerSz, macSz,
+ handshake, 1);
+ idx += finishedSz;
+
+ /* read mac and fill */
+ mac = input + idx;
+ idx += ssl->specs.hash_size;
+
+ if (ssl->options.tls1_1 && ssl->specs.cipher_type == block)
+ padSz -= ssl->specs.block_size;
+
+ idx += padSz;
+
+ /* verify mac */
+ if (XMEMCMP(mac, verifyMAC, ssl->specs.hash_size))
+ return VERIFY_MAC_ERROR;
+
+ if (ssl->options.side == CLIENT_END) {
+ ssl->options.serverState = SERVER_FINISHED_COMPLETE;
+ if (!ssl->options.resuming)
+ ssl->options.handShakeState = HANDSHAKE_DONE;
+ }
+ else {
+ ssl->options.clientState = CLIENT_FINISHED_COMPLETE;
+ if (ssl->options.resuming)
+ ssl->options.handShakeState = HANDSHAKE_DONE;
+ }
+
+ *inOutIdx = idx;
+ return 0;
+}
+
+
+static int DoHandShakeMsg(SSL* ssl, byte* input, word32* inOutIdx,
+ word32 totalSz)
+{
+ byte type;
+ word32 size;
+ int ret = 0;
+
+ CYASSL_ENTER("DoHandShakeMsg()");
+
+ if (GetHandShakeHeader(ssl, input, inOutIdx, &type, &size) != 0)
+ return PARSE_ERROR;
+
+ if (*inOutIdx + size > totalSz)
+ return INCOMPLETE_DATA;
+
+ HashInput(ssl, input + *inOutIdx, size);
+#ifdef CYASSL_CALLBACKS
+ /* add name later, add on record and handshake header part back on */
+ if (ssl->toInfoOn) {
+ int add = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+ AddPacketInfo(0, &ssl->timeoutInfo, input + *inOutIdx - add,
+ size + add, ssl->heap);
+ AddLateRecordHeader(&ssl->curRL, &ssl->timeoutInfo);
+ }
+#endif
+
+ switch (type) {
+
+#ifndef NO_CYASSL_CLIENT
+ case hello_verify_request:
+ CYASSL_MSG("processing hello verify request");
+ ret = DoHelloVerifyRequest(ssl, input,inOutIdx);
+ break;
+
+ case server_hello:
+ CYASSL_MSG("processing server hello");
+ ret = DoServerHello(ssl, input, inOutIdx);
+ break;
+
+ case certificate_request:
+ CYASSL_MSG("processing certificate request");
+ ret = DoCertificateRequest(ssl, input, inOutIdx);
+ break;
+
+ case server_key_exchange:
+ CYASSL_MSG("processing server key exchange");
+ ret = DoServerKeyExchange(ssl, input, inOutIdx);
+ break;
+#endif
+
+ case certificate:
+ CYASSL_MSG("processing certificate");
+ ret = DoCertificate(ssl, input, inOutIdx);
+ break;
+
+ case server_hello_done:
+ CYASSL_MSG("processing server hello done");
+ #ifdef CYASSL_CALLBACKS
+ if (ssl->hsInfoOn)
+ AddPacketName("ServerHelloDone", &ssl->handShakeInfo);
+ if (ssl->toInfoOn)
+ AddLateName("ServerHelloDone", &ssl->timeoutInfo);
+ #endif
+ ssl->options.serverState = SERVER_HELLODONE_COMPLETE;
+ break;
+
+ case finished:
+ CYASSL_MSG("processing finished");
+ ret = DoFinished(ssl, input, inOutIdx, NO_SNIFF);
+ break;
+
+#ifndef NO_CYASSL_SERVER
+ case client_hello:
+ CYASSL_MSG("processing client hello");
+ ret = DoClientHello(ssl, input, inOutIdx, totalSz, size);
+ break;
+
+ case client_key_exchange:
+ CYASSL_MSG("processing client key exchange");
+ ret = DoClientKeyExchange(ssl, input, inOutIdx);
+ break;
+
+ case certificate_verify:
+ CYASSL_MSG("processing certificate verify");
+ ret = DoCertificateVerify(ssl, input, inOutIdx, totalSz);
+ break;
+
+#endif
+
+ default:
+ ret = UNKNOWN_HANDSHAKE_TYPE;
+ }
+
+ CYASSL_LEAVE("DoHandShakeMsg()", ret);
+ return ret;
+}
+
+
+static INLINE void Encrypt(SSL* ssl, byte* out, const byte* input, word32 sz)
+{
+ switch (ssl->specs.bulk_cipher_algorithm) {
+ #ifdef BUILD_ARC4
+ case rc4:
+ Arc4Process(&ssl->encrypt.arc4, out, input, sz);
+ break;
+ #endif
+
+ #ifdef BUILD_DES3
+ case triple_des:
+ Des3_CbcEncrypt(&ssl->encrypt.des3, out, input, sz);
+ break;
+ #endif
+
+ #ifdef BUILD_AES
+ case aes:
+#ifdef CYASSL_AESNI
+ if ((word)input % 16) {
+ byte buffer[MAX_RECORD_SIZE + MAX_COMP_EXTRA+MAX_MSG_EXTRA];
+ XMEMCPY(buffer, input, sz);
+ AesCbcEncrypt(&ssl->encrypt.aes, buffer, buffer, sz);
+ XMEMCPY(out, buffer, sz);
+ break;
+ }
+#endif
+ AesCbcEncrypt(&ssl->encrypt.aes, out, input, sz);
+ break;
+ #endif
+
+ #ifdef BUILD_HC128
+ case hc128:
+ Hc128_Process(&ssl->encrypt.hc128, out, input, sz);
+ break;
+ #endif
+
+ #ifdef BUILD_RABBIT
+ case rabbit:
+ RabbitProcess(&ssl->encrypt.rabbit, out, input, sz);
+ break;
+ #endif
+ }
+}
+
+
+static INLINE void Decrypt(SSL* ssl, byte* plain, const byte* input, word32 sz)
+{
+ switch (ssl->specs.bulk_cipher_algorithm) {
+ #ifdef BUILD_ARC4
+ case rc4:
+ Arc4Process(&ssl->decrypt.arc4, plain, input, sz);
+ break;
+ #endif
+
+ #ifdef BUILD_DES3
+ case triple_des:
+ Des3_CbcDecrypt(&ssl->decrypt.des3, plain, input, sz);
+ break;
+ #endif
+
+ #ifdef BUILD_AES
+ case aes:
+ AesCbcDecrypt(&ssl->decrypt.aes, plain, input, sz);
+ break;
+ #endif
+
+ #ifdef BUILD_HC128
+ case hc128:
+ Hc128_Process(&ssl->decrypt.hc128, plain, input, sz);
+ break;
+ #endif
+
+ #ifdef BUILD_RABBIT
+ case rabbit:
+ RabbitProcess(&ssl->decrypt.rabbit, plain, input, sz);
+ break;
+ #endif
+ }
+}
+
+
+/* decrypt input message in place */
+static int DecryptMessage(SSL* ssl, byte* input, word32 sz, word32* idx)
+{
+ Decrypt(ssl, input, input, sz);
+ ssl->keys.encryptSz = sz;
+ if (ssl->options.tls1_1 && ssl->specs.cipher_type == block)
+ *idx += ssl->specs.block_size; /* go past TLSv1.1 IV */
+
+ return 0;
+}
+
+
+static INLINE word32 GetSEQIncrement(SSL* ssl, int verify)
+{
+ if (verify)
+ return ssl->keys.peer_sequence_number++;
+ else
+ return ssl->keys.sequence_number++;
+}
+
+
+int DoApplicationData(SSL* ssl, byte* input, word32* inOutIdx)
+{
+ word32 msgSz = ssl->keys.encryptSz;
+ word32 pad = 0,
+ padByte = 0,
+ idx = *inOutIdx,
+ digestSz = ssl->specs.hash_size;
+ int dataSz;
+ int ivExtra = 0;
+ byte* rawData = input + idx; /* keep current for hmac */
+#ifdef HAVE_LIBZ
+ byte decomp[MAX_RECORD_SIZE + MAX_COMP_EXTRA];
+#endif
+
+ byte verify[SHA_DIGEST_SIZE];
+ const byte* mac;
+
+ if (ssl->specs.cipher_type == block) {
+ if (ssl->options.tls1_1)
+ ivExtra = ssl->specs.block_size;
+ pad = *(input + idx + msgSz - ivExtra - 1);
+ padByte = 1;
+ }
+
+ dataSz = msgSz - ivExtra - digestSz - pad - padByte;
+ if (dataSz < 0)
+ return BUFFER_ERROR;
+
+ /* read data */
+ if (dataSz) {
+ int rawSz = dataSz; /* keep raw size for hmac */
+
+ ssl->hmac(ssl, verify, rawData, rawSz, application_data, 1);
+
+#ifdef HAVE_LIBZ
+ byte decomp[MAX_RECORD_SIZE + MAX_COMP_EXTRA];
+
+ if (ssl->options.usingCompression) {
+ dataSz = DeCompress(ssl, rawData, dataSz, decomp, sizeof(decomp));
+ if (dataSz < 0) return dataSz;
+ }
+#endif
+
+ if (ssl->options.usingCompression)
+ idx += rawSz;
+ else
+ idx += dataSz;
+
+ ssl->buffers.clearOutputBuffer.buffer = rawData;
+ ssl->buffers.clearOutputBuffer.length = dataSz;
+ }
+
+ /* read mac and fill */
+ mac = input + idx;
+ idx += digestSz;
+
+ idx += pad;
+ if (padByte)
+ idx++;
+
+#ifdef HAVE_LIBZ
+ if (ssl->options.usingCompression)
+ XMEMMOVE(rawData, decomp, dataSz);
+#endif
+
+ /* verify */
+ if (dataSz) {
+ if (XMEMCMP(mac, verify, digestSz))
+ return VERIFY_MAC_ERROR;
+ }
+ else
+ GetSEQIncrement(ssl, 1); /* even though no data, increment verify */
+
+ *inOutIdx = idx;
+ return 0;
+}
+
+
+/* process alert, return level */
+static int DoAlert(SSL* ssl, byte* input, word32* inOutIdx, int* type)
+{
+ byte level;
+
+ #ifdef CYASSL_CALLBACKS
+ if (ssl->hsInfoOn)
+ AddPacketName("Alert", &ssl->handShakeInfo);
+ if (ssl->toInfoOn)
+ /* add record header back on to info + 2 byte level, data */
+ AddPacketInfo("Alert", &ssl->timeoutInfo, input + *inOutIdx -
+ RECORD_HEADER_SZ, 2 + RECORD_HEADER_SZ, ssl->heap);
+ #endif
+ level = input[(*inOutIdx)++];
+ *type = (int)input[(*inOutIdx)++];
+
+ if (*type == close_notify)
+ ssl->options.closeNotify = 1;
+
+ if (ssl->keys.encryptionOn) {
+ int aSz = ALERT_SIZE;
+ const byte* mac;
+ byte verify[SHA_DIGEST_SIZE];
+ int padSz = ssl->keys.encryptSz - aSz - ssl->specs.hash_size;
+
+ ssl->hmac(ssl, verify, input + *inOutIdx - aSz, aSz, alert, 1);
+
+ /* read mac and fill */
+ mac = input + *inOutIdx;
+ *inOutIdx += (ssl->specs.hash_size + padSz);
+
+ /* verify */
+ if (XMEMCMP(mac, verify, ssl->specs.hash_size))
+ return VERIFY_MAC_ERROR;
+ }
+
+ return level;
+}
+
+static int GetInputData(SSL *ssl, size_t size)
+{
+ int in;
+ int inSz;
+ int maxLength;
+ int usedLength;
+
+
+ /* check max input length */
+ usedLength = ssl->buffers.inputBuffer.length - ssl->buffers.inputBuffer.idx;
+ maxLength = ssl->buffers.inputBuffer.bufferSize - usedLength;
+ inSz = (int)(size - usedLength); /* from last partial read */
+
+#ifdef CYASSL_DTLS
+ if (ssl->options.dtls)
+ inSz = 1500; /* read ahead up to MTU */
+#endif
+
+ if (inSz > maxLength) {
+ if (GrowInputBuffer(ssl, size, usedLength) < 0)
+ return MEMORY_E;
+ }
+
+ if (inSz <= 0)
+ return BUFFER_ERROR;
+
+ /* Put buffer data at start if not there */
+ if (usedLength > 0 && ssl->buffers.inputBuffer.idx != 0)
+ XMEMMOVE(ssl->buffers.inputBuffer.buffer,
+ ssl->buffers.inputBuffer.buffer + ssl->buffers.inputBuffer.idx,
+ usedLength);
+
+ /* remove processed data */
+ ssl->buffers.inputBuffer.idx = 0;
+ ssl->buffers.inputBuffer.length = usedLength;
+
+ /* read data from network */
+ do {
+ in = Receive(ssl,
+ ssl->buffers.inputBuffer.buffer +
+ ssl->buffers.inputBuffer.length,
+ inSz, 0);
+ if (in == -1)
+ return SOCKET_ERROR_E;
+
+ if (in == WANT_READ)
+ return WANT_READ;
+
+ ssl->buffers.inputBuffer.length += in;
+ inSz -= in;
+
+ } while (ssl->buffers.inputBuffer.length < size);
+
+ return 0;
+}
+
+/* process input requests, return 0 is done, 1 is call again to complete, and
+ negative number is error */
+int ProcessReply(SSL* ssl)
+{
+ int ret, type, readSz;
+ word32 startIdx = 0;
+ byte b0, b1;
+#ifdef CYASSL_DTLS
+ int used;
+#endif
+
+ for (;;) {
+ switch ((processReply)ssl->options.processReply) {
+
+ /* in the CYASSL_SERVER case, get the first byte for detecting
+ * old client hello */
+ case doProcessInit:
+
+ readSz = RECORD_HEADER_SZ;
+
+ #ifdef CYASSL_DTLS
+ if (ssl->options.dtls)
+ readSz = DTLS_RECORD_HEADER_SZ;
+ #endif
+
+ /* get header or return error */
+ if (!ssl->options.dtls) {
+ if ((ret = GetInputData(ssl, readSz)) < 0)
+ return ret;
+ } else {
+ #ifdef CYASSL_DTLS
+ /* read ahead may already have header */
+ used = ssl->buffers.inputBuffer.length -
+ ssl->buffers.inputBuffer.idx;
+ if (used < readSz)
+ if ((ret = GetInputData(ssl, readSz)) < 0)
+ return ret;
+ #endif
+ }
+
+#ifndef NO_CYASSL_SERVER
+
+ /* see if sending SSLv2 client hello */
+ if ( ssl->options.side == SERVER_END &&
+ ssl->options.clientState == NULL_STATE &&
+ ssl->buffers.inputBuffer.buffer[ssl->buffers.inputBuffer.idx]
+ != handshake) {
+ ssl->options.processReply = runProcessOldClientHello;
+
+ /* how many bytes need ProcessOldClientHello */
+ b0 =
+ ssl->buffers.inputBuffer.buffer[ssl->buffers.inputBuffer.idx++];
+ b1 =
+ ssl->buffers.inputBuffer.buffer[ssl->buffers.inputBuffer.idx++];
+ ssl->curSize = ((b0 & 0x7f) << 8) | b1;
+ }
+ else {
+ ssl->options.processReply = getRecordLayerHeader;
+ continue;
+ }
+
+ /* in the CYASSL_SERVER case, run the old client hello */
+ case runProcessOldClientHello:
+
+ /* get sz bytes or return error */
+ if (!ssl->options.dtls) {
+ if ((ret = GetInputData(ssl, ssl->curSize)) < 0)
+ return ret;
+ } else {
+ #ifdef CYASSL_DTLS
+ /* read ahead may already have */
+ used = ssl->buffers.inputBuffer.length -
+ ssl->buffers.inputBuffer.idx;
+ if (used < ssl->curSize)
+ if ((ret = GetInputData(ssl, ssl->curSize)) < 0)
+ return ret;
+ #endif /* CYASSL_DTLS */
+ }
+
+ ret = ProcessOldClientHello(ssl, ssl->buffers.inputBuffer.buffer,
+ &ssl->buffers.inputBuffer.idx,
+ ssl->buffers.inputBuffer.length -
+ ssl->buffers.inputBuffer.idx,
+ ssl->curSize);
+ if (ret < 0)
+ return ret;
+
+ else if (ssl->buffers.inputBuffer.idx ==
+ ssl->buffers.inputBuffer.length) {
+ ssl->options.processReply = doProcessInit;
+ return 0;
+ }
+
+#endif /* NO_CYASSL_SERVER */
+
+ /* get the record layer header */
+ case getRecordLayerHeader:
+
+ ret = GetRecordHeader(ssl, ssl->buffers.inputBuffer.buffer,
+ &ssl->buffers.inputBuffer.idx,
+ &ssl->curRL, &ssl->curSize);
+ if (ret != 0)
+ return ret;
+
+ ssl->options.processReply = getData;
+
+ /* retrieve record layer data */
+ case getData:
+
+ /* get sz bytes or return error */
+ if (!ssl->options.dtls) {
+ if ((ret = GetInputData(ssl, ssl->curSize)) < 0)
+ return ret;
+ } else {
+#ifdef CYASSL_DTLS
+ /* read ahead may already have */
+ used = ssl->buffers.inputBuffer.length -
+ ssl->buffers.inputBuffer.idx;
+ if (used < ssl->curSize)
+ if ((ret = GetInputData(ssl, ssl->curSize)) < 0)
+ return ret;
+#endif
+ }
+
+ ssl->options.processReply = runProcessingOneMessage;
+ startIdx = ssl->buffers.inputBuffer.idx; /* in case > 1 msg per */
+
+ /* the record layer is here */
+ case runProcessingOneMessage:
+
+ if (ssl->keys.encryptionOn)
+ if (DecryptMessage(ssl, ssl->buffers.inputBuffer.buffer +
+ ssl->buffers.inputBuffer.idx,
+ ssl->curSize,
+ &ssl->buffers.inputBuffer.idx) < 0)
+ return DECRYPT_ERROR;
+
+ CYASSL_MSG("received record layer msg");
+
+ switch (ssl->curRL.type) {
+ case handshake :
+ /* debugging in DoHandShakeMsg */
+ if ((ret = DoHandShakeMsg(ssl,
+ ssl->buffers.inputBuffer.buffer,
+ &ssl->buffers.inputBuffer.idx,
+ ssl->buffers.inputBuffer.length))
+ != 0)
+ return ret;
+ break;
+
+ case change_cipher_spec:
+ CYASSL_MSG("got CHANGE CIPHER SPEC");
+ #ifdef CYASSL_CALLBACKS
+ if (ssl->hsInfoOn)
+ AddPacketName("ChangeCipher", &ssl->handShakeInfo);
+ /* add record header back on info */
+ if (ssl->toInfoOn) {
+ AddPacketInfo("ChangeCipher", &ssl->timeoutInfo,
+ ssl->buffers.inputBuffer.buffer +
+ ssl->buffers.inputBuffer.idx - RECORD_HEADER_SZ,
+ 1 + RECORD_HEADER_SZ, ssl->heap);
+ AddLateRecordHeader(&ssl->curRL, &ssl->timeoutInfo);
+ }
+ #endif
+ ssl->buffers.inputBuffer.idx++;
+ ssl->keys.encryptionOn = 1;
+
+ #ifdef CYASSL_DTLS
+ if (ssl->options.dtls)
+ ssl->keys.dtls_peer_epoch++;
+ #endif
+
+ #ifdef HAVE_LIBZ
+ if (ssl->options.usingCompression)
+ if ( (ret = InitStreams(ssl)) != 0)
+ return ret;
+ #endif
+ if (ssl->options.resuming && ssl->options.side ==
+ CLIENT_END)
+ BuildFinished(ssl, &ssl->verifyHashes, server);
+ else if (!ssl->options.resuming && ssl->options.side ==
+ SERVER_END)
+ BuildFinished(ssl, &ssl->verifyHashes, client);
+ break;
+
+ case application_data:
+ CYASSL_MSG("got app DATA");
+ if ((ret = DoApplicationData(ssl,
+ ssl->buffers.inputBuffer.buffer,
+ &ssl->buffers.inputBuffer.idx))
+ != 0) {
+ CYASSL_ERROR(ret);
+ return ret;
+ }
+ break;
+
+ case alert:
+ CYASSL_MSG("got ALERT!");
+ if (DoAlert(ssl, ssl->buffers.inputBuffer.buffer,
+ &ssl->buffers.inputBuffer.idx, &type) == alert_fatal)
+ return FATAL_ERROR;
+
+ /* catch warnings that are handled as errors */
+ if (type == close_notify)
+ return ssl->error = ZERO_RETURN;
+
+ if (type == decrypt_error)
+ return FATAL_ERROR;
+ break;
+
+ default:
+ CYASSL_ERROR(UNKNOWN_RECORD_TYPE);
+ return UNKNOWN_RECORD_TYPE;
+ }
+
+ ssl->options.processReply = doProcessInit;
+
+ /* input exhausted? */
+ if (ssl->buffers.inputBuffer.idx == ssl->buffers.inputBuffer.length)
+ return 0;
+ /* more messages per record */
+ else if ((ssl->buffers.inputBuffer.idx - startIdx) < ssl->curSize) {
+ #ifdef CYASSL_DTLS
+ /* read-ahead but dtls doesn't bundle messages per record */
+ if (ssl->options.dtls) {
+ ssl->options.processReply = doProcessInit;
+ continue;
+ }
+ #endif
+ ssl->options.processReply = runProcessingOneMessage;
+ continue;
+ }
+ /* more records */
+ else {
+ ssl->options.processReply = doProcessInit;
+ continue;
+ }
+ }
+ }
+}
+
+
+int SendChangeCipher(SSL* ssl)
+{
+ byte *output;
+ int sendSz = RECORD_HEADER_SZ + ENUM_LEN;
+ int idx = RECORD_HEADER_SZ;
+ int ret;
+
+ #ifdef CYASSL_DTLS
+ if (ssl->options.dtls) {
+ sendSz += DTLS_RECORD_EXTRA;
+ idx += DTLS_RECORD_EXTRA;
+ }
+ #endif
+
+ /* check for avalaible size */
+ if ((ret = CheckAvalaibleSize(ssl, sendSz)) != 0)
+ return ret;
+
+ /* get ouput buffer */
+ output = ssl->buffers.outputBuffer.buffer +
+ ssl->buffers.outputBuffer.idx;
+
+ AddRecordHeader(output, 1, change_cipher_spec, ssl);
+
+ output[idx] = 1; /* turn it on */
+
+ #ifdef CYASSL_CALLBACKS
+ if (ssl->hsInfoOn) AddPacketName("ChangeCipher", &ssl->handShakeInfo);
+ if (ssl->toInfoOn)
+ AddPacketInfo("ChangeCipher", &ssl->timeoutInfo, output, sendSz,
+ ssl->heap);
+ #endif
+ ssl->buffers.outputBuffer.length += sendSz;
+ return SendBuffered(ssl);
+}
+
+
+static INLINE const byte* GetMacSecret(SSL* ssl, int verify)
+{
+ if ( (ssl->options.side == CLIENT_END && !verify) ||
+ (ssl->options.side == SERVER_END && verify) )
+ return ssl->keys.client_write_MAC_secret;
+ else
+ return ssl->keys.server_write_MAC_secret;
+}
+
+
+static void Hmac(SSL* ssl, byte* digest, const byte* buffer, word32 sz,
+ int content, int verify)
+{
+ byte result[SHA_DIGEST_SIZE]; /* max possible sizes */
+ word32 digestSz = ssl->specs.hash_size; /* actual sizes */
+ word32 padSz = ssl->specs.pad_size;
+
+ Md5 md5;
+ Sha sha;
+
+ /* data */
+ byte seq[SEQ_SZ] = { 0x00, 0x00, 0x00, 0x00 };
+ byte conLen[ENUM_LEN + LENGTH_SZ]; /* content & length */
+ const byte* macSecret = GetMacSecret(ssl, verify);
+
+ conLen[0] = content;
+ c16toa((word16)sz, &conLen[ENUM_LEN]);
+ c32toa(GetSEQIncrement(ssl, verify), &seq[sizeof(word32)]);
+
+ if (ssl->specs.mac_algorithm == md5_mac) {
+ InitMd5(&md5);
+ /* inner */
+ Md5Update(&md5, macSecret, digestSz);
+ Md5Update(&md5, PAD1, padSz);
+ Md5Update(&md5, seq, SEQ_SZ);
+ Md5Update(&md5, conLen, sizeof(conLen));
+ /* buffer */
+ Md5Update(&md5, buffer, sz);
+ Md5Final(&md5, result);
+ /* outer */
+ Md5Update(&md5, macSecret, digestSz);
+ Md5Update(&md5, PAD2, padSz);
+ Md5Update(&md5, result, digestSz);
+ Md5Final(&md5, digest);
+ }
+ else {
+ InitSha(&sha);
+ /* inner */
+ ShaUpdate(&sha, macSecret, digestSz);
+ ShaUpdate(&sha, PAD1, padSz);
+ ShaUpdate(&sha, seq, SEQ_SZ);
+ ShaUpdate(&sha, conLen, sizeof(conLen));
+ /* buffer */
+ ShaUpdate(&sha, buffer, sz);
+ ShaFinal(&sha, result);
+ /* outer */
+ ShaUpdate(&sha, macSecret, digestSz);
+ ShaUpdate(&sha, PAD2, padSz);
+ ShaUpdate(&sha, result, digestSz);
+ ShaFinal(&sha, digest);
+ }
+}
+
+
+static void BuildMD5_CertVerify(SSL* ssl, byte* digest)
+{
+ byte md5_result[MD5_DIGEST_SIZE];
+
+ /* make md5 inner */
+ Md5Update(&ssl->hashMd5, ssl->arrays.masterSecret, SECRET_LEN);
+ Md5Update(&ssl->hashMd5, PAD1, PAD_MD5);
+ Md5Final(&ssl->hashMd5, md5_result);
+
+ /* make md5 outer */
+ Md5Update(&ssl->hashMd5, ssl->arrays.masterSecret, SECRET_LEN);
+ Md5Update(&ssl->hashMd5, PAD2, PAD_MD5);
+ Md5Update(&ssl->hashMd5, md5_result, MD5_DIGEST_SIZE);
+
+ Md5Final(&ssl->hashMd5, digest);
+}
+
+
+static void BuildSHA_CertVerify(SSL* ssl, byte* digest)
+{
+ byte sha_result[SHA_DIGEST_SIZE];
+
+ /* make sha inner */
+ ShaUpdate(&ssl->hashSha, ssl->arrays.masterSecret, SECRET_LEN);
+ ShaUpdate(&ssl->hashSha, PAD1, PAD_SHA);
+ ShaFinal(&ssl->hashSha, sha_result);
+
+ /* make sha outer */
+ ShaUpdate(&ssl->hashSha, ssl->arrays.masterSecret, SECRET_LEN);
+ ShaUpdate(&ssl->hashSha, PAD2, PAD_SHA);
+ ShaUpdate(&ssl->hashSha, sha_result, SHA_DIGEST_SIZE);
+
+ ShaFinal(&ssl->hashSha, digest);
+}
+
+
+static void BuildCertHashes(SSL* ssl, Hashes* hashes)
+{
+ /* store current states, building requires get_digest which resets state */
+ Md5 md5 = ssl->hashMd5;
+ Sha sha = ssl->hashSha;
+#ifndef NO_SHA256 /* for possible future changes */
+ Sha256 sha256;
+ if (IsAtLeastTLSv1_2(ssl))
+ sha256 = ssl->hashSha256;
+#endif
+
+ if (ssl->options.tls) {
+ Md5Final(&ssl->hashMd5, hashes->md5);
+ ShaFinal(&ssl->hashSha, hashes->sha);
+ }
+ else {
+ BuildMD5_CertVerify(ssl, hashes->md5);
+ BuildSHA_CertVerify(ssl, hashes->sha);
+ }
+
+ /* restore */
+ ssl->hashMd5 = md5;
+ ssl->hashSha = sha;
+#ifndef NO_SHA256
+ if (IsAtLeastTLSv1_2(ssl))
+ ssl->hashSha256 = sha256;
+#endif
+}
+
+
+/* Build SSL Message, encrypted */
+static int BuildMessage(SSL* ssl, byte* output, const byte* input, int inSz,
+ int type)
+{
+ word32 digestSz = ssl->specs.hash_size;
+ word32 sz = RECORD_HEADER_SZ + inSz + digestSz;
+ word32 pad = 0, i;
+ word32 idx = RECORD_HEADER_SZ;
+ word32 ivSz = 0; /* TLSv1.1 IV */
+ word32 headerSz = RECORD_HEADER_SZ;
+ word16 size;
+ byte iv[AES_BLOCK_SIZE]; /* max size */
+
+#ifdef CYASSL_DTLS
+ if (ssl->options.dtls) {
+ sz += DTLS_RECORD_EXTRA;
+ idx += DTLS_RECORD_EXTRA;
+ headerSz += DTLS_RECORD_EXTRA;
+ }
+#endif
+
+ if (ssl->specs.cipher_type == block) {
+ word32 blockSz = ssl->specs.block_size;
+ if (ssl->options.tls1_1) {
+ ivSz = blockSz;
+ sz += ivSz;
+ RNG_GenerateBlock(&ssl->rng, iv, ivSz);
+ }
+ sz += 1; /* pad byte */
+ pad = (sz - headerSz) % blockSz;
+ pad = blockSz - pad;
+ sz += pad;
+ }
+
+ size = sz - headerSz; /* include mac and digest */
+ AddRecordHeader(output, size, type, ssl);
+
+ /* write to output */
+ if (ivSz) {
+ XMEMCPY(output + idx, iv, ivSz);
+ idx += ivSz;
+ }
+ XMEMCPY(output + idx, input, inSz);
+ idx += inSz;
+
+ if (type == handshake)
+ HashOutput(ssl, output, headerSz + inSz, ivSz);
+ ssl->hmac(ssl, output+idx, output + headerSz + ivSz, inSz, type, 0);
+ idx += digestSz;
+
+ if (ssl->specs.cipher_type == block)
+ for (i = 0; i <= pad; i++) output[idx++] = pad; /* pad byte gets */
+ /* pad value too */
+ Encrypt(ssl, output + headerSz, output + headerSz, size);
+
+ return sz;
+}
+
+
+int SendFinished(SSL* ssl)
+{
+ int sendSz,
+ finishedSz = ssl->options.tls ? TLS_FINISHED_SZ :
+ FINISHED_SZ;
+ byte input[FINISHED_SZ + DTLS_HANDSHAKE_HEADER_SZ]; /* max */
+ byte *output;
+ Hashes* hashes;
+ int ret;
+ int headerSz = HANDSHAKE_HEADER_SZ;
+
+
+ #ifdef CYASSL_DTLS
+ if (ssl->options.dtls) {
+ headerSz += DTLS_HANDSHAKE_EXTRA;
+ ssl->keys.dtls_epoch++;
+ ssl->keys.dtls_sequence_number = 0; /* reset after epoch change */
+ }
+ #endif
+
+ /* check for avalaible size */
+ if ((ret = CheckAvalaibleSize(ssl, sizeof(input) + MAX_MSG_EXTRA)) != 0)
+ return ret;
+
+ /* get ouput buffer */
+ output = ssl->buffers.outputBuffer.buffer +
+ ssl->buffers.outputBuffer.idx;
+
+ AddHandShakeHeader(input, finishedSz, finished, ssl);
+
+ /* make finished hashes */
+ hashes = (Hashes*)&input[headerSz];
+ BuildFinished(ssl, hashes, ssl->options.side == CLIENT_END ? client :
+ server);
+
+ if ( (sendSz = BuildMessage(ssl, output, input, headerSz +
+ finishedSz, handshake)) == -1)
+ return BUILD_MSG_ERROR;
+
+ if (!ssl->options.resuming) {
+ AddSession(ssl); /* just try */
+ if (ssl->options.side == CLIENT_END)
+ BuildFinished(ssl, &ssl->verifyHashes, server);
+ else
+ ssl->options.handShakeState = HANDSHAKE_DONE;
+ }
+ else {
+ if (ssl->options.side == CLIENT_END)
+ ssl->options.handShakeState = HANDSHAKE_DONE;
+ else
+ BuildFinished(ssl, &ssl->verifyHashes, client);
+ }
+
+ #ifdef CYASSL_CALLBACKS
+ if (ssl->hsInfoOn) AddPacketName("Finished", &ssl->handShakeInfo);
+ if (ssl->toInfoOn)
+ AddPacketInfo("Finished", &ssl->timeoutInfo, output, sendSz,
+ ssl->heap);
+ #endif
+
+ ssl->buffers.outputBuffer.length += sendSz;
+
+ return SendBuffered(ssl);
+}
+
+
+int SendCertificate(SSL* ssl)
+{
+ int sendSz, length, ret = 0;
+ word32 i = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+ word32 certSz, listSz;
+ byte* output = 0;
+
+ if (ssl->options.usingPSK_cipher) return 0; /* not needed */
+
+ if (ssl->options.sendVerify == SEND_BLANK_CERT) {
+ certSz = 0;
+ length = CERT_HEADER_SZ;
+ listSz = 0;
+ }
+ else {
+ certSz = ssl->buffers.certificate.length;
+ /* list + cert size */
+ length = certSz + 2 * CERT_HEADER_SZ;
+ listSz = certSz + CERT_HEADER_SZ;
+ }
+ sendSz = length + RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+
+ #ifdef CYASSL_DTLS
+ if (ssl->options.dtls) {
+ sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+ i += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+ }
+ #endif
+
+ /* check for avalaible size */
+ if ((ret = CheckAvalaibleSize(ssl, sendSz)) != 0)
+ return ret;
+
+ /* get ouput buffer */
+ output = ssl->buffers.outputBuffer.buffer +
+ ssl->buffers.outputBuffer.idx;
+
+ AddHeaders(output, length, certificate, ssl);
+
+ /* list total */
+ c32to24(listSz, output + i);
+ i += CERT_HEADER_SZ;
+
+ /* member */
+ if (certSz) {
+ c32to24(certSz, output + i);
+ i += CERT_HEADER_SZ;
+ XMEMCPY(output + i, ssl->buffers.certificate.buffer, certSz);
+ i += certSz;
+ }
+ HashOutput(ssl, output, sendSz, 0);
+ #ifdef CYASSL_CALLBACKS
+ if (ssl->hsInfoOn) AddPacketName("Certificate", &ssl->handShakeInfo);
+ if (ssl->toInfoOn)
+ AddPacketInfo("Certificate", &ssl->timeoutInfo, output, sendSz,
+ ssl->heap);
+ #endif
+
+ if (ssl->options.side == SERVER_END)
+ ssl->options.serverState = SERVER_CERT_COMPLETE;
+
+ ssl->buffers.outputBuffer.length += sendSz;
+ return SendBuffered(ssl);
+}
+
+
+int SendCertificateRequest(SSL* ssl)
+{
+ byte *output;
+ int ret;
+ int sendSz;
+ word32 i = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+
+ int typeTotal = 1; /* only rsa for now */
+ int reqSz = ENUM_LEN + typeTotal + REQ_HEADER_SZ; /* add auth later */
+
+ if (IsAtLeastTLSv1_2(ssl))
+ reqSz += LENGTH_SZ + HASH_SIG_SIZE;
+
+ if (ssl->options.usingPSK_cipher) return 0; /* not needed */
+
+ sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ + reqSz;
+
+ #ifdef CYASSL_DTLS
+ if (ssl->options.dtls) {
+ sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+ i += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+ }
+ #endif
+ /* check for avalaible size */
+ if ((ret = CheckAvalaibleSize(ssl, sendSz)) != 0)
+ return ret;
+
+ /* get ouput buffer */
+ output = ssl->buffers.outputBuffer.buffer + ssl->buffers.outputBuffer.idx;
+
+ AddHeaders(output, reqSz, certificate_request, ssl);
+
+ /* write to output */
+ output[i++] = typeTotal; /* # of types */
+ output[i++] = rsa_sign;
+
+ /* supported hash/sig */
+ if (IsAtLeastTLSv1_2(ssl)) {
+ c16toa(HASH_SIG_SIZE, &output[i]);
+ i += LENGTH_SZ;
+
+ output[i++] = sha_mac; /* hash */
+ output[i++] = rsa_sa_algo; /* sig */
+ }
+
+ c16toa(0, &output[i]); /* auth's */
+ i += REQ_HEADER_SZ;
+
+ HashOutput(ssl, output, sendSz, 0);
+
+ #ifdef CYASSL_CALLBACKS
+ if (ssl->hsInfoOn)
+ AddPacketName("CertificateRequest", &ssl->handShakeInfo);
+ if (ssl->toInfoOn)
+ AddPacketInfo("CertificateRequest", &ssl->timeoutInfo, output,
+ sendSz, ssl->heap);
+ #endif
+ ssl->buffers.outputBuffer.length += sendSz;
+ return SendBuffered(ssl);
+}
+
+
+int SendData(SSL* ssl, const void* buffer, int sz)
+{
+ int sent = 0, /* plainText size */
+ sendSz,
+ ret;
+
+ if (ssl->error == WANT_WRITE)
+ ssl->error = 0;
+
+ if (ssl->options.handShakeState != HANDSHAKE_DONE) {
+ int err;
+ if ( (err = CyaSSL_negotiate(ssl)) != 0)
+ return err;
+ }
+
+ /* last time system socket output buffer was full, try again to send */
+ if (ssl->buffers.outputBuffer.length > 0) {
+ if ( (ssl->error = SendBuffered(ssl)) < 0) {
+ CYASSL_ERROR(ssl->error);
+ if (ssl->error == SOCKET_ERROR_E && ssl->options.connReset)
+ return 0; /* peer reset */
+ return ssl->error;
+ }
+ else {
+ /* advance sent to previous sent + plain size just sent */
+ sent = ssl->buffers.prevSent + ssl->buffers.plainSz;
+ CYASSL_MSG("sent write buffered data");
+ }
+ }
+
+ for (;;) {
+ int len = min(sz - sent, OUTPUT_RECORD_SIZE);
+ byte* out;
+ byte* sendBuffer = (byte*)buffer + sent; /* may switch on comp */
+ int buffSz = len; /* may switch on comp */
+#ifdef HAVE_LIBZ
+ byte comp[MAX_RECORD_SIZE + MAX_COMP_EXTRA];
+#endif
+
+ if (sent == sz) break;
+
+#ifdef CYASSL_DTLS
+ if (ssl->options.dtls) {
+ len = min(len, MAX_UDP_SIZE);
+ buffSz = len;
+ }
+#endif
+
+ /* check for avalaible size */
+ if ((ret = CheckAvalaibleSize(ssl, len + COMP_EXTRA +
+ MAX_MSG_EXTRA)) != 0)
+ return ret;
+
+ /* get ouput buffer */
+ out = ssl->buffers.outputBuffer.buffer +
+ ssl->buffers.outputBuffer.idx;
+
+#ifdef HAVE_LIBZ
+ if (ssl->options.usingCompression) {
+ buffSz = Compress(ssl, sendBuffer, buffSz, comp, sizeof(comp));
+ if (buffSz < 0) {
+ return buffSz;
+ }
+ sendBuffer = comp;
+ }
+#endif
+ sendSz = BuildMessage(ssl, out, sendBuffer, buffSz,
+ application_data);
+
+ ssl->buffers.outputBuffer.length += sendSz;
+
+ if ( (ret = SendBuffered(ssl)) < 0) {
+ CYASSL_ERROR(ret);
+ /* store for next call if WANT_WRITE or user embedSend() that
+ doesn't present like WANT_WRITE */
+ ssl->buffers.plainSz = len;
+ ssl->buffers.prevSent = sent;
+ if (ret == SOCKET_ERROR_E && ssl->options.connReset)
+ return 0; /* peer reset */
+ return ssl->error = ret;
+ }
+
+ sent += len;
+
+ /* only one message per attempt */
+ if (ssl->options.partialWrite == 1)
+ break;
+ }
+
+ return sent;
+}
+
+/* process input data */
+int ReceiveData(SSL* ssl, byte* output, int sz)
+{
+ int size;
+
+ CYASSL_ENTER("ReceiveData()");
+
+ if (ssl->error == WANT_READ)
+ ssl->error = 0;
+
+ if (ssl->options.handShakeState != HANDSHAKE_DONE) {
+ int err;
+ if ( (err = CyaSSL_negotiate(ssl)) != 0)
+ return err;
+ }
+
+ while (ssl->buffers.clearOutputBuffer.length == 0)
+ if ( (ssl->error = ProcessReply(ssl)) < 0) {
+ CYASSL_ERROR(ssl->error);
+ if (ssl->error == ZERO_RETURN) {
+ ssl->options.isClosed = 1;
+ return 0; /* no more data coming */
+ }
+ if (ssl->error == SOCKET_ERROR_E)
+ if (ssl->options.connReset || ssl->options.isClosed)
+ return 0; /* peer reset or closed */
+ return ssl->error;
+ }
+
+ if (sz < (int)ssl->buffers.clearOutputBuffer.length)
+ size = sz;
+ else
+ size = ssl->buffers.clearOutputBuffer.length;
+
+ XMEMCPY(output, ssl->buffers.clearOutputBuffer.buffer, size);
+ ssl->buffers.clearOutputBuffer.length -= size;
+ ssl->buffers.clearOutputBuffer.buffer += size;
+
+ if (ssl->buffers.clearOutputBuffer.length == 0 &&
+ ssl->buffers.inputBuffer.dynamicFlag)
+ ShrinkInputBuffer(ssl, NO_FORCED_FREE);
+
+ CYASSL_LEAVE("ReceiveData()", size);
+ return size;
+}
+
+
+/* send alert message */
+int SendAlert(SSL* ssl, int severity, int type)
+{
+ byte input[ALERT_SIZE];
+ byte *output;
+ int sendSz;
+ int ret;
+
+ /* if sendalert is called again for nonbloking */
+ if (ssl->options.sendAlertState != 0) {
+ ret = SendBuffered(ssl);
+ if (ret == 0)
+ ssl->options.sendAlertState = 0;
+ return ret;
+ }
+
+ /* check for avalaible size */
+ if ((ret = CheckAvalaibleSize(ssl, ALERT_SIZE + MAX_MSG_EXTRA)) != 0)
+ return ret;
+
+ /* get ouput buffer */
+ output = ssl->buffers.outputBuffer.buffer +
+ ssl->buffers.outputBuffer.idx;
+
+ input[0] = severity;
+ input[1] = type;
+
+ if (ssl->keys.encryptionOn)
+ sendSz = BuildMessage(ssl, output, input, sizeof(input), alert);
+ else {
+ RecordLayerHeader *const rl = (RecordLayerHeader*)output;
+ rl->type = alert;
+ rl->version = ssl->version;
+ c16toa(ALERT_SIZE, rl->length);
+
+ XMEMCPY(output + RECORD_HEADER_SZ, input, sizeof(input));
+ sendSz = RECORD_HEADER_SZ + sizeof(input);
+ }
+
+ #ifdef CYASSL_CALLBACKS
+ if (ssl->hsInfoOn)
+ AddPacketName("Alert", &ssl->handShakeInfo);
+ if (ssl->toInfoOn)
+ AddPacketInfo("Alert", &ssl->timeoutInfo, output, sendSz,ssl->heap);
+ #endif
+
+ ssl->buffers.outputBuffer.length += sendSz;
+ ssl->options.sendAlertState = 1;
+
+ return SendBuffered(ssl);
+}
+
+
+
+void SetErrorString(int error, char* buffer)
+{
+ const int max = MAX_ERROR_SZ; /* shorthand */
+
+#ifdef NO_ERROR_STRINGS
+
+ XSTRNCPY(buffer, "no support for error strings built in", max);
+
+#else
+
+ /* pass to CTaoCrypt */
+ if (error < MAX_CODE_E && error > MIN_CODE_E) {
+ CTaoCryptErrorString(error, buffer);
+ return;
+ }
+
+ switch (error) {
+
+ case UNSUPPORTED_SUITE :
+ XSTRNCPY(buffer, "unsupported cipher suite", max);
+ break;
+
+ case PREFIX_ERROR :
+ XSTRNCPY(buffer, "bad index to key rounds", max);
+ break;
+
+ case MEMORY_ERROR :
+ XSTRNCPY(buffer, "out of memory", max);
+ break;
+
+ case VERIFY_FINISHED_ERROR :
+ XSTRNCPY(buffer, "verify problem on finished", max);
+ break;
+
+ case VERIFY_MAC_ERROR :
+ XSTRNCPY(buffer, "verify mac problem", max);
+ break;
+
+ case PARSE_ERROR :
+ XSTRNCPY(buffer, "parse error on header", max);
+ break;
+
+ case SIDE_ERROR :
+ XSTRNCPY(buffer, "wrong client/server type", max);
+ break;
+
+ case NO_PEER_CERT :
+ XSTRNCPY(buffer, "peer didn't send cert", max);
+ break;
+
+ case UNKNOWN_HANDSHAKE_TYPE :
+ XSTRNCPY(buffer, "weird handshake type", max);
+ break;
+
+ case SOCKET_ERROR_E :
+ XSTRNCPY(buffer, "error state on socket", max);
+ break;
+
+ case SOCKET_NODATA :
+ XSTRNCPY(buffer, "expected data, not there", max);
+ break;
+
+ case INCOMPLETE_DATA :
+ XSTRNCPY(buffer, "don't have enough data to complete task", max);
+ break;
+
+ case UNKNOWN_RECORD_TYPE :
+ XSTRNCPY(buffer, "unknown type in record hdr", max);
+ break;
+
+ case DECRYPT_ERROR :
+ XSTRNCPY(buffer, "error during decryption", max);
+ break;
+
+ case FATAL_ERROR :
+ XSTRNCPY(buffer, "revcd alert fatal error", max);
+ break;
+
+ case ENCRYPT_ERROR :
+ XSTRNCPY(buffer, "error during encryption", max);
+ break;
+
+ case FREAD_ERROR :
+ XSTRNCPY(buffer, "fread problem", max);
+ break;
+
+ case NO_PEER_KEY :
+ XSTRNCPY(buffer, "need peer's key", max);
+ break;
+
+ case NO_PRIVATE_KEY :
+ XSTRNCPY(buffer, "need the private key", max);
+ break;
+
+ case RSA_PRIVATE_ERROR :
+ XSTRNCPY(buffer, "error during rsa priv op", max);
+ break;
+
+ case MATCH_SUITE_ERROR :
+ XSTRNCPY(buffer, "can't match cipher suite", max);
+ break;
+
+ case BUILD_MSG_ERROR :
+ XSTRNCPY(buffer, "build message failure", max);
+ break;
+
+ case BAD_HELLO :
+ XSTRNCPY(buffer, "client hello malformed", max);
+ break;
+
+ case DOMAIN_NAME_MISMATCH :
+ XSTRNCPY(buffer, "peer subject name mismatch", max);
+ break;
+
+ case WANT_READ :
+ XSTRNCPY(buffer, "non-blocking socket wants data to be read", max);
+ break;
+
+ case NOT_READY_ERROR :
+ XSTRNCPY(buffer, "handshake layer not ready yet, complete first", max);
+ break;
+
+ case PMS_VERSION_ERROR :
+ XSTRNCPY(buffer, "premaster secret version mismatch error", max);
+ break;
+
+ case VERSION_ERROR :
+ XSTRNCPY(buffer, "record layer version error", max);
+ break;
+
+ case WANT_WRITE :
+ XSTRNCPY(buffer, "non-blocking socket write buffer full", max);
+ break;
+
+ case BUFFER_ERROR :
+ XSTRNCPY(buffer, "malformed buffer input error", max);
+ break;
+
+ case VERIFY_CERT_ERROR :
+ XSTRNCPY(buffer, "verify problem on certificate", max);
+ break;
+
+ case VERIFY_SIGN_ERROR :
+ XSTRNCPY(buffer, "verify problem based on signature", max);
+ break;
+
+ case CLIENT_ID_ERROR :
+ XSTRNCPY(buffer, "psk client identity error", max);
+ break;
+
+ case SERVER_HINT_ERROR:
+ XSTRNCPY(buffer, "psk server hint error", max);
+ break;
+
+ case PSK_KEY_ERROR:
+ XSTRNCPY(buffer, "psk key callback error", max);
+ break;
+
+ case NTRU_KEY_ERROR:
+ XSTRNCPY(buffer, "NTRU key error", max);
+ break;
+
+ case NTRU_DRBG_ERROR:
+ XSTRNCPY(buffer, "NTRU drbg error", max);
+ break;
+
+ case NTRU_ENCRYPT_ERROR:
+ XSTRNCPY(buffer, "NTRU encrypt error", max);
+ break;
+
+ case NTRU_DECRYPT_ERROR:
+ XSTRNCPY(buffer, "NTRU decrypt error", max);
+ break;
+
+ case ZLIB_INIT_ERROR:
+ XSTRNCPY(buffer, "zlib init error", max);
+ break;
+
+ case ZLIB_COMPRESS_ERROR:
+ XSTRNCPY(buffer, "zlib compress error", max);
+ break;
+
+ case ZLIB_DECOMPRESS_ERROR:
+ XSTRNCPY(buffer, "zlib decompress error", max);
+ break;
+
+ case GETTIME_ERROR:
+ XSTRNCPY(buffer, "gettimeofday() error", max);
+ break;
+
+ case GETITIMER_ERROR:
+ XSTRNCPY(buffer, "getitimer() error", max);
+ break;
+
+ case SIGACT_ERROR:
+ XSTRNCPY(buffer, "sigaction() error", max);
+ break;
+
+ case SETITIMER_ERROR:
+ XSTRNCPY(buffer, "setitimer() error", max);
+ break;
+
+ case LENGTH_ERROR:
+ XSTRNCPY(buffer, "record layer length error", max);
+ break;
+
+ case PEER_KEY_ERROR:
+ XSTRNCPY(buffer, "cant decode peer key", max);
+ break;
+
+ case ZERO_RETURN:
+ XSTRNCPY(buffer, "peer sent close notify alert", max);
+ break;
+
+ case ECC_CURVETYPE_ERROR:
+ XSTRNCPY(buffer, "Bad ECC Curve Type or unsupported", max);
+ break;
+
+ case ECC_CURVE_ERROR:
+ XSTRNCPY(buffer, "Bad ECC Curve or unsupported", max);
+ break;
+
+ case ECC_PEERKEY_ERROR:
+ XSTRNCPY(buffer, "Bad ECC Peer Key", max);
+ break;
+
+ case ECC_MAKEKEY_ERROR:
+ XSTRNCPY(buffer, "ECC Make Key failutre", max);
+ break;
+
+ case ECC_EXPORT_ERROR:
+ XSTRNCPY(buffer, "ECC Export Key failutre", max);
+ break;
+
+ case ECC_SHARED_ERROR:
+ XSTRNCPY(buffer, "ECC DHE shared failutre", max);
+ break;
+
+ default :
+ XSTRNCPY(buffer, "unknown error number", max);
+ }
+
+#endif /* NO_ERROR_STRINGS */
+}
+
+
+
+/* be sure to add to cipher_name_idx too !!!! */
+const char* const cipher_names[] =
+{
+#ifdef BUILD_SSL_RSA_WITH_RC4_128_SHA
+ "RC4-SHA",
+#endif
+
+#ifdef BUILD_SSL_RSA_WITH_RC4_128_MD5
+ "RC4-MD5",
+#endif
+
+#ifdef BUILD_SSL_RSA_WITH_3DES_EDE_CBC_SHA
+ "DES-CBC3-SHA",
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA
+ "AES128-SHA",
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA
+ "AES256-SHA",
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA
+ "DHE-RSA-AES128-SHA",
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA
+ "DHE-RSA-AES256-SHA",
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA
+ "PSK-AES128-CBC-SHA",
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA
+ "PSK-AES256-CBC-SHA",
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_HC_128_CBC_MD5
+ "HC128-MD5",
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_HC_128_CBC_SHA
+ "HC128-SHA",
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_RABBIT_CBC_SHA
+ "RABBIT-SHA",
+#endif
+
+#ifdef BUILD_TLS_NTRU_RSA_WITH_RC4_128_SHA
+ "NTRU-RC4-SHA",
+#endif
+
+#ifdef BUILD_TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA
+ "NTRU-DES-CBC3-SHA",
+#endif
+
+#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_128_CBC_SHA
+ "NTRU-AES128-SHA",
+#endif
+
+#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_256_CBC_SHA
+ "NTRU-AES256-SHA",
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
+ "ECDHE-RSA-AES128-SHA",
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
+ "ECDHE-RSA-AES256-SHA",
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
+ "ECDHE-ECDSA-AES128-SHA",
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
+ "ECDHE-ECDSA-AES256-SHA",
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_RC4_128_SHA
+ "ECDHE-RSA-RC4-SHA",
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
+ "ECDHE-RSA-DES-CBC3-SHA",
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
+ "ECDHE-ECDSA-RC4-SHA",
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
+ "ECDHE-ECDSA-DES-CBC3-SHA",
+#endif
+
+};
+
+
+
+/* cipher suite number that matches above name table */
+int cipher_name_idx[] =
+{
+
+#ifdef BUILD_SSL_RSA_WITH_RC4_128_SHA
+ SSL_RSA_WITH_RC4_128_SHA,
+#endif
+
+#ifdef BUILD_SSL_RSA_WITH_RC4_128_MD5
+ SSL_RSA_WITH_RC4_128_MD5,
+#endif
+
+#ifdef BUILD_SSL_RSA_WITH_3DES_EDE_CBC_SHA
+ SSL_RSA_WITH_3DES_EDE_CBC_SHA,
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA
+ TLS_RSA_WITH_AES_128_CBC_SHA,
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA
+ TLS_RSA_WITH_AES_256_CBC_SHA,
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA
+ TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA
+ TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA
+ TLS_PSK_WITH_AES_128_CBC_SHA,
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA
+ TLS_PSK_WITH_AES_256_CBC_SHA,
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_HC_128_CBC_MD5
+ TLS_RSA_WITH_HC_128_CBC_MD5,
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_HC_128_CBC_SHA
+ TLS_RSA_WITH_HC_128_CBC_SHA,
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_RABBIT_CBC_SHA
+ TLS_RSA_WITH_RABBIT_CBC_SHA,
+#endif
+
+#ifdef BUILD_TLS_NTRU_RSA_WITH_RC4_128_SHA
+ TLS_NTRU_RSA_WITH_RC4_128_SHA,
+#endif
+
+#ifdef BUILD_TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA
+ TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA,
+#endif
+
+#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_128_CBC_SHA
+ TLS_NTRU_RSA_WITH_AES_128_CBC_SHA,
+#endif
+
+#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_256_CBC_SHA
+ TLS_NTRU_RSA_WITH_AES_256_CBC_SHA,
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
+ TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
+ TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
+ TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
+ TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_RC4_128_SHA
+ TLS_ECDHE_RSA_WITH_RC4_128_SHA,
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
+ TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
+ TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
+ TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
+#endif
+
+};
+
+
+/* return true if set, else false */
+/* only supports full name from cipher_name[] delimited by : */
+int SetCipherList(SSL_CTX* ctx, const char* list)
+{
+ int ret = 0, i;
+ char name[MAX_SUITE_NAME];
+
+ char needle[] = ":";
+ char* haystack = (char*)list;
+ char* prev;
+
+ const int suiteSz = sizeof(cipher_names) / sizeof(cipher_names[0]);
+ int idx = 0;
+
+ if (!list)
+ return 0;
+
+ if (*list == 0) return 1; /* CyaSSL default */
+
+ if (XSTRNCMP(haystack, "ALL", 3) == 0) return 1; /* CyaSSL defualt */
+
+ for(;;) {
+ size_t len;
+ prev = haystack;
+ haystack = XSTRSTR(haystack, needle);
+
+ if (!haystack) /* last cipher */
+ len = min(sizeof(name), XSTRLEN(prev));
+ else
+ len = min(sizeof(name), (size_t)(haystack - prev));
+
+ XSTRNCPY(name, prev, len);
+ name[(len == sizeof(name)) ? len - 1 : len] = 0;
+
+ for (i = 0; i < suiteSz; i++)
+ if (XSTRNCMP(name, cipher_names[i], sizeof(name)) == 0) {
+ if (XSTRSTR(name, "EC"))
+ ctx->suites.suites[idx++] = ECC_BYTE; /* ECC suite */
+ else
+ ctx->suites.suites[idx++] = 0x00; /* normal */
+ ctx->suites.suites[idx++] = cipher_name_idx[i];
+
+ if (!ret) ret = 1; /* found at least one */
+ break;
+ }
+ if (!haystack) break;
+ haystack++;
+ }
+
+ if (ret) {
+ ctx->suites.setSuites = 1;
+ ctx->suites.suiteSz = idx;
+ }
+
+ return ret;
+}
+
+
+#ifdef CYASSL_CALLBACKS
+
+ /* Initialisze HandShakeInfo */
+ void InitHandShakeInfo(HandShakeInfo* info)
+ {
+ int i;
+
+ info->cipherName[0] = 0;
+ for (i = 0; i < MAX_PACKETS_HANDSHAKE; i++)
+ info->packetNames[i][0] = 0;
+ info->numberPackets = 0;
+ info->negotiationError = 0;
+ }
+
+ /* Set Final HandShakeInfo parameters */
+ void FinishHandShakeInfo(HandShakeInfo* info, const SSL* ssl)
+ {
+ int i;
+ int sz = sizeof(cipher_name_idx)/sizeof(int);
+
+ for (i = 0; i < sz; i++)
+ if (ssl->options.cipherSuite == (byte)cipher_name_idx[i]) {
+ if (ssl->options.cipherSuite0 == ECC_BYTE)
+ continue; /* ECC suites at end */
+ XSTRNCPY(info->cipherName, cipher_names[i], MAX_CIPHERNAME_SZ);
+ break;
+ }
+
+ /* error max and min are negative numbers */
+ if (ssl->error <= MIN_PARAM_ERR && ssl->error >= MAX_PARAM_ERR)
+ info->negotiationError = ssl->error;
+ }
+
+
+ /* Add name to info packet names, increase packet name count */
+ void AddPacketName(const char* name, HandShakeInfo* info)
+ {
+ if (info->numberPackets < MAX_PACKETS_HANDSHAKE) {
+ XSTRNCPY(info->packetNames[info->numberPackets++], name,
+ MAX_PACKETNAME_SZ);
+ }
+ }
+
+
+ /* Initialisze TimeoutInfo */
+ void InitTimeoutInfo(TimeoutInfo* info)
+ {
+ int i;
+
+ info->timeoutName[0] = 0;
+ info->flags = 0;
+
+ for (i = 0; i < MAX_PACKETS_HANDSHAKE; i++) {
+ info->packets[i].packetName[0] = 0;
+ info->packets[i].timestamp.tv_sec = 0;
+ info->packets[i].timestamp.tv_usec = 0;
+ info->packets[i].bufferValue = 0;
+ info->packets[i].valueSz = 0;
+ }
+ info->numberPackets = 0;
+ info->timeoutValue.tv_sec = 0;
+ info->timeoutValue.tv_usec = 0;
+ }
+
+
+ /* Free TimeoutInfo */
+ void FreeTimeoutInfo(TimeoutInfo* info, void* heap)
+ {
+ int i;
+ for (i = 0; i < MAX_PACKETS_HANDSHAKE; i++)
+ if (info->packets[i].bufferValue) {
+ XFREE(info->packets[i].bufferValue, heap, DYNAMIC_TYPE_INFO);
+ info->packets[i].bufferValue = 0;
+ }
+
+ }
+
+
+ /* Add PacketInfo to TimeoutInfo */
+ void AddPacketInfo(const char* name, TimeoutInfo* info, const byte* data,
+ int sz, void* heap)
+ {
+ if (info->numberPackets < (MAX_PACKETS_HANDSHAKE - 1)) {
+ Timeval currTime;
+
+ /* may add name after */
+ if (name)
+ XSTRNCPY(info->packets[info->numberPackets].packetName, name,
+ MAX_PACKETNAME_SZ);
+
+ /* add data, put in buffer if bigger than static buffer */
+ info->packets[info->numberPackets].valueSz = sz;
+ if (sz < MAX_VALUE_SZ)
+ XMEMCPY(info->packets[info->numberPackets].value, data, sz);
+ else {
+ info->packets[info->numberPackets].bufferValue =
+ XMALLOC(sz, heap, DYNAMIC_TYPE_INFO);
+ if (!info->packets[info->numberPackets].bufferValue)
+ /* let next alloc catch, just don't fill, not fatal here */
+ info->packets[info->numberPackets].valueSz = 0;
+ else
+ XMEMCPY(info->packets[info->numberPackets].bufferValue,
+ data, sz);
+ }
+ gettimeofday(&currTime, 0);
+ info->packets[info->numberPackets].timestamp.tv_sec =
+ currTime.tv_sec;
+ info->packets[info->numberPackets].timestamp.tv_usec =
+ currTime.tv_usec;
+ info->numberPackets++;
+ }
+ }
+
+
+ /* Add packet name to previsouly added packet info */
+ void AddLateName(const char* name, TimeoutInfo* info)
+ {
+ /* make sure we have a valid previous one */
+ if (info->numberPackets > 0 && info->numberPackets <
+ MAX_PACKETS_HANDSHAKE) {
+ XSTRNCPY(info->packets[info->numberPackets - 1].packetName, name,
+ MAX_PACKETNAME_SZ);
+ }
+ }
+
+ /* Add record header to previsouly added packet info */
+ void AddLateRecordHeader(const RecordLayerHeader* rl, TimeoutInfo* info)
+ {
+ /* make sure we have a valid previous one */
+ if (info->numberPackets > 0 && info->numberPackets <
+ MAX_PACKETS_HANDSHAKE) {
+ if (info->packets[info->numberPackets - 1].bufferValue)
+ XMEMCPY(info->packets[info->numberPackets - 1].bufferValue, rl,
+ RECORD_HEADER_SZ);
+ else
+ XMEMCPY(info->packets[info->numberPackets - 1].value, rl,
+ RECORD_HEADER_SZ);
+ }
+ }
+
+#endif /* CYASSL_CALLBACKS */
+
+
+
+/* client only parts */
+#ifndef NO_CYASSL_CLIENT
+
+ int SendClientHello(SSL* ssl)
+ {
+ byte *output;
+ word32 length, idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+ int sendSz;
+ int idSz = ssl->options.resuming ? ID_LEN : 0;
+ int ret;
+
+ length = sizeof(ProtocolVersion) + RAN_LEN
+ + idSz + ENUM_LEN
+ + ssl->suites.suiteSz + SUITE_LEN
+ + COMP_LEN + ENUM_LEN;
+
+ sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
+
+#ifdef CYASSL_DTLS
+ if (ssl->options.dtls) {
+ length += ENUM_LEN; /* cookie */
+ sendSz = length + DTLS_HANDSHAKE_HEADER_SZ + DTLS_RECORD_HEADER_SZ;
+ idx += DTLS_HANDSHAKE_EXTRA + DTLS_RECORD_EXTRA;
+ }
+#endif
+
+ /* check for avalaible size */
+ if ((ret = CheckAvalaibleSize(ssl, sendSz)) != 0)
+ return ret;
+
+ /* get ouput buffer */
+ output = ssl->buffers.outputBuffer.buffer +
+ ssl->buffers.outputBuffer.idx;
+
+ AddHeaders(output, length, client_hello, ssl);
+
+ /* client hello, first version */
+ XMEMCPY(output + idx, &ssl->version, sizeof(ProtocolVersion));
+ idx += sizeof(ProtocolVersion);
+ ssl->chVersion = ssl->version; /* store in case changed */
+
+ /* then random */
+ if (ssl->options.connectState == CONNECT_BEGIN) {
+ RNG_GenerateBlock(&ssl->rng, output + idx, RAN_LEN);
+
+ /* store random */
+ XMEMCPY(ssl->arrays.clientRandom, output + idx, RAN_LEN);
+ } else {
+#ifdef CYASSL_DTLS
+ /* send same random on hello again */
+ XMEMCPY(output + idx, ssl->arrays.clientRandom, RAN_LEN);
+#endif
+ }
+ idx += RAN_LEN;
+
+ /* then session id */
+ output[idx++] = idSz;
+ if (idSz) {
+ XMEMCPY(output + idx, ssl->session.sessionID, ID_LEN);
+ idx += ID_LEN;
+ }
+
+ /* then DTLS cookie */
+#ifdef CYASSL_DTLS
+ if (ssl->options.dtls) {
+ output[idx++] = 0;
+ }
+#endif
+ /* then cipher suites */
+ c16toa(ssl->suites.suiteSz, output + idx);
+ idx += 2;
+ XMEMCPY(output + idx, &ssl->suites.suites, ssl->suites.suiteSz);
+ idx += ssl->suites.suiteSz;
+
+ /* last, compression */
+ output[idx++] = COMP_LEN;
+ if (ssl->options.usingCompression)
+ output[idx++] = ZLIB_COMPRESSION;
+ else
+ output[idx++] = NO_COMPRESSION;
+
+ HashOutput(ssl, output, sendSz, 0);
+
+ ssl->options.clientState = CLIENT_HELLO_COMPLETE;
+
+#ifdef CYASSL_CALLBACKS
+ if (ssl->hsInfoOn) AddPacketName("ClientHello", &ssl->handShakeInfo);
+ if (ssl->toInfoOn)
+ AddPacketInfo("ClientHello", &ssl->timeoutInfo, output, sendSz,
+ ssl->heap);
+#endif
+
+ ssl->buffers.outputBuffer.length += sendSz;
+
+ return SendBuffered(ssl);
+ }
+
+
+ static int DoHelloVerifyRequest(SSL* ssl, const byte* input,
+ word32* inOutIdx)
+ {
+ ProtocolVersion pv;
+ byte cookieSz;
+
+#ifdef CYASSL_CALLBACKS
+ if (ssl->hsInfoOn) AddPacketName("HelloVerifyRequest",
+ &ssl->handShakeInfo);
+ if (ssl->toInfoOn) AddLateName("HelloVerifyRequest", &ssl->timeoutInfo);
+#endif
+ XMEMCPY(&pv, input + *inOutIdx, sizeof(pv));
+ *inOutIdx += sizeof(pv);
+
+ cookieSz = input[(*inOutIdx)++];
+
+ if (cookieSz)
+ *inOutIdx += cookieSz; /* skip for now */
+
+ ssl->options.serverState = SERVER_HELLOVERIFYREQUEST_COMPLETE;
+ return 0;
+ }
+
+
+ static int DoServerHello(SSL* ssl, const byte* input, word32* inOutIdx)
+ {
+ byte b;
+ byte compression;
+ ProtocolVersion pv;
+ word32 i = *inOutIdx;
+
+#ifdef CYASSL_CALLBACKS
+ if (ssl->hsInfoOn) AddPacketName("ServerHello", &ssl->handShakeInfo);
+ if (ssl->toInfoOn) AddLateName("ServerHello", &ssl->timeoutInfo);
+#endif
+ XMEMCPY(&pv, input + i, sizeof(pv));
+ i += sizeof(pv);
+ XMEMCPY(ssl->arrays.serverRandom, input + i, RAN_LEN);
+ i += RAN_LEN;
+ b = input[i++];
+ if (b) {
+ XMEMCPY(ssl->arrays.sessionID, input + i, b);
+ i += b;
+ }
+ ssl->options.cipherSuite0 = input[i++];
+ ssl->options.cipherSuite = input[i++];
+ compression = input[i++];
+
+ if (compression != ZLIB_COMPRESSION && ssl->options.usingCompression)
+ ssl->options.usingCompression = 0; /* turn off if server refused */
+
+ ssl->options.serverState = SERVER_HELLO_COMPLETE;
+
+ *inOutIdx = i;
+
+ if (ssl->options.resuming) {
+ if (XMEMCMP(ssl->arrays.sessionID, ssl->session.sessionID, ID_LEN)
+ == 0) {
+ if (SetCipherSpecs(ssl) == 0) {
+ int ret;
+ XMEMCPY(ssl->arrays.masterSecret, ssl->session.masterSecret,
+ SECRET_LEN);
+ if (ssl->options.tls)
+ ret = DeriveTlsKeys(ssl);
+ else
+ ret = DeriveKeys(ssl);
+ ssl->options.serverState = SERVER_HELLODONE_COMPLETE;
+ return ret;
+ }
+ else
+ return UNSUPPORTED_SUITE;
+ }
+ else
+ ssl->options.resuming = 0; /* server denied resumption try */
+ }
+
+ return SetCipherSpecs(ssl);
+ }
+
+
+ /* just read in and ignore for now TODO: */
+ static int DoCertificateRequest(SSL* ssl, const byte* input, word32*
+ inOutIdx)
+ {
+ word16 len;
+
+ #ifdef CYASSL_CALLBACKS
+ if (ssl->hsInfoOn)
+ AddPacketName("CertificateRequest", &ssl->handShakeInfo);
+ if (ssl->toInfoOn)
+ AddLateName("CertificateRequest", &ssl->timeoutInfo);
+ #endif
+ len = input[(*inOutIdx)++];
+
+ /* types, read in here */
+ *inOutIdx += len;
+ ato16(&input[*inOutIdx], &len);
+ *inOutIdx += LENGTH_SZ;
+
+ if (IsAtLeastTLSv1_2(ssl)) {
+ /* hash sig format */
+ *inOutIdx += len;
+ ato16(&input[*inOutIdx], &len);
+ *inOutIdx += LENGTH_SZ;
+ }
+
+ /* authorities */
+ while (len) {
+ word16 dnSz;
+
+ ato16(&input[*inOutIdx], &dnSz);
+ *inOutIdx += (REQUEST_HEADER + dnSz);
+ len -= dnSz + REQUEST_HEADER;
+ }
+
+ /* don't send client cert or cert verify if user hasn't provided
+ cert and private key */
+ if (ssl->buffers.certificate.buffer && ssl->buffers.key.buffer)
+ ssl->options.sendVerify = SEND_CERT;
+ else if (IsAtLeastTLSv1_2(ssl))
+ ssl->options.sendVerify = SEND_BLANK_CERT;
+
+ return 0;
+ }
+
+
+ static int DoServerKeyExchange(SSL* ssl, const byte* input, word32*
+ inOutIdx)
+ {
+ word16 sigLen;
+ word16 verifySz;
+ word16 length;
+ byte* signature;
+
+ sigLen = 0;
+ signature = 0;
+
+ /* keep start idx */
+ verifySz = *inOutIdx;
+
+ #ifdef CYASSL_CALLBACKS
+ if (ssl->hsInfoOn)
+ AddPacketName("ServerKeyExchange", &ssl->handShakeInfo);
+ if (ssl->toInfoOn)
+ AddLateName("ServerKeyExchange", &ssl->timeoutInfo);
+ #endif
+
+ #ifndef NO_PSK
+ if (ssl->specs.kea == psk_kea) {
+ ato16(&input[*inOutIdx], &length);
+ *inOutIdx += LENGTH_SZ;
+ XMEMCPY(ssl->arrays.server_hint, &input[*inOutIdx],
+ min(length, MAX_PSK_ID_LEN));
+ if (length < MAX_PSK_ID_LEN)
+ ssl->arrays.server_hint[length] = 0;
+ else
+ ssl->arrays.server_hint[MAX_PSK_ID_LEN - 1] = 0;
+ *inOutIdx += length;
+
+ return 0;
+ }
+ #endif
+ #ifdef OPENSSL_EXTRA
+ if (ssl->specs.kea == diffie_hellman_kea)
+ {
+ /* p */
+ ato16(&input[*inOutIdx], &length);
+ *inOutIdx += LENGTH_SZ;
+
+ ssl->buffers.serverDH_P.buffer = (byte*) XMALLOC(length, ssl->heap,
+ DYNAMIC_TYPE_DH);
+ if (ssl->buffers.serverDH_P.buffer)
+ ssl->buffers.serverDH_P.length = length;
+ else
+ return MEMORY_ERROR;
+ XMEMCPY(ssl->buffers.serverDH_P.buffer, &input[*inOutIdx], length);
+ *inOutIdx += length;
+
+ /* g */
+ ato16(&input[*inOutIdx], &length);
+ *inOutIdx += LENGTH_SZ;
+
+ ssl->buffers.serverDH_G.buffer = (byte*) XMALLOC(length, ssl->heap,
+ DYNAMIC_TYPE_DH);
+ if (ssl->buffers.serverDH_G.buffer)
+ ssl->buffers.serverDH_G.length = length;
+ else
+ return MEMORY_ERROR;
+ XMEMCPY(ssl->buffers.serverDH_G.buffer, &input[*inOutIdx], length);
+ *inOutIdx += length;
+
+ /* pub */
+ ato16(&input[*inOutIdx], &length);
+ *inOutIdx += LENGTH_SZ;
+
+ ssl->buffers.serverDH_Pub.buffer = (byte*) XMALLOC(length, ssl->heap,
+ DYNAMIC_TYPE_DH);
+ if (ssl->buffers.serverDH_Pub.buffer)
+ ssl->buffers.serverDH_Pub.length = length;
+ else
+ return MEMORY_ERROR;
+ XMEMCPY(ssl->buffers.serverDH_Pub.buffer, &input[*inOutIdx], length);
+ *inOutIdx += length;
+ } /* dh_kea */
+ #endif /* OPENSSL_EXTRA */
+
+ #ifdef HAVE_ECC
+ if (ssl->specs.kea == ecc_diffie_hellman_kea)
+ {
+ byte b = input[*inOutIdx];
+ *inOutIdx += 1;
+
+ if (b != named_curve)
+ return ECC_CURVETYPE_ERROR;
+
+ *inOutIdx += 1; /* curve type, eat leading 0 */
+ b = input[*inOutIdx];
+ *inOutIdx += 1;
+
+ if (b != secp256r1 && b != secp384r1 && b != secp521r1 && b !=
+ secp160r1 && b != secp192r1 && b != secp224r1)
+ return ECC_CURVE_ERROR;
+
+ length = input[*inOutIdx];
+ *inOutIdx += 1;
+
+ if (ecc_import_x963(&input[*inOutIdx], length, &ssl->peerEccKey) != 0)
+ return ECC_PEERKEY_ERROR;
+
+ *inOutIdx += length;
+ ssl->peerEccKeyPresent = 1;
+ }
+ #endif /* HAVE_ECC */
+
+ #if defined(OPENSSL_EXTRA) || defined(HAVE_ECC)
+ {
+ Md5 md5;
+ Sha sha;
+ byte hash[FINISHED_SZ];
+ byte messageVerify[MAX_DH_SZ];
+
+ /* adjust from start idx */
+ verifySz = *inOutIdx - verifySz;
+
+ /* save message for hash verify */
+ if (verifySz > sizeof(messageVerify))
+ return BUFFER_ERROR;
+ XMEMCPY(messageVerify, &input[*inOutIdx - verifySz], verifySz);
+
+ if (IsAtLeastTLSv1_2(ssl)) {
+ /* just advance for now TODO: validate hash algo params */
+ *inOutIdx += LENGTH_SZ;
+ }
+
+ /* signature */
+ ato16(&input[*inOutIdx], &length);
+ *inOutIdx += LENGTH_SZ;
+
+ signature = (byte*)&input[*inOutIdx];
+ *inOutIdx += length;
+ sigLen = length;
+
+ /* verify signature */
+
+ /* md5 */
+ InitMd5(&md5);
+ Md5Update(&md5, ssl->arrays.clientRandom, RAN_LEN);
+ Md5Update(&md5, ssl->arrays.serverRandom, RAN_LEN);
+ Md5Update(&md5, messageVerify, verifySz);
+ Md5Final(&md5, hash);
+
+ /* sha */
+ InitSha(&sha);
+ ShaUpdate(&sha, ssl->arrays.clientRandom, RAN_LEN);
+ ShaUpdate(&sha, ssl->arrays.serverRandom, RAN_LEN);
+ ShaUpdate(&sha, messageVerify, verifySz);
+ ShaFinal(&sha, &hash[MD5_DIGEST_SIZE]);
+
+ /* rsa */
+ if (ssl->specs.sig_algo == rsa_sa_algo)
+ {
+ int ret;
+ byte* out;
+
+ if (!ssl->peerRsaKeyPresent)
+ return NO_PEER_KEY;
+
+ ret = RsaSSL_VerifyInline(signature, sigLen,&out, &ssl->peerRsaKey);
+
+ if (IsAtLeastTLSv1_2(ssl)) {
+ byte encodedSig[MAX_ENCODED_SIG_SZ];
+ word32 encSigSz;
+ byte* digest;
+ int hashType;
+ int digestSz;
+
+ /* sha1 for now */
+ digest = &hash[MD5_DIGEST_SIZE];
+ hashType = SHAh;
+ digestSz = SHA_DIGEST_SIZE;
+
+ encSigSz = EncodeSignature(encodedSig,digest,digestSz,hashType);
+
+ if (encSigSz != ret || XMEMCMP(out, encodedSig, encSigSz) != 0)
+ return VERIFY_SIGN_ERROR;
+ }
+ else {
+ if (ret != sizeof(hash) || XMEMCMP(out, hash, sizeof(hash)))
+ return VERIFY_SIGN_ERROR;
+ }
+ }
+#ifdef HAVE_ECC
+ /* ecdsa */
+ else if (ssl->specs.sig_algo == ecc_dsa_sa_algo) {
+ int verify = 0, ret;
+ if (!ssl->peerEccDsaKeyPresent)
+ return NO_PEER_KEY;
+
+ ret = ecc_verify_hash(signature, sigLen, &hash[MD5_DIGEST_SIZE],
+ SHA_DIGEST_SIZE, &verify, &ssl->peerEccDsaKey);
+ if (ret != 0 || verify == 0)
+ return VERIFY_SIGN_ERROR;
+ }
+#endif /* HAVE_ECC */
+ else
+ return -1;
+
+ ssl->options.serverState = SERVER_KEYEXCHANGE_COMPLETE;
+
+ return 0;
+
+ }
+#endif /* HAVE_OPENSSL or HAVE_ECC */
+ return -1; /* not supported by build */
+ }
+
+
+ int SendClientKeyExchange(SSL* ssl)
+ {
+ byte encSecret[MAX_NTRU_ENCRYPT_SZ];
+ word32 encSz = 0;
+ word32 idx = 0;
+ int ret = 0;
+
+ if (ssl->specs.kea == rsa_kea) {
+ RNG_GenerateBlock(&ssl->rng, ssl->arrays.preMasterSecret,
+ SECRET_LEN);
+ ssl->arrays.preMasterSecret[0] = ssl->chVersion.major;
+ ssl->arrays.preMasterSecret[1] = ssl->chVersion.minor;
+ ssl->arrays.preMasterSz = SECRET_LEN;
+
+ if (ssl->peerRsaKeyPresent == 0)
+ return NO_PEER_KEY;
+
+ ret = RsaPublicEncrypt(ssl->arrays.preMasterSecret, SECRET_LEN,
+ encSecret, sizeof(encSecret), &ssl->peerRsaKey,
+ &ssl->rng);
+ if (ret > 0) {
+ encSz = ret;
+ ret = 0; /* set success to 0 */
+ }
+ #ifdef OPENSSL_EXTRA
+ } else if (ssl->specs.kea == diffie_hellman_kea) {
+ buffer serverP = ssl->buffers.serverDH_P;
+ buffer serverG = ssl->buffers.serverDH_G;
+ buffer serverPub = ssl->buffers.serverDH_Pub;
+ byte priv[ENCRYPT_LEN];
+ word32 privSz;
+ DhKey key;
+
+ if (serverP.buffer == 0 || serverG.buffer == 0 ||
+ serverPub.buffer == 0)
+ return NO_PEER_KEY;
+
+ InitDhKey(&key);
+ ret = DhSetKey(&key, serverP.buffer, serverP.length,
+ serverG.buffer, serverG.length);
+ if (ret == 0)
+ /* for DH, encSecret is Yc, agree is pre-master */
+ ret = DhGenerateKeyPair(&key, &ssl->rng, priv, &privSz,
+ encSecret, &encSz);
+ if (ret == 0)
+ ret = DhAgree(&key, ssl->arrays.preMasterSecret,
+ &ssl->arrays.preMasterSz, priv, privSz,
+ serverPub.buffer, serverPub.length);
+ FreeDhKey(&key);
+ #endif /* OPENSSL_EXTRA */
+ #ifndef NO_PSK
+ } else if (ssl->specs.kea == psk_kea) {
+ byte* pms = ssl->arrays.preMasterSecret;
+
+ ssl->arrays.psk_keySz = ssl->options.client_psk_cb(ssl,
+ ssl->arrays.server_hint, ssl->arrays.client_identity,
+ MAX_PSK_ID_LEN, ssl->arrays.psk_key, MAX_PSK_KEY_LEN);
+ if (ssl->arrays.psk_keySz == 0 ||
+ ssl->arrays.psk_keySz > MAX_PSK_KEY_LEN)
+ return PSK_KEY_ERROR;
+ encSz = (word32)XSTRLEN(ssl->arrays.client_identity);
+ if (encSz > MAX_PSK_ID_LEN) return CLIENT_ID_ERROR;
+ XMEMCPY(encSecret, ssl->arrays.client_identity, encSz);
+
+ /* make psk pre master secret */
+ /* length of key + length 0s + length of key + key */
+ c16toa((word16)ssl->arrays.psk_keySz, pms);
+ pms += 2;
+ XMEMSET(pms, 0, ssl->arrays.psk_keySz);
+ pms += ssl->arrays.psk_keySz;
+ c16toa((word16)ssl->arrays.psk_keySz, pms);
+ pms += 2;
+ XMEMCPY(pms, ssl->arrays.psk_key, ssl->arrays.psk_keySz);
+ ssl->arrays.preMasterSz = ssl->arrays.psk_keySz * 2 + 4;
+ #endif /* NO_PSK */
+ #ifdef HAVE_NTRU
+ } else if (ssl->specs.kea == ntru_kea) {
+ word32 rc;
+ word16 cipherLen = sizeof(encSecret);
+ DRBG_HANDLE drbg;
+ static uint8_t const cyasslStr[] = {
+ 'C', 'y', 'a', 'S', 'S', 'L', ' ', 'N', 'T', 'R', 'U'
+ };
+
+ RNG_GenerateBlock(&ssl->rng, ssl->arrays.preMasterSecret,
+ SECRET_LEN);
+ ssl->arrays.preMasterSz = SECRET_LEN;
+
+ if (ssl->peerNtruKeyPresent == 0)
+ return NO_PEER_KEY;
+
+ rc = crypto_drbg_instantiate(MAX_NTRU_BITS, cyasslStr,
+ sizeof(cyasslStr), GetEntropy, &drbg);
+ if (rc != DRBG_OK)
+ return NTRU_DRBG_ERROR;
+
+ rc = crypto_ntru_encrypt(drbg, ssl->peerNtruKeyLen,ssl->peerNtruKey,
+ ssl->arrays.preMasterSz,
+ ssl->arrays.preMasterSecret,
+ &cipherLen, encSecret);
+ crypto_drbg_uninstantiate(drbg);
+ if (rc != NTRU_OK)
+ return NTRU_ENCRYPT_ERROR;
+
+ encSz = cipherLen;
+ ret = 0;
+ #endif /* HAVE_NTRU */
+ #ifdef HAVE_ECC
+ } else if (ssl->specs.kea == ecc_diffie_hellman_kea) {
+ ecc_key myKey;
+ word32 size = sizeof(encSecret);
+
+ if (!ssl->peerEccKeyPresent || !ssl->peerEccKey.dp)
+ return NO_PEER_KEY;
+
+ ecc_init(&myKey);
+ ret = ecc_make_key(&ssl->rng, ssl->peerEccKey.dp->size, &myKey);
+ if (ret != 0)
+ return ECC_MAKEKEY_ERROR;
+
+ /* precede export with 1 byte length */
+ ret = ecc_export_x963(&myKey, encSecret + 1, &size);
+ encSecret[0] = size;
+ encSz = size + 1;
+
+ if (ret != 0)
+ ret = ECC_EXPORT_ERROR;
+ else {
+ size = sizeof(ssl->arrays.preMasterSecret);
+ ret = ecc_shared_secret(&myKey, &ssl->peerEccKey,
+ ssl->arrays.preMasterSecret, &size);
+ if (ret != 0)
+ ret = ECC_SHARED_ERROR;
+ }
+
+ ssl->arrays.preMasterSz = size;
+ ecc_free(&myKey);
+ #endif /* HAVE_ECC */
+ } else
+ return -1; /* unsupported kea */
+
+ if (ret == 0) {
+ byte *output;
+ int sendSz;
+ word32 tlsSz = 0;
+
+ if (ssl->options.tls || ssl->specs.kea == diffie_hellman_kea)
+ tlsSz = 2;
+
+ if (ssl->specs.kea == ecc_diffie_hellman_kea) /* always off */
+ tlsSz = 0;
+
+ sendSz = encSz + tlsSz + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
+ idx = HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
+
+ #ifdef CYASSL_DTLS
+ if (ssl->options.dtls) {
+ sendSz += DTLS_HANDSHAKE_EXTRA + DTLS_RECORD_EXTRA;
+ idx += DTLS_HANDSHAKE_EXTRA + DTLS_RECORD_EXTRA;
+ }
+ #endif
+
+ /* check for avalaible size */
+ if ((ret = CheckAvalaibleSize(ssl, sendSz)) != 0)
+ return ret;
+
+ /* get ouput buffer */
+ output = ssl->buffers.outputBuffer.buffer +
+ ssl->buffers.outputBuffer.idx;
+
+ AddHeaders(output, encSz + tlsSz, client_key_exchange, ssl);
+
+ if (tlsSz) {
+ c16toa((word16)encSz, &output[idx]);
+ idx += 2;
+ }
+ XMEMCPY(output + idx, encSecret, encSz);
+ idx += encSz;
+
+ HashOutput(ssl, output, sendSz, 0);
+
+ #ifdef CYASSL_CALLBACKS
+ if (ssl->hsInfoOn)
+ AddPacketName("ClientKeyExchange", &ssl->handShakeInfo);
+ if (ssl->toInfoOn)
+ AddPacketInfo("ClientKeyExchange", &ssl->timeoutInfo,
+ output, sendSz, ssl->heap);
+ #endif
+
+ ssl->buffers.outputBuffer.length += sendSz;
+
+ ret = SendBuffered(ssl);
+ }
+
+ if (ret == 0 || ret == WANT_WRITE) {
+ int tmpRet = MakeMasterSecret(ssl);
+ if (tmpRet != 0)
+ ret = tmpRet; /* save WANT_WRITE unless more serious */
+ ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE;
+ }
+
+ return ret;
+ }
+
+ int SendCertificateVerify(SSL* ssl)
+ {
+ byte *output;
+ int sendSz = 0, length, ret;
+ word32 idx = 0;
+ RsaKey key;
+
+ if (ssl->options.sendVerify == SEND_BLANK_CERT)
+ return 0; /* sent blank cert, can't verify */
+
+ /* check for avalaible size */
+ if ((ret = CheckAvalaibleSize(ssl, MAX_CERT_VERIFY_SZ)) != 0)
+ return ret;
+
+ /* get ouput buffer */
+ output = ssl->buffers.outputBuffer.buffer +
+ ssl->buffers.outputBuffer.idx;
+
+ BuildCertHashes(ssl, &ssl->certHashes);
+
+ /* TODO: when add DSS support check here */
+ InitRsaKey(&key, ssl->heap);
+ ret = RsaPrivateKeyDecode(ssl->buffers.key.buffer, &idx, &key,
+ ssl->buffers.key.length);
+ if (ret == 0) {
+ byte* verify = (byte*)&output[RECORD_HEADER_SZ +
+ HANDSHAKE_HEADER_SZ];
+ byte* signBuffer = ssl->certHashes.md5;
+ word32 signSz = sizeof(Hashes);
+ byte encodedSig[MAX_ENCODED_SIG_SZ];
+ word32 extraSz = 0; /* tls 1.2 hash/sig */
+
+ #ifdef CYASSL_DTLS
+ if (ssl->options.dtls)
+ verify += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+ #endif
+ length = RsaEncryptSize(&key);
+ if (IsAtLeastTLSv1_2(ssl)) {
+ verify[0] = sha_mac;
+ verify[1] = rsa_sa_algo;
+ extraSz = HASH_SIG_SIZE;
+ }
+ c16toa((word16)length, verify + extraSz); /* prepend verify header*/
+
+ if (IsAtLeastTLSv1_2(ssl)) {
+ byte* digest;
+ int hashType;
+ int digestSz;
+
+ /* sha1 for now */
+ digest = ssl->certHashes.sha;
+ hashType = SHAh;
+ digestSz = SHA_DIGEST_SIZE;
+
+ signSz = EncodeSignature(encodedSig, digest, digestSz,hashType);
+ signBuffer = encodedSig;
+ }
+
+ ret = RsaSSL_Sign(signBuffer, signSz, verify + extraSz +
+ VERIFY_HEADER, ENCRYPT_LEN, &key, &ssl->rng);
+
+ if (ret > 0) {
+ ret = 0; /* reset */
+
+ AddHeaders(output, length + extraSz + VERIFY_HEADER,
+ certificate_verify, ssl);
+
+ sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ + length +
+ extraSz + VERIFY_HEADER;
+ #ifdef CYASSL_DTLS
+ if (ssl->options.dtls)
+ sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+ #endif
+ HashOutput(ssl, output, sendSz, 0);
+ }
+ }
+
+ FreeRsaKey(&key);
+
+ if (ret == 0) {
+ #ifdef CYASSL_CALLBACKS
+ if (ssl->hsInfoOn)
+ AddPacketName("CertificateVerify", &ssl->handShakeInfo);
+ if (ssl->toInfoOn)
+ AddPacketInfo("CertificateVerify", &ssl->timeoutInfo,
+ output, sendSz, ssl->heap);
+ #endif
+ ssl->buffers.outputBuffer.length += sendSz;
+ return SendBuffered(ssl);
+ }
+ else
+ return ret;
+ }
+
+
+
+#endif /* NO_CYASSL_CLIENT */
+
+
+#ifndef NO_CYASSL_SERVER
+
+ int SendServerHello(SSL* ssl)
+ {
+ byte *output;
+ word32 length, idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+ int sendSz;
+ int ret;
+
+ length = sizeof(ProtocolVersion) + RAN_LEN
+ + ID_LEN + ENUM_LEN
+ + SUITE_LEN
+ + ENUM_LEN;
+
+ /* check for avalaible size */
+ if ((ret = CheckAvalaibleSize(ssl, MAX_HELLO_SZ)) != 0)
+ return ret;
+
+ /* get ouput buffer */
+ output = ssl->buffers.outputBuffer.buffer +
+ ssl->buffers.outputBuffer.idx;
+
+ sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
+ AddHeaders(output, length, server_hello, ssl);
+
+ #ifdef CYASSL_DTLS
+ if (ssl->options.dtls) {
+ idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+ sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+ }
+ #endif
+ /* now write to output */
+ /* first version */
+ XMEMCPY(output + idx, &ssl->version, sizeof(ProtocolVersion));
+ idx += sizeof(ProtocolVersion);
+
+ /* then random */
+ if (!ssl->options.resuming)
+ RNG_GenerateBlock(&ssl->rng, ssl->arrays.serverRandom, RAN_LEN);
+ XMEMCPY(output + idx, ssl->arrays.serverRandom, RAN_LEN);
+ idx += RAN_LEN;
+
+#ifdef SHOW_SECRETS
+ {
+ int j;
+ printf("server random: ");
+ for (j = 0; j < RAN_LEN; j++)
+ printf("%02x", ssl->arrays.serverRandom[j]);
+ printf("\n");
+ }
+#endif
+ /* then session id */
+ output[idx++] = ID_LEN;
+ if (!ssl->options.resuming)
+ RNG_GenerateBlock(&ssl->rng, ssl->arrays.sessionID, ID_LEN);
+ XMEMCPY(output + idx, ssl->arrays.sessionID, ID_LEN);
+ idx += ID_LEN;
+
+ /* then cipher suite */
+ output[idx++] = ssl->options.cipherSuite0;
+ output[idx++] = ssl->options.cipherSuite;
+
+ /* last, compression */
+ if (ssl->options.usingCompression)
+ output[idx++] = ZLIB_COMPRESSION;
+ else
+ output[idx++] = NO_COMPRESSION;
+
+ ssl->buffers.outputBuffer.length += sendSz;
+ HashOutput(ssl, output, sendSz, 0);
+
+ #ifdef CYASSL_CALLBACKS
+ if (ssl->hsInfoOn)
+ AddPacketName("ServerHello", &ssl->handShakeInfo);
+ if (ssl->toInfoOn)
+ AddPacketInfo("ServerHello", &ssl->timeoutInfo, output, sendSz,
+ ssl->heap);
+ #endif
+
+ ssl->options.serverState = SERVER_HELLO_COMPLETE;
+
+ return SendBuffered(ssl);
+ }
+
+
+#ifdef HAVE_ECC
+
+ byte SetCurveId(int size)
+ {
+ switch(size) {
+ case 20:
+ return secp160r1;
+ break;
+ case 24:
+ return secp192r1;
+ break;
+ case 28:
+ return secp224r1;
+ break;
+ case 32:
+ return secp256r1;
+ break;
+ case 48:
+ return secp384r1;
+ break;
+ case 66:
+ return secp521r1;
+ break;
+ default:
+ return 0;
+ }
+ }
+
+#endif /* HAVE_ECC */
+
+
+ int SendServerKeyExchange(SSL* ssl)
+ {
+ int ret = 0;
+
+ #ifndef NO_PSK
+ if (ssl->specs.kea == psk_kea)
+ {
+ byte *output;
+ word32 length, idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+ int sendSz;
+ if (ssl->arrays.server_hint[0] == 0) return 0; /* don't send */
+
+ /* include size part */
+ length = (word32)XSTRLEN(ssl->arrays.server_hint);
+ if (length > MAX_PSK_ID_LEN) return SERVER_HINT_ERROR;
+ length += HINT_LEN_SZ;
+ sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
+
+ #ifdef CYASSL_DTLS
+ if (ssl->options.dtls) {
+ sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+ idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+ }
+ #endif
+ /* check for avalaible size */
+ if ((ret = CheckAvalaibleSize(ssl, sendSz)) != 0)
+ return ret;
+
+ /* get ouput buffer */
+ output = ssl->buffers.outputBuffer.buffer +
+ ssl->buffers.outputBuffer.idx;
+
+ AddHeaders(output, length, server_key_exchange, ssl);
+
+ /* key data */
+ c16toa((word16)(length - HINT_LEN_SZ), output + idx);
+ idx += HINT_LEN_SZ;
+ XMEMCPY(output + idx, ssl->arrays.server_hint, length -HINT_LEN_SZ);
+
+ HashOutput(ssl, output, sendSz, 0);
+
+ #ifdef CYASSL_CALLBACKS
+ if (ssl->hsInfoOn)
+ AddPacketName("ServerKeyExchange", &ssl->handShakeInfo);
+ if (ssl->toInfoOn)
+ AddPacketInfo("ServerKeyExchange", &ssl->timeoutInfo,
+ output, sendSz, ssl->heap);
+ #endif
+
+ ssl->buffers.outputBuffer.length += sendSz;
+ ret = SendBuffered(ssl);
+ ssl->options.serverState = SERVER_KEYEXCHANGE_COMPLETE;
+ }
+ #endif /*NO_PSK */
+
+ #ifdef HAVE_ECC
+ if (ssl->specs.kea == ecc_diffie_hellman_kea)
+ {
+ byte *output;
+ word32 length, idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+ int sendSz;
+ byte export[MAX_EXPORT_ECC_SZ];
+ word32 expSz = sizeof(export);
+ word32 sigSz;
+ word32 preSigSz, preSigIdx;
+ RsaKey rsaKey;
+ ecc_key dsaKey;
+
+ /* curve type, named curve, length(1) */
+ length = ENUM_LEN + CURVE_LEN + ENUM_LEN;
+ /* pub key size */
+ if (ecc_export_x963(&ssl->eccTempKey, export, &expSz) != 0)
+ return ECC_EXPORT_ERROR;
+ length += expSz;
+
+ preSigSz = length;
+ preSigIdx = idx;
+
+ InitRsaKey(&rsaKey, ssl->heap);
+ ecc_init(&dsaKey);
+
+ /* sig length */
+ length += LENGTH_SZ;
+
+ if (!ssl->buffers.key.buffer) {
+ FreeRsaKey(&rsaKey);
+ ecc_free(&dsaKey);
+ return NO_PRIVATE_KEY;
+ }
+
+ if (ssl->specs.sig_algo == rsa_sa_algo) {
+ /* rsa sig size */
+ word32 i = 0;
+ ret = RsaPrivateKeyDecode(ssl->buffers.key.buffer, &i,
+ &rsaKey, ssl->buffers.key.length);
+ if (ret != 0) return ret;
+ sigSz = RsaEncryptSize(&rsaKey);
+ }
+ else if (ssl->specs.sig_algo == ecc_dsa_sa_algo) {
+ /* ecdsa sig size */
+ word32 i = 0;
+ ret = EccPrivateKeyDecode(ssl->buffers.key.buffer, &i,
+ &dsaKey, ssl->buffers.key.length);
+ if (ret != 0) return ret;
+ sigSz = ecc_sig_size(&dsaKey);
+ }
+ else {
+ FreeRsaKey(&rsaKey);
+ ecc_free(&dsaKey);
+ return -1; /* unsupported type */
+ }
+ length += sigSz;
+
+ if (IsAtLeastTLSv1_2(ssl))
+ length += HASH_SIG_SIZE;
+
+ sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
+
+ #ifdef CYASSL_DTLS
+ if (ssl->options.dtls) {
+ sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+ idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+ }
+ #endif
+ /* check for avalaible size */
+ if ((ret = CheckAvalaibleSize(ssl, sendSz)) != 0) {
+ FreeRsaKey(&rsaKey);
+ ecc_free(&dsaKey);
+ return ret;
+ }
+
+ /* get ouput buffer */
+ output = ssl->buffers.outputBuffer.buffer +
+ ssl->buffers.outputBuffer.idx;
+
+ AddHeaders(output, length, server_key_exchange, ssl);
+
+ /* key exchange data */
+ output[idx++] = named_curve;
+ output[idx++] = 0x00; /* leading zero */
+ output[idx++] = SetCurveId(ecc_size(&ssl->eccTempKey));
+ output[idx++] = expSz;
+ XMEMCPY(output + idx, export, expSz);
+ idx += expSz;
+ if (IsAtLeastTLSv1_2(ssl)) {
+ output[idx++] = sha_mac;
+ output[idx++] = ssl->specs.sig_algo;
+ }
+ c16toa(sigSz, output + idx);
+ idx += LENGTH_SZ;
+
+ /* do signature */
+ {
+ Md5 md5;
+ Sha sha;
+ byte hash[FINISHED_SZ];
+ byte* signBuffer = hash;
+ word32 signSz = sizeof(hash);
+
+ /* md5 */
+ InitMd5(&md5);
+ Md5Update(&md5, ssl->arrays.clientRandom, RAN_LEN);
+ Md5Update(&md5, ssl->arrays.serverRandom, RAN_LEN);
+ Md5Update(&md5, output + preSigIdx, preSigSz);
+ Md5Final(&md5, hash);
+
+ /* sha */
+ InitSha(&sha);
+ ShaUpdate(&sha, ssl->arrays.clientRandom, RAN_LEN);
+ ShaUpdate(&sha, ssl->arrays.serverRandom, RAN_LEN);
+ ShaUpdate(&sha, output + preSigIdx, preSigSz);
+ ShaFinal(&sha, &hash[MD5_DIGEST_SIZE]);
+
+ if (ssl->specs.sig_algo == rsa_sa_algo) {
+ byte encodedSig[MAX_ENCODED_SIG_SZ];
+ if (IsAtLeastTLSv1_2(ssl)) {
+ byte* digest;
+ int hashType;
+ int digestSz;
+
+ /* sha1 for now */
+ digest = &hash[MD5_DIGEST_SIZE];
+ hashType = SHAh;
+ digestSz = SHA_DIGEST_SIZE;
+
+ signSz = EncodeSignature(encodedSig, digest, digestSz,
+ hashType);
+ signBuffer = encodedSig;
+ }
+ ret = RsaSSL_Sign(signBuffer, signSz, output + idx, sigSz,
+ &rsaKey, &ssl->rng);
+ FreeRsaKey(&rsaKey);
+ if (ret > 0)
+ ret = 0; /* reset on success */
+ else
+ return ret;
+ }
+ else if (ssl->specs.sig_algo == ecc_dsa_sa_algo) {
+ word32 sz = sigSz;
+
+ FreeRsaKey(&rsaKey);
+ ret = ecc_sign_hash(&hash[MD5_DIGEST_SIZE], SHA_DIGEST_SIZE,
+ output + idx, &sz, &ssl->rng, &dsaKey);
+ }
+ }
+
+ HashOutput(ssl, output, sendSz, 0);
+
+ #ifdef CYASSL_CALLBACKS
+ if (ssl->hsInfoOn)
+ AddPacketName("ServerKeyExchange", &ssl->handShakeInfo);
+ if (ssl->toInfoOn)
+ AddPacketInfo("ServerKeyExchange", &ssl->timeoutInfo,
+ output, sendSz, ssl->heap);
+ #endif
+
+ ssl->buffers.outputBuffer.length += sendSz;
+ ret = SendBuffered(ssl);
+ ssl->options.serverState = SERVER_KEYEXCHANGE_COMPLETE;
+ }
+ #endif /* HAVE_ECC */
+
+ return ret;
+ }
+
+
+ static int MatchSuite(SSL* ssl, Suites* peerSuites)
+ {
+ word16 i, j;
+
+ /* & 0x1 equivalent % 2 */
+ if (peerSuites->suiteSz == 0 || peerSuites->suiteSz & 0x1)
+ return MATCH_SUITE_ERROR;
+
+ /* start with best, if a match we are good */
+ for (i = 0; i < ssl->suites.suiteSz; i += 2)
+ for (j = 0; j < peerSuites->suiteSz; j += 2)
+ if (ssl->suites.suites[i] == peerSuites->suites[j] &&
+ ssl->suites.suites[i+1] == peerSuites->suites[j+1] ) {
+
+ ssl->options.cipherSuite0 = ssl->suites.suites[i];
+ ssl->options.cipherSuite = ssl->suites.suites[i+1];
+ return SetCipherSpecs(ssl);
+ }
+
+ return MATCH_SUITE_ERROR;
+ }
+
+
+ /* process alert, return level */
+ int ProcessOldClientHello(SSL* ssl, const byte* input, word32* inOutIdx,
+ word32 inSz, word16 sz)
+ {
+ word32 idx = *inOutIdx;
+ word16 sessionSz;
+ word16 randomSz;
+ word16 i, j;
+ ProtocolVersion pv;
+ Suites clSuites;
+
+#ifdef CYASSL_CALLBACKS
+ if (ssl->hsInfoOn)
+ AddPacketName("ClientHello", &ssl->handShakeInfo);
+ if (ssl->toInfoOn)
+ AddLateName("ClientHello", &ssl->timeoutInfo);
+#endif
+
+ /* manually hash input since different format */
+ Md5Update(&ssl->hashMd5, input + idx, sz);
+ ShaUpdate(&ssl->hashSha, input + idx, sz);
+#ifndef NO_SHA256
+ if (IsAtLeastTLSv1_2(ssl))
+ Sha256Update(&ssl->hashSha256, input + idx, sz);
+#endif
+
+ /* does this value mean client_hello? */
+ idx++;
+
+ /* version */
+ pv.major = input[idx++];
+ pv.minor = input[idx++];
+ ssl->chVersion = pv; /* store */
+
+ if (ssl->version.minor > 0 && pv.minor == 0) {
+ if (!ssl->options.downgrade)
+ return VERSION_ERROR;
+ /* turn off tls */
+ ssl->options.tls = 0;
+ ssl->options.tls1_1 = 0;
+ ssl->version.minor = 0;
+ InitSuites(&ssl->suites, ssl->version, ssl->options.haveDH, FALSE,
+ ssl->options.haveNTRU, ssl->options.haveECDSA,
+ ssl->ctx->method->side);
+ }
+
+ /* suite size */
+ ato16(&input[idx], &clSuites.suiteSz);
+ idx += 2;
+
+ if (clSuites.suiteSz > MAX_SUITE_SZ)
+ return BUFFER_ERROR;
+
+ /* session size */
+ ato16(&input[idx], &sessionSz);
+ idx += 2;
+
+ if (sessionSz > ID_LEN)
+ return BUFFER_ERROR;
+
+ /* random size */
+ ato16(&input[idx], &randomSz);
+ idx += 2;
+
+ if (randomSz > RAN_LEN)
+ return BUFFER_ERROR;
+
+ /* suites */
+ for (i = 0, j = 0; i < clSuites.suiteSz; i += 3) {
+ byte first = input[idx++];
+ if (!first) { /* implicit: skip sslv2 type */
+ XMEMCPY(&clSuites.suites[j], &input[idx], 2);
+ j += 2;
+ }
+ idx += 2;
+ }
+ clSuites.suiteSz = j;
+
+ /* session id */
+ if (sessionSz) {
+ XMEMCPY(ssl->arrays.sessionID, input + idx, sessionSz);
+ idx += sessionSz;
+ ssl->options.resuming = 1;
+ }
+
+ /* random */
+ if (randomSz < RAN_LEN)
+ XMEMSET(ssl->arrays.clientRandom, 0, RAN_LEN - randomSz);
+ XMEMCPY(&ssl->arrays.clientRandom[RAN_LEN - randomSz], input + idx,
+ randomSz);
+ idx += randomSz;
+
+ if (ssl->options.usingCompression)
+ ssl->options.usingCompression = 0; /* turn off */
+
+ ssl->options.clientState = CLIENT_HELLO_COMPLETE;
+ *inOutIdx = idx;
+
+ /* DoClientHello uses same resume code */
+ while (ssl->options.resuming) { /* let's try */
+ int ret;
+ SSL_SESSION* session = GetSession(ssl, ssl->arrays.masterSecret);
+ if (!session) {
+ ssl->options.resuming = 0;
+ break; /* session lookup failed */
+ }
+ if (MatchSuite(ssl, &clSuites) < 0)
+ return UNSUPPORTED_SUITE;
+
+ RNG_GenerateBlock(&ssl->rng, ssl->arrays.serverRandom, RAN_LEN);
+ if (ssl->options.tls)
+ ret = DeriveTlsKeys(ssl);
+ else
+ ret = DeriveKeys(ssl);
+ ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE;
+
+ return ret;
+ }
+
+ return MatchSuite(ssl, &clSuites);
+ }
+
+
+ static int DoClientHello(SSL* ssl, const byte* input, word32* inOutIdx,
+ word32 totalSz, word32 helloSz)
+ {
+ byte b;
+ ProtocolVersion pv;
+ Suites clSuites;
+ word32 i = *inOutIdx;
+ word32 begin = i;
+
+#ifdef CYASSL_CALLBACKS
+ if (ssl->hsInfoOn) AddPacketName("ClientHello", &ssl->handShakeInfo);
+ if (ssl->toInfoOn) AddLateName("ClientHello", &ssl->timeoutInfo);
+#endif
+ /* make sure can read up to session */
+ if (i + sizeof(pv) + RAN_LEN + ENUM_LEN > totalSz)
+ return INCOMPLETE_DATA;
+
+ XMEMCPY(&pv, input + i, sizeof(pv));
+ ssl->chVersion = pv; /* store */
+ i += sizeof(pv);
+ if (ssl->version.minor > 0 && pv.minor == 0) {
+ if (!ssl->options.downgrade)
+ return VERSION_ERROR;
+ /* turn off tls */
+ ssl->options.tls = 0;
+ ssl->options.tls1_1 = 0;
+ ssl->version.minor = 0;
+ InitSuites(&ssl->suites, ssl->version, ssl->options.haveDH, FALSE,
+ ssl->options.haveNTRU, ssl->options.haveECDSA,
+ ssl->ctx->method->side);
+ }
+ /* random */
+ XMEMCPY(ssl->arrays.clientRandom, input + i, RAN_LEN);
+ i += RAN_LEN;
+
+#ifdef SHOW_SECRETS
+ {
+ int j;
+ printf("client random: ");
+ for (j = 0; j < RAN_LEN; j++)
+ printf("%02x", ssl->arrays.clientRandom[j]);
+ printf("\n");
+ }
+#endif
+ /* session id */
+ b = input[i++];
+ if (b) {
+ if (i + ID_LEN > totalSz)
+ return INCOMPLETE_DATA;
+ XMEMCPY(ssl->arrays.sessionID, input + i, ID_LEN);
+ i += b;
+ ssl->options.resuming= 1; /* client wants to resume */
+ }
+
+ #ifdef CYASSL_DTLS
+ /* cookie */
+ if (ssl->options.dtls) {
+ b = input[i++];
+ if (b) {
+ if (b > MAX_COOKIE_LEN)
+ return BUFFER_ERROR;
+ if (i + b > totalSz)
+ return INCOMPLETE_DATA;
+ XMEMCPY(ssl->arrays.cookie, input + i, b);
+ i += b;
+ }
+ }
+ #endif
+
+ if (i + LENGTH_SZ > totalSz)
+ return INCOMPLETE_DATA;
+ /* suites */
+ ato16(&input[i], &clSuites.suiteSz);
+ i += 2;
+
+ /* suites and comp len */
+ if (i + clSuites.suiteSz + ENUM_LEN > totalSz)
+ return INCOMPLETE_DATA;
+ if (clSuites.suiteSz > MAX_SUITE_SZ)
+ return BUFFER_ERROR;
+ XMEMCPY(clSuites.suites, input + i, clSuites.suiteSz);
+ i += clSuites.suiteSz;
+
+ b = input[i++]; /* comp len */
+ if (i + b > totalSz)
+ return INCOMPLETE_DATA;
+
+ if (ssl->options.usingCompression) {
+ int match = 0;
+ while (b--) {
+ byte comp = input[i++];
+ if (comp == ZLIB_COMPRESSION)
+ match = 1;
+ }
+ if (!match)
+ ssl->options.usingCompression = 0; /* turn off */
+ }
+ else
+ i += b; /* ignore, since we're not on */
+
+ ssl->options.clientState = CLIENT_HELLO_COMPLETE;
+
+ *inOutIdx = i;
+ if ( (i - begin) < helloSz)
+ *inOutIdx = begin + helloSz; /* skip extensions */
+
+ /* ProcessOld uses same resume code */
+ while (ssl->options.resuming) { /* let's try */
+ int ret;
+ SSL_SESSION* session = GetSession(ssl, ssl->arrays.masterSecret);
+ if (!session) {
+ ssl->options.resuming = 0;
+ break; /* session lookup failed */
+ }
+ if (MatchSuite(ssl, &clSuites) < 0)
+ return UNSUPPORTED_SUITE;
+
+ RNG_GenerateBlock(&ssl->rng, ssl->arrays.serverRandom, RAN_LEN);
+ if (ssl->options.tls)
+ ret = DeriveTlsKeys(ssl);
+ else
+ ret = DeriveKeys(ssl);
+ ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE;
+
+ return ret;
+ }
+ return MatchSuite(ssl, &clSuites);
+ }
+
+
+ static int DoCertificateVerify(SSL* ssl, byte* input, word32* inOutsz,
+ word32 totalSz)
+ {
+ word16 sz = 0;
+ word32 i = *inOutsz;
+ int ret = VERIFY_CERT_ERROR; /* start in error state */
+ byte* sig;
+ byte* out;
+ int outLen;
+
+ #ifdef CYASSL_CALLBACKS
+ if (ssl->hsInfoOn)
+ AddPacketName("CertificateVerify", &ssl->handShakeInfo);
+ if (ssl->toInfoOn)
+ AddLateName("CertificateVerify", &ssl->timeoutInfo);
+ #endif
+ if ( (i + VERIFY_HEADER) > totalSz)
+ return INCOMPLETE_DATA;
+
+ if (IsAtLeastTLSv1_2(ssl))
+ i += HASH_SIG_SIZE;
+ ato16(&input[i], &sz);
+ i += VERIFY_HEADER;
+
+ if ( (i + sz) > totalSz)
+ return INCOMPLETE_DATA;
+
+ if (sz > ENCRYPT_LEN)
+ return BUFFER_ERROR;
+
+ sig = &input[i];
+ *inOutsz = i + sz;
+ /* TODO: when add DSS support check here */
+ if (ssl->peerRsaKeyPresent != 0) {
+ outLen = RsaSSL_VerifyInline(sig, sz, &out, &ssl->peerRsaKey);
+
+ if (IsAtLeastTLSv1_2(ssl)) {
+ byte encodedSig[MAX_ENCODED_SIG_SZ];
+ word32 sigSz;
+ byte* digest;
+ int hashType;
+ int digestSz;
+
+ /* sha1 for now */
+ digest = ssl->certHashes.sha;
+ hashType = SHAh;
+ digestSz = SHA_DIGEST_SIZE;
+
+ sigSz = EncodeSignature(encodedSig, digest, digestSz, hashType);
+
+ if (outLen == sigSz && XMEMCMP(out, encodedSig, sigSz) == 0)
+ ret = 0;
+ }
+ else {
+ if (outLen == sizeof(ssl->certHashes) && XMEMCMP(out,
+ ssl->certHashes.md5, sizeof(ssl->certHashes)) == 0)
+ ret = 0;
+ }
+ }
+ return ret;
+ }
+
+
+ int SendServerHelloDone(SSL* ssl)
+ {
+ byte *output;
+ int sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+ int ret;
+
+ #ifdef CYASSL_DTLS
+ if (ssl->options.dtls)
+ sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+ #endif
+ /* check for avalaible size */
+ if ((ret = CheckAvalaibleSize(ssl, sendSz)) != 0)
+ return ret;
+
+ /* get ouput buffer */
+ output = ssl->buffers.outputBuffer.buffer +
+ ssl->buffers.outputBuffer.idx;
+
+ AddHeaders(output, 0, server_hello_done, ssl);
+
+ HashOutput(ssl, output, sendSz, 0);
+#ifdef CYASSL_CALLBACKS
+ if (ssl->hsInfoOn)
+ AddPacketName("ServerHelloDone", &ssl->handShakeInfo);
+ if (ssl->toInfoOn)
+ AddPacketInfo("ServerHelloDone", &ssl->timeoutInfo, output, sendSz,
+ ssl->heap);
+#endif
+ ssl->options.serverState = SERVER_HELLODONE_COMPLETE;
+
+ ssl->buffers.outputBuffer.length += sendSz;
+
+ return SendBuffered(ssl);
+ }
+
+
+ int SendHelloVerifyRequest(SSL* ssl)
+ {
+ byte* output;
+ int length = VERSION_SZ + ENUM_LEN;
+ int idx = DTLS_RECORD_HEADER_SZ + DTLS_HANDSHAKE_HEADER_SZ;
+ int sendSz = length + idx;
+ int ret;
+
+ /* check for avalaible size */
+ if ((ret = CheckAvalaibleSize(ssl, sendSz)) != 0)
+ return ret;
+
+ /* get ouput buffer */
+ output = ssl->buffers.outputBuffer.buffer +
+ ssl->buffers.outputBuffer.idx;
+
+ AddHeaders(output, length, hello_verify_request, ssl);
+
+ XMEMCPY(output + idx, &ssl->chVersion, VERSION_SZ);
+ idx += VERSION_SZ;
+ output[idx++] = 0; /* no cookie for now */
+
+ HashOutput(ssl, output, sendSz, 0);
+#ifdef CYASSL_CALLBACKS
+ if (ssl->hsInfoOn)
+ AddPacketName("HelloVerifyRequest", &ssl->handShakeInfo);
+ if (ssl->toInfoOn)
+ AddPacketInfo("HelloVerifyRequest", &ssl->timeoutInfo, output,
+ sendSz, ssl->heap);
+#endif
+ ssl->options.serverState = SERVER_HELLOVERIFYREQUEST_COMPLETE;
+
+ ssl->buffers.outputBuffer.length += sendSz;
+
+ return SendBuffered(ssl);
+ }
+
+
+ static int DoClientKeyExchange(SSL* ssl, byte* input,
+ word32* inOutIdx)
+ {
+ int ret = 0;
+ word32 length = 0;
+ byte* out;
+
+ if (ssl->options.verifyPeer && ssl->options.failNoCert)
+ if (!ssl->options.havePeerCert) {
+ CYASSL_MSG("client didn't present peer cert");
+ return NO_PEER_CERT;
+ }
+
+ #ifdef CYASSL_CALLBACKS
+ if (ssl->hsInfoOn)
+ AddPacketName("ClientKeyExchange", &ssl->handShakeInfo);
+ if (ssl->toInfoOn)
+ AddLateName("ClientKeyExchange", &ssl->timeoutInfo);
+ #endif
+ if (ssl->specs.kea == rsa_kea) {
+ word32 idx = 0;
+ RsaKey key;
+ byte* tmp = 0;
+
+ InitRsaKey(&key, ssl->heap);
+
+ if (ssl->buffers.key.buffer)
+ ret = RsaPrivateKeyDecode(ssl->buffers.key.buffer, &idx, &key,
+ ssl->buffers.key.length);
+ else
+ return NO_PRIVATE_KEY;
+
+ if (ret == 0) {
+ length = RsaEncryptSize(&key);
+ ssl->arrays.preMasterSz = SECRET_LEN;
+
+ if (ssl->options.tls)
+ (*inOutIdx) += 2;
+ tmp = input + *inOutIdx;
+ *inOutIdx += length;
+
+ if (RsaPrivateDecryptInline(tmp, length, &out, &key) ==
+ SECRET_LEN) {
+ XMEMCPY(ssl->arrays.preMasterSecret, out, SECRET_LEN);
+ if (ssl->arrays.preMasterSecret[0] != ssl->chVersion.major
+ ||
+ ssl->arrays.preMasterSecret[1] != ssl->chVersion.minor)
+
+ ret = PMS_VERSION_ERROR;
+ else
+ ret = MakeMasterSecret(ssl);
+ }
+ else
+ ret = RSA_PRIVATE_ERROR;
+ }
+
+ FreeRsaKey(&key);
+#ifndef NO_PSK
+ } else if (ssl->specs.kea == psk_kea) {
+ byte* pms = ssl->arrays.preMasterSecret;
+ word16 ci_sz;
+
+ ato16(&input[*inOutIdx], &ci_sz);
+ *inOutIdx += LENGTH_SZ;
+ if (ci_sz > MAX_PSK_ID_LEN) return CLIENT_ID_ERROR;
+
+ XMEMCPY(ssl->arrays.client_identity, &input[*inOutIdx], ci_sz);
+ *inOutIdx += ci_sz;
+ ssl->arrays.client_identity[ci_sz] = 0;
+
+ ssl->arrays.psk_keySz = ssl->options.server_psk_cb(ssl,
+ ssl->arrays.client_identity, ssl->arrays.psk_key,
+ MAX_PSK_KEY_LEN);
+ if (ssl->arrays.psk_keySz == 0 ||
+ ssl->arrays.psk_keySz > MAX_PSK_KEY_LEN) return PSK_KEY_ERROR;
+
+ /* make psk pre master secret */
+ /* length of key + length 0s + length of key + key */
+ c16toa((word16)ssl->arrays.psk_keySz, pms);
+ pms += 2;
+ XMEMSET(pms, 0, ssl->arrays.psk_keySz);
+ pms += ssl->arrays.psk_keySz;
+ c16toa((word16)ssl->arrays.psk_keySz, pms);
+ pms += 2;
+ XMEMCPY(pms, ssl->arrays.psk_key, ssl->arrays.psk_keySz);
+ ssl->arrays.preMasterSz = ssl->arrays.psk_keySz * 2 + 4;
+
+ ret = MakeMasterSecret(ssl);
+#endif /* NO_PSK */
+#ifdef HAVE_NTRU
+ } else if (ssl->specs.kea == ntru_kea) {
+ word32 rc;
+ word16 cipherLen;
+ word16 plainLen = sizeof(ssl->arrays.preMasterSecret);
+ byte* tmp;
+
+ if (!ssl->buffers.key.buffer)
+ return NO_PRIVATE_KEY;
+
+ ato16(&input[*inOutIdx], &cipherLen);
+ *inOutIdx += LENGTH_SZ;
+ if (cipherLen > MAX_NTRU_ENCRYPT_SZ)
+ return NTRU_KEY_ERROR;
+
+ tmp = input + *inOutIdx;
+ rc = crypto_ntru_decrypt((word16)ssl->buffers.key.length,
+ ssl->buffers.key.buffer, cipherLen, tmp, &plainLen,
+ ssl->arrays.preMasterSecret);
+
+ if (rc != NTRU_OK || plainLen != SECRET_LEN)
+ return NTRU_DECRYPT_ERROR;
+ *inOutIdx += cipherLen;
+
+ ssl->arrays.preMasterSz = plainLen;
+ ret = MakeMasterSecret(ssl);
+#endif /* HAVE_NTRU */
+#ifdef HAVE_ECC
+ } else if (ssl->specs.kea == ecc_diffie_hellman_kea) {
+ word32 size;
+ word32 length = input[*inOutIdx]; /* one byte length */
+ *inOutIdx += 1;
+
+ ret = ecc_import_x963(&input[*inOutIdx], length, &ssl->peerEccKey);
+ if (ret != 0)
+ return ECC_PEERKEY_ERROR;
+ *inOutIdx += length;
+ ssl->peerEccKeyPresent = 1;
+
+ size = sizeof(ssl->arrays.preMasterSecret);
+ ret = ecc_shared_secret(&ssl->eccTempKey, &ssl->peerEccKey,
+ ssl->arrays.preMasterSecret, &size);
+ if (ret != 0)
+ return ECC_SHARED_ERROR;
+ ssl->arrays.preMasterSz = size;
+ ret = MakeMasterSecret(ssl);
+#endif /* HAVE_ECC */
+ }
+
+ if (ret == 0) {
+ ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE;
+ if (ssl->options.verifyPeer)
+ BuildCertHashes(ssl, &ssl->certHashes);
+ }
+
+ return ret;
+ }
+
+#endif /* NO_CYASSL_SERVER */
+
+
+#ifdef SINGLE_THREADED
+
+int InitMutex(CyaSSL_Mutex* m)
+{
+ return 0;
+}
+
+
+int FreeMutex(CyaSSL_Mutex* m)
+{
+ return 0;
+}
+
+
+int LockMutex(CyaSSL_Mutex* m)
+{
+ return 0;
+}
+
+
+int UnLockMutex(CyaSSL_Mutex* m)
+{
+ return 0;
+}
+
+#else /* MULTI_THREAD */
+
+ #ifdef USE_WINDOWS_API
+
+ int InitMutex(CyaSSL_Mutex* m)
+ {
+ InitializeCriticalSection(m);
+ return 0;
+ }
+
+
+ int FreeMutex(CyaSSL_Mutex* m)
+ {
+ DeleteCriticalSection(m);
+ return 0;
+ }
+
+
+ int LockMutex(CyaSSL_Mutex* m)
+ {
+ EnterCriticalSection(m);
+ return 0;
+ }
+
+
+ int UnLockMutex(CyaSSL_Mutex* m)
+ {
+ LeaveCriticalSection(m);
+ return 0;
+ }
+
+ #elif defined(CYASSL_PTHREADS)
+
+ int InitMutex(CyaSSL_Mutex* m)
+ {
+ if (pthread_mutex_init(m, 0) == 0)
+ return 0;
+ else
+ return -1;
+ }
+
+
+ int FreeMutex(CyaSSL_Mutex* m)
+ {
+ if (pthread_mutex_destroy(m) == 0)
+ return 0;
+ else
+ return -1;
+ }
+
+
+ int LockMutex(CyaSSL_Mutex* m)
+ {
+ if (pthread_mutex_lock(m) == 0)
+ return 0;
+ else
+ return -1;
+ }
+
+
+ int UnLockMutex(CyaSSL_Mutex* m)
+ {
+ if (pthread_mutex_unlock(m) == 0)
+ return 0;
+ else
+ return -1;
+ }
+
+ #elif defined(THREADX)
+
+ int InitMutex(CyaSSL_Mutex* m)
+ {
+ if (tx_mutex_create(m, "CyaSSL Mutex", TX_NO_INHERIT) == 0)
+ return 0;
+ else
+ return -1;
+ }
+
+
+ int FreeMutex(CyaSSL_Mutex* m)
+ {
+ if (tx_mutex_delete(m) == 0)
+ return 0;
+ else
+ return -1;
+ }
+
+
+ int LockMutex(CyaSSL_Mutex* m)
+ {
+ if (tx_mutex_get(m, TX_WAIT_FOREVER) == 0)
+ return 0;
+ else
+ return -1;
+ }
+
+
+ int UnLockMutex(CyaSSL_Mutex* m)
+ {
+ if (tx_mutex_put(m) == 0)
+ return 0;
+ else
+ return -1;
+ }
+
+ #elif defined(MICRIUM)
+
+ int InitMutex(CyaSSL_Mutex* m)
+ {
+ #if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED)
+ if (NetSecure_OS_MutexCreate(m) == 0)
+ return 0;
+ else
+ return -1;
+ #else
+ return 0;
+ #endif
+ }
+
+
+ int FreeMutex(CyaSSL_Mutex* m)
+ {
+ #if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED)
+ if (NetSecure_OS_FreeMutex(m) == 0)
+ return 0;
+ else
+ return -1;
+ #else
+ return 0;
+ #endif
+ }
+
+
+ int LockMutex(CyaSSL_Mutex* m)
+ {
+ #if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED)
+ if (NetSecure_OS_LockMutex(m) == 0)
+ return 0;
+ else
+ return -1;
+ #else
+ return 0;
+ #endif
+ }
+
+
+ int UnLockMutex(CyaSSL_Mutex* m)
+ {
+ #if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED)
+ if (NetSecure_OS_UnLockMutex(m) == 0)
+ return 0;
+ else
+ return -1;
+ #else
+ return 0;
+ #endif
+
+ }
+
+ #endif /* USE_WINDOWS_API */
+#endif /* SINGLE_THREADED */
+
+
+#ifdef DEBUG_CYASSL
+
+ static int logging = 0;
+
+
+ int CyaSSL_Debugging_ON(void)
+ {
+ logging = 1;
+ return 0;
+ }
+
+
+ void CyaSSL_Debugging_OFF(void)
+ {
+ logging = 0;
+ }
+
+
+#ifdef THREADX
+ int dc_log_printf(char*, ...);
+#endif
+
+ void CYASSL_MSG(const char* msg)
+ {
+ if (logging) {
+#ifdef THREADX
+ dc_log_printf("%s\n", msg);
+#elif defined(MICRIUM)
+ #if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED)
+ NetSecure_TraceOut((CPU_CHAR *)msg);
+ #endif
+#else
+ fprintf(stderr, "%s\n", msg);
+#endif
+ }
+ }
+
+
+ void CYASSL_ENTER(const char* msg)
+ {
+ if (logging) {
+ char buffer[80];
+ sprintf(buffer, "CyaSSL Entering %s", msg);
+ CYASSL_MSG(buffer);
+ }
+ }
+
+
+ void CYASSL_LEAVE(const char* msg, int ret)
+ {
+ if (logging) {
+ char buffer[80];
+ sprintf(buffer, "CyaSSL Leaving %s, return %d", msg, ret);
+ CYASSL_MSG(buffer);
+ }
+ }
+
+
+ void CYASSL_ERROR(int error)
+ {
+ if (logging) {
+ char buffer[80];
+ sprintf(buffer, "CyaSSL error occured, error = %d", error);
+ CYASSL_MSG(buffer);
+ }
+ }
+
+
+#else /* DEBUG_CYASSL */
+
+ int CyaSSL_Debugging_ON(void)
+ {
+ return -1; /* not compiled in */
+ }
+
+
+ void CyaSSL_Debugging_OFF(void)
+ {
+ /* already off */
+ }
+
+#endif /* DEBUG_CYASSL */
diff --git a/release/src/router/cyassl/src/cyassl_io.c b/release/src/router/cyassl/src/cyassl_io.c
new file mode 100644
index 00000000..a5f5283f
--- /dev/null
+++ b/release/src/router/cyassl/src/cyassl_io.c
@@ -0,0 +1,190 @@
+/* cyassl_io.c
+ *
+ * Copyright (C) 2006-2011 Sawtooth Consulting Ltd.
+ *
+ * This file is part of CyaSSL.
+ *
+ * CyaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * CyaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+#ifdef _WIN32_WCE
+ /* On WinCE winsock2.h must be included before windows.h for socket stuff */
+ #include <winsock2.h>
+#endif
+
+#include "cyassl_int.h"
+
+/* if user writes own I/O callbacks they can define CYASSL_USER_IO to remove
+ automatic setting of default I/O functions EmbedSend() and EmbedReceive()
+ but they'll still nedd SetCallback xxx() at end of file
+*/
+#ifndef CYASSL_USER_IO
+
+#ifdef HAVE_LIBZ
+ #include "zlib.h"
+#endif
+
+#ifndef USE_WINDOWS_API
+ #include <sys/types.h>
+ #include <errno.h>
+ #include <unistd.h>
+ #include <fcntl.h>
+ #if !(defined(DEVKITPRO) || defined(THREADX))
+ #include <sys/socket.h>
+ #include <arpa/inet.h>
+ #include <netinet/in.h>
+ #include <netdb.h>
+ #include <sys/ioctl.h>
+ #endif
+ #ifdef THREADX
+ #include <socket.h>
+ #endif
+#endif /* USE_WINDOWS_API */
+
+#ifdef __sun
+ #include <sys/filio.h>
+#endif
+
+#ifdef USE_WINDOWS_API
+ /* no epipe yet */
+ #ifndef WSAEPIPE
+ #define WSAEPIPE -12345
+ #endif
+ #define SOCKET_EWOULDBLOCK WSAEWOULDBLOCK
+ #define SOCKET_EAGAIN WSAEWOULDBLOCK
+ #define SOCKET_ECONNRESET WSAECONNRESET
+ #define SOCKET_EINTR WSAEINTR
+ #define SOCKET_EPIPE WSAEPIPE
+#else
+ #define SOCKET_EWOULDBLOCK EWOULDBLOCK
+ #define SOCKET_EAGAIN EAGAIN
+ #define SOCKET_ECONNRESET ECONNRESET
+ #define SOCKET_EINTR EINTR
+ #define SOCKET_EPIPE EPIPE
+#endif /* USE_WINDOWS_API */
+
+
+#ifdef DEVKITPRO
+ /* from network.h */
+ int net_send(int, const void*, int, unsigned int);
+ int net_recv(int, void*, int, unsigned int);
+ #define SEND_FUNCTION net_send
+ #define RECV_FUNCTION net_recv
+#else
+ #define SEND_FUNCTION send
+ #define RECV_FUNCTION recv
+#endif
+
+
+static INLINE int LastError(void)
+{
+#ifdef USE_WINDOWS_API
+ return WSAGetLastError();
+#else
+ return errno;
+#endif
+}
+
+/* The receive embedded callback
+ * return : nb bytes read, or error
+ */
+int EmbedReceive(char *buf, int sz, void *ctx)
+{
+ int recvd;
+ int err;
+ int socket = *(int*)ctx;
+
+ recvd = RECV_FUNCTION(socket, (char *)buf, sz, 0);
+
+ if (recvd == -1) {
+ err = LastError();
+ if (err == SOCKET_EWOULDBLOCK ||
+ err == SOCKET_EAGAIN)
+ return IO_ERR_WANT_READ;
+
+ else if (err == SOCKET_ECONNRESET)
+ return IO_ERR_CONN_RST;
+
+ else if (err == SOCKET_EINTR)
+ return IO_ERR_ISR;
+
+ else
+ return IO_ERR_GENERAL;
+ }
+ else if (recvd == 0)
+ return IO_ERR_CONN_CLOSE;
+
+ return recvd;
+}
+
+/* The send embedded callback
+ * return : nb bytes sent, or error
+ */
+int EmbedSend(char *buf, int sz, void *ctx)
+{
+ int socket = *(int*)ctx;
+ int sent;
+ int len = sz;
+
+ sent = SEND_FUNCTION(socket, &buf[sz - len], len, 0);
+
+ if (sent == -1) {
+ if (LastError() == SOCKET_EWOULDBLOCK ||
+ LastError() == SOCKET_EAGAIN)
+ return IO_ERR_WANT_WRITE;
+
+ else if (LastError() == SOCKET_ECONNRESET)
+ return IO_ERR_CONN_RST;
+
+ else if (LastError() == SOCKET_EINTR)
+ return IO_ERR_ISR;
+
+ else if (LastError() == SOCKET_EPIPE)
+ return IO_ERR_CONN_CLOSE;
+
+ else
+ return IO_ERR_GENERAL;
+ }
+
+ return sent;
+}
+
+
+#endif /* CYASSL_USER_IO */
+
+void CyaSSL_SetIORecv(SSL_CTX *ctx, CallbackIORecv CBIORecv)
+{
+ ctx->CBIORecv = CBIORecv;
+}
+
+
+void CyaSSL_SetIOSend(SSL_CTX *ctx, CallbackIOSend CBIOSend)
+{
+ ctx->CBIOSend = CBIOSend;
+}
+
+
+void CyaSSL_SetIOReadCtx(SSL* ssl, void *rctx)
+{
+ ssl->IOCB_ReadCtx = rctx;
+}
+
+
+void CyaSSL_SetIOWriteCtx(SSL* ssl, void *wctx)
+{
+ ssl->IOCB_WriteCtx = wctx;
+}
+
diff --git a/release/src/router/cyassl/src/keys.c b/release/src/router/cyassl/src/keys.c
new file mode 100644
index 00000000..3a51f7fb
--- /dev/null
+++ b/release/src/router/cyassl/src/keys.c
@@ -0,0 +1,751 @@
+/* keys.c
+ *
+ * Copyright (C) 2006-2011 Sawtooth Consulting Ltd.
+ *
+ * This file is part of CyaSSL.
+ *
+ * CyaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * CyaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+
+#include "cyassl_int.h"
+#include "cyassl_error.h"
+#ifdef SHOW_SECRETS
+ #include <stdio.h>
+#endif
+
+
+#ifndef NO_TLS
+ int MakeTlsMasterSecret(SSL*);
+ void TLS_hmac(SSL* ssl, byte* digest, const byte* buffer, word32 sz,
+ int content, int verify);
+#endif
+
+
+
+int SetCipherSpecs(SSL* ssl)
+{
+ /* ECC extensions */
+ if (ssl->options.cipherSuite0 == ECC_BYTE) {
+
+ switch (ssl->options.cipherSuite) {
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
+ case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA :
+ ssl->specs.bulk_cipher_algorithm = aes;
+ ssl->specs.cipher_type = block;
+ ssl->specs.mac_algorithm = sha_mac;
+ ssl->specs.kea = ecc_diffie_hellman_kea;
+ ssl->specs.sig_algo = rsa_sa_algo;
+ ssl->specs.hash_size = SHA_DIGEST_SIZE;
+ ssl->specs.pad_size = PAD_SHA;
+ ssl->specs.key_size = AES_128_KEY_SIZE;
+ ssl->specs.block_size = AES_BLOCK_SIZE;
+ ssl->specs.iv_size = AES_IV_SIZE;
+
+ break;
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
+ case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA :
+ ssl->specs.bulk_cipher_algorithm = triple_des;
+ ssl->specs.cipher_type = block;
+ ssl->specs.mac_algorithm = sha_mac;
+ ssl->specs.kea = ecc_diffie_hellman_kea;
+ ssl->specs.sig_algo = rsa_sa_algo;
+ ssl->specs.hash_size = SHA_DIGEST_SIZE;
+ ssl->specs.pad_size = PAD_SHA;
+ ssl->specs.key_size = DES3_KEY_SIZE;
+ ssl->specs.block_size = DES_BLOCK_SIZE;
+ ssl->specs.iv_size = DES_IV_SIZE;
+
+ break;
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_RC4_128_SHA
+ case TLS_ECDHE_RSA_WITH_RC4_128_SHA :
+ ssl->specs.bulk_cipher_algorithm = rc4;
+ ssl->specs.cipher_type = stream;
+ ssl->specs.mac_algorithm = sha_mac;
+ ssl->specs.kea = ecc_diffie_hellman_kea;
+ ssl->specs.sig_algo = rsa_sa_algo;
+ ssl->specs.hash_size = SHA_DIGEST_SIZE;
+ ssl->specs.pad_size = PAD_SHA;
+ ssl->specs.key_size = RC4_KEY_SIZE;
+ ssl->specs.iv_size = 0;
+ ssl->specs.block_size = 0;
+
+ break;
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
+ case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA :
+ ssl->specs.bulk_cipher_algorithm = triple_des;
+ ssl->specs.cipher_type = block;
+ ssl->specs.mac_algorithm = sha_mac;
+ ssl->specs.kea = ecc_diffie_hellman_kea;
+ ssl->specs.sig_algo = ecc_dsa_sa_algo;
+ ssl->specs.hash_size = SHA_DIGEST_SIZE;
+ ssl->specs.pad_size = PAD_SHA;
+ ssl->specs.key_size = DES3_KEY_SIZE;
+ ssl->specs.block_size = DES_BLOCK_SIZE;
+ ssl->specs.iv_size = DES_IV_SIZE;
+
+ break;
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
+ case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA :
+ ssl->specs.bulk_cipher_algorithm = rc4;
+ ssl->specs.cipher_type = stream;
+ ssl->specs.mac_algorithm = sha_mac;
+ ssl->specs.kea = ecc_diffie_hellman_kea;
+ ssl->specs.sig_algo = ecc_dsa_sa_algo;
+ ssl->specs.hash_size = SHA_DIGEST_SIZE;
+ ssl->specs.pad_size = PAD_SHA;
+ ssl->specs.key_size = RC4_KEY_SIZE;
+ ssl->specs.iv_size = 0;
+ ssl->specs.block_size = 0;
+
+ break;
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
+ case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA :
+ ssl->specs.bulk_cipher_algorithm = aes;
+ ssl->specs.cipher_type = block;
+ ssl->specs.mac_algorithm = sha_mac;
+ ssl->specs.kea = ecc_diffie_hellman_kea;
+ ssl->specs.sig_algo = rsa_sa_algo;
+ ssl->specs.hash_size = SHA_DIGEST_SIZE;
+ ssl->specs.pad_size = PAD_SHA;
+ ssl->specs.key_size = AES_256_KEY_SIZE;
+ ssl->specs.block_size = AES_BLOCK_SIZE;
+ ssl->specs.iv_size = AES_IV_SIZE;
+
+ break;
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
+ case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA :
+ ssl->specs.bulk_cipher_algorithm = aes;
+ ssl->specs.cipher_type = block;
+ ssl->specs.mac_algorithm = sha_mac;
+ ssl->specs.kea = ecc_diffie_hellman_kea;
+ ssl->specs.sig_algo = ecc_dsa_sa_algo;
+ ssl->specs.hash_size = SHA_DIGEST_SIZE;
+ ssl->specs.pad_size = PAD_SHA;
+ ssl->specs.key_size = AES_128_KEY_SIZE;
+ ssl->specs.block_size = AES_BLOCK_SIZE;
+ ssl->specs.iv_size = AES_IV_SIZE;
+
+ break;
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
+ case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA :
+ ssl->specs.bulk_cipher_algorithm = aes;
+ ssl->specs.cipher_type = block;
+ ssl->specs.mac_algorithm = sha_mac;
+ ssl->specs.kea = ecc_diffie_hellman_kea;
+ ssl->specs.sig_algo = ecc_dsa_sa_algo;
+ ssl->specs.hash_size = SHA_DIGEST_SIZE;
+ ssl->specs.pad_size = PAD_SHA;
+ ssl->specs.key_size = AES_256_KEY_SIZE;
+ ssl->specs.block_size = AES_BLOCK_SIZE;
+ ssl->specs.iv_size = AES_IV_SIZE;
+
+ break;
+#endif
+
+ default:
+ return UNSUPPORTED_SUITE;
+ }
+ } else { /* Normal suites */
+ switch (ssl->options.cipherSuite) {
+
+#ifdef BUILD_SSL_RSA_WITH_RC4_128_SHA
+ case SSL_RSA_WITH_RC4_128_SHA :
+ ssl->specs.bulk_cipher_algorithm = rc4;
+ ssl->specs.cipher_type = stream;
+ ssl->specs.mac_algorithm = sha_mac;
+ ssl->specs.kea = rsa_kea;
+ ssl->specs.hash_size = SHA_DIGEST_SIZE;
+ ssl->specs.pad_size = PAD_SHA;
+ ssl->specs.key_size = RC4_KEY_SIZE;
+ ssl->specs.iv_size = 0;
+ ssl->specs.block_size = 0;
+
+ break;
+#endif
+
+#ifdef BUILD_TLS_NTRU_RSA_WITH_RC4_128_SHA
+ case TLS_NTRU_RSA_WITH_RC4_128_SHA :
+ ssl->specs.bulk_cipher_algorithm = rc4;
+ ssl->specs.cipher_type = stream;
+ ssl->specs.mac_algorithm = sha_mac;
+ ssl->specs.kea = ntru_kea;
+ ssl->specs.hash_size = SHA_DIGEST_SIZE;
+ ssl->specs.pad_size = PAD_SHA;
+ ssl->specs.key_size = RC4_KEY_SIZE;
+ ssl->specs.iv_size = 0;
+ ssl->specs.block_size = 0;
+
+ break;
+#endif
+
+#ifdef BUILD_SSL_RSA_WITH_RC4_128_MD5
+ case SSL_RSA_WITH_RC4_128_MD5 :
+ ssl->specs.bulk_cipher_algorithm = rc4;
+ ssl->specs.cipher_type = stream;
+ ssl->specs.mac_algorithm = md5_mac;
+ ssl->specs.kea = rsa_kea;
+ ssl->specs.hash_size = MD5_DIGEST_SIZE;
+ ssl->specs.pad_size = PAD_MD5;
+ ssl->specs.key_size = RC4_KEY_SIZE;
+ ssl->specs.iv_size = 0;
+ ssl->specs.block_size = 0;
+
+ break;
+#endif
+
+#ifdef BUILD_SSL_RSA_WITH_3DES_EDE_CBC_SHA
+ case SSL_RSA_WITH_3DES_EDE_CBC_SHA :
+ ssl->specs.bulk_cipher_algorithm = triple_des;
+ ssl->specs.cipher_type = block;
+ ssl->specs.mac_algorithm = sha_mac;
+ ssl->specs.kea = rsa_kea;
+ ssl->specs.hash_size = SHA_DIGEST_SIZE;
+ ssl->specs.pad_size = PAD_SHA;
+ ssl->specs.key_size = DES3_KEY_SIZE;
+ ssl->specs.block_size = DES_BLOCK_SIZE;
+ ssl->specs.iv_size = DES_IV_SIZE;
+
+ break;
+#endif
+
+#ifdef BUILD_TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA
+ case TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA :
+ ssl->specs.bulk_cipher_algorithm = triple_des;
+ ssl->specs.cipher_type = block;
+ ssl->specs.mac_algorithm = sha_mac;
+ ssl->specs.kea = ntru_kea;
+ ssl->specs.hash_size = SHA_DIGEST_SIZE;
+ ssl->specs.pad_size = PAD_SHA;
+ ssl->specs.key_size = DES3_KEY_SIZE;
+ ssl->specs.block_size = DES_BLOCK_SIZE;
+ ssl->specs.iv_size = DES_IV_SIZE;
+
+ break;
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA
+ case TLS_RSA_WITH_AES_128_CBC_SHA :
+ ssl->specs.bulk_cipher_algorithm = aes;
+ ssl->specs.cipher_type = block;
+ ssl->specs.mac_algorithm = sha_mac;
+ ssl->specs.kea = rsa_kea;
+ ssl->specs.hash_size = SHA_DIGEST_SIZE;
+ ssl->specs.pad_size = PAD_SHA;
+ ssl->specs.key_size = AES_128_KEY_SIZE;
+ ssl->specs.block_size = AES_BLOCK_SIZE;
+ ssl->specs.iv_size = AES_IV_SIZE;
+
+ break;
+#endif
+
+#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_128_CBC_SHA
+ case TLS_NTRU_RSA_WITH_AES_128_CBC_SHA :
+ ssl->specs.bulk_cipher_algorithm = aes;
+ ssl->specs.cipher_type = block;
+ ssl->specs.mac_algorithm = sha_mac;
+ ssl->specs.kea = ntru_kea;
+ ssl->specs.hash_size = SHA_DIGEST_SIZE;
+ ssl->specs.pad_size = PAD_SHA;
+ ssl->specs.key_size = AES_128_KEY_SIZE;
+ ssl->specs.block_size = AES_BLOCK_SIZE;
+ ssl->specs.iv_size = AES_IV_SIZE;
+
+ break;
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA
+ case TLS_RSA_WITH_AES_256_CBC_SHA :
+ ssl->specs.bulk_cipher_algorithm = aes;
+ ssl->specs.cipher_type = block;
+ ssl->specs.mac_algorithm = sha_mac;
+ ssl->specs.kea = rsa_kea;
+ ssl->specs.hash_size = SHA_DIGEST_SIZE;
+ ssl->specs.pad_size = PAD_SHA;
+ ssl->specs.key_size = AES_256_KEY_SIZE;
+ ssl->specs.block_size = AES_BLOCK_SIZE;
+ ssl->specs.iv_size = AES_IV_SIZE;
+
+ break;
+#endif
+
+#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_256_CBC_SHA
+ case TLS_NTRU_RSA_WITH_AES_256_CBC_SHA :
+ ssl->specs.bulk_cipher_algorithm = aes;
+ ssl->specs.cipher_type = block;
+ ssl->specs.mac_algorithm = sha_mac;
+ ssl->specs.kea = ntru_kea;
+ ssl->specs.hash_size = SHA_DIGEST_SIZE;
+ ssl->specs.pad_size = PAD_SHA;
+ ssl->specs.key_size = AES_256_KEY_SIZE;
+ ssl->specs.block_size = AES_BLOCK_SIZE;
+ ssl->specs.iv_size = AES_IV_SIZE;
+
+ break;
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA
+ case TLS_PSK_WITH_AES_128_CBC_SHA :
+ ssl->specs.bulk_cipher_algorithm = aes;
+ ssl->specs.cipher_type = block;
+ ssl->specs.mac_algorithm = sha_mac;
+ ssl->specs.kea = psk_kea;
+ ssl->specs.hash_size = SHA_DIGEST_SIZE;
+ ssl->specs.pad_size = PAD_SHA;
+ ssl->specs.key_size = AES_128_KEY_SIZE;
+ ssl->specs.block_size = AES_BLOCK_SIZE;
+ ssl->specs.iv_size = AES_IV_SIZE;
+
+ ssl->options.usingPSK_cipher = 1;
+ break;
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA
+ case TLS_PSK_WITH_AES_256_CBC_SHA :
+ ssl->specs.bulk_cipher_algorithm = aes;
+ ssl->specs.cipher_type = block;
+ ssl->specs.mac_algorithm = sha_mac;
+ ssl->specs.kea = psk_kea;
+ ssl->specs.hash_size = SHA_DIGEST_SIZE;
+ ssl->specs.pad_size = PAD_SHA;
+ ssl->specs.key_size = AES_256_KEY_SIZE;
+ ssl->specs.block_size = AES_BLOCK_SIZE;
+ ssl->specs.iv_size = AES_IV_SIZE;
+
+ ssl->options.usingPSK_cipher = 1;
+ break;
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA
+ case TLS_DHE_RSA_WITH_AES_128_CBC_SHA :
+ ssl->specs.bulk_cipher_algorithm = aes;
+ ssl->specs.cipher_type = block;
+ ssl->specs.mac_algorithm = sha_mac;
+ ssl->specs.kea = diffie_hellman_kea;
+ ssl->specs.sig_algo = rsa_sa_algo;
+ ssl->specs.hash_size = SHA_DIGEST_SIZE;
+ ssl->specs.pad_size = PAD_SHA;
+ ssl->specs.key_size = AES_128_KEY_SIZE;
+ ssl->specs.block_size = AES_BLOCK_SIZE;
+ ssl->specs.iv_size = AES_IV_SIZE;
+
+ break;
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA
+ case TLS_DHE_RSA_WITH_AES_256_CBC_SHA :
+ ssl->specs.bulk_cipher_algorithm = aes;
+ ssl->specs.cipher_type = block;
+ ssl->specs.mac_algorithm = sha_mac;
+ ssl->specs.kea = diffie_hellman_kea;
+ ssl->specs.sig_algo = rsa_sa_algo;
+ ssl->specs.hash_size = SHA_DIGEST_SIZE;
+ ssl->specs.pad_size = PAD_SHA;
+ ssl->specs.key_size = AES_256_KEY_SIZE;
+ ssl->specs.block_size = AES_BLOCK_SIZE;
+ ssl->specs.iv_size = AES_IV_SIZE;
+
+ break;
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_HC_128_CBC_MD5
+ case TLS_RSA_WITH_HC_128_CBC_MD5 :
+ ssl->specs.bulk_cipher_algorithm = hc128;
+ ssl->specs.cipher_type = stream;
+ ssl->specs.mac_algorithm = md5_mac;
+ ssl->specs.kea = rsa_kea;
+ ssl->specs.hash_size = MD5_DIGEST_SIZE;
+ ssl->specs.pad_size = PAD_MD5;
+ ssl->specs.key_size = HC_128_KEY_SIZE;
+ ssl->specs.block_size = 0;
+ ssl->specs.iv_size = HC_128_IV_SIZE;
+
+ break;
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_HC_128_CBC_SHA
+ case TLS_RSA_WITH_HC_128_CBC_SHA :
+ ssl->specs.bulk_cipher_algorithm = hc128;
+ ssl->specs.cipher_type = stream;
+ ssl->specs.mac_algorithm = sha_mac;
+ ssl->specs.kea = rsa_kea;
+ ssl->specs.hash_size = SHA_DIGEST_SIZE;
+ ssl->specs.pad_size = PAD_SHA;
+ ssl->specs.key_size = HC_128_KEY_SIZE;
+ ssl->specs.block_size = 0;
+ ssl->specs.iv_size = HC_128_IV_SIZE;
+
+ break;
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_RABBIT_CBC_SHA
+ case TLS_RSA_WITH_RABBIT_CBC_SHA :
+ ssl->specs.bulk_cipher_algorithm = rabbit;
+ ssl->specs.cipher_type = stream;
+ ssl->specs.mac_algorithm = sha_mac;
+ ssl->specs.kea = rsa_kea;
+ ssl->specs.hash_size = SHA_DIGEST_SIZE;
+ ssl->specs.pad_size = PAD_SHA;
+ ssl->specs.key_size = RABBIT_KEY_SIZE;
+ ssl->specs.block_size = 0;
+ ssl->specs.iv_size = RABBIT_IV_SIZE;
+
+ break;
+#endif
+
+ default:
+ return UNSUPPORTED_SUITE;
+ }
+ } /* ECC / Normal suites else */
+
+ /* set TLS if it hasn't been turned off */
+ if (ssl->version.major == 3 && ssl->version.minor >= 1) {
+#ifndef NO_TLS
+ ssl->options.tls = 1;
+ ssl->hmac = TLS_hmac;
+ if (ssl->version.minor >= 2)
+ ssl->options.tls1_1 = 1;
+#endif
+ }
+
+#ifdef CYASSL_DTLS
+ if (ssl->options.dtls)
+ ssl->hmac = TLS_hmac;
+#endif
+
+ return 0;
+}
+
+
+enum KeyStuff {
+ MASTER_ROUNDS = 3,
+ PREFIX = 3, /* up to three letters for master prefix */
+ KEY_PREFIX = 7 /* up to 7 prefix letters for key rounds */
+
+
+};
+
+
+/* true or false, zero for error */
+static int SetPrefix(byte* sha_input, int index)
+{
+ switch (index) {
+ case 0:
+ XMEMCPY(sha_input, "A", 1);
+ break;
+ case 1:
+ XMEMCPY(sha_input, "BB", 2);
+ break;
+ case 2:
+ XMEMCPY(sha_input, "CCC", 3);
+ break;
+ case 3:
+ XMEMCPY(sha_input, "DDDD", 4);
+ break;
+ case 4:
+ XMEMCPY(sha_input, "EEEEE", 5);
+ break;
+ case 5:
+ XMEMCPY(sha_input, "FFFFFF", 6);
+ break;
+ case 6:
+ XMEMCPY(sha_input, "GGGGGGG", 7);
+ break;
+ default:
+ return 0;
+ }
+ return 1;
+}
+
+
+static int SetKeys(Ciphers* encrypt, Ciphers* decrypt, Keys* keys,
+ CipherSpecs* specs, byte side)
+{
+#ifdef BUILD_ARC4
+ word32 sz = specs->key_size;
+ if (specs->bulk_cipher_algorithm == rc4) {
+ if (side == CLIENT_END) {
+ Arc4SetKey(&encrypt->arc4, keys->client_write_key, sz);
+ Arc4SetKey(&decrypt->arc4, keys->server_write_key, sz);
+ }
+ else {
+ Arc4SetKey(&encrypt->arc4, keys->server_write_key, sz);
+ Arc4SetKey(&decrypt->arc4, keys->client_write_key, sz);
+ }
+ }
+#endif
+
+#ifdef BUILD_HC128
+ if (specs->bulk_cipher_algorithm == hc128) {
+ if (side == CLIENT_END) {
+ Hc128_SetKey(&encrypt->hc128, keys->client_write_key,
+ keys->client_write_IV);
+ Hc128_SetKey(&decrypt->hc128, keys->server_write_key,
+ keys->server_write_IV);
+ }
+ else {
+ Hc128_SetKey(&encrypt->hc128, keys->server_write_key,
+ keys->server_write_IV);
+ Hc128_SetKey(&decrypt->hc128, keys->client_write_key,
+ keys->client_write_IV);
+ }
+ }
+#endif
+
+#ifdef BUILD_RABBIT
+ if (specs->bulk_cipher_algorithm == rabbit) {
+ if (side == CLIENT_END) {
+ RabbitSetKey(&encrypt->rabbit, keys->client_write_key,
+ keys->client_write_IV);
+ RabbitSetKey(&decrypt->rabbit, keys->server_write_key,
+ keys->server_write_IV);
+ }
+ else {
+ RabbitSetKey(&encrypt->rabbit, keys->server_write_key,
+ keys->server_write_IV);
+ RabbitSetKey(&decrypt->rabbit, keys->client_write_key,
+ keys->client_write_IV);
+ }
+ }
+#endif
+
+#ifdef BUILD_DES3
+ if (specs->bulk_cipher_algorithm == triple_des) {
+ if (side == CLIENT_END) {
+ Des3_SetKey(&encrypt->des3, keys->client_write_key,
+ keys->client_write_IV, DES_ENCRYPTION);
+ Des3_SetKey(&decrypt->des3, keys->server_write_key,
+ keys->server_write_IV, DES_DECRYPTION);
+ }
+ else {
+ Des3_SetKey(&encrypt->des3, keys->server_write_key,
+ keys->server_write_IV, DES_ENCRYPTION);
+ Des3_SetKey(&decrypt->des3, keys->client_write_key,
+ keys->client_write_IV, DES_DECRYPTION);
+ }
+ }
+#endif
+
+#ifdef BUILD_AES
+ if (specs->bulk_cipher_algorithm == aes) {
+ if (side == CLIENT_END) {
+ AesSetKey(&encrypt->aes, keys->client_write_key,
+ specs->key_size, keys->client_write_IV,
+ AES_ENCRYPTION);
+ AesSetKey(&decrypt->aes, keys->server_write_key,
+ specs->key_size, keys->server_write_IV,
+ AES_DECRYPTION);
+ }
+ else {
+ AesSetKey(&encrypt->aes, keys->server_write_key,
+ specs->key_size, keys->server_write_IV,
+ AES_ENCRYPTION);
+ AesSetKey(&decrypt->aes, keys->client_write_key,
+ specs->key_size, keys->client_write_IV,
+ AES_DECRYPTION);
+ }
+ }
+#endif
+
+ keys->sequence_number = 0;
+ keys->peer_sequence_number = 0;
+ keys->encryptionOn = 0;
+
+ return 0;
+}
+
+
+/* TLS can call too */
+int StoreKeys(SSL* ssl, const byte* keyData)
+{
+ int sz = ssl->specs.hash_size, i;
+
+ XMEMCPY(ssl->keys.client_write_MAC_secret, keyData, sz);
+ i = sz;
+ XMEMCPY(ssl->keys.server_write_MAC_secret,&keyData[i], sz);
+ i += sz;
+
+ sz = ssl->specs.key_size;
+ XMEMCPY(ssl->keys.client_write_key, &keyData[i], sz);
+ i += sz;
+ XMEMCPY(ssl->keys.server_write_key, &keyData[i], sz);
+ i += sz;
+
+ sz = ssl->specs.iv_size;
+ XMEMCPY(ssl->keys.client_write_IV, &keyData[i], sz);
+ i += sz;
+ XMEMCPY(ssl->keys.server_write_IV, &keyData[i], sz);
+
+ return SetKeys(&ssl->encrypt, &ssl->decrypt, &ssl->keys, &ssl->specs,
+ ssl->options.side);
+}
+
+
+int DeriveKeys(SSL* ssl)
+{
+ int length = 2 * ssl->specs.hash_size +
+ 2 * ssl->specs.key_size +
+ 2 * ssl->specs.iv_size;
+ int rounds = (length + MD5_DIGEST_SIZE - 1 ) / MD5_DIGEST_SIZE, i;
+
+ byte shaOutput[SHA_DIGEST_SIZE];
+ byte md5Input[SECRET_LEN + SHA_DIGEST_SIZE];
+ byte shaInput[KEY_PREFIX + SECRET_LEN + 2 * RAN_LEN];
+
+ Md5 md5;
+ Sha sha;
+
+ byte keyData[KEY_PREFIX * MD5_DIGEST_SIZE]; /* max size */
+
+ InitMd5(&md5);
+ InitSha(&sha);
+
+ XMEMCPY(md5Input, ssl->arrays.masterSecret, SECRET_LEN);
+
+ for (i = 0; i < rounds; ++i) {
+ int j = i + 1;
+ int idx = j;
+
+ if (!SetPrefix(shaInput, i)) {
+ return PREFIX_ERROR;
+ }
+
+ XMEMCPY(shaInput + idx, ssl->arrays.masterSecret, SECRET_LEN);
+ idx += SECRET_LEN;
+ XMEMCPY(shaInput + idx, ssl->arrays.serverRandom, RAN_LEN);
+ idx += RAN_LEN;
+ XMEMCPY(shaInput + idx, ssl->arrays.clientRandom, RAN_LEN);
+ idx += RAN_LEN;
+
+ ShaUpdate(&sha, shaInput, sizeof(shaInput) - KEY_PREFIX + j);
+ ShaFinal(&sha, shaOutput);
+
+ XMEMCPY(&md5Input[SECRET_LEN], shaOutput, SHA_DIGEST_SIZE);
+ Md5Update(&md5, md5Input, sizeof(md5Input));
+ Md5Final(&md5, keyData + i * MD5_DIGEST_SIZE);
+ }
+
+ return StoreKeys(ssl, keyData);
+}
+
+
+void CleanPreMaster(SSL* ssl)
+{
+ int i, sz = ssl->arrays.preMasterSz;
+
+ for (i = 0; i < sz; i++)
+ ssl->arrays.preMasterSecret[i] = 0;
+
+ RNG_GenerateBlock(&ssl->rng, ssl->arrays.preMasterSecret, sz);
+
+ for (i = 0; i < sz; i++)
+ ssl->arrays.preMasterSecret[i] = 0;
+
+}
+
+
+/* Create and store the master secret see page 32, 6.1 */
+int MakeMasterSecret(SSL* ssl)
+{
+ byte shaOutput[SHA_DIGEST_SIZE];
+ byte md5Input[ENCRYPT_LEN + SHA_DIGEST_SIZE];
+ byte shaInput[PREFIX + ENCRYPT_LEN + 2 * RAN_LEN];
+ int i, ret;
+ word32 idx;
+ word32 pmsSz = ssl->arrays.preMasterSz;
+
+ Md5 md5;
+ Sha sha;
+
+#ifdef SHOW_SECRETS
+ {
+ int j;
+ printf("pre master secret: ");
+ for (j = 0; j < pmsSz; j++)
+ printf("%02x", ssl->arrays.preMasterSecret[j]);
+ printf("\n");
+ }
+#endif
+
+#ifndef NO_TLS
+ if (ssl->options.tls) return MakeTlsMasterSecret(ssl);
+#endif
+
+ InitMd5(&md5);
+ InitSha(&sha);
+
+ XMEMCPY(md5Input, ssl->arrays.preMasterSecret, pmsSz);
+
+ for (i = 0; i < MASTER_ROUNDS; ++i) {
+ byte prefix[PREFIX];
+ if (!SetPrefix(prefix, i)) {
+ return PREFIX_ERROR;
+ }
+
+ idx = 0;
+ XMEMCPY(shaInput, prefix, i + 1);
+ idx += i + 1;
+
+ XMEMCPY(shaInput + idx, ssl->arrays.preMasterSecret, pmsSz);
+ idx += pmsSz;
+ XMEMCPY(shaInput + idx, ssl->arrays.clientRandom, RAN_LEN);
+ idx += RAN_LEN;
+ XMEMCPY(shaInput + idx, ssl->arrays.serverRandom, RAN_LEN);
+ idx += RAN_LEN;
+ ShaUpdate(&sha, shaInput, idx);
+ ShaFinal(&sha, shaOutput);
+
+ idx = pmsSz; /* preSz */
+ XMEMCPY(md5Input + idx, shaOutput, SHA_DIGEST_SIZE);
+ idx += SHA_DIGEST_SIZE;
+ Md5Update(&md5, md5Input, idx);
+ Md5Final(&md5, &ssl->arrays.masterSecret[i * MD5_DIGEST_SIZE]);
+ }
+
+#ifdef SHOW_SECRETS
+ {
+ int i;
+ printf("master secret: ");
+ for (i = 0; i < SECRET_LEN; i++)
+ printf("%02x", ssl->arrays.masterSecret[i]);
+ printf("\n");
+ }
+#endif
+
+ ret = DeriveKeys(ssl);
+ CleanPreMaster(ssl);
+
+ return ret;
+}
+
+
+
+
diff --git a/release/src/router/cyassl/src/sniffer.c b/release/src/router/cyassl/src/sniffer.c
new file mode 100644
index 00000000..40891dfc
--- /dev/null
+++ b/release/src/router/cyassl/src/sniffer.c
@@ -0,0 +1,2187 @@
+/* sniffer.c
+ *
+ * Copyright (C) 2006-2011 Sawtooth Consulting Ltd.
+ *
+ * This file is part of CyaSSL.
+ *
+ * CyaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * CyaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#ifdef CYASSL_SNIFFER
+
+#include "ssl.h"
+#include "cyassl_int.h"
+#include "cyassl_error.h"
+#include "sniffer.h"
+#include "sniffer_error.h"
+#include <time.h>
+
+#ifndef _WIN32
+ #include <arpa/inet.h>
+#endif
+
+#include <assert.h>
+
+
+#ifdef _WIN32
+ #define SNPRINTF _snprintf
+#else
+ #define SNPRINTF snprintf
+#endif
+
+
+/* Misc constants */
+enum {
+ MAX_SERVER_ADDRESS = 128, /* maximum server address length */
+ MAX_ERROR_LEN = 80, /* maximum error length */
+ ETHER_IF_ADDR_LEN = 6, /* ethernet interface address length */
+ LOCAL_IF_ADDR_LEN = 4, /* localhost interface address length, !windows */
+ TCP_PROTO = 6, /* TCP_PROTOCOL */
+ IP_HDR_SZ = 20, /* IP header legnth, min */
+ TCP_HDR_SZ = 20, /* TCP header legnth, min */
+ IPV4 = 4, /* IP version 4 */
+ TCP_PROTOCOL = 6, /* TCP Protocol id */
+ TRACE_MSG_SZ = 80, /* Trace Message buffer size */
+ HASH_SIZE = 499, /* Session Hash Table Rows */
+ PSEUDO_HDR_SZ = 12, /* TCP Pseudo Header size in bytes */
+ FATAL_ERROR_STATE = 1, /* SnifferSession fatal error state */
+ SNIFFER_TIMEOUT = 900, /* Cache unclosed Sessions for 15 minutes */
+};
+
+
+#ifdef _WIN32
+
+static HMODULE dllModule; /* for error string resources */
+
+BOOL APIENTRY DllMain( HMODULE hModule,
+ DWORD ul_reason_for_call,
+ LPVOID lpReserved
+ )
+{
+ static int didInit = 0;
+
+ switch (ul_reason_for_call)
+ {
+ case DLL_PROCESS_ATTACH:
+ if (didInit == 0) {
+ dllModule = hModule;
+ ssl_InitSniffer();
+ didInit = 1;
+ }
+ break;
+ case DLL_THREAD_ATTACH:
+ break;
+ case DLL_THREAD_DETACH:
+ break;
+ case DLL_PROCESS_DETACH:
+ if (didInit) {
+ ssl_FreeSniffer();
+ didInit = 0;
+ }
+ break;
+ }
+ return TRUE;
+}
+
+#endif /* _WIN32 */
+
+
+static int TraceOn = 0; /* Trace is off by default */
+static FILE* TraceFile = 0;
+
+
+/* windows uses .rc talbe for this */
+#ifndef _WIN32
+
+static const char* const msgTable[] =
+{
+ /* 1 */
+ "Out of Memory",
+ "New SSL Sniffer Server Registered",
+ "Checking IP Header",
+ "SSL Sniffer Server Not Registered",
+ "Checking TCP Header",
+
+ /* 6 */
+ "SSL Sniffer Server Port Not Registered",
+ "RSA Private Decrypt Error",
+ "RSA Private Decode Error",
+ "Set Cipher Spec Error",
+ "Server Hello Input Malformed",
+
+ /* 11 */
+ "Couldn't Resume Session Error",
+ "Server Did Resumption",
+ "Client Hello Input Malformed",
+ "Client Trying to Resume",
+ "Handshake Input Malformed",
+
+ /* 16 */
+ "Got Hello Verify msg",
+ "Got Server Hello msg",
+ "Got Cert Request msg",
+ "Got Server Key Exchange msg",
+ "Got Cert msg",
+
+ /* 21 */
+ "Got Server Hello Done msg",
+ "Got Finished msg",
+ "Got Client Hello msg",
+ "Got Client Key Exchange msg",
+ "Got Cert Verify msg",
+
+ /* 26 */
+ "Got Unknown Handshake msg",
+ "New SSL Sniffer Session created",
+ "Couldn't create new SSL",
+ "Got a Packet to decode",
+ "No data present",
+
+ /* 31 */
+ "Session Not Found",
+ "Got an Old Client Hello msg",
+ "Old Client Hello Input Malformed",
+ "Old Client Hello OK",
+ "Bad Old Client Hello",
+
+ /* 36 */
+ "Bad Record Header",
+ "Record Header Input Malformed",
+ "Got a HandShake msg",
+ "Bad HandShake msg",
+ "Got a Change Cipher Spec msg",
+
+ /* 41 */
+ "Got Application Data msg",
+ "Bad Application Data",
+ "Got an Alert msg",
+ "Another msg to Process",
+ "Removing Session From Table",
+
+ /* 46 */
+ "Bad Key File",
+ "Wrong IP Version",
+ "Wrong Protocol type",
+ "Packet Short for header processing",
+ "Got Unknown Record Type",
+
+ /* 51 */
+ "Can't Open Trace File",
+ "Session in Fatal Error State",
+ "Partial SSL record received",
+ "Buffer Error, malformed input",
+ "Added to Partial Input",
+
+ /* 56 */
+ "Received a Duplicate Packet",
+ "Received an Out of Order Packet",
+ "Received an Overlap Duplicate Packet",
+ "Received an Overlap Reassembly Begin Duplicate Packet",
+ "Received an Overlap Reassembly End Duplicate Packet",
+
+ /* 61 */
+ "Missed the Client Hello Entirely",
+};
+
+
+/* *nix version uses table above */
+static void GetError(int idx, char* buffer)
+{
+ XSTRNCPY(buffer, msgTable[idx - 1], MAX_ERROR_LEN);
+}
+
+
+#else /* _WIN32 */
+
+
+/* Windows version uses .rc table */
+static void GetError(int idx, char* buffer)
+{
+ if (!LoadStringA(dllModule, idx, buffer, MAX_ERROR_LEN))
+ buffer[0] = 0;
+}
+
+
+#endif /* _WIN32 */
+
+
+/* Packet Buffer for reassembly list and ready list */
+typedef struct PacketBuffer {
+ word32 begin; /* relative sequence begin */
+ word32 end; /* relative sequence end */
+ byte* data; /* actual data */
+ struct PacketBuffer* next; /* next on reassembly list or ready list */
+} PacketBuffer;
+
+
+/* Sniffer Server holds info for each server/port monitored */
+typedef struct SnifferServer {
+ SSL_CTX* ctx; /* SSL context */
+ char address[MAX_SERVER_ADDRESS]; /* passed in server address */
+ word32 server; /* netowrk order address */
+ int port; /* server port */
+ struct SnifferServer* next; /* for list */
+} SnifferServer;
+
+
+/* Session Flags */
+typedef struct Flags {
+ byte side; /* which end is current packet headed */
+ byte serverCipherOn; /* indicates whether cipher is active */
+ byte clientCipherOn; /* indicates whether cipher is active */
+ byte resuming; /* did this session come from resumption */
+ byte cached; /* have we cached this session yet */
+ byte clientHello; /* processed client hello yet, for SSLv2 */
+ byte finCount; /* get both FINs before removing */
+ byte fatalError; /* fatal error state */
+} Flags;
+
+
+/* Out of Order FIN caputre */
+typedef struct FinCaputre {
+ word32 cliFinSeq; /* client relative sequence FIN 0 is no */
+ word32 srvFinSeq; /* server relative sequence FIN, 0 is no */
+ byte cliCounted; /* did we count yet, detects duplicates */
+ byte srvCounted; /* did we count yet, detects duplicates */
+} FinCaputre;
+
+
+/* Sniffer Session holds info for each client/server SSL/TLS session */
+typedef struct SnifferSession {
+ SnifferServer* context; /* server context */
+ SSL* sslServer; /* SSL server side decode */
+ SSL* sslClient; /* SSL client side decode */
+ word32 server; /* server address in network byte order */
+ word32 client; /* client address in network byte order */
+ word16 srvPort; /* server port */
+ word16 cliPort; /* client port */
+ word32 cliSeqStart; /* client start sequence */
+ word32 srvSeqStart; /* server start sequence */
+ word32 cliExpected; /* client expected sequence (relative) */
+ word32 srvExpected; /* server expected sequence (relative) */
+ FinCaputre finCaputre; /* retain out of order FIN s */
+ Flags flags; /* session flags */
+ time_t bornOn; /* born on ticks */
+ PacketBuffer* cliReassemblyList; /* client out of order packets */
+ PacketBuffer* srvReassemblyList; /* server out of order packets */
+ struct SnifferSession* next; /* for hash table list */
+} SnifferSession;
+
+
+/* Sniffer Server List and mutex */
+static SnifferServer* ServerList = 0;
+static CyaSSL_Mutex ServerListMutex;
+
+
+/* Session Hash Table, mutex, and count */
+static SnifferSession* SessionTable[HASH_SIZE];
+static CyaSSL_Mutex SessionMutex;
+static int SessionCount = 0;
+
+
+/* Initialize overall Sniffer */
+void ssl_InitSniffer(void)
+{
+ InitCyaSSL();
+ InitMutex(&ServerListMutex);
+ InitMutex(&SessionMutex);
+}
+
+
+/* Free Sniffer Server's resources/self */
+static void FreeSnifferServer(SnifferServer* server)
+{
+ if (server)
+ SSL_CTX_free(server->ctx);
+ free(server);
+}
+
+
+/* free PacketBuffer's resources/self */
+static void FreePacketBuffer(PacketBuffer* remove)
+{
+ if (remove) {
+ free(remove->data);
+ free(remove);
+ }
+}
+
+
+/* remove PacketBuffer List */
+static void FreePacketList(PacketBuffer* buffer)
+{
+ if (buffer) {
+ PacketBuffer* remove;
+ PacketBuffer* packet = buffer;
+
+ while (packet) {
+ remove = packet;
+ packet = packet->next;
+ FreePacketBuffer(remove);
+ }
+ }
+}
+
+
+/* Free Sniffer Session's resources/self */
+static void FreeSnifferSession(SnifferSession* session)
+{
+ if (session) {
+ SSL_free(session->sslClient);
+ SSL_free(session->sslServer);
+
+ FreePacketList(session->cliReassemblyList);
+ FreePacketList(session->srvReassemblyList);
+ }
+ free(session);
+}
+
+
+/* Free overall Sniffer */
+void ssl_FreeSniffer(void)
+{
+ SnifferServer* server;
+ SnifferServer* removeServer;
+ SnifferSession* session;
+ SnifferSession* removeSession;
+ int i;
+
+ LockMutex(&ServerListMutex);
+ LockMutex(&SessionMutex);
+
+ server = ServerList;
+ while (server) {
+ removeServer = server;
+ server = server->next;
+ FreeSnifferServer(removeServer);
+ }
+
+ for (i = 0; i < HASH_SIZE; i++) {
+ session = SessionTable[i];
+ while (session) {
+ removeSession = session;
+ session = session->next;
+ FreeSnifferSession(removeSession);
+ }
+ }
+
+ UnLockMutex(&SessionMutex);
+ UnLockMutex(&ServerListMutex);
+
+ FreeMutex(&SessionMutex);
+ FreeMutex(&ServerListMutex);
+ FreeCyaSSL();
+}
+
+
+/* Initialize a SnifferServer */
+static void InitSnifferServer(SnifferServer* sniffer)
+{
+ sniffer->ctx = 0;
+ XMEMSET(sniffer->address, 0, MAX_SERVER_ADDRESS);
+ sniffer->server = 0;
+ sniffer->port = 0;
+ sniffer->next = 0;
+}
+
+
+/* Initialize session flags */
+static void InitFlags(Flags* flags)
+{
+ flags->side = 0;
+ flags->serverCipherOn = 0;
+ flags->clientCipherOn = 0;
+ flags->resuming = 0;
+ flags->cached = 0;
+ flags->clientHello = 0;
+ flags->finCount = 0;
+ flags->fatalError = 0;
+}
+
+
+/* Initialize FIN Capture */
+static void InitFinCapture(FinCaputre* cap)
+{
+ cap->cliFinSeq = 0;
+ cap->srvFinSeq = 0;
+ cap->cliCounted = 0;
+ cap->srvCounted = 0;
+}
+
+
+/* Initialize a Sniffer Session */
+static void InitSession(SnifferSession* session)
+{
+ session->context = 0;
+ session->sslServer = 0;
+ session->sslClient = 0;
+ session->server = 0;
+ session->client = 0;
+ session->srvPort = 0;
+ session->cliPort = 0;
+ session->cliSeqStart = 0;
+ session->srvSeqStart = 0;
+ session->cliExpected = 0;
+ session->srvExpected = 0;
+ session->bornOn = 0;
+ session->cliReassemblyList = 0;
+ session->srvReassemblyList = 0;
+ session->next = 0;
+
+ InitFlags(&session->flags);
+ InitFinCapture(&session->finCaputre);
+}
+
+
+/* IP Info from IP Header */
+typedef struct IpInfo {
+ int length; /* length of this header */
+ int total; /* total length of fragment */
+ word32 src; /* network order source address */
+ word32 dst; /* network order destination address */
+} IpInfo;
+
+
+/* TCP Info from TCP Header */
+typedef struct TcpInfo {
+ int srcPort; /* source port */
+ int dstPort; /* source port */
+ int length; /* length of this header */
+ word32 sequence; /* sequence number */
+ byte fin; /* FIN set */
+ byte rst; /* RST set */
+ byte syn; /* SYN set */
+ byte ack; /* ACK set */
+} TcpInfo;
+
+
+/* Tcp Pseudo Header for Checksum calculation */
+typedef struct TcpPseudoHdr {
+ word32 src; /* source address */
+ word32 dst; /* destination address */
+ byte rsv; /* reserved, always 0 */
+ byte protocol; /* IP protocol */
+ word16 legnth; /* tcp header length + data length (doesn't include */
+ /* pseudo header length) network order */
+} TcpPseudoHdr;
+
+
+/* Password Setting Callback */
+static int SetPassword(char* passwd, int sz, int rw, void* userdata)
+{
+ XSTRNCPY(passwd, userdata, sz);
+ return XSTRLEN(userdata);
+}
+
+
+/* Ethernet Header */
+typedef struct EthernetHdr {
+ byte dst[ETHER_IF_ADDR_LEN]; /* destination host address */
+ byte src[ETHER_IF_ADDR_LEN]; /* source host address */
+ word16 type; /* IP, ARP, etc */
+} EthernetHdr;
+
+
+/* IP Header */
+typedef struct IpHdr {
+ byte ver_hl; /* version/header length */
+ byte tos; /* type of service */
+ word16 length; /* total length */
+ word16 id; /* identification */
+ word16 offset; /* fragment offset field */
+ byte ttl; /* time to live */
+ byte protocol; /* protocol */
+ word16 sum; /* checksum */
+ word32 src; /* source address */
+ word32 dst; /* destination address */
+} IpHdr;
+
+
+#define IP_HL(ip) ( (((ip)->ver_hl) & 0x0f) * 4)
+#define IP_V(ip) ( ((ip)->ver_hl) >> 4)
+
+/* TCP Header */
+typedef struct TcpHdr {
+ word16 srcPort; /* source port */
+ word16 dstPort; /* destination port */
+ word32 sequence; /* sequence number */
+ word32 ack; /* acknoledgment number */
+ byte offset; /* data offset, reserved */
+ byte flags; /* option flags */
+ word16 window; /* window */
+ word16 sum; /* checksum */
+ word16 urgent; /* urgent pointer */
+} TcpHdr;
+
+#define TCP_LEN(tcp) ( (((tcp)->offset & 0xf0) >> 4) * 4)
+#define TCP_FIN 0x01
+#define TCP_SYN 0x02
+#define TCP_RST 0x04
+#define TCP_ACK 0x10
+
+
+
+
+
+/* Use platform specific GetError to write to tracfile if tracing */
+static void Trace(int idx)
+{
+ if (TraceOn) {
+ char buffer[MAX_ERROR_LEN];
+ GetError(idx, buffer);
+ fprintf(TraceFile, "\t%s\n", buffer);
+#ifdef DEBUG_SNIFFER
+ fprintf(stderr, "\t%s\n", buffer);
+#endif
+ }
+}
+
+
+/* Show TimeStamp for beginning of packet Trace */
+static void TraceHeader(void)
+{
+ if (TraceOn) {
+ time_t ticks = time(NULL);
+ fprintf(TraceFile, "\n%s", ctime(&ticks));
+ }
+}
+
+
+/* Show Set Server info for Trace */
+static void TraceSetServer(const char* server, int port, const char* keyFile)
+{
+ if (TraceOn) {
+ fprintf(TraceFile, "\tTrying to install a new Sniffer Server with\n");
+ fprintf(TraceFile, "\tserver: %s, port: %d, keyFile: %s\n", server,
+ port, keyFile);
+ }
+}
+
+
+/* Trace got packet number */
+static void TracePacket(void)
+{
+ if (TraceOn) {
+ static word32 packetNumber = 0;
+ fprintf(TraceFile, "\tGot a Packet to decode, packet %u\n",
+ ++packetNumber);
+ }
+}
+
+
+/* Convert network byte order address into human readable */
+static char* IpToS(word32 addr, char* str)
+{
+ byte* p = (byte*)&addr;
+
+ SNPRINTF(str, TRACE_MSG_SZ, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
+
+ return str;
+}
+
+
+/* Show destination and source address from Ip Hdr for packet Trace */
+static void TraceIP(IpHdr* iphdr)
+{
+ if (TraceOn) {
+ char src[TRACE_MSG_SZ];
+ char dst[TRACE_MSG_SZ];
+ fprintf(TraceFile, "\tdst:%s src:%s\n", IpToS(iphdr->dst, dst),
+ IpToS(iphdr->src, src));
+ }
+}
+
+
+/* Show destination and source port from Tcp Hdr for packet Trace */
+static void TraceTcp(TcpHdr* tcphdr)
+{
+ if (TraceOn) {
+ fprintf(TraceFile, "\tdstPort:%u srcPort:%u\n", ntohs(tcphdr->dstPort),
+ ntohs(tcphdr->srcPort));
+ }
+}
+
+
+/* Show sequence and payload length for Trace */
+static void TraceSequence(word32 seq, int len)
+{
+ if (TraceOn) {
+ fprintf(TraceFile, "\tSequence:%u, payload length:%d\n", seq, len);
+ }
+}
+
+
+/* Show relative expected and relative received sequences */
+static void TraceRelativeSequence(word32 expected, word32 got)
+{
+ if (TraceOn) {
+ fprintf(TraceFile, "\tExpected sequence:%u, received sequence:%u\n",
+ expected, got);
+ }
+}
+
+
+/* Show server sequence startup from SYN */
+static void TraceServerSyn(word32 seq)
+{
+ if (TraceOn) {
+ fprintf(TraceFile, "\tServer SYN, Sequence Start:%u\n", seq);
+ }
+}
+
+
+/* Show client sequence startup from SYN */
+static void TraceClientSyn(word32 seq)
+{
+ if (TraceOn) {
+ fprintf(TraceFile, "\tClient SYN, Sequence Start:%u\n", seq);
+ }
+}
+
+
+/* Show client FIN capture */
+static void TraceClientFin(word32 finSeq, word32 relSeq)
+{
+ if (TraceOn) {
+ fprintf(TraceFile, "\tClient FIN capture:%u, current SEQ:%u\n",
+ finSeq, relSeq);
+ }
+}
+
+
+/* Show server FIN capture */
+static void TraceServerFin(word32 finSeq, word32 relSeq)
+{
+ if (TraceOn) {
+ fprintf(TraceFile, "\tServer FIN capture:%u, current SEQ:%u\n",
+ finSeq, relSeq);
+ }
+}
+
+
+/* Show number of SSL data bytes decoded, could be 0 (ok) */
+static void TraceGotData(int bytes)
+{
+ if (TraceOn) {
+ fprintf(TraceFile, "\t%d bytes of SSL App data processed\n", bytes);
+ }
+}
+
+
+/* Show bytes added to old SSL App data */
+static void TraceAddedData(int newBytes, int existingBytes)
+{
+ if (TraceOn) {
+ fprintf(TraceFile,
+ "\t%d bytes added to %d exisiting bytes in User Buffer\n",
+ newBytes, existingBytes);
+ }
+}
+
+
+/* Show Stale Session */
+static void TraceStaleSession(SnifferSession* session)
+{
+ if (TraceOn) {
+ fprintf(TraceFile, "\tFound a stale session\n");
+ }
+}
+
+
+/* Show Finding Stale Sessions */
+static void TraceFindingStale()
+{
+ if (TraceOn) {
+ fprintf(TraceFile, "\tTrying to find Stale Sessions\n");
+ }
+}
+
+
+/* Show Removed Session */
+static void TraceRemovedSession()
+{
+ if (TraceOn) {
+ fprintf(TraceFile, "\tRemoved it\n");
+ }
+}
+
+
+/* Set user error string */
+static void SetError(int idx, char* error, SnifferSession* session, int fatal)
+{
+ GetError(idx, error);
+ Trace(idx);
+ if (session && fatal == FATAL_ERROR_STATE)
+ session->flags.fatalError = 1;
+}
+
+
+/* See if this IPV4 network order address has been registered */
+/* return 1 is true, 0 is false */
+static int IsServerRegistered(word32 addr)
+{
+ int ret = 0; /* false */
+ SnifferServer* sniffer;
+
+ LockMutex(&ServerListMutex);
+
+ sniffer = ServerList;
+ while (sniffer) {
+ if (sniffer->server == addr) {
+ ret = 1;
+ break;
+ }
+ sniffer = sniffer->next;
+ }
+
+ UnLockMutex(&ServerListMutex);
+
+ return ret;
+}
+
+
+/* See if this port has been registered to watch */
+/* return 1 is true, 0 is false */
+static int IsPortRegistered(word32 port)
+{
+ int ret = 0; /* false */
+ SnifferServer* sniffer;
+
+ LockMutex(&ServerListMutex);
+
+ sniffer = ServerList;
+ while (sniffer) {
+ if (sniffer->port == port) {
+ ret = 1;
+ break;
+ }
+ sniffer = sniffer->next;
+ }
+
+ UnLockMutex(&ServerListMutex);
+
+ return ret;
+}
+
+
+/* Get SnifferServer from IP and Port */
+static SnifferServer* GetSnifferServer(IpInfo* ipInfo, TcpInfo* tcpInfo)
+{
+ SnifferServer* sniffer;
+
+ LockMutex(&ServerListMutex);
+
+ sniffer = ServerList;
+ while (sniffer) {
+ if (sniffer->port == tcpInfo->srcPort && sniffer->server == ipInfo->src)
+ break;
+ if (sniffer->port == tcpInfo->dstPort && sniffer->server == ipInfo->dst)
+ break;
+ sniffer = sniffer->next;
+ }
+
+ UnLockMutex(&ServerListMutex);
+
+ return sniffer;
+}
+
+
+/* Hash the Session Info, return hash row */
+static word32 SessionHash(IpInfo* ipInfo, TcpInfo* tcpInfo)
+{
+ word32 hash = ipInfo->src * ipInfo->dst;
+ hash *= tcpInfo->srcPort * tcpInfo->dstPort;
+
+ return hash % HASH_SIZE;
+}
+
+
+/* Get Exisiting SnifferSession from IP and Port */
+static SnifferSession* GetSnifferSession(IpInfo* ipInfo, TcpInfo* tcpInfo)
+{
+ SnifferSession* session;
+
+ word32 row = SessionHash(ipInfo, tcpInfo);
+ assert(row >= 0 && row <= HASH_SIZE);
+
+ LockMutex(&SessionMutex);
+
+ session = SessionTable[row];
+ while (session) {
+ if (session->server == ipInfo->src && session->client == ipInfo->dst &&
+ session->srvPort == tcpInfo->srcPort &&
+ session->cliPort == tcpInfo->dstPort)
+ break;
+ if (session->client == ipInfo->src && session->server == ipInfo->dst &&
+ session->cliPort == tcpInfo->srcPort &&
+ session->srvPort == tcpInfo->dstPort)
+ break;
+
+ session = session->next;
+ }
+
+ UnLockMutex(&SessionMutex);
+
+ /* determine side */
+ if (session) {
+ if (ipInfo->dst == session->context->server &&
+ tcpInfo->dstPort == session->context->port)
+ session->flags.side = SERVER_END;
+ else
+ session->flags.side = CLIENT_END;
+ }
+
+ return session;
+}
+
+
+/* Sets the private key for a specific server and port */
+/* returns 0 on success, -1 on error */
+int ssl_SetPrivateKey(const char* serverAddress, int port, const char* keyFile,
+ int keyType, const char* password, char* error)
+{
+ int ret;
+ int type = (keyType == FILETYPE_PEM) ? SSL_FILETYPE_PEM :
+ SSL_FILETYPE_ASN1;
+ SnifferServer* sniffer;
+
+ TraceHeader();
+ TraceSetServer(serverAddress, port, keyFile);
+
+ sniffer = (SnifferServer*)malloc(sizeof(SnifferServer));
+ if (sniffer == NULL) {
+ SetError(MEMORY_STR, error, NULL, 0);
+ return -1;
+ }
+ InitSnifferServer(sniffer);
+
+ XSTRNCPY(sniffer->address, serverAddress, MAX_SERVER_ADDRESS);
+ sniffer->server = inet_addr(sniffer->address);
+ sniffer->port = port;
+
+ /* start in client mode since SSL_new needs a cert for server */
+ sniffer->ctx = SSL_CTX_new(SSLv3_client_method());
+ if (!sniffer->ctx) {
+ SetError(MEMORY_STR, error, NULL, 0);
+ FreeSnifferServer(sniffer);
+ return -1;
+ }
+
+ if (password){
+ SSL_CTX_set_default_passwd_cb(sniffer->ctx, SetPassword);
+ SSL_CTX_set_default_passwd_cb_userdata(sniffer->ctx, (void*)password);
+ }
+ ret = SSL_CTX_use_PrivateKey_file(sniffer->ctx, keyFile, type);
+ if (ret != SSL_SUCCESS) {
+ SetError(KEY_FILE_STR, error, NULL, 0);
+ FreeSnifferServer(sniffer);
+ return -1;
+ }
+ Trace(NEW_SERVER_STR);
+
+ LockMutex(&ServerListMutex);
+
+ sniffer->next = ServerList;
+ ServerList = sniffer;
+
+ UnLockMutex(&ServerListMutex);
+
+ return 0;
+}
+
+
+/* Check IP Header for IPV4, TCP, and a registered server address */
+/* returns 0 on success, -1 on error */
+static int CheckIpHdr(IpHdr* iphdr, IpInfo* info, char* error)
+{
+ int version = IP_V(iphdr);
+
+ TraceIP(iphdr);
+ Trace(IP_CHECK_STR);
+ if (version != IPV4) {
+ SetError(BAD_IPVER_STR, error, NULL, 0);
+ return -1;
+ }
+
+ if (iphdr->protocol != TCP_PROTOCOL) {
+ SetError(BAD_PROTO_STR, error, NULL, 0);
+ return -1;
+ }
+
+ if (!IsServerRegistered(iphdr->src) && !IsServerRegistered(iphdr->dst)) {
+ SetError(SERVER_NOT_REG_STR, error, NULL, 0);
+ return -1;
+ }
+
+ info->length = IP_HL(iphdr);
+ info->total = ntohs(iphdr->length);
+ info->src = iphdr->src;
+ info->dst = iphdr->dst;
+
+ return 0;
+}
+
+
+/* Check TCP Header for a registered port */
+/* returns 0 on success, -1 on error */
+static int CheckTcpHdr(TcpHdr* tcphdr, TcpInfo* info, char* error)
+{
+ TraceTcp(tcphdr);
+ Trace(TCP_CHECK_STR);
+ info->srcPort = ntohs(tcphdr->srcPort);
+ info->dstPort = ntohs(tcphdr->dstPort);
+ info->length = TCP_LEN(tcphdr);
+ info->sequence = ntohl(tcphdr->sequence);
+ info->fin = tcphdr->flags & TCP_FIN;
+ info->rst = tcphdr->flags & TCP_RST;
+ info->syn = tcphdr->flags & TCP_SYN;
+ info->ack = tcphdr->flags & TCP_ACK;
+
+ if (!IsPortRegistered(info->srcPort) && !IsPortRegistered(info->dstPort)) {
+ SetError(SERVER_PORT_NOT_REG_STR, error, NULL, 0);
+ return -1;
+ }
+
+ return 0;
+}
+
+
+/* Decode Record Layer Header */
+static int GetRecordHeader(const byte* input, RecordLayerHeader* rh, int* size)
+{
+ XMEMCPY(rh, input, RECORD_HEADER_SZ);
+ *size = (rh->length[0] << 8) | rh->length[1];
+
+ if (*size > (RECORD_SIZE + MAX_COMP_EXTRA + MAX_MSG_EXTRA))
+ return LENGTH_ERROR;
+
+ return 0;
+}
+
+
+/* Process Client Key Exchange, RSA only */
+static int ProcessClientKeyExchange(const byte* input, int* sslBytes,
+ SnifferSession* session, char* error)
+{
+ word32 idx = 0;
+ RsaKey key;
+ int ret;
+
+ InitRsaKey(&key, 0);
+
+ ret = RsaPrivateKeyDecode(session->context->ctx->privateKey.buffer,
+ &idx, &key, session->context->ctx->privateKey.length);
+ if (ret == 0) {
+ int length = RsaEncryptSize(&key);
+
+ if (IsTLS(session->sslServer))
+ input += 2; /* tls pre length */
+
+ ret = RsaPrivateDecrypt(input, length,
+ session->sslServer->arrays.preMasterSecret, SECRET_LEN, &key);
+
+ if (ret != SECRET_LEN) {
+ SetError(RSA_DECRYPT_STR, error, session, FATAL_ERROR_STATE);
+ FreeRsaKey(&key);
+ return -1;
+ }
+ ret = 0; /* not in error state */
+ session->sslServer->arrays.preMasterSz = SECRET_LEN;
+
+ /* store for client side as well */
+ XMEMCPY(session->sslClient->arrays.preMasterSecret,
+ session->sslServer->arrays.preMasterSecret, SECRET_LEN);
+ session->sslClient->arrays.preMasterSz = SECRET_LEN;
+
+ #ifdef SHOW_SECRETS
+ {
+ int i;
+ printf("pre master secret: ");
+ for (i = 0; i < SECRET_LEN; i++)
+ printf("%02x", session->sslServer->arrays.preMasterSecret[i]);
+ printf("\n");
+ }
+ #endif
+ }
+ else {
+ SetError(RSA_DECODE_STR, error, session, FATAL_ERROR_STATE);
+ FreeRsaKey(&key);
+ return -1;
+ }
+
+ if (SetCipherSpecs(session->sslServer) != 0) {
+ SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
+ FreeRsaKey(&key);
+ return -1;
+ }
+
+ if (SetCipherSpecs(session->sslClient) != 0) {
+ SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
+ FreeRsaKey(&key);
+ return -1;
+ }
+
+ MakeMasterSecret(session->sslServer);
+ MakeMasterSecret(session->sslClient);
+#ifdef SHOW_SECRETS
+ {
+ int i;
+ printf("server master secret: ");
+ for (i = 0; i < SECRET_LEN; i++)
+ printf("%02x", session->sslServer->arrays.masterSecret[i]);
+ printf("\n");
+
+ printf("client master secret: ");
+ for (i = 0; i < SECRET_LEN; i++)
+ printf("%02x", session->sslClient->arrays.masterSecret[i]);
+ printf("\n");
+
+ printf("server suite = %d\n", session->sslServer->options.cipherSuite);
+ printf("client suite = %d\n", session->sslClient->options.cipherSuite);
+ }
+#endif
+
+ FreeRsaKey(&key);
+ return ret;
+}
+
+
+/* Process Server Hello */
+static int ProcessServerHello(const byte* input, int* sslBytes,
+ SnifferSession* session, char* error)
+{
+ ProtocolVersion pv;
+ byte b;
+ int toRead = sizeof(ProtocolVersion) + RAN_LEN + ENUM_LEN;
+
+ /* make sure we didn't miss ClientHello */
+ if (session->flags.clientHello == 0) {
+ SetError(MISSED_CLIENT_HELLO_STR, error, session, FATAL_ERROR_STATE);
+ return -1;
+ }
+
+ /* make sure can read through session len */
+ if (toRead > *sslBytes) {
+ SetError(SERVER_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
+ return -1;
+ }
+
+ XMEMCPY(&pv, input, sizeof(ProtocolVersion));
+ input += sizeof(ProtocolVersion);
+ *sslBytes -= sizeof(ProtocolVersion);
+
+ session->sslServer->version = pv;
+ session->sslClient->version = pv;
+
+ XMEMCPY(session->sslServer->arrays.serverRandom, input, RAN_LEN);
+ XMEMCPY(session->sslClient->arrays.serverRandom, input, RAN_LEN);
+ input += RAN_LEN;
+ *sslBytes -= RAN_LEN;
+
+ b = *input++;
+ *sslBytes -= 1;
+
+ /* make sure can read through compression */
+ if ( (b + SUITE_LEN + ENUM_LEN) > *sslBytes) {
+ SetError(SERVER_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
+ return -1;
+ }
+ XMEMCPY(session->sslServer->arrays.sessionID, input, ID_LEN);
+ input += b;
+ *sslBytes -= b;
+
+ (void)*input++; /* eat first byte, always 0 */
+ b = *input++;
+ session->sslServer->options.cipherSuite = b;
+ session->sslClient->options.cipherSuite = b;
+ *sslBytes -= SUITE_LEN;
+
+ if (XMEMCMP(session->sslServer->arrays.sessionID,
+ session->sslClient->arrays.sessionID, ID_LEN) == 0) {
+ /* resuming */
+ SSL_SESSION* resume = GetSession(session->sslServer,
+ session->sslServer->arrays.masterSecret);
+ if (resume == NULL) {
+ SetError(BAD_SESSION_RESUME_STR, error, session, FATAL_ERROR_STATE);
+ return -1;
+ }
+ /* make sure client has master secret too */
+ XMEMCPY(session->sslClient->arrays.masterSecret,
+ session->sslServer->arrays.masterSecret, SECRET_LEN);
+ session->flags.resuming = 1;
+
+ Trace(SERVER_DID_RESUMPTION_STR);
+ if (SetCipherSpecs(session->sslServer) != 0) {
+ SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
+ return -1;
+ }
+
+ if (SetCipherSpecs(session->sslClient) != 0) {
+ SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
+ return -1;
+ }
+
+ if (session->sslServer->options.tls) {
+ DeriveTlsKeys(session->sslServer);
+ DeriveTlsKeys(session->sslClient);
+ }
+ else {
+ DeriveKeys(session->sslServer);
+ DeriveKeys(session->sslClient);
+ }
+ }
+#ifdef SHOW_SECRETS
+ {
+ int i;
+ printf("cipher suite = 0x%02x\n",
+ session->sslServer->options.cipherSuite);
+ printf("server random: ");
+ for (i = 0; i < RAN_LEN; i++)
+ printf("%02x", session->sslServer->arrays.serverRandom[i]);
+ printf("\n");
+ }
+#endif
+ return 0;
+}
+
+
+/* Process normal Client Hello */
+static int ProcessClientHello(const byte* input, int* sslBytes,
+ SnifferSession* session, char* error)
+{
+ byte sessionLen;
+ int toRead = sizeof(ProtocolVersion) + RAN_LEN + ENUM_LEN;
+
+ session->flags.clientHello = 1; /* don't process again */
+
+ /* make sure can read up to session len */
+ if (toRead > *sslBytes) {
+ SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
+ return -1;
+ }
+
+ /* skip, get negotiated one from server hello */
+ input += sizeof(ProtocolVersion);
+ *sslBytes -= sizeof(ProtocolVersion);
+
+ XMEMCPY(session->sslServer->arrays.clientRandom, input, RAN_LEN);
+ XMEMCPY(session->sslClient->arrays.clientRandom, input, RAN_LEN);
+
+ input += RAN_LEN;
+ *sslBytes -= RAN_LEN;
+
+ /* store session in case trying to resume */
+ sessionLen = *input++;
+ if (sessionLen) {
+ if (ID_LEN > *sslBytes) {
+ SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
+ return -1;
+ }
+ Trace(CLIENT_RESUME_TRY_STR);
+ XMEMCPY(session->sslClient->arrays.sessionID, input, ID_LEN);
+ }
+#ifdef SHOW_SECRETS
+ {
+ int i;
+ printf("client random: ");
+ for (i = 0; i < RAN_LEN; i++)
+ printf("%02x", session->sslServer->arrays.clientRandom[i]);
+ printf("\n");
+ }
+#endif
+
+ return 0;
+}
+
+
+/* Process HandShake input */
+static int DoHandShake(const byte* input, int* sslBytes, IpInfo* ipInfo,
+ TcpInfo* tcpInfo, SnifferSession* session, char* error)
+{
+ byte type;
+ int size;
+ int ret = 0;
+
+ if (*sslBytes < HANDSHAKE_HEADER_SZ) {
+ SetError(HANDSHAKE_INPUT_STR, error, session, FATAL_ERROR_STATE);
+ return -1;
+ }
+ type = input[0];
+ size = (input[1] << 16) | (input[2] << 8) | input[3];
+
+ input += HANDSHAKE_HEADER_SZ;
+ *sslBytes -= HANDSHAKE_HEADER_SZ;
+
+ if (*sslBytes < size) {
+ SetError(HANDSHAKE_INPUT_STR, error, session, FATAL_ERROR_STATE);
+ return -1;
+ }
+
+ switch (type) {
+ case hello_verify_request:
+ Trace(GOT_HELLO_VERIFY_STR);
+ break;
+ case server_hello:
+ Trace(GOT_SERVER_HELLO_STR);
+ ret = ProcessServerHello(input, sslBytes, session, error);
+ break;
+ case certificate_request:
+ Trace(GOT_CERT_REQ_STR);
+ break;
+ case server_key_exchange:
+ Trace(GOT_SERVER_KEY_EX_STR);
+ break;
+ case certificate:
+ Trace(GOT_CERT_STR);
+ break;
+ case server_hello_done:
+ Trace(GOT_SERVER_HELLO_DONE_STR);
+ break;
+ case finished:
+ Trace(GOT_FINISHED_STR);
+ {
+ SSL* ssl;
+ word32 inOutIdx = 0;
+
+ if (session->flags.side == SERVER_END)
+ ssl = session->sslServer;
+ else
+ ssl = session->sslClient;
+ ret = DoFinished(ssl, input, &inOutIdx, SNIFF);
+
+ if (ret == 0 && session->flags.cached == 0) {
+ AddSession(session->sslServer);
+ session->flags.cached = 1;
+ }
+ }
+ break;
+ case client_hello:
+ Trace(GOT_CLIENT_HELLO_STR);
+ ret = ProcessClientHello(input, sslBytes, session, error);
+ break;
+ case client_key_exchange:
+ Trace(GOT_CLIENT_KEY_EX_STR);
+ ret = ProcessClientKeyExchange(input, sslBytes, session, error);
+ break;
+ case certificate_verify:
+ Trace(GOT_CERT_VER_STR);
+ break;
+ default:
+ SetError(GOT_UNKNOWN_HANDSHAKE_STR, error, session, 0);
+ return -1;
+ }
+
+ return ret;
+}
+
+
+/* Decrypt input into plain output */
+static void Decrypt(SSL* ssl, byte* output, const byte* input, word32 sz)
+{
+ switch (ssl->specs.bulk_cipher_algorithm) {
+ #ifdef BUILD_ARC4
+ case rc4:
+ Arc4Process(&ssl->decrypt.arc4, output, input, sz);
+ break;
+ #endif
+
+ #ifdef BUILD_DES3
+ case triple_des:
+ Des3_CbcDecrypt(&ssl->decrypt.des3, output, input, sz);
+ break;
+ #endif
+
+ #ifdef BUILD_AES
+ case aes:
+ AesCbcDecrypt(&ssl->decrypt.aes, output, input, sz);
+ break;
+ #endif
+
+ #ifdef BUILD_HC128
+ case hc128:
+ Hc128_Process(&ssl->decrypt.hc128, output, input, sz);
+ break;
+ #endif
+
+ #ifdef BUILD_RABBIT
+ case rabbit:
+ RabbitProcess(&ssl->decrypt.rabbit, output, input, sz);
+ break;
+ #endif
+ }
+}
+
+
+/* Decrypt input message into output, adjust output steam if needed */
+static const byte* DecryptMessage(SSL* ssl, const byte* input, word32 sz,
+ byte* output)
+{
+ Decrypt(ssl, output, input, sz);
+ ssl->keys.encryptSz = sz;
+ if (ssl->options.tls1_1 && ssl->specs.cipher_type == block)
+ return output + ssl->specs.block_size; /* go past TLSv1.1 IV */
+
+ return output;
+}
+
+
+/* remove session from table, use rowHint if no info (means we have a lock) */
+static void RemoveSession(SnifferSession* session, IpInfo* ipInfo,
+ TcpInfo* tcpInfo, word32 rowHint)
+{
+ SnifferSession* previous = 0;
+ SnifferSession* current;
+ word32 row = rowHint;
+ int haveLock = 0;
+
+ if (ipInfo && tcpInfo)
+ row = SessionHash(ipInfo, tcpInfo);
+ else
+ haveLock = 1;
+
+ assert(row >= 0 && row <= HASH_SIZE);
+ Trace(REMOVE_SESSION_STR);
+
+ if (!haveLock)
+ LockMutex(&SessionMutex);
+
+ current = SessionTable[row];
+
+ while (current) {
+ if (current == session) {
+ if (previous)
+ previous->next = current->next;
+ else
+ SessionTable[row] = current->next;
+ FreeSnifferSession(session);
+ TraceRemovedSession();
+ break;
+ }
+ previous = current;
+ current = current->next;
+ }
+
+ if (!haveLock)
+ UnLockMutex(&SessionMutex);
+}
+
+
+/* Remove stale sessions from the Session Table, have a lock */
+static void RemoveStaleSessions()
+{
+ word32 i;
+ SnifferSession* session;
+
+ for (i = 0; i < HASH_SIZE; i++) {
+ session = SessionTable[i];
+ while (session) {
+ SnifferSession* next = session->next;
+ if (time(NULL) >= session->bornOn + SNIFFER_TIMEOUT) {
+ TraceStaleSession(session);
+ RemoveSession(session, NULL, NULL, i);
+ }
+ session = next;
+ }
+ }
+}
+
+
+/* Create a new Sniffer Session */
+static SnifferSession* CreateSession(IpInfo* ipInfo, TcpInfo* tcpInfo,
+ char* error)
+{
+ SnifferSession* session = 0;
+ int row;
+
+ Trace(NEW_SESSION_STR);
+ /* create a new one */
+ session = (SnifferSession*)malloc(sizeof(SnifferSession));
+ if (session == NULL) {
+ SetError(MEMORY_STR, error, NULL, 0);
+ return 0;
+ }
+ InitSession(session);
+ session->server = ipInfo->dst;
+ session->client = ipInfo->src;
+ session->srvPort = tcpInfo->dstPort;
+ session->cliPort = tcpInfo->srcPort;
+ session->cliSeqStart = tcpInfo->sequence;
+ session->cliExpected = 1; /* relative */
+ session->bornOn = time(NULL);
+
+ session->context = GetSnifferServer(ipInfo, tcpInfo);
+ if (session->context == NULL) {
+ SetError(SERVER_NOT_REG_STR, error, NULL, 0);
+ free(session);
+ return 0;
+ }
+
+ session->sslServer = SSL_new(session->context->ctx);
+ session->sslClient = SSL_new(session->context->ctx);
+ if (session->sslClient == NULL) {
+ if (session->sslServer) {
+ SSL_free(session->sslClient);
+ session->sslClient = 0;
+ }
+ SetError(BAD_NEW_SSL_STR, error, session, FATAL_ERROR_STATE);
+ free(session);
+ return 0;
+ }
+ /* put server back into server mode */
+ session->sslServer->options.side = SERVER_END;
+
+ row = SessionHash(ipInfo, tcpInfo);
+
+ /* add it to the session table */
+ LockMutex(&SessionMutex);
+
+ session->next = SessionTable[row];
+ SessionTable[row] = session;
+
+ SessionCount++;
+
+ if ( (SessionCount % HASH_SIZE) == 0) {
+ TraceFindingStale();
+ RemoveStaleSessions();
+ }
+
+ UnLockMutex(&SessionMutex);
+
+ /* determine headed side */
+ if (ipInfo->dst == session->context->server &&
+ tcpInfo->dstPort == session->context->port)
+ session->flags.side = SERVER_END;
+ else
+ session->flags.side = CLIENT_END;
+
+ return session;
+}
+
+
+/* Process Old Client Hello Input */
+static int DoOldHello(SnifferSession* session, const byte* sslFrame,
+ int* rhSize, int* sslBytes, char* error)
+{
+ const byte* input = sslFrame;
+ byte b0, b1;
+ word32 idx = 0;
+ int ret;
+
+ Trace(GOT_OLD_CLIENT_HELLO_STR);
+ session->flags.clientHello = 1; /* don't process again */
+ b0 = *input++;
+ b1 = *input++;
+ *sslBytes -= 2;
+ *rhSize = ((b0 & 0x7f) << 8) | b1;
+
+ if (*rhSize > *sslBytes) {
+ SetError(OLD_CLIENT_INPUT_STR, error, session, FATAL_ERROR_STATE);
+ return -1;
+ }
+
+ ret = ProcessOldClientHello(session->sslServer, input, &idx, *sslBytes,
+ *rhSize);
+ if (ret < 0) {
+ SetError(BAD_OLD_CLIENT_STR, error, session, FATAL_ERROR_STATE);
+ return -1;
+ }
+
+ Trace(OLD_CLIENT_OK_STR);
+ XMEMCPY(session->sslClient->arrays.clientRandom,
+ session->sslServer->arrays.clientRandom, RAN_LEN);
+
+ *sslBytes -= *rhSize;
+ return 0;
+}
+
+
+/* Calculate the TCP checksum, see RFC 1071 */
+/* return 0 for success, -1 on error */
+/* can be called from decode() with
+ TcpChecksum(&ipInfo, &tcpInfo, sslBytes, packet + ipInfo.length);
+ could also add a 64bit version if type available and using this
+*/
+int TcpChecksum(IpInfo* ipInfo, TcpInfo* tcpInfo, int dataLen,
+ const byte* packet)
+{
+ TcpPseudoHdr pseudo;
+ int count = PSEUDO_HDR_SZ;
+ const word16* data = (word16*)&pseudo;
+ word32 sum = 0;
+ word16 checksum;
+
+ pseudo.src = ipInfo->src;
+ pseudo.dst = ipInfo->dst;
+ pseudo.rsv = 0;
+ pseudo.protocol = TCP_PROTO;
+ pseudo.legnth = htons(tcpInfo->length + dataLen);
+
+ /* pseudo header sum */
+ while (count >= 2) {
+ sum += *data++;
+ count -= 2;
+ }
+
+ count = tcpInfo->length + dataLen;
+ data = (word16*)packet;
+
+ /* main sum */
+ while (count > 1) {
+ sum += *data++;
+ count -=2;
+ }
+
+ /* get left-over, if any */
+ packet = (byte*)data;
+ if (count > 0) {
+ sum += *packet;
+ }
+
+ /* fold 32bit sum into 16 bits */
+ while (sum >> 16)
+ sum = (sum & 0xffff) + (sum >> 16);
+
+ checksum = (word16)~sum;
+ /* checksum should now equal 0, since included already calcd checksum */
+ /* field, but tcp checksum offloading could negate calculation */
+ if (checksum == 0)
+ return 0;
+ return -1;
+}
+
+
+/* Check IP and TCP headers, set payload */
+/* returns 0 on success, -1 on error */
+int CheckHeaders(IpInfo* ipInfo, TcpInfo* tcpInfo, const byte* packet,
+ int length, const byte** sslFrame, int* sslBytes, char* error)
+{
+ TraceHeader();
+ TracePacket();
+ if (length < IP_HDR_SZ) {
+ SetError(PACKET_HDR_SHORT_STR, error, NULL, 0);
+ return -1;
+ }
+ if (CheckIpHdr((IpHdr*)packet, ipInfo, error) != 0)
+ return -1;
+
+ if (length < (ipInfo->length + TCP_HDR_SZ)) {
+ SetError(PACKET_HDR_SHORT_STR, error, NULL, 0);
+ return -1;
+ }
+ if (CheckTcpHdr((TcpHdr*)(packet + ipInfo->length), tcpInfo, error) != 0)
+ return -1;
+
+ *sslFrame = packet + ipInfo->length + tcpInfo->length;
+ if (*sslFrame > packet + length) {
+ SetError(PACKET_HDR_SHORT_STR, error, NULL, 0);
+ return -1;
+ }
+ *sslBytes = packet + length - *sslFrame;
+
+ return 0;
+}
+
+
+/* Create or Find existing session */
+/* returns 0 on success (continue), -1 on error, 1 on success (end) */
+static int CheckSession(IpInfo* ipInfo, TcpInfo* tcpInfo, int sslBytes,
+ SnifferSession** session, char* error)
+{
+ /* create a new SnifferSession on client SYN */
+ if (tcpInfo->syn && !tcpInfo->ack) {
+ TraceClientSyn(tcpInfo->sequence);
+ *session = CreateSession(ipInfo, tcpInfo, error);
+ if (*session == NULL) {
+ *session = GetSnifferSession(ipInfo, tcpInfo);
+ /* already had exisiting, so OK */
+ if (*session)
+ return 1;
+
+ SetError(MEMORY_STR, error, NULL, 0);
+ return -1;
+ }
+ return 1;
+ }
+ /* get existing sniffer session */
+ else {
+ *session = GetSnifferSession(ipInfo, tcpInfo);
+ if (*session == NULL) {
+ /* don't worry about extraneous RST or duplicate FINs */
+ if (tcpInfo->fin || tcpInfo->rst)
+ return 1;
+ /* don't worry about duplicate ACKs either */
+ if (sslBytes == 0 && tcpInfo->ack)
+ return 1;
+
+ SetError(BAD_SESSION_STR, error, NULL, 0);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+
+#ifndef min
+
+static INLINE word32 min(word32 a, word32 b)
+{
+ return a > b ? b : a;
+}
+
+#endif
+
+
+/* Create a Packet Buffer from *begin - end, adjust new *begin and bytesLeft */
+static PacketBuffer* CreateBuffer(word32* begin, word32 end, const byte* data,
+ int* bytesLeft)
+{
+ PacketBuffer* pb;
+
+ int added = end - *begin + 1;
+ assert(*begin <= end);
+
+ pb = (PacketBuffer*)malloc(sizeof(PacketBuffer));
+ if (pb == NULL) return NULL;
+
+ pb->next = 0;
+ pb->begin = *begin;
+ pb->end = end;
+ pb->data = (byte*)malloc(added);
+
+ if (pb->data == NULL) {
+ free(pb);
+ return NULL;
+ }
+ XMEMCPY(pb->data, data, added);
+
+ *bytesLeft -= added;
+ *begin = pb->end + 1;
+
+ return pb;
+}
+
+
+/* Add sslFrame to Reassembly List */
+/* returns 1 (end) on success, -1, on error */
+static int AddToReassembly(byte from, word32 seq, const byte* sslFrame,
+ int sslBytes, SnifferSession* session, char* error)
+{
+ PacketBuffer* add;
+ PacketBuffer** front = (from == SERVER_END) ? &session->cliReassemblyList:
+ &session->srvReassemblyList;
+ PacketBuffer* curr = *front;
+ PacketBuffer* prev = curr;
+
+ word32 startSeq = seq;
+ word32 added;
+ int bytesLeft = sslBytes; /* could be overlapping fragment */
+
+ /* if list is empty add full frame to front */
+ if (!curr) {
+ add = CreateBuffer(&seq, seq + sslBytes - 1, sslFrame, &bytesLeft);
+ if (add == NULL) {
+ SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
+ return -1;
+ }
+ *front = add;
+ return 1;
+ }
+
+ /* add to front if before current front, up to next->begin */
+ if (seq < curr->begin) {
+ word32 end = seq + sslBytes - 1;
+
+ if (end >= curr->begin)
+ end = curr->begin - 1;
+
+ add = CreateBuffer(&seq, end, sslFrame, &bytesLeft);
+ if (add == NULL) {
+ SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
+ return -1;
+ }
+ add->next = curr;
+ *front = add;
+ }
+
+ /* while we have bytes left, try to find a gap to fill */
+ while (bytesLeft > 0) {
+ /* get previous packet in list */
+ while (curr && (seq >= curr->begin)) {
+ prev = curr;
+ curr = curr->next;
+ }
+
+ /* don't add duplicate data */
+ if (prev->end >= seq) {
+ if ( (seq + bytesLeft - 1) <= prev->end)
+ return 1;
+ seq = prev->end + 1;
+ bytesLeft = startSeq + sslBytes - seq;
+ }
+
+ if (!curr)
+ /* we're at the end */
+ added = bytesLeft;
+ else
+ /* we're in between two frames */
+ added = min((word32)bytesLeft, curr->begin - seq);
+
+ /* data already there */
+ if (added == 0)
+ continue;
+
+ add = CreateBuffer(&seq, seq + added - 1, &sslFrame[seq - startSeq],
+ &bytesLeft);
+ if (add == NULL) {
+ SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
+ return -1;
+ }
+ add->next = prev->next;
+ prev->next = add;
+ }
+ return 1;
+}
+
+
+/* Add out of order FIN capture */
+/* returns 1 for success (end) */
+static int AddFinCapture(SnifferSession* session, word32 sequence)
+{
+ if (session->flags.side == SERVER_END) {
+ if (session->finCaputre.cliCounted == 0)
+ session->finCaputre.cliFinSeq = sequence;
+ }
+ else {
+ if (session->finCaputre.srvCounted == 0)
+ session->finCaputre.srvFinSeq = sequence;
+ }
+ return 1;
+}
+
+
+/* Adjust incoming sequence based on side */
+/* returns 0 on success (continue), -1 on error, 1 on success (end) */
+static int AdjustSequence(TcpInfo* tcpInfo, SnifferSession* session,
+ int* sslBytes, const byte** sslFrame, char* error)
+{
+ word32 seqStart = (session->flags.side == SERVER_END) ?
+ session->cliSeqStart :session->srvSeqStart;
+ word32 real = tcpInfo->sequence - seqStart;
+ word32* expected = (session->flags.side == SERVER_END) ?
+ &session->cliExpected : &session->srvExpected;
+ PacketBuffer* reassemblyList = (session->flags.side == SERVER_END) ?
+ session->cliReassemblyList : session->srvReassemblyList;
+
+ /* handle rollover of sequence */
+ if (tcpInfo->sequence < seqStart)
+ real = 0xffffffffU - seqStart + tcpInfo->sequence;
+
+ TraceRelativeSequence(*expected, real);
+
+ if (real < *expected) {
+ Trace(DUPLICATE_STR);
+ if (real + *sslBytes > *expected) {
+ int overlap = *expected - real;
+ Trace(OVERLAP_DUPLICATE_STR);
+
+ /* adjust to expected, remove duplicate */
+ *sslFrame += overlap;
+ *sslBytes -= overlap;
+
+ if (reassemblyList) {
+ word32 newEnd = *expected + *sslBytes;
+
+ if (newEnd > reassemblyList->begin) {
+ Trace(OVERLAP_REASSEMBLY_BEGIN_STR);
+
+ /* remove bytes already on reassembly list */
+ *sslBytes -= newEnd - reassemblyList->begin;
+ }
+ if (newEnd > reassemblyList->end) {
+ Trace(OVERLAP_REASSEMBLY_END_STR);
+
+ /* may be past reassembly list end (could have more on list)
+ so try to add what's past the front->end */
+ AddToReassembly(session->flags.side, reassemblyList->end +1,
+ *sslFrame + reassemblyList->end - *expected + 1,
+ newEnd - reassemblyList->end, session, error);
+ }
+ }
+ }
+ else
+ return 1;
+ }
+ else if (real > *expected) {
+ Trace(OUT_OF_ORDER_STR);
+ if (*sslBytes > 0)
+ return AddToReassembly(session->flags.side, real, *sslFrame,
+ *sslBytes, session, error);
+ else if (tcpInfo->fin)
+ return AddFinCapture(session, real);
+ }
+ /* got expected sequence */
+ *expected += *sslBytes;
+ if (tcpInfo->fin)
+ *expected += 1;
+
+ return 0;
+}
+
+
+/* Check TCP Sequence status */
+/* returns 0 on success (continue), -1 on error, 1 on success (end) */
+static int CheckSequence(IpInfo* ipInfo, TcpInfo* tcpInfo,
+ SnifferSession* session, int* sslBytes,
+ const byte** sslFrame, char* error)
+{
+ int actualLen;
+
+ /* init SEQ from server to client */
+ if (tcpInfo->syn && tcpInfo->ack) {
+ session->srvSeqStart = tcpInfo->sequence;
+ session->srvExpected = 1;
+ TraceServerSyn(tcpInfo->sequence);
+ return 1;
+ }
+
+ /* adjust potential ethernet trailer */
+ actualLen = ipInfo->total - ipInfo->length - tcpInfo->length;
+ if (*sslBytes > actualLen) {
+ *sslBytes = actualLen;
+ }
+
+ TraceSequence(tcpInfo->sequence, *sslBytes);
+
+ return AdjustSequence(tcpInfo, session, sslBytes, sslFrame, error);
+}
+
+
+/* Check Status before record processing */
+/* returns 0 on success (continue), -1 on error, 1 on success (end) */
+static int CheckPreRecord(IpInfo* ipInfo, TcpInfo* tcpInfo,
+ const byte** sslFrame, SnifferSession* session,
+ int* sslBytes, const byte** end, char* error)
+{
+ word32 length;
+ SSL* ssl = (session->flags.side == SERVER_END) ? session->sslServer :
+ session->sslClient;
+ /* remove SnifferSession on 2nd FIN or RST */
+ if (tcpInfo->fin || tcpInfo->rst) {
+ /* flag FIN and RST */
+ if (tcpInfo->fin)
+ session->flags.finCount += 1;
+ else if (tcpInfo->rst)
+ session->flags.finCount += 2;
+
+ if (session->flags.finCount >= 2) {
+ RemoveSession(session, ipInfo, tcpInfo, 0);
+ return 1;
+ }
+ }
+
+ if (session->flags.fatalError == FATAL_ERROR_STATE) {
+ SetError(FATAL_ERROR_STR, error, NULL, 0);
+ return -1;
+ }
+
+ if (*sslBytes == 0) {
+ Trace(NO_DATA_STR);
+ return 1;
+ }
+
+ /* if current partial data, add to end of partial */
+ if ( (length = ssl->buffers.inputBuffer.length) ) {
+ Trace(PARTIAL_ADD_STR);
+
+ if ( (*sslBytes + length) > ssl->buffers.inputBuffer.bufferSize) {
+ SetError(BUFFER_ERROR_STR, error, session, FATAL_ERROR_STATE);
+ return -1;
+ }
+ XMEMCPY(&ssl->buffers.inputBuffer.buffer[length], *sslFrame, *sslBytes);
+ *sslBytes += length;
+ ssl->buffers.inputBuffer.length = *sslBytes;
+ *sslFrame = ssl->buffers.inputBuffer.buffer;
+ *end = *sslFrame + *sslBytes;
+ }
+
+ if (session->flags.clientHello == 0 && **sslFrame != handshake) {
+ int rhSize;
+ int ret = DoOldHello(session, *sslFrame, &rhSize, sslBytes, error);
+ if (ret < 0)
+ return -1; /* error already set */
+ if (*sslBytes <= 0)
+ return 1;
+ }
+
+ return 0;
+}
+
+
+/* See if input on the reassembly list is ready for consuming */
+/* returns 1 for TRUE, 0 for FALSE */
+static int HaveMoreInput(SnifferSession* session, const byte** sslFrame,
+ int* sslBytes, const byte** end)
+{
+ /* sequence and reassembly based on from, not to */
+ int moreInput = 0;
+ PacketBuffer** front = (session->flags.side == SERVER_END) ?
+ &session->cliReassemblyList : &session->srvReassemblyList;
+ word32* expected = (session->flags.side == SERVER_END) ?
+ &session->cliExpected : &session->srvExpected;
+ /* buffer is on receiving end */
+ word32* length = (session->flags.side == SERVER_END) ?
+ &session->sslServer->buffers.inputBuffer.length :
+ &session->sslClient->buffers.inputBuffer.length;
+ byte* buffer = (session->flags.side == SERVER_END) ?
+ session->sslServer->buffers.inputBuffer.buffer :
+ session->sslClient->buffers.inputBuffer.buffer;
+
+ while (*front && ((*front)->begin == *expected) ) {
+ word32 room = STATIC_BUFFER_LEN - *length;
+ word32 packetLen = (*front)->end - (*front)->begin + 1;
+
+ if (packetLen <= room) {
+ PacketBuffer* remove = *front;
+
+ XMEMCPY(&buffer[*length], (*front)->data, packetLen);
+ *length += packetLen;
+ *expected += packetLen;
+
+ /* remove used packet */
+ *front = (*front)->next;
+ FreePacketBuffer(remove);
+
+ moreInput = 1;
+ }
+ else
+ break;
+ }
+ if (moreInput) {
+ *sslFrame = buffer;
+ *sslBytes = *length;
+ *end = buffer + *length;
+ }
+ return moreInput;
+}
+
+
+
+/* Process Message(s) from sslFrame */
+/* return Number of bytes on success, 0 for no data yet, and -1 on error */
+static int ProcessMessage(IpInfo* ipInfo, TcpInfo* tcpInfo,const byte* sslFrame,
+ SnifferSession* session, int sslBytes, byte* data,
+ const byte* end, char* error)
+{
+ const byte* sslBegin = sslFrame;
+ const byte* tmp;
+ RecordLayerHeader rh;
+ int rhSize;
+ int ret;
+ int decoded = 0; /* bytes stored for user in data */
+ int notEnough; /* notEnough bytes yet flag */
+ SSL* ssl = (session->flags.side == SERVER_END) ?
+ session->sslServer : session->sslClient;
+doMessage:
+ notEnough = 0;
+ if (sslBytes >= RECORD_HEADER_SZ) {
+ if (GetRecordHeader(sslFrame, &rh, &rhSize) != 0) {
+ SetError(BAD_RECORD_HDR_STR, error, session, FATAL_ERROR_STATE);
+ return -1;
+ }
+ }
+ else
+ notEnough = 1;
+
+ if (notEnough || rhSize > (sslBytes - RECORD_HEADER_SZ)) {
+ /* don't have enough input yet to process full SSL record */
+ Trace(PARTIAL_INPUT_STR);
+
+ /* store partial if not there already or we advanced */
+ if (ssl->buffers.inputBuffer.length == 0 || sslBegin != sslFrame) {
+ if (sslBytes > ssl->buffers.inputBuffer.bufferSize) {
+ SetError(BUFFER_ERROR_STR, error, session, FATAL_ERROR_STATE);
+ return -1;
+ }
+ XMEMCPY(ssl->buffers.inputBuffer.buffer, sslFrame, sslBytes);
+ ssl->buffers.inputBuffer.length = sslBytes;
+ }
+ if (HaveMoreInput(session, &sslFrame, &sslBytes, &end))
+ goto doMessage;
+ return decoded;
+ }
+ sslFrame += RECORD_HEADER_SZ;
+ sslBytes -= RECORD_HEADER_SZ;
+ tmp = sslFrame + rhSize; /* may have more than one record to process */
+
+ /* decrypt if needed */
+ if (session->flags.side == SERVER_END && session->flags.serverCipherOn)
+ sslFrame = DecryptMessage(ssl, sslFrame, rhSize,
+ ssl->buffers.outputBuffer.buffer);
+ else if (session->flags.side == CLIENT_END && session->flags.clientCipherOn)
+ sslFrame = DecryptMessage(ssl, sslFrame, rhSize,
+ ssl->buffers.outputBuffer.buffer);
+
+ switch ((enum ContentType)rh.type) {
+ case handshake:
+ Trace(GOT_HANDSHAKE_STR);
+ ret = DoHandShake(sslFrame, &sslBytes, ipInfo, tcpInfo, session,
+ error);
+ if (ret != 0) {
+ if (session->flags.fatalError == 0)
+ SetError(BAD_HANDSHAKE_STR,error,session,FATAL_ERROR_STATE);
+ return -1;
+ }
+ break;
+ case change_cipher_spec:
+ if (session->flags.side == SERVER_END)
+ session->flags.serverCipherOn = 1;
+ else
+ session->flags.clientCipherOn = 1;
+ Trace(GOT_CHANGE_CIPHER_STR);
+ break;
+ case application_data:
+ Trace(GOT_APP_DATA_STR);
+ {
+ word32 inOutIdx = 0;
+
+ ret = DoApplicationData(ssl, (byte*)sslFrame, &inOutIdx);
+ if (ret == 0) {
+ ret = ssl->buffers.clearOutputBuffer.length;
+ TraceGotData(ret);
+ if (ret) { /* may be blank message */
+ XMEMCPY(&data[decoded],
+ ssl->buffers.clearOutputBuffer.buffer, ret);
+ TraceAddedData(ret, decoded);
+ decoded += ret;
+ ssl->buffers.clearOutputBuffer.length = 0;
+ }
+ }
+ else {
+ SetError(BAD_APP_DATA_STR, error,session,FATAL_ERROR_STATE);
+ return -1;
+ }
+ }
+ break;
+ case alert:
+ Trace(GOT_ALERT_STR);
+ break;
+ default:
+ SetError(GOT_UNKNOWN_RECORD_STR, error, session, FATAL_ERROR_STATE);
+ return -1;
+ }
+
+ if (tmp < end) {
+ Trace(ANOTHER_MSG_STR);
+ sslFrame = tmp;
+ sslBytes = end - tmp;
+ goto doMessage;
+ }
+
+ /* clear used input */
+ ssl->buffers.inputBuffer.length = 0;
+
+ /* could have more input ready now */
+ if (HaveMoreInput(session, &sslFrame, &sslBytes, &end))
+ goto doMessage;
+
+ return decoded;
+}
+
+
+/* See if we need to process any pending FIN captures */
+static void CheckFinCapture(IpInfo* ipInfo, TcpInfo* tcpInfo,
+ SnifferSession* session)
+{
+ if (session->finCaputre.cliFinSeq && session->finCaputre.cliFinSeq <=
+ session->cliExpected) {
+ if (session->finCaputre.cliCounted == 0) {
+ session->flags.finCount += 1;
+ session->finCaputre.cliCounted = 1;
+ TraceClientFin(session->finCaputre.cliFinSeq, session->cliExpected);
+ }
+ }
+
+ if (session->finCaputre.srvFinSeq && session->finCaputre.srvFinSeq <=
+ session->srvExpected) {
+ if (session->finCaputre.srvCounted == 0) {
+ session->flags.finCount += 1;
+ session->finCaputre.srvCounted = 1;
+ TraceServerFin(session->finCaputre.srvFinSeq, session->srvExpected);
+ }
+ }
+
+ if (session->flags.finCount >= 2)
+ RemoveSession(session, ipInfo, tcpInfo, 0);
+}
+
+
+/* Passes in an IP/TCP packet for decoding (ethernet/localhost frame) removed */
+/* returns Number of bytes on success, 0 for no data yet, and -1 on error */
+int ssl_DecodePacket(const byte* packet, int length, byte* data, char* error)
+{
+ TcpInfo tcpInfo;
+ IpInfo ipInfo;
+ const byte* sslFrame;
+ const byte* end = packet + length;
+ int sslBytes; /* ssl bytes unconsumed */
+ int ret;
+ SnifferSession* session = 0;
+
+ if (CheckHeaders(&ipInfo, &tcpInfo, packet, length, &sslFrame, &sslBytes,
+ error) != 0)
+ return -1;
+
+ ret = CheckSession(&ipInfo, &tcpInfo, sslBytes, &session, error);
+ if (ret == -1) return -1;
+ else if (ret == 1) return 0; /* done for now */
+
+ ret = CheckSequence(&ipInfo, &tcpInfo, session, &sslBytes, &sslFrame,error);
+ if (ret == -1) return -1;
+ else if (ret == 1) return 0; /* done for now */
+
+ ret = CheckPreRecord(&ipInfo, &tcpInfo, &sslFrame, session, &sslBytes,
+ &end, error);
+ if (ret == -1) return -1;
+ else if (ret == 1) return 0; /* done for now */
+
+ ret = ProcessMessage(&ipInfo, &tcpInfo, sslFrame, session, sslBytes, data,
+ end, error);
+ CheckFinCapture(&ipInfo, &tcpInfo, session);
+ return ret;
+}
+
+
+/* Enables (if traceFile)/ Disables debug tracing */
+/* returns 0 on success, -1 on error */
+int ssl_Trace(const char* traceFile, char* error)
+{
+ if (traceFile) {
+ TraceFile = fopen(traceFile, "a");
+ if (!TraceFile) {
+ SetError(BAD_TRACE_FILE_STR, error, NULL, 0);
+ return -1;
+ }
+ TraceOn = 1;
+ }
+ else
+ TraceOn = 0;
+
+ return 0;
+}
+
+
+
+
+#endif /* CYASSL_SNIFFER */
diff --git a/release/src/router/cyassl/src/ssl.c b/release/src/router/cyassl/src/ssl.c
new file mode 100644
index 00000000..68be3614
--- /dev/null
+++ b/release/src/router/cyassl/src/ssl.c
@@ -0,0 +1,3496 @@
+/* ssl.c
+ *
+ * Copyright (C) 2006-2011 Sawtooth Consulting Ltd.
+ *
+ * This file is part of CyaSSL.
+ *
+ * CyaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * CyaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+#include "ssl.h"
+#include "cyassl_int.h"
+#include "cyassl_error.h"
+#include "coding.h"
+
+#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
+ #include "evp.h"
+#endif
+
+#ifdef OPENSSL_EXTRA
+ /* openssl headers begin */
+ #include "hmac.h"
+ #include "crypto.h"
+ #include "des.h"
+ /* openssl headers end, cyassl internal headers next */
+ #include "ctc_hmac.h"
+ #include "random.h"
+ #include "des3.h"
+ #include "ctc_md4.h"
+ #include "coding.h"
+#endif
+
+#ifdef HAVE_ERRNO_H
+ #include <errno.h>
+#endif
+
+#define TRUE 1
+#define FALSE 0
+
+
+#ifndef min
+
+ static INLINE word32 min(word32 a, word32 b)
+ {
+ return a > b ? b : a;
+ }
+
+#endif /* min */
+
+
+
+SSL_CTX* SSL_CTX_new(SSL_METHOD* method)
+{
+ SSL_CTX* ctx = (SSL_CTX*) XMALLOC(sizeof(SSL_CTX), 0, DYNAMIC_TYPE_CTX);
+ if (ctx)
+ InitSSL_Ctx(ctx, method);
+
+ return ctx;
+}
+
+
+void SSL_CTX_free(SSL_CTX* ctx)
+{
+ if (ctx)
+ FreeSSL_Ctx(ctx);
+}
+
+
+SSL* SSL_new(SSL_CTX* ctx)
+{
+
+ SSL* ssl = (SSL*) XMALLOC(sizeof(SSL), ctx->heap, DYNAMIC_TYPE_SSL);
+ if (ssl)
+ if (InitSSL(ssl, ctx) < 0) {
+ FreeSSL(ssl);
+ ssl = 0;
+ }
+
+ return ssl;
+}
+
+
+void SSL_free(SSL* ssl)
+{
+ CYASSL_ENTER("SSL_free");
+ if (ssl)
+ FreeSSL(ssl);
+ CYASSL_LEAVE("SSL_free", 0);
+}
+
+
+int SSL_set_fd(SSL* ssl, int fd)
+{
+ ssl->rfd = fd; /* not used directly to allow IO callbacks */
+ ssl->wfd = fd;
+
+ ssl->IOCB_ReadCtx = &ssl->rfd;
+ ssl->IOCB_WriteCtx = &ssl->wfd;
+
+ return SSL_SUCCESS;
+}
+
+
+int SSL_get_fd(const SSL* ssl)
+{
+ return ssl->rfd;
+}
+
+
+int CyaSSL_negotiate(SSL* ssl)
+{
+ int err = -1;
+
+#ifndef NO_CYASSL_SERVER
+ if (ssl->options.side == SERVER_END)
+ err = SSL_accept(ssl);
+#endif
+
+#ifndef NO_CYASSL_CLIENT
+ if (ssl->options.side == CLIENT_END)
+ err = SSL_connect(ssl);
+#endif
+
+ if (err == SSL_SUCCESS)
+ return 0;
+ else
+ return err;
+}
+
+
+int SSL_write(SSL* ssl, const void* buffer, int sz)
+{
+ int ret;
+
+ CYASSL_ENTER("SSL_write()");
+
+#ifdef HAVE_ERRNO_H
+ errno = 0;
+#endif
+
+ ret = SendData(ssl, buffer, sz);
+
+ CYASSL_LEAVE("SSL_write()", ret);
+
+ if (ret < 0)
+ return SSL_FATAL_ERROR;
+ else
+ return ret;
+}
+
+
+int SSL_read(SSL* ssl, void* buffer, int sz)
+{
+ int ret;
+
+ CYASSL_ENTER("SSL_read()");
+
+#ifdef HAVE_ERRNO_H
+ errno = 0;
+#endif
+
+ ret = ReceiveData(ssl, (byte*)buffer, min(sz, OUTPUT_RECORD_SIZE));
+
+ CYASSL_LEAVE("SSL_read()", ret);
+
+ if (ret < 0)
+ return SSL_FATAL_ERROR;
+ else
+ return ret;
+}
+
+
+int SSL_shutdown(SSL* ssl)
+{
+ CYASSL_ENTER("SSL_shutdown()");
+
+ if (ssl->options.quietShutdown) {
+ CYASSL_MSG("quiet shutdown, no close notify sent");
+ return 0;
+ }
+
+ /* try to send close notify, not an error if can't */
+ if (!ssl->options.isClosed && !ssl->options.connReset &&
+ !ssl->options.sentNotify) {
+ ssl->error = SendAlert(ssl, alert_warning, close_notify);
+ if (ssl->error < 0) {
+ CYASSL_ERROR(ssl->error);
+ return SSL_FATAL_ERROR;
+ }
+ ssl->options.sentNotify = 1; /* don't send close_notify twice */
+ }
+
+ CYASSL_LEAVE("SSL_shutdown()", ssl->error);
+
+ ssl->error = SSL_ERROR_SYSCALL; /* simulate OpenSSL behavior */
+
+ return 0;
+}
+
+
+int SSL_get_error(SSL* ssl, int dummy)
+{
+ if (ssl->error == WANT_READ)
+ return SSL_ERROR_WANT_READ; /* convert to OpenSSL type */
+ else if (ssl->error == WANT_WRITE)
+ return SSL_ERROR_WANT_WRITE; /* convert to OpenSSL type */
+ else if (ssl->error == ZERO_RETURN)
+ return SSL_ERROR_ZERO_RETURN; /* convert to OpenSSL type */
+ return ssl->error;
+}
+
+
+int SSL_want_read(SSL* ssl)
+{
+ if (ssl->error == WANT_READ)
+ return 1;
+
+ return 0;
+}
+
+
+int SSL_want_write(SSL* ssl)
+{
+ if (ssl->error == WANT_WRITE)
+ return 1;
+
+ return 0;
+}
+
+
+char* ERR_error_string(unsigned long errNumber, char* buffer)
+{
+ static char* msg = "Please supply a buffer for error string";
+
+ if (buffer) {
+ SetErrorString(errNumber, buffer);
+ return buffer;
+ }
+
+ return msg;
+}
+
+
+void ERR_error_string_n(unsigned long e, char* buf, size_t len)
+{
+ if (len) ERR_error_string(e, buf);
+}
+
+
+#ifndef NO_FILESYSTEM
+
+void ERR_print_errors_fp(FILE* fp, int err)
+{
+ char buffer[MAX_ERROR_SZ + 1];
+
+ SetErrorString(err, buffer);
+ fprintf(fp, "%s", buffer);
+}
+
+#endif
+
+
+int SSL_pending(SSL* ssl)
+{
+ return ssl->buffers.clearOutputBuffer.length;
+}
+
+
+/* owns der */
+static int AddCA(SSL_CTX* ctx, buffer der)
+{
+ word32 ret;
+ DecodedCert cert;
+ Signer* signer = 0;
+
+ InitDecodedCert(&cert, der.buffer, ctx->heap);
+ ret = ParseCert(&cert, der.length, CA_TYPE, ctx->verifyPeer, 0);
+
+ if (ret == 0) {
+ /* take over signer parts */
+ signer = MakeSigner(ctx->heap);
+ if (!signer)
+ ret = MEMORY_ERROR;
+ else {
+ signer->keyOID = cert.keyOID;
+ signer->publicKey = cert.publicKey;
+ signer->pubKeySize = cert.pubKeySize;
+ signer->name = cert.subjectCN;
+ XMEMCPY(signer->hash, cert.subjectHash, SHA_DIGEST_SIZE);
+
+ cert.publicKey = 0; /* don't free here */
+ cert.subjectCN = 0;
+
+ signer->next = ctx->caList;
+ ctx->caList = signer; /* takes ownership */
+ }
+ }
+
+ FreeDecodedCert(&cert);
+ XFREE(der.buffer, ctx->heap, DYNAMIC_TYPE_CA);
+
+ if (ret == 0) return SSL_SUCCESS;
+ return ret;
+}
+
+
+#ifndef NO_SESSION_CACHE
+
+ /* basic config gives a cache with 33 sessions, adequate for clients and
+ embedded servers
+
+ BIG_SESSION_CACHE allows 1055 sessions, adequate for servers that aren't
+ under heavy load, basically allows 200 new sessions per minute
+
+ HUGE_SESSION_CACHE yields 65,791 sessions, for servers under heavy load,
+ allows over 13,000 new sessions per minute or over 200 new sessions per
+ second
+ */
+ #ifdef HUGE_SESSION_CACHE
+ #define SESSIONS_PER_ROW 11
+ #define SESSION_ROWS 5981
+ #elif defined(BIG_SESSION_CACHE)
+ #define SESSIONS_PER_ROW 5
+ #define SESSION_ROWS 211
+ #else
+ #define SESSIONS_PER_ROW 3
+ #define SESSION_ROWS 11
+ #endif
+
+ typedef struct SessionRow {
+ int nextIdx; /* where to place next one */
+ int totalCount; /* sessions ever on this row */
+ SSL_SESSION Sessions[SESSIONS_PER_ROW];
+ } SessionRow;
+
+ static SessionRow SessionCache[SESSION_ROWS];
+
+ static CyaSSL_Mutex mutex; /* SessionCache mutex */
+
+#endif /* NO_SESSION_CACHE */
+
+
+ static int PemToDer(const unsigned char* buff, long sz, int type,
+ buffer* der, void* heap, EncryptedInfo* info, int* eccKey)
+ {
+ char header[PEM_LINE_LEN];
+ char footer[PEM_LINE_LEN];
+ char* headerEnd;
+ char* footerEnd;
+ long neededSz;
+ int pkcs8 = 0;
+ int dynamicType;
+
+ if (type == CERT_TYPE || type == CA_TYPE) {
+ XSTRNCPY(header, "-----BEGIN CERTIFICATE-----", sizeof(header));
+ XSTRNCPY(footer, "-----END CERTIFICATE-----", sizeof(footer));
+ dynamicType = (type == CA_TYPE) ? DYNAMIC_TYPE_CA :
+ DYNAMIC_TYPE_CERT;
+ } else {
+ XSTRNCPY(header, "-----BEGIN RSA PRIVATE KEY-----", sizeof(header));
+ XSTRNCPY(footer, "-----END RSA PRIVATE KEY-----", sizeof(footer));
+ dynamicType = DYNAMIC_TYPE_KEY;
+ }
+
+ /* find header */
+ headerEnd = XSTRSTR((char*)buff, header);
+ if (!headerEnd && type == PRIVATEKEY_TYPE) { /* may be pkcs8 */
+ XSTRNCPY(header, "-----BEGIN PRIVATE KEY-----", sizeof(header));
+ XSTRNCPY(footer, "-----END PRIVATE KEY-----", sizeof(footer));
+
+ headerEnd = XSTRSTR((char*)buff, header);
+ if (headerEnd)
+ pkcs8 = 1;
+ /*
+ else
+ maybe encrypted "-----BEGIN ENCRYPTED PRIVATE KEY-----"
+ */
+ }
+ if (!headerEnd && type == PRIVATEKEY_TYPE) { /* may be ecc */
+ XSTRNCPY(header, "-----BEGIN EC PRIVATE KEY-----", sizeof(header));
+ XSTRNCPY(footer, "-----END EC PRIVATE KEY-----", sizeof(footer));
+
+ headerEnd = XSTRSTR((char*)buff, header);
+ if (headerEnd)
+ *eccKey = 1;
+ }
+ if (!headerEnd)
+ return SSL_BAD_FILE;
+ headerEnd += XSTRLEN(header);
+
+ /* get next line */
+ if (headerEnd[0] == '\n')
+ headerEnd++;
+ else if (headerEnd[1] == '\n')
+ headerEnd += 2;
+ else
+ return SSL_BAD_FILE;
+
+#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
+ {
+ /* remove encrypted header if there */
+ char encHeader[] = "Proc-Type";
+ char* line = XSTRSTR((char*)buff, encHeader);
+ if (line) {
+ char* newline;
+ char* finish;
+ char* start = XSTRSTR(line, "DES");
+
+ if (!start)
+ start = XSTRSTR(line, "AES");
+
+ if (!start) return SSL_BAD_FILE;
+ if (!info) return SSL_BAD_FILE;
+
+ finish = XSTRSTR(start, ",");
+
+ if (start && finish && (start < finish)) {
+ newline = XSTRSTR(finish, "\r");
+
+ XMEMCPY(info->name, start, finish - start);
+ info->name[finish - start] = 0;
+ XMEMCPY(info->iv, finish + 1, sizeof(info->iv));
+
+ if (!newline) newline = XSTRSTR(finish, "\n");
+ if (newline && (newline > finish)) {
+ info->ivSz = (word32)(newline - (finish + 1));
+ info->set = 1;
+ }
+ else
+ return SSL_BAD_FILE;
+ }
+ else
+ return SSL_BAD_FILE;
+
+ /* eat blank line */
+ while (*newline == '\r' || *newline == '\n')
+ newline++;
+ headerEnd = newline;
+ }
+ }
+#endif /* OPENSSL_EXTRA || HAVE_WEBSERVER */
+
+ /* find footer */
+ footerEnd = XSTRSTR((char*)buff, footer);
+ if (!footerEnd) return SSL_BAD_FILE;
+
+ /* set up der buffer */
+ neededSz = (long)(footerEnd - headerEnd);
+ if (neededSz > sz || neededSz < 0) return SSL_BAD_FILE;
+ der->buffer = (byte*) XMALLOC(neededSz, heap, dynamicType);
+ if (!der->buffer) return MEMORY_ERROR;
+ der->length = neededSz;
+
+ if (Base64Decode((byte*)headerEnd, neededSz, der->buffer,
+ &der->length) < 0)
+ return SSL_BAD_FILE;
+
+ if (pkcs8)
+ return ToTraditional(der->buffer, der->length);
+
+ /* not full support yet
+ if (pkcs8Enc)
+ return ToTraditionalEnc(der->buffer, der->length);
+ */
+
+ return 0;
+ }
+
+
+ static int ProcessBuffer(SSL_CTX* ctx, const unsigned char* buff,
+ long sz, int format, int type)
+ {
+ EncryptedInfo info;
+ buffer der; /* holds DER or RAW (for NTRU) */
+ int dynamicType;
+ int eccKey = 0;
+
+ info.set = 0;
+ der.buffer = 0;
+
+ if (format != SSL_FILETYPE_ASN1 && format != SSL_FILETYPE_PEM
+ && format != SSL_FILETYPE_RAW)
+ return SSL_BAD_FILETYPE;
+
+ if (type == CA_TYPE)
+ dynamicType = DYNAMIC_TYPE_CA;
+ else if (type == CERT_TYPE)
+ dynamicType = DYNAMIC_TYPE_CERT;
+ else
+ dynamicType = DYNAMIC_TYPE_KEY;
+
+ if (format == SSL_FILETYPE_PEM) {
+ if (PemToDer(buff, sz, type, &der, ctx->heap, &info, &eccKey) < 0) {
+ XFREE(der.buffer, ctx->heap, dynamicType);
+ return SSL_BAD_FILE;
+ }
+ }
+ else { /* ASN1 (DER) or RAW (NTRU) */
+ der.buffer = (byte*) XMALLOC(sz, ctx->heap, dynamicType);
+ if (!der.buffer) return MEMORY_ERROR;
+ XMEMCPY(der.buffer, buff, sz);
+ der.length = sz;
+ }
+
+#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
+ if (info.set) {
+ /* decrypt */
+ char password[80];
+ int passwordSz;
+
+ byte key[AES_256_KEY_SIZE];
+ byte iv[AES_IV_SIZE];
+
+ if (!ctx->passwd_cb) return -1;
+
+ /* use file's salt for key derivation, hex decode first */
+ if (Base16Decode(info.iv, info.ivSz, info.iv, &info.ivSz) != 0)
+ return -1;
+
+ passwordSz = ctx->passwd_cb(password, sizeof(password), 0,
+ ctx->userdata);
+ if (EVP_BytesToKey(info.name, "MD5", info.iv, (byte*)password,
+ passwordSz, 1, key, iv) <= 0)
+ return -1;
+
+ if (XSTRNCMP(info.name, "DES-CBC", 7) == 0) {
+ Des des;
+ Des_SetKey(&des, key, info.iv, DES_DECRYPTION);
+ Des_CbcDecrypt(&des, der.buffer, der.buffer, der.length);
+ }
+ else if (XSTRNCMP(info.name, "DES-EDE3-CBC", 13) == 0) {
+ Des3 des;
+ Des3_SetKey(&des, key, info.iv, DES_DECRYPTION);
+ Des3_CbcDecrypt(&des, der.buffer, der.buffer, der.length);
+ }
+ else if (XSTRNCMP(info.name, "AES-128-CBC", 13) == 0) {
+ Aes aes;
+ AesSetKey(&aes, key, AES_128_KEY_SIZE, info.iv, AES_DECRYPTION);
+ AesCbcDecrypt(&aes, der.buffer, der.buffer, der.length);
+ }
+ else if (XSTRNCMP(info.name, "AES-192-CBC", 13) == 0) {
+ Aes aes;
+ AesSetKey(&aes, key, AES_192_KEY_SIZE, info.iv, AES_DECRYPTION);
+ AesCbcDecrypt(&aes, der.buffer, der.buffer, der.length);
+ }
+ else if (XSTRNCMP(info.name, "AES-256-CBC", 13) == 0) {
+ Aes aes;
+ AesSetKey(&aes, key, AES_256_KEY_SIZE, info.iv, AES_DECRYPTION);
+ AesCbcDecrypt(&aes, der.buffer, der.buffer, der.length);
+ }
+ else
+ return SSL_BAD_FILE;
+ }
+#endif /* OPENSSL_EXTRA || HAVE_WEBSERVER */
+
+ if (type == CA_TYPE)
+ return AddCA(ctx, der); /* takes der over */
+ else if (type == CERT_TYPE) {
+ if (ctx->certificate.buffer)
+ XFREE(ctx->certificate.buffer, ctx->heap, dynamicType);
+ ctx->certificate = der; /* takes der over */
+ }
+ else if (type == PRIVATEKEY_TYPE) {
+ if (ctx->privateKey.buffer)
+ XFREE(ctx->privateKey.buffer, ctx->heap, dynamicType);
+ ctx->privateKey = der; /* takes der over */
+ }
+ else {
+ XFREE(der.buffer, ctx->heap, dynamicType);
+ return SSL_BAD_CERTTYPE;
+ }
+
+ if (type == PRIVATEKEY_TYPE && format != SSL_FILETYPE_RAW) {
+ if (!eccKey) {
+ /* make sure RSA key can be used */
+ RsaKey key;
+ word32 idx = 0;
+
+ InitRsaKey(&key, 0);
+ if (RsaPrivateKeyDecode(der.buffer,&idx,&key,der.length) != 0) {
+#ifdef HAVE_ECC
+ /* could have DER ECC, no easy way to tell */
+ if (format == SSL_FILETYPE_ASN1)
+ eccKey = 1; /* try it out */
+#endif
+ if (!eccKey) {
+ FreeRsaKey(&key);
+ return SSL_BAD_FILE;
+ }
+ }
+ FreeRsaKey(&key);
+ }
+#ifdef HAVE_ECC
+ if (eccKey ) {
+ /* make sure ECC key can be used */
+ word32 idx = 0;
+ ecc_key key;
+
+ ecc_init(&key);
+ if (EccPrivateKeyDecode(der.buffer,&idx,&key,der.length) != 0) {
+ ecc_free(&key);
+ return SSL_BAD_FILE;
+ }
+ ecc_free(&key);
+ ctx->haveECDSA = 1;
+ }
+#endif /* HAVE_ECC */
+ }
+
+ return SSL_SUCCESS;
+ }
+
+
+#ifndef NO_FILESYSTEM
+
+#ifndef MICRIUM
+ #define XFILE FILE
+ #define XFOPEN fopen
+ #define XFSEEK fseek
+ #define XFTELL ftell
+ #define XREWIND rewind
+ #define XFREAD fread
+ #define XFCLOSE fclose
+ #define XSEEK_END SEEK_END
+#else
+ #include <fs.h>
+ #define XFILE FS_FILE
+ #define XFOPEN fs_fopen
+ #define XFSEEK fs_fseek
+ #define XFTELL fs_ftell
+ #define XREWIND fs_rewind
+ #define XFREAD fs_fread
+ #define XFCLOSE fs_fclose
+ #define XSEEK_END FS_SEEK_END
+#endif
+
+static int ProcessFile(SSL_CTX* ctx, const char* fname, int format, int type)
+{
+ byte staticBuffer[FILE_BUFFER_SIZE];
+ byte* buffer = staticBuffer;
+ int dynamic = 0;
+ int ret;
+ long sz = 0;
+ XFILE* file = XFOPEN(fname, "rb");
+
+ if (!file) return SSL_BAD_FILE;
+ XFSEEK(file, 0, XSEEK_END);
+ sz = XFTELL(file);
+ XREWIND(file);
+
+ if (sz > sizeof(staticBuffer)) {
+ buffer = (byte*) XMALLOC(sz, ctx->heap, DYNAMIC_TYPE_FILE);
+ if (buffer == NULL) {
+ XFCLOSE(file);
+ return SSL_BAD_FILE;
+ }
+ dynamic = 1;
+ }
+
+ if ( (ret = XFREAD(buffer, sz, 1, file)) < 0)
+ ret = SSL_BAD_FILE;
+ else
+ ret = ProcessBuffer(ctx, buffer, sz, format, type);
+
+ XFCLOSE(file);
+ if (dynamic) XFREE(buffer, ctx->heap, DYNAMIC_TYPE_FILE);
+
+ return ret;
+}
+
+
+/* just one for now TODO: add dir support from path */
+int SSL_CTX_load_verify_locations(SSL_CTX* ctx, const char* file,
+ const char* path)
+{
+ if (ProcessFile(ctx, file, SSL_FILETYPE_PEM, CA_TYPE) == SSL_SUCCESS)
+ return SSL_SUCCESS;
+
+ return SSL_FAILURE;
+}
+
+
+#ifdef CYASSL_DER_LOAD
+
+/* Add format parameter to allow DER load of CA files */
+int CyaSSL_CTX_load_verify_locations(SSL_CTX* ctx, const char* file, int format)
+{
+ if (ProcessFile(ctx, file, format, CA_TYPE) == SSL_SUCCESS)
+ return SSL_SUCCESS;
+
+ return SSL_FAILURE;
+}
+
+#endif /* CYASSL_DER_LOAD */
+
+
+#ifdef CYASSL_CERT_GEN
+
+/* load pem cert from file into der buffer, return der size or error */
+int CyaSSL_PemCertToDer(const char* fileName, unsigned char* derBuf, int derSz)
+{
+ byte staticBuffer[FILE_BUFFER_SIZE];
+ byte* fileBuf = staticBuffer;
+ int dynamic = 0;
+ int ret;
+ int ecc = 0;
+ long sz = 0;
+ XFILE* file = XFOPEN(fileName, "rb");
+ EncryptedInfo info;
+ buffer converted;
+
+ converted.buffer = 0;
+
+ if (!file) return SSL_BAD_FILE;
+ XFSEEK(file, 0, XSEEK_END);
+ sz = XFTELL(file);
+ XREWIND(file);
+
+ if (sz > sizeof(staticBuffer)) {
+ fileBuf = (byte*) XMALLOC(sz, 0, DYNAMIC_TYPE_FILE);
+ if (fileBuf == NULL) {
+ XFCLOSE(file);
+ return SSL_BAD_FILE;
+ }
+ dynamic = 1;
+ }
+
+ if ( (ret = XFREAD(fileBuf, sz, 1, file)) < 0)
+ ret = SSL_BAD_FILE;
+ else
+ ret = PemToDer(fileBuf, sz, CA_TYPE, &converted, 0, &info, &ecc);
+
+ if (ret == 0) {
+ if (converted.length < derSz) {
+ memcpy(derBuf, converted.buffer, converted.length);
+ ret = converted.length;
+ }
+ else
+ ret = BUFFER_E;
+ }
+
+ XFREE(converted.buffer, 0, DYNAMIC_TYPE_CA);
+ if (dynamic)
+ XFREE(fileBuf, 0, DYNAMIC_TYPE_FILE);
+ XFCLOSE(file);
+
+ return ret;
+}
+
+#endif /* CYASSL_CERT_GEN */
+
+
+int SSL_CTX_use_certificate_file(SSL_CTX* ctx, const char* file, int format)
+{
+ if (ProcessFile(ctx, file, format, CERT_TYPE) == SSL_SUCCESS)
+ return SSL_SUCCESS;
+
+ return SSL_FAILURE;
+}
+
+
+int SSL_CTX_use_PrivateKey_file(SSL_CTX* ctx, const char* file, int format)
+{
+ if (ProcessFile(ctx, file, format, PRIVATEKEY_TYPE) == SSL_SUCCESS)
+ return SSL_SUCCESS;
+
+ return SSL_FAILURE;
+}
+
+
+int SSL_CTX_use_certificate_chain_file(SSL_CTX* ctx, const char* file)
+{
+ /* add first to ctx, all tested implementations support this */
+ if (ProcessFile(ctx, file, SSL_FILETYPE_PEM, CERT_TYPE) == SSL_SUCCESS)
+ return SSL_SUCCESS;
+
+ return SSL_FAILURE;
+}
+
+
+#ifdef HAVE_NTRU
+
+int CyaSSL_CTX_use_NTRUPrivateKey_file(SSL_CTX* ctx, const char* file)
+{
+ if (ProcessFile(ctx, file, SSL_FILETYPE_RAW, PRIVATEKEY_TYPE)
+ == SSL_SUCCESS) {
+ ctx->haveNTRU = 1;
+ return SSL_SUCCESS;
+ }
+
+ return SSL_FAILURE;
+}
+
+#endif /* HAVE_NTRU */
+
+
+
+#ifdef OPENSSL_EXTRA
+
+ int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX* ctx,const char* file,int format)
+ {
+ if (ProcessFile(ctx, file, format, PRIVATEKEY_TYPE) == SSL_SUCCESS)
+ return SSL_SUCCESS;
+
+ return SSL_FAILURE;
+ }
+
+#endif /* OPENSSL_EXTRA */
+
+#endif /* NO_FILESYSTEM */
+
+
+void SSL_CTX_set_verify(SSL_CTX* ctx, int mode, VerifyCallback vc)
+{
+ if (mode & SSL_VERIFY_PEER) {
+ ctx->verifyPeer = 1;
+ ctx->verifyNone = 0; /* in case perviously set */
+ }
+
+ if (mode == SSL_VERIFY_NONE) {
+ ctx->verifyNone = 1;
+ ctx->verifyPeer = 0; /* in case previously set */
+ }
+
+ if (mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)
+ ctx->failNoCert = 1;
+
+ ctx->verifyCallback = vc;
+}
+
+
+#ifndef NO_SESSION_CACHE
+
+SSL_SESSION* SSL_get_session(SSL* ssl)
+{
+ return GetSession(ssl, 0);
+}
+
+
+int SSL_set_session(SSL* ssl, SSL_SESSION* session)
+{
+ if (session)
+ return SetSession(ssl, session);
+
+ return SSL_FAILURE;
+}
+
+#endif /* NO_SESSION_CACHE */
+
+
+void SSL_load_error_strings(void) /* compatibility only */
+{}
+
+
+int SSL_library_init(void)
+{
+ if (InitCyaSSL() == 0)
+ return SSL_SUCCESS;
+ else
+ return -1;
+}
+
+
+#ifndef NO_SESSION_CACHE
+
+/* on by default if built in but allow user to turn off */
+long SSL_CTX_set_session_cache_mode(SSL_CTX* ctx, long mode)
+{
+ if (mode == SSL_SESS_CACHE_OFF)
+ ctx->sessionCacheOff = 1;
+
+ if (mode == SSL_SESS_CACHE_NO_AUTO_CLEAR)
+ ctx->sessionCacheFlushOff = 1;
+
+ return SSL_SUCCESS;
+}
+
+#endif /* NO_SESSION_CACHE */
+
+
+int SSL_CTX_set_cipher_list(SSL_CTX* ctx, const char* list)
+{
+ if (SetCipherList(ctx, list))
+ return SSL_SUCCESS;
+ else
+ return SSL_FAILURE;
+}
+
+
+/* client only parts */
+#ifndef NO_CYASSL_CLIENT
+
+ SSL_METHOD* SSLv3_client_method(void)
+ {
+ SSL_METHOD* method = (SSL_METHOD*) XMALLOC(sizeof(SSL_METHOD), 0,
+ DYNAMIC_TYPE_METHOD);
+ if (method)
+ InitSSL_Method(method, MakeSSLv3());
+ return method;
+ }
+
+ #ifdef CYASSL_DTLS
+ SSL_METHOD* DTLSv1_client_method(void)
+ {
+ SSL_METHOD* method = (SSL_METHOD*) XMALLOC(sizeof(SSL_METHOD), 0,
+ DYNAMIC_TYPE_METHOD);
+ if (method)
+ InitSSL_Method(method, MakeDTLSv1());
+ return method;
+ }
+ #endif
+
+
+ /* please see note at top of README if you get an error from connect */
+ int SSL_connect(SSL* ssl)
+ {
+ int neededState;
+
+ CYASSL_ENTER("SSL_connect()");
+
+ #ifdef HAVE_ERRNO_H
+ errno = 0;
+ #endif
+
+ if (ssl->options.side != CLIENT_END) {
+ CYASSL_ERROR(ssl->error = SIDE_ERROR);
+ return SSL_FATAL_ERROR;
+ }
+
+ #ifdef CYASSL_DTLS
+ if (ssl->version.major == DTLS_MAJOR &&
+ ssl->version.minor == DTLS_MINOR) {
+ ssl->options.dtls = 1;
+ ssl->options.tls = 1;
+ ssl->options.tls1_1 = 1;
+ }
+ #endif
+
+ if (ssl->buffers.outputBuffer.length > 0) {
+ if ( (ssl->error = SendBuffered(ssl)) == 0) {
+ ssl->options.connectState++;
+ CYASSL_MSG("connect state: Advanced from buffered send");
+ }
+ else {
+ CYASSL_ERROR(ssl->error);
+ return SSL_FATAL_ERROR;
+ }
+ }
+
+ switch (ssl->options.connectState) {
+
+ case CONNECT_BEGIN :
+ /* always send client hello first */
+ if ( (ssl->error = SendClientHello(ssl)) != 0) {
+ CYASSL_ERROR(ssl->error);
+ return SSL_FATAL_ERROR;
+ }
+ ssl->options.connectState = CLIENT_HELLO_SENT;
+ CYASSL_MSG("connect state: CLIENT_HELLO_SENT");
+
+ case CLIENT_HELLO_SENT :
+ neededState = ssl->options.resuming ? SERVER_FINISHED_COMPLETE :
+ SERVER_HELLODONE_COMPLETE;
+ #ifdef CYASSL_DTLS
+ if (ssl->options.dtls && !ssl->options.resuming)
+ neededState = SERVER_HELLOVERIFYREQUEST_COMPLETE;
+ #endif
+ /* get response */
+ while (ssl->options.serverState < neededState) {
+ if ( (ssl->error = ProcessReply(ssl)) < 0) {
+ CYASSL_ERROR(ssl->error);
+ return SSL_FATAL_ERROR;
+ }
+ /* if resumption failed, reset needed state */
+ else if (neededState == SERVER_FINISHED_COMPLETE)
+ if (!ssl->options.resuming) {
+ if (!ssl->options.dtls)
+ neededState = SERVER_HELLODONE_COMPLETE;
+ else
+ neededState = SERVER_HELLOVERIFYREQUEST_COMPLETE;
+ }
+ }
+
+ ssl->options.connectState = HELLO_AGAIN;
+ CYASSL_MSG("connect state: HELLO_AGAIN");
+
+ case HELLO_AGAIN :
+ #ifdef CYASSL_DTLS
+ if (ssl->options.dtls && !ssl->options.resuming) {
+ /* re-init hashes, exclude first hello and verify request */
+ InitMd5(&ssl->hashMd5);
+ InitSha(&ssl->hashSha);
+ #ifndef NO_SHA256
+ if (IsAtLeastTLSv1_2(ssl))
+ InitSha256(&ssl->hashSha256);
+ #endif
+ if ( (ssl->error = SendClientHello(ssl)) != 0) {
+ CYASSL_ERROR(ssl->error);
+ return SSL_FATAL_ERROR;
+ }
+ }
+ #endif
+
+ ssl->options.connectState = HELLO_AGAIN_REPLY;
+ CYASSL_MSG("connect state: HELLO_AGAIN_REPLY");
+
+ case HELLO_AGAIN_REPLY :
+ #ifdef CYASSL_DTLS
+ if (ssl->options.dtls) {
+ neededState = ssl->options.resuming ?
+ SERVER_FINISHED_COMPLETE : SERVER_HELLODONE_COMPLETE;
+
+ /* get response */
+ while (ssl->options.serverState < neededState) {
+ if ( (ssl->error = ProcessReply(ssl)) < 0) {
+ CYASSL_ERROR(ssl->error);
+ return SSL_FATAL_ERROR;
+ }
+ /* if resumption failed, reset needed state */
+ else if (neededState == SERVER_FINISHED_COMPLETE)
+ if (!ssl->options.resuming)
+ neededState = SERVER_HELLODONE_COMPLETE;
+ }
+ }
+ #endif
+
+ ssl->options.connectState = FIRST_REPLY_DONE;
+ CYASSL_MSG("connect state: FIRST_REPLY_DONE");
+
+ case FIRST_REPLY_DONE :
+ if (ssl->options.sendVerify)
+ if ( (ssl->error = SendCertificate(ssl)) != 0) {
+ CYASSL_ERROR(ssl->error);
+ return SSL_FATAL_ERROR;
+ }
+
+ ssl->options.connectState = FIRST_REPLY_FIRST;
+ CYASSL_MSG("connect state: FIRST_REPLY_FIRST");
+
+ case FIRST_REPLY_FIRST :
+ if (!ssl->options.resuming)
+ if ( (ssl->error = SendClientKeyExchange(ssl)) != 0) {
+ CYASSL_ERROR(ssl->error);
+ return SSL_FATAL_ERROR;
+ }
+
+ ssl->options.connectState = FIRST_REPLY_SECOND;
+ CYASSL_MSG("connect state: FIRST_REPLY_SECOND");
+
+ case FIRST_REPLY_SECOND :
+ if (ssl->options.sendVerify)
+ if ( (ssl->error = SendCertificateVerify(ssl)) != 0) {
+ CYASSL_ERROR(ssl->error);
+ return SSL_FATAL_ERROR;
+ }
+ ssl->options.connectState = FIRST_REPLY_THIRD;
+ CYASSL_MSG("connect state: FIRST_REPLY_THIRD");
+
+ case FIRST_REPLY_THIRD :
+ if ( (ssl->error = SendChangeCipher(ssl)) != 0) {
+ CYASSL_ERROR(ssl->error);
+ return SSL_FATAL_ERROR;
+ }
+ ssl->options.connectState = FIRST_REPLY_FOURTH;
+ CYASSL_MSG("connect state: FIRST_REPLY_FOURTH");
+
+ case FIRST_REPLY_FOURTH :
+ if ( (ssl->error = SendFinished(ssl)) != 0) {
+ CYASSL_ERROR(ssl->error);
+ return SSL_FATAL_ERROR;
+ }
+
+ ssl->options.connectState = FINISHED_DONE;
+ CYASSL_MSG("connect state: FINISHED_DONE");
+
+ case FINISHED_DONE :
+ /* get response */
+ while (ssl->options.serverState < SERVER_FINISHED_COMPLETE)
+ if ( (ssl->error = ProcessReply(ssl)) < 0) {
+ CYASSL_ERROR(ssl->error);
+ return SSL_FATAL_ERROR;
+ }
+
+ ssl->options.connectState = SECOND_REPLY_DONE;
+ CYASSL_MSG("connect state: SECOND_REPLY_DONE");
+
+ case SECOND_REPLY_DONE:
+ if (ssl->buffers.inputBuffer.dynamicFlag)
+ ShrinkInputBuffer(ssl, NO_FORCED_FREE);
+ CYASSL_LEAVE("SSL_connect()", SSL_SUCCESS);
+ return SSL_SUCCESS;
+
+ default:
+ CYASSL_MSG("Unknown connect state ERROR");
+ return SSL_FATAL_ERROR; /* unknown connect state */
+ }
+ }
+
+#endif /* NO_CYASSL_CLIENT */
+
+
+/* server only parts */
+#ifndef NO_CYASSL_SERVER
+
+ SSL_METHOD* SSLv3_server_method(void)
+ {
+ SSL_METHOD* method = (SSL_METHOD*) XMALLOC(sizeof(SSL_METHOD), 0,
+ DYNAMIC_TYPE_METHOD);
+ if (method) {
+ InitSSL_Method(method, MakeSSLv3());
+ method->side = SERVER_END;
+ }
+ return method;
+ }
+
+
+ #ifdef CYASSL_DTLS
+ SSL_METHOD* DTLSv1_server_method(void)
+ {
+ SSL_METHOD* method = (SSL_METHOD*) XMALLOC(sizeof(SSL_METHOD), 0,
+ DYNAMIC_TYPE_METHOD);
+ if (method) {
+ InitSSL_Method(method, MakeDTLSv1());
+ method->side = SERVER_END;
+ }
+ return method;
+ }
+ #endif
+
+
+ int SSL_accept(SSL* ssl)
+ {
+ CYASSL_ENTER("SSL_accept()");
+
+ #ifdef HAVE_ERRNO_H
+ errno = 0;
+ #endif
+
+ if (ssl->options.side != SERVER_END) {
+ CYASSL_ERROR(ssl->error = SIDE_ERROR);
+ return SSL_FATAL_ERROR;
+ }
+
+ #ifdef CYASSL_DTLS
+ if (ssl->version.major == DTLS_MAJOR &&
+ ssl->version.minor == DTLS_MINOR) {
+ ssl->options.dtls = 1;
+ ssl->options.tls = 1;
+ ssl->options.tls1_1 = 1;
+ }
+ #endif
+
+ if (ssl->buffers.outputBuffer.length > 0) {
+ if ( (ssl->error = SendBuffered(ssl)) == 0) {
+ ssl->options.acceptState++;
+ CYASSL_MSG("accept state: Advanced from buffered send");
+ }
+ else {
+ CYASSL_ERROR(ssl->error);
+ return SSL_FATAL_ERROR;
+ }
+ }
+
+ switch (ssl->options.acceptState) {
+
+ case ACCEPT_BEGIN :
+ /* get response */
+ while (ssl->options.clientState < CLIENT_HELLO_COMPLETE)
+ if ( (ssl->error = ProcessReply(ssl)) < 0) {
+ CYASSL_ERROR(ssl->error);
+ return SSL_FATAL_ERROR;
+ }
+ ssl->options.acceptState = ACCEPT_CLIENT_HELLO_DONE;
+ CYASSL_MSG("accept state ACCEPT_CLIENT_HELLO_DONE");
+
+ case ACCEPT_CLIENT_HELLO_DONE :
+ #ifdef CYASSL_DTLS
+ if (ssl->options.dtls && !ssl->options.resuming)
+ if ( (ssl->error = SendHelloVerifyRequest(ssl)) != 0) {
+ CYASSL_ERROR(ssl->error);
+ return SSL_FATAL_ERROR;
+ }
+ #endif
+ ssl->options.acceptState = HELLO_VERIFY_SENT;
+ CYASSL_MSG("accept state HELLO_VERIFY_SENT");
+
+ case HELLO_VERIFY_SENT:
+ #ifdef CYASSL_DTLS
+ if (ssl->options.dtls && !ssl->options.resuming) {
+ ssl->options.clientState = NULL_STATE; /* get again */
+ /* re-init hashes, exclude first hello and verify request */
+ InitMd5(&ssl->hashMd5);
+ InitSha(&ssl->hashSha);
+ #ifndef NO_SHA256
+ if (IsAtLeastTLSv1_2(ssl))
+ InitSha256(&ssl->hashSha256);
+ #endif
+
+ while (ssl->options.clientState < CLIENT_HELLO_COMPLETE)
+ if ( (ssl->error = ProcessReply(ssl)) < 0) {
+ CYASSL_ERROR(ssl->error);
+ return SSL_FATAL_ERROR;
+ }
+ }
+ #endif
+ ssl->options.acceptState = ACCEPT_FIRST_REPLY_DONE;
+ CYASSL_MSG("accept state ACCEPT_FIRST_REPLY_DONE");
+
+ case ACCEPT_FIRST_REPLY_DONE :
+ if ( (ssl->error = SendServerHello(ssl)) != 0) {
+ CYASSL_ERROR(ssl->error);
+ return SSL_FATAL_ERROR;
+ }
+ ssl->options.acceptState = SERVER_HELLO_SENT;
+ CYASSL_MSG("accept state SERVER_HELLO_SENT");
+
+ case SERVER_HELLO_SENT :
+ if (!ssl->options.resuming)
+ if ( (ssl->error = SendCertificate(ssl)) != 0) {
+ CYASSL_ERROR(ssl->error);
+ return SSL_FATAL_ERROR;
+ }
+ ssl->options.acceptState = CERT_SENT;
+ CYASSL_MSG("accept state CERT_SENT");
+
+ case CERT_SENT :
+ if (!ssl->options.resuming)
+ if ( (ssl->error = SendServerKeyExchange(ssl)) != 0) {
+ CYASSL_ERROR(ssl->error);
+ return SSL_FATAL_ERROR;
+ }
+ ssl->options.acceptState = KEY_EXCHANGE_SENT;
+ CYASSL_MSG("accept state KEY_EXCHANGE_SENT");
+
+ case KEY_EXCHANGE_SENT :
+ if (!ssl->options.resuming)
+ if (ssl->options.verifyPeer)
+ if ( (ssl->error = SendCertificateRequest(ssl)) != 0) {
+ CYASSL_ERROR(ssl->error);
+ return SSL_FATAL_ERROR;
+ }
+ ssl->options.acceptState = CERT_REQ_SENT;
+ CYASSL_MSG("accept state CERT_REQ_SENT");
+
+ case CERT_REQ_SENT :
+ if (!ssl->options.resuming)
+ if ( (ssl->error = SendServerHelloDone(ssl)) != 0) {
+ CYASSL_ERROR(ssl->error);
+ return SSL_FATAL_ERROR;
+ }
+ ssl->options.acceptState = SERVER_HELLO_DONE;
+ CYASSL_MSG("accept state SERVER_HELLO_DONE");
+
+ case SERVER_HELLO_DONE :
+ if (!ssl->options.resuming) {
+ while (ssl->options.clientState < CLIENT_FINISHED_COMPLETE)
+ if ( (ssl->error = ProcessReply(ssl)) < 0) {
+ CYASSL_ERROR(ssl->error);
+ return SSL_FATAL_ERROR;
+ }
+ }
+ ssl->options.acceptState = ACCEPT_SECOND_REPLY_DONE;
+ CYASSL_MSG("accept state ACCEPT_SECOND_REPLY_DONE");
+
+ case ACCEPT_SECOND_REPLY_DONE :
+ if ( (ssl->error = SendChangeCipher(ssl)) != 0) {
+ CYASSL_ERROR(ssl->error);
+ return SSL_FATAL_ERROR;
+ }
+ ssl->options.acceptState = CHANGE_CIPHER_SENT;
+ CYASSL_MSG("accept state CHANGE_CIPHER_SENT");
+
+ case CHANGE_CIPHER_SENT :
+ if ( (ssl->error = SendFinished(ssl)) != 0) {
+ CYASSL_ERROR(ssl->error);
+ return SSL_FATAL_ERROR;
+ }
+
+ ssl->options.acceptState = ACCEPT_FINISHED_DONE;
+ CYASSL_MSG("accept state ACCEPT_FINISHED_DONE");
+
+ case ACCEPT_FINISHED_DONE :
+ if (ssl->options.resuming)
+ while (ssl->options.clientState < CLIENT_FINISHED_COMPLETE)
+ if ( (ssl->error = ProcessReply(ssl)) < 0) {
+ CYASSL_ERROR(ssl->error);
+ return SSL_FATAL_ERROR;
+ }
+
+ ssl->options.acceptState = ACCEPT_THIRD_REPLY_DONE;
+ CYASSL_MSG("accept state ACCEPT_THIRD_REPLY_DONE");
+
+ case ACCEPT_THIRD_REPLY_DONE :
+ if (ssl->buffers.inputBuffer.dynamicFlag)
+ ShrinkInputBuffer(ssl, NO_FORCED_FREE);
+ CYASSL_LEAVE("SSL_accept()", SSL_SUCCESS);
+ return SSL_SUCCESS;
+
+ default :
+ CYASSL_MSG("Unknown accept state ERROR");
+ return SSL_FATAL_ERROR;
+ }
+ }
+
+#endif /* NO_CYASSL_SERVER */
+
+
+int InitCyaSSL(void)
+{
+#ifndef NO_SESSION_CACHE
+ if (InitMutex(&mutex) == 0)
+ return 0;
+ else
+ return -1;
+#else
+ return 0;
+#endif
+}
+
+
+int FreeCyaSSL(void)
+{
+#ifndef NO_SESSION_CACHE
+ if (FreeMutex(&mutex) == 0)
+ return 0;
+ else
+ return -1;
+#else
+ return 0;
+#endif
+}
+
+
+#ifndef NO_SESSION_CACHE
+
+
+static INLINE word32 HashSession(const byte* sessionID)
+{
+ /* id is random, just make 32 bit number from first 4 bytes for now */
+ return (sessionID[0] << 24) | (sessionID[1] << 16) | (sessionID[2] << 8) |
+ sessionID[3];
+}
+
+
+void SSL_flush_sessions(SSL_CTX* ctx, long tm)
+{
+ /* static table now, no flusing needed */
+}
+
+
+SSL_SESSION* GetSession(SSL* ssl, byte* masterSecret)
+{
+ SSL_SESSION* ret = 0;
+ const byte* id = ssl->arrays.sessionID;
+ word32 row;
+ int idx;
+
+ if (ssl->options.sessionCacheOff)
+ return 0;
+
+ row = HashSession(id) % SESSION_ROWS;
+
+ if (LockMutex(&mutex) != 0)
+ return 0;
+
+ if (SessionCache[row].totalCount >= SESSIONS_PER_ROW)
+ idx = SESSIONS_PER_ROW - 1;
+ else
+ idx = SessionCache[row].nextIdx - 1;
+
+ for (; idx >= 0; idx--) {
+ SSL_SESSION* current;
+
+ if (idx >= SESSIONS_PER_ROW) /* server could have restarted, idx */
+ break; /* would be word32(-1) and seg fault */
+
+ current = &SessionCache[row].Sessions[idx];
+ if (XMEMCMP(current->sessionID, id, ID_LEN) == 0) {
+ if (LowResTimer() < (current->bornOn + current->timeout)) {
+ ret = current;
+ if (masterSecret)
+ XMEMCPY(masterSecret, current->masterSecret, SECRET_LEN);
+ }
+ break;
+ }
+ }
+
+ UnLockMutex(&mutex);
+
+ return ret;
+}
+
+
+int SetSession(SSL* ssl, SSL_SESSION* session)
+{
+ if (ssl->options.sessionCacheOff)
+ return SSL_FAILURE;
+
+ if (LowResTimer() < (session->bornOn + session->timeout)) {
+ ssl->session = *session;
+ ssl->options.resuming = 1;
+
+#ifdef SESSION_CERTS
+ ssl->version = session->version;
+ ssl->options.cipherSuite0 = session->cipherSuite0;
+ ssl->options.cipherSuite = session->cipherSuite;
+#endif
+
+ return SSL_SUCCESS;
+ }
+ return SSL_FAILURE; /* session timed out */
+}
+
+
+int AddSession(SSL* ssl)
+{
+ word32 row, idx;
+
+ if (ssl->options.sessionCacheOff)
+ return 0;
+
+ row = HashSession(ssl->arrays.sessionID) % SESSION_ROWS;
+
+ if (LockMutex(&mutex) != 0)
+ return -1;
+
+ idx = SessionCache[row].nextIdx++;
+
+ XMEMCPY(SessionCache[row].Sessions[idx].masterSecret,
+ ssl->arrays.masterSecret, SECRET_LEN);
+ XMEMCPY(SessionCache[row].Sessions[idx].sessionID, ssl->arrays.sessionID,
+ ID_LEN);
+
+ SessionCache[row].Sessions[idx].timeout = DEFAULT_TIMEOUT;
+ SessionCache[row].Sessions[idx].bornOn = LowResTimer();
+
+#ifdef SESSION_CERTS
+ SessionCache[row].Sessions[idx].chain.count = ssl->session.chain.count;
+ XMEMCPY(SessionCache[row].Sessions[idx].chain.certs,
+ ssl->session.chain.certs, sizeof(x509_buffer) * MAX_CHAIN_DEPTH);
+
+ SessionCache[row].Sessions[idx].version = ssl->version;
+ SessionCache[row].Sessions[idx].cipherSuite0 = ssl->options.cipherSuite0;
+ SessionCache[row].Sessions[idx].cipherSuite = ssl->options.cipherSuite;
+#endif
+
+ SessionCache[row].totalCount++;
+ if (SessionCache[row].nextIdx == SESSIONS_PER_ROW)
+ SessionCache[row].nextIdx = 0;
+
+ if (UnLockMutex(&mutex) != 0)
+ return -1;
+
+ return 0;
+}
+
+
+ #ifdef SESSION_STATS
+
+ void PrintSessionStats(void)
+ {
+ word32 totalSessionsSeen = 0;
+ word32 totalSessionsNow = 0;
+ word32 rowNow;
+ int i;
+ double E; /* expected freq */
+ double chiSquare = 0;
+
+ for (i = 0; i < SESSION_ROWS; i++) {
+ totalSessionsSeen += SessionCache[i].totalCount;
+
+ if (SessionCache[i].totalCount >= SESSIONS_PER_ROW)
+ rowNow = SESSIONS_PER_ROW;
+ else if (SessionCache[i].nextIdx == 0)
+ rowNow = 0;
+ else
+ rowNow = SessionCache[i].nextIdx;
+
+ totalSessionsNow += rowNow;
+ }
+
+ printf("Total Sessions Seen = %d\n", totalSessionsSeen);
+ printf("Total Sessions Now = %d\n", totalSessionsNow);
+
+ E = (double)totalSessionsSeen / SESSION_ROWS;
+
+ for (i = 0; i < SESSION_ROWS; i++) {
+ double diff = SessionCache[i].totalCount - E;
+ diff *= diff; /* sqaure */
+ diff /= E; /* normalize */
+
+ chiSquare += diff;
+ }
+ printf(" chi-square = %5.1f, d.f. = %d\n", chiSquare,
+ SESSION_ROWS - 1);
+ if (SESSION_ROWS == 11)
+ printf(" .05 p value = 18.3, chi-square should be less\n");
+ else if (SESSION_ROWS == 211)
+ printf(".05 p value = 244.8, chi-square should be less\n");
+ else if (SESSION_ROWS == 5981)
+ printf(".05 p value = 6161.0, chi-square should be less\n");
+ printf("\n");
+ }
+
+ #endif /* SESSION_STATS */
+
+#endif /* NO_SESSION_CACHE */
+
+
+/* call before SSL_connect, if verifying will add name check to
+ date check and signature check */
+int CyaSSL_check_domain_name(SSL* ssl, const char* dn)
+{
+ if (ssl->buffers.domainName.buffer)
+ XFREE(ssl->buffers.domainName.buffer, ssl->heap, DYNAMIC_TYPE_DOMAIN);
+
+ ssl->buffers.domainName.length = (word32)XSTRLEN(dn) + 1;
+ ssl->buffers.domainName.buffer = (byte*) XMALLOC(
+ ssl->buffers.domainName.length, ssl->heap, DYNAMIC_TYPE_DOMAIN);
+
+ if (ssl->buffers.domainName.buffer) {
+ XSTRNCPY((char*)ssl->buffers.domainName.buffer, dn,
+ ssl->buffers.domainName.length);
+ return SSL_SUCCESS;
+ }
+ else {
+ ssl->error = MEMORY_ERROR;
+ return SSL_FAILURE;
+ }
+}
+
+
+/* turn on CyaSSL zlib compression
+ returns 0 for success, else error (not built in)
+*/
+int CyaSSL_set_compression(SSL* ssl)
+{
+#ifdef HAVE_LIBZ
+ ssl->options.usingCompression = 1;
+ return 0;
+#else
+ return -1;
+#endif
+}
+
+
+#ifndef USE_WINDOWS_API
+ #ifndef NO_WRITEV
+
+ /* simulate writev semantics, doesn't actually do block at a time though
+ because of SSL_write behavior and because front adds may be small */
+ int CyaSSL_writev(SSL* ssl, const struct iovec* iov, int iovcnt)
+ {
+ byte tmp[OUTPUT_RECORD_SIZE];
+ byte* buffer = tmp;
+ int send = 0;
+ int newBuffer = 0;
+ int idx = 0;
+ int i;
+ int ret;
+
+ for (i = 0; i < iovcnt; i++)
+ send += iov[i].iov_len;
+
+ if (send > sizeof(tmp)) {
+ byte* tmp2 = (byte*) XMALLOC(send, ssl->heap,
+ DYNAMIC_TYPE_WRITEV);
+ if (!tmp2)
+ return MEMORY_ERROR;
+ buffer = tmp2;
+ newBuffer = 1;
+ }
+
+ for (i = 0; i < iovcnt; i++) {
+ XMEMCPY(&buffer[idx], iov[i].iov_base, iov[i].iov_len);
+ idx += iov[i].iov_len;
+ }
+
+ ret = SSL_write(ssl, buffer, send);
+
+ if (newBuffer) XFREE(buffer, ssl->heap, DYNAMIC_TYPE_WRITEV);
+
+ return ret;
+ }
+ #endif
+#endif
+
+
+#ifdef CYASSL_CALLBACKS
+
+ typedef struct itimerval Itimerval;
+
+ /* don't keep calling simple functions while setting up timer and singals
+ if no inlining these are the next best */
+
+ #define AddTimes(a, b, c) \
+ do { \
+ c.tv_sec = a.tv_sec + b.tv_sec; \
+ c.tv_usec = a.tv_usec + b.tv_usec; \
+ if (c.tv_sec >= 1000000) { \
+ c.tv_sec++; \
+ c.tv_usec -= 1000000; \
+ } \
+ } while (0)
+
+
+ #define SubtractTimes(a, b, c) \
+ do { \
+ c.tv_sec = a.tv_sec - b.tv_sec; \
+ c.tv_usec = a.tv_usec - b.tv_usec; \
+ if (c.tv_sec < 0) { \
+ c.tv_sec--; \
+ c.tv_usec += 1000000; \
+ } \
+ } while (0)
+
+ #define CmpTimes(a, b, cmp) \
+ ((a.tv_sec == b.tv_sec) ? \
+ (a.tv_usec cmp b.tv_usec) : \
+ (a.tv_sec cmp b.tv_sec)) \
+
+
+ /* do nothing handler */
+ static void myHandler(int signo)
+ {
+ return;
+ }
+
+
+ static int CyaSSL_ex_wrapper(SSL* ssl, HandShakeCallBack hsCb,
+ TimeoutCallBack toCb, Timeval timeout)
+ {
+ int ret = -1;
+ int oldTimerOn = 0; /* was timer already on */
+ Timeval startTime;
+ Timeval endTime;
+ Timeval totalTime;
+ Itimerval myTimeout;
+ Itimerval oldTimeout; /* if old timer adjust from total time to reset */
+ struct sigaction act, oact;
+
+ #define ERR_OUT(x) { ssl->hsInfoOn = 0; ssl->toInfoOn = 0; return x; }
+
+ if (hsCb) {
+ ssl->hsInfoOn = 1;
+ InitHandShakeInfo(&ssl->handShakeInfo);
+ }
+ if (toCb) {
+ ssl->toInfoOn = 1;
+ InitTimeoutInfo(&ssl->timeoutInfo);
+
+ if (gettimeofday(&startTime, 0) < 0)
+ ERR_OUT(GETTIME_ERROR);
+
+ /* use setitimer to simulate getitimer, init 0 myTimeout */
+ myTimeout.it_interval.tv_sec = 0;
+ myTimeout.it_interval.tv_usec = 0;
+ myTimeout.it_value.tv_sec = 0;
+ myTimeout.it_value.tv_usec = 0;
+ if (setitimer(ITIMER_REAL, &myTimeout, &oldTimeout) < 0)
+ ERR_OUT(SETITIMER_ERROR);
+
+ if (oldTimeout.it_value.tv_sec || oldTimeout.it_value.tv_usec) {
+ oldTimerOn = 1;
+
+ /* is old timer going to expire before ours */
+ if (CmpTimes(oldTimeout.it_value, timeout, <)) {
+ timeout.tv_sec = oldTimeout.it_value.tv_sec;
+ timeout.tv_usec = oldTimeout.it_value.tv_usec;
+ }
+ }
+ myTimeout.it_value.tv_sec = timeout.tv_sec;
+ myTimeout.it_value.tv_usec = timeout.tv_usec;
+
+ /* set up signal handler, don't restart socket send/recv */
+ act.sa_handler = myHandler;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = 0;
+#ifdef SA_INTERRUPT
+ act.sa_flags |= SA_INTERRUPT;
+#endif
+ if (sigaction(SIGALRM, &act, &oact) < 0)
+ ERR_OUT(SIGACT_ERROR);
+
+ if (setitimer(ITIMER_REAL, &myTimeout, 0) < 0)
+ ERR_OUT(SETITIMER_ERROR);
+ }
+
+ /* do main work */
+#ifndef NO_CYASSL_CLIENT
+ if (ssl->options.side == CLIENT_END)
+ ret = SSL_connect(ssl);
+#endif
+#ifndef NO_CYASSL_SERVER
+ if (ssl->options.side == SERVER_END)
+ ret = SSL_accept(ssl);
+#endif
+
+ /* do callbacks */
+ if (toCb) {
+ if (oldTimerOn) {
+ gettimeofday(&endTime, 0);
+ SubtractTimes(endTime, startTime, totalTime);
+ /* adjust old timer for elapsed time */
+ if (CmpTimes(totalTime, oldTimeout.it_value, <))
+ SubtractTimes(oldTimeout.it_value, totalTime,
+ oldTimeout.it_value);
+ else {
+ /* reset value to interval, may be off */
+ oldTimeout.it_value.tv_sec = oldTimeout.it_interval.tv_sec;
+ oldTimeout.it_value.tv_usec =oldTimeout.it_interval.tv_usec;
+ }
+ /* keep iter the same whether there or not */
+ }
+ /* restore old handler */
+ if (sigaction(SIGALRM, &oact, 0) < 0)
+ ret = SIGACT_ERROR; /* more pressing error, stomp */
+ else
+ /* use old settings which may turn off (expired or not there) */
+ if (setitimer(ITIMER_REAL, &oldTimeout, 0) < 0)
+ ret = SETITIMER_ERROR;
+
+ /* if we had a timeout call callback */
+ if (ssl->timeoutInfo.timeoutName[0]) {
+ ssl->timeoutInfo.timeoutValue.tv_sec = timeout.tv_sec;
+ ssl->timeoutInfo.timeoutValue.tv_usec = timeout.tv_usec;
+ (toCb)(&ssl->timeoutInfo);
+ }
+ /* clean up */
+ FreeTimeoutInfo(&ssl->timeoutInfo, ssl->heap);
+ ssl->toInfoOn = 0;
+ }
+ if (hsCb) {
+ FinishHandShakeInfo(&ssl->handShakeInfo, ssl);
+ (hsCb)(&ssl->handShakeInfo);
+ ssl->hsInfoOn = 0;
+ }
+ return ret;
+ }
+
+
+#ifndef NO_CYASSL_CLIENT
+
+ int CyaSSL_connect_ex(SSL* ssl, HandShakeCallBack hsCb,
+ TimeoutCallBack toCb, Timeval timeout)
+ {
+ return CyaSSL_ex_wrapper(ssl, hsCb, toCb, timeout);
+ }
+
+#endif
+
+
+#ifndef NO_CYASSL_SERVER
+
+ int CyaSSL_accept_ex(SSL* ssl, HandShakeCallBack hsCb,
+ TimeoutCallBack toCb,Timeval timeout)
+ {
+ return CyaSSL_ex_wrapper(ssl, hsCb, toCb, timeout);
+ }
+
+#endif
+
+#endif /* CYASSL_CALLBACKS */
+
+
+#ifndef NO_PSK
+
+ void SSL_CTX_set_psk_client_callback(SSL_CTX* ctx, psk_client_callback cb)
+ {
+ ctx->havePSK = 1;
+ ctx->client_psk_cb = cb;
+ }
+
+
+ void SSL_set_psk_client_callback(SSL* ssl, psk_client_callback cb)
+ {
+ ssl->options.havePSK = 1;
+ ssl->options.client_psk_cb = cb;
+
+ InitSuites(&ssl->suites, ssl->version,TRUE,TRUE, ssl->options.haveNTRU,
+ ssl->options.haveECDSA, ssl->ctx->method->side);
+ }
+
+
+ void SSL_CTX_set_psk_server_callback(SSL_CTX* ctx, psk_server_callback cb)
+ {
+ ctx->havePSK = 1;
+ ctx->server_psk_cb = cb;
+ }
+
+
+ void SSL_set_psk_server_callback(SSL* ssl, psk_server_callback cb)
+ {
+ ssl->options.havePSK = 1;
+ ssl->options.server_psk_cb = cb;
+
+ InitSuites(&ssl->suites, ssl->version, ssl->options.haveDH, TRUE,
+ ssl->options.haveNTRU, ssl->options.haveECDSA,
+ ssl->ctx->method->side);
+ }
+
+
+ const char* SSL_get_psk_identity_hint(const SSL* ssl)
+ {
+ return ssl->arrays.server_hint;
+ }
+
+
+ const char* SSL_get_psk_identity(const SSL* ssl)
+ {
+ return ssl->arrays.client_identity;
+ }
+
+
+ int SSL_CTX_use_psk_identity_hint(SSL_CTX* ctx, const char* hint)
+ {
+ if (hint == 0)
+ ctx->server_hint[0] = 0;
+ else
+ XSTRNCPY(ctx->server_hint, hint, MAX_PSK_ID_LEN);
+ return SSL_SUCCESS;
+ }
+
+
+ int SSL_use_psk_identity_hint(SSL* ssl, const char* hint)
+ {
+ if (hint == 0)
+ ssl->arrays.server_hint[0] = 0;
+ else
+ XSTRNCPY(ssl->arrays.server_hint, hint, MAX_PSK_ID_LEN);
+ return SSL_SUCCESS;
+ }
+
+#endif /* NO_PSK */
+
+
+#if defined(NO_FILESYSTEM) || defined(MICRIUM)
+
+ /* CyaSSL extension allows DER files to be loaded from buffers as well */
+ int CyaSSL_CTX_load_verify_buffer(SSL_CTX* ctx, const unsigned char* buffer,
+ long sz, int format)
+ {
+ return ProcessBuffer(ctx, buffer, sz, format, CA_TYPE);
+ }
+
+
+ int CyaSSL_CTX_use_certificate_buffer(SSL_CTX* ctx,
+ const unsigned char* buffer,long sz,int format)
+ {
+ return ProcessBuffer(ctx, buffer, sz, format, CERT_TYPE);
+ }
+
+
+ int CyaSSL_CTX_use_PrivateKey_buffer(SSL_CTX* ctx,
+ const unsigned char* buffer,long sz,int format)
+ {
+ return ProcessBuffer(ctx, buffer, sz, format, PRIVATEKEY_TYPE);
+ }
+
+
+ int CyaSSL_CTX_use_certificate_chain_buffer(SSL_CTX* ctx,
+ const unsigned char* buffer, long sz)
+ {
+ /* add first to ctx, all tested implementations support this */
+ return ProcessBuffer(ctx, buffer, sz, SSL_FILETYPE_PEM, CA_TYPE);
+ }
+
+#endif /* NO_FILESYSTEM || MICRIUM */
+
+
+#if defined(OPENSSL_EXTRA) || defined(GOAHEAD_WS)
+
+
+ int SSLeay_add_ssl_algorithms(void)
+ {
+ OpenSSL_add_all_algorithms();
+ return SSL_SUCCESS;
+ }
+
+
+ long SSL_CTX_sess_set_cache_size(SSL_CTX* ctx, long sz)
+ {
+ /* cache size fixed at compile time in CyaSSL */
+ return 0;
+ }
+
+
+ void SSL_CTX_set_quiet_shutdown(SSL_CTX* ctx, int mode)
+ {
+ if (mode)
+ ctx->quietShutdown = 1;
+ }
+
+
+ int SSL_CTX_check_private_key(SSL_CTX* ctx)
+ {
+ /* TODO: check private against public for RSA match */
+ return SSL_SUCCESS;
+ }
+
+
+ void SSL_set_bio(SSL* ssl, BIO* rd, BIO* wr)
+ {
+ SSL_set_rfd(ssl, rd->fd);
+ SSL_set_wfd(ssl, wr->fd);
+
+ ssl->biord = rd;
+ ssl->biowr = wr;
+ }
+
+
+ void SSL_CTX_set_client_CA_list(SSL_CTX* ctx, STACK_OF(X509_NAME)* names)
+ {
+
+ }
+
+
+ STACK_OF(X509_NAME)* SSL_load_client_CA_file(const char* fname)
+ {
+ return 0;
+ }
+
+
+ int SSL_CTX_set_default_verify_paths(SSL_CTX* ctx)
+ {
+ /* TODO:, not needed in goahead */
+ return SSL_NOT_IMPLEMENTED;
+ }
+
+
+ void SSL_set_accept_state(SSL* ssl)
+ {
+ byte havePSK = 0;
+
+ ssl->options.side = SERVER_END;
+ /* reset suites in case user switched */
+#ifndef NO_PSK
+ havePSK = ssl->options.havePSK;
+#endif
+ InitSuites(&ssl->suites, ssl->version, ssl->options.haveDH, havePSK,
+ ssl->options.haveNTRU, ssl->options.haveECDSA,
+ ssl->ctx->method->side);
+ }
+
+
+ void OpenSSL_add_all_algorithms(void)
+ {
+ InitCyaSSL();
+ }
+
+
+ int SSLeay_add_all_algorithms(void)
+ {
+ OpenSSL_add_all_algorithms();
+ return SSL_SUCCESS;
+ }
+
+
+ void SSL_CTX_set_tmp_rsa_callback(SSL_CTX* ctx, RSA*(*f)(SSL*, int, int))
+ {
+ /* CyaSSL verifies all these internally */
+ }
+
+
+ void SSL_set_shutdown(SSL* ssl, int opt)
+ {
+
+ }
+
+
+ long SSL_CTX_set_options(SSL_CTX* ctx, long opt)
+ {
+ /* goahead calls with 0, do nothing */
+ return opt;
+ }
+
+
+ int SSL_set_rfd(SSL* ssl, int rfd)
+ {
+ ssl->rfd = rfd; /* not used directly to allow IO callbacks */
+
+ ssl->IOCB_ReadCtx = &ssl->rfd;
+
+ return SSL_SUCCESS;
+ }
+
+
+ int SSL_set_wfd(SSL* ssl, int wfd)
+ {
+ ssl->wfd = wfd; /* not used directly to allow IO callbacks */
+
+ ssl->IOCB_WriteCtx = &ssl->wfd;
+
+ return SSL_SUCCESS;
+ }
+
+
+ RSA* RSA_generate_key(int len, unsigned long bits, void(*f)(int,
+ int, void*), void* data)
+ {
+ /* no tmp key needed, actual generation not supported */
+ return 0;
+ }
+
+
+ X509_NAME* X509_get_issuer_name(X509* cert)
+ {
+ return &cert->issuer;
+ }
+
+
+ X509_NAME* X509_get_subject_name(X509* cert)
+ {
+ return &cert->subject;
+ }
+
+
+ /* copy name into buffer, at most sz bytes, if buffer is null will
+ malloc buffer, call responsible for freeing */
+ char* X509_NAME_oneline(X509_NAME* name, char* buffer, int sz)
+ {
+ int copySz = min(sz, name->sz);
+ if (!name->sz) return buffer;
+
+ if (!buffer) {
+ buffer = (char*)XMALLOC(name->sz, 0, DYNAMIC_TYPE_OPENSSL);
+ if (!buffer) return buffer;
+ copySz = name->sz;
+ }
+
+ if (copySz == 0)
+ return buffer;
+
+ XMEMCPY(buffer, name->name, copySz - 1);
+ buffer[copySz - 1] = 0;
+
+ return buffer;
+ }
+
+
+ X509* X509_STORE_CTX_get_current_cert(X509_STORE_CTX* ctx)
+ {
+ return 0;
+ }
+
+
+ int X509_STORE_CTX_get_error(X509_STORE_CTX* ctx)
+ {
+ return 0;
+ }
+
+
+ int X509_STORE_CTX_get_error_depth(X509_STORE_CTX* ctx)
+ {
+ return 0;
+ }
+
+
+ BIO_METHOD* BIO_f_buffer(void)
+ {
+ static BIO_METHOD meth;
+ meth.type = BIO_BUFFER;
+
+ return &meth;
+ }
+
+
+ long BIO_set_write_buffer_size(BIO* bio, long size)
+ {
+ /* CyaSSL has internal buffer, compatibility only */
+ return size;
+ }
+
+
+ BIO_METHOD* BIO_f_ssl(void)
+ {
+ static BIO_METHOD meth;
+ meth.type = BIO_SSL;
+
+ return &meth;
+ }
+
+
+ BIO* BIO_new_socket(int sfd, int close)
+ {
+ BIO* bio = (BIO*) XMALLOC(sizeof(BIO), 0, DYNAMIC_TYPE_OPENSSL);
+ if (bio) {
+ bio->type = BIO_SOCKET;
+ bio->close = close;
+ bio->eof = 0;
+ bio->ssl = 0;
+ bio->fd = sfd;
+ bio->prev = 0;
+ bio->next = 0;
+ }
+ return bio;
+ }
+
+
+ int BIO_eof(BIO* b)
+ {
+ if (b->eof)
+ return 1;
+
+ return 0;
+ }
+
+
+ long BIO_set_ssl(BIO* b, SSL* ssl, int close)
+ {
+ b->ssl = ssl;
+ b->close = close;
+ /* add to ssl for bio free if SSL_free called before/instead of free_all? */
+
+ return 0;
+ }
+
+
+ BIO* BIO_new(BIO_METHOD* method)
+ {
+ BIO* bio = (BIO*) XMALLOC(sizeof(BIO), 0, DYNAMIC_TYPE_OPENSSL);
+ if (bio) {
+ bio->type = method->type;
+ bio->close = 0;
+ bio->eof = 0;
+ bio->ssl = 0;
+ bio->fd = 0;
+ bio->prev = 0;
+ bio->next = 0;
+ }
+ return bio;
+ }
+
+
+#ifdef USE_WINDOWS_API
+ #define CloseSocket(s) closesocket(s)
+#else
+ #define CloseSocket(s) close(s)
+#endif
+
+ int BIO_free(BIO* bio)
+ {
+ /* unchain?, doesn't matter in goahead since from free all */
+ if (bio) {
+ if (bio->close) {
+ if (bio->ssl)
+ SSL_free(bio->ssl);
+ if (bio->fd)
+ CloseSocket(bio->fd);
+ }
+ XFREE(bio, 0, DYNAMIC_TYPE_OPENSSL);
+ }
+ return 0;
+ }
+
+
+ int BIO_free_all(BIO* bio)
+ {
+ BIO* next = bio;
+
+ while ( (bio = next) ) {
+ next = bio->next;
+ BIO_free(bio);
+ }
+ return 0;
+ }
+
+
+ int BIO_read(BIO* bio, void* buf, int len)
+ {
+ int ret;
+ SSL* ssl = 0;
+ BIO* front = bio;
+
+ /* already got eof, again is error */
+ if (front->eof)
+ return -1;
+
+ while(bio && ((ssl = bio->ssl) == 0) )
+ bio = bio->next;
+
+ if (ssl == 0) return -1;
+
+ ret = SSL_read(ssl, buf, len);
+ if (ret == 0)
+ front->eof = 1;
+ else if (ret < 0) {
+ int err = SSL_get_error(ssl, 0);
+ if ( !(err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) )
+ front->eof = 1;
+ }
+ return ret;
+ }
+
+
+ int BIO_write(BIO* bio, const void* data, int len)
+ {
+ int ret;
+ SSL* ssl = 0;
+ BIO* front = bio;
+
+ /* already got eof, again is error */
+ if (front->eof)
+ return -1;
+
+ while(bio && ((ssl = bio->ssl) == 0) )
+ bio = bio->next;
+
+ if (ssl == 0) return -1;
+
+ ret = SSL_write(ssl, data, len);
+ if (ret == 0)
+ front->eof = 1;
+ else if (ret < 0) {
+ int err = SSL_get_error(ssl, 0);
+ if ( !(err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) )
+ front->eof = 1;
+ }
+
+ return ret;
+ }
+
+
+ BIO* BIO_push(BIO* top, BIO* append)
+ {
+ top->next = append;
+ append->prev = top;
+
+ return top;
+ }
+
+
+ int BIO_flush(BIO* bio)
+ {
+ /* for CyaSSL no flushing needed */
+ return 1;
+ }
+
+
+#endif /* OPENSSL_EXTRA || GOAHEAD_WS */
+
+
+#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
+
+ void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX* ctx, void* userdata)
+ {
+ ctx->userdata = userdata;
+ }
+
+
+ void SSL_CTX_set_default_passwd_cb(SSL_CTX* ctx, pem_password_cb cb)
+ {
+ ctx->passwd_cb = cb;
+ }
+
+ int CRYPTO_num_locks(void)
+ {
+ return 0;
+ }
+
+ void CRYPTO_set_locking_callback(void (*f)(int, int, const char*, int))
+ {
+
+ }
+
+ void CRYPTO_set_id_callback(unsigned long (*f)(void))
+ {
+
+ }
+
+ unsigned long ERR_get_error(void)
+ {
+ /* TODO: */
+ return 0;
+ }
+
+ int EVP_BytesToKey(const EVP_CIPHER* type, const EVP_MD* md,
+ const byte* salt, const byte* data, int sz, int count,
+ byte* key, byte* iv)
+ {
+ int keyLen = 0;
+ int ivLen = 0;
+
+ Md5 myMD;
+ byte digest[MD5_DIGEST_SIZE];
+
+ int j;
+ int keyLeft;
+ int ivLeft;
+ int keyOutput = 0;
+
+ InitMd5(&myMD);
+
+ /* only support MD5 for now */
+ if (XSTRNCMP(md, "MD5", 3)) return 0;
+
+ /* only support CBC DES and AES for now */
+ if (XSTRNCMP(type, "DES-CBC", 7) == 0) {
+ keyLen = DES_KEY_SIZE;
+ ivLen = DES_IV_SIZE;
+ }
+ else if (XSTRNCMP(type, "DES-EDE3-CBC", 12) == 0) {
+ keyLen = DES3_KEY_SIZE;
+ ivLen = DES_IV_SIZE;
+ }
+ else if (XSTRNCMP(type, "AES-128-CBC", 11) == 0) {
+ keyLen = AES_128_KEY_SIZE;
+ ivLen = AES_IV_SIZE;
+ }
+ else if (XSTRNCMP(type, "AES-192-CBC", 11) == 0) {
+ keyLen = AES_192_KEY_SIZE;
+ ivLen = AES_IV_SIZE;
+ }
+ else if (XSTRNCMP(type, "AES-256-CBC", 11) == 0) {
+ keyLen = AES_256_KEY_SIZE;
+ ivLen = AES_IV_SIZE;
+ }
+ else
+ return 0;
+
+ keyLeft = keyLen;
+ ivLeft = ivLen;
+
+ while (keyOutput < (keyLen + ivLen)) {
+ int digestLeft = MD5_DIGEST_SIZE;
+ /* D_(i - 1) */
+ if (keyOutput) /* first time D_0 is empty */
+ Md5Update(&myMD, digest, MD5_DIGEST_SIZE);
+ /* data */
+ Md5Update(&myMD, data, sz);
+ /* salt */
+ if (salt)
+ Md5Update(&myMD, salt, EVP_SALT_SIZE);
+ Md5Final(&myMD, digest);
+ /* count */
+ for (j = 1; j < count; j++) {
+ Md5Update(&myMD, digest, MD5_DIGEST_SIZE);
+ Md5Final(&myMD, digest);
+ }
+
+ if (keyLeft) {
+ int store = min(keyLeft, MD5_DIGEST_SIZE);
+ XMEMCPY(&key[keyLen - keyLeft], digest, store);
+
+ keyOutput += store;
+ keyLeft -= store;
+ digestLeft -= store;
+ }
+
+ if (ivLeft && digestLeft) {
+ int store = min(ivLeft, digestLeft);
+ XMEMCPY(&iv[ivLen - ivLeft], &digest[MD5_DIGEST_SIZE -
+ digestLeft], store);
+ keyOutput += store;
+ ivLeft -= store;
+ }
+ }
+ if (keyOutput != (keyLen + ivLen))
+ return 0;
+ return keyOutput;
+ }
+
+#endif /* OPENSSL_EXTRA || HAVE_WEBSERVER */
+
+
+#ifdef OPENSSL_EXTRA
+
+ unsigned long SSLeay(void)
+ {
+ return SSLEAY_VERSION_NUMBER;
+ }
+
+
+ const char* SSLeay_version(int type)
+ {
+ static const char* version = "SSLeay CyaSSL compatibility";
+ return version;
+ }
+
+
+ void MD5_Init(MD5_CTX* md5)
+ {
+ typedef char md5_test[sizeof(MD5_CTX) >= sizeof(Md5) ? 1 : -1];
+ (void)sizeof(md5_test);
+
+ InitMd5((Md5*)md5);
+ }
+
+
+ void MD5_Update(MD5_CTX* md5, const void* input, unsigned long sz)
+ {
+ Md5Update((Md5*)md5, (const byte*)input, sz);
+ }
+
+
+ void MD5_Final(byte* input, MD5_CTX* md5)
+ {
+ Md5Final((Md5*)md5, input);
+ }
+
+
+ void SHA_Init(SHA_CTX* sha)
+ {
+ typedef char sha_test[sizeof(SHA_CTX) >= sizeof(Sha) ? 1 : -1];
+ (void)sizeof(sha_test);
+
+ InitSha((Sha*)sha);
+ }
+
+
+ void SHA_Update(SHA_CTX* sha, const void* input, unsigned long sz)
+ {
+ ShaUpdate((Sha*)sha, (const byte*)input, sz);
+ }
+
+
+ void SHA_Final(byte* input, SHA_CTX* sha)
+ {
+ ShaFinal((Sha*)sha, input);
+ }
+
+
+ const EVP_MD* EVP_md5(void)
+ {
+ static const char* type = "MD5";
+ return type;
+ }
+
+
+ const EVP_MD* EVP_sha1(void)
+ {
+ static const char* type = "SHA";
+ return type;
+ }
+
+
+ void EVP_MD_CTX_init(EVP_MD_CTX* ctx)
+ {
+ /* do nothing */
+ }
+
+
+ int EVP_MD_CTX_cleanup(EVP_MD_CTX* ctx)
+ {
+ return 0;
+ }
+
+
+ int EVP_DigestInit(EVP_MD_CTX* ctx, const EVP_MD* type)
+ {
+ if (XSTRNCMP(type, "MD5", 3) == 0) {
+ ctx->macType = MD5;
+ MD5_Init((MD5_CTX*)&ctx->hash);
+ }
+ else if (XSTRNCMP(type, "SHA", 3) == 0) {
+ ctx->macType = SHA;
+ SHA_Init((SHA_CTX*)&ctx->hash);
+ }
+ else
+ return -1;
+
+ return 0;
+ }
+
+
+ int EVP_DigestUpdate(EVP_MD_CTX* ctx, const void* data, size_t sz)
+ {
+ if (ctx->macType == MD5)
+ MD5_Update((MD5_CTX*)&ctx->hash, data, (unsigned long)sz);
+ else if (ctx->macType == SHA)
+ SHA_Update((SHA_CTX*)&ctx->hash, data, (unsigned long)sz);
+ else
+ return -1;
+
+ return 0;
+ }
+
+
+ int EVP_DigestFinal(EVP_MD_CTX* ctx, unsigned char* md, unsigned int* s)
+ {
+ if (ctx->macType == MD5) {
+ MD5_Final(md, (MD5_CTX*)&ctx->hash);
+ if (s) *s = MD5_DIGEST_SIZE;
+ }
+ else if (ctx->macType == SHA) {
+ SHA_Final(md, (SHA_CTX*)&ctx->hash);
+ if (s) *s = SHA_DIGEST_SIZE;
+ }
+ else
+ return -1;
+
+ return 0;
+ }
+
+
+ int EVP_DigestFinal_ex(EVP_MD_CTX* ctx, unsigned char* md, unsigned int* s)
+ {
+ return EVP_DigestFinal(ctx, md, s);
+ }
+
+
+ unsigned char* HMAC(const EVP_MD* evp_md, const void* key, int key_len,
+ const unsigned char* d, int n, unsigned char* md, unsigned int* md_len)
+ {
+ Hmac hmac;
+
+ if (!md) return 0; /* no static buffer support */
+
+ if (XSTRNCMP(evp_md, "MD5", 3) == 0) {
+ HmacSetKey(&hmac, MD5, key, key_len);
+ if (md_len) *md_len = MD5_DIGEST_SIZE;
+ }
+ else if (XSTRNCMP(evp_md, "SHA", 3) == 0) {
+ HmacSetKey(&hmac, SHA, key, key_len);
+ if (md_len) *md_len = SHA_DIGEST_SIZE;
+ }
+ else
+ return 0;
+
+ HmacUpdate(&hmac, d, n);
+ HmacFinal(&hmac, md);
+
+ return md;
+ }
+
+ void ERR_clear_error(void)
+ {
+ /* TODO: */
+ }
+
+
+ int RAND_status(void)
+ {
+ return 1; /* CTaoCrypt provides enough seed internally */
+ }
+
+
+ int RAND_bytes(unsigned char* buf, int num)
+ {
+ RNG rng;
+
+ if (InitRng(&rng))
+ return 0;
+
+ RNG_GenerateBlock(&rng, buf, num);
+
+ return 1;
+ }
+
+
+ int DES_key_sched(const_DES_cblock* key, DES_key_schedule* schedule)
+ {
+ XMEMCPY(schedule, key, sizeof(const_DES_cblock));
+ return 0;
+ }
+
+
+ void DES_cbc_encrypt(const unsigned char* input, unsigned char* output,
+ long length, DES_key_schedule* schedule, DES_cblock* ivec,
+ int enc)
+ {
+ Des des;
+ Des_SetKey(&des, (const byte*)schedule, (const byte*)ivec, !enc);
+
+ if (enc)
+ Des_CbcEncrypt(&des, output, input, length);
+ else
+ Des_CbcDecrypt(&des, output, input, length);
+ }
+
+
+ /* correctly sets ivec for next call */
+ void DES_ncbc_encrypt(const unsigned char* input, unsigned char* output,
+ long length, DES_key_schedule* schedule, DES_cblock* ivec,
+ int enc)
+ {
+ Des des;
+ Des_SetKey(&des, (const byte*)schedule, (const byte*)ivec, !enc);
+
+ if (enc)
+ Des_CbcEncrypt(&des, output, input, length);
+ else
+ Des_CbcDecrypt(&des, output, input, length);
+
+ XMEMCPY(ivec, output + length - sizeof(DES_cblock), sizeof(DES_cblock));
+ }
+
+
+ void ERR_free_strings(void)
+ {
+ /* handled internally */
+ }
+
+
+ void ERR_remove_state(unsigned long state)
+ {
+ /* TODO: GetErrors().Remove(); */
+ }
+
+
+ void EVP_cleanup(void)
+ {
+ /* nothing to do here */
+ }
+
+
+ void CRYPTO_cleanup_all_ex_data(void)
+ {
+ /* nothing to do here */
+ }
+
+
+ long SSL_CTX_set_mode(SSL_CTX* ctx, long mode)
+ {
+ /* SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER is CyaSSL default mode */
+
+ if (mode == SSL_MODE_ENABLE_PARTIAL_WRITE)
+ ctx->partialWrite = 1;
+
+ return mode;
+ }
+
+
+ long SSL_CTX_get_mode(SSL_CTX* ctx)
+ {
+ /* TODO: */
+ return 0;
+ }
+
+
+ void SSL_CTX_set_default_read_ahead(SSL_CTX* ctx, int m)
+ {
+ /* TODO: maybe? */
+ }
+
+
+ int SSL_CTX_set_session_id_context(SSL_CTX* ctx,
+ const unsigned char* sid_ctx,
+ unsigned int sid_ctx_len)
+ {
+ /* No application specific context needed for cyaSSL */
+ return SSL_SUCCESS;
+ }
+
+
+ long SSL_CTX_sess_get_cache_size(SSL_CTX* ctx)
+ {
+ /* TODO: maybe? */
+ return (~0);
+ }
+
+ unsigned long ERR_get_error_line_data(const char** file, int* line,
+ const char** data, int *flags)
+ {
+ /* Not implemented */
+ return 0;
+ }
+
+
+ X509* SSL_get_peer_certificate(SSL* ssl)
+ {
+ if (ssl->peerCert.issuer.sz)
+ return &ssl->peerCert;
+ else
+ return 0;
+ }
+
+
+
+ int SSL_set_ex_data(SSL* ssl, int idx, void* data)
+ {
+ return 0;
+ }
+
+
+ int SSL_get_shutdown(const SSL* ssl)
+ {
+ return 0;
+ }
+
+
+ int SSL_set_session_id_context(SSL* ssl, const unsigned char* id,
+ unsigned int len)
+ {
+ return 0;
+ }
+
+
+ void SSL_set_connect_state(SSL* ssl)
+ {
+ /* client by default */
+ }
+
+
+ int SSL_session_reused(SSL* ssl)
+ {
+ return ssl->options.resuming;
+ }
+
+
+ void SSL_SESSION_free(SSL_SESSION* session)
+ {
+
+ }
+
+
+ const char* SSL_get_version(SSL* ssl)
+ {
+ if (ssl->version.major == 3) {
+ switch (ssl->version.minor) {
+ case 0 :
+ return "SSLv3";
+ case 1 :
+ return "TLSv1";
+ case 2 :
+ return "TLSv1.1";
+ case 3 :
+ return "TLSv1.2";
+ }
+ }
+ return "unknown";
+ }
+
+
+ SSL_CIPHER* SSL_get_current_cipher(SSL* ssl)
+ {
+ return &ssl->cipher;
+ }
+
+
+ const char* SSL_CIPHER_get_name(const SSL_CIPHER* cipher)
+ {
+ if (cipher) {
+ if (cipher->ssl->options.cipherSuite0 == ECC_BYTE) {
+ /* ECC suites */
+ switch (cipher->ssl->options.cipherSuite) {
+ case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA :
+ return "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA";
+ case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA :
+ return "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA";
+ case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA :
+ return "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA";
+ case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA :
+ return "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA";
+ case TLS_ECDHE_RSA_WITH_RC4_128_SHA :
+ return "TLS_ECDHE_RSA_WITH_RC4_128_SHA";
+ case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA :
+ return "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA";
+ case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA :
+ return "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA";
+ case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA :
+ return "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA";
+ }
+ } else {
+ /* normal suites */
+ switch (cipher->ssl->options.cipherSuite) {
+ case SSL_RSA_WITH_RC4_128_SHA :
+ return "SSL_RSA_WITH_RC4_128_SHA";
+ case SSL_RSA_WITH_RC4_128_MD5 :
+ return "SSL_RSA_WITH_RC4_128_MD5";
+ case SSL_RSA_WITH_3DES_EDE_CBC_SHA :
+ return "SSL_RSA_WITH_3DES_EDE_CBC_SHA";
+ case TLS_RSA_WITH_AES_128_CBC_SHA :
+ return "TLS_RSA_WITH_AES_128_CBC_SHA";
+ case TLS_RSA_WITH_AES_256_CBC_SHA :
+ return "TLS_RSA_WITH_AES_256_CBC_SHA";
+ case TLS_PSK_WITH_AES_128_CBC_SHA :
+ return "TLS_PSK_WITH_AES_128_CBC_SHA";
+ case TLS_PSK_WITH_AES_256_CBC_SHA :
+ return "TLS_PSK_WITH_AES_256_CBC_SHA";
+ case TLS_DHE_RSA_WITH_AES_128_CBC_SHA :
+ return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA";
+ case TLS_DHE_RSA_WITH_AES_256_CBC_SHA :
+ return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA";
+ case TLS_RSA_WITH_HC_128_CBC_MD5 :
+ return "TLS_RSA_WITH_HC_128_CBC_MD5";
+ case TLS_RSA_WITH_HC_128_CBC_SHA :
+ return "TLS_RSA_WITH_HC_128_CBC_SHA";
+ case TLS_RSA_WITH_RABBIT_CBC_SHA :
+ return "TLS_RSA_WITH_RABBIT_CBC_SHA";
+ case TLS_NTRU_RSA_WITH_RC4_128_SHA :
+ return "TLS_NTRU_RSA_WITH_RC4_128_SHA";
+ case TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA :
+ return "TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA";
+ case TLS_NTRU_RSA_WITH_AES_128_CBC_SHA :
+ return "TLS_NTRU_RSA_WITH_AES_128_CBC_SHA";
+ case TLS_NTRU_RSA_WITH_AES_256_CBC_SHA :
+ return "TLS_NTRU_RSA_WITH_AES_256_CBC_SHA";
+ }
+ } /* normal / ECC */
+ }
+
+ return "NONE";
+ }
+
+
+ char* SSL_CIPHER_description(SSL_CIPHER* cipher, char* buffer, int len)
+ {
+ return 0;
+ }
+
+
+ SSL_SESSION* SSL_get1_session(SSL* ssl) /* what's ref count */
+ {
+ return 0;
+ }
+
+
+ void X509_free(X509* buf)
+ {
+
+ }
+
+
+ void OPENSSL_free(void* buf)
+ {
+
+ }
+
+
+ int OCSP_parse_url(char* url, char** host, char** port, char** path,
+ int* ssl)
+ {
+ return 0;
+ }
+
+
+ SSL_METHOD* SSLv2_client_method(void)
+ {
+ return 0;
+ }
+
+
+ SSL_METHOD* SSLv2_server_method(void)
+ {
+ return 0;
+ }
+
+
+#ifndef NO_MD4
+
+ void MD4_Init(MD4_CTX* md4)
+ {
+ /* make sure we have a big enough buffer */
+ typedef char ok[sizeof(md4->buffer) >= sizeof(Md4) ? 1 : -1];
+ (void) sizeof(ok);
+
+ InitMd4((Md4*)md4);
+ }
+
+
+ void MD4_Update(MD4_CTX* md4, const void* data, size_t len)
+ {
+ Md4Update((Md4*)md4, (const byte*)data, (word32)len);
+ }
+
+
+ void MD4_Final(unsigned char* digest, MD4_CTX* md4)
+ {
+ Md4Final((Md4*)md4, digest);
+ }
+
+#endif /* NO_MD4 */
+
+
+ BIO* BIO_pop(BIO* top)
+ {
+ return 0;
+ }
+
+
+ int BIO_pending(BIO* bio)
+ {
+ return 0;
+ }
+
+
+
+ BIO_METHOD* BIO_s_mem(void)
+ {
+ return 0;
+ }
+
+
+ BIO_METHOD* BIO_f_base64(void)
+ {
+ return 0;
+ }
+
+
+ void BIO_set_flags(BIO* bio, int flags)
+ {
+
+ }
+
+
+
+ void RAND_screen(void)
+ {
+
+ }
+
+
+ const char* RAND_file_name(char* fname, size_t len)
+ {
+ return 0;
+ }
+
+
+ int RAND_write_file(const char* fname)
+ {
+ return 0;
+ }
+
+
+ int RAND_load_file(const char* fname, long len)
+ {
+ /* CTaoCrypt provides enough entropy internally or will report error */
+ if (len == -1)
+ return 1024;
+ else
+ return (int)len;
+ }
+
+
+ int RAND_egd(const char* path)
+ {
+ return 0;
+ }
+
+
+
+ COMP_METHOD* COMP_zlib(void)
+ {
+ return 0;
+ }
+
+
+ COMP_METHOD* COMP_rle(void)
+ {
+ return 0;
+ }
+
+
+ int SSL_COMP_add_compression_method(int method, void* data)
+ {
+ return 0;
+ }
+
+
+
+ int SSL_get_ex_new_index(long idx, void* data, void* cb1, void* cb2,
+ void* cb3)
+ {
+ return 0;
+ }
+
+
+ void CRYPTO_set_dynlock_create_callback(CRYPTO_dynlock_value* (*f)(
+ const char*, int))
+ {
+
+ }
+
+
+ void CRYPTO_set_dynlock_lock_callback(void (*f)(int, CRYPTO_dynlock_value*,
+ const char*, int))
+ {
+
+ }
+
+
+ void CRYPTO_set_dynlock_destroy_callback(void (*f)(CRYPTO_dynlock_value*,
+ const char*, int))
+ {
+
+ }
+
+
+
+ const char* X509_verify_cert_error_string(long err)
+ {
+ return 0;
+ }
+
+
+
+ int X509_LOOKUP_add_dir(X509_LOOKUP* lookup, const char* dir, long len)
+ {
+ return 0;
+ }
+
+
+ int X509_LOOKUP_load_file(X509_LOOKUP* lookup, const char* file, long len)
+ {
+ return 0;
+ }
+
+
+ X509_LOOKUP_METHOD* X509_LOOKUP_hash_dir(void)
+ {
+ return 0;
+ }
+
+
+ X509_LOOKUP_METHOD* X509_LOOKUP_file(void)
+ {
+ return 0;
+ }
+
+
+
+ X509_LOOKUP* X509_STORE_add_lookup(X509_STORE* store, X509_LOOKUP_METHOD* m)
+ {
+ return 0;
+ }
+
+
+ X509_STORE* X509_STORE_new(void)
+ {
+ return 0;
+ }
+
+
+ int X509_STORE_get_by_subject(X509_STORE_CTX* ctx, int idx, X509_NAME* name,
+ X509_OBJECT* obj)
+ {
+ return 0;
+ }
+
+
+ int X509_STORE_CTX_init(X509_STORE_CTX* ctx, X509_STORE* store, X509* x509,
+ STACK_OF(X509)* sk)
+ {
+ return 0;
+ }
+
+
+ void X509_STORE_CTX_cleanup(X509_STORE_CTX* ctx)
+ {
+
+ }
+
+
+
+ ASN1_TIME* X509_CRL_get_lastUpdate(X509_CRL* crl)
+ {
+ return 0;
+ }
+
+
+ ASN1_TIME* X509_CRL_get_nextUpdate(X509_CRL* crl)
+ {
+ return 0;
+ }
+
+
+
+ EVP_PKEY* X509_get_pubkey(X509* x509)
+ {
+ return 0;
+ }
+
+
+ int X509_CRL_verify(X509_CRL* crl, EVP_PKEY* key)
+ {
+ return 0;
+ }
+
+
+ void X509_STORE_CTX_set_error(X509_STORE_CTX* ctx, int err)
+ {
+
+ }
+
+
+ void X509_OBJECT_free_contents(X509_OBJECT* obj)
+ {
+
+ }
+
+
+ void EVP_PKEY_free(EVP_PKEY* key)
+ {
+
+ }
+
+
+ int X509_cmp_current_time(const ASN1_TIME* time)
+ {
+ return 0;
+ }
+
+
+ int sk_X509_REVOKED_num(X509_REVOKED* revoked)
+ {
+ return 0;
+ }
+
+
+
+ X509_REVOKED* X509_CRL_get_REVOKED(X509_CRL* crl)
+ {
+ return 0;
+ }
+
+
+ X509_REVOKED* sk_X509_REVOKED_value(X509_REVOKED* revoked, int value)
+ {
+ return 0;
+ }
+
+
+
+ ASN1_INTEGER* X509_get_serialNumber(X509* x509)
+ {
+ return 0;
+ }
+
+
+
+ int ASN1_TIME_print(BIO* bio, const ASN1_TIME* time)
+ {
+ return 0;
+ }
+
+
+
+ int ASN1_INTEGER_cmp(const ASN1_INTEGER* a, const ASN1_INTEGER* b)
+ {
+ return 0;
+ }
+
+
+ long ASN1_INTEGER_get(const ASN1_INTEGER* i)
+ {
+ return 0;
+ }
+
+
+
+ void* X509_STORE_CTX_get_ex_data(X509_STORE_CTX* ctx, int idx)
+ {
+ return 0;
+ }
+
+
+ int SSL_get_ex_data_X509_STORE_CTX_idx(void)
+ {
+ return 0;
+ }
+
+
+ void* SSL_get_ex_data(const SSL* ssl, int idx)
+ {
+ return 0;
+ }
+
+
+ long SSL_CTX_set_timeout(SSL_CTX* ctx, long to)
+ {
+ return 0;
+ }
+
+
+ void SSL_CTX_set_info_callback(SSL_CTX* ctx, void (*f)())
+ {
+
+ }
+
+
+ unsigned long ERR_peek_error(void)
+ {
+ return 0;
+ }
+
+
+ int ERR_GET_REASON(int err)
+ {
+ return 0;
+ }
+
+
+ char* SSL_alert_type_string_long(int alert)
+ {
+ return 0;
+ }
+
+
+ char* SSL_alert_desc_string_long(int alert)
+ {
+ return 0;
+ }
+
+
+ char* SSL_state_string_long(SSL* ssl)
+ {
+ return 0;
+ }
+
+
+
+ void RSA_free(RSA* rsa)
+ {
+
+ }
+
+
+ int PEM_def_callback(char* name, int num, int w, void* key)
+ {
+ return 0;
+ }
+
+
+ long SSL_CTX_sess_accept(SSL_CTX* ctx)
+ {
+ return 0;
+ }
+
+
+ long SSL_CTX_sess_connect(SSL_CTX* ctx)
+ {
+ return 0;
+ }
+
+
+ long SSL_CTX_sess_accept_good(SSL_CTX* ctx)
+ {
+ return 0;
+ }
+
+
+ long SSL_CTX_sess_connect_good(SSL_CTX* ctx)
+ {
+ return 0;
+ }
+
+
+ long SSL_CTX_sess_accept_renegotiate(SSL_CTX* ctx)
+ {
+ return 0;
+ }
+
+
+ long SSL_CTX_sess_connect_renegotiate(SSL_CTX* ctx)
+ {
+ return 0;
+ }
+
+
+ long SSL_CTX_sess_hits(SSL_CTX* ctx)
+ {
+ return 0;
+ }
+
+
+ long SSL_CTX_sess_cb_hits(SSL_CTX* ctx)
+ {
+ return 0;
+ }
+
+
+ long SSL_CTX_sess_cache_full(SSL_CTX* ctx)
+ {
+ return 0;
+ }
+
+
+ long SSL_CTX_sess_misses(SSL_CTX* ctx)
+ {
+ return 0;
+ }
+
+
+ long SSL_CTX_sess_timeouts(SSL_CTX* ctx)
+ {
+ return 0;
+ }
+
+
+ long SSL_CTX_sess_number(SSL_CTX* ctx)
+ {
+ return 0;
+ }
+
+
+ void DES_set_key_unchecked(const_DES_cblock* des, DES_key_schedule* key)
+ {
+ }
+
+
+ void DES_set_odd_parity(DES_cblock* des)
+ {
+ }
+
+
+ void DES_ecb_encrypt(DES_cblock* desa, DES_cblock* desb,
+ DES_key_schedule* key, int len)
+ {
+ }
+
+ int BIO_printf(BIO* bio, const char* format, ...)
+ {
+ return 0;
+ }
+
+
+ int ASN1_UTCTIME_print(BIO* bio, const ASN1_UTCTIME* a)
+ {
+ return 0;
+ }
+
+
+ int sk_num(X509_REVOKED* rev)
+ {
+ return 0;
+ }
+
+
+ void* sk_value(X509_REVOKED* rev, int i)
+ {
+ return 0;
+ }
+
+
+ /* stunnel 4.28 needs */
+ void* SSL_CTX_get_ex_data(const SSL_CTX* ctx, int d)
+ {
+ return 0;
+ }
+
+
+ int SSL_CTX_set_ex_data(SSL_CTX* ctx, int d, void* p)
+ {
+ return SSL_SUCCESS;
+ }
+
+
+ void SSL_CTX_sess_set_get_cb(SSL_CTX* ctx, SSL_SESSION*(*f)(SSL*,
+ unsigned char*, int, int*))
+ {
+
+ }
+
+
+ void SSL_CTX_sess_set_new_cb(SSL_CTX* ctx, int (*f)(SSL*, SSL_SESSION*))
+ {
+
+ }
+
+
+ void SSL_CTX_sess_set_remove_cb(SSL_CTX* ctx, void (*f)(SSL_CTX*,
+ SSL_SESSION*))
+ {
+
+ }
+
+
+ int i2d_SSL_SESSION(SSL_SESSION* sess, unsigned char** p)
+ {
+ return sizeof(SSL_SESSION);
+ }
+
+
+ SSL_SESSION* d2i_SSL_SESSION(SSL_SESSION** sess, const unsigned char** p,
+ long i)
+ {
+ return *sess;
+ }
+
+
+ long SSL_SESSION_get_timeout(const SSL_SESSION* sess)
+ {
+ return sess->timeout;
+ }
+
+
+ long SSL_SESSION_get_time(const SSL_SESSION* sess)
+ {
+ return sess->bornOn;
+ }
+
+
+ int SSL_CTX_get_ex_new_index(long idx, void* arg, void* a, void* b, void* c)
+ {
+ return 0;
+ }
+
+
+#endif /* OPENSSL_EXTRA */
+
+
+#ifdef SESSION_CERTS
+
+
+/* Get peer's certificate chain */
+X509_CHAIN* CyaSSL_get_peer_chain(SSL* ssl)
+{
+ if (ssl)
+ return &ssl->session.chain;
+
+ return 0;
+}
+
+
+/* Get peer's certificate chain total count */
+int CyaSSL_get_chain_count(X509_CHAIN* chain)
+{
+ if (chain)
+ return chain->count;
+
+ return 0;
+}
+
+
+/* Get peer's ASN.1 DER ceritifcate at index (idx) length in bytes */
+int CyaSSL_get_chain_length(X509_CHAIN* chain, int idx)
+{
+ if (chain)
+ return chain->certs[idx].length;
+
+ return 0;
+}
+
+
+/* Get peer's ASN.1 DER ceritifcate at index (idx) */
+byte* CyaSSL_get_chain_cert(X509_CHAIN* chain, int idx)
+{
+ if (chain)
+ return chain->certs[idx].buffer;
+
+ return 0;
+}
+
+
+/* Get peer's PEM ceritifcate at index (idx), output to buffer if inLen big
+ enough else return error (-1), output length is in *outLen */
+int CyaSSL_get_chain_cert_pem(X509_CHAIN* chain, int idx,
+ unsigned char* buffer, int inLen, int* outLen)
+{
+ const char header[] = "-----BEGIN CERTIFICATE-----\n";
+ const char footer[] = "-----END CERTIFICATE-----\n";
+
+ int headerLen = sizeof(header) - 1;
+ int footerLen = sizeof(footer) - 1;
+ int i;
+
+ if (!chain || !outLen || !buffer)
+ return -1;
+
+ /* don't even try if inLen too short */
+ if (inLen < headerLen + footerLen + chain->certs[idx].length)
+ return -1;
+
+ /* header */
+ XMEMCPY(buffer, header, headerLen);
+ i = headerLen;
+
+ /* body */
+ *outLen = inLen; /* input to Base64Encode */
+ if (Base64Encode(chain->certs[idx].buffer, chain->certs[idx].length,
+ buffer + i, (word32*)outLen) < 0)
+ return -1;
+ i += *outLen;
+
+ /* footer */
+ if ( (i + footerLen) > inLen)
+ return -1;
+ XMEMCPY(buffer + i, footer, footerLen);
+ *outLen += headerLen + footerLen;
+
+ return 0;
+}
+
+
+/* get session ID */
+const byte* CyaSSL_get_sessionID(const SSL_SESSION* session)
+{
+ return session->sessionID;
+}
+
+
+#endif /* SESSION_CERTS */
+
diff --git a/release/src/router/cyassl/src/tls.c b/release/src/router/cyassl/src/tls.c
new file mode 100644
index 00000000..d6dd003e
--- /dev/null
+++ b/release/src/router/cyassl/src/tls.c
@@ -0,0 +1,457 @@
+/* tls.c
+ *
+ * Copyright (C) 2006-2011 Sawtooth Consulting Ltd.
+ *
+ * This file is part of CyaSSL.
+ *
+ * CyaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * CyaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+#include "ssl.h"
+#include "cyassl_int.h"
+#include "cyassl_error.h"
+#include "ctc_hmac.h"
+
+
+
+#ifndef NO_TLS
+
+
+#ifndef min
+
+ static INLINE word32 min(word32 a, word32 b)
+ {
+ return a > b ? b : a;
+ }
+
+#endif /* min */
+
+
+/* calculate XOR for TLSv1 PRF */
+static INLINE void get_xor(byte *digest, word32 digLen, byte* md5, byte* sha)
+{
+ word32 i;
+
+ for (i = 0; i < digLen; i++)
+ digest[i] = md5[i] ^ sha[i];
+}
+
+
+
+/* compute p_hash for MD5, SHA-1, or SHA-256 for TLSv1 PRF */
+void p_hash(byte* result, word32 resLen, const byte* secret, word32 secLen,
+ const byte* seed, word32 seedLen, int hash)
+{
+ word32 len = hash == md5_mac ? MD5_DIGEST_SIZE : hash == sha_mac ?
+ SHA_DIGEST_SIZE : SHA256_DIGEST_SIZE;
+ word32 times = resLen / len;
+ word32 lastLen = resLen % len;
+ word32 lastTime;
+ word32 i;
+ word32 idx = 0;
+ byte previous[SHA256_DIGEST_SIZE]; /* max size */
+ byte current[SHA256_DIGEST_SIZE]; /* max size */
+
+ Hmac hmac;
+
+ if (lastLen) times += 1;
+ lastTime = times - 1;
+
+ HmacSetKey(&hmac, hash == md5_mac ? MD5 : hash == sha_mac ? SHA : SHA256,
+ secret, secLen);
+ HmacUpdate(&hmac, seed, seedLen); /* A0 = seed */
+ HmacFinal(&hmac, previous); /* A1 */
+
+ for (i = 0; i < times; i++) {
+ HmacUpdate(&hmac, previous, len);
+ HmacUpdate(&hmac, seed, seedLen);
+ HmacFinal(&hmac, current);
+
+ if ( (i == lastTime) && lastLen)
+ XMEMCPY(&result[idx], current, lastLen);
+ else {
+ XMEMCPY(&result[idx], current, len);
+ idx += len;
+ HmacUpdate(&hmac, previous, len);
+ HmacFinal(&hmac, previous);
+ }
+ }
+}
+
+
+
+/* compute TLSv1 PRF (pseudo random function using HMAC) */
+static void PRF(byte* digest, word32 digLen, const byte* secret, word32 secLen,
+ const byte* label, word32 labLen, const byte* seed, word32 seedLen,
+ int useSha256)
+{
+ word32 half = (secLen + 1) / 2;
+
+ byte md5_half[MAX_PRF_HALF]; /* half is real size */
+ byte sha_half[MAX_PRF_HALF]; /* half is real size */
+ byte labelSeed[MAX_PRF_LABSEED]; /* labLen + seedLen is real size */
+ byte md5_result[MAX_PRF_DIG]; /* digLen is real size */
+ byte sha_result[MAX_PRF_DIG]; /* digLen is real size */
+
+ if (half > MAX_PRF_HALF)
+ return;
+ if (labLen + seedLen > MAX_PRF_LABSEED)
+ return;
+ if (digLen > MAX_PRF_DIG)
+ return;
+
+ XMEMCPY(md5_half, secret, half);
+ XMEMCPY(sha_half, secret + half - secLen % 2, half);
+
+ XMEMCPY(labelSeed, label, labLen);
+ XMEMCPY(labelSeed + labLen, seed, seedLen);
+
+ if (useSha256) {
+ p_hash(digest, digLen, secret, secLen, labelSeed, labLen + seedLen,
+ sha256_mac);
+ return;
+ }
+
+ p_hash(md5_result, digLen, md5_half, half, labelSeed, labLen + seedLen,
+ md5_mac);
+ p_hash(sha_result, digLen, sha_half, half, labelSeed, labLen + seedLen,
+ sha_mac);
+ get_xor(digest, digLen, md5_result, sha_result);
+}
+
+
+void BuildTlsFinished(SSL* ssl, Hashes* hashes, const byte* sender)
+{
+ const byte* side;
+ byte handshake_hash[FINISHED_SZ];
+ word32 hashSz = FINISHED_SZ;
+
+ Md5Final(&ssl->hashMd5, handshake_hash);
+ ShaFinal(&ssl->hashSha, &handshake_hash[MD5_DIGEST_SIZE]);
+#ifndef NO_SHA256
+ if (IsAtLeastTLSv1_2(ssl)) {
+ Sha256Final(&ssl->hashSha256, handshake_hash);
+ hashSz = SHA256_DIGEST_SIZE;
+ }
+#endif
+
+ if ( XSTRNCMP((const char*)sender, (const char*)client, SIZEOF_SENDER) == 0)
+ side = tls_client;
+ else
+ side = tls_server;
+
+ PRF(hashes->md5, TLS_FINISHED_SZ, ssl->arrays.masterSecret, SECRET_LEN,
+ side, FINISHED_LABEL_SZ, handshake_hash, hashSz, IsAtLeastTLSv1_2(ssl));
+}
+
+
+ProtocolVersion MakeTLSv1(void)
+{
+ ProtocolVersion pv;
+ pv.major = SSLv3_MAJOR;
+ pv.minor = TLSv1_MINOR;
+
+ return pv;
+}
+
+
+ProtocolVersion MakeTLSv1_1(void)
+{
+ ProtocolVersion pv;
+ pv.major = SSLv3_MAJOR;
+ pv.minor = TLSv1_1_MINOR;
+
+ return pv;
+}
+
+
+ProtocolVersion MakeTLSv1_2(void)
+{
+ ProtocolVersion pv;
+ pv.major = SSLv3_MAJOR;
+ pv.minor = TLSv1_2_MINOR;
+
+ return pv;
+}
+
+
+static const byte master_label[MASTER_LABEL_SZ + 1] = "master secret";
+static const byte key_label [KEY_LABEL_SZ + 1] = "key expansion";
+
+
+int DeriveTlsKeys(SSL* ssl)
+{
+ int length = 2 * ssl->specs.hash_size +
+ 2 * ssl->specs.key_size +
+ 2 * ssl->specs.iv_size;
+ byte seed[SEED_LEN];
+ byte key_data[MAX_PRF_DIG];
+
+ XMEMCPY(seed, ssl->arrays.serverRandom, RAN_LEN);
+ XMEMCPY(&seed[RAN_LEN], ssl->arrays.clientRandom, RAN_LEN);
+
+ PRF(key_data, length, ssl->arrays.masterSecret, SECRET_LEN, key_label,
+ KEY_LABEL_SZ, seed, SEED_LEN, IsAtLeastTLSv1_2(ssl));
+
+ return StoreKeys(ssl, key_data);
+}
+
+
+int MakeTlsMasterSecret(SSL* ssl)
+{
+ byte seed[SEED_LEN];
+
+ XMEMCPY(seed, ssl->arrays.clientRandom, RAN_LEN);
+ XMEMCPY(&seed[RAN_LEN], ssl->arrays.serverRandom, RAN_LEN);
+
+ PRF(ssl->arrays.masterSecret, SECRET_LEN,
+ ssl->arrays.preMasterSecret, ssl->arrays.preMasterSz,
+ master_label, MASTER_LABEL_SZ,
+ seed, SEED_LEN, IsAtLeastTLSv1_2(ssl));
+
+#ifdef SHOW_SECRETS
+ {
+ int i;
+ printf("master secret: ");
+ for (i = 0; i < SECRET_LEN; i++)
+ printf("%02x", ssl->arrays.masterSecret[i]);
+ printf("\n");
+ }
+#endif
+
+ return DeriveTlsKeys(ssl);
+}
+
+
+/*** next for static INLINE s copied from cyassl_int.c ***/
+
+/* convert 16 bit integer to opaque */
+static void INLINE c16toa(word16 u16, byte* c)
+{
+ c[0] = (u16 >> 8) & 0xff;
+ c[1] = u16 & 0xff;
+}
+
+
+/* convert 32 bit integer to opaque */
+static INLINE void c32toa(word32 u32, byte* c)
+{
+ c[0] = (u32 >> 24) & 0xff;
+ c[1] = (u32 >> 16) & 0xff;
+ c[2] = (u32 >> 8) & 0xff;
+ c[3] = u32 & 0xff;
+}
+
+
+static INLINE word32 GetSEQIncrement(SSL* ssl, int verify)
+{
+#ifdef CYASSL_DTLS
+ if (ssl->options.dtls) {
+ if (verify)
+ return ssl->keys.dtls_peer_sequence_number; /* explicit from peer */
+ else
+ return ssl->keys.dtls_sequence_number - 1; /* already incremented */
+ }
+#endif
+ if (verify)
+ return ssl->keys.peer_sequence_number++;
+ else
+ return ssl->keys.sequence_number++;
+}
+
+
+#ifdef CYASSL_DTLS
+
+static INLINE word32 GetEpoch(SSL* ssl, int verify)
+{
+ if (verify)
+ return ssl->keys.dtls_peer_epoch;
+ else
+ return ssl->keys.dtls_epoch;
+}
+
+#endif /* CYASSL_DTLS */
+
+
+static INLINE const byte* GetMacSecret(SSL* ssl, int verify)
+{
+ if ( (ssl->options.side == CLIENT_END && !verify) ||
+ (ssl->options.side == SERVER_END && verify) )
+ return ssl->keys.client_write_MAC_secret;
+ else
+ return ssl->keys.server_write_MAC_secret;
+}
+
+/*** end copy ***/
+
+
+/* TLS type HAMC */
+void TLS_hmac(SSL* ssl, byte* digest, const byte* buffer, word32 sz,
+ int content, int verify)
+{
+ Hmac hmac;
+ byte seq[SEQ_SZ] = { 0x00, 0x00, 0x00, 0x00 };
+ byte length[LENGTH_SZ];
+ byte inner[ENUM_LEN + VERSION_SZ + LENGTH_SZ]; /* type + version +len */
+ int type;
+
+ c16toa((word16)sz, length);
+#ifdef CYASSL_DTLS
+ if (ssl->options.dtls)
+ c16toa(GetEpoch(ssl, verify), seq);
+#endif
+ c32toa(GetSEQIncrement(ssl, verify), &seq[sizeof(word32)]);
+
+ if (ssl->specs.mac_algorithm == md5_mac)
+ type = MD5;
+ else
+ type = SHA;
+ HmacSetKey(&hmac, type, GetMacSecret(ssl, verify), ssl->specs.hash_size);
+
+ HmacUpdate(&hmac, seq, SEQ_SZ); /* seq_num */
+ inner[0] = content; /* type */
+ inner[ENUM_LEN] = ssl->version.major;
+ inner[ENUM_LEN + ENUM_LEN] = ssl->version.minor; /* version */
+ XMEMCPY(&inner[ENUM_LEN + VERSION_SZ], length, LENGTH_SZ); /* length */
+ HmacUpdate(&hmac, inner, sizeof(inner));
+ HmacUpdate(&hmac, buffer, sz); /* content */
+ HmacFinal(&hmac, digest);
+}
+
+
+#ifndef NO_CYASSL_CLIENT
+
+ SSL_METHOD* TLSv1_client_method(void)
+ {
+ SSL_METHOD* method = (SSL_METHOD*) XMALLOC(sizeof(SSL_METHOD), 0,
+ DYNAMIC_TYPE_METHOD);
+ if (method)
+ InitSSL_Method(method, MakeTLSv1());
+ return method;
+ }
+
+
+ SSL_METHOD* TLSv1_1_client_method(void)
+ {
+ SSL_METHOD* method = (SSL_METHOD*) XMALLOC(sizeof(SSL_METHOD), 0,
+ DYNAMIC_TYPE_METHOD);
+ if (method)
+ InitSSL_Method(method, MakeTLSv1_1());
+ return method;
+ }
+
+
+ SSL_METHOD* TLSv1_2_client_method(void)
+ {
+ SSL_METHOD* method = (SSL_METHOD*) XMALLOC(sizeof(SSL_METHOD), 0,
+ DYNAMIC_TYPE_METHOD);
+ if (method)
+ InitSSL_Method(method, MakeTLSv1_2());
+ return method;
+ }
+
+
+ /* TODO: add downgrade */
+ SSL_METHOD* SSLv23_client_method(void)
+ {
+ SSL_METHOD* method = (SSL_METHOD*) XMALLOC(sizeof(SSL_METHOD), 0,
+ DYNAMIC_TYPE_METHOD);
+ if (method)
+ InitSSL_Method(method, MakeTLSv1());
+ return method;
+ }
+
+
+#endif /* NO_CYASSL_CLIENT */
+
+
+
+#ifndef NO_CYASSL_SERVER
+
+ SSL_METHOD* TLSv1_server_method(void)
+ {
+ SSL_METHOD* method = (SSL_METHOD*) XMALLOC(sizeof(SSL_METHOD), 0,
+ DYNAMIC_TYPE_METHOD);
+ if (method) {
+ InitSSL_Method(method, MakeTLSv1());
+ method->side = SERVER_END;
+ }
+ return method;
+ }
+
+
+ SSL_METHOD* TLSv1_1_server_method(void)
+ {
+ SSL_METHOD* method = (SSL_METHOD*) XMALLOC(sizeof(SSL_METHOD), 0,
+ DYNAMIC_TYPE_METHOD);
+ if (method) {
+ InitSSL_Method(method, MakeTLSv1_1());
+ method->side = SERVER_END;
+ }
+ return method;
+ }
+
+
+ SSL_METHOD* TLSv1_2_server_method(void)
+ {
+ SSL_METHOD* method = (SSL_METHOD*) XMALLOC(sizeof(SSL_METHOD), 0,
+ DYNAMIC_TYPE_METHOD);
+ if (method) {
+ InitSSL_Method(method, MakeTLSv1_2());
+ method->side = SERVER_END;
+ }
+ return method;
+ }
+
+
+ SSL_METHOD *SSLv23_server_method(void)
+ {
+ SSL_METHOD* method = (SSL_METHOD*) XMALLOC(sizeof(SSL_METHOD), 0,
+ DYNAMIC_TYPE_METHOD);
+ if (method) {
+ InitSSL_Method(method, MakeTLSv1());
+ method->side = SERVER_END;
+ method->downgrade = 1;
+ }
+ return method;
+ }
+
+
+
+#endif /* NO_CYASSL_SERVER */
+
+#else /* NO_TLS */
+
+/* catch CyaSSL programming errors */
+void BuildTlsFinished(SSL* ssl, Hashes* hashes, const byte* sender)
+{
+
+}
+
+
+int DeriveTlsKeys(SSL* ssl)
+{
+ return -1;
+}
+
+
+int MakeTlsMasterSecret(SSL* ssl)
+{
+ return -1;
+}
+
+#endif /* NO_TLS */
+